Update r.js (running latest master until new r.js is published to NPM)
[jquery.git] / build / r.js
blob5aa492092437d1863d3e41d4c585ab4fedc91058
1 /**
2  * @license r.js 2.1.8+ Fri, 30 Aug 2013 03:19:39 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+ Fri, 30 Aug 2013 03:19:39 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         },
2696         /**
2697          * Does a type of deep copy. Do not give it anything fancy, best
2698          * for basic object copies of objects that also work well as
2699          * JSON-serialized things, or has properties pointing to functions.
2700          * For non-array/object values, just returns the same object.
2701          * @param  {Object} obj      copy properties from this object
2702          * @param  {Object} [result] optional result object to use
2703          * @return {Object}
2704          */
2705         deeplikeCopy: function (obj) {
2706             var type, result;
2708             if (lang.isArray(obj)) {
2709                 result = [];
2710                 obj.forEach(function(value) {
2711                     result.push(lang.deeplikeCopy(value));
2712                 });
2713                 return result;
2714             }
2716             type = typeof obj;
2717             if (obj === null || obj === undefined || type === 'boolean' ||
2718                 type === 'string' || type === 'number' || lang.isFunction(obj) ||
2719                 lang.isRegExp(obj)) {
2720                 return obj;
2721             }
2723             //Anything else is an object, hopefully.
2724             result = {};
2725             lang.eachProp(obj, function(value, key) {
2726                 result[key] = lang.deeplikeCopy(value);
2727             });
2728             return result;
2729         },
2731         delegate: (function () {
2732             // boodman/crockford delegation w/ cornford optimization
2733             function TMP() {}
2734             return function (obj, props) {
2735                 TMP.prototype = obj;
2736                 var tmp = new TMP();
2737                 TMP.prototype = null;
2738                 if (props) {
2739                     lang.mixin(tmp, props);
2740                 }
2741                 return tmp; // Object
2742             };
2743         }()),
2745         /**
2746          * Helper function for iterating over an array. If the func returns
2747          * a true value, it will break out of the loop.
2748          */
2749         each: function each(ary, func) {
2750             if (ary) {
2751                 var i;
2752                 for (i = 0; i < ary.length; i += 1) {
2753                     if (func(ary[i], i, ary)) {
2754                         break;
2755                     }
2756                 }
2757             }
2758         },
2760         /**
2761          * Cycles over properties in an object and calls a function for each
2762          * property value. If the function returns a truthy value, then the
2763          * iteration is stopped.
2764          */
2765         eachProp: function eachProp(obj, func) {
2766             var prop;
2767             for (prop in obj) {
2768                 if (hasProp(obj, prop)) {
2769                     if (func(obj[prop], prop)) {
2770                         break;
2771                     }
2772                 }
2773             }
2774         },
2776         //Similar to Function.prototype.bind, but the "this" object is specified
2777         //first, since it is easier to read/figure out what "this" will be.
2778         bind: function bind(obj, fn) {
2779             return function () {
2780                 return fn.apply(obj, arguments);
2781             };
2782         },
2784         //Escapes a content string to be be a string that has characters escaped
2785         //for inclusion as part of a JS string.
2786         jsEscape: function (content) {
2787             return content.replace(/(["'\\])/g, '\\$1')
2788                 .replace(/[\f]/g, "\\f")
2789                 .replace(/[\b]/g, "\\b")
2790                 .replace(/[\n]/g, "\\n")
2791                 .replace(/[\t]/g, "\\t")
2792                 .replace(/[\r]/g, "\\r");
2793         }
2794     };
2795     return lang;
2798  * prim 0.0.1 Copyright (c) 2012-2013, The Dojo Foundation All Rights Reserved.
2799  * Available via the MIT or new BSD license.
2800  * see: http://github.com/requirejs/prim for details
2801  */
2803 /*global setImmediate, process, setTimeout, define, module */
2805 //Set prime.hideResolutionConflict = true to allow "resolution-races"
2806 //in promise-tests to pass.
2807 //Since the goal of prim is to be a small impl for trusted code, it is
2808 //more important to normally throw in this case so that we can find
2809 //logic errors quicker.
2811 var prim;
2812 (function () {
2813     'use strict';
2814     var op = Object.prototype,
2815         hasOwn = op.hasOwnProperty;
2817     function hasProp(obj, prop) {
2818         return hasOwn.call(obj, prop);
2819     }
2821     /**
2822      * Helper function for iterating over an array. If the func returns
2823      * a true value, it will break out of the loop.
2824      */
2825     function each(ary, func) {
2826         if (ary) {
2827             var i;
2828             for (i = 0; i < ary.length; i += 1) {
2829                 if (ary[i]) {
2830                     func(ary[i], i, ary);
2831                 }
2832             }
2833         }
2834     }
2836     function check(p) {
2837         if (hasProp(p, 'e') || hasProp(p, 'v')) {
2838             if (!prim.hideResolutionConflict) {
2839                 throw new Error('nope');
2840             }
2841             return false;
2842         }
2843         return true;
2844     }
2846     function notify(ary, value) {
2847         prim.nextTick(function () {
2848             each(ary, function (item) {
2849                 item(value);
2850             });
2851         });
2852     }
2854     prim = function prim() {
2855         var p,
2856             ok = [],
2857             fail = [];
2859         return (p = {
2860             callback: function (yes, no) {
2861                 if (no) {
2862                     p.errback(no);
2863                 }
2865                 if (hasProp(p, 'v')) {
2866                     prim.nextTick(function () {
2867                         yes(p.v);
2868                     });
2869                 } else {
2870                     ok.push(yes);
2871                 }
2872             },
2874             errback: function (no) {
2875                 if (hasProp(p, 'e')) {
2876                     prim.nextTick(function () {
2877                         no(p.e);
2878                     });
2879                 } else {
2880                     fail.push(no);
2881                 }
2882             },
2884             finished: function () {
2885                 return hasProp(p, 'e') || hasProp(p, 'v');
2886             },
2888             rejected: function () {
2889                 return hasProp(p, 'e');
2890             },
2892             resolve: function (v) {
2893                 if (check(p)) {
2894                     p.v = v;
2895                     notify(ok, v);
2896                 }
2897                 return p;
2898             },
2899             reject: function (e) {
2900                 if (check(p)) {
2901                     p.e = e;
2902                     notify(fail, e);
2903                 }
2904                 return p;
2905             },
2907             start: function (fn) {
2908                 p.resolve();
2909                 return p.promise.then(fn);
2910             },
2912             promise: {
2913                 then: function (yes, no) {
2914                     var next = prim();
2916                     p.callback(function (v) {
2917                         try {
2918                             if (yes && typeof yes === 'function') {
2919                                 v = yes(v);
2920                             }
2922                             if (v && v.then) {
2923                                 v.then(next.resolve, next.reject);
2924                             } else {
2925                                 next.resolve(v);
2926                             }
2927                         } catch (e) {
2928                             next.reject(e);
2929                         }
2930                     }, function (e) {
2931                         var err;
2933                         try {
2934                             if (!no || typeof no !== 'function') {
2935                                 next.reject(e);
2936                             } else {
2937                                 err = no(e);
2939                                 if (err && err.then) {
2940                                     err.then(next.resolve, next.reject);
2941                                 } else {
2942                                     next.resolve(err);
2943                                 }
2944                             }
2945                         } catch (e2) {
2946                             next.reject(e2);
2947                         }
2948                     });
2950                     return next.promise;
2951                 },
2953                 fail: function (no) {
2954                     return p.promise.then(null, no);
2955                 },
2957                 end: function () {
2958                     p.errback(function (e) {
2959                         throw e;
2960                     });
2961                 }
2962             }
2963         });
2964     };
2966     prim.serial = function (ary) {
2967         var result = prim().resolve().promise;
2968         each(ary, function (item) {
2969             result = result.then(function () {
2970                 return item();
2971             });
2972         });
2973         return result;
2974     };
2976     prim.nextTick = typeof setImmediate === 'function' ? setImmediate :
2977         (typeof process !== 'undefined' && process.nextTick ?
2978             process.nextTick : (typeof setTimeout !== 'undefined' ?
2979                 function (fn) {
2980                 setTimeout(fn, 0);
2981             } : function (fn) {
2982         fn();
2983     }));
2985     if (typeof define === 'function' && define.amd) {
2986         define('prim', function () { return prim; });
2987     } else if (typeof module !== 'undefined' && module.exports) {
2988         module.exports = prim;
2989     }
2990 }());
2991 if(env === 'browser') {
2993  * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
2994  * Available via the MIT or new BSD license.
2995  * see: http://github.com/jrburke/requirejs for details
2996  */
2998 /*jslint strict: false */
2999 /*global define: false, load: false */
3001 //Just a stub for use with uglify's consolidator.js
3002 define('browser/assert', function () {
3003     return {};
3008 if(env === 'node') {
3010  * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
3011  * Available via the MIT or new BSD license.
3012  * see: http://github.com/jrburke/requirejs for details
3013  */
3015 /*jslint strict: false */
3016 /*global define: false, load: false */
3018 //Needed so that rhino/assert can return a stub for uglify's consolidator.js
3019 define('node/assert', ['assert'], function (assert) {
3020     return assert;
3025 if(env === 'rhino') {
3027  * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
3028  * Available via the MIT or new BSD license.
3029  * see: http://github.com/jrburke/requirejs for details
3030  */
3032 /*jslint strict: false */
3033 /*global define: false, load: false */
3035 //Just a stub for use with uglify's consolidator.js
3036 define('rhino/assert', function () {
3037     return {};
3042 if(env === 'xpconnect') {
3044  * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
3045  * Available via the MIT or new BSD license.
3046  * see: http://github.com/jrburke/requirejs for details
3047  */
3049 /*jslint strict: false */
3050 /*global define: false, load: false */
3052 //Just a stub for use with uglify's consolidator.js
3053 define('xpconnect/assert', function () {
3054     return {};
3059 if(env === 'browser') {
3061  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3062  * Available via the MIT or new BSD license.
3063  * see: http://github.com/jrburke/requirejs for details
3064  */
3066 /*jslint strict: false */
3067 /*global define: false, process: false */
3069 define('browser/args', function () {
3070     //Always expect config via an API call
3071     return [];
3076 if(env === 'node') {
3078  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3079  * Available via the MIT or new BSD license.
3080  * see: http://github.com/jrburke/requirejs for details
3081  */
3083 /*jslint strict: false */
3084 /*global define: false, process: false */
3086 define('node/args', function () {
3087     //Do not return the "node" or "r.js" arguments
3088     var args = process.argv.slice(2);
3090     //Ignore any command option used for main x.js branching
3091     if (args[0] && args[0].indexOf('-') === 0) {
3092         args = args.slice(1);
3093     }
3095     return args;
3100 if(env === 'rhino') {
3102  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3103  * Available via the MIT or new BSD license.
3104  * see: http://github.com/jrburke/requirejs for details
3105  */
3107 /*jslint strict: false */
3108 /*global define: false, process: false */
3110 var jsLibRhinoArgs = (typeof rhinoArgs !== 'undefined' && rhinoArgs) || [].concat(Array.prototype.slice.call(arguments, 0));
3112 define('rhino/args', function () {
3113     var args = jsLibRhinoArgs;
3115     //Ignore any command option used for main x.js branching
3116     if (args[0] && args[0].indexOf('-') === 0) {
3117         args = args.slice(1);
3118     }
3120     return args;
3125 if(env === 'xpconnect') {
3127  * @license Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
3128  * Available via the MIT or new BSD license.
3129  * see: http://github.com/jrburke/requirejs for details
3130  */
3132 /*jslint strict: false */
3133 /*global define, xpconnectArgs */
3135 var jsLibXpConnectArgs = (typeof xpconnectArgs !== 'undefined' && xpconnectArgs) || [].concat(Array.prototype.slice.call(arguments, 0));
3137 define('xpconnect/args', function () {
3138     var args = jsLibXpConnectArgs;
3140     //Ignore any command option used for main x.js branching
3141     if (args[0] && args[0].indexOf('-') === 0) {
3142         args = args.slice(1);
3143     }
3145     return args;
3150 if(env === 'browser') {
3152  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3153  * Available via the MIT or new BSD license.
3154  * see: http://github.com/jrburke/requirejs for details
3155  */
3157 /*jslint strict: false */
3158 /*global define: false, console: false */
3160 define('browser/load', ['./file'], function (file) {
3161     function load(fileName) {
3162         eval(file.readFile(fileName));
3163     }
3165     return load;
3170 if(env === 'node') {
3172  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3173  * Available via the MIT or new BSD license.
3174  * see: http://github.com/jrburke/requirejs for details
3175  */
3177 /*jslint strict: false */
3178 /*global define: false, console: false */
3180 define('node/load', ['fs'], function (fs) {
3181     function load(fileName) {
3182         var contents = fs.readFileSync(fileName, 'utf8');
3183         process.compile(contents, fileName);
3184     }
3186     return load;
3191 if(env === 'rhino') {
3193  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3194  * Available via the MIT or new BSD license.
3195  * see: http://github.com/jrburke/requirejs for details
3196  */
3198 /*jslint strict: false */
3199 /*global define: false, load: false */
3201 define('rhino/load', function () {
3202     return load;
3207 if(env === 'xpconnect') {
3209  * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
3210  * Available via the MIT or new BSD license.
3211  * see: http://github.com/jrburke/requirejs for details
3212  */
3214 /*jslint strict: false */
3215 /*global define: false, load: false */
3217 define('xpconnect/load', function () {
3218     return load;
3223 if(env === 'browser') {
3225  * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
3226  * Available via the MIT or new BSD license.
3227  * see: http://github.com/jrburke/requirejs for details
3228  */
3230 /*jslint sloppy: true, nomen: true */
3231 /*global require, define, console, XMLHttpRequest, requirejs, location */
3233 define('browser/file', ['prim'], function (prim) {
3235     var file,
3236         currDirRegExp = /^\.(\/|$)/;
3238     function frontSlash(path) {
3239         return path.replace(/\\/g, '/');
3240     }
3242     function exists(path) {
3243         var status, xhr = new XMLHttpRequest();
3245         //Oh yeah, that is right SYNC IO. Behold its glory
3246         //and horrible blocking behavior.
3247         xhr.open('HEAD', path, false);
3248         xhr.send();
3249         status = xhr.status;
3251         return status === 200 || status === 304;
3252     }
3254     function mkDir(dir) {
3255         console.log('mkDir is no-op in browser');
3256     }
3258     function mkFullDir(dir) {
3259         console.log('mkFullDir is no-op in browser');
3260     }
3262     file = {
3263         backSlashRegExp: /\\/g,
3264         exclusionRegExp: /^\./,
3265         getLineSeparator: function () {
3266             return '/';
3267         },
3269         exists: function (fileName) {
3270             return exists(fileName);
3271         },
3273         parent: function (fileName) {
3274             var parts = fileName.split('/');
3275             parts.pop();
3276             return parts.join('/');
3277         },
3279         /**
3280          * Gets the absolute file path as a string, normalized
3281          * to using front slashes for path separators.
3282          * @param {String} fileName
3283          */
3284         absPath: function (fileName) {
3285             var dir;
3286             if (currDirRegExp.test(fileName)) {
3287                 dir = frontSlash(location.href);
3288                 if (dir.indexOf('/') !== -1) {
3289                     dir = dir.split('/');
3291                     //Pull off protocol and host, just want
3292                     //to allow paths (other build parts, like
3293                     //require._isSupportedBuildUrl do not support
3294                     //full URLs), but a full path from
3295                     //the root.
3296                     dir.splice(0, 3);
3298                     dir.pop();
3299                     dir = '/' + dir.join('/');
3300                 }
3302                 fileName = dir + fileName.substring(1);
3303             }
3305             return fileName;
3306         },
3308         normalize: function (fileName) {
3309             return fileName;
3310         },
3312         isFile: function (path) {
3313             return true;
3314         },
3316         isDirectory: function (path) {
3317             return false;
3318         },
3320         getFilteredFileList: function (startDir, regExpFilters, makeUnixPaths) {
3321             console.log('file.getFilteredFileList is no-op in browser');
3322         },
3324         copyDir: function (srcDir, destDir, regExpFilter, onlyCopyNew) {
3325             console.log('file.copyDir is no-op in browser');
3327         },
3329         copyFile: function (srcFileName, destFileName, onlyCopyNew) {
3330             console.log('file.copyFile is no-op in browser');
3331         },
3333         /**
3334          * Renames a file. May fail if "to" already exists or is on another drive.
3335          */
3336         renameFile: function (from, to) {
3337             console.log('file.renameFile is no-op in browser');
3338         },
3340         /**
3341          * Reads a *text* file.
3342          */
3343         readFile: function (path, encoding) {
3344             var xhr = new XMLHttpRequest();
3346             //Oh yeah, that is right SYNC IO. Behold its glory
3347             //and horrible blocking behavior.
3348             xhr.open('GET', path, false);
3349             xhr.send();
3351             return xhr.responseText;
3352         },
3354         readFileAsync: function (path, encoding) {
3355             var xhr = new XMLHttpRequest(),
3356                 d = prim();
3358             xhr.open('GET', path, true);
3359             xhr.send();
3361             xhr.onreadystatechange = function () {
3362                 if (xhr.readyState === 4) {
3363                     if (xhr.status > 400) {
3364                         d.reject(new Error('Status: ' + xhr.status + ': ' + xhr.statusText));
3365                     } else {
3366                         d.resolve(xhr.responseText);
3367                     }
3368                 }
3369             };
3371             return d.promise;
3372         },
3374         saveUtf8File: function (fileName, fileContents) {
3375             //summary: saves a *text* file using UTF-8 encoding.
3376             file.saveFile(fileName, fileContents, "utf8");
3377         },
3379         saveFile: function (fileName, fileContents, encoding) {
3380             requirejs.browser.saveFile(fileName, fileContents, encoding);
3381         },
3383         deleteFile: function (fileName) {
3384             console.log('file.deleteFile is no-op in browser');
3385         },
3387         /**
3388          * Deletes any empty directories under the given directory.
3389          */
3390         deleteEmptyDirs: function (startDir) {
3391             console.log('file.deleteEmptyDirs is no-op in browser');
3392         }
3393     };
3395     return file;
3401 if(env === 'node') {
3403  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3404  * Available via the MIT or new BSD license.
3405  * see: http://github.com/jrburke/requirejs for details
3406  */
3408 /*jslint plusplus: false, octal:false, strict: false */
3409 /*global define: false, process: false */
3411 define('node/file', ['fs', 'path', 'prim'], function (fs, path, prim) {
3413     var isWindows = process.platform === 'win32',
3414         windowsDriveRegExp = /^[a-zA-Z]\:\/$/,
3415         file;
3417     function frontSlash(path) {
3418         return path.replace(/\\/g, '/');
3419     }
3421     function exists(path) {
3422         if (isWindows && path.charAt(path.length - 1) === '/' &&
3423             path.charAt(path.length - 2) !== ':') {
3424             path = path.substring(0, path.length - 1);
3425         }
3427         try {
3428             fs.statSync(path);
3429             return true;
3430         } catch (e) {
3431             return false;
3432         }
3433     }
3435     function mkDir(dir) {
3436         if (!exists(dir) && (!isWindows || !windowsDriveRegExp.test(dir))) {
3437             fs.mkdirSync(dir, 511);
3438         }
3439     }
3441     function mkFullDir(dir) {
3442         var parts = dir.split('/'),
3443             currDir = '',
3444             first = true;
3446         parts.forEach(function (part) {
3447             //First part may be empty string if path starts with a slash.
3448             currDir += part + '/';
3449             first = false;
3451             if (part) {
3452                 mkDir(currDir);
3453             }
3454         });
3455     }
3457     file = {
3458         backSlashRegExp: /\\/g,
3459         exclusionRegExp: /^\./,
3460         getLineSeparator: function () {
3461             return '/';
3462         },
3464         exists: function (fileName) {
3465             return exists(fileName);
3466         },
3468         parent: function (fileName) {
3469             var parts = fileName.split('/');
3470             parts.pop();
3471             return parts.join('/');
3472         },
3474         /**
3475          * Gets the absolute file path as a string, normalized
3476          * to using front slashes for path separators.
3477          * @param {String} fileName
3478          */
3479         absPath: function (fileName) {
3480             return frontSlash(path.normalize(frontSlash(fs.realpathSync(fileName))));
3481         },
3483         normalize: function (fileName) {
3484             return frontSlash(path.normalize(fileName));
3485         },
3487         isFile: function (path) {
3488             return fs.statSync(path).isFile();
3489         },
3491         isDirectory: function (path) {
3492             return fs.statSync(path).isDirectory();
3493         },
3495         getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths) {
3496             //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
3497             //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
3498             //and it will be treated as the "include" case.
3499             //Ignores files/directories that start with a period (.) unless exclusionRegExp
3500             //is set to another value.
3501             var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
3502                 i, stat, filePath, ok, dirFiles, fileName;
3504             topDir = startDir;
3506             regExpInclude = regExpFilters.include || regExpFilters;
3507             regExpExclude = regExpFilters.exclude || null;
3509             if (file.exists(topDir)) {
3510                 dirFileArray = fs.readdirSync(topDir);
3511                 for (i = 0; i < dirFileArray.length; i++) {
3512                     fileName = dirFileArray[i];
3513                     filePath = path.join(topDir, fileName);
3514                     stat = fs.statSync(filePath);
3515                     if (stat.isFile()) {
3516                         if (makeUnixPaths) {
3517                             //Make sure we have a JS string.
3518                             if (filePath.indexOf("/") === -1) {
3519                                 filePath = frontSlash(filePath);
3520                             }
3521                         }
3523                         ok = true;
3524                         if (regExpInclude) {
3525                             ok = filePath.match(regExpInclude);
3526                         }
3527                         if (ok && regExpExclude) {
3528                             ok = !filePath.match(regExpExclude);
3529                         }
3531                         if (ok && (!file.exclusionRegExp ||
3532                             !file.exclusionRegExp.test(fileName))) {
3533                             files.push(filePath);
3534                         }
3535                     } else if (stat.isDirectory() &&
3536                               (!file.exclusionRegExp || !file.exclusionRegExp.test(fileName))) {
3537                         dirFiles = this.getFilteredFileList(filePath, regExpFilters, makeUnixPaths);
3538                         files.push.apply(files, dirFiles);
3539                     }
3540                 }
3541             }
3543             return files; //Array
3544         },
3546         copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
3547             //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
3548             //file should be copied. Returns a list file name strings of the destinations that were copied.
3549             regExpFilter = regExpFilter || /\w/;
3551             //Normalize th directory names, but keep front slashes.
3552             //path module on windows now returns backslashed paths.
3553             srcDir = frontSlash(path.normalize(srcDir));
3554             destDir = frontSlash(path.normalize(destDir));
3556             var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
3557             copiedFiles = [], i, srcFileName, destFileName;
3559             for (i = 0; i < fileNames.length; i++) {
3560                 srcFileName = fileNames[i];
3561                 destFileName = srcFileName.replace(srcDir, destDir);
3563                 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
3564                     copiedFiles.push(destFileName);
3565                 }
3566             }
3568             return copiedFiles.length ? copiedFiles : null; //Array or null
3569         },
3571         copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
3572             //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
3573             //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
3574             var parentDir;
3576             //logger.trace("Src filename: " + srcFileName);
3577             //logger.trace("Dest filename: " + destFileName);
3579             //If onlyCopyNew is true, then compare dates and only copy if the src is newer
3580             //than dest.
3581             if (onlyCopyNew) {
3582                 if (file.exists(destFileName) && fs.statSync(destFileName).mtime.getTime() >= fs.statSync(srcFileName).mtime.getTime()) {
3583                     return false; //Boolean
3584                 }
3585             }
3587             //Make sure destination dir exists.
3588             parentDir = path.dirname(destFileName);
3589             if (!file.exists(parentDir)) {
3590                 mkFullDir(parentDir);
3591             }
3593             fs.writeFileSync(destFileName, fs.readFileSync(srcFileName, 'binary'), 'binary');
3595             return true; //Boolean
3596         },
3598         /**
3599          * Renames a file. May fail if "to" already exists or is on another drive.
3600          */
3601         renameFile: function (from, to) {
3602             return fs.renameSync(from, to);
3603         },
3605         /**
3606          * Reads a *text* file.
3607          */
3608         readFile: function (/*String*/path, /*String?*/encoding) {
3609             if (encoding === 'utf-8') {
3610                 encoding = 'utf8';
3611             }
3612             if (!encoding) {
3613                 encoding = 'utf8';
3614             }
3616             var text = fs.readFileSync(path, encoding);
3618             //Hmm, would not expect to get A BOM, but it seems to happen,
3619             //remove it just in case.
3620             if (text.indexOf('\uFEFF') === 0) {
3621                 text = text.substring(1, text.length);
3622             }
3624             return text;
3625         },
3627         readFileAsync: function (path, encoding) {
3628             var d = prim();
3629             try {
3630                 d.resolve(file.readFile(path, encoding));
3631             } catch (e) {
3632                 d.reject(e);
3633             }
3634             return d.promise;
3635         },
3637         saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
3638             //summary: saves a *text* file using UTF-8 encoding.
3639             file.saveFile(fileName, fileContents, "utf8");
3640         },
3642         saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
3643             //summary: saves a *text* file.
3644             var parentDir;
3646             if (encoding === 'utf-8') {
3647                 encoding = 'utf8';
3648             }
3649             if (!encoding) {
3650                 encoding = 'utf8';
3651             }
3653             //Make sure destination directories exist.
3654             parentDir = path.dirname(fileName);
3655             if (!file.exists(parentDir)) {
3656                 mkFullDir(parentDir);
3657             }
3659             fs.writeFileSync(fileName, fileContents, encoding);
3660         },
3662         deleteFile: function (/*String*/fileName) {
3663             //summary: deletes a file or directory if it exists.
3664             var files, i, stat;
3665             if (file.exists(fileName)) {
3666                 stat = fs.statSync(fileName);
3667                 if (stat.isDirectory()) {
3668                     files = fs.readdirSync(fileName);
3669                     for (i = 0; i < files.length; i++) {
3670                         this.deleteFile(path.join(fileName, files[i]));
3671                     }
3672                     fs.rmdirSync(fileName);
3673                 } else {
3674                     fs.unlinkSync(fileName);
3675                 }
3676             }
3677         },
3680         /**
3681          * Deletes any empty directories under the given directory.
3682          */
3683         deleteEmptyDirs: function (startDir) {
3684             var dirFileArray, i, fileName, filePath, stat;
3686             if (file.exists(startDir)) {
3687                 dirFileArray = fs.readdirSync(startDir);
3688                 for (i = 0; i < dirFileArray.length; i++) {
3689                     fileName = dirFileArray[i];
3690                     filePath = path.join(startDir, fileName);
3691                     stat = fs.statSync(filePath);
3692                     if (stat.isDirectory()) {
3693                         file.deleteEmptyDirs(filePath);
3694                     }
3695                 }
3697                 //If directory is now empty, remove it.
3698                 if (fs.readdirSync(startDir).length ===  0) {
3699                     file.deleteFile(startDir);
3700                 }
3701             }
3702         }
3703     };
3705     return file;
3711 if(env === 'rhino') {
3713  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3714  * Available via the MIT or new BSD license.
3715  * see: http://github.com/jrburke/requirejs for details
3716  */
3717 //Helper functions to deal with file I/O.
3719 /*jslint plusplus: false */
3720 /*global java: false, define: false */
3722 define('rhino/file', ['prim'], function (prim) {
3723     var file = {
3724         backSlashRegExp: /\\/g,
3726         exclusionRegExp: /^\./,
3728         getLineSeparator: function () {
3729             return file.lineSeparator;
3730         },
3732         lineSeparator: java.lang.System.getProperty("line.separator"), //Java String
3734         exists: function (fileName) {
3735             return (new java.io.File(fileName)).exists();
3736         },
3738         parent: function (fileName) {
3739             return file.absPath((new java.io.File(fileName)).getParentFile());
3740         },
3742         normalize: function (fileName) {
3743             return file.absPath(fileName);
3744         },
3746         isFile: function (path) {
3747             return (new java.io.File(path)).isFile();
3748         },
3750         isDirectory: function (path) {
3751             return (new java.io.File(path)).isDirectory();
3752         },
3754         /**
3755          * Gets the absolute file path as a string, normalized
3756          * to using front slashes for path separators.
3757          * @param {java.io.File||String} file
3758          */
3759         absPath: function (fileObj) {
3760             if (typeof fileObj === "string") {
3761                 fileObj = new java.io.File(fileObj);
3762             }
3763             return (fileObj.getCanonicalPath() + "").replace(file.backSlashRegExp, "/");
3764         },
3766         getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) {
3767             //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
3768             //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
3769             //and it will be treated as the "include" case.
3770             //Ignores files/directories that start with a period (.) unless exclusionRegExp
3771             //is set to another value.
3772             var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
3773                 i, fileObj, filePath, ok, dirFiles;
3775             topDir = startDir;
3776             if (!startDirIsJavaObject) {
3777                 topDir = new java.io.File(startDir);
3778             }
3780             regExpInclude = regExpFilters.include || regExpFilters;
3781             regExpExclude = regExpFilters.exclude || null;
3783             if (topDir.exists()) {
3784                 dirFileArray = topDir.listFiles();
3785                 for (i = 0; i < dirFileArray.length; i++) {
3786                     fileObj = dirFileArray[i];
3787                     if (fileObj.isFile()) {
3788                         filePath = fileObj.getPath();
3789                         if (makeUnixPaths) {
3790                             //Make sure we have a JS string.
3791                             filePath = String(filePath);
3792                             if (filePath.indexOf("/") === -1) {
3793                                 filePath = filePath.replace(/\\/g, "/");
3794                             }
3795                         }
3797                         ok = true;
3798                         if (regExpInclude) {
3799                             ok = filePath.match(regExpInclude);
3800                         }
3801                         if (ok && regExpExclude) {
3802                             ok = !filePath.match(regExpExclude);
3803                         }
3805                         if (ok && (!file.exclusionRegExp ||
3806                             !file.exclusionRegExp.test(fileObj.getName()))) {
3807                             files.push(filePath);
3808                         }
3809                     } else if (fileObj.isDirectory() &&
3810                               (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.getName()))) {
3811                         dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true);
3812                         files.push.apply(files, dirFiles);
3813                     }
3814                 }
3815             }
3817             return files; //Array
3818         },
3820         copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
3821             //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
3822             //file should be copied. Returns a list file name strings of the destinations that were copied.
3823             regExpFilter = regExpFilter || /\w/;
3825             var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
3826             copiedFiles = [], i, srcFileName, destFileName;
3828             for (i = 0; i < fileNames.length; i++) {
3829                 srcFileName = fileNames[i];
3830                 destFileName = srcFileName.replace(srcDir, destDir);
3832                 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
3833                     copiedFiles.push(destFileName);
3834                 }
3835             }
3837             return copiedFiles.length ? copiedFiles : null; //Array or null
3838         },
3840         copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
3841             //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
3842             //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
3843             var destFile = new java.io.File(destFileName), srcFile, parentDir,
3844             srcChannel, destChannel;
3846             //logger.trace("Src filename: " + srcFileName);
3847             //logger.trace("Dest filename: " + destFileName);
3849             //If onlyCopyNew is true, then compare dates and only copy if the src is newer
3850             //than dest.
3851             if (onlyCopyNew) {
3852                 srcFile = new java.io.File(srcFileName);
3853                 if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
3854                     return false; //Boolean
3855                 }
3856             }
3858             //Make sure destination dir exists.
3859             parentDir = destFile.getParentFile();
3860             if (!parentDir.exists()) {
3861                 if (!parentDir.mkdirs()) {
3862                     throw "Could not create directory: " + parentDir.getCanonicalPath();
3863                 }
3864             }
3866             //Java's version of copy file.
3867             srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
3868             destChannel = new java.io.FileOutputStream(destFileName).getChannel();
3869             destChannel.transferFrom(srcChannel, 0, srcChannel.size());
3870             srcChannel.close();
3871             destChannel.close();
3873             return true; //Boolean
3874         },
3876         /**
3877          * Renames a file. May fail if "to" already exists or is on another drive.
3878          */
3879         renameFile: function (from, to) {
3880             return (new java.io.File(from)).renameTo((new java.io.File(to)));
3881         },
3883         readFile: function (/*String*/path, /*String?*/encoding) {
3884             //A file read function that can deal with BOMs
3885             encoding = encoding || "utf-8";
3886             var fileObj = new java.io.File(path),
3887                     input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(fileObj), encoding)),
3888                     stringBuffer, line;
3889             try {
3890                 stringBuffer = new java.lang.StringBuffer();
3891                 line = input.readLine();
3893                 // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
3894                 // http://www.unicode.org/faq/utf_bom.html
3896                 // 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:
3897                 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
3898                 if (line && line.length() && line.charAt(0) === 0xfeff) {
3899                     // Eat the BOM, since we've already found the encoding on this file,
3900                     // and we plan to concatenating this buffer with others; the BOM should
3901                     // only appear at the top of a file.
3902                     line = line.substring(1);
3903                 }
3904                 while (line !== null) {
3905                     stringBuffer.append(line);
3906                     stringBuffer.append(file.lineSeparator);
3907                     line = input.readLine();
3908                 }
3909                 //Make sure we return a JavaScript string and not a Java string.
3910                 return String(stringBuffer.toString()); //String
3911             } finally {
3912                 input.close();
3913             }
3914         },
3916         readFileAsync: function (path, encoding) {
3917             var d = prim();
3918             try {
3919                 d.resolve(file.readFile(path, encoding));
3920             } catch (e) {
3921                 d.reject(e);
3922             }
3923             return d.promise;
3924         },
3926         saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
3927             //summary: saves a file using UTF-8 encoding.
3928             file.saveFile(fileName, fileContents, "utf-8");
3929         },
3931         saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
3932             //summary: saves a file.
3933             var outFile = new java.io.File(fileName), outWriter, parentDir, os;
3935             parentDir = outFile.getAbsoluteFile().getParentFile();
3936             if (!parentDir.exists()) {
3937                 if (!parentDir.mkdirs()) {
3938                     throw "Could not create directory: " + parentDir.getAbsolutePath();
3939                 }
3940             }
3942             if (encoding) {
3943                 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
3944             } else {
3945                 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
3946             }
3948             os = new java.io.BufferedWriter(outWriter);
3949             try {
3950                 os.write(fileContents);
3951             } finally {
3952                 os.close();
3953             }
3954         },
3956         deleteFile: function (/*String*/fileName) {
3957             //summary: deletes a file or directory if it exists.
3958             var fileObj = new java.io.File(fileName), files, i;
3959             if (fileObj.exists()) {
3960                 if (fileObj.isDirectory()) {
3961                     files = fileObj.listFiles();
3962                     for (i = 0; i < files.length; i++) {
3963                         this.deleteFile(files[i]);
3964                     }
3965                 }
3966                 fileObj["delete"]();
3967             }
3968         },
3970         /**
3971          * Deletes any empty directories under the given directory.
3972          * The startDirIsJavaObject is private to this implementation's
3973          * recursion needs.
3974          */
3975         deleteEmptyDirs: function (startDir, startDirIsJavaObject) {
3976             var topDir = startDir,
3977                 dirFileArray, i, fileObj;
3979             if (!startDirIsJavaObject) {
3980                 topDir = new java.io.File(startDir);
3981             }
3983             if (topDir.exists()) {
3984                 dirFileArray = topDir.listFiles();
3985                 for (i = 0; i < dirFileArray.length; i++) {
3986                     fileObj = dirFileArray[i];
3987                     if (fileObj.isDirectory()) {
3988                         file.deleteEmptyDirs(fileObj, true);
3989                     }
3990                 }
3992                 //If the directory is empty now, delete it.
3993                 if (topDir.listFiles().length === 0) {
3994                     file.deleteFile(String(topDir.getPath()));
3995                 }
3996             }
3997         }
3998     };
4000     return file;
4005 if(env === 'xpconnect') {
4007  * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
4008  * Available via the MIT or new BSD license.
4009  * see: http://github.com/jrburke/requirejs for details
4010  */
4011 //Helper functions to deal with file I/O.
4013 /*jslint plusplus: false */
4014 /*global define, Components, xpcUtil */
4016 define('xpconnect/file', ['prim'], function (prim) {
4017     var file,
4018         Cc = Components.classes,
4019         Ci = Components.interfaces,
4020         //Depends on xpcUtil which is set up in x.js
4021         xpfile = xpcUtil.xpfile;
4023     function mkFullDir(dirObj) {
4024         //1 is DIRECTORY_TYPE, 511 is 0777 permissions
4025         if (!dirObj.exists()) {
4026             dirObj.create(1, 511);
4027         }
4028     }
4030     file = {
4031         backSlashRegExp: /\\/g,
4033         exclusionRegExp: /^\./,
4035         getLineSeparator: function () {
4036             return file.lineSeparator;
4037         },
4039         lineSeparator: ('@mozilla.org/windows-registry-key;1' in Cc) ?
4040                         '\r\n' : '\n',
4042         exists: function (fileName) {
4043             return xpfile(fileName).exists();
4044         },
4046         parent: function (fileName) {
4047             return xpfile(fileName).parent;
4048         },
4050         normalize: function (fileName) {
4051             return file.absPath(fileName);
4052         },
4054         isFile: function (path) {
4055             return xpfile(path).isFile();
4056         },
4058         isDirectory: function (path) {
4059             return xpfile(path).isDirectory();
4060         },
4062         /**
4063          * Gets the absolute file path as a string, normalized
4064          * to using front slashes for path separators.
4065          * @param {java.io.File||String} file
4066          */
4067         absPath: function (fileObj) {
4068             if (typeof fileObj === "string") {
4069                 fileObj = xpfile(fileObj);
4070             }
4071             return fileObj.path;
4072         },
4074         getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsObject) {
4075             //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
4076             //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
4077             //and it will be treated as the "include" case.
4078             //Ignores files/directories that start with a period (.) unless exclusionRegExp
4079             //is set to another value.
4080             var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
4081                 fileObj, filePath, ok, dirFiles;
4083             topDir = startDir;
4084             if (!startDirIsObject) {
4085                 topDir = xpfile(startDir);
4086             }
4088             regExpInclude = regExpFilters.include || regExpFilters;
4089             regExpExclude = regExpFilters.exclude || null;
4091             if (topDir.exists()) {
4092                 dirFileArray = topDir.directoryEntries;
4093                 while (dirFileArray.hasMoreElements()) {
4094                     fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile);
4095                     if (fileObj.isFile()) {
4096                         filePath = fileObj.path;
4097                         if (makeUnixPaths) {
4098                             if (filePath.indexOf("/") === -1) {
4099                                 filePath = filePath.replace(/\\/g, "/");
4100                             }
4101                         }
4103                         ok = true;
4104                         if (regExpInclude) {
4105                             ok = filePath.match(regExpInclude);
4106                         }
4107                         if (ok && regExpExclude) {
4108                             ok = !filePath.match(regExpExclude);
4109                         }
4111                         if (ok && (!file.exclusionRegExp ||
4112                             !file.exclusionRegExp.test(fileObj.leafName))) {
4113                             files.push(filePath);
4114                         }
4115                     } else if (fileObj.isDirectory() &&
4116                               (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.leafName))) {
4117                         dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true);
4118                         files.push.apply(files, dirFiles);
4119                     }
4120                 }
4121             }
4123             return files; //Array
4124         },
4126         copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
4127             //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
4128             //file should be copied. Returns a list file name strings of the destinations that were copied.
4129             regExpFilter = regExpFilter || /\w/;
4131             var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
4132             copiedFiles = [], i, srcFileName, destFileName;
4134             for (i = 0; i < fileNames.length; i += 1) {
4135                 srcFileName = fileNames[i];
4136                 destFileName = srcFileName.replace(srcDir, destDir);
4138                 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
4139                     copiedFiles.push(destFileName);
4140                 }
4141             }
4143             return copiedFiles.length ? copiedFiles : null; //Array or null
4144         },
4146         copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
4147             //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
4148             //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
4149             var destFile = xpfile(destFileName),
4150             srcFile = xpfile(srcFileName);
4152             //logger.trace("Src filename: " + srcFileName);
4153             //logger.trace("Dest filename: " + destFileName);
4155             //If onlyCopyNew is true, then compare dates and only copy if the src is newer
4156             //than dest.
4157             if (onlyCopyNew) {
4158                 if (destFile.exists() && destFile.lastModifiedTime >= srcFile.lastModifiedTime) {
4159                     return false; //Boolean
4160                 }
4161             }
4163             srcFile.copyTo(destFile.parent, destFile.leafName);
4165             return true; //Boolean
4166         },
4168         /**
4169          * Renames a file. May fail if "to" already exists or is on another drive.
4170          */
4171         renameFile: function (from, to) {
4172             var toFile = xpfile(to);
4173             return xpfile(from).moveTo(toFile.parent, toFile.leafName);
4174         },
4176         readFile: xpcUtil.readFile,
4178         readFileAsync: function (path, encoding) {
4179             var d = prim();
4180             try {
4181                 d.resolve(file.readFile(path, encoding));
4182             } catch (e) {
4183                 d.reject(e);
4184             }
4185             return d.promise;
4186         },
4188         saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
4189             //summary: saves a file using UTF-8 encoding.
4190             file.saveFile(fileName, fileContents, "utf-8");
4191         },
4193         saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
4194             var outStream, convertStream,
4195                 fileObj = xpfile(fileName);
4197             mkFullDir(fileObj.parent);
4199             try {
4200                 outStream = Cc['@mozilla.org/network/file-output-stream;1']
4201                              .createInstance(Ci.nsIFileOutputStream);
4202                 //438 is decimal for 0777
4203                 outStream.init(fileObj, 0x02 | 0x08 | 0x20, 511, 0);
4205                 convertStream = Cc['@mozilla.org/intl/converter-output-stream;1']
4206                                   .createInstance(Ci.nsIConverterOutputStream);
4208                 convertStream.init(outStream, encoding, 0, 0);
4209                 convertStream.writeString(fileContents);
4210             } catch (e) {
4211                 throw new Error((fileObj && fileObj.path || '') + ': ' + e);
4212             } finally {
4213                 if (convertStream) {
4214                     convertStream.close();
4215                 }
4216                 if (outStream) {
4217                     outStream.close();
4218                 }
4219             }
4220         },
4222         deleteFile: function (/*String*/fileName) {
4223             //summary: deletes a file or directory if it exists.
4224             var fileObj = xpfile(fileName);
4225             if (fileObj.exists()) {
4226                 fileObj.remove(true);
4227             }
4228         },
4230         /**
4231          * Deletes any empty directories under the given directory.
4232          * The startDirIsJavaObject is private to this implementation's
4233          * recursion needs.
4234          */
4235         deleteEmptyDirs: function (startDir, startDirIsObject) {
4236             var topDir = startDir,
4237                 dirFileArray, fileObj;
4239             if (!startDirIsObject) {
4240                 topDir = xpfile(startDir);
4241             }
4243             if (topDir.exists()) {
4244                 dirFileArray = topDir.directoryEntries;
4245                 while (dirFileArray.hasMoreElements()) {
4246                     fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile);
4248                     if (fileObj.isDirectory()) {
4249                         file.deleteEmptyDirs(fileObj, true);
4250                     }
4251                 }
4253                 //If the directory is empty now, delete it.
4254                 dirFileArray = topDir.directoryEntries;
4255                 if (!dirFileArray.hasMoreElements()) {
4256                     file.deleteFile(topDir.path);
4257                 }
4258             }
4259         }
4260     };
4262     return file;
4267 if(env === 'browser') {
4268 /*global process */
4269 define('browser/quit', function () {
4270     'use strict';
4271     return function (code) {
4272     };
4276 if(env === 'node') {
4277 /*global process */
4278 define('node/quit', function () {
4279     'use strict';
4280     return function (code) {
4281         var draining = 0;
4282         var exit = function () {
4283             if (draining === 0) {
4284                 process.exit(code);
4285             } else {
4286                 draining -= 1;
4287             }
4288         };
4289         if (process.stdout.bufferSize) {
4290             draining += 1;
4291             process.stdout.once('drain', exit);
4292         }
4293         if (process.stderr.bufferSize) {
4294             draining += 1;
4295             process.stderr.once('drain', exit);
4296         }
4297         exit();
4298     };
4303 if(env === 'rhino') {
4304 /*global quit */
4305 define('rhino/quit', function () {
4306     'use strict';
4307     return function (code) {
4308         return quit(code);
4309     };
4314 if(env === 'xpconnect') {
4315 /*global quit */
4316 define('xpconnect/quit', function () {
4317     'use strict';
4318     return function (code) {
4319         return quit(code);
4320     };
4325 if(env === 'browser') {
4327  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
4328  * Available via the MIT or new BSD license.
4329  * see: http://github.com/jrburke/requirejs for details
4330  */
4332 /*jslint strict: false */
4333 /*global define: false, console: false */
4335 define('browser/print', function () {
4336     function print(msg) {
4337         console.log(msg);
4338     }
4340     return print;
4345 if(env === 'node') {
4347  * @license RequireJS Copyright (c) 2010-2011, 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, console: false */
4355 define('node/print', function () {
4356     function print(msg) {
4357         console.log(msg);
4358     }
4360     return print;
4365 if(env === 'rhino') {
4367  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
4368  * Available via the MIT or new BSD license.
4369  * see: http://github.com/jrburke/requirejs for details
4370  */
4372 /*jslint strict: false */
4373 /*global define: false, print: false */
4375 define('rhino/print', function () {
4376     return print;
4381 if(env === 'xpconnect') {
4383  * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
4384  * Available via the MIT or new BSD license.
4385  * see: http://github.com/jrburke/requirejs for details
4386  */
4388 /*jslint strict: false */
4389 /*global define: false, print: false */
4391 define('xpconnect/print', function () {
4392     return print;
4397  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
4398  * Available via the MIT or new BSD license.
4399  * see: http://github.com/jrburke/requirejs for details
4400  */
4402 /*jslint nomen: false, strict: false */
4403 /*global define: false */
4405 define('logger', ['env!env/print'], function (print) {
4406     var logger = {
4407         TRACE: 0,
4408         INFO: 1,
4409         WARN: 2,
4410         ERROR: 3,
4411         SILENT: 4,
4412         level: 0,
4413         logPrefix: "",
4415         logLevel: function( level ) {
4416             this.level = level;
4417         },
4419         trace: function (message) {
4420             if (this.level <= this.TRACE) {
4421                 this._print(message);
4422             }
4423         },
4425         info: function (message) {
4426             if (this.level <= this.INFO) {
4427                 this._print(message);
4428             }
4429         },
4431         warn: function (message) {
4432             if (this.level <= this.WARN) {
4433                 this._print(message);
4434             }
4435         },
4437         error: function (message) {
4438             if (this.level <= this.ERROR) {
4439                 this._print(message);
4440             }
4441         },
4443         _print: function (message) {
4444             this._sysPrint((this.logPrefix ? (this.logPrefix + " ") : "") + message);
4445         },
4447         _sysPrint: function (message) {
4448             print(message);
4449         }
4450     };
4452     return logger;
4454 //Just a blank file to use when building the optimizer with the optimizer,
4455 //so that the build does not attempt to inline some env modules,
4456 //like Node's fs and path.
4459   Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
4460   Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
4461   Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
4462   Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
4463   Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
4464   Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
4465   Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
4467   Redistribution and use in source and binary forms, with or without
4468   modification, are permitted provided that the following conditions are met:
4470     * Redistributions of source code must retain the above copyright
4471       notice, this list of conditions and the following disclaimer.
4472     * Redistributions in binary form must reproduce the above copyright
4473       notice, this list of conditions and the following disclaimer in the
4474       documentation and/or other materials provided with the distribution.
4476   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4477   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4478   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4479   ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
4480   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4481   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4482   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
4483   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4484   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
4485   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4488 /*jslint bitwise:true plusplus:true */
4489 /*global esprima:true, define:true, exports:true, window: true,
4490 throwError: true, createLiteral: true, generateStatement: true,
4491 parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
4492 parseFunctionDeclaration: true, parseFunctionExpression: true,
4493 parseFunctionSourceElements: true, parseVariableIdentifier: true,
4494 parseLeftHandSideExpression: true,
4495 parseStatement: true, parseSourceElement: true */
4497 (function (root, factory) {
4498     'use strict';
4500     // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
4501     // Rhino, and plain browser loading.
4502     if (typeof define === 'function' && define.amd) {
4503         define('esprima', ['exports'], factory);
4504     } else if (typeof exports !== 'undefined') {
4505         factory(exports);
4506     } else {
4507         factory((root.esprima = {}));
4508     }
4509 }(this, function (exports) {
4510     'use strict';
4512     var Token,
4513         TokenName,
4514         Syntax,
4515         PropertyKind,
4516         Messages,
4517         Regex,
4518         source,
4519         strict,
4520         index,
4521         lineNumber,
4522         lineStart,
4523         length,
4524         buffer,
4525         state,
4526         extra;
4528     Token = {
4529         BooleanLiteral: 1,
4530         EOF: 2,
4531         Identifier: 3,
4532         Keyword: 4,
4533         NullLiteral: 5,
4534         NumericLiteral: 6,
4535         Punctuator: 7,
4536         StringLiteral: 8
4537     };
4539     TokenName = {};
4540     TokenName[Token.BooleanLiteral] = 'Boolean';
4541     TokenName[Token.EOF] = '<end>';
4542     TokenName[Token.Identifier] = 'Identifier';
4543     TokenName[Token.Keyword] = 'Keyword';
4544     TokenName[Token.NullLiteral] = 'Null';
4545     TokenName[Token.NumericLiteral] = 'Numeric';
4546     TokenName[Token.Punctuator] = 'Punctuator';
4547     TokenName[Token.StringLiteral] = 'String';
4549     Syntax = {
4550         AssignmentExpression: 'AssignmentExpression',
4551         ArrayExpression: 'ArrayExpression',
4552         BlockStatement: 'BlockStatement',
4553         BinaryExpression: 'BinaryExpression',
4554         BreakStatement: 'BreakStatement',
4555         CallExpression: 'CallExpression',
4556         CatchClause: 'CatchClause',
4557         ConditionalExpression: 'ConditionalExpression',
4558         ContinueStatement: 'ContinueStatement',
4559         DoWhileStatement: 'DoWhileStatement',
4560         DebuggerStatement: 'DebuggerStatement',
4561         EmptyStatement: 'EmptyStatement',
4562         ExpressionStatement: 'ExpressionStatement',
4563         ForStatement: 'ForStatement',
4564         ForInStatement: 'ForInStatement',
4565         FunctionDeclaration: 'FunctionDeclaration',
4566         FunctionExpression: 'FunctionExpression',
4567         Identifier: 'Identifier',
4568         IfStatement: 'IfStatement',
4569         Literal: 'Literal',
4570         LabeledStatement: 'LabeledStatement',
4571         LogicalExpression: 'LogicalExpression',
4572         MemberExpression: 'MemberExpression',
4573         NewExpression: 'NewExpression',
4574         ObjectExpression: 'ObjectExpression',
4575         Program: 'Program',
4576         Property: 'Property',
4577         ReturnStatement: 'ReturnStatement',
4578         SequenceExpression: 'SequenceExpression',
4579         SwitchStatement: 'SwitchStatement',
4580         SwitchCase: 'SwitchCase',
4581         ThisExpression: 'ThisExpression',
4582         ThrowStatement: 'ThrowStatement',
4583         TryStatement: 'TryStatement',
4584         UnaryExpression: 'UnaryExpression',
4585         UpdateExpression: 'UpdateExpression',
4586         VariableDeclaration: 'VariableDeclaration',
4587         VariableDeclarator: 'VariableDeclarator',
4588         WhileStatement: 'WhileStatement',
4589         WithStatement: 'WithStatement'
4590     };
4592     PropertyKind = {
4593         Data: 1,
4594         Get: 2,
4595         Set: 4
4596     };
4598     // Error messages should be identical to V8.
4599     Messages = {
4600         UnexpectedToken:  'Unexpected token %0',
4601         UnexpectedNumber:  'Unexpected number',
4602         UnexpectedString:  'Unexpected string',
4603         UnexpectedIdentifier:  'Unexpected identifier',
4604         UnexpectedReserved:  'Unexpected reserved word',
4605         UnexpectedEOS:  'Unexpected end of input',
4606         NewlineAfterThrow:  'Illegal newline after throw',
4607         InvalidRegExp: 'Invalid regular expression',
4608         UnterminatedRegExp:  'Invalid regular expression: missing /',
4609         InvalidLHSInAssignment:  'Invalid left-hand side in assignment',
4610         InvalidLHSInForIn:  'Invalid left-hand side in for-in',
4611         MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
4612         NoCatchOrFinally:  'Missing catch or finally after try',
4613         UnknownLabel: 'Undefined label \'%0\'',
4614         Redeclaration: '%0 \'%1\' has already been declared',
4615         IllegalContinue: 'Illegal continue statement',
4616         IllegalBreak: 'Illegal break statement',
4617         IllegalReturn: 'Illegal return statement',
4618         StrictModeWith:  'Strict mode code may not include a with statement',
4619         StrictCatchVariable:  'Catch variable may not be eval or arguments in strict mode',
4620         StrictVarName:  'Variable name may not be eval or arguments in strict mode',
4621         StrictParamName:  'Parameter name eval or arguments is not allowed in strict mode',
4622         StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
4623         StrictFunctionName:  'Function name may not be eval or arguments in strict mode',
4624         StrictOctalLiteral:  'Octal literals are not allowed in strict mode.',
4625         StrictDelete:  'Delete of an unqualified identifier in strict mode.',
4626         StrictDuplicateProperty:  'Duplicate data property in object literal not allowed in strict mode',
4627         AccessorDataProperty:  'Object literal may not have data and accessor property with the same name',
4628         AccessorGetSet:  'Object literal may not have multiple get/set accessors with the same name',
4629         StrictLHSAssignment:  'Assignment to eval or arguments is not allowed in strict mode',
4630         StrictLHSPostfix:  'Postfix increment/decrement may not have eval or arguments operand in strict mode',
4631         StrictLHSPrefix:  'Prefix increment/decrement may not have eval or arguments operand in strict mode',
4632         StrictReservedWord:  'Use of future reserved word in strict mode'
4633     };
4635     // See also tools/generate-unicode-regex.py.
4636     Regex = {
4637         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]'),
4638         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]')
4639     };
4641     // Ensure the condition is true, otherwise throw an error.
4642     // This is only to have a better contract semantic, i.e. another safety net
4643     // to catch a logic error. The condition shall be fulfilled in normal case.
4644     // Do NOT use this to enforce a certain condition on any user input.
4646     function assert(condition, message) {
4647         if (!condition) {
4648             throw new Error('ASSERT: ' + message);
4649         }
4650     }
4652     function sliceSource(from, to) {
4653         return source.slice(from, to);
4654     }
4656     if (typeof 'esprima'[0] === 'undefined') {
4657         sliceSource = function sliceArraySource(from, to) {
4658             return source.slice(from, to).join('');
4659         };
4660     }
4662     function isDecimalDigit(ch) {
4663         return '0123456789'.indexOf(ch) >= 0;
4664     }
4666     function isHexDigit(ch) {
4667         return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
4668     }
4670     function isOctalDigit(ch) {
4671         return '01234567'.indexOf(ch) >= 0;
4672     }
4675     // 7.2 White Space
4677     function isWhiteSpace(ch) {
4678         return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
4679             (ch === '\u000C') || (ch === '\u00A0') ||
4680             (ch.charCodeAt(0) >= 0x1680 &&
4681              '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
4682     }
4684     // 7.3 Line Terminators
4686     function isLineTerminator(ch) {
4687         return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
4688     }
4690     // 7.6 Identifier Names and Identifiers
4692     function isIdentifierStart(ch) {
4693         return (ch === '$') || (ch === '_') || (ch === '\\') ||
4694             (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
4695             ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
4696     }
4698     function isIdentifierPart(ch) {
4699         return (ch === '$') || (ch === '_') || (ch === '\\') ||
4700             (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
4701             ((ch >= '0') && (ch <= '9')) ||
4702             ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
4703     }
4705     // 7.6.1.2 Future Reserved Words
4707     function isFutureReservedWord(id) {
4708         switch (id) {
4710         // Future reserved words.
4711         case 'class':
4712         case 'enum':
4713         case 'export':
4714         case 'extends':
4715         case 'import':
4716         case 'super':
4717             return true;
4718         }
4720         return false;
4721     }
4723     function isStrictModeReservedWord(id) {
4724         switch (id) {
4726         // Strict Mode reserved words.
4727         case 'implements':
4728         case 'interface':
4729         case 'package':
4730         case 'private':
4731         case 'protected':
4732         case 'public':
4733         case 'static':
4734         case 'yield':
4735         case 'let':
4736             return true;
4737         }
4739         return false;
4740     }
4742     function isRestrictedWord(id) {
4743         return id === 'eval' || id === 'arguments';
4744     }
4746     // 7.6.1.1 Keywords
4748     function isKeyword(id) {
4749         var keyword = false;
4750         switch (id.length) {
4751         case 2:
4752             keyword = (id === 'if') || (id === 'in') || (id === 'do');
4753             break;
4754         case 3:
4755             keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
4756             break;
4757         case 4:
4758             keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with');
4759             break;
4760         case 5:
4761             keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw');
4762             break;
4763         case 6:
4764             keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch');
4765             break;
4766         case 7:
4767             keyword = (id === 'default') || (id === 'finally');
4768             break;
4769         case 8:
4770             keyword = (id === 'function') || (id === 'continue') || (id === 'debugger');
4771             break;
4772         case 10:
4773             keyword = (id === 'instanceof');
4774             break;
4775         }
4777         if (keyword) {
4778             return true;
4779         }
4781         switch (id) {
4782         // Future reserved words.
4783         // 'const' is specialized as Keyword in V8.
4784         case 'const':
4785             return true;
4787         // For compatiblity to SpiderMonkey and ES.next
4788         case 'yield':
4789         case 'let':
4790             return true;
4791         }
4793         if (strict && isStrictModeReservedWord(id)) {
4794             return true;
4795         }
4797         return isFutureReservedWord(id);
4798     }
4800     // 7.4 Comments
4802     function skipComment() {
4803         var ch, blockComment, lineComment;
4805         blockComment = false;
4806         lineComment = false;
4808         while (index < length) {
4809             ch = source[index];
4811             if (lineComment) {
4812                 ch = source[index++];
4813                 if (isLineTerminator(ch)) {
4814                     lineComment = false;
4815                     if (ch === '\r' && source[index] === '\n') {
4816                         ++index;
4817                     }
4818                     ++lineNumber;
4819                     lineStart = index;
4820                 }
4821             } else if (blockComment) {
4822                 if (isLineTerminator(ch)) {
4823                     if (ch === '\r' && source[index + 1] === '\n') {
4824                         ++index;
4825                     }
4826                     ++lineNumber;
4827                     ++index;
4828                     lineStart = index;
4829                     if (index >= length) {
4830                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
4831                     }
4832                 } else {
4833                     ch = source[index++];
4834                     if (index >= length) {
4835                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
4836                     }
4837                     if (ch === '*') {
4838                         ch = source[index];
4839                         if (ch === '/') {
4840                             ++index;
4841                             blockComment = false;
4842                         }
4843                     }
4844                 }
4845             } else if (ch === '/') {
4846                 ch = source[index + 1];
4847                 if (ch === '/') {
4848                     index += 2;
4849                     lineComment = true;
4850                 } else if (ch === '*') {
4851                     index += 2;
4852                     blockComment = true;
4853                     if (index >= length) {
4854                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
4855                     }
4856                 } else {
4857                     break;
4858                 }
4859             } else if (isWhiteSpace(ch)) {
4860                 ++index;
4861             } else if (isLineTerminator(ch)) {
4862                 ++index;
4863                 if (ch ===  '\r' && source[index] === '\n') {
4864                     ++index;
4865                 }
4866                 ++lineNumber;
4867                 lineStart = index;
4868             } else {
4869                 break;
4870             }
4871         }
4872     }
4874     function scanHexEscape(prefix) {
4875         var i, len, ch, code = 0;
4877         len = (prefix === 'u') ? 4 : 2;
4878         for (i = 0; i < len; ++i) {
4879             if (index < length && isHexDigit(source[index])) {
4880                 ch = source[index++];
4881                 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
4882             } else {
4883                 return '';
4884             }
4885         }
4886         return String.fromCharCode(code);
4887     }
4889     function scanIdentifier() {
4890         var ch, start, id, restore;
4892         ch = source[index];
4893         if (!isIdentifierStart(ch)) {
4894             return;
4895         }
4897         start = index;
4898         if (ch === '\\') {
4899             ++index;
4900             if (source[index] !== 'u') {
4901                 return;
4902             }
4903             ++index;
4904             restore = index;
4905             ch = scanHexEscape('u');
4906             if (ch) {
4907                 if (ch === '\\' || !isIdentifierStart(ch)) {
4908                     return;
4909                 }
4910                 id = ch;
4911             } else {
4912                 index = restore;
4913                 id = 'u';
4914             }
4915         } else {
4916             id = source[index++];
4917         }
4919         while (index < length) {
4920             ch = source[index];
4921             if (!isIdentifierPart(ch)) {
4922                 break;
4923             }
4924             if (ch === '\\') {
4925                 ++index;
4926                 if (source[index] !== 'u') {
4927                     return;
4928                 }
4929                 ++index;
4930                 restore = index;
4931                 ch = scanHexEscape('u');
4932                 if (ch) {
4933                     if (ch === '\\' || !isIdentifierPart(ch)) {
4934                         return;
4935                     }
4936                     id += ch;
4937                 } else {
4938                     index = restore;
4939                     id += 'u';
4940                 }
4941             } else {
4942                 id += source[index++];
4943             }
4944         }
4946         // There is no keyword or literal with only one character.
4947         // Thus, it must be an identifier.
4948         if (id.length === 1) {
4949             return {
4950                 type: Token.Identifier,
4951                 value: id,
4952                 lineNumber: lineNumber,
4953                 lineStart: lineStart,
4954                 range: [start, index]
4955             };
4956         }
4958         if (isKeyword(id)) {
4959             return {
4960                 type: Token.Keyword,
4961                 value: id,
4962                 lineNumber: lineNumber,
4963                 lineStart: lineStart,
4964                 range: [start, index]
4965             };
4966         }
4968         // 7.8.1 Null Literals
4970         if (id === 'null') {
4971             return {
4972                 type: Token.NullLiteral,
4973                 value: id,
4974                 lineNumber: lineNumber,
4975                 lineStart: lineStart,
4976                 range: [start, index]
4977             };
4978         }
4980         // 7.8.2 Boolean Literals
4982         if (id === 'true' || id === 'false') {
4983             return {
4984                 type: Token.BooleanLiteral,
4985                 value: id,
4986                 lineNumber: lineNumber,
4987                 lineStart: lineStart,
4988                 range: [start, index]
4989             };
4990         }
4992         return {
4993             type: Token.Identifier,
4994             value: id,
4995             lineNumber: lineNumber,
4996             lineStart: lineStart,
4997             range: [start, index]
4998         };
4999     }
5001     // 7.7 Punctuators
5003     function scanPunctuator() {
5004         var start = index,
5005             ch1 = source[index],
5006             ch2,
5007             ch3,
5008             ch4;
5010         // Check for most common single-character punctuators.
5012         if (ch1 === ';' || ch1 === '{' || ch1 === '}') {
5013             ++index;
5014             return {
5015                 type: Token.Punctuator,
5016                 value: ch1,
5017                 lineNumber: lineNumber,
5018                 lineStart: lineStart,
5019                 range: [start, index]
5020             };
5021         }
5023         if (ch1 === ',' || ch1 === '(' || ch1 === ')') {
5024             ++index;
5025             return {
5026                 type: Token.Punctuator,
5027                 value: ch1,
5028                 lineNumber: lineNumber,
5029                 lineStart: lineStart,
5030                 range: [start, index]
5031             };
5032         }
5034         // Dot (.) can also start a floating-point number, hence the need
5035         // to check the next character.
5037         ch2 = source[index + 1];
5038         if (ch1 === '.' && !isDecimalDigit(ch2)) {
5039             return {
5040                 type: Token.Punctuator,
5041                 value: source[index++],
5042                 lineNumber: lineNumber,
5043                 lineStart: lineStart,
5044                 range: [start, index]
5045             };
5046         }
5048         // Peek more characters.
5050         ch3 = source[index + 2];
5051         ch4 = source[index + 3];
5053         // 4-character punctuator: >>>=
5055         if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
5056             if (ch4 === '=') {
5057                 index += 4;
5058                 return {
5059                     type: Token.Punctuator,
5060                     value: '>>>=',
5061                     lineNumber: lineNumber,
5062                     lineStart: lineStart,
5063                     range: [start, index]
5064                 };
5065             }
5066         }
5068         // 3-character punctuators: === !== >>> <<= >>=
5070         if (ch1 === '=' && ch2 === '=' && ch3 === '=') {
5071             index += 3;
5072             return {
5073                 type: Token.Punctuator,
5074                 value: '===',
5075                 lineNumber: lineNumber,
5076                 lineStart: lineStart,
5077                 range: [start, index]
5078             };
5079         }
5081         if (ch1 === '!' && ch2 === '=' && ch3 === '=') {
5082             index += 3;
5083             return {
5084                 type: Token.Punctuator,
5085                 value: '!==',
5086                 lineNumber: lineNumber,
5087                 lineStart: lineStart,
5088                 range: [start, index]
5089             };
5090         }
5092         if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
5093             index += 3;
5094             return {
5095                 type: Token.Punctuator,
5096                 value: '>>>',
5097                 lineNumber: lineNumber,
5098                 lineStart: lineStart,
5099                 range: [start, index]
5100             };
5101         }
5103         if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
5104             index += 3;
5105             return {
5106                 type: Token.Punctuator,
5107                 value: '<<=',
5108                 lineNumber: lineNumber,
5109                 lineStart: lineStart,
5110                 range: [start, index]
5111             };
5112         }
5114         if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
5115             index += 3;
5116             return {
5117                 type: Token.Punctuator,
5118                 value: '>>=',
5119                 lineNumber: lineNumber,
5120                 lineStart: lineStart,
5121                 range: [start, index]
5122             };
5123         }
5125         // 2-character punctuators: <= >= == != ++ -- << >> && ||
5126         // += -= *= %= &= |= ^= /=
5128         if (ch2 === '=') {
5129             if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
5130                 index += 2;
5131                 return {
5132                     type: Token.Punctuator,
5133                     value: ch1 + ch2,
5134                     lineNumber: lineNumber,
5135                     lineStart: lineStart,
5136                     range: [start, index]
5137                 };
5138             }
5139         }
5141         if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
5142             if ('+-<>&|'.indexOf(ch2) >= 0) {
5143                 index += 2;
5144                 return {
5145                     type: Token.Punctuator,
5146                     value: ch1 + ch2,
5147                     lineNumber: lineNumber,
5148                     lineStart: lineStart,
5149                     range: [start, index]
5150                 };
5151             }
5152         }
5154         // The remaining 1-character punctuators.
5156         if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) {
5157             return {
5158                 type: Token.Punctuator,
5159                 value: source[index++],
5160                 lineNumber: lineNumber,
5161                 lineStart: lineStart,
5162                 range: [start, index]
5163             };
5164         }
5165     }
5167     // 7.8.3 Numeric Literals
5169     function scanNumericLiteral() {
5170         var number, start, ch;
5172         ch = source[index];
5173         assert(isDecimalDigit(ch) || (ch === '.'),
5174             'Numeric literal must start with a decimal digit or a decimal point');
5176         start = index;
5177         number = '';
5178         if (ch !== '.') {
5179             number = source[index++];
5180             ch = source[index];
5182             // Hex number starts with '0x'.
5183             // Octal number starts with '0'.
5184             if (number === '0') {
5185                 if (ch === 'x' || ch === 'X') {
5186                     number += source[index++];
5187                     while (index < length) {
5188                         ch = source[index];
5189                         if (!isHexDigit(ch)) {
5190                             break;
5191                         }
5192                         number += source[index++];
5193                     }
5195                     if (number.length <= 2) {
5196                         // only 0x
5197                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5198                     }
5200                     if (index < length) {
5201                         ch = source[index];
5202                         if (isIdentifierStart(ch)) {
5203                             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5204                         }
5205                     }
5206                     return {
5207                         type: Token.NumericLiteral,
5208                         value: parseInt(number, 16),
5209                         lineNumber: lineNumber,
5210                         lineStart: lineStart,
5211                         range: [start, index]
5212                     };
5213                 } else if (isOctalDigit(ch)) {
5214                     number += source[index++];
5215                     while (index < length) {
5216                         ch = source[index];
5217                         if (!isOctalDigit(ch)) {
5218                             break;
5219                         }
5220                         number += source[index++];
5221                     }
5223                     if (index < length) {
5224                         ch = source[index];
5225                         if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
5226                             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5227                         }
5228                     }
5229                     return {
5230                         type: Token.NumericLiteral,
5231                         value: parseInt(number, 8),
5232                         octal: true,
5233                         lineNumber: lineNumber,
5234                         lineStart: lineStart,
5235                         range: [start, index]
5236                     };
5237                 }
5239                 // decimal number starts with '0' such as '09' is illegal.
5240                 if (isDecimalDigit(ch)) {
5241                     throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5242                 }
5243             }
5245             while (index < length) {
5246                 ch = source[index];
5247                 if (!isDecimalDigit(ch)) {
5248                     break;
5249                 }
5250                 number += source[index++];
5251             }
5252         }
5254         if (ch === '.') {
5255             number += source[index++];
5256             while (index < length) {
5257                 ch = source[index];
5258                 if (!isDecimalDigit(ch)) {
5259                     break;
5260                 }
5261                 number += source[index++];
5262             }
5263         }
5265         if (ch === 'e' || ch === 'E') {
5266             number += source[index++];
5268             ch = source[index];
5269             if (ch === '+' || ch === '-') {
5270                 number += source[index++];
5271             }
5273             ch = source[index];
5274             if (isDecimalDigit(ch)) {
5275                 number += source[index++];
5276                 while (index < length) {
5277                     ch = source[index];
5278                     if (!isDecimalDigit(ch)) {
5279                         break;
5280                     }
5281                     number += source[index++];
5282                 }
5283             } else {
5284                 ch = 'character ' + ch;
5285                 if (index >= length) {
5286                     ch = '<end>';
5287                 }
5288                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5289             }
5290         }
5292         if (index < length) {
5293             ch = source[index];
5294             if (isIdentifierStart(ch)) {
5295                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5296             }
5297         }
5299         return {
5300             type: Token.NumericLiteral,
5301             value: parseFloat(number),
5302             lineNumber: lineNumber,
5303             lineStart: lineStart,
5304             range: [start, index]
5305         };
5306     }
5308     // 7.8.4 String Literals
5310     function scanStringLiteral() {
5311         var str = '', quote, start, ch, code, unescaped, restore, octal = false;
5313         quote = source[index];
5314         assert((quote === '\'' || quote === '"'),
5315             'String literal must starts with a quote');
5317         start = index;
5318         ++index;
5320         while (index < length) {
5321             ch = source[index++];
5323             if (ch === quote) {
5324                 quote = '';
5325                 break;
5326             } else if (ch === '\\') {
5327                 ch = source[index++];
5328                 if (!isLineTerminator(ch)) {
5329                     switch (ch) {
5330                     case 'n':
5331                         str += '\n';
5332                         break;
5333                     case 'r':
5334                         str += '\r';
5335                         break;
5336                     case 't':
5337                         str += '\t';
5338                         break;
5339                     case 'u':
5340                     case 'x':
5341                         restore = index;
5342                         unescaped = scanHexEscape(ch);
5343                         if (unescaped) {
5344                             str += unescaped;
5345                         } else {
5346                             index = restore;
5347                             str += ch;
5348                         }
5349                         break;
5350                     case 'b':
5351                         str += '\b';
5352                         break;
5353                     case 'f':
5354                         str += '\f';
5355                         break;
5356                     case 'v':
5357                         str += '\x0B';
5358                         break;
5360                     default:
5361                         if (isOctalDigit(ch)) {
5362                             code = '01234567'.indexOf(ch);
5364                             // \0 is not octal escape sequence
5365                             if (code !== 0) {
5366                                 octal = true;
5367                             }
5369                             if (index < length && isOctalDigit(source[index])) {
5370                                 octal = true;
5371                                 code = code * 8 + '01234567'.indexOf(source[index++]);
5373                                 // 3 digits are only allowed when string starts
5374                                 // with 0, 1, 2, 3
5375                                 if ('0123'.indexOf(ch) >= 0 &&
5376                                         index < length &&
5377                                         isOctalDigit(source[index])) {
5378                                     code = code * 8 + '01234567'.indexOf(source[index++]);
5379                                 }
5380                             }
5381                             str += String.fromCharCode(code);
5382                         } else {
5383                             str += ch;
5384                         }
5385                         break;
5386                     }
5387                 } else {
5388                     ++lineNumber;
5389                     if (ch ===  '\r' && source[index] === '\n') {
5390                         ++index;
5391                     }
5392                 }
5393             } else if (isLineTerminator(ch)) {
5394                 break;
5395             } else {
5396                 str += ch;
5397             }
5398         }
5400         if (quote !== '') {
5401             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5402         }
5404         return {
5405             type: Token.StringLiteral,
5406             value: str,
5407             octal: octal,
5408             lineNumber: lineNumber,
5409             lineStart: lineStart,
5410             range: [start, index]
5411         };
5412     }
5414     function scanRegExp() {
5415         var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
5417         buffer = null;
5418         skipComment();
5420         start = index;
5421         ch = source[index];
5422         assert(ch === '/', 'Regular expression literal must start with a slash');
5423         str = source[index++];
5425         while (index < length) {
5426             ch = source[index++];
5427             str += ch;
5428             if (classMarker) {
5429                 if (ch === ']') {
5430                     classMarker = false;
5431                 }
5432             } else {
5433                 if (ch === '\\') {
5434                     ch = source[index++];
5435                     // ECMA-262 7.8.5
5436                     if (isLineTerminator(ch)) {
5437                         throwError({}, Messages.UnterminatedRegExp);
5438                     }
5439                     str += ch;
5440                 } else if (ch === '/') {
5441                     terminated = true;
5442                     break;
5443                 } else if (ch === '[') {
5444                     classMarker = true;
5445                 } else if (isLineTerminator(ch)) {
5446                     throwError({}, Messages.UnterminatedRegExp);
5447                 }
5448             }
5449         }
5451         if (!terminated) {
5452             throwError({}, Messages.UnterminatedRegExp);
5453         }
5455         // Exclude leading and trailing slash.
5456         pattern = str.substr(1, str.length - 2);
5458         flags = '';
5459         while (index < length) {
5460             ch = source[index];
5461             if (!isIdentifierPart(ch)) {
5462                 break;
5463             }
5465             ++index;
5466             if (ch === '\\' && index < length) {
5467                 ch = source[index];
5468                 if (ch === 'u') {
5469                     ++index;
5470                     restore = index;
5471                     ch = scanHexEscape('u');
5472                     if (ch) {
5473                         flags += ch;
5474                         str += '\\u';
5475                         for (; restore < index; ++restore) {
5476                             str += source[restore];
5477                         }
5478                     } else {
5479                         index = restore;
5480                         flags += 'u';
5481                         str += '\\u';
5482                     }
5483                 } else {
5484                     str += '\\';
5485                 }
5486             } else {
5487                 flags += ch;
5488                 str += ch;
5489             }
5490         }
5492         try {
5493             value = new RegExp(pattern, flags);
5494         } catch (e) {
5495             throwError({}, Messages.InvalidRegExp);
5496         }
5498         return {
5499             literal: str,
5500             value: value,
5501             range: [start, index]
5502         };
5503     }
5505     function isIdentifierName(token) {
5506         return token.type === Token.Identifier ||
5507             token.type === Token.Keyword ||
5508             token.type === Token.BooleanLiteral ||
5509             token.type === Token.NullLiteral;
5510     }
5512     function advance() {
5513         var ch, token;
5515         skipComment();
5517         if (index >= length) {
5518             return {
5519                 type: Token.EOF,
5520                 lineNumber: lineNumber,
5521                 lineStart: lineStart,
5522                 range: [index, index]
5523             };
5524         }
5526         token = scanPunctuator();
5527         if (typeof token !== 'undefined') {
5528             return token;
5529         }
5531         ch = source[index];
5533         if (ch === '\'' || ch === '"') {
5534             return scanStringLiteral();
5535         }
5537         if (ch === '.' || isDecimalDigit(ch)) {
5538             return scanNumericLiteral();
5539         }
5541         token = scanIdentifier();
5542         if (typeof token !== 'undefined') {
5543             return token;
5544         }
5546         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5547     }
5549     function lex() {
5550         var token;
5552         if (buffer) {
5553             index = buffer.range[1];
5554             lineNumber = buffer.lineNumber;
5555             lineStart = buffer.lineStart;
5556             token = buffer;
5557             buffer = null;
5558             return token;
5559         }
5561         buffer = null;
5562         return advance();
5563     }
5565     function lookahead() {
5566         var pos, line, start;
5568         if (buffer !== null) {
5569             return buffer;
5570         }
5572         pos = index;
5573         line = lineNumber;
5574         start = lineStart;
5575         buffer = advance();
5576         index = pos;
5577         lineNumber = line;
5578         lineStart = start;
5580         return buffer;
5581     }
5583     // Return true if there is a line terminator before the next token.
5585     function peekLineTerminator() {
5586         var pos, line, start, found;
5588         pos = index;
5589         line = lineNumber;
5590         start = lineStart;
5591         skipComment();
5592         found = lineNumber !== line;
5593         index = pos;
5594         lineNumber = line;
5595         lineStart = start;
5597         return found;
5598     }
5600     // Throw an exception
5602     function throwError(token, messageFormat) {
5603         var error,
5604             args = Array.prototype.slice.call(arguments, 2),
5605             msg = messageFormat.replace(
5606                 /%(\d)/g,
5607                 function (whole, index) {
5608                     return args[index] || '';
5609                 }
5610             );
5612         if (typeof token.lineNumber === 'number') {
5613             error = new Error('Line ' + token.lineNumber + ': ' + msg);
5614             error.index = token.range[0];
5615             error.lineNumber = token.lineNumber;
5616             error.column = token.range[0] - lineStart + 1;
5617         } else {
5618             error = new Error('Line ' + lineNumber + ': ' + msg);
5619             error.index = index;
5620             error.lineNumber = lineNumber;
5621             error.column = index - lineStart + 1;
5622         }
5624         throw error;
5625     }
5627     function throwErrorTolerant() {
5628         try {
5629             throwError.apply(null, arguments);
5630         } catch (e) {
5631             if (extra.errors) {
5632                 extra.errors.push(e);
5633             } else {
5634                 throw e;
5635             }
5636         }
5637     }
5640     // Throw an exception because of the token.
5642     function throwUnexpected(token) {
5643         if (token.type === Token.EOF) {
5644             throwError(token, Messages.UnexpectedEOS);
5645         }
5647         if (token.type === Token.NumericLiteral) {
5648             throwError(token, Messages.UnexpectedNumber);
5649         }
5651         if (token.type === Token.StringLiteral) {
5652             throwError(token, Messages.UnexpectedString);
5653         }
5655         if (token.type === Token.Identifier) {
5656             throwError(token, Messages.UnexpectedIdentifier);
5657         }
5659         if (token.type === Token.Keyword) {
5660             if (isFutureReservedWord(token.value)) {
5661                 throwError(token, Messages.UnexpectedReserved);
5662             } else if (strict && isStrictModeReservedWord(token.value)) {
5663                 throwErrorTolerant(token, Messages.StrictReservedWord);
5664                 return;
5665             }
5666             throwError(token, Messages.UnexpectedToken, token.value);
5667         }
5669         // BooleanLiteral, NullLiteral, or Punctuator.
5670         throwError(token, Messages.UnexpectedToken, token.value);
5671     }
5673     // Expect the next token to match the specified punctuator.
5674     // If not, an exception will be thrown.
5676     function expect(value) {
5677         var token = lex();
5678         if (token.type !== Token.Punctuator || token.value !== value) {
5679             throwUnexpected(token);
5680         }
5681     }
5683     // Expect the next token to match the specified keyword.
5684     // If not, an exception will be thrown.
5686     function expectKeyword(keyword) {
5687         var token = lex();
5688         if (token.type !== Token.Keyword || token.value !== keyword) {
5689             throwUnexpected(token);
5690         }
5691     }
5693     // Return true if the next token matches the specified punctuator.
5695     function match(value) {
5696         var token = lookahead();
5697         return token.type === Token.Punctuator && token.value === value;
5698     }
5700     // Return true if the next token matches the specified keyword
5702     function matchKeyword(keyword) {
5703         var token = lookahead();
5704         return token.type === Token.Keyword && token.value === keyword;
5705     }
5707     // Return true if the next token is an assignment operator
5709     function matchAssign() {
5710         var token = lookahead(),
5711             op = token.value;
5713         if (token.type !== Token.Punctuator) {
5714             return false;
5715         }
5716         return op === '=' ||
5717             op === '*=' ||
5718             op === '/=' ||
5719             op === '%=' ||
5720             op === '+=' ||
5721             op === '-=' ||
5722             op === '<<=' ||
5723             op === '>>=' ||
5724             op === '>>>=' ||
5725             op === '&=' ||
5726             op === '^=' ||
5727             op === '|=';
5728     }
5730     function consumeSemicolon() {
5731         var token, line;
5733         // Catch the very common case first.
5734         if (source[index] === ';') {
5735             lex();
5736             return;
5737         }
5739         line = lineNumber;
5740         skipComment();
5741         if (lineNumber !== line) {
5742             return;
5743         }
5745         if (match(';')) {
5746             lex();
5747             return;
5748         }
5750         token = lookahead();
5751         if (token.type !== Token.EOF && !match('}')) {
5752             throwUnexpected(token);
5753         }
5754     }
5756     // Return true if provided expression is LeftHandSideExpression
5758     function isLeftHandSide(expr) {
5759         return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
5760     }
5762     // 11.1.4 Array Initialiser
5764     function parseArrayInitialiser() {
5765         var elements = [];
5767         expect('[');
5769         while (!match(']')) {
5770             if (match(',')) {
5771                 lex();
5772                 elements.push(null);
5773             } else {
5774                 elements.push(parseAssignmentExpression());
5776                 if (!match(']')) {
5777                     expect(',');
5778                 }
5779             }
5780         }
5782         expect(']');
5784         return {
5785             type: Syntax.ArrayExpression,
5786             elements: elements
5787         };
5788     }
5790     // 11.1.5 Object Initialiser
5792     function parsePropertyFunction(param, first) {
5793         var previousStrict, body;
5795         previousStrict = strict;
5796         body = parseFunctionSourceElements();
5797         if (first && strict && isRestrictedWord(param[0].name)) {
5798             throwErrorTolerant(first, Messages.StrictParamName);
5799         }
5800         strict = previousStrict;
5802         return {
5803             type: Syntax.FunctionExpression,
5804             id: null,
5805             params: param,
5806             defaults: [],
5807             body: body,
5808             rest: null,
5809             generator: false,
5810             expression: false
5811         };
5812     }
5814     function parseObjectPropertyKey() {
5815         var token = lex();
5817         // Note: This function is called only from parseObjectProperty(), where
5818         // EOF and Punctuator tokens are already filtered out.
5820         if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
5821             if (strict && token.octal) {
5822                 throwErrorTolerant(token, Messages.StrictOctalLiteral);
5823             }
5824             return createLiteral(token);
5825         }
5827         return {
5828             type: Syntax.Identifier,
5829             name: token.value
5830         };
5831     }
5833     function parseObjectProperty() {
5834         var token, key, id, param;
5836         token = lookahead();
5838         if (token.type === Token.Identifier) {
5840             id = parseObjectPropertyKey();
5842             // Property Assignment: Getter and Setter.
5844             if (token.value === 'get' && !match(':')) {
5845                 key = parseObjectPropertyKey();
5846                 expect('(');
5847                 expect(')');
5848                 return {
5849                     type: Syntax.Property,
5850                     key: key,
5851                     value: parsePropertyFunction([]),
5852                     kind: 'get'
5853                 };
5854             } else if (token.value === 'set' && !match(':')) {
5855                 key = parseObjectPropertyKey();
5856                 expect('(');
5857                 token = lookahead();
5858                 if (token.type !== Token.Identifier) {
5859                     expect(')');
5860                     throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
5861                     return {
5862                         type: Syntax.Property,
5863                         key: key,
5864                         value: parsePropertyFunction([]),
5865                         kind: 'set'
5866                     };
5867                 } else {
5868                     param = [ parseVariableIdentifier() ];
5869                     expect(')');
5870                     return {
5871                         type: Syntax.Property,
5872                         key: key,
5873                         value: parsePropertyFunction(param, token),
5874                         kind: 'set'
5875                     };
5876                 }
5877             } else {
5878                 expect(':');
5879                 return {
5880                     type: Syntax.Property,
5881                     key: id,
5882                     value: parseAssignmentExpression(),
5883                     kind: 'init'
5884                 };
5885             }
5886         } else if (token.type === Token.EOF || token.type === Token.Punctuator) {
5887             throwUnexpected(token);
5888         } else {
5889             key = parseObjectPropertyKey();
5890             expect(':');
5891             return {
5892                 type: Syntax.Property,
5893                 key: key,
5894                 value: parseAssignmentExpression(),
5895                 kind: 'init'
5896             };
5897         }
5898     }
5900     function parseObjectInitialiser() {
5901         var properties = [], property, name, kind, map = {}, toString = String;
5903         expect('{');
5905         while (!match('}')) {
5906             property = parseObjectProperty();
5908             if (property.key.type === Syntax.Identifier) {
5909                 name = property.key.name;
5910             } else {
5911                 name = toString(property.key.value);
5912             }
5913             kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
5914             if (Object.prototype.hasOwnProperty.call(map, name)) {
5915                 if (map[name] === PropertyKind.Data) {
5916                     if (strict && kind === PropertyKind.Data) {
5917                         throwErrorTolerant({}, Messages.StrictDuplicateProperty);
5918                     } else if (kind !== PropertyKind.Data) {
5919                         throwErrorTolerant({}, Messages.AccessorDataProperty);
5920                     }
5921                 } else {
5922                     if (kind === PropertyKind.Data) {
5923                         throwErrorTolerant({}, Messages.AccessorDataProperty);
5924                     } else if (map[name] & kind) {
5925                         throwErrorTolerant({}, Messages.AccessorGetSet);
5926                     }
5927                 }
5928                 map[name] |= kind;
5929             } else {
5930                 map[name] = kind;
5931             }
5933             properties.push(property);
5935             if (!match('}')) {
5936                 expect(',');
5937             }
5938         }
5940         expect('}');
5942         return {
5943             type: Syntax.ObjectExpression,
5944             properties: properties
5945         };
5946     }
5948     // 11.1.6 The Grouping Operator
5950     function parseGroupExpression() {
5951         var expr;
5953         expect('(');
5955         expr = parseExpression();
5957         expect(')');
5959         return expr;
5960     }
5963     // 11.1 Primary Expressions
5965     function parsePrimaryExpression() {
5966         var token = lookahead(),
5967             type = token.type;
5969         if (type === Token.Identifier) {
5970             return {
5971                 type: Syntax.Identifier,
5972                 name: lex().value
5973             };
5974         }
5976         if (type === Token.StringLiteral || type === Token.NumericLiteral) {
5977             if (strict && token.octal) {
5978                 throwErrorTolerant(token, Messages.StrictOctalLiteral);
5979             }
5980             return createLiteral(lex());
5981         }
5983         if (type === Token.Keyword) {
5984             if (matchKeyword('this')) {
5985                 lex();
5986                 return {
5987                     type: Syntax.ThisExpression
5988                 };
5989             }
5991             if (matchKeyword('function')) {
5992                 return parseFunctionExpression();
5993             }
5994         }
5996         if (type === Token.BooleanLiteral) {
5997             lex();
5998             token.value = (token.value === 'true');
5999             return createLiteral(token);
6000         }
6002         if (type === Token.NullLiteral) {
6003             lex();
6004             token.value = null;
6005             return createLiteral(token);
6006         }
6008         if (match('[')) {
6009             return parseArrayInitialiser();
6010         }
6012         if (match('{')) {
6013             return parseObjectInitialiser();
6014         }
6016         if (match('(')) {
6017             return parseGroupExpression();
6018         }
6020         if (match('/') || match('/=')) {
6021             return createLiteral(scanRegExp());
6022         }
6024         return throwUnexpected(lex());
6025     }
6027     // 11.2 Left-Hand-Side Expressions
6029     function parseArguments() {
6030         var args = [];
6032         expect('(');
6034         if (!match(')')) {
6035             while (index < length) {
6036                 args.push(parseAssignmentExpression());
6037                 if (match(')')) {
6038                     break;
6039                 }
6040                 expect(',');
6041             }
6042         }
6044         expect(')');
6046         return args;
6047     }
6049     function parseNonComputedProperty() {
6050         var token = lex();
6052         if (!isIdentifierName(token)) {
6053             throwUnexpected(token);
6054         }
6056         return {
6057             type: Syntax.Identifier,
6058             name: token.value
6059         };
6060     }
6062     function parseNonComputedMember() {
6063         expect('.');
6065         return parseNonComputedProperty();
6066     }
6068     function parseComputedMember() {
6069         var expr;
6071         expect('[');
6073         expr = parseExpression();
6075         expect(']');
6077         return expr;
6078     }
6080     function parseNewExpression() {
6081         var expr;
6083         expectKeyword('new');
6085         expr = {
6086             type: Syntax.NewExpression,
6087             callee: parseLeftHandSideExpression(),
6088             'arguments': []
6089         };
6091         if (match('(')) {
6092             expr['arguments'] = parseArguments();
6093         }
6095         return expr;
6096     }
6098     function parseLeftHandSideExpressionAllowCall() {
6099         var expr;
6101         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
6103         while (match('.') || match('[') || match('(')) {
6104             if (match('(')) {
6105                 expr = {
6106                     type: Syntax.CallExpression,
6107                     callee: expr,
6108                     'arguments': parseArguments()
6109                 };
6110             } else if (match('[')) {
6111                 expr = {
6112                     type: Syntax.MemberExpression,
6113                     computed: true,
6114                     object: expr,
6115                     property: parseComputedMember()
6116                 };
6117             } else {
6118                 expr = {
6119                     type: Syntax.MemberExpression,
6120                     computed: false,
6121                     object: expr,
6122                     property: parseNonComputedMember()
6123                 };
6124             }
6125         }
6127         return expr;
6128     }
6131     function parseLeftHandSideExpression() {
6132         var expr;
6134         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
6136         while (match('.') || match('[')) {
6137             if (match('[')) {
6138                 expr = {
6139                     type: Syntax.MemberExpression,
6140                     computed: true,
6141                     object: expr,
6142                     property: parseComputedMember()
6143                 };
6144             } else {
6145                 expr = {
6146                     type: Syntax.MemberExpression,
6147                     computed: false,
6148                     object: expr,
6149                     property: parseNonComputedMember()
6150                 };
6151             }
6152         }
6154         return expr;
6155     }
6157     // 11.3 Postfix Expressions
6159     function parsePostfixExpression() {
6160         var expr = parseLeftHandSideExpressionAllowCall(), token;
6162         token = lookahead();
6163         if (token.type !== Token.Punctuator) {
6164             return expr;
6165         }
6167         if ((match('++') || match('--')) && !peekLineTerminator()) {
6168             // 11.3.1, 11.3.2
6169             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
6170                 throwErrorTolerant({}, Messages.StrictLHSPostfix);
6171             }
6173             if (!isLeftHandSide(expr)) {
6174                 throwError({}, Messages.InvalidLHSInAssignment);
6175             }
6177             expr = {
6178                 type: Syntax.UpdateExpression,
6179                 operator: lex().value,
6180                 argument: expr,
6181                 prefix: false
6182             };
6183         }
6185         return expr;
6186     }
6188     // 11.4 Unary Operators
6190     function parseUnaryExpression() {
6191         var token, expr;
6193         token = lookahead();
6194         if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
6195             return parsePostfixExpression();
6196         }
6198         if (match('++') || match('--')) {
6199             token = lex();
6200             expr = parseUnaryExpression();
6201             // 11.4.4, 11.4.5
6202             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
6203                 throwErrorTolerant({}, Messages.StrictLHSPrefix);
6204             }
6206             if (!isLeftHandSide(expr)) {
6207                 throwError({}, Messages.InvalidLHSInAssignment);
6208             }
6210             expr = {
6211                 type: Syntax.UpdateExpression,
6212                 operator: token.value,
6213                 argument: expr,
6214                 prefix: true
6215             };
6216             return expr;
6217         }
6219         if (match('+') || match('-') || match('~') || match('!')) {
6220             expr = {
6221                 type: Syntax.UnaryExpression,
6222                 operator: lex().value,
6223                 argument: parseUnaryExpression(),
6224                 prefix: true
6225             };
6226             return expr;
6227         }
6229         if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
6230             expr = {
6231                 type: Syntax.UnaryExpression,
6232                 operator: lex().value,
6233                 argument: parseUnaryExpression(),
6234                 prefix: true
6235             };
6236             if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
6237                 throwErrorTolerant({}, Messages.StrictDelete);
6238             }
6239             return expr;
6240         }
6242         return parsePostfixExpression();
6243     }
6245     // 11.5 Multiplicative Operators
6247     function parseMultiplicativeExpression() {
6248         var expr = parseUnaryExpression();
6250         while (match('*') || match('/') || match('%')) {
6251             expr = {
6252                 type: Syntax.BinaryExpression,
6253                 operator: lex().value,
6254                 left: expr,
6255                 right: parseUnaryExpression()
6256             };
6257         }
6259         return expr;
6260     }
6262     // 11.6 Additive Operators
6264     function parseAdditiveExpression() {
6265         var expr = parseMultiplicativeExpression();
6267         while (match('+') || match('-')) {
6268             expr = {
6269                 type: Syntax.BinaryExpression,
6270                 operator: lex().value,
6271                 left: expr,
6272                 right: parseMultiplicativeExpression()
6273             };
6274         }
6276         return expr;
6277     }
6279     // 11.7 Bitwise Shift Operators
6281     function parseShiftExpression() {
6282         var expr = parseAdditiveExpression();
6284         while (match('<<') || match('>>') || match('>>>')) {
6285             expr = {
6286                 type: Syntax.BinaryExpression,
6287                 operator: lex().value,
6288                 left: expr,
6289                 right: parseAdditiveExpression()
6290             };
6291         }
6293         return expr;
6294     }
6295     // 11.8 Relational Operators
6297     function parseRelationalExpression() {
6298         var expr, previousAllowIn;
6300         previousAllowIn = state.allowIn;
6301         state.allowIn = true;
6303         expr = parseShiftExpression();
6305         while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) {
6306             expr = {
6307                 type: Syntax.BinaryExpression,
6308                 operator: lex().value,
6309                 left: expr,
6310                 right: parseShiftExpression()
6311             };
6312         }
6314         state.allowIn = previousAllowIn;
6315         return expr;
6316     }
6318     // 11.9 Equality Operators
6320     function parseEqualityExpression() {
6321         var expr = parseRelationalExpression();
6323         while (match('==') || match('!=') || match('===') || match('!==')) {
6324             expr = {
6325                 type: Syntax.BinaryExpression,
6326                 operator: lex().value,
6327                 left: expr,
6328                 right: parseRelationalExpression()
6329             };
6330         }
6332         return expr;
6333     }
6335     // 11.10 Binary Bitwise Operators
6337     function parseBitwiseANDExpression() {
6338         var expr = parseEqualityExpression();
6340         while (match('&')) {
6341             lex();
6342             expr = {
6343                 type: Syntax.BinaryExpression,
6344                 operator: '&',
6345                 left: expr,
6346                 right: parseEqualityExpression()
6347             };
6348         }
6350         return expr;
6351     }
6353     function parseBitwiseXORExpression() {
6354         var expr = parseBitwiseANDExpression();
6356         while (match('^')) {
6357             lex();
6358             expr = {
6359                 type: Syntax.BinaryExpression,
6360                 operator: '^',
6361                 left: expr,
6362                 right: parseBitwiseANDExpression()
6363             };
6364         }
6366         return expr;
6367     }
6369     function parseBitwiseORExpression() {
6370         var expr = parseBitwiseXORExpression();
6372         while (match('|')) {
6373             lex();
6374             expr = {
6375                 type: Syntax.BinaryExpression,
6376                 operator: '|',
6377                 left: expr,
6378                 right: parseBitwiseXORExpression()
6379             };
6380         }
6382         return expr;
6383     }
6385     // 11.11 Binary Logical Operators
6387     function parseLogicalANDExpression() {
6388         var expr = parseBitwiseORExpression();
6390         while (match('&&')) {
6391             lex();
6392             expr = {
6393                 type: Syntax.LogicalExpression,
6394                 operator: '&&',
6395                 left: expr,
6396                 right: parseBitwiseORExpression()
6397             };
6398         }
6400         return expr;
6401     }
6403     function parseLogicalORExpression() {
6404         var expr = parseLogicalANDExpression();
6406         while (match('||')) {
6407             lex();
6408             expr = {
6409                 type: Syntax.LogicalExpression,
6410                 operator: '||',
6411                 left: expr,
6412                 right: parseLogicalANDExpression()
6413             };
6414         }
6416         return expr;
6417     }
6419     // 11.12 Conditional Operator
6421     function parseConditionalExpression() {
6422         var expr, previousAllowIn, consequent;
6424         expr = parseLogicalORExpression();
6426         if (match('?')) {
6427             lex();
6428             previousAllowIn = state.allowIn;
6429             state.allowIn = true;
6430             consequent = parseAssignmentExpression();
6431             state.allowIn = previousAllowIn;
6432             expect(':');
6434             expr = {
6435                 type: Syntax.ConditionalExpression,
6436                 test: expr,
6437                 consequent: consequent,
6438                 alternate: parseAssignmentExpression()
6439             };
6440         }
6442         return expr;
6443     }
6445     // 11.13 Assignment Operators
6447     function parseAssignmentExpression() {
6448         var token, expr;
6450         token = lookahead();
6451         expr = parseConditionalExpression();
6453         if (matchAssign()) {
6454             // LeftHandSideExpression
6455             if (!isLeftHandSide(expr)) {
6456                 throwError({}, Messages.InvalidLHSInAssignment);
6457             }
6459             // 11.13.1
6460             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
6461                 throwErrorTolerant(token, Messages.StrictLHSAssignment);
6462             }
6464             expr = {
6465                 type: Syntax.AssignmentExpression,
6466                 operator: lex().value,
6467                 left: expr,
6468                 right: parseAssignmentExpression()
6469             };
6470         }
6472         return expr;
6473     }
6475     // 11.14 Comma Operator
6477     function parseExpression() {
6478         var expr = parseAssignmentExpression();
6480         if (match(',')) {
6481             expr = {
6482                 type: Syntax.SequenceExpression,
6483                 expressions: [ expr ]
6484             };
6486             while (index < length) {
6487                 if (!match(',')) {
6488                     break;
6489                 }
6490                 lex();
6491                 expr.expressions.push(parseAssignmentExpression());
6492             }
6494         }
6495         return expr;
6496     }
6498     // 12.1 Block
6500     function parseStatementList() {
6501         var list = [],
6502             statement;
6504         while (index < length) {
6505             if (match('}')) {
6506                 break;
6507             }
6508             statement = parseSourceElement();
6509             if (typeof statement === 'undefined') {
6510                 break;
6511             }
6512             list.push(statement);
6513         }
6515         return list;
6516     }
6518     function parseBlock() {
6519         var block;
6521         expect('{');
6523         block = parseStatementList();
6525         expect('}');
6527         return {
6528             type: Syntax.BlockStatement,
6529             body: block
6530         };
6531     }
6533     // 12.2 Variable Statement
6535     function parseVariableIdentifier() {
6536         var token = lex();
6538         if (token.type !== Token.Identifier) {
6539             throwUnexpected(token);
6540         }
6542         return {
6543             type: Syntax.Identifier,
6544             name: token.value
6545         };
6546     }
6548     function parseVariableDeclaration(kind) {
6549         var id = parseVariableIdentifier(),
6550             init = null;
6552         // 12.2.1
6553         if (strict && isRestrictedWord(id.name)) {
6554             throwErrorTolerant({}, Messages.StrictVarName);
6555         }
6557         if (kind === 'const') {
6558             expect('=');
6559             init = parseAssignmentExpression();
6560         } else if (match('=')) {
6561             lex();
6562             init = parseAssignmentExpression();
6563         }
6565         return {
6566             type: Syntax.VariableDeclarator,
6567             id: id,
6568             init: init
6569         };
6570     }
6572     function parseVariableDeclarationList(kind) {
6573         var list = [];
6575         do {
6576             list.push(parseVariableDeclaration(kind));
6577             if (!match(',')) {
6578                 break;
6579             }
6580             lex();
6581         } while (index < length);
6583         return list;
6584     }
6586     function parseVariableStatement() {
6587         var declarations;
6589         expectKeyword('var');
6591         declarations = parseVariableDeclarationList();
6593         consumeSemicolon();
6595         return {
6596             type: Syntax.VariableDeclaration,
6597             declarations: declarations,
6598             kind: 'var'
6599         };
6600     }
6602     // kind may be `const` or `let`
6603     // Both are experimental and not in the specification yet.
6604     // see http://wiki.ecmascript.org/doku.php?id=harmony:const
6605     // and http://wiki.ecmascript.org/doku.php?id=harmony:let
6606     function parseConstLetDeclaration(kind) {
6607         var declarations;
6609         expectKeyword(kind);
6611         declarations = parseVariableDeclarationList(kind);
6613         consumeSemicolon();
6615         return {
6616             type: Syntax.VariableDeclaration,
6617             declarations: declarations,
6618             kind: kind
6619         };
6620     }
6622     // 12.3 Empty Statement
6624     function parseEmptyStatement() {
6625         expect(';');
6627         return {
6628             type: Syntax.EmptyStatement
6629         };
6630     }
6632     // 12.4 Expression Statement
6634     function parseExpressionStatement() {
6635         var expr = parseExpression();
6637         consumeSemicolon();
6639         return {
6640             type: Syntax.ExpressionStatement,
6641             expression: expr
6642         };
6643     }
6645     // 12.5 If statement
6647     function parseIfStatement() {
6648         var test, consequent, alternate;
6650         expectKeyword('if');
6652         expect('(');
6654         test = parseExpression();
6656         expect(')');
6658         consequent = parseStatement();
6660         if (matchKeyword('else')) {
6661             lex();
6662             alternate = parseStatement();
6663         } else {
6664             alternate = null;
6665         }
6667         return {
6668             type: Syntax.IfStatement,
6669             test: test,
6670             consequent: consequent,
6671             alternate: alternate
6672         };
6673     }
6675     // 12.6 Iteration Statements
6677     function parseDoWhileStatement() {
6678         var body, test, oldInIteration;
6680         expectKeyword('do');
6682         oldInIteration = state.inIteration;
6683         state.inIteration = true;
6685         body = parseStatement();
6687         state.inIteration = oldInIteration;
6689         expectKeyword('while');
6691         expect('(');
6693         test = parseExpression();
6695         expect(')');
6697         if (match(';')) {
6698             lex();
6699         }
6701         return {
6702             type: Syntax.DoWhileStatement,
6703             body: body,
6704             test: test
6705         };
6706     }
6708     function parseWhileStatement() {
6709         var test, body, oldInIteration;
6711         expectKeyword('while');
6713         expect('(');
6715         test = parseExpression();
6717         expect(')');
6719         oldInIteration = state.inIteration;
6720         state.inIteration = true;
6722         body = parseStatement();
6724         state.inIteration = oldInIteration;
6726         return {
6727             type: Syntax.WhileStatement,
6728             test: test,
6729             body: body
6730         };
6731     }
6733     function parseForVariableDeclaration() {
6734         var token = lex();
6736         return {
6737             type: Syntax.VariableDeclaration,
6738             declarations: parseVariableDeclarationList(),
6739             kind: token.value
6740         };
6741     }
6743     function parseForStatement() {
6744         var init, test, update, left, right, body, oldInIteration;
6746         init = test = update = null;
6748         expectKeyword('for');
6750         expect('(');
6752         if (match(';')) {
6753             lex();
6754         } else {
6755             if (matchKeyword('var') || matchKeyword('let')) {
6756                 state.allowIn = false;
6757                 init = parseForVariableDeclaration();
6758                 state.allowIn = true;
6760                 if (init.declarations.length === 1 && matchKeyword('in')) {
6761                     lex();
6762                     left = init;
6763                     right = parseExpression();
6764                     init = null;
6765                 }
6766             } else {
6767                 state.allowIn = false;
6768                 init = parseExpression();
6769                 state.allowIn = true;
6771                 if (matchKeyword('in')) {
6772                     // LeftHandSideExpression
6773                     if (!isLeftHandSide(init)) {
6774                         throwError({}, Messages.InvalidLHSInForIn);
6775                     }
6777                     lex();
6778                     left = init;
6779                     right = parseExpression();
6780                     init = null;
6781                 }
6782             }
6784             if (typeof left === 'undefined') {
6785                 expect(';');
6786             }
6787         }
6789         if (typeof left === 'undefined') {
6791             if (!match(';')) {
6792                 test = parseExpression();
6793             }
6794             expect(';');
6796             if (!match(')')) {
6797                 update = parseExpression();
6798             }
6799         }
6801         expect(')');
6803         oldInIteration = state.inIteration;
6804         state.inIteration = true;
6806         body = parseStatement();
6808         state.inIteration = oldInIteration;
6810         if (typeof left === 'undefined') {
6811             return {
6812                 type: Syntax.ForStatement,
6813                 init: init,
6814                 test: test,
6815                 update: update,
6816                 body: body
6817             };
6818         }
6820         return {
6821             type: Syntax.ForInStatement,
6822             left: left,
6823             right: right,
6824             body: body,
6825             each: false
6826         };
6827     }
6829     // 12.7 The continue statement
6831     function parseContinueStatement() {
6832         var token, label = null;
6834         expectKeyword('continue');
6836         // Optimize the most common form: 'continue;'.
6837         if (source[index] === ';') {
6838             lex();
6840             if (!state.inIteration) {
6841                 throwError({}, Messages.IllegalContinue);
6842             }
6844             return {
6845                 type: Syntax.ContinueStatement,
6846                 label: null
6847             };
6848         }
6850         if (peekLineTerminator()) {
6851             if (!state.inIteration) {
6852                 throwError({}, Messages.IllegalContinue);
6853             }
6855             return {
6856                 type: Syntax.ContinueStatement,
6857                 label: null
6858             };
6859         }
6861         token = lookahead();
6862         if (token.type === Token.Identifier) {
6863             label = parseVariableIdentifier();
6865             if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
6866                 throwError({}, Messages.UnknownLabel, label.name);
6867             }
6868         }
6870         consumeSemicolon();
6872         if (label === null && !state.inIteration) {
6873             throwError({}, Messages.IllegalContinue);
6874         }
6876         return {
6877             type: Syntax.ContinueStatement,
6878             label: label
6879         };
6880     }
6882     // 12.8 The break statement
6884     function parseBreakStatement() {
6885         var token, label = null;
6887         expectKeyword('break');
6889         // Optimize the most common form: 'break;'.
6890         if (source[index] === ';') {
6891             lex();
6893             if (!(state.inIteration || state.inSwitch)) {
6894                 throwError({}, Messages.IllegalBreak);
6895             }
6897             return {
6898                 type: Syntax.BreakStatement,
6899                 label: null
6900             };
6901         }
6903         if (peekLineTerminator()) {
6904             if (!(state.inIteration || state.inSwitch)) {
6905                 throwError({}, Messages.IllegalBreak);
6906             }
6908             return {
6909                 type: Syntax.BreakStatement,
6910                 label: null
6911             };
6912         }
6914         token = lookahead();
6915         if (token.type === Token.Identifier) {
6916             label = parseVariableIdentifier();
6918             if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
6919                 throwError({}, Messages.UnknownLabel, label.name);
6920             }
6921         }
6923         consumeSemicolon();
6925         if (label === null && !(state.inIteration || state.inSwitch)) {
6926             throwError({}, Messages.IllegalBreak);
6927         }
6929         return {
6930             type: Syntax.BreakStatement,
6931             label: label
6932         };
6933     }
6935     // 12.9 The return statement
6937     function parseReturnStatement() {
6938         var token, argument = null;
6940         expectKeyword('return');
6942         if (!state.inFunctionBody) {
6943             throwErrorTolerant({}, Messages.IllegalReturn);
6944         }
6946         // 'return' followed by a space and an identifier is very common.
6947         if (source[index] === ' ') {
6948             if (isIdentifierStart(source[index + 1])) {
6949                 argument = parseExpression();
6950                 consumeSemicolon();
6951                 return {
6952                     type: Syntax.ReturnStatement,
6953                     argument: argument
6954                 };
6955             }
6956         }
6958         if (peekLineTerminator()) {
6959             return {
6960                 type: Syntax.ReturnStatement,
6961                 argument: null
6962             };
6963         }
6965         if (!match(';')) {
6966             token = lookahead();
6967             if (!match('}') && token.type !== Token.EOF) {
6968                 argument = parseExpression();
6969             }
6970         }
6972         consumeSemicolon();
6974         return {
6975             type: Syntax.ReturnStatement,
6976             argument: argument
6977         };
6978     }
6980     // 12.10 The with statement
6982     function parseWithStatement() {
6983         var object, body;
6985         if (strict) {
6986             throwErrorTolerant({}, Messages.StrictModeWith);
6987         }
6989         expectKeyword('with');
6991         expect('(');
6993         object = parseExpression();
6995         expect(')');
6997         body = parseStatement();
6999         return {
7000             type: Syntax.WithStatement,
7001             object: object,
7002             body: body
7003         };
7004     }
7006     // 12.10 The swith statement
7008     function parseSwitchCase() {
7009         var test,
7010             consequent = [],
7011             statement;
7013         if (matchKeyword('default')) {
7014             lex();
7015             test = null;
7016         } else {
7017             expectKeyword('case');
7018             test = parseExpression();
7019         }
7020         expect(':');
7022         while (index < length) {
7023             if (match('}') || matchKeyword('default') || matchKeyword('case')) {
7024                 break;
7025             }
7026             statement = parseStatement();
7027             if (typeof statement === 'undefined') {
7028                 break;
7029             }
7030             consequent.push(statement);
7031         }
7033         return {
7034             type: Syntax.SwitchCase,
7035             test: test,
7036             consequent: consequent
7037         };
7038     }
7040     function parseSwitchStatement() {
7041         var discriminant, cases, clause, oldInSwitch, defaultFound;
7043         expectKeyword('switch');
7045         expect('(');
7047         discriminant = parseExpression();
7049         expect(')');
7051         expect('{');
7053         if (match('}')) {
7054             lex();
7055             return {
7056                 type: Syntax.SwitchStatement,
7057                 discriminant: discriminant
7058             };
7059         }
7061         cases = [];
7063         oldInSwitch = state.inSwitch;
7064         state.inSwitch = true;
7065         defaultFound = false;
7067         while (index < length) {
7068             if (match('}')) {
7069                 break;
7070             }
7071             clause = parseSwitchCase();
7072             if (clause.test === null) {
7073                 if (defaultFound) {
7074                     throwError({}, Messages.MultipleDefaultsInSwitch);
7075                 }
7076                 defaultFound = true;
7077             }
7078             cases.push(clause);
7079         }
7081         state.inSwitch = oldInSwitch;
7083         expect('}');
7085         return {
7086             type: Syntax.SwitchStatement,
7087             discriminant: discriminant,
7088             cases: cases
7089         };
7090     }
7092     // 12.13 The throw statement
7094     function parseThrowStatement() {
7095         var argument;
7097         expectKeyword('throw');
7099         if (peekLineTerminator()) {
7100             throwError({}, Messages.NewlineAfterThrow);
7101         }
7103         argument = parseExpression();
7105         consumeSemicolon();
7107         return {
7108             type: Syntax.ThrowStatement,
7109             argument: argument
7110         };
7111     }
7113     // 12.14 The try statement
7115     function parseCatchClause() {
7116         var param;
7118         expectKeyword('catch');
7120         expect('(');
7121         if (match(')')) {
7122             throwUnexpected(lookahead());
7123         }
7125         param = parseVariableIdentifier();
7126         // 12.14.1
7127         if (strict && isRestrictedWord(param.name)) {
7128             throwErrorTolerant({}, Messages.StrictCatchVariable);
7129         }
7131         expect(')');
7133         return {
7134             type: Syntax.CatchClause,
7135             param: param,
7136             body: parseBlock()
7137         };
7138     }
7140     function parseTryStatement() {
7141         var block, handlers = [], finalizer = null;
7143         expectKeyword('try');
7145         block = parseBlock();
7147         if (matchKeyword('catch')) {
7148             handlers.push(parseCatchClause());
7149         }
7151         if (matchKeyword('finally')) {
7152             lex();
7153             finalizer = parseBlock();
7154         }
7156         if (handlers.length === 0 && !finalizer) {
7157             throwError({}, Messages.NoCatchOrFinally);
7158         }
7160         return {
7161             type: Syntax.TryStatement,
7162             block: block,
7163             guardedHandlers: [],
7164             handlers: handlers,
7165             finalizer: finalizer
7166         };
7167     }
7169     // 12.15 The debugger statement
7171     function parseDebuggerStatement() {
7172         expectKeyword('debugger');
7174         consumeSemicolon();
7176         return {
7177             type: Syntax.DebuggerStatement
7178         };
7179     }
7181     // 12 Statements
7183     function parseStatement() {
7184         var token = lookahead(),
7185             expr,
7186             labeledBody;
7188         if (token.type === Token.EOF) {
7189             throwUnexpected(token);
7190         }
7192         if (token.type === Token.Punctuator) {
7193             switch (token.value) {
7194             case ';':
7195                 return parseEmptyStatement();
7196             case '{':
7197                 return parseBlock();
7198             case '(':
7199                 return parseExpressionStatement();
7200             default:
7201                 break;
7202             }
7203         }
7205         if (token.type === Token.Keyword) {
7206             switch (token.value) {
7207             case 'break':
7208                 return parseBreakStatement();
7209             case 'continue':
7210                 return parseContinueStatement();
7211             case 'debugger':
7212                 return parseDebuggerStatement();
7213             case 'do':
7214                 return parseDoWhileStatement();
7215             case 'for':
7216                 return parseForStatement();
7217             case 'function':
7218                 return parseFunctionDeclaration();
7219             case 'if':
7220                 return parseIfStatement();
7221             case 'return':
7222                 return parseReturnStatement();
7223             case 'switch':
7224                 return parseSwitchStatement();
7225             case 'throw':
7226                 return parseThrowStatement();
7227             case 'try':
7228                 return parseTryStatement();
7229             case 'var':
7230                 return parseVariableStatement();
7231             case 'while':
7232                 return parseWhileStatement();
7233             case 'with':
7234                 return parseWithStatement();
7235             default:
7236                 break;
7237             }
7238         }
7240         expr = parseExpression();
7242         // 12.12 Labelled Statements
7243         if ((expr.type === Syntax.Identifier) && match(':')) {
7244             lex();
7246             if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) {
7247                 throwError({}, Messages.Redeclaration, 'Label', expr.name);
7248             }
7250             state.labelSet[expr.name] = true;
7251             labeledBody = parseStatement();
7252             delete state.labelSet[expr.name];
7254             return {
7255                 type: Syntax.LabeledStatement,
7256                 label: expr,
7257                 body: labeledBody
7258             };
7259         }
7261         consumeSemicolon();
7263         return {
7264             type: Syntax.ExpressionStatement,
7265             expression: expr
7266         };
7267     }
7269     // 13 Function Definition
7271     function parseFunctionSourceElements() {
7272         var sourceElement, sourceElements = [], token, directive, firstRestricted,
7273             oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody;
7275         expect('{');
7277         while (index < length) {
7278             token = lookahead();
7279             if (token.type !== Token.StringLiteral) {
7280                 break;
7281             }
7283             sourceElement = parseSourceElement();
7284             sourceElements.push(sourceElement);
7285             if (sourceElement.expression.type !== Syntax.Literal) {
7286                 // this is not directive
7287                 break;
7288             }
7289             directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
7290             if (directive === 'use strict') {
7291                 strict = true;
7292                 if (firstRestricted) {
7293                     throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
7294                 }
7295             } else {
7296                 if (!firstRestricted && token.octal) {
7297                     firstRestricted = token;
7298                 }
7299             }
7300         }
7302         oldLabelSet = state.labelSet;
7303         oldInIteration = state.inIteration;
7304         oldInSwitch = state.inSwitch;
7305         oldInFunctionBody = state.inFunctionBody;
7307         state.labelSet = {};
7308         state.inIteration = false;
7309         state.inSwitch = false;
7310         state.inFunctionBody = true;
7312         while (index < length) {
7313             if (match('}')) {
7314                 break;
7315             }
7316             sourceElement = parseSourceElement();
7317             if (typeof sourceElement === 'undefined') {
7318                 break;
7319             }
7320             sourceElements.push(sourceElement);
7321         }
7323         expect('}');
7325         state.labelSet = oldLabelSet;
7326         state.inIteration = oldInIteration;
7327         state.inSwitch = oldInSwitch;
7328         state.inFunctionBody = oldInFunctionBody;
7330         return {
7331             type: Syntax.BlockStatement,
7332             body: sourceElements
7333         };
7334     }
7336     function parseFunctionDeclaration() {
7337         var id, param, params = [], body, token, stricted, firstRestricted, message, previousStrict, paramSet;
7339         expectKeyword('function');
7340         token = lookahead();
7341         id = parseVariableIdentifier();
7342         if (strict) {
7343             if (isRestrictedWord(token.value)) {
7344                 throwErrorTolerant(token, Messages.StrictFunctionName);
7345             }
7346         } else {
7347             if (isRestrictedWord(token.value)) {
7348                 firstRestricted = token;
7349                 message = Messages.StrictFunctionName;
7350             } else if (isStrictModeReservedWord(token.value)) {
7351                 firstRestricted = token;
7352                 message = Messages.StrictReservedWord;
7353             }
7354         }
7356         expect('(');
7358         if (!match(')')) {
7359             paramSet = {};
7360             while (index < length) {
7361                 token = lookahead();
7362                 param = parseVariableIdentifier();
7363                 if (strict) {
7364                     if (isRestrictedWord(token.value)) {
7365                         stricted = token;
7366                         message = Messages.StrictParamName;
7367                     }
7368                     if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
7369                         stricted = token;
7370                         message = Messages.StrictParamDupe;
7371                     }
7372                 } else if (!firstRestricted) {
7373                     if (isRestrictedWord(token.value)) {
7374                         firstRestricted = token;
7375                         message = Messages.StrictParamName;
7376                     } else if (isStrictModeReservedWord(token.value)) {
7377                         firstRestricted = token;
7378                         message = Messages.StrictReservedWord;
7379                     } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
7380                         firstRestricted = token;
7381                         message = Messages.StrictParamDupe;
7382                     }
7383                 }
7384                 params.push(param);
7385                 paramSet[param.name] = true;
7386                 if (match(')')) {
7387                     break;
7388                 }
7389                 expect(',');
7390             }
7391         }
7393         expect(')');
7395         previousStrict = strict;
7396         body = parseFunctionSourceElements();
7397         if (strict && firstRestricted) {
7398             throwError(firstRestricted, message);
7399         }
7400         if (strict && stricted) {
7401             throwErrorTolerant(stricted, message);
7402         }
7403         strict = previousStrict;
7405         return {
7406             type: Syntax.FunctionDeclaration,
7407             id: id,
7408             params: params,
7409             defaults: [],
7410             body: body,
7411             rest: null,
7412             generator: false,
7413             expression: false
7414         };
7415     }
7417     function parseFunctionExpression() {
7418         var token, id = null, stricted, firstRestricted, message, param, params = [], body, previousStrict, paramSet;
7420         expectKeyword('function');
7422         if (!match('(')) {
7423             token = lookahead();
7424             id = parseVariableIdentifier();
7425             if (strict) {
7426                 if (isRestrictedWord(token.value)) {
7427                     throwErrorTolerant(token, Messages.StrictFunctionName);
7428                 }
7429             } else {
7430                 if (isRestrictedWord(token.value)) {
7431                     firstRestricted = token;
7432                     message = Messages.StrictFunctionName;
7433                 } else if (isStrictModeReservedWord(token.value)) {
7434                     firstRestricted = token;
7435                     message = Messages.StrictReservedWord;
7436                 }
7437             }
7438         }
7440         expect('(');
7442         if (!match(')')) {
7443             paramSet = {};
7444             while (index < length) {
7445                 token = lookahead();
7446                 param = parseVariableIdentifier();
7447                 if (strict) {
7448                     if (isRestrictedWord(token.value)) {
7449                         stricted = token;
7450                         message = Messages.StrictParamName;
7451                     }
7452                     if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
7453                         stricted = token;
7454                         message = Messages.StrictParamDupe;
7455                     }
7456                 } else if (!firstRestricted) {
7457                     if (isRestrictedWord(token.value)) {
7458                         firstRestricted = token;
7459                         message = Messages.StrictParamName;
7460                     } else if (isStrictModeReservedWord(token.value)) {
7461                         firstRestricted = token;
7462                         message = Messages.StrictReservedWord;
7463                     } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
7464                         firstRestricted = token;
7465                         message = Messages.StrictParamDupe;
7466                     }
7467                 }
7468                 params.push(param);
7469                 paramSet[param.name] = true;
7470                 if (match(')')) {
7471                     break;
7472                 }
7473                 expect(',');
7474             }
7475         }
7477         expect(')');
7479         previousStrict = strict;
7480         body = parseFunctionSourceElements();
7481         if (strict && firstRestricted) {
7482             throwError(firstRestricted, message);
7483         }
7484         if (strict && stricted) {
7485             throwErrorTolerant(stricted, message);
7486         }
7487         strict = previousStrict;
7489         return {
7490             type: Syntax.FunctionExpression,
7491             id: id,
7492             params: params,
7493             defaults: [],
7494             body: body,
7495             rest: null,
7496             generator: false,
7497             expression: false
7498         };
7499     }
7501     // 14 Program
7503     function parseSourceElement() {
7504         var token = lookahead();
7506         if (token.type === Token.Keyword) {
7507             switch (token.value) {
7508             case 'const':
7509             case 'let':
7510                 return parseConstLetDeclaration(token.value);
7511             case 'function':
7512                 return parseFunctionDeclaration();
7513             default:
7514                 return parseStatement();
7515             }
7516         }
7518         if (token.type !== Token.EOF) {
7519             return parseStatement();
7520         }
7521     }
7523     function parseSourceElements() {
7524         var sourceElement, sourceElements = [], token, directive, firstRestricted;
7526         while (index < length) {
7527             token = lookahead();
7528             if (token.type !== Token.StringLiteral) {
7529                 break;
7530             }
7532             sourceElement = parseSourceElement();
7533             sourceElements.push(sourceElement);
7534             if (sourceElement.expression.type !== Syntax.Literal) {
7535                 // this is not directive
7536                 break;
7537             }
7538             directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
7539             if (directive === 'use strict') {
7540                 strict = true;
7541                 if (firstRestricted) {
7542                     throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
7543                 }
7544             } else {
7545                 if (!firstRestricted && token.octal) {
7546                     firstRestricted = token;
7547                 }
7548             }
7549         }
7551         while (index < length) {
7552             sourceElement = parseSourceElement();
7553             if (typeof sourceElement === 'undefined') {
7554                 break;
7555             }
7556             sourceElements.push(sourceElement);
7557         }
7558         return sourceElements;
7559     }
7561     function parseProgram() {
7562         var program;
7563         strict = false;
7564         program = {
7565             type: Syntax.Program,
7566             body: parseSourceElements()
7567         };
7568         return program;
7569     }
7571     // The following functions are needed only when the option to preserve
7572     // the comments is active.
7574     function addComment(type, value, start, end, loc) {
7575         assert(typeof start === 'number', 'Comment must have valid position');
7577         // Because the way the actual token is scanned, often the comments
7578         // (if any) are skipped twice during the lexical analysis.
7579         // Thus, we need to skip adding a comment if the comment array already
7580         // handled it.
7581         if (extra.comments.length > 0) {
7582             if (extra.comments[extra.comments.length - 1].range[1] > start) {
7583                 return;
7584             }
7585         }
7587         extra.comments.push({
7588             type: type,
7589             value: value,
7590             range: [start, end],
7591             loc: loc
7592         });
7593     }
7595     function scanComment() {
7596         var comment, ch, loc, start, blockComment, lineComment;
7598         comment = '';
7599         blockComment = false;
7600         lineComment = false;
7602         while (index < length) {
7603             ch = source[index];
7605             if (lineComment) {
7606                 ch = source[index++];
7607                 if (isLineTerminator(ch)) {
7608                     loc.end = {
7609                         line: lineNumber,
7610                         column: index - lineStart - 1
7611                     };
7612                     lineComment = false;
7613                     addComment('Line', comment, start, index - 1, loc);
7614                     if (ch === '\r' && source[index] === '\n') {
7615                         ++index;
7616                     }
7617                     ++lineNumber;
7618                     lineStart = index;
7619                     comment = '';
7620                 } else if (index >= length) {
7621                     lineComment = false;
7622                     comment += ch;
7623                     loc.end = {
7624                         line: lineNumber,
7625                         column: length - lineStart
7626                     };
7627                     addComment('Line', comment, start, length, loc);
7628                 } else {
7629                     comment += ch;
7630                 }
7631             } else if (blockComment) {
7632                 if (isLineTerminator(ch)) {
7633                     if (ch === '\r' && source[index + 1] === '\n') {
7634                         ++index;
7635                         comment += '\r\n';
7636                     } else {
7637                         comment += ch;
7638                     }
7639                     ++lineNumber;
7640                     ++index;
7641                     lineStart = index;
7642                     if (index >= length) {
7643                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
7644                     }
7645                 } else {
7646                     ch = source[index++];
7647                     if (index >= length) {
7648                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
7649                     }
7650                     comment += ch;
7651                     if (ch === '*') {
7652                         ch = source[index];
7653                         if (ch === '/') {
7654                             comment = comment.substr(0, comment.length - 1);
7655                             blockComment = false;
7656                             ++index;
7657                             loc.end = {
7658                                 line: lineNumber,
7659                                 column: index - lineStart
7660                             };
7661                             addComment('Block', comment, start, index, loc);
7662                             comment = '';
7663                         }
7664                     }
7665                 }
7666             } else if (ch === '/') {
7667                 ch = source[index + 1];
7668                 if (ch === '/') {
7669                     loc = {
7670                         start: {
7671                             line: lineNumber,
7672                             column: index - lineStart
7673                         }
7674                     };
7675                     start = index;
7676                     index += 2;
7677                     lineComment = true;
7678                     if (index >= length) {
7679                         loc.end = {
7680                             line: lineNumber,
7681                             column: index - lineStart
7682                         };
7683                         lineComment = false;
7684                         addComment('Line', comment, start, index, loc);
7685                     }
7686                 } else if (ch === '*') {
7687                     start = index;
7688                     index += 2;
7689                     blockComment = true;
7690                     loc = {
7691                         start: {
7692                             line: lineNumber,
7693                             column: index - lineStart - 2
7694                         }
7695                     };
7696                     if (index >= length) {
7697                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
7698                     }
7699                 } else {
7700                     break;
7701                 }
7702             } else if (isWhiteSpace(ch)) {
7703                 ++index;
7704             } else if (isLineTerminator(ch)) {
7705                 ++index;
7706                 if (ch ===  '\r' && source[index] === '\n') {
7707                     ++index;
7708                 }
7709                 ++lineNumber;
7710                 lineStart = index;
7711             } else {
7712                 break;
7713             }
7714         }
7715     }
7717     function filterCommentLocation() {
7718         var i, entry, comment, comments = [];
7720         for (i = 0; i < extra.comments.length; ++i) {
7721             entry = extra.comments[i];
7722             comment = {
7723                 type: entry.type,
7724                 value: entry.value
7725             };
7726             if (extra.range) {
7727                 comment.range = entry.range;
7728             }
7729             if (extra.loc) {
7730                 comment.loc = entry.loc;
7731             }
7732             comments.push(comment);
7733         }
7735         extra.comments = comments;
7736     }
7738     function collectToken() {
7739         var start, loc, token, range, value;
7741         skipComment();
7742         start = index;
7743         loc = {
7744             start: {
7745                 line: lineNumber,
7746                 column: index - lineStart
7747             }
7748         };
7750         token = extra.advance();
7751         loc.end = {
7752             line: lineNumber,
7753             column: index - lineStart
7754         };
7756         if (token.type !== Token.EOF) {
7757             range = [token.range[0], token.range[1]];
7758             value = sliceSource(token.range[0], token.range[1]);
7759             extra.tokens.push({
7760                 type: TokenName[token.type],
7761                 value: value,
7762                 range: range,
7763                 loc: loc
7764             });
7765         }
7767         return token;
7768     }
7770     function collectRegex() {
7771         var pos, loc, regex, token;
7773         skipComment();
7775         pos = index;
7776         loc = {
7777             start: {
7778                 line: lineNumber,
7779                 column: index - lineStart
7780             }
7781         };
7783         regex = extra.scanRegExp();
7784         loc.end = {
7785             line: lineNumber,
7786             column: index - lineStart
7787         };
7789         // Pop the previous token, which is likely '/' or '/='
7790         if (extra.tokens.length > 0) {
7791             token = extra.tokens[extra.tokens.length - 1];
7792             if (token.range[0] === pos && token.type === 'Punctuator') {
7793                 if (token.value === '/' || token.value === '/=') {
7794                     extra.tokens.pop();
7795                 }
7796             }
7797         }
7799         extra.tokens.push({
7800             type: 'RegularExpression',
7801             value: regex.literal,
7802             range: [pos, index],
7803             loc: loc
7804         });
7806         return regex;
7807     }
7809     function filterTokenLocation() {
7810         var i, entry, token, tokens = [];
7812         for (i = 0; i < extra.tokens.length; ++i) {
7813             entry = extra.tokens[i];
7814             token = {
7815                 type: entry.type,
7816                 value: entry.value
7817             };
7818             if (extra.range) {
7819                 token.range = entry.range;
7820             }
7821             if (extra.loc) {
7822                 token.loc = entry.loc;
7823             }
7824             tokens.push(token);
7825         }
7827         extra.tokens = tokens;
7828     }
7830     function createLiteral(token) {
7831         return {
7832             type: Syntax.Literal,
7833             value: token.value
7834         };
7835     }
7837     function createRawLiteral(token) {
7838         return {
7839             type: Syntax.Literal,
7840             value: token.value,
7841             raw: sliceSource(token.range[0], token.range[1])
7842         };
7843     }
7845     function createLocationMarker() {
7846         var marker = {};
7848         marker.range = [index, index];
7849         marker.loc = {
7850             start: {
7851                 line: lineNumber,
7852                 column: index - lineStart
7853             },
7854             end: {
7855                 line: lineNumber,
7856                 column: index - lineStart
7857             }
7858         };
7860         marker.end = function () {
7861             this.range[1] = index;
7862             this.loc.end.line = lineNumber;
7863             this.loc.end.column = index - lineStart;
7864         };
7866         marker.applyGroup = function (node) {
7867             if (extra.range) {
7868                 node.groupRange = [this.range[0], this.range[1]];
7869             }
7870             if (extra.loc) {
7871                 node.groupLoc = {
7872                     start: {
7873                         line: this.loc.start.line,
7874                         column: this.loc.start.column
7875                     },
7876                     end: {
7877                         line: this.loc.end.line,
7878                         column: this.loc.end.column
7879                     }
7880                 };
7881             }
7882         };
7884         marker.apply = function (node) {
7885             if (extra.range) {
7886                 node.range = [this.range[0], this.range[1]];
7887             }
7888             if (extra.loc) {
7889                 node.loc = {
7890                     start: {
7891                         line: this.loc.start.line,
7892                         column: this.loc.start.column
7893                     },
7894                     end: {
7895                         line: this.loc.end.line,
7896                         column: this.loc.end.column
7897                     }
7898                 };
7899             }
7900         };
7902         return marker;
7903     }
7905     function trackGroupExpression() {
7906         var marker, expr;
7908         skipComment();
7909         marker = createLocationMarker();
7910         expect('(');
7912         expr = parseExpression();
7914         expect(')');
7916         marker.end();
7917         marker.applyGroup(expr);
7919         return expr;
7920     }
7922     function trackLeftHandSideExpression() {
7923         var marker, expr;
7925         skipComment();
7926         marker = createLocationMarker();
7928         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
7930         while (match('.') || match('[')) {
7931             if (match('[')) {
7932                 expr = {
7933                     type: Syntax.MemberExpression,
7934                     computed: true,
7935                     object: expr,
7936                     property: parseComputedMember()
7937                 };
7938                 marker.end();
7939                 marker.apply(expr);
7940             } else {
7941                 expr = {
7942                     type: Syntax.MemberExpression,
7943                     computed: false,
7944                     object: expr,
7945                     property: parseNonComputedMember()
7946                 };
7947                 marker.end();
7948                 marker.apply(expr);
7949             }
7950         }
7952         return expr;
7953     }
7955     function trackLeftHandSideExpressionAllowCall() {
7956         var marker, expr;
7958         skipComment();
7959         marker = createLocationMarker();
7961         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
7963         while (match('.') || match('[') || match('(')) {
7964             if (match('(')) {
7965                 expr = {
7966                     type: Syntax.CallExpression,
7967                     callee: expr,
7968                     'arguments': parseArguments()
7969                 };
7970                 marker.end();
7971                 marker.apply(expr);
7972             } else if (match('[')) {
7973                 expr = {
7974                     type: Syntax.MemberExpression,
7975                     computed: true,
7976                     object: expr,
7977                     property: parseComputedMember()
7978                 };
7979                 marker.end();
7980                 marker.apply(expr);
7981             } else {
7982                 expr = {
7983                     type: Syntax.MemberExpression,
7984                     computed: false,
7985                     object: expr,
7986                     property: parseNonComputedMember()
7987                 };
7988                 marker.end();
7989                 marker.apply(expr);
7990             }
7991         }
7993         return expr;
7994     }
7996     function filterGroup(node) {
7997         var n, i, entry;
7999         n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {};
8000         for (i in node) {
8001             if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') {
8002                 entry = node[i];
8003                 if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) {
8004                     n[i] = entry;
8005                 } else {
8006                     n[i] = filterGroup(entry);
8007                 }
8008             }
8009         }
8010         return n;
8011     }
8013     function wrapTrackingFunction(range, loc) {
8015         return function (parseFunction) {
8017             function isBinary(node) {
8018                 return node.type === Syntax.LogicalExpression ||
8019                     node.type === Syntax.BinaryExpression;
8020             }
8022             function visit(node) {
8023                 var start, end;
8025                 if (isBinary(node.left)) {
8026                     visit(node.left);
8027                 }
8028                 if (isBinary(node.right)) {
8029                     visit(node.right);
8030                 }
8032                 if (range) {
8033                     if (node.left.groupRange || node.right.groupRange) {
8034                         start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0];
8035                         end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1];
8036                         node.range = [start, end];
8037                     } else if (typeof node.range === 'undefined') {
8038                         start = node.left.range[0];
8039                         end = node.right.range[1];
8040                         node.range = [start, end];
8041                     }
8042                 }
8043                 if (loc) {
8044                     if (node.left.groupLoc || node.right.groupLoc) {
8045                         start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start;
8046                         end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end;
8047                         node.loc = {
8048                             start: start,
8049                             end: end
8050                         };
8051                     } else if (typeof node.loc === 'undefined') {
8052                         node.loc = {
8053                             start: node.left.loc.start,
8054                             end: node.right.loc.end
8055                         };
8056                     }
8057                 }
8058             }
8060             return function () {
8061                 var marker, node;
8063                 skipComment();
8065                 marker = createLocationMarker();
8066                 node = parseFunction.apply(null, arguments);
8067                 marker.end();
8069                 if (range && typeof node.range === 'undefined') {
8070                     marker.apply(node);
8071                 }
8073                 if (loc && typeof node.loc === 'undefined') {
8074                     marker.apply(node);
8075                 }
8077                 if (isBinary(node)) {
8078                     visit(node);
8079                 }
8081                 return node;
8082             };
8083         };
8084     }
8086     function patch() {
8088         var wrapTracking;
8090         if (extra.comments) {
8091             extra.skipComment = skipComment;
8092             skipComment = scanComment;
8093         }
8095         if (extra.raw) {
8096             extra.createLiteral = createLiteral;
8097             createLiteral = createRawLiteral;
8098         }
8100         if (extra.range || extra.loc) {
8102             extra.parseGroupExpression = parseGroupExpression;
8103             extra.parseLeftHandSideExpression = parseLeftHandSideExpression;
8104             extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;
8105             parseGroupExpression = trackGroupExpression;
8106             parseLeftHandSideExpression = trackLeftHandSideExpression;
8107             parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall;
8109             wrapTracking = wrapTrackingFunction(extra.range, extra.loc);
8111             extra.parseAdditiveExpression = parseAdditiveExpression;
8112             extra.parseAssignmentExpression = parseAssignmentExpression;
8113             extra.parseBitwiseANDExpression = parseBitwiseANDExpression;
8114             extra.parseBitwiseORExpression = parseBitwiseORExpression;
8115             extra.parseBitwiseXORExpression = parseBitwiseXORExpression;
8116             extra.parseBlock = parseBlock;
8117             extra.parseFunctionSourceElements = parseFunctionSourceElements;
8118             extra.parseCatchClause = parseCatchClause;
8119             extra.parseComputedMember = parseComputedMember;
8120             extra.parseConditionalExpression = parseConditionalExpression;
8121             extra.parseConstLetDeclaration = parseConstLetDeclaration;
8122             extra.parseEqualityExpression = parseEqualityExpression;
8123             extra.parseExpression = parseExpression;
8124             extra.parseForVariableDeclaration = parseForVariableDeclaration;
8125             extra.parseFunctionDeclaration = parseFunctionDeclaration;
8126             extra.parseFunctionExpression = parseFunctionExpression;
8127             extra.parseLogicalANDExpression = parseLogicalANDExpression;
8128             extra.parseLogicalORExpression = parseLogicalORExpression;
8129             extra.parseMultiplicativeExpression = parseMultiplicativeExpression;
8130             extra.parseNewExpression = parseNewExpression;
8131             extra.parseNonComputedProperty = parseNonComputedProperty;
8132             extra.parseObjectProperty = parseObjectProperty;
8133             extra.parseObjectPropertyKey = parseObjectPropertyKey;
8134             extra.parsePostfixExpression = parsePostfixExpression;
8135             extra.parsePrimaryExpression = parsePrimaryExpression;
8136             extra.parseProgram = parseProgram;
8137             extra.parsePropertyFunction = parsePropertyFunction;
8138             extra.parseRelationalExpression = parseRelationalExpression;
8139             extra.parseStatement = parseStatement;
8140             extra.parseShiftExpression = parseShiftExpression;
8141             extra.parseSwitchCase = parseSwitchCase;
8142             extra.parseUnaryExpression = parseUnaryExpression;
8143             extra.parseVariableDeclaration = parseVariableDeclaration;
8144             extra.parseVariableIdentifier = parseVariableIdentifier;
8146             parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression);
8147             parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);
8148             parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression);
8149             parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression);
8150             parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression);
8151             parseBlock = wrapTracking(extra.parseBlock);
8152             parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
8153             parseCatchClause = wrapTracking(extra.parseCatchClause);
8154             parseComputedMember = wrapTracking(extra.parseComputedMember);
8155             parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
8156             parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);
8157             parseEqualityExpression = wrapTracking(extra.parseEqualityExpression);
8158             parseExpression = wrapTracking(extra.parseExpression);
8159             parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
8160             parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
8161             parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
8162             parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression);
8163             parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression);
8164             parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression);
8165             parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression);
8166             parseNewExpression = wrapTracking(extra.parseNewExpression);
8167             parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
8168             parseObjectProperty = wrapTracking(extra.parseObjectProperty);
8169             parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
8170             parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);
8171             parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);
8172             parseProgram = wrapTracking(extra.parseProgram);
8173             parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);
8174             parseRelationalExpression = wrapTracking(extra.parseRelationalExpression);
8175             parseStatement = wrapTracking(extra.parseStatement);
8176             parseShiftExpression = wrapTracking(extra.parseShiftExpression);
8177             parseSwitchCase = wrapTracking(extra.parseSwitchCase);
8178             parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);
8179             parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);
8180             parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);
8181         }
8183         if (typeof extra.tokens !== 'undefined') {
8184             extra.advance = advance;
8185             extra.scanRegExp = scanRegExp;
8187             advance = collectToken;
8188             scanRegExp = collectRegex;
8189         }
8190     }
8192     function unpatch() {
8193         if (typeof extra.skipComment === 'function') {
8194             skipComment = extra.skipComment;
8195         }
8197         if (extra.raw) {
8198             createLiteral = extra.createLiteral;
8199         }
8201         if (extra.range || extra.loc) {
8202             parseAdditiveExpression = extra.parseAdditiveExpression;
8203             parseAssignmentExpression = extra.parseAssignmentExpression;
8204             parseBitwiseANDExpression = extra.parseBitwiseANDExpression;
8205             parseBitwiseORExpression = extra.parseBitwiseORExpression;
8206             parseBitwiseXORExpression = extra.parseBitwiseXORExpression;
8207             parseBlock = extra.parseBlock;
8208             parseFunctionSourceElements = extra.parseFunctionSourceElements;
8209             parseCatchClause = extra.parseCatchClause;
8210             parseComputedMember = extra.parseComputedMember;
8211             parseConditionalExpression = extra.parseConditionalExpression;
8212             parseConstLetDeclaration = extra.parseConstLetDeclaration;
8213             parseEqualityExpression = extra.parseEqualityExpression;
8214             parseExpression = extra.parseExpression;
8215             parseForVariableDeclaration = extra.parseForVariableDeclaration;
8216             parseFunctionDeclaration = extra.parseFunctionDeclaration;
8217             parseFunctionExpression = extra.parseFunctionExpression;
8218             parseGroupExpression = extra.parseGroupExpression;
8219             parseLeftHandSideExpression = extra.parseLeftHandSideExpression;
8220             parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall;
8221             parseLogicalANDExpression = extra.parseLogicalANDExpression;
8222             parseLogicalORExpression = extra.parseLogicalORExpression;
8223             parseMultiplicativeExpression = extra.parseMultiplicativeExpression;
8224             parseNewExpression = extra.parseNewExpression;
8225             parseNonComputedProperty = extra.parseNonComputedProperty;
8226             parseObjectProperty = extra.parseObjectProperty;
8227             parseObjectPropertyKey = extra.parseObjectPropertyKey;
8228             parsePrimaryExpression = extra.parsePrimaryExpression;
8229             parsePostfixExpression = extra.parsePostfixExpression;
8230             parseProgram = extra.parseProgram;
8231             parsePropertyFunction = extra.parsePropertyFunction;
8232             parseRelationalExpression = extra.parseRelationalExpression;
8233             parseStatement = extra.parseStatement;
8234             parseShiftExpression = extra.parseShiftExpression;
8235             parseSwitchCase = extra.parseSwitchCase;
8236             parseUnaryExpression = extra.parseUnaryExpression;
8237             parseVariableDeclaration = extra.parseVariableDeclaration;
8238             parseVariableIdentifier = extra.parseVariableIdentifier;
8239         }
8241         if (typeof extra.scanRegExp === 'function') {
8242             advance = extra.advance;
8243             scanRegExp = extra.scanRegExp;
8244         }
8245     }
8247     function stringToArray(str) {
8248         var length = str.length,
8249             result = [],
8250             i;
8251         for (i = 0; i < length; ++i) {
8252             result[i] = str.charAt(i);
8253         }
8254         return result;
8255     }
8257     function parse(code, options) {
8258         var program, toString;
8260         toString = String;
8261         if (typeof code !== 'string' && !(code instanceof String)) {
8262             code = toString(code);
8263         }
8265         source = code;
8266         index = 0;
8267         lineNumber = (source.length > 0) ? 1 : 0;
8268         lineStart = 0;
8269         length = source.length;
8270         buffer = null;
8271         state = {
8272             allowIn: true,
8273             labelSet: {},
8274             inFunctionBody: false,
8275             inIteration: false,
8276             inSwitch: false
8277         };
8279         extra = {};
8280         if (typeof options !== 'undefined') {
8281             extra.range = (typeof options.range === 'boolean') && options.range;
8282             extra.loc = (typeof options.loc === 'boolean') && options.loc;
8283             extra.raw = (typeof options.raw === 'boolean') && options.raw;
8284             if (typeof options.tokens === 'boolean' && options.tokens) {
8285                 extra.tokens = [];
8286             }
8287             if (typeof options.comment === 'boolean' && options.comment) {
8288                 extra.comments = [];
8289             }
8290             if (typeof options.tolerant === 'boolean' && options.tolerant) {
8291                 extra.errors = [];
8292             }
8293         }
8295         if (length > 0) {
8296             if (typeof source[0] === 'undefined') {
8297                 // Try first to convert to a string. This is good as fast path
8298                 // for old IE which understands string indexing for string
8299                 // literals only and not for string object.
8300                 if (code instanceof String) {
8301                     source = code.valueOf();
8302                 }
8304                 // Force accessing the characters via an array.
8305                 if (typeof source[0] === 'undefined') {
8306                     source = stringToArray(code);
8307                 }
8308             }
8309         }
8311         patch();
8312         try {
8313             program = parseProgram();
8314             if (typeof extra.comments !== 'undefined') {
8315                 filterCommentLocation();
8316                 program.comments = extra.comments;
8317             }
8318             if (typeof extra.tokens !== 'undefined') {
8319                 filterTokenLocation();
8320                 program.tokens = extra.tokens;
8321             }
8322             if (typeof extra.errors !== 'undefined') {
8323                 program.errors = extra.errors;
8324             }
8325             if (extra.range || extra.loc) {
8326                 program.body = filterGroup(program.body);
8327             }
8328         } catch (e) {
8329             throw e;
8330         } finally {
8331             unpatch();
8332             extra = {};
8333         }
8335         return program;
8336     }
8338     // Sync with package.json.
8339     exports.version = '1.0.3';
8341     exports.parse = parse;
8343     // Deep copy.
8344     exports.Syntax = (function () {
8345         var name, types = {};
8347         if (typeof Object.create === 'function') {
8348             types = Object.create(null);
8349         }
8351         for (name in Syntax) {
8352             if (Syntax.hasOwnProperty(name)) {
8353                 types[name] = Syntax[name];
8354             }
8355         }
8357         if (typeof Object.freeze === 'function') {
8358             Object.freeze(types);
8359         }
8361         return types;
8362     }());
8364 }));
8365 /* vim: set sw=4 ts=4 et tw=80 : */
8367  * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
8368  * Available via the MIT or new BSD license.
8369  * see: http://github.com/jrburke/requirejs for details
8370  */
8372 /*global define, Reflect */
8375  * xpcshell has a smaller stack on linux and windows (1MB vs 9MB on mac),
8376  * and the recursive nature of esprima can cause it to overflow pretty
8377  * quickly. So favor it built in Reflect parser:
8378  * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
8379  */
8380 define('esprimaAdapter', ['./esprima', 'env'], function (esprima, env) {
8381     if (env.get() === 'xpconnect' && typeof Reflect !== 'undefined') {
8382         return Reflect;
8383     } else {
8384         return esprima;
8385     }
8387 define('uglifyjs/consolidator', ["require", "exports", "module", "./parse-js", "./process"], function(require, exports, module) {
8389  * @preserve Copyright 2012 Robert Gust-Bardon <http://robert.gust-bardon.org/>.
8390  * All rights reserved.
8392  * Redistribution and use in source and binary forms, with or without
8393  * modification, are permitted provided that the following conditions
8394  * are met:
8396  *     * Redistributions of source code must retain the above
8397  *       copyright notice, this list of conditions and the following
8398  *       disclaimer.
8400  *     * Redistributions in binary form must reproduce the above
8401  *       copyright notice, this list of conditions and the following
8402  *       disclaimer in the documentation and/or other materials
8403  *       provided with the distribution.
8405  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
8406  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8407  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
8408  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
8409  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
8410  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
8411  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
8412  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
8413  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
8414  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
8415  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8416  * SUCH DAMAGE.
8417  */
8420  * @fileoverview Enhances <a href="https://github.com/mishoo/UglifyJS/"
8421  * >UglifyJS</a> with consolidation of null, Boolean, and String values.
8422  * <p>Also known as aliasing, this feature has been deprecated in <a href=
8423  * "http://closure-compiler.googlecode.com/">the Closure Compiler</a> since its
8424  * initial release, where it is unavailable from the <abbr title=
8425  * "command line interface">CLI</a>. The Closure Compiler allows one to log and
8426  * influence this process. In contrast, this implementation does not introduce
8427  * any variable declarations in global code and derives String values from
8428  * identifier names used as property accessors.</p>
8429  * <p>Consolidating literals may worsen the data compression ratio when an <a
8430  * href="http://tools.ietf.org/html/rfc2616#section-3.5">encoding
8431  * transformation</a> is applied. For instance, <a href=
8432  * "http://code.jquery.com/jquery-1.7.1.js">jQuery 1.7.1</a> takes 248235 bytes.
8433  * Building it with <a href="https://github.com/mishoo/UglifyJS/tarball/v1.2.5">
8434  * UglifyJS v1.2.5</a> results in 93647 bytes (37.73% of the original) which are
8435  * then compressed to 33154 bytes (13.36% of the original) using <a href=
8436  * "http://linux.die.net/man/1/gzip">gzip(1)</a>. Building it with the same
8437  * version of UglifyJS 1.2.5 patched with the implementation of consolidation
8438  * results in 80784 bytes (a decrease of 12863 bytes, i.e. 13.74%, in comparison
8439  * to the aforementioned 93647 bytes) which are then compressed to 34013 bytes
8440  * (an increase of 859 bytes, i.e. 2.59%, in comparison to the aforementioned
8441  * 33154 bytes).</p>
8442  * <p>Written in <a href="http://es5.github.com/#x4.2.2">the strict variant</a>
8443  * of <a href="http://es5.github.com/">ECMA-262 5.1 Edition</a>. Encoded in <a
8444  * href="http://tools.ietf.org/html/rfc3629">UTF-8</a>. Follows <a href=
8445  * "http://google-styleguide.googlecode.com/svn-history/r76/trunk/javascriptguide.xml"
8446  * >Revision 2.28 of the Google JavaScript Style Guide</a> (except for the
8447  * discouraged use of the {@code function} tag and the {@code namespace} tag).
8448  * 100% typed for the <a href=
8449  * "http://closure-compiler.googlecode.com/files/compiler-20120123.tar.gz"
8450  * >Closure Compiler Version 1741</a>.</p>
8451  * <p>Should you find this software useful, please consider <a href=
8452  * "https://paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JZLW72X8FD4WG"
8453  * >a donation</a>.</p>
8454  * @author follow.me@RGustBardon (Robert Gust-Bardon)
8455  * @supported Tested with:
8456  *     <ul>
8457  *     <li><a href="http://nodejs.org/dist/v0.6.10/">Node v0.6.10</a>,</li>
8458  *     <li><a href="https://github.com/mishoo/UglifyJS/tarball/v1.2.5">UglifyJS
8459  *       v1.2.5</a>.</li>
8460  *     </ul>
8461  */
8463 /*global console:false, exports:true, module:false, require:false */
8464 /*jshint sub:true */
8466  * Consolidates null, Boolean, and String values found inside an <abbr title=
8467  * "abstract syntax tree">AST</abbr>.
8468  * @param {!TSyntacticCodeUnit} oAbstractSyntaxTree An array-like object
8469  *     representing an <abbr title="abstract syntax tree">AST</abbr>.
8470  * @return {!TSyntacticCodeUnit} An array-like object representing an <abbr
8471  *     title="abstract syntax tree">AST</abbr> with its null, Boolean, and
8472  *     String values consolidated.
8473  */
8474 // TODO(user) Consolidation of mathematical values found in numeric literals.
8475 // TODO(user) Unconsolidation.
8476 // TODO(user) Consolidation of ECMA-262 6th Edition programs.
8477 // TODO(user) Rewrite in ECMA-262 6th Edition.
8478 exports['ast_consolidate'] = function(oAbstractSyntaxTree) {
8479   'use strict';
8480   /*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true,
8481         latedef:true, newcap:true, noarge:true, noempty:true, nonew:true,
8482         onevar:true, plusplus:true, regexp:true, undef:true, strict:true,
8483         sub:false, trailing:true */
8485   var _,
8486       /**
8487        * A record consisting of data about one or more source elements.
8488        * @constructor
8489        * @nosideeffects
8490        */
8491       TSourceElementsData = function() {
8492         /**
8493          * The category of the elements.
8494          * @type {number}
8495          * @see ESourceElementCategories
8496          */
8497         this.nCategory = ESourceElementCategories.N_OTHER;
8498         /**
8499          * The number of occurrences (within the elements) of each primitive
8500          * value that could be consolidated.
8501          * @type {!Array.<!Object.<string, number>>}
8502          */
8503         this.aCount = [];
8504         this.aCount[EPrimaryExpressionCategories.N_IDENTIFIER_NAMES] = {};
8505         this.aCount[EPrimaryExpressionCategories.N_STRING_LITERALS] = {};
8506         this.aCount[EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS] =
8507             {};
8508         /**
8509          * Identifier names found within the elements.
8510          * @type {!Array.<string>}
8511          */
8512         this.aIdentifiers = [];
8513         /**
8514          * Prefixed representation Strings of each primitive value that could be
8515          * consolidated within the elements.
8516          * @type {!Array.<string>}
8517          */
8518         this.aPrimitiveValues = [];
8519       },
8520       /**
8521        * A record consisting of data about a primitive value that could be
8522        * consolidated.
8523        * @constructor
8524        * @nosideeffects
8525        */
8526       TPrimitiveValue = function() {
8527         /**
8528          * The difference in the number of terminal symbols between the original
8529          * source text and the one with the primitive value consolidated. If the
8530          * difference is positive, the primitive value is considered worthwhile.
8531          * @type {number}
8532          */
8533         this.nSaving = 0;
8534         /**
8535          * An identifier name of the variable that will be declared and assigned
8536          * the primitive value if the primitive value is consolidated.
8537          * @type {string}
8538          */
8539         this.sName = '';
8540       },
8541       /**
8542        * A record consisting of data on what to consolidate within the range of
8543        * source elements that is currently being considered.
8544        * @constructor
8545        * @nosideeffects
8546        */
8547       TSolution = function() {
8548         /**
8549          * An object whose keys are prefixed representation Strings of each
8550          * primitive value that could be consolidated within the elements and
8551          * whose values are corresponding data about those primitive values.
8552          * @type {!Object.<string, {nSaving: number, sName: string}>}
8553          * @see TPrimitiveValue
8554          */
8555         this.oPrimitiveValues = {};
8556         /**
8557          * The difference in the number of terminal symbols between the original
8558          * source text and the one with all the worthwhile primitive values
8559          * consolidated.
8560          * @type {number}
8561          * @see TPrimitiveValue#nSaving
8562          */
8563         this.nSavings = 0;
8564       },
8565       /**
8566        * The processor of <abbr title="abstract syntax tree">AST</abbr>s found
8567        * in UglifyJS.
8568        * @namespace
8569        * @type {!TProcessor}
8570        */
8571       oProcessor = (/** @type {!TProcessor} */ require('./process')),
8572       /**
8573        * A record consisting of a number of constants that represent the
8574        * difference in the number of terminal symbols between a source text with
8575        * a modified syntactic code unit and the original one.
8576        * @namespace
8577        * @type {!Object.<string, number>}
8578        */
8579       oWeights = {
8580         /**
8581          * The difference in the number of punctuators required by the bracket
8582          * notation and the dot notation.
8583          * <p><code>'[]'.length - '.'.length</code></p>
8584          * @const
8585          * @type {number}
8586          */
8587         N_PROPERTY_ACCESSOR: 1,
8588         /**
8589          * The number of punctuators required by a variable declaration with an
8590          * initialiser.
8591          * <p><code>':'.length + ';'.length</code></p>
8592          * @const
8593          * @type {number}
8594          */
8595         N_VARIABLE_DECLARATION: 2,
8596         /**
8597          * The number of terminal symbols required to introduce a variable
8598          * statement (excluding its variable declaration list).
8599          * <p><code>'var '.length</code></p>
8600          * @const
8601          * @type {number}
8602          */
8603         N_VARIABLE_STATEMENT_AFFIXATION: 4,
8604         /**
8605          * The number of terminal symbols needed to enclose source elements
8606          * within a function call with no argument values to a function with an
8607          * empty parameter list.
8608          * <p><code>'(function(){}());'.length</code></p>
8609          * @const
8610          * @type {number}
8611          */
8612         N_CLOSURE: 17
8613       },
8614       /**
8615        * Categories of primary expressions from which primitive values that
8616        * could be consolidated are derivable.
8617        * @namespace
8618        * @enum {number}
8619        */
8620       EPrimaryExpressionCategories = {
8621         /**
8622          * Identifier names used as property accessors.
8623          * @type {number}
8624          */
8625         N_IDENTIFIER_NAMES: 0,
8626         /**
8627          * String literals.
8628          * @type {number}
8629          */
8630         N_STRING_LITERALS: 1,
8631         /**
8632          * Null and Boolean literals.
8633          * @type {number}
8634          */
8635         N_NULL_AND_BOOLEAN_LITERALS: 2
8636       },
8637       /**
8638        * Prefixes of primitive values that could be consolidated.
8639        * The String values of the prefixes must have same number of characters.
8640        * The prefixes must not be used in any properties defined in any version
8641        * of <a href=
8642        * "http://www.ecma-international.org/publications/standards/Ecma-262.htm"
8643        * >ECMA-262</a>.
8644        * @namespace
8645        * @enum {string}
8646        */
8647       EValuePrefixes = {
8648         /**
8649          * Identifies String values.
8650          * @type {string}
8651          */
8652         S_STRING: '#S',
8653         /**
8654          * Identifies null and Boolean values.
8655          * @type {string}
8656          */
8657         S_SYMBOLIC: '#O'
8658       },
8659       /**
8660        * Categories of source elements in terms of their appropriateness of
8661        * having their primitive values consolidated.
8662        * @namespace
8663        * @enum {number}
8664        */
8665       ESourceElementCategories = {
8666         /**
8667          * Identifies a source element that includes the <a href=
8668          * "http://es5.github.com/#x12.10">{@code with}</a> statement.
8669          * @type {number}
8670          */
8671         N_WITH: 0,
8672         /**
8673          * Identifies a source element that includes the <a href=
8674          * "http://es5.github.com/#x15.1.2.1">{@code eval}</a> identifier name.
8675          * @type {number}
8676          */
8677         N_EVAL: 1,
8678         /**
8679          * Identifies a source element that must be excluded from the process
8680          * unless its whole scope is examined.
8681          * @type {number}
8682          */
8683         N_EXCLUDABLE: 2,
8684         /**
8685          * Identifies source elements not posing any problems.
8686          * @type {number}
8687          */
8688         N_OTHER: 3
8689       },
8690       /**
8691        * The list of literals (other than the String ones) whose primitive
8692        * values can be consolidated.
8693        * @const
8694        * @type {!Array.<string>}
8695        */
8696       A_OTHER_SUBSTITUTABLE_LITERALS = [
8697         'null',   // The null literal.
8698         'false',  // The Boolean literal {@code false}.
8699         'true'    // The Boolean literal {@code true}.
8700       ];
8702   (/**
8703     * Consolidates all worthwhile primitive values in a syntactic code unit.
8704     * @param {!TSyntacticCodeUnit} oSyntacticCodeUnit An array-like object
8705     *     representing the branch of the abstract syntax tree representing the
8706     *     syntactic code unit along with its scope.
8707     * @see TPrimitiveValue#nSaving
8708     */
8709    function fExamineSyntacticCodeUnit(oSyntacticCodeUnit) {
8710      var _,
8711          /**
8712           * Indicates whether the syntactic code unit represents global code.
8713           * @type {boolean}
8714           */
8715          bIsGlobal = 'toplevel' === oSyntacticCodeUnit[0],
8716          /**
8717           * Indicates whether the whole scope is being examined.
8718           * @type {boolean}
8719           */
8720          bIsWhollyExaminable = !bIsGlobal,
8721          /**
8722           * An array-like object representing source elements that constitute a
8723           * syntactic code unit.
8724           * @type {!TSyntacticCodeUnit}
8725           */
8726          oSourceElements,
8727          /**
8728           * A record consisting of data about the source element that is
8729           * currently being examined.
8730           * @type {!TSourceElementsData}
8731           */
8732          oSourceElementData,
8733          /**
8734           * The scope of the syntactic code unit.
8735           * @type {!TScope}
8736           */
8737          oScope,
8738          /**
8739           * An instance of an object that allows the traversal of an <abbr
8740           * title="abstract syntax tree">AST</abbr>.
8741           * @type {!TWalker}
8742           */
8743          oWalker,
8744          /**
8745           * An object encompassing collections of functions used during the
8746           * traversal of an <abbr title="abstract syntax tree">AST</abbr>.
8747           * @namespace
8748           * @type {!Object.<string, !Object.<string, function(...[*])>>}
8749           */
8750          oWalkers = {
8751            /**
8752             * A collection of functions used during the surveyance of source
8753             * elements.
8754             * @namespace
8755             * @type {!Object.<string, function(...[*])>}
8756             */
8757            oSurveySourceElement: {
8758              /**#nocode+*/  // JsDoc Toolkit 2.4.0 hides some of the keys.
8759              /**
8760               * Classifies the source element as excludable if it does not
8761               * contain a {@code with} statement or the {@code eval} identifier
8762               * name. Adds the identifier of the function and its formal
8763               * parameters to the list of identifier names found.
8764               * @param {string} sIdentifier The identifier of the function.
8765               * @param {!Array.<string>} aFormalParameterList Formal parameters.
8766               * @param {!TSyntacticCodeUnit} oFunctionBody Function code.
8767               */
8768              'defun': function(
8769                  sIdentifier,
8770                  aFormalParameterList,
8771                  oFunctionBody) {
8772                fClassifyAsExcludable();
8773                fAddIdentifier(sIdentifier);
8774                aFormalParameterList.forEach(fAddIdentifier);
8775              },
8776              /**
8777               * Increments the count of the number of occurrences of the String
8778               * value that is equivalent to the sequence of terminal symbols
8779               * that constitute the encountered identifier name.
8780               * @param {!TSyntacticCodeUnit} oExpression The nonterminal
8781               *     MemberExpression.
8782               * @param {string} sIdentifierName The identifier name used as the
8783               *     property accessor.
8784               * @return {!Array} The encountered branch of an <abbr title=
8785               *     "abstract syntax tree">AST</abbr> with its nonterminal
8786               *     MemberExpression traversed.
8787               */
8788              'dot': function(oExpression, sIdentifierName) {
8789                fCountPrimaryExpression(
8790                    EPrimaryExpressionCategories.N_IDENTIFIER_NAMES,
8791                    EValuePrefixes.S_STRING + sIdentifierName);
8792                return ['dot', oWalker.walk(oExpression), sIdentifierName];
8793              },
8794              /**
8795               * Adds the optional identifier of the function and its formal
8796               * parameters to the list of identifier names found.
8797               * @param {?string} sIdentifier The optional identifier of the
8798               *     function.
8799               * @param {!Array.<string>} aFormalParameterList Formal parameters.
8800               * @param {!TSyntacticCodeUnit} oFunctionBody Function code.
8801               */
8802              'function': function(
8803                  sIdentifier,
8804                  aFormalParameterList,
8805                  oFunctionBody) {
8806                if ('string' === typeof sIdentifier) {
8807                  fAddIdentifier(sIdentifier);
8808                }
8809                aFormalParameterList.forEach(fAddIdentifier);
8810              },
8811              /**
8812               * Either increments the count of the number of occurrences of the
8813               * encountered null or Boolean value or classifies a source element
8814               * as containing the {@code eval} identifier name.
8815               * @param {string} sIdentifier The identifier encountered.
8816               */
8817              'name': function(sIdentifier) {
8818                if (-1 !== A_OTHER_SUBSTITUTABLE_LITERALS.indexOf(sIdentifier)) {
8819                  fCountPrimaryExpression(
8820                      EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS,
8821                      EValuePrefixes.S_SYMBOLIC + sIdentifier);
8822                } else {
8823                  if ('eval' === sIdentifier) {
8824                    oSourceElementData.nCategory =
8825                        ESourceElementCategories.N_EVAL;
8826                  }
8827                  fAddIdentifier(sIdentifier);
8828                }
8829              },
8830              /**
8831               * Classifies the source element as excludable if it does not
8832               * contain a {@code with} statement or the {@code eval} identifier
8833               * name.
8834               * @param {TSyntacticCodeUnit} oExpression The expression whose
8835               *     value is to be returned.
8836               */
8837              'return': function(oExpression) {
8838                fClassifyAsExcludable();
8839              },
8840              /**
8841               * Increments the count of the number of occurrences of the
8842               * encountered String value.
8843               * @param {string} sStringValue The String value of the string
8844               *     literal encountered.
8845               */
8846              'string': function(sStringValue) {
8847                if (sStringValue.length > 0) {
8848                  fCountPrimaryExpression(
8849                      EPrimaryExpressionCategories.N_STRING_LITERALS,
8850                      EValuePrefixes.S_STRING + sStringValue);
8851                }
8852              },
8853              /**
8854               * Adds the identifier reserved for an exception to the list of
8855               * identifier names found.
8856               * @param {!TSyntacticCodeUnit} oTry A block of code in which an
8857               *     exception can occur.
8858               * @param {Array} aCatch The identifier reserved for an exception
8859               *     and a block of code to handle the exception.
8860               * @param {TSyntacticCodeUnit} oFinally An optional block of code
8861               *     to be evaluated regardless of whether an exception occurs.
8862               */
8863              'try': function(oTry, aCatch, oFinally) {
8864                if (Array.isArray(aCatch)) {
8865                  fAddIdentifier(aCatch[0]);
8866                }
8867              },
8868              /**
8869               * Classifies the source element as excludable if it does not
8870               * contain a {@code with} statement or the {@code eval} identifier
8871               * name. Adds the identifier of each declared variable to the list
8872               * of identifier names found.
8873               * @param {!Array.<!Array>} aVariableDeclarationList Variable
8874               *     declarations.
8875               */
8876              'var': function(aVariableDeclarationList) {
8877                fClassifyAsExcludable();
8878                aVariableDeclarationList.forEach(fAddVariable);
8879              },
8880              /**
8881               * Classifies a source element as containing the {@code with}
8882               * statement.
8883               * @param {!TSyntacticCodeUnit} oExpression An expression whose
8884               *     value is to be converted to a value of type Object and
8885               *     become the binding object of a new object environment
8886               *     record of a new lexical environment in which the statement
8887               *     is to be executed.
8888               * @param {!TSyntacticCodeUnit} oStatement The statement to be
8889               *     executed in the augmented lexical environment.
8890               * @return {!Array} An empty array to stop the traversal.
8891               */
8892              'with': function(oExpression, oStatement) {
8893                oSourceElementData.nCategory = ESourceElementCategories.N_WITH;
8894                return [];
8895              }
8896              /**#nocode-*/  // JsDoc Toolkit 2.4.0 hides some of the keys.
8897            },
8898            /**
8899             * A collection of functions used while looking for nested functions.
8900             * @namespace
8901             * @type {!Object.<string, function(...[*])>}
8902             */
8903            oExamineFunctions: {
8904              /**#nocode+*/  // JsDoc Toolkit 2.4.0 hides some of the keys.
8905              /**
8906               * Orders an examination of a nested function declaration.
8907               * @this {!TSyntacticCodeUnit} An array-like object representing
8908               *     the branch of an <abbr title="abstract syntax tree"
8909               *     >AST</abbr> representing the syntactic code unit along with
8910               *     its scope.
8911               * @return {!Array} An empty array to stop the traversal.
8912               */
8913              'defun': function() {
8914                fExamineSyntacticCodeUnit(this);
8915                return [];
8916              },
8917              /**
8918               * Orders an examination of a nested function expression.
8919               * @this {!TSyntacticCodeUnit} An array-like object representing
8920               *     the branch of an <abbr title="abstract syntax tree"
8921               *     >AST</abbr> representing the syntactic code unit along with
8922               *     its scope.
8923               * @return {!Array} An empty array to stop the traversal.
8924               */
8925              'function': function() {
8926                fExamineSyntacticCodeUnit(this);
8927                return [];
8928              }
8929              /**#nocode-*/  // JsDoc Toolkit 2.4.0 hides some of the keys.
8930            }
8931          },
8932          /**
8933           * Records containing data about source elements.
8934           * @type {Array.<TSourceElementsData>}
8935           */
8936          aSourceElementsData = [],
8937          /**
8938           * The index (in the source text order) of the source element
8939           * immediately following a <a href="http://es5.github.com/#x14.1"
8940           * >Directive Prologue</a>.
8941           * @type {number}
8942           */
8943          nAfterDirectivePrologue = 0,
8944          /**
8945           * The index (in the source text order) of the source element that is
8946           * currently being considered.
8947           * @type {number}
8948           */
8949          nPosition,
8950          /**
8951           * The index (in the source text order) of the source element that is
8952           * the last element of the range of source elements that is currently
8953           * being considered.
8954           * @type {(undefined|number)}
8955           */
8956          nTo,
8957          /**
8958           * Initiates the traversal of a source element.
8959           * @param {!TWalker} oWalker An instance of an object that allows the
8960           *     traversal of an abstract syntax tree.
8961           * @param {!TSyntacticCodeUnit} oSourceElement A source element from
8962           *     which the traversal should commence.
8963           * @return {function(): !TSyntacticCodeUnit} A function that is able to
8964           *     initiate the traversal from a given source element.
8965           */
8966          cContext = function(oWalker, oSourceElement) {
8967            /**
8968             * @return {!TSyntacticCodeUnit} A function that is able to
8969             *     initiate the traversal from a given source element.
8970             */
8971            var fLambda = function() {
8972              return oWalker.walk(oSourceElement);
8973            };
8975            return fLambda;
8976          },
8977          /**
8978           * Classifies the source element as excludable if it does not
8979           * contain a {@code with} statement or the {@code eval} identifier
8980           * name.
8981           */
8982          fClassifyAsExcludable = function() {
8983            if (oSourceElementData.nCategory ===
8984                ESourceElementCategories.N_OTHER) {
8985              oSourceElementData.nCategory =
8986                  ESourceElementCategories.N_EXCLUDABLE;
8987            }
8988          },
8989          /**
8990           * Adds an identifier to the list of identifier names found.
8991           * @param {string} sIdentifier The identifier to be added.
8992           */
8993          fAddIdentifier = function(sIdentifier) {
8994            if (-1 === oSourceElementData.aIdentifiers.indexOf(sIdentifier)) {
8995              oSourceElementData.aIdentifiers.push(sIdentifier);
8996            }
8997          },
8998          /**
8999           * Adds the identifier of a variable to the list of identifier names
9000           * found.
9001           * @param {!Array} aVariableDeclaration A variable declaration.
9002           */
9003          fAddVariable = function(aVariableDeclaration) {
9004            fAddIdentifier(/** @type {string} */ aVariableDeclaration[0]);
9005          },
9006          /**
9007           * Increments the count of the number of occurrences of the prefixed
9008           * String representation attributed to the primary expression.
9009           * @param {number} nCategory The category of the primary expression.
9010           * @param {string} sName The prefixed String representation attributed
9011           *     to the primary expression.
9012           */
9013          fCountPrimaryExpression = function(nCategory, sName) {
9014            if (!oSourceElementData.aCount[nCategory].hasOwnProperty(sName)) {
9015              oSourceElementData.aCount[nCategory][sName] = 0;
9016              if (-1 === oSourceElementData.aPrimitiveValues.indexOf(sName)) {
9017                oSourceElementData.aPrimitiveValues.push(sName);
9018              }
9019            }
9020            oSourceElementData.aCount[nCategory][sName] += 1;
9021          },
9022          /**
9023           * Consolidates all worthwhile primitive values in a range of source
9024           *     elements.
9025           * @param {number} nFrom The index (in the source text order) of the
9026           *     source element that is the first element of the range.
9027           * @param {number} nTo The index (in the source text order) of the
9028           *     source element that is the last element of the range.
9029           * @param {boolean} bEnclose Indicates whether the range should be
9030           *     enclosed within a function call with no argument values to a
9031           *     function with an empty parameter list if any primitive values
9032           *     are consolidated.
9033           * @see TPrimitiveValue#nSaving
9034           */
9035          fExamineSourceElements = function(nFrom, nTo, bEnclose) {
9036            var _,
9037                /**
9038                 * The index of the last mangled name.
9039                 * @type {number}
9040                 */
9041                nIndex = oScope.cname,
9042                /**
9043                 * The index of the source element that is currently being
9044                 * considered.
9045                 * @type {number}
9046                 */
9047                nPosition,
9048                /**
9049                 * A collection of functions used during the consolidation of
9050                 * primitive values and identifier names used as property
9051                 * accessors.
9052                 * @namespace
9053                 * @type {!Object.<string, function(...[*])>}
9054                 */
9055                oWalkersTransformers = {
9056                  /**
9057                   * If the String value that is equivalent to the sequence of
9058                   * terminal symbols that constitute the encountered identifier
9059                   * name is worthwhile, a syntactic conversion from the dot
9060                   * notation to the bracket notation ensues with that sequence
9061                   * being substituted by an identifier name to which the value
9062                   * is assigned.
9063                   * Applies to property accessors that use the dot notation.
9064                   * @param {!TSyntacticCodeUnit} oExpression The nonterminal
9065                   *     MemberExpression.
9066                   * @param {string} sIdentifierName The identifier name used as
9067                   *     the property accessor.
9068                   * @return {!Array} A syntactic code unit that is equivalent to
9069                   *     the one encountered.
9070                   * @see TPrimitiveValue#nSaving
9071                   */
9072                  'dot': function(oExpression, sIdentifierName) {
9073                    /**
9074                     * The prefixed String value that is equivalent to the
9075                     * sequence of terminal symbols that constitute the
9076                     * encountered identifier name.
9077                     * @type {string}
9078                     */
9079                    var sPrefixed = EValuePrefixes.S_STRING + sIdentifierName;
9081                    return oSolutionBest.oPrimitiveValues.hasOwnProperty(
9082                        sPrefixed) &&
9083                        oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
9084                        ['sub',
9085                         oWalker.walk(oExpression),
9086                         ['name',
9087                          oSolutionBest.oPrimitiveValues[sPrefixed].sName]] :
9088                        ['dot', oWalker.walk(oExpression), sIdentifierName];
9089                  },
9090                  /**
9091                   * If the encountered identifier is a null or Boolean literal
9092                   * and its value is worthwhile, the identifier is substituted
9093                   * by an identifier name to which that value is assigned.
9094                   * Applies to identifier names.
9095                   * @param {string} sIdentifier The identifier encountered.
9096                   * @return {!Array} A syntactic code unit that is equivalent to
9097                   *     the one encountered.
9098                   * @see TPrimitiveValue#nSaving
9099                   */
9100                  'name': function(sIdentifier) {
9101                    /**
9102                     * The prefixed representation String of the identifier.
9103                     * @type {string}
9104                     */
9105                    var sPrefixed = EValuePrefixes.S_SYMBOLIC + sIdentifier;
9107                    return [
9108                      'name',
9109                      oSolutionBest.oPrimitiveValues.hasOwnProperty(sPrefixed) &&
9110                      oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
9111                      oSolutionBest.oPrimitiveValues[sPrefixed].sName :
9112                      sIdentifier
9113                    ];
9114                  },
9115                  /**
9116                   * If the encountered String value is worthwhile, it is
9117                   * substituted by an identifier name to which that value is
9118                   * assigned.
9119                   * Applies to String values.
9120                   * @param {string} sStringValue The String value of the string
9121                   *     literal encountered.
9122                   * @return {!Array} A syntactic code unit that is equivalent to
9123                   *     the one encountered.
9124                   * @see TPrimitiveValue#nSaving
9125                   */
9126                  'string': function(sStringValue) {
9127                    /**
9128                     * The prefixed representation String of the primitive value
9129                     * of the literal.
9130                     * @type {string}
9131                     */
9132                    var sPrefixed =
9133                        EValuePrefixes.S_STRING + sStringValue;
9135                    return oSolutionBest.oPrimitiveValues.hasOwnProperty(
9136                        sPrefixed) &&
9137                        oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
9138                        ['name',
9139                         oSolutionBest.oPrimitiveValues[sPrefixed].sName] :
9140                        ['string', sStringValue];
9141                  }
9142                },
9143                /**
9144                 * Such data on what to consolidate within the range of source
9145                 * elements that is currently being considered that lead to the
9146                 * greatest known reduction of the number of the terminal symbols
9147                 * in comparison to the original source text.
9148                 * @type {!TSolution}
9149                 */
9150                oSolutionBest = new TSolution(),
9151                /**
9152                 * Data representing an ongoing attempt to find a better
9153                 * reduction of the number of the terminal symbols in comparison
9154                 * to the original source text than the best one that is
9155                 * currently known.
9156                 * @type {!TSolution}
9157                 * @see oSolutionBest
9158                 */
9159                oSolutionCandidate = new TSolution(),
9160                /**
9161                 * A record consisting of data about the range of source elements
9162                 * that is currently being examined.
9163                 * @type {!TSourceElementsData}
9164                 */
9165                oSourceElementsData = new TSourceElementsData(),
9166                /**
9167                 * Variable declarations for each primitive value that is to be
9168                 * consolidated within the elements.
9169                 * @type {!Array.<!Array>}
9170                 */
9171                aVariableDeclarations = [],
9172                /**
9173                 * Augments a list with a prefixed representation String.
9174                 * @param {!Array.<string>} aList A list that is to be augmented.
9175                 * @return {function(string)} A function that augments a list
9176                 *     with a prefixed representation String.
9177                 */
9178                cAugmentList = function(aList) {
9179                  /**
9180                   * @param {string} sPrefixed Prefixed representation String of
9181                   *     a primitive value that could be consolidated within the
9182                   *     elements.
9183                   */
9184                  var fLambda = function(sPrefixed) {
9185                    if (-1 === aList.indexOf(sPrefixed)) {
9186                      aList.push(sPrefixed);
9187                    }
9188                  };
9190                  return fLambda;
9191                },
9192                /**
9193                 * Adds the number of occurrences of a primitive value of a given
9194                 * category that could be consolidated in the source element with
9195                 * a given index to the count of occurrences of that primitive
9196                 * value within the range of source elements that is currently
9197                 * being considered.
9198                 * @param {number} nPosition The index (in the source text order)
9199                 *     of a source element.
9200                 * @param {number} nCategory The category of the primary
9201                 *     expression from which the primitive value is derived.
9202                 * @return {function(string)} A function that performs the
9203                 *     addition.
9204                 * @see cAddOccurrencesInCategory
9205                 */
9206                cAddOccurrences = function(nPosition, nCategory) {
9207                  /**
9208                   * @param {string} sPrefixed The prefixed representation String
9209                   *     of a primitive value.
9210                   */
9211                  var fLambda = function(sPrefixed) {
9212                    if (!oSourceElementsData.aCount[nCategory].hasOwnProperty(
9213                            sPrefixed)) {
9214                      oSourceElementsData.aCount[nCategory][sPrefixed] = 0;
9215                    }
9216                    oSourceElementsData.aCount[nCategory][sPrefixed] +=
9217                        aSourceElementsData[nPosition].aCount[nCategory][
9218                            sPrefixed];
9219                  };
9221                  return fLambda;
9222                },
9223                /**
9224                 * Adds the number of occurrences of each primitive value of a
9225                 * given category that could be consolidated in the source
9226                 * element with a given index to the count of occurrences of that
9227                 * primitive values within the range of source elements that is
9228                 * currently being considered.
9229                 * @param {number} nPosition The index (in the source text order)
9230                 *     of a source element.
9231                 * @return {function(number)} A function that performs the
9232                 *     addition.
9233                 * @see fAddOccurrences
9234                 */
9235                cAddOccurrencesInCategory = function(nPosition) {
9236                  /**
9237                   * @param {number} nCategory The category of the primary
9238                   *     expression from which the primitive value is derived.
9239                   */
9240                  var fLambda = function(nCategory) {
9241                    Object.keys(
9242                        aSourceElementsData[nPosition].aCount[nCategory]
9243                    ).forEach(cAddOccurrences(nPosition, nCategory));
9244                  };
9246                  return fLambda;
9247                },
9248                /**
9249                 * Adds the number of occurrences of each primitive value that
9250                 * could be consolidated in the source element with a given index
9251                 * to the count of occurrences of that primitive values within
9252                 * the range of source elements that is currently being
9253                 * considered.
9254                 * @param {number} nPosition The index (in the source text order)
9255                 *     of a source element.
9256                 */
9257                fAddOccurrences = function(nPosition) {
9258                  Object.keys(aSourceElementsData[nPosition].aCount).forEach(
9259                      cAddOccurrencesInCategory(nPosition));
9260                },
9261                /**
9262                 * Creates a variable declaration for a primitive value if that
9263                 * primitive value is to be consolidated within the elements.
9264                 * @param {string} sPrefixed Prefixed representation String of a
9265                 *     primitive value that could be consolidated within the
9266                 *     elements.
9267                 * @see aVariableDeclarations
9268                 */
9269                cAugmentVariableDeclarations = function(sPrefixed) {
9270                  if (oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0) {
9271                    aVariableDeclarations.push([
9272                      oSolutionBest.oPrimitiveValues[sPrefixed].sName,
9273                      [0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC) ?
9274                       'name' : 'string',
9275                       sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length)]
9276                    ]);
9277                  }
9278                },
9279                /**
9280                 * Sorts primitive values with regard to the difference in the
9281                 * number of terminal symbols between the original source text
9282                 * and the one with those primitive values consolidated.
9283                 * @param {string} sPrefixed0 The prefixed representation String
9284                 *     of the first of the two primitive values that are being
9285                 *     compared.
9286                 * @param {string} sPrefixed1 The prefixed representation String
9287                 *     of the second of the two primitive values that are being
9288                 *     compared.
9289                 * @return {number}
9290                 *     <dl>
9291                 *         <dt>-1</dt>
9292                 *         <dd>if the first primitive value must be placed before
9293                 *              the other one,</dd>
9294                 *         <dt>0</dt>
9295                 *         <dd>if the first primitive value may be placed before
9296                 *              the other one,</dd>
9297                 *         <dt>1</dt>
9298                 *         <dd>if the first primitive value must not be placed
9299                 *              before the other one.</dd>
9300                 *     </dl>
9301                 * @see TSolution.oPrimitiveValues
9302                 */
9303                cSortPrimitiveValues = function(sPrefixed0, sPrefixed1) {
9304                  /**
9305                   * The difference between:
9306                   * <ol>
9307                   * <li>the difference in the number of terminal symbols
9308                   *     between the original source text and the one with the
9309                   *     first primitive value consolidated, and</li>
9310                   * <li>the difference in the number of terminal symbols
9311                   *     between the original source text and the one with the
9312                   *     second primitive value consolidated.</li>
9313                   * </ol>
9314                   * @type {number}
9315                   */
9316                  var nDifference =
9317                      oSolutionCandidate.oPrimitiveValues[sPrefixed0].nSaving -
9318                      oSolutionCandidate.oPrimitiveValues[sPrefixed1].nSaving;
9320                  return nDifference > 0 ? -1 : nDifference < 0 ? 1 : 0;
9321                },
9322                /**
9323                 * Assigns an identifier name to a primitive value and calculates
9324                 * whether instances of that primitive value are worth
9325                 * consolidating.
9326                 * @param {string} sPrefixed The prefixed representation String
9327                 *     of a primitive value that is being evaluated.
9328                 */
9329                fEvaluatePrimitiveValue = function(sPrefixed) {
9330                  var _,
9331                      /**
9332                       * The index of the last mangled name.
9333                       * @type {number}
9334                       */
9335                      nIndex,
9336                      /**
9337                       * The representation String of the primitive value that is
9338                       * being evaluated.
9339                       * @type {string}
9340                       */
9341                      sName =
9342                          sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length),
9343                      /**
9344                       * The number of source characters taken up by the
9345                       * representation String of the primitive value that is
9346                       * being evaluated.
9347                       * @type {number}
9348                       */
9349                      nLengthOriginal = sName.length,
9350                      /**
9351                       * The number of source characters taken up by the
9352                       * identifier name that could substitute the primitive
9353                       * value that is being evaluated.
9354                       * substituted.
9355                       * @type {number}
9356                       */
9357                      nLengthSubstitution,
9358                      /**
9359                       * The number of source characters taken up by by the
9360                       * representation String of the primitive value that is
9361                       * being evaluated when it is represented by a string
9362                       * literal.
9363                       * @type {number}
9364                       */
9365                      nLengthString = oProcessor.make_string(sName).length;
9367                  oSolutionCandidate.oPrimitiveValues[sPrefixed] =
9368                      new TPrimitiveValue();
9369                  do {  // Find an identifier unused in this or any nested scope.
9370                    nIndex = oScope.cname;
9371                    oSolutionCandidate.oPrimitiveValues[sPrefixed].sName =
9372                        oScope.next_mangled();
9373                  } while (-1 !== oSourceElementsData.aIdentifiers.indexOf(
9374                      oSolutionCandidate.oPrimitiveValues[sPrefixed].sName));
9375                  nLengthSubstitution = oSolutionCandidate.oPrimitiveValues[
9376                      sPrefixed].sName.length;
9377                  if (0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC)) {
9378                    // foo:null, or foo:null;
9379                    oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -=
9380                        nLengthSubstitution + nLengthOriginal +
9381                        oWeights.N_VARIABLE_DECLARATION;
9382                    // null vs foo
9383                    oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
9384                        oSourceElementsData.aCount[
9385                            EPrimaryExpressionCategories.
9386                                N_NULL_AND_BOOLEAN_LITERALS][sPrefixed] *
9387                        (nLengthOriginal - nLengthSubstitution);
9388                  } else {
9389                    // foo:'fromCharCode';
9390                    oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -=
9391                        nLengthSubstitution + nLengthString +
9392                        oWeights.N_VARIABLE_DECLARATION;
9393                    // .fromCharCode vs [foo]
9394                    if (oSourceElementsData.aCount[
9395                            EPrimaryExpressionCategories.N_IDENTIFIER_NAMES
9396                        ].hasOwnProperty(sPrefixed)) {
9397                      oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
9398                          oSourceElementsData.aCount[
9399                              EPrimaryExpressionCategories.N_IDENTIFIER_NAMES
9400                          ][sPrefixed] *
9401                          (nLengthOriginal - nLengthSubstitution -
9402                           oWeights.N_PROPERTY_ACCESSOR);
9403                    }
9404                    // 'fromCharCode' vs foo
9405                    if (oSourceElementsData.aCount[
9406                            EPrimaryExpressionCategories.N_STRING_LITERALS
9407                        ].hasOwnProperty(sPrefixed)) {
9408                      oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
9409                          oSourceElementsData.aCount[
9410                              EPrimaryExpressionCategories.N_STRING_LITERALS
9411                          ][sPrefixed] *
9412                          (nLengthString - nLengthSubstitution);
9413                    }
9414                  }
9415                  if (oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving >
9416                      0) {
9417                    oSolutionCandidate.nSavings +=
9418                        oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving;
9419                  } else {
9420                    oScope.cname = nIndex; // Free the identifier name.
9421                  }
9422                },
9423                /**
9424                 * Adds a variable declaration to an existing variable statement.
9425                 * @param {!Array} aVariableDeclaration A variable declaration
9426                 *     with an initialiser.
9427                 */
9428                cAddVariableDeclaration = function(aVariableDeclaration) {
9429                  (/** @type {!Array} */ oSourceElements[nFrom][1]).unshift(
9430                      aVariableDeclaration);
9431                };
9433            if (nFrom > nTo) {
9434              return;
9435            }
9436            // If the range is a closure, reuse the closure.
9437            if (nFrom === nTo &&
9438                'stat' === oSourceElements[nFrom][0] &&
9439                'call' === oSourceElements[nFrom][1][0] &&
9440                'function' === oSourceElements[nFrom][1][1][0]) {
9441              fExamineSyntacticCodeUnit(oSourceElements[nFrom][1][1]);
9442              return;
9443            }
9444            // Create a list of all derived primitive values within the range.
9445            for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
9446              aSourceElementsData[nPosition].aPrimitiveValues.forEach(
9447                  cAugmentList(oSourceElementsData.aPrimitiveValues));
9448            }
9449            if (0 === oSourceElementsData.aPrimitiveValues.length) {
9450              return;
9451            }
9452            for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
9453              // Add the number of occurrences to the total count.
9454              fAddOccurrences(nPosition);
9455              // Add identifiers of this or any nested scope to the list.
9456              aSourceElementsData[nPosition].aIdentifiers.forEach(
9457                  cAugmentList(oSourceElementsData.aIdentifiers));
9458            }
9459            // Distribute identifier names among derived primitive values.
9460            do {  // If there was any progress, find a better distribution.
9461              oSolutionBest = oSolutionCandidate;
9462              if (Object.keys(oSolutionCandidate.oPrimitiveValues).length > 0) {
9463                // Sort primitive values descending by their worthwhileness.
9464                oSourceElementsData.aPrimitiveValues.sort(cSortPrimitiveValues);
9465              }
9466              oSolutionCandidate = new TSolution();
9467              oSourceElementsData.aPrimitiveValues.forEach(
9468                  fEvaluatePrimitiveValue);
9469              oScope.cname = nIndex;
9470            } while (oSolutionCandidate.nSavings > oSolutionBest.nSavings);
9471            // Take the necessity of adding a variable statement into account.
9472            if ('var' !== oSourceElements[nFrom][0]) {
9473              oSolutionBest.nSavings -= oWeights.N_VARIABLE_STATEMENT_AFFIXATION;
9474            }
9475            if (bEnclose) {
9476              // Take the necessity of forming a closure into account.
9477              oSolutionBest.nSavings -= oWeights.N_CLOSURE;
9478            }
9479            if (oSolutionBest.nSavings > 0) {
9480              // Create variable declarations suitable for UglifyJS.
9481              Object.keys(oSolutionBest.oPrimitiveValues).forEach(
9482                  cAugmentVariableDeclarations);
9483              // Rewrite expressions that contain worthwhile primitive values.
9484              for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
9485                oWalker = oProcessor.ast_walker();
9486                oSourceElements[nPosition] =
9487                    oWalker.with_walkers(
9488                        oWalkersTransformers,
9489                        cContext(oWalker, oSourceElements[nPosition]));
9490              }
9491              if ('var' === oSourceElements[nFrom][0]) {  // Reuse the statement.
9492                (/** @type {!Array.<!Array>} */ aVariableDeclarations.reverse(
9493                    )).forEach(cAddVariableDeclaration);
9494              } else {  // Add a variable statement.
9495                Array.prototype.splice.call(
9496                    oSourceElements,
9497                    nFrom,
9498                    0,
9499                    ['var', aVariableDeclarations]);
9500                nTo += 1;
9501              }
9502              if (bEnclose) {
9503                // Add a closure.
9504                Array.prototype.splice.call(
9505                    oSourceElements,
9506                    nFrom,
9507                    0,
9508                    ['stat', ['call', ['function', null, [], []], []]]);
9509                // Copy source elements into the closure.
9510                for (nPosition = nTo + 1; nPosition > nFrom; nPosition -= 1) {
9511                  Array.prototype.unshift.call(
9512                      oSourceElements[nFrom][1][1][3],
9513                      oSourceElements[nPosition]);
9514                }
9515                // Remove source elements outside the closure.
9516                Array.prototype.splice.call(
9517                    oSourceElements,
9518                    nFrom + 1,
9519                    nTo - nFrom + 1);
9520              }
9521            }
9522            if (bEnclose) {
9523              // Restore the availability of identifier names.
9524              oScope.cname = nIndex;
9525            }
9526          };
9528      oSourceElements = (/** @type {!TSyntacticCodeUnit} */
9529          oSyntacticCodeUnit[bIsGlobal ? 1 : 3]);
9530      if (0 === oSourceElements.length) {
9531        return;
9532      }
9533      oScope = bIsGlobal ? oSyntacticCodeUnit.scope : oSourceElements.scope;
9534      // Skip a Directive Prologue.
9535      while (nAfterDirectivePrologue < oSourceElements.length &&
9536             'directive' === oSourceElements[nAfterDirectivePrologue][0]) {
9537        nAfterDirectivePrologue += 1;
9538        aSourceElementsData.push(null);
9539      }
9540      if (oSourceElements.length === nAfterDirectivePrologue) {
9541        return;
9542      }
9543      for (nPosition = nAfterDirectivePrologue;
9544           nPosition < oSourceElements.length;
9545           nPosition += 1) {
9546        oSourceElementData = new TSourceElementsData();
9547        oWalker = oProcessor.ast_walker();
9548        // Classify a source element.
9549        // Find its derived primitive values and count their occurrences.
9550        // Find all identifiers used (including nested scopes).
9551        oWalker.with_walkers(
9552            oWalkers.oSurveySourceElement,
9553            cContext(oWalker, oSourceElements[nPosition]));
9554        // Establish whether the scope is still wholly examinable.
9555        bIsWhollyExaminable = bIsWhollyExaminable &&
9556            ESourceElementCategories.N_WITH !== oSourceElementData.nCategory &&
9557            ESourceElementCategories.N_EVAL !== oSourceElementData.nCategory;
9558        aSourceElementsData.push(oSourceElementData);
9559      }
9560      if (bIsWhollyExaminable) {  // Examine the whole scope.
9561        fExamineSourceElements(
9562            nAfterDirectivePrologue,
9563            oSourceElements.length - 1,
9564            false);
9565      } else {  // Examine unexcluded ranges of source elements.
9566        for (nPosition = oSourceElements.length - 1;
9567             nPosition >= nAfterDirectivePrologue;
9568             nPosition -= 1) {
9569          oSourceElementData = (/** @type {!TSourceElementsData} */
9570              aSourceElementsData[nPosition]);
9571          if (ESourceElementCategories.N_OTHER ===
9572              oSourceElementData.nCategory) {
9573            if ('undefined' === typeof nTo) {
9574              nTo = nPosition;  // Indicate the end of a range.
9575            }
9576            // Examine the range if it immediately follows a Directive Prologue.
9577            if (nPosition === nAfterDirectivePrologue) {
9578              fExamineSourceElements(nPosition, nTo, true);
9579            }
9580          } else {
9581            if ('undefined' !== typeof nTo) {
9582              // Examine the range that immediately follows this source element.
9583              fExamineSourceElements(nPosition + 1, nTo, true);
9584              nTo = void 0;  // Obliterate the range.
9585            }
9586            // Examine nested functions.
9587            oWalker = oProcessor.ast_walker();
9588            oWalker.with_walkers(
9589                oWalkers.oExamineFunctions,
9590                cContext(oWalker, oSourceElements[nPosition]));
9591          }
9592        }
9593      }
9594    }(oAbstractSyntaxTree = oProcessor.ast_add_scope(oAbstractSyntaxTree)));
9595   return oAbstractSyntaxTree;
9597 /*jshint sub:false */
9599 /* Local Variables:      */
9600 /* mode: js              */
9601 /* coding: utf-8         */
9602 /* indent-tabs-mode: nil */
9603 /* tab-width: 2          */
9604 /* End:                  */
9605 /* vim: set ft=javascript fenc=utf-8 et ts=2 sts=2 sw=2: */
9606 /* :mode=javascript:noTabs=true:tabSize=2:indentSize=2:deepIndent=true: */
9608 define('uglifyjs/parse-js', ["exports"], function(exports) {
9609 /***********************************************************************
9611   A JavaScript tokenizer / parser / beautifier / compressor.
9613   This version is suitable for Node.js.  With minimal changes (the
9614   exports stuff) it should work on any JS platform.
9616   This file contains the tokenizer/parser.  It is a port to JavaScript
9617   of parse-js [1], a JavaScript parser library written in Common Lisp
9618   by Marijn Haverbeke.  Thank you Marijn!
9620   [1] http://marijn.haverbeke.nl/parse-js/
9622   Exported functions:
9624     - tokenizer(code) -- returns a function.  Call the returned
9625       function to fetch the next token.
9627     - parse(code) -- returns an AST of the given JavaScript code.
9629   -------------------------------- (C) ---------------------------------
9631                            Author: Mihai Bazon
9632                          <mihai.bazon@gmail.com>
9633                        http://mihai.bazon.net/blog
9635   Distributed under the BSD license:
9637     Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
9638     Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
9640     Redistribution and use in source and binary forms, with or without
9641     modification, are permitted provided that the following conditions
9642     are met:
9644         * Redistributions of source code must retain the above
9645           copyright notice, this list of conditions and the following
9646           disclaimer.
9648         * Redistributions in binary form must reproduce the above
9649           copyright notice, this list of conditions and the following
9650           disclaimer in the documentation and/or other materials
9651           provided with the distribution.
9653     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
9654     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9655     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9656     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
9657     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
9658     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9659     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9660     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9661     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
9662     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
9663     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9664     SUCH DAMAGE.
9666  ***********************************************************************/
9668 /* -----[ Tokenizer (constants) ]----- */
9670 var KEYWORDS = array_to_hash([
9671     "break",
9672     "case",
9673     "catch",
9674     "const",
9675     "continue",
9676     "debugger",
9677     "default",
9678     "delete",
9679     "do",
9680     "else",
9681     "finally",
9682     "for",
9683     "function",
9684     "if",
9685     "in",
9686     "instanceof",
9687     "new",
9688     "return",
9689     "switch",
9690     "throw",
9691     "try",
9692     "typeof",
9693     "var",
9694     "void",
9695     "while",
9696     "with"
9699 var RESERVED_WORDS = array_to_hash([
9700     "abstract",
9701     "boolean",
9702     "byte",
9703     "char",
9704     "class",
9705     "double",
9706     "enum",
9707     "export",
9708     "extends",
9709     "final",
9710     "float",
9711     "goto",
9712     "implements",
9713     "import",
9714     "int",
9715     "interface",
9716     "long",
9717     "native",
9718     "package",
9719     "private",
9720     "protected",
9721     "public",
9722     "short",
9723     "static",
9724     "super",
9725     "synchronized",
9726     "throws",
9727     "transient",
9728     "volatile"
9731 var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([
9732     "return",
9733     "new",
9734     "delete",
9735     "throw",
9736     "else",
9737     "case"
9740 var KEYWORDS_ATOM = array_to_hash([
9741     "false",
9742     "null",
9743     "true",
9744     "undefined"
9747 var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^"));
9749 var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
9750 var RE_OCT_NUMBER = /^0[0-7]+$/;
9751 var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
9753 var OPERATORS = array_to_hash([
9754     "in",
9755     "instanceof",
9756     "typeof",
9757     "new",
9758     "void",
9759     "delete",
9760     "++",
9761     "--",
9762     "+",
9763     "-",
9764     "!",
9765     "~",
9766     "&",
9767     "|",
9768     "^",
9769     "*",
9770     "/",
9771     "%",
9772     ">>",
9773     "<<",
9774     ">>>",
9775     "<",
9776     ">",
9777     "<=",
9778     ">=",
9779     "==",
9780     "===",
9781     "!=",
9782     "!==",
9783     "?",
9784     "=",
9785     "+=",
9786     "-=",
9787     "/=",
9788     "*=",
9789     "%=",
9790     ">>=",
9791     "<<=",
9792     ">>>=",
9793     "|=",
9794     "^=",
9795     "&=",
9796     "&&",
9797     "||"
9800 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"));
9802 var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{(,.;:"));
9804 var PUNC_CHARS = array_to_hash(characters("[]{}(),;:"));
9806 var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
9808 /* -----[ Tokenizer ]----- */
9810 var UNICODE = {  // Unicode 6.1
9811     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]"),
9812     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]"),
9813     connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]"),
9814     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]")
9817 function is_letter(ch) {
9818     return UNICODE.letter.test(ch);
9821 function is_digit(ch) {
9822     ch = ch.charCodeAt(0);
9823     return ch >= 48 && ch <= 57;
9826 function is_unicode_digit(ch) {
9827     return UNICODE.digit.test(ch);
9830 function is_alphanumeric_char(ch) {
9831     return is_digit(ch) || is_letter(ch);
9834 function is_unicode_combining_mark(ch) {
9835     return UNICODE.combining_mark.test(ch);
9838 function is_unicode_connector_punctuation(ch) {
9839     return UNICODE.connector_punctuation.test(ch);
9842 function is_identifier_start(ch) {
9843     return ch == "$" || ch == "_" || is_letter(ch);
9846 function is_identifier_char(ch) {
9847     return is_identifier_start(ch)
9848         || is_unicode_combining_mark(ch)
9849         || is_unicode_digit(ch)
9850         || is_unicode_connector_punctuation(ch)
9851         || ch == "\u200c" // zero-width non-joiner <ZWNJ>
9852         || ch == "\u200d" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
9853     ;
9856 function parse_js_number(num) {
9857     if (RE_HEX_NUMBER.test(num)) {
9858         return parseInt(num.substr(2), 16);
9859     } else if (RE_OCT_NUMBER.test(num)) {
9860         return parseInt(num.substr(1), 8);
9861     } else if (RE_DEC_NUMBER.test(num)) {
9862         return parseFloat(num);
9863     }
9866 function JS_Parse_Error(message, line, col, pos) {
9867     this.message = message;
9868     this.line = line + 1;
9869     this.col = col + 1;
9870     this.pos = pos + 1;
9871     this.stack = new Error().stack;
9874 JS_Parse_Error.prototype.toString = function() {
9875     return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
9878 function js_error(message, line, col, pos) {
9879     throw new JS_Parse_Error(message, line, col, pos);
9882 function is_token(token, type, val) {
9883     return token.type == type && (val == null || token.value == val);
9886 var EX_EOF = {};
9888 function tokenizer($TEXT) {
9890     var S = {
9891         text            : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''),
9892         pos             : 0,
9893         tokpos          : 0,
9894         line            : 0,
9895         tokline         : 0,
9896         col             : 0,
9897         tokcol          : 0,
9898         newline_before  : false,
9899         regex_allowed   : false,
9900         comments_before : []
9901     };
9903     function peek() { return S.text.charAt(S.pos); };
9905     function next(signal_eof, in_string) {
9906         var ch = S.text.charAt(S.pos++);
9907         if (signal_eof && !ch)
9908             throw EX_EOF;
9909         if (ch == "\n") {
9910             S.newline_before = S.newline_before || !in_string;
9911             ++S.line;
9912             S.col = 0;
9913         } else {
9914             ++S.col;
9915         }
9916         return ch;
9917     };
9919     function eof() {
9920         return !S.peek();
9921     };
9923     function find(what, signal_eof) {
9924         var pos = S.text.indexOf(what, S.pos);
9925         if (signal_eof && pos == -1) throw EX_EOF;
9926         return pos;
9927     };
9929     function start_token() {
9930         S.tokline = S.line;
9931         S.tokcol = S.col;
9932         S.tokpos = S.pos;
9933     };
9935     function token(type, value, is_comment) {
9936         S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) ||
9937                            (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||
9938                            (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value)));
9939         var ret = {
9940             type   : type,
9941             value  : value,
9942             line   : S.tokline,
9943             col    : S.tokcol,
9944             pos    : S.tokpos,
9945             endpos : S.pos,
9946             nlb    : S.newline_before
9947         };
9948         if (!is_comment) {
9949             ret.comments_before = S.comments_before;
9950             S.comments_before = [];
9951             // make note of any newlines in the comments that came before
9952             for (var i = 0, len = ret.comments_before.length; i < len; i++) {
9953                 ret.nlb = ret.nlb || ret.comments_before[i].nlb;
9954             }
9955         }
9956         S.newline_before = false;
9957         return ret;
9958     };
9960     function skip_whitespace() {
9961         while (HOP(WHITESPACE_CHARS, peek()))
9962             next();
9963     };
9965     function read_while(pred) {
9966         var ret = "", ch = peek(), i = 0;
9967         while (ch && pred(ch, i++)) {
9968             ret += next();
9969             ch = peek();
9970         }
9971         return ret;
9972     };
9974     function parse_error(err) {
9975         js_error(err, S.tokline, S.tokcol, S.tokpos);
9976     };
9978     function read_num(prefix) {
9979         var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
9980         var num = read_while(function(ch, i){
9981             if (ch == "x" || ch == "X") {
9982                 if (has_x) return false;
9983                 return has_x = true;
9984             }
9985             if (!has_x && (ch == "E" || ch == "e")) {
9986                 if (has_e) return false;
9987                 return has_e = after_e = true;
9988             }
9989             if (ch == "-") {
9990                 if (after_e || (i == 0 && !prefix)) return true;
9991                 return false;
9992             }
9993             if (ch == "+") return after_e;
9994             after_e = false;
9995             if (ch == ".") {
9996                 if (!has_dot && !has_x && !has_e)
9997                     return has_dot = true;
9998                 return false;
9999             }
10000             return is_alphanumeric_char(ch);
10001         });
10002         if (prefix)
10003             num = prefix + num;
10004         var valid = parse_js_number(num);
10005         if (!isNaN(valid)) {
10006             return token("num", valid);
10007         } else {
10008             parse_error("Invalid syntax: " + num);
10009         }
10010     };
10012     function read_escaped_char(in_string) {
10013         var ch = next(true, in_string);
10014         switch (ch) {
10015           case "n" : return "\n";
10016           case "r" : return "\r";
10017           case "t" : return "\t";
10018           case "b" : return "\b";
10019           case "v" : return "\u000b";
10020           case "f" : return "\f";
10021           case "0" : return "\0";
10022           case "x" : return String.fromCharCode(hex_bytes(2));
10023           case "u" : return String.fromCharCode(hex_bytes(4));
10024           case "\n": return "";
10025           default  : return ch;
10026         }
10027     };
10029     function hex_bytes(n) {
10030         var num = 0;
10031         for (; n > 0; --n) {
10032             var digit = parseInt(next(true), 16);
10033             if (isNaN(digit))
10034                 parse_error("Invalid hex-character pattern in string");
10035             num = (num << 4) | digit;
10036         }
10037         return num;
10038     };
10040     function read_string() {
10041         return with_eof_error("Unterminated string constant", function(){
10042             var quote = next(), ret = "";
10043             for (;;) {
10044                 var ch = next(true);
10045                 if (ch == "\\") {
10046                     // read OctalEscapeSequence (XXX: deprecated if "strict mode")
10047                     // https://github.com/mishoo/UglifyJS/issues/178
10048                     var octal_len = 0, first = null;
10049                     ch = read_while(function(ch){
10050                         if (ch >= "0" && ch <= "7") {
10051                             if (!first) {
10052                                 first = ch;
10053                                 return ++octal_len;
10054                             }
10055                             else if (first <= "3" && octal_len <= 2) return ++octal_len;
10056                             else if (first >= "4" && octal_len <= 1) return ++octal_len;
10057                         }
10058                         return false;
10059                     });
10060                     if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
10061                     else ch = read_escaped_char(true);
10062                 }
10063                 else if (ch == quote) break;
10064                 else if (ch == "\n") throw EX_EOF;
10065                 ret += ch;
10066             }
10067             return token("string", ret);
10068         });
10069     };
10071     function read_line_comment() {
10072         next();
10073         var i = find("\n"), ret;
10074         if (i == -1) {
10075             ret = S.text.substr(S.pos);
10076             S.pos = S.text.length;
10077         } else {
10078             ret = S.text.substring(S.pos, i);
10079             S.pos = i;
10080         }
10081         return token("comment1", ret, true);
10082     };
10084     function read_multiline_comment() {
10085         next();
10086         return with_eof_error("Unterminated multiline comment", function(){
10087             var i = find("*/", true),
10088             text = S.text.substring(S.pos, i);
10089             S.pos = i + 2;
10090             S.line += text.split("\n").length - 1;
10091             S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
10093             // https://github.com/mishoo/UglifyJS/issues/#issue/100
10094             if (/^@cc_on/i.test(text)) {
10095                 warn("WARNING: at line " + S.line);
10096                 warn("*** Found \"conditional comment\": " + text);
10097                 warn("*** UglifyJS DISCARDS ALL COMMENTS.  This means your code might no longer work properly in Internet Explorer.");
10098             }
10100             return token("comment2", text, true);
10101         });
10102     };
10104     function read_name() {
10105         var backslash = false, name = "", ch, escaped = false, hex;
10106         while ((ch = peek()) != null) {
10107             if (!backslash) {
10108                 if (ch == "\\") escaped = backslash = true, next();
10109                 else if (is_identifier_char(ch)) name += next();
10110                 else break;
10111             }
10112             else {
10113                 if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
10114                 ch = read_escaped_char();
10115                 if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
10116                 name += ch;
10117                 backslash = false;
10118             }
10119         }
10120         if (HOP(KEYWORDS, name) && escaped) {
10121             hex = name.charCodeAt(0).toString(16).toUpperCase();
10122             name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
10123         }
10124         return name;
10125     };
10127     function read_regexp(regexp) {
10128         return with_eof_error("Unterminated regular expression", function(){
10129             var prev_backslash = false, ch, in_class = false;
10130             while ((ch = next(true))) if (prev_backslash) {
10131                 regexp += "\\" + ch;
10132                 prev_backslash = false;
10133             } else if (ch == "[") {
10134                 in_class = true;
10135                 regexp += ch;
10136             } else if (ch == "]" && in_class) {
10137                 in_class = false;
10138                 regexp += ch;
10139             } else if (ch == "/" && !in_class) {
10140                 break;
10141             } else if (ch == "\\") {
10142                 prev_backslash = true;
10143             } else {
10144                 regexp += ch;
10145             }
10146             var mods = read_name();
10147             return token("regexp", [ regexp, mods ]);
10148         });
10149     };
10151     function read_operator(prefix) {
10152         function grow(op) {
10153             if (!peek()) return op;
10154             var bigger = op + peek();
10155             if (HOP(OPERATORS, bigger)) {
10156                 next();
10157                 return grow(bigger);
10158             } else {
10159                 return op;
10160             }
10161         };
10162         return token("operator", grow(prefix || next()));
10163     };
10165     function handle_slash() {
10166         next();
10167         var regex_allowed = S.regex_allowed;
10168         switch (peek()) {
10169           case "/":
10170             S.comments_before.push(read_line_comment());
10171             S.regex_allowed = regex_allowed;
10172             return next_token();
10173           case "*":
10174             S.comments_before.push(read_multiline_comment());
10175             S.regex_allowed = regex_allowed;
10176             return next_token();
10177         }
10178         return S.regex_allowed ? read_regexp("") : read_operator("/");
10179     };
10181     function handle_dot() {
10182         next();
10183         return is_digit(peek())
10184             ? read_num(".")
10185             : token("punc", ".");
10186     };
10188     function read_word() {
10189         var word = read_name();
10190         return !HOP(KEYWORDS, word)
10191             ? token("name", word)
10192             : HOP(OPERATORS, word)
10193             ? token("operator", word)
10194             : HOP(KEYWORDS_ATOM, word)
10195             ? token("atom", word)
10196             : token("keyword", word);
10197     };
10199     function with_eof_error(eof_error, cont) {
10200         try {
10201             return cont();
10202         } catch(ex) {
10203             if (ex === EX_EOF) parse_error(eof_error);
10204             else throw ex;
10205         }
10206     };
10208     function next_token(force_regexp) {
10209         if (force_regexp != null)
10210             return read_regexp(force_regexp);
10211         skip_whitespace();
10212         start_token();
10213         var ch = peek();
10214         if (!ch) return token("eof");
10215         if (is_digit(ch)) return read_num();
10216         if (ch == '"' || ch == "'") return read_string();
10217         if (HOP(PUNC_CHARS, ch)) return token("punc", next());
10218         if (ch == ".") return handle_dot();
10219         if (ch == "/") return handle_slash();
10220         if (HOP(OPERATOR_CHARS, ch)) return read_operator();
10221         if (ch == "\\" || is_identifier_start(ch)) return read_word();
10222         parse_error("Unexpected character '" + ch + "'");
10223     };
10225     next_token.context = function(nc) {
10226         if (nc) S = nc;
10227         return S;
10228     };
10230     return next_token;
10234 /* -----[ Parser (constants) ]----- */
10236 var UNARY_PREFIX = array_to_hash([
10237     "typeof",
10238     "void",
10239     "delete",
10240     "--",
10241     "++",
10242     "!",
10243     "~",
10244     "-",
10245     "+"
10248 var UNARY_POSTFIX = array_to_hash([ "--", "++" ]);
10250 var ASSIGNMENT = (function(a, ret, i){
10251     while (i < a.length) {
10252         ret[a[i]] = a[i].substr(0, a[i].length - 1);
10253         i++;
10254     }
10255     return ret;
10257     ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="],
10258     { "=": true },
10259     0
10262 var PRECEDENCE = (function(a, ret){
10263     for (var i = 0, n = 1; i < a.length; ++i, ++n) {
10264         var b = a[i];
10265         for (var j = 0; j < b.length; ++j) {
10266             ret[b[j]] = n;
10267         }
10268     }
10269     return ret;
10271     [
10272         ["||"],
10273         ["&&"],
10274         ["|"],
10275         ["^"],
10276         ["&"],
10277         ["==", "===", "!=", "!=="],
10278         ["<", ">", "<=", ">=", "in", "instanceof"],
10279         [">>", "<<", ">>>"],
10280         ["+", "-"],
10281         ["*", "/", "%"]
10282     ],
10283     {}
10286 var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
10288 var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
10290 /* -----[ Parser ]----- */
10292 function NodeWithToken(str, start, end) {
10293     this.name = str;
10294     this.start = start;
10295     this.end = end;
10298 NodeWithToken.prototype.toString = function() { return this.name; };
10300 function parse($TEXT, exigent_mode, embed_tokens) {
10302     var S = {
10303         input         : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT,
10304         token         : null,
10305         prev          : null,
10306         peeked        : null,
10307         in_function   : 0,
10308         in_directives : true,
10309         in_loop       : 0,
10310         labels        : []
10311     };
10313     S.token = next();
10315     function is(type, value) {
10316         return is_token(S.token, type, value);
10317     };
10319     function peek() { return S.peeked || (S.peeked = S.input()); };
10321     function next() {
10322         S.prev = S.token;
10323         if (S.peeked) {
10324             S.token = S.peeked;
10325             S.peeked = null;
10326         } else {
10327             S.token = S.input();
10328         }
10329         S.in_directives = S.in_directives && (
10330             S.token.type == "string" || is("punc", ";")
10331         );
10332         return S.token;
10333     };
10335     function prev() {
10336         return S.prev;
10337     };
10339     function croak(msg, line, col, pos) {
10340         var ctx = S.input.context();
10341         js_error(msg,
10342                  line != null ? line : ctx.tokline,
10343                  col != null ? col : ctx.tokcol,
10344                  pos != null ? pos : ctx.tokpos);
10345     };
10347     function token_error(token, msg) {
10348         croak(msg, token.line, token.col);
10349     };
10351     function unexpected(token) {
10352         if (token == null)
10353             token = S.token;
10354         token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
10355     };
10357     function expect_token(type, val) {
10358         if (is(type, val)) {
10359             return next();
10360         }
10361         token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type);
10362     };
10364     function expect(punc) { return expect_token("punc", punc); };
10366     function can_insert_semicolon() {
10367         return !exigent_mode && (
10368             S.token.nlb || is("eof") || is("punc", "}")
10369         );
10370     };
10372     function semicolon() {
10373         if (is("punc", ";")) next();
10374         else if (!can_insert_semicolon()) unexpected();
10375     };
10377     function as() {
10378         return slice(arguments);
10379     };
10381     function parenthesised() {
10382         expect("(");
10383         var ex = expression();
10384         expect(")");
10385         return ex;
10386     };
10388     function add_tokens(str, start, end) {
10389         return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);
10390     };
10392     function maybe_embed_tokens(parser) {
10393         if (embed_tokens) return function() {
10394             var start = S.token;
10395             var ast = parser.apply(this, arguments);
10396             ast[0] = add_tokens(ast[0], start, prev());
10397             return ast;
10398         };
10399         else return parser;
10400     };
10402     var statement = maybe_embed_tokens(function() {
10403         if (is("operator", "/") || is("operator", "/=")) {
10404             S.peeked = null;
10405             S.token = S.input(S.token.value.substr(1)); // force regexp
10406         }
10407         switch (S.token.type) {
10408           case "string":
10409             var dir = S.in_directives, stat = simple_statement();
10410             if (dir && stat[1][0] == "string" && !is("punc", ","))
10411                 return as("directive", stat[1][1]);
10412             return stat;
10413           case "num":
10414           case "regexp":
10415           case "operator":
10416           case "atom":
10417             return simple_statement();
10419           case "name":
10420             return is_token(peek(), "punc", ":")
10421                 ? labeled_statement(prog1(S.token.value, next, next))
10422                 : simple_statement();
10424           case "punc":
10425             switch (S.token.value) {
10426               case "{":
10427                 return as("block", block_());
10428               case "[":
10429               case "(":
10430                 return simple_statement();
10431               case ";":
10432                 next();
10433                 return as("block");
10434               default:
10435                 unexpected();
10436             }
10438           case "keyword":
10439             switch (prog1(S.token.value, next)) {
10440               case "break":
10441                 return break_cont("break");
10443               case "continue":
10444                 return break_cont("continue");
10446               case "debugger":
10447                 semicolon();
10448                 return as("debugger");
10450               case "do":
10451                 return (function(body){
10452                     expect_token("keyword", "while");
10453                     return as("do", prog1(parenthesised, semicolon), body);
10454                 })(in_loop(statement));
10456               case "for":
10457                 return for_();
10459               case "function":
10460                 return function_(true);
10462               case "if":
10463                 return if_();
10465               case "return":
10466                 if (S.in_function == 0)
10467                     croak("'return' outside of function");
10468                 return as("return",
10469                           is("punc", ";")
10470                           ? (next(), null)
10471                           : can_insert_semicolon()
10472                           ? null
10473                           : prog1(expression, semicolon));
10475               case "switch":
10476                 return as("switch", parenthesised(), switch_block_());
10478               case "throw":
10479                 if (S.token.nlb)
10480                     croak("Illegal newline after 'throw'");
10481                 return as("throw", prog1(expression, semicolon));
10483               case "try":
10484                 return try_();
10486               case "var":
10487                 return prog1(var_, semicolon);
10489               case "const":
10490                 return prog1(const_, semicolon);
10492               case "while":
10493                 return as("while", parenthesised(), in_loop(statement));
10495               case "with":
10496                 return as("with", parenthesised(), statement());
10498               default:
10499                 unexpected();
10500             }
10501         }
10502     });
10504     function labeled_statement(label) {
10505         S.labels.push(label);
10506         var start = S.token, stat = statement();
10507         if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
10508             unexpected(start);
10509         S.labels.pop();
10510         return as("label", label, stat);
10511     };
10513     function simple_statement() {
10514         return as("stat", prog1(expression, semicolon));
10515     };
10517     function break_cont(type) {
10518         var name;
10519         if (!can_insert_semicolon()) {
10520             name = is("name") ? S.token.value : null;
10521         }
10522         if (name != null) {
10523             next();
10524             if (!member(name, S.labels))
10525                 croak("Label " + name + " without matching loop or statement");
10526         }
10527         else if (S.in_loop == 0)
10528             croak(type + " not inside a loop or switch");
10529         semicolon();
10530         return as(type, name);
10531     };
10533     function for_() {
10534         expect("(");
10535         var init = null;
10536         if (!is("punc", ";")) {
10537             init = is("keyword", "var")
10538                 ? (next(), var_(true))
10539                 : expression(true, true);
10540             if (is("operator", "in")) {
10541                 if (init[0] == "var" && init[1].length > 1)
10542                     croak("Only one variable declaration allowed in for..in loop");
10543                 return for_in(init);
10544             }
10545         }
10546         return regular_for(init);
10547     };
10549     function regular_for(init) {
10550         expect(";");
10551         var test = is("punc", ";") ? null : expression();
10552         expect(";");
10553         var step = is("punc", ")") ? null : expression();
10554         expect(")");
10555         return as("for", init, test, step, in_loop(statement));
10556     };
10558     function for_in(init) {
10559         var lhs = init[0] == "var" ? as("name", init[1][0]) : init;
10560         next();
10561         var obj = expression();
10562         expect(")");
10563         return as("for-in", init, lhs, obj, in_loop(statement));
10564     };
10566     var function_ = function(in_statement) {
10567         var name = is("name") ? prog1(S.token.value, next) : null;
10568         if (in_statement && !name)
10569             unexpected();
10570         expect("(");
10571         return as(in_statement ? "defun" : "function",
10572                   name,
10573                   // arguments
10574                   (function(first, a){
10575                       while (!is("punc", ")")) {
10576                           if (first) first = false; else expect(",");
10577                           if (!is("name")) unexpected();
10578                           a.push(S.token.value);
10579                           next();
10580                       }
10581                       next();
10582                       return a;
10583                   })(true, []),
10584                   // body
10585                   (function(){
10586                       ++S.in_function;
10587                       var loop = S.in_loop;
10588                       S.in_directives = true;
10589                       S.in_loop = 0;
10590                       var a = block_();
10591                       --S.in_function;
10592                       S.in_loop = loop;
10593                       return a;
10594                   })());
10595     };
10597     function if_() {
10598         var cond = parenthesised(), body = statement(), belse;
10599         if (is("keyword", "else")) {
10600             next();
10601             belse = statement();
10602         }
10603         return as("if", cond, body, belse);
10604     };
10606     function block_() {
10607         expect("{");
10608         var a = [];
10609         while (!is("punc", "}")) {
10610             if (is("eof")) unexpected();
10611             a.push(statement());
10612         }
10613         next();
10614         return a;
10615     };
10617     var switch_block_ = curry(in_loop, function(){
10618         expect("{");
10619         var a = [], cur = null;
10620         while (!is("punc", "}")) {
10621             if (is("eof")) unexpected();
10622             if (is("keyword", "case")) {
10623                 next();
10624                 cur = [];
10625                 a.push([ expression(), cur ]);
10626                 expect(":");
10627             }
10628             else if (is("keyword", "default")) {
10629                 next();
10630                 expect(":");
10631                 cur = [];
10632                 a.push([ null, cur ]);
10633             }
10634             else {
10635                 if (!cur) unexpected();
10636                 cur.push(statement());
10637             }
10638         }
10639         next();
10640         return a;
10641     });
10643     function try_() {
10644         var body = block_(), bcatch, bfinally;
10645         if (is("keyword", "catch")) {
10646             next();
10647             expect("(");
10648             if (!is("name"))
10649                 croak("Name expected");
10650             var name = S.token.value;
10651             next();
10652             expect(")");
10653             bcatch = [ name, block_() ];
10654         }
10655         if (is("keyword", "finally")) {
10656             next();
10657             bfinally = block_();
10658         }
10659         if (!bcatch && !bfinally)
10660             croak("Missing catch/finally blocks");
10661         return as("try", body, bcatch, bfinally);
10662     };
10664     function vardefs(no_in) {
10665         var a = [];
10666         for (;;) {
10667             if (!is("name"))
10668                 unexpected();
10669             var name = S.token.value;
10670             next();
10671             if (is("operator", "=")) {
10672                 next();
10673                 a.push([ name, expression(false, no_in) ]);
10674             } else {
10675                 a.push([ name ]);
10676             }
10677             if (!is("punc", ","))
10678                 break;
10679             next();
10680         }
10681         return a;
10682     };
10684     function var_(no_in) {
10685         return as("var", vardefs(no_in));
10686     };
10688     function const_() {
10689         return as("const", vardefs());
10690     };
10692     function new_() {
10693         var newexp = expr_atom(false), args;
10694         if (is("punc", "(")) {
10695             next();
10696             args = expr_list(")");
10697         } else {
10698             args = [];
10699         }
10700         return subscripts(as("new", newexp, args), true);
10701     };
10703     var expr_atom = maybe_embed_tokens(function(allow_calls) {
10704         if (is("operator", "new")) {
10705             next();
10706             return new_();
10707         }
10708         if (is("punc")) {
10709             switch (S.token.value) {
10710               case "(":
10711                 next();
10712                 return subscripts(prog1(expression, curry(expect, ")")), allow_calls);
10713               case "[":
10714                 next();
10715                 return subscripts(array_(), allow_calls);
10716               case "{":
10717                 next();
10718                 return subscripts(object_(), allow_calls);
10719             }
10720             unexpected();
10721         }
10722         if (is("keyword", "function")) {
10723             next();
10724             return subscripts(function_(false), allow_calls);
10725         }
10726         if (HOP(ATOMIC_START_TOKEN, S.token.type)) {
10727             var atom = S.token.type == "regexp"
10728                 ? as("regexp", S.token.value[0], S.token.value[1])
10729                 : as(S.token.type, S.token.value);
10730             return subscripts(prog1(atom, next), allow_calls);
10731         }
10732         unexpected();
10733     });
10735     function expr_list(closing, allow_trailing_comma, allow_empty) {
10736         var first = true, a = [];
10737         while (!is("punc", closing)) {
10738             if (first) first = false; else expect(",");
10739             if (allow_trailing_comma && is("punc", closing)) break;
10740             if (is("punc", ",") && allow_empty) {
10741                 a.push([ "atom", "undefined" ]);
10742             } else {
10743                 a.push(expression(false));
10744             }
10745         }
10746         next();
10747         return a;
10748     };
10750     function array_() {
10751         return as("array", expr_list("]", !exigent_mode, true));
10752     };
10754     function object_() {
10755         var first = true, a = [];
10756         while (!is("punc", "}")) {
10757             if (first) first = false; else expect(",");
10758             if (!exigent_mode && is("punc", "}"))
10759                 // allow trailing comma
10760                 break;
10761             var type = S.token.type;
10762             var name = as_property_name();
10763             if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) {
10764                 a.push([ as_name(), function_(false), name ]);
10765             } else {
10766                 expect(":");
10767                 a.push([ name, expression(false) ]);
10768             }
10769         }
10770         next();
10771         return as("object", a);
10772     };
10774     function as_property_name() {
10775         switch (S.token.type) {
10776           case "num":
10777           case "string":
10778             return prog1(S.token.value, next);
10779         }
10780         return as_name();
10781     };
10783     function as_name() {
10784         switch (S.token.type) {
10785           case "name":
10786           case "operator":
10787           case "keyword":
10788           case "atom":
10789             return prog1(S.token.value, next);
10790           default:
10791             unexpected();
10792         }
10793     };
10795     function subscripts(expr, allow_calls) {
10796         if (is("punc", ".")) {
10797             next();
10798             return subscripts(as("dot", expr, as_name()), allow_calls);
10799         }
10800         if (is("punc", "[")) {
10801             next();
10802             return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls);
10803         }
10804         if (allow_calls && is("punc", "(")) {
10805             next();
10806             return subscripts(as("call", expr, expr_list(")")), true);
10807         }
10808         return expr;
10809     };
10811     function maybe_unary(allow_calls) {
10812         if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) {
10813             return make_unary("unary-prefix",
10814                               prog1(S.token.value, next),
10815                               maybe_unary(allow_calls));
10816         }
10817         var val = expr_atom(allow_calls);
10818         while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) {
10819             val = make_unary("unary-postfix", S.token.value, val);
10820             next();
10821         }
10822         return val;
10823     };
10825     function make_unary(tag, op, expr) {
10826         if ((op == "++" || op == "--") && !is_assignable(expr))
10827             croak("Invalid use of " + op + " operator");
10828         return as(tag, op, expr);
10829     };
10831     function expr_op(left, min_prec, no_in) {
10832         var op = is("operator") ? S.token.value : null;
10833         if (op && op == "in" && no_in) op = null;
10834         var prec = op != null ? PRECEDENCE[op] : null;
10835         if (prec != null && prec > min_prec) {
10836             next();
10837             var right = expr_op(maybe_unary(true), prec, no_in);
10838             return expr_op(as("binary", op, left, right), min_prec, no_in);
10839         }
10840         return left;
10841     };
10843     function expr_ops(no_in) {
10844         return expr_op(maybe_unary(true), 0, no_in);
10845     };
10847     function maybe_conditional(no_in) {
10848         var expr = expr_ops(no_in);
10849         if (is("operator", "?")) {
10850             next();
10851             var yes = expression(false);
10852             expect(":");
10853             return as("conditional", expr, yes, expression(false, no_in));
10854         }
10855         return expr;
10856     };
10858     function is_assignable(expr) {
10859         if (!exigent_mode) return true;
10860         switch (expr[0]+"") {
10861           case "dot":
10862           case "sub":
10863           case "new":
10864           case "call":
10865             return true;
10866           case "name":
10867             return expr[1] != "this";
10868         }
10869     };
10871     function maybe_assign(no_in) {
10872         var left = maybe_conditional(no_in), val = S.token.value;
10873         if (is("operator") && HOP(ASSIGNMENT, val)) {
10874             if (is_assignable(left)) {
10875                 next();
10876                 return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in));
10877             }
10878             croak("Invalid assignment");
10879         }
10880         return left;
10881     };
10883     var expression = maybe_embed_tokens(function(commas, no_in) {
10884         if (arguments.length == 0)
10885             commas = true;
10886         var expr = maybe_assign(no_in);
10887         if (commas && is("punc", ",")) {
10888             next();
10889             return as("seq", expr, expression(true, no_in));
10890         }
10891         return expr;
10892     });
10894     function in_loop(cont) {
10895         try {
10896             ++S.in_loop;
10897             return cont();
10898         } finally {
10899             --S.in_loop;
10900         }
10901     };
10903     return as("toplevel", (function(a){
10904         while (!is("eof"))
10905             a.push(statement());
10906         return a;
10907     })([]));
10911 /* -----[ Utilities ]----- */
10913 function curry(f) {
10914     var args = slice(arguments, 1);
10915     return function() { return f.apply(this, args.concat(slice(arguments))); };
10918 function prog1(ret) {
10919     if (ret instanceof Function)
10920         ret = ret();
10921     for (var i = 1, n = arguments.length; --n > 0; ++i)
10922         arguments[i]();
10923     return ret;
10926 function array_to_hash(a) {
10927     var ret = {};
10928     for (var i = 0; i < a.length; ++i)
10929         ret[a[i]] = true;
10930     return ret;
10933 function slice(a, start) {
10934     return Array.prototype.slice.call(a, start || 0);
10937 function characters(str) {
10938     return str.split("");
10941 function member(name, array) {
10942     for (var i = array.length; --i >= 0;)
10943         if (array[i] == name)
10944             return true;
10945     return false;
10948 function HOP(obj, prop) {
10949     return Object.prototype.hasOwnProperty.call(obj, prop);
10952 var warn = function() {};
10954 /* -----[ Exports ]----- */
10956 exports.tokenizer = tokenizer;
10957 exports.parse = parse;
10958 exports.slice = slice;
10959 exports.curry = curry;
10960 exports.member = member;
10961 exports.array_to_hash = array_to_hash;
10962 exports.PRECEDENCE = PRECEDENCE;
10963 exports.KEYWORDS_ATOM = KEYWORDS_ATOM;
10964 exports.RESERVED_WORDS = RESERVED_WORDS;
10965 exports.KEYWORDS = KEYWORDS;
10966 exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;
10967 exports.OPERATORS = OPERATORS;
10968 exports.is_alphanumeric_char = is_alphanumeric_char;
10969 exports.is_identifier_start = is_identifier_start;
10970 exports.is_identifier_char = is_identifier_char;
10971 exports.set_logger = function(logger) {
10972     warn = logger;
10975 // Local variables:
10976 // js-indent-level: 4
10977 // End:
10978 });define('uglifyjs/squeeze-more', ["require", "exports", "module", "./parse-js", "./squeeze-more"], function(require, exports, module) {
10979 var jsp = require("./parse-js"),
10980     pro = require("./process"),
10981     slice = jsp.slice,
10982     member = jsp.member,
10983     curry = jsp.curry,
10984     MAP = pro.MAP,
10985     PRECEDENCE = jsp.PRECEDENCE,
10986     OPERATORS = jsp.OPERATORS;
10988 function ast_squeeze_more(ast) {
10989     var w = pro.ast_walker(), walk = w.walk, scope;
10990     function with_scope(s, cont) {
10991         var save = scope, ret;
10992         scope = s;
10993         ret = cont();
10994         scope = save;
10995         return ret;
10996     };
10997     function _lambda(name, args, body) {
10998         return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];
10999     };
11000     return w.with_walkers({
11001         "toplevel": function(body) {
11002             return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];
11003         },
11004         "function": _lambda,
11005         "defun": _lambda,
11006         "new": function(ctor, args) {
11007             if (ctor[0] == "name") {
11008                 if (ctor[1] == "Array" && !scope.has("Array")) {
11009                     if (args.length != 1) {
11010                         return [ "array", args ];
11011                     } else {
11012                         return walk([ "call", [ "name", "Array" ], args ]);
11013                     }
11014                 } else if (ctor[1] == "Object" && !scope.has("Object")) {
11015                     if (!args.length) {
11016                         return [ "object", [] ];
11017                     } else {
11018                         return walk([ "call", [ "name", "Object" ], args ]);
11019                     }
11020                 } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) {
11021                     return walk([ "call", [ "name", ctor[1] ], args]);
11022                 }
11023             }
11024         },
11025         "call": function(expr, args) {
11026             if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1
11027                 && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) {
11028                 return [ "call", [ "dot", expr[1], "slice"], args];
11029             }
11030             if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
11031                 // foo.toString()  ==>  foo+""
11032                 if (expr[1][0] == "string") return expr[1];
11033                 return [ "binary", "+", expr[1], [ "string", "" ]];
11034             }
11035             if (expr[0] == "name") {
11036                 if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
11037                     return [ "array", args ];
11038                 }
11039                 if (expr[1] == "Object" && !args.length && !scope.has("Object")) {
11040                     return [ "object", [] ];
11041                 }
11042                 if (expr[1] == "String" && !scope.has("String")) {
11043                     return [ "binary", "+", args[0], [ "string", "" ]];
11044                 }
11045             }
11046         }
11047     }, function() {
11048         return walk(pro.ast_add_scope(ast));
11049     });
11052 exports.ast_squeeze_more = ast_squeeze_more;
11054 // Local variables:
11055 // js-indent-level: 4
11056 // End:
11058 define('uglifyjs/process', ["require", "exports", "module", "./parse-js", "./squeeze-more"], function(require, exports, module) {
11059 /***********************************************************************
11061   A JavaScript tokenizer / parser / beautifier / compressor.
11063   This version is suitable for Node.js.  With minimal changes (the
11064   exports stuff) it should work on any JS platform.
11066   This file implements some AST processors.  They work on data built
11067   by parse-js.
11069   Exported functions:
11071     - ast_mangle(ast, options) -- mangles the variable/function names
11072       in the AST.  Returns an AST.
11074     - ast_squeeze(ast) -- employs various optimizations to make the
11075       final generated code even smaller.  Returns an AST.
11077     - gen_code(ast, options) -- generates JS code from the AST.  Pass
11078       true (or an object, see the code for some options) as second
11079       argument to get "pretty" (indented) code.
11081   -------------------------------- (C) ---------------------------------
11083                            Author: Mihai Bazon
11084                          <mihai.bazon@gmail.com>
11085                        http://mihai.bazon.net/blog
11087   Distributed under the BSD license:
11089     Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
11091     Redistribution and use in source and binary forms, with or without
11092     modification, are permitted provided that the following conditions
11093     are met:
11095         * Redistributions of source code must retain the above
11096           copyright notice, this list of conditions and the following
11097           disclaimer.
11099         * Redistributions in binary form must reproduce the above
11100           copyright notice, this list of conditions and the following
11101           disclaimer in the documentation and/or other materials
11102           provided with the distribution.
11104     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
11105     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
11106     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
11107     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
11108     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
11109     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
11110     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
11111     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11112     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
11113     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
11114     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
11115     SUCH DAMAGE.
11117  ***********************************************************************/
11119 var jsp = require("./parse-js"),
11120     curry = jsp.curry,
11121     slice = jsp.slice,
11122     member = jsp.member,
11123     is_identifier_char = jsp.is_identifier_char,
11124     PRECEDENCE = jsp.PRECEDENCE,
11125     OPERATORS = jsp.OPERATORS;
11127 /* -----[ helper for AST traversal ]----- */
11129 function ast_walker() {
11130     function _vardefs(defs) {
11131         return [ this[0], MAP(defs, function(def){
11132             var a = [ def[0] ];
11133             if (def.length > 1)
11134                 a[1] = walk(def[1]);
11135             return a;
11136         }) ];
11137     };
11138     function _block(statements) {
11139         var out = [ this[0] ];
11140         if (statements != null)
11141             out.push(MAP(statements, walk));
11142         return out;
11143     };
11144     var walkers = {
11145         "string": function(str) {
11146             return [ this[0], str ];
11147         },
11148         "num": function(num) {
11149             return [ this[0], num ];
11150         },
11151         "name": function(name) {
11152             return [ this[0], name ];
11153         },
11154         "toplevel": function(statements) {
11155             return [ this[0], MAP(statements, walk) ];
11156         },
11157         "block": _block,
11158         "splice": _block,
11159         "var": _vardefs,
11160         "const": _vardefs,
11161         "try": function(t, c, f) {
11162             return [
11163                 this[0],
11164                 MAP(t, walk),
11165                 c != null ? [ c[0], MAP(c[1], walk) ] : null,
11166                 f != null ? MAP(f, walk) : null
11167             ];
11168         },
11169         "throw": function(expr) {
11170             return [ this[0], walk(expr) ];
11171         },
11172         "new": function(ctor, args) {
11173             return [ this[0], walk(ctor), MAP(args, walk) ];
11174         },
11175         "switch": function(expr, body) {
11176             return [ this[0], walk(expr), MAP(body, function(branch){
11177                 return [ branch[0] ? walk(branch[0]) : null,
11178                          MAP(branch[1], walk) ];
11179             }) ];
11180         },
11181         "break": function(label) {
11182             return [ this[0], label ];
11183         },
11184         "continue": function(label) {
11185             return [ this[0], label ];
11186         },
11187         "conditional": function(cond, t, e) {
11188             return [ this[0], walk(cond), walk(t), walk(e) ];
11189         },
11190         "assign": function(op, lvalue, rvalue) {
11191             return [ this[0], op, walk(lvalue), walk(rvalue) ];
11192         },
11193         "dot": function(expr) {
11194             return [ this[0], walk(expr) ].concat(slice(arguments, 1));
11195         },
11196         "call": function(expr, args) {
11197             return [ this[0], walk(expr), MAP(args, walk) ];
11198         },
11199         "function": function(name, args, body) {
11200             return [ this[0], name, args.slice(), MAP(body, walk) ];
11201         },
11202         "debugger": function() {
11203             return [ this[0] ];
11204         },
11205         "defun": function(name, args, body) {
11206             return [ this[0], name, args.slice(), MAP(body, walk) ];
11207         },
11208         "if": function(conditional, t, e) {
11209             return [ this[0], walk(conditional), walk(t), walk(e) ];
11210         },
11211         "for": function(init, cond, step, block) {
11212             return [ this[0], walk(init), walk(cond), walk(step), walk(block) ];
11213         },
11214         "for-in": function(vvar, key, hash, block) {
11215             return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ];
11216         },
11217         "while": function(cond, block) {
11218             return [ this[0], walk(cond), walk(block) ];
11219         },
11220         "do": function(cond, block) {
11221             return [ this[0], walk(cond), walk(block) ];
11222         },
11223         "return": function(expr) {
11224             return [ this[0], walk(expr) ];
11225         },
11226         "binary": function(op, left, right) {
11227             return [ this[0], op, walk(left), walk(right) ];
11228         },
11229         "unary-prefix": function(op, expr) {
11230             return [ this[0], op, walk(expr) ];
11231         },
11232         "unary-postfix": function(op, expr) {
11233             return [ this[0], op, walk(expr) ];
11234         },
11235         "sub": function(expr, subscript) {
11236             return [ this[0], walk(expr), walk(subscript) ];
11237         },
11238         "object": function(props) {
11239             return [ this[0], MAP(props, function(p){
11240                 return p.length == 2
11241                     ? [ p[0], walk(p[1]) ]
11242                     : [ p[0], walk(p[1]), p[2] ]; // get/set-ter
11243             }) ];
11244         },
11245         "regexp": function(rx, mods) {
11246             return [ this[0], rx, mods ];
11247         },
11248         "array": function(elements) {
11249             return [ this[0], MAP(elements, walk) ];
11250         },
11251         "stat": function(stat) {
11252             return [ this[0], walk(stat) ];
11253         },
11254         "seq": function() {
11255             return [ this[0] ].concat(MAP(slice(arguments), walk));
11256         },
11257         "label": function(name, block) {
11258             return [ this[0], name, walk(block) ];
11259         },
11260         "with": function(expr, block) {
11261             return [ this[0], walk(expr), walk(block) ];
11262         },
11263         "atom": function(name) {
11264             return [ this[0], name ];
11265         },
11266         "directive": function(dir) {
11267             return [ this[0], dir ];
11268         }
11269     };
11271     var user = {};
11272     var stack = [];
11273     function walk(ast) {
11274         if (ast == null)
11275             return null;
11276         try {
11277             stack.push(ast);
11278             var type = ast[0];
11279             var gen = user[type];
11280             if (gen) {
11281                 var ret = gen.apply(ast, ast.slice(1));
11282                 if (ret != null)
11283                     return ret;
11284             }
11285             gen = walkers[type];
11286             return gen.apply(ast, ast.slice(1));
11287         } finally {
11288             stack.pop();
11289         }
11290     };
11292     function dive(ast) {
11293         if (ast == null)
11294             return null;
11295         try {
11296             stack.push(ast);
11297             return walkers[ast[0]].apply(ast, ast.slice(1));
11298         } finally {
11299             stack.pop();
11300         }
11301     };
11303     function with_walkers(walkers, cont){
11304         var save = {}, i;
11305         for (i in walkers) if (HOP(walkers, i)) {
11306             save[i] = user[i];
11307             user[i] = walkers[i];
11308         }
11309         var ret = cont();
11310         for (i in save) if (HOP(save, i)) {
11311             if (!save[i]) delete user[i];
11312             else user[i] = save[i];
11313         }
11314         return ret;
11315     };
11317     return {
11318         walk: walk,
11319         dive: dive,
11320         with_walkers: with_walkers,
11321         parent: function() {
11322             return stack[stack.length - 2]; // last one is current node
11323         },
11324         stack: function() {
11325             return stack;
11326         }
11327     };
11330 /* -----[ Scope and mangling ]----- */
11332 function Scope(parent) {
11333     this.names = {};        // names defined in this scope
11334     this.mangled = {};      // mangled names (orig.name => mangled)
11335     this.rev_mangled = {};  // reverse lookup (mangled => orig.name)
11336     this.cname = -1;        // current mangled name
11337     this.refs = {};         // names referenced from this scope
11338     this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes
11339     this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes
11340     this.directives = [];   // directives activated from this scope
11341     this.parent = parent;   // parent scope
11342     this.children = [];     // sub-scopes
11343     if (parent) {
11344         this.level = parent.level + 1;
11345         parent.children.push(this);
11346     } else {
11347         this.level = 0;
11348     }
11351 function base54_digits() {
11352     if (typeof DIGITS_OVERRIDE_FOR_TESTING != "undefined")
11353         return DIGITS_OVERRIDE_FOR_TESTING;
11354     else
11355         return "etnrisouaflchpdvmgybwESxTNCkLAOM_DPHBjFIqRUzWXV$JKQGYZ0516372984";
11358 var base54 = (function(){
11359     var DIGITS = base54_digits();
11360     return function(num) {
11361         var ret = "", base = 54;
11362         do {
11363             ret += DIGITS.charAt(num % base);
11364             num = Math.floor(num / base);
11365             base = 64;
11366         } while (num > 0);
11367         return ret;
11368     };
11369 })();
11371 Scope.prototype = {
11372     has: function(name) {
11373         for (var s = this; s; s = s.parent)
11374             if (HOP(s.names, name))
11375                 return s;
11376     },
11377     has_mangled: function(mname) {
11378         for (var s = this; s; s = s.parent)
11379             if (HOP(s.rev_mangled, mname))
11380                 return s;
11381     },
11382     toJSON: function() {
11383         return {
11384             names: this.names,
11385             uses_eval: this.uses_eval,
11386             uses_with: this.uses_with
11387         };
11388     },
11390     next_mangled: function() {
11391         // we must be careful that the new mangled name:
11392         //
11393         // 1. doesn't shadow a mangled name from a parent
11394         //    scope, unless we don't reference the original
11395         //    name from this scope OR from any sub-scopes!
11396         //    This will get slow.
11397         //
11398         // 2. doesn't shadow an original name from a parent
11399         //    scope, in the event that the name is not mangled
11400         //    in the parent scope and we reference that name
11401         //    here OR IN ANY SUBSCOPES!
11402         //
11403         // 3. doesn't shadow a name that is referenced but not
11404         //    defined (possibly global defined elsewhere).
11405         for (;;) {
11406             var m = base54(++this.cname), prior;
11408             // case 1.
11409             prior = this.has_mangled(m);
11410             if (prior && this.refs[prior.rev_mangled[m]] === prior)
11411                 continue;
11413             // case 2.
11414             prior = this.has(m);
11415             if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m))
11416                 continue;
11418             // case 3.
11419             if (HOP(this.refs, m) && this.refs[m] == null)
11420                 continue;
11422             // I got "do" once. :-/
11423             if (!is_identifier(m))
11424                 continue;
11426             return m;
11427         }
11428     },
11429     set_mangle: function(name, m) {
11430         this.rev_mangled[m] = name;
11431         return this.mangled[name] = m;
11432     },
11433     get_mangled: function(name, newMangle) {
11434         if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use
11435         var s = this.has(name);
11436         if (!s) return name; // not in visible scope, no mangle
11437         if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope
11438         if (!newMangle) return name;                      // not found and no mangling requested
11439         return s.set_mangle(name, s.next_mangled());
11440     },
11441     references: function(name) {
11442         return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name];
11443     },
11444     define: function(name, type) {
11445         if (name != null) {
11446             if (type == "var" || !HOP(this.names, name))
11447                 this.names[name] = type || "var";
11448             return name;
11449         }
11450     },
11451     active_directive: function(dir) {
11452         return member(dir, this.directives) || this.parent && this.parent.active_directive(dir);
11453     }
11456 function ast_add_scope(ast) {
11458     var current_scope = null;
11459     var w = ast_walker(), walk = w.walk;
11460     var having_eval = [];
11462     function with_new_scope(cont) {
11463         current_scope = new Scope(current_scope);
11464         current_scope.labels = new Scope();
11465         var ret = current_scope.body = cont();
11466         ret.scope = current_scope;
11467         current_scope = current_scope.parent;
11468         return ret;
11469     };
11471     function define(name, type) {
11472         return current_scope.define(name, type);
11473     };
11475     function reference(name) {
11476         current_scope.refs[name] = true;
11477     };
11479     function _lambda(name, args, body) {
11480         var is_defun = this[0] == "defun";
11481         return [ this[0], is_defun ? define(name, "defun") : name, args, with_new_scope(function(){
11482             if (!is_defun) define(name, "lambda");
11483             MAP(args, function(name){ define(name, "arg") });
11484             return MAP(body, walk);
11485         })];
11486     };
11488     function _vardefs(type) {
11489         return function(defs) {
11490             MAP(defs, function(d){
11491                 define(d[0], type);
11492                 if (d[1]) reference(d[0]);
11493             });
11494         };
11495     };
11497     function _breacont(label) {
11498         if (label)
11499             current_scope.labels.refs[label] = true;
11500     };
11502     return with_new_scope(function(){
11503         // process AST
11504         var ret = w.with_walkers({
11505             "function": _lambda,
11506             "defun": _lambda,
11507             "label": function(name, stat) { current_scope.labels.define(name) },
11508             "break": _breacont,
11509             "continue": _breacont,
11510             "with": function(expr, block) {
11511                 for (var s = current_scope; s; s = s.parent)
11512                     s.uses_with = true;
11513             },
11514             "var": _vardefs("var"),
11515             "const": _vardefs("const"),
11516             "try": function(t, c, f) {
11517                 if (c != null) return [
11518                     this[0],
11519                     MAP(t, walk),
11520                     [ define(c[0], "catch"), MAP(c[1], walk) ],
11521                     f != null ? MAP(f, walk) : null
11522                 ];
11523             },
11524             "name": function(name) {
11525                 if (name == "eval")
11526                     having_eval.push(current_scope);
11527                 reference(name);
11528             }
11529         }, function(){
11530             return walk(ast);
11531         });
11533         // the reason why we need an additional pass here is
11534         // that names can be used prior to their definition.
11536         // scopes where eval was detected and their parents
11537         // are marked with uses_eval, unless they define the
11538         // "eval" name.
11539         MAP(having_eval, function(scope){
11540             if (!scope.has("eval")) while (scope) {
11541                 scope.uses_eval = true;
11542                 scope = scope.parent;
11543             }
11544         });
11546         // for referenced names it might be useful to know
11547         // their origin scope.  current_scope here is the
11548         // toplevel one.
11549         function fixrefs(scope, i) {
11550             // do children first; order shouldn't matter
11551             for (i = scope.children.length; --i >= 0;)
11552                 fixrefs(scope.children[i]);
11553             for (i in scope.refs) if (HOP(scope.refs, i)) {
11554                 // find origin scope and propagate the reference to origin
11555                 for (var origin = scope.has(i), s = scope; s; s = s.parent) {
11556                     s.refs[i] = origin;
11557                     if (s === origin) break;
11558                 }
11559             }
11560         };
11561         fixrefs(current_scope);
11563         return ret;
11564     });
11568 /* -----[ mangle names ]----- */
11570 function ast_mangle(ast, options) {
11571     var w = ast_walker(), walk = w.walk, scope;
11572     options = defaults(options, {
11573         mangle       : true,
11574         toplevel     : false,
11575         defines      : null,
11576         except       : null,
11577         no_functions : false
11578     });
11580     function get_mangled(name, newMangle) {
11581         if (!options.mangle) return name;
11582         if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel
11583         if (options.except && member(name, options.except))
11584             return name;
11585         if (options.no_functions && HOP(scope.names, name) &&
11586             (scope.names[name] == 'defun' || scope.names[name] == 'lambda'))
11587             return name;
11588         return scope.get_mangled(name, newMangle);
11589     };
11591     function get_define(name) {
11592         if (options.defines) {
11593             // we always lookup a defined symbol for the current scope FIRST, so declared
11594             // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value
11595             if (!scope.has(name)) {
11596                 if (HOP(options.defines, name)) {
11597                     return options.defines[name];
11598                 }
11599             }
11600             return null;
11601         }
11602     };
11604     function _lambda(name, args, body) {
11605         if (!options.no_functions && options.mangle) {
11606             var is_defun = this[0] == "defun", extra;
11607             if (name) {
11608                 if (is_defun) name = get_mangled(name);
11609                 else if (body.scope.references(name)) {
11610                     extra = {};
11611                     if (!(scope.uses_eval || scope.uses_with))
11612                         name = extra[name] = scope.next_mangled();
11613                     else
11614                         extra[name] = name;
11615                 }
11616                 else name = null;
11617             }
11618         }
11619         body = with_scope(body.scope, function(){
11620             args = MAP(args, function(name){ return get_mangled(name) });
11621             return MAP(body, walk);
11622         }, extra);
11623         return [ this[0], name, args, body ];
11624     };
11626     function with_scope(s, cont, extra) {
11627         var _scope = scope;
11628         scope = s;
11629         if (extra) for (var i in extra) if (HOP(extra, i)) {
11630             s.set_mangle(i, extra[i]);
11631         }
11632         for (var i in s.names) if (HOP(s.names, i)) {
11633             get_mangled(i, true);
11634         }
11635         var ret = cont();
11636         ret.scope = s;
11637         scope = _scope;
11638         return ret;
11639     };
11641     function _vardefs(defs) {
11642         return [ this[0], MAP(defs, function(d){
11643             return [ get_mangled(d[0]), walk(d[1]) ];
11644         }) ];
11645     };
11647     function _breacont(label) {
11648         if (label) return [ this[0], scope.labels.get_mangled(label) ];
11649     };
11651     return w.with_walkers({
11652         "function": _lambda,
11653         "defun": function() {
11654             // move function declarations to the top when
11655             // they are not in some block.
11656             var ast = _lambda.apply(this, arguments);
11657             switch (w.parent()[0]) {
11658               case "toplevel":
11659               case "function":
11660               case "defun":
11661                 return MAP.at_top(ast);
11662             }
11663             return ast;
11664         },
11665         "label": function(label, stat) {
11666             if (scope.labels.refs[label]) return [
11667                 this[0],
11668                 scope.labels.get_mangled(label, true),
11669                 walk(stat)
11670             ];
11671             return walk(stat);
11672         },
11673         "break": _breacont,
11674         "continue": _breacont,
11675         "var": _vardefs,
11676         "const": _vardefs,
11677         "name": function(name) {
11678             return get_define(name) || [ this[0], get_mangled(name) ];
11679         },
11680         "try": function(t, c, f) {
11681             return [ this[0],
11682                      MAP(t, walk),
11683                      c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,
11684                      f != null ? MAP(f, walk) : null ];
11685         },
11686         "toplevel": function(body) {
11687             var self = this;
11688             return with_scope(self.scope, function(){
11689                 return [ self[0], MAP(body, walk) ];
11690             });
11691         },
11692         "directive": function() {
11693             return MAP.at_top(this);
11694         }
11695     }, function() {
11696         return walk(ast_add_scope(ast));
11697     });
11700 /* -----[
11701    - compress foo["bar"] into foo.bar,
11702    - remove block brackets {} where possible
11703    - join consecutive var declarations
11704    - various optimizations for IFs:
11705    - if (cond) foo(); else bar();  ==>  cond?foo():bar();
11706    - if (cond) foo();  ==>  cond&&foo();
11707    - if (foo) return bar(); else return baz();  ==> return foo?bar():baz(); // also for throw
11708    - if (foo) return bar(); else something();  ==> {if(foo)return bar();something()}
11709    ]----- */
11711 var warn = function(){};
11713 function best_of(ast1, ast2) {
11714     return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1;
11717 function last_stat(b) {
11718     if (b[0] == "block" && b[1] && b[1].length > 0)
11719         return b[1][b[1].length - 1];
11720     return b;
11723 function aborts(t) {
11724     if (t) switch (last_stat(t)[0]) {
11725       case "return":
11726       case "break":
11727       case "continue":
11728       case "throw":
11729         return true;
11730     }
11733 function boolean_expr(expr) {
11734     return ( (expr[0] == "unary-prefix"
11735               && member(expr[1], [ "!", "delete" ])) ||
11737              (expr[0] == "binary"
11738               && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) ||
11740              (expr[0] == "binary"
11741               && member(expr[1], [ "&&", "||" ])
11742               && boolean_expr(expr[2])
11743               && boolean_expr(expr[3])) ||
11745              (expr[0] == "conditional"
11746               && boolean_expr(expr[2])
11747               && boolean_expr(expr[3])) ||
11749              (expr[0] == "assign"
11750               && expr[1] === true
11751               && boolean_expr(expr[3])) ||
11753              (expr[0] == "seq"
11754               && boolean_expr(expr[expr.length - 1]))
11755            );
11758 function empty(b) {
11759     return !b || (b[0] == "block" && (!b[1] || b[1].length == 0));
11762 function is_string(node) {
11763     return (node[0] == "string" ||
11764             node[0] == "unary-prefix" && node[1] == "typeof" ||
11765             node[0] == "binary" && node[1] == "+" &&
11766             (is_string(node[2]) || is_string(node[3])));
11769 var when_constant = (function(){
11771     var $NOT_CONSTANT = {};
11773     // this can only evaluate constant expressions.  If it finds anything
11774     // not constant, it throws $NOT_CONSTANT.
11775     function evaluate(expr) {
11776         switch (expr[0]) {
11777           case "string":
11778           case "num":
11779             return expr[1];
11780           case "name":
11781           case "atom":
11782             switch (expr[1]) {
11783               case "true": return true;
11784               case "false": return false;
11785               case "null": return null;
11786             }
11787             break;
11788           case "unary-prefix":
11789             switch (expr[1]) {
11790               case "!": return !evaluate(expr[2]);
11791               case "typeof": return typeof evaluate(expr[2]);
11792               case "~": return ~evaluate(expr[2]);
11793               case "-": return -evaluate(expr[2]);
11794               case "+": return +evaluate(expr[2]);
11795             }
11796             break;
11797           case "binary":
11798             var left = expr[2], right = expr[3];
11799             switch (expr[1]) {
11800               case "&&"         : return evaluate(left) &&         evaluate(right);
11801               case "||"         : return evaluate(left) ||         evaluate(right);
11802               case "|"          : return evaluate(left) |          evaluate(right);
11803               case "&"          : return evaluate(left) &          evaluate(right);
11804               case "^"          : return evaluate(left) ^          evaluate(right);
11805               case "+"          : return evaluate(left) +          evaluate(right);
11806               case "*"          : return evaluate(left) *          evaluate(right);
11807               case "/"          : return evaluate(left) /          evaluate(right);
11808               case "%"          : return evaluate(left) %          evaluate(right);
11809               case "-"          : return evaluate(left) -          evaluate(right);
11810               case "<<"         : return evaluate(left) <<         evaluate(right);
11811               case ">>"         : return evaluate(left) >>         evaluate(right);
11812               case ">>>"        : return evaluate(left) >>>        evaluate(right);
11813               case "=="         : return evaluate(left) ==         evaluate(right);
11814               case "==="        : return evaluate(left) ===        evaluate(right);
11815               case "!="         : return evaluate(left) !=         evaluate(right);
11816               case "!=="        : return evaluate(left) !==        evaluate(right);
11817               case "<"          : return evaluate(left) <          evaluate(right);
11818               case "<="         : return evaluate(left) <=         evaluate(right);
11819               case ">"          : return evaluate(left) >          evaluate(right);
11820               case ">="         : return evaluate(left) >=         evaluate(right);
11821               case "in"         : return evaluate(left) in         evaluate(right);
11822               case "instanceof" : return evaluate(left) instanceof evaluate(right);
11823             }
11824         }
11825         throw $NOT_CONSTANT;
11826     };
11828     return function(expr, yes, no) {
11829         try {
11830             var val = evaluate(expr), ast;
11831             switch (typeof val) {
11832               case "string": ast =  [ "string", val ]; break;
11833               case "number": ast =  [ "num", val ]; break;
11834               case "boolean": ast =  [ "name", String(val) ]; break;
11835               default:
11836                 if (val === null) { ast = [ "atom", "null" ]; break; }
11837                 throw new Error("Can't handle constant of type: " + (typeof val));
11838             }
11839             return yes.call(expr, ast, val);
11840         } catch(ex) {
11841             if (ex === $NOT_CONSTANT) {
11842                 if (expr[0] == "binary"
11843                     && (expr[1] == "===" || expr[1] == "!==")
11844                     && ((is_string(expr[2]) && is_string(expr[3]))
11845                         || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {
11846                     expr[1] = expr[1].substr(0, 2);
11847                 }
11848                 else if (no && expr[0] == "binary"
11849                          && (expr[1] == "||" || expr[1] == "&&")) {
11850                     // the whole expression is not constant but the lval may be...
11851                     try {
11852                         var lval = evaluate(expr[2]);
11853                         expr = ((expr[1] == "&&" && (lval ? expr[3] : lval))    ||
11854                                 (expr[1] == "||" && (lval ? lval    : expr[3])) ||
11855                                 expr);
11856                     } catch(ex2) {
11857                         // IGNORE... lval is not constant
11858                     }
11859                 }
11860                 return no ? no.call(expr, expr) : null;
11861             }
11862             else throw ex;
11863         }
11864     };
11866 })();
11868 function warn_unreachable(ast) {
11869     if (!empty(ast))
11870         warn("Dropping unreachable code: " + gen_code(ast, true));
11873 function prepare_ifs(ast) {
11874     var w = ast_walker(), walk = w.walk;
11875     // In this first pass, we rewrite ifs which abort with no else with an
11876     // if-else.  For example:
11877     //
11878     // if (x) {
11879     //     blah();
11880     //     return y;
11881     // }
11882     // foobar();
11883     //
11884     // is rewritten into:
11885     //
11886     // if (x) {
11887     //     blah();
11888     //     return y;
11889     // } else {
11890     //     foobar();
11891     // }
11892     function redo_if(statements) {
11893         statements = MAP(statements, walk);
11895         for (var i = 0; i < statements.length; ++i) {
11896             var fi = statements[i];
11897             if (fi[0] != "if") continue;
11899             if (fi[3]) continue;
11901             var t = fi[2];
11902             if (!aborts(t)) continue;
11904             var conditional = walk(fi[1]);
11906             var e_body = redo_if(statements.slice(i + 1));
11907             var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ];
11909             return statements.slice(0, i).concat([ [
11910                 fi[0],          // "if"
11911                 conditional,    // conditional
11912                 t,              // then
11913                 e               // else
11914             ] ]);
11915         }
11917         return statements;
11918     };
11920     function redo_if_lambda(name, args, body) {
11921         body = redo_if(body);
11922         return [ this[0], name, args, body ];
11923     };
11925     function redo_if_block(statements) {
11926         return [ this[0], statements != null ? redo_if(statements) : null ];
11927     };
11929     return w.with_walkers({
11930         "defun": redo_if_lambda,
11931         "function": redo_if_lambda,
11932         "block": redo_if_block,
11933         "splice": redo_if_block,
11934         "toplevel": function(statements) {
11935             return [ this[0], redo_if(statements) ];
11936         },
11937         "try": function(t, c, f) {
11938             return [
11939                 this[0],
11940                 redo_if(t),
11941                 c != null ? [ c[0], redo_if(c[1]) ] : null,
11942                 f != null ? redo_if(f) : null
11943             ];
11944         }
11945     }, function() {
11946         return walk(ast);
11947     });
11950 function for_side_effects(ast, handler) {
11951     var w = ast_walker(), walk = w.walk;
11952     var $stop = {}, $restart = {};
11953     function stop() { throw $stop };
11954     function restart() { throw $restart };
11955     function found(){ return handler.call(this, this, w, stop, restart) };
11956     function unary(op) {
11957         if (op == "++" || op == "--")
11958             return found.apply(this, arguments);
11959     };
11960     function binary(op) {
11961         if (op == "&&" || op == "||")
11962             return found.apply(this, arguments);
11963     };
11964     return w.with_walkers({
11965         "try": found,
11966         "throw": found,
11967         "return": found,
11968         "new": found,
11969         "switch": found,
11970         "break": found,
11971         "continue": found,
11972         "assign": found,
11973         "call": found,
11974         "if": found,
11975         "for": found,
11976         "for-in": found,
11977         "while": found,
11978         "do": found,
11979         "return": found,
11980         "unary-prefix": unary,
11981         "unary-postfix": unary,
11982         "conditional": found,
11983         "binary": binary,
11984         "defun": found
11985     }, function(){
11986         while (true) try {
11987             walk(ast);
11988             break;
11989         } catch(ex) {
11990             if (ex === $stop) break;
11991             if (ex === $restart) continue;
11992             throw ex;
11993         }
11994     });
11997 function ast_lift_variables(ast) {
11998     var w = ast_walker(), walk = w.walk, scope;
11999     function do_body(body, env) {
12000         var _scope = scope;
12001         scope = env;
12002         body = MAP(body, walk);
12003         var hash = {}, names = MAP(env.names, function(type, name){
12004             if (type != "var") return MAP.skip;
12005             if (!env.references(name)) return MAP.skip;
12006             hash[name] = true;
12007             return [ name ];
12008         });
12009         if (names.length > 0) {
12010             // looking for assignments to any of these variables.
12011             // we can save considerable space by moving the definitions
12012             // in the var declaration.
12013             for_side_effects([ "block", body ], function(ast, walker, stop, restart) {
12014                 if (ast[0] == "assign"
12015                     && ast[1] === true
12016                     && ast[2][0] == "name"
12017                     && HOP(hash, ast[2][1])) {
12018                     // insert the definition into the var declaration
12019                     for (var i = names.length; --i >= 0;) {
12020                         if (names[i][0] == ast[2][1]) {
12021                             if (names[i][1]) // this name already defined, we must stop
12022                                 stop();
12023                             names[i][1] = ast[3]; // definition
12024                             names.push(names.splice(i, 1)[0]);
12025                             break;
12026                         }
12027                     }
12028                     // remove this assignment from the AST.
12029                     var p = walker.parent();
12030                     if (p[0] == "seq") {
12031                         var a = p[2];
12032                         a.unshift(0, p.length);
12033                         p.splice.apply(p, a);
12034                     }
12035                     else if (p[0] == "stat") {
12036                         p.splice(0, p.length, "block"); // empty statement
12037                     }
12038                     else {
12039                         stop();
12040                     }
12041                     restart();
12042                 }
12043                 stop();
12044             });
12045             body.unshift([ "var", names ]);
12046         }
12047         scope = _scope;
12048         return body;
12049     };
12050     function _vardefs(defs) {
12051         var ret = null;
12052         for (var i = defs.length; --i >= 0;) {
12053             var d = defs[i];
12054             if (!d[1]) continue;
12055             d = [ "assign", true, [ "name", d[0] ], d[1] ];
12056             if (ret == null) ret = d;
12057             else ret = [ "seq", d, ret ];
12058         }
12059         if (ret == null && w.parent()[0] != "for") {
12060             if (w.parent()[0] == "for-in")
12061                 return [ "name", defs[0][0] ];
12062             return MAP.skip;
12063         }
12064         return [ "stat", ret ];
12065     };
12066     function _toplevel(body) {
12067         return [ this[0], do_body(body, this.scope) ];
12068     };
12069     return w.with_walkers({
12070         "function": function(name, args, body){
12071             for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)
12072                 args.pop();
12073             if (!body.scope.references(name)) name = null;
12074             return [ this[0], name, args, do_body(body, body.scope) ];
12075         },
12076         "defun": function(name, args, body){
12077             if (!scope.references(name)) return MAP.skip;
12078             for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)
12079                 args.pop();
12080             return [ this[0], name, args, do_body(body, body.scope) ];
12081         },
12082         "var": _vardefs,
12083         "toplevel": _toplevel
12084     }, function(){
12085         return walk(ast_add_scope(ast));
12086     });
12089 function ast_squeeze(ast, options) {
12090     ast = squeeze_1(ast, options);
12091     ast = squeeze_2(ast, options);
12092     return ast;
12095 function squeeze_1(ast, options) {
12096     options = defaults(options, {
12097         make_seqs   : true,
12098         dead_code   : true,
12099         no_warnings : false,
12100         keep_comps  : true,
12101         unsafe      : false
12102     });
12104     var w = ast_walker(), walk = w.walk, scope;
12106     function negate(c) {
12107         var not_c = [ "unary-prefix", "!", c ];
12108         switch (c[0]) {
12109           case "unary-prefix":
12110             return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c;
12111           case "seq":
12112             c = slice(c);
12113             c[c.length - 1] = negate(c[c.length - 1]);
12114             return c;
12115           case "conditional":
12116             return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]);
12117           case "binary":
12118             var op = c[1], left = c[2], right = c[3];
12119             if (!options.keep_comps) switch (op) {
12120               case "<="  : return [ "binary", ">", left, right ];
12121               case "<"   : return [ "binary", ">=", left, right ];
12122               case ">="  : return [ "binary", "<", left, right ];
12123               case ">"   : return [ "binary", "<=", left, right ];
12124             }
12125             switch (op) {
12126               case "=="  : return [ "binary", "!=", left, right ];
12127               case "!="  : return [ "binary", "==", left, right ];
12128               case "===" : return [ "binary", "!==", left, right ];
12129               case "!==" : return [ "binary", "===", left, right ];
12130               case "&&"  : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]);
12131               case "||"  : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]);
12132             }
12133             break;
12134         }
12135         return not_c;
12136     };
12138     function make_conditional(c, t, e) {
12139         var make_real_conditional = function() {
12140             if (c[0] == "unary-prefix" && c[1] == "!") {
12141                 return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
12142             } else {
12143                 return e ? best_of(
12144                     [ "conditional", c, t, e ],
12145                     [ "conditional", negate(c), e, t ]
12146                 ) : [ "binary", "&&", c, t ];
12147             }
12148         };
12149         // shortcut the conditional if the expression has a constant value
12150         return when_constant(c, function(ast, val){
12151             warn_unreachable(val ? e : t);
12152             return          (val ? t : e);
12153         }, make_real_conditional);
12154     };
12156     function rmblock(block) {
12157         if (block != null && block[0] == "block" && block[1]) {
12158             if (block[1].length == 1)
12159                 block = block[1][0];
12160             else if (block[1].length == 0)
12161                 block = [ "block" ];
12162         }
12163         return block;
12164     };
12166     function _lambda(name, args, body) {
12167         return [ this[0], name, args, tighten(body, "lambda") ];
12168     };
12170     // this function does a few things:
12171     // 1. discard useless blocks
12172     // 2. join consecutive var declarations
12173     // 3. remove obviously dead code
12174     // 4. transform consecutive statements using the comma operator
12175     // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... }
12176     function tighten(statements, block_type) {
12177         statements = MAP(statements, walk);
12179         statements = statements.reduce(function(a, stat){
12180             if (stat[0] == "block") {
12181                 if (stat[1]) {
12182                     a.push.apply(a, stat[1]);
12183                 }
12184             } else {
12185                 a.push(stat);
12186             }
12187             return a;
12188         }, []);
12190         statements = (function(a, prev){
12191             statements.forEach(function(cur){
12192                 if (prev && ((cur[0] == "var" && prev[0] == "var") ||
12193                              (cur[0] == "const" && prev[0] == "const"))) {
12194                     prev[1] = prev[1].concat(cur[1]);
12195                 } else {
12196                     a.push(cur);
12197                     prev = cur;
12198                 }
12199             });
12200             return a;
12201         })([]);
12203         if (options.dead_code) statements = (function(a, has_quit){
12204             statements.forEach(function(st){
12205                 if (has_quit) {
12206                     if (st[0] == "function" || st[0] == "defun") {
12207                         a.push(st);
12208                     }
12209                     else if (st[0] == "var" || st[0] == "const") {
12210                         if (!options.no_warnings)
12211                             warn("Variables declared in unreachable code");
12212                         st[1] = MAP(st[1], function(def){
12213                             if (def[1] && !options.no_warnings)
12214                                 warn_unreachable([ "assign", true, [ "name", def[0] ], def[1] ]);
12215                             return [ def[0] ];
12216                         });
12217                         a.push(st);
12218                     }
12219                     else if (!options.no_warnings)
12220                         warn_unreachable(st);
12221                 }
12222                 else {
12223                     a.push(st);
12224                     if (member(st[0], [ "return", "throw", "break", "continue" ]))
12225                         has_quit = true;
12226                 }
12227             });
12228             return a;
12229         })([]);
12231         if (options.make_seqs) statements = (function(a, prev) {
12232             statements.forEach(function(cur){
12233                 if (prev && prev[0] == "stat" && cur[0] == "stat") {
12234                     prev[1] = [ "seq", prev[1], cur[1] ];
12235                 } else {
12236                     a.push(cur);
12237                     prev = cur;
12238                 }
12239             });
12240             if (a.length >= 2
12241                 && a[a.length-2][0] == "stat"
12242                 && (a[a.length-1][0] == "return" || a[a.length-1][0] == "throw")
12243                 && a[a.length-1][1])
12244             {
12245                 a.splice(a.length - 2, 2,
12246                          [ a[a.length-1][0],
12247                            [ "seq", a[a.length-2][1], a[a.length-1][1] ]]);
12248             }
12249             return a;
12250         })([]);
12252         // this increases jQuery by 1K.  Probably not such a good idea after all..
12253         // part of this is done in prepare_ifs anyway.
12254         // if (block_type == "lambda") statements = (function(i, a, stat){
12255         //         while (i < statements.length) {
12256         //                 stat = statements[i++];
12257         //                 if (stat[0] == "if" && !stat[3]) {
12258         //                         if (stat[2][0] == "return" && stat[2][1] == null) {
12259         //                                 a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ]));
12260         //                                 break;
12261         //                         }
12262         //                         var last = last_stat(stat[2]);
12263         //                         if (last[0] == "return" && last[1] == null) {
12264         //                                 a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ]));
12265         //                                 break;
12266         //                         }
12267         //                 }
12268         //                 a.push(stat);
12269         //         }
12270         //         return a;
12271         // })(0, []);
12273         return statements;
12274     };
12276     function make_if(c, t, e) {
12277         return when_constant(c, function(ast, val){
12278             if (val) {
12279                 t = walk(t);
12280                 warn_unreachable(e);
12281                 return t || [ "block" ];
12282             } else {
12283                 e = walk(e);
12284                 warn_unreachable(t);
12285                 return e || [ "block" ];
12286             }
12287         }, function() {
12288             return make_real_if(c, t, e);
12289         });
12290     };
12292     function abort_else(c, t, e) {
12293         var ret = [ [ "if", negate(c), e ] ];
12294         if (t[0] == "block") {
12295             if (t[1]) ret = ret.concat(t[1]);
12296         } else {
12297             ret.push(t);
12298         }
12299         return walk([ "block", ret ]);
12300     };
12302     function make_real_if(c, t, e) {
12303         c = walk(c);
12304         t = walk(t);
12305         e = walk(e);
12307         if (empty(e) && empty(t))
12308             return [ "stat", c ];
12310         if (empty(t)) {
12311             c = negate(c);
12312             t = e;
12313             e = null;
12314         } else if (empty(e)) {
12315             e = null;
12316         } else {
12317             // if we have both else and then, maybe it makes sense to switch them?
12318             (function(){
12319                 var a = gen_code(c);
12320                 var n = negate(c);
12321                 var b = gen_code(n);
12322                 if (b.length < a.length) {
12323                     var tmp = t;
12324                     t = e;
12325                     e = tmp;
12326                     c = n;
12327                 }
12328             })();
12329         }
12330         var ret = [ "if", c, t, e ];
12331         if (t[0] == "if" && empty(t[3]) && empty(e)) {
12332             ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ]));
12333         }
12334         else if (t[0] == "stat") {
12335             if (e) {
12336                 if (e[0] == "stat")
12337                     ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]);
12338                 else if (aborts(e))
12339                     ret = abort_else(c, t, e);
12340             }
12341             else {
12342                 ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]);
12343             }
12344         }
12345         else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) {
12346             ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]);
12347         }
12348         else if (e && aborts(t)) {
12349             ret = [ [ "if", c, t ] ];
12350             if (e[0] == "block") {
12351                 if (e[1]) ret = ret.concat(e[1]);
12352             }
12353             else {
12354                 ret.push(e);
12355             }
12356             ret = walk([ "block", ret ]);
12357         }
12358         else if (t && aborts(e)) {
12359             ret = abort_else(c, t, e);
12360         }
12361         return ret;
12362     };
12364     function _do_while(cond, body) {
12365         return when_constant(cond, function(cond, val){
12366             if (!val) {
12367                 warn_unreachable(body);
12368                 return [ "block" ];
12369             } else {
12370                 return [ "for", null, null, null, walk(body) ];
12371             }
12372         });
12373     };
12375     return w.with_walkers({
12376         "sub": function(expr, subscript) {
12377             if (subscript[0] == "string") {
12378                 var name = subscript[1];
12379                 if (is_identifier(name))
12380                     return [ "dot", walk(expr), name ];
12381                 else if (/^[1-9][0-9]*$/.test(name) || name === "0")
12382                     return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ];
12383             }
12384         },
12385         "if": make_if,
12386         "toplevel": function(body) {
12387             return [ "toplevel", tighten(body) ];
12388         },
12389         "switch": function(expr, body) {
12390             var last = body.length - 1;
12391             return [ "switch", walk(expr), MAP(body, function(branch, i){
12392                 var block = tighten(branch[1]);
12393                 if (i == last && block.length > 0) {
12394                     var node = block[block.length - 1];
12395                     if (node[0] == "break" && !node[1])
12396                         block.pop();
12397                 }
12398                 return [ branch[0] ? walk(branch[0]) : null, block ];
12399             }) ];
12400         },
12401         "function": _lambda,
12402         "defun": _lambda,
12403         "block": function(body) {
12404             if (body) return rmblock([ "block", tighten(body) ]);
12405         },
12406         "binary": function(op, left, right) {
12407             return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){
12408                 return best_of(walk(c), this);
12409             }, function no() {
12410                 return function(){
12411                     if(op != "==" && op != "!=") return;
12412                     var l = walk(left), r = walk(right);
12413                     if(l && l[0] == "unary-prefix" && l[1] == "!" && l[2][0] == "num")
12414                         left = ['num', +!l[2][1]];
12415                     else if (r && r[0] == "unary-prefix" && r[1] == "!" && r[2][0] == "num")
12416                         right = ['num', +!r[2][1]];
12417                     return ["binary", op, left, right];
12418                 }() || this;
12419             });
12420         },
12421         "conditional": function(c, t, e) {
12422             return make_conditional(walk(c), walk(t), walk(e));
12423         },
12424         "try": function(t, c, f) {
12425             return [
12426                 "try",
12427                 tighten(t),
12428                 c != null ? [ c[0], tighten(c[1]) ] : null,
12429                 f != null ? tighten(f) : null
12430             ];
12431         },
12432         "unary-prefix": function(op, expr) {
12433             expr = walk(expr);
12434             var ret = [ "unary-prefix", op, expr ];
12435             if (op == "!")
12436                 ret = best_of(ret, negate(expr));
12437             return when_constant(ret, function(ast, val){
12438                 return walk(ast); // it's either true or false, so minifies to !0 or !1
12439             }, function() { return ret });
12440         },
12441         "name": function(name) {
12442             switch (name) {
12443               case "true": return [ "unary-prefix", "!", [ "num", 0 ]];
12444               case "false": return [ "unary-prefix", "!", [ "num", 1 ]];
12445             }
12446         },
12447         "while": _do_while,
12448         "assign": function(op, lvalue, rvalue) {
12449             lvalue = walk(lvalue);
12450             rvalue = walk(rvalue);
12451             var okOps = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
12452             if (op === true && lvalue[0] === "name" && rvalue[0] === "binary" &&
12453                 ~okOps.indexOf(rvalue[1]) && rvalue[2][0] === "name" &&
12454                 rvalue[2][1] === lvalue[1]) {
12455                 return [ this[0], rvalue[1], lvalue, rvalue[3] ]
12456             }
12457             return [ this[0], op, lvalue, rvalue ];
12458         },
12459         "call": function(expr, args) {
12460             expr = walk(expr);
12461             if (options.unsafe && expr[0] == "dot" && expr[1][0] == "string" && expr[2] == "toString") {
12462                 return expr[1];
12463             }
12464             return [ this[0], expr,  MAP(args, walk) ];
12465         },
12466         "num": function (num) {
12467             if (!isFinite(num))
12468                 return [ "binary", "/", num === 1 / 0
12469                          ? [ "num", 1 ] : num === -1 / 0
12470                          ? [ "unary-prefix", "-", [ "num", 1 ] ]
12471                          : [ "num", 0 ], [ "num", 0 ] ];
12473             return [ this[0], num ];
12474         }
12475     }, function() {
12476         return walk(prepare_ifs(walk(prepare_ifs(ast))));
12477     });
12480 function squeeze_2(ast, options) {
12481     var w = ast_walker(), walk = w.walk, scope;
12482     function with_scope(s, cont) {
12483         var save = scope, ret;
12484         scope = s;
12485         ret = cont();
12486         scope = save;
12487         return ret;
12488     };
12489     function lambda(name, args, body) {
12490         return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];
12491     };
12492     return w.with_walkers({
12493         "directive": function(dir) {
12494             if (scope.active_directive(dir))
12495                 return [ "block" ];
12496             scope.directives.push(dir);
12497         },
12498         "toplevel": function(body) {
12499             return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];
12500         },
12501         "function": lambda,
12502         "defun": lambda
12503     }, function(){
12504         return walk(ast_add_scope(ast));
12505     });
12508 /* -----[ re-generate code from the AST ]----- */
12510 var DOT_CALL_NO_PARENS = jsp.array_to_hash([
12511     "name",
12512     "array",
12513     "object",
12514     "string",
12515     "dot",
12516     "sub",
12517     "call",
12518     "regexp",
12519     "defun"
12522 function make_string(str, ascii_only) {
12523     var dq = 0, sq = 0;
12524     str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){
12525         switch (s) {
12526           case "\\": return "\\\\";
12527           case "\b": return "\\b";
12528           case "\f": return "\\f";
12529           case "\n": return "\\n";
12530           case "\r": return "\\r";
12531           case "\u2028": return "\\u2028";
12532           case "\u2029": return "\\u2029";
12533           case '"': ++dq; return '"';
12534           case "'": ++sq; return "'";
12535           case "\0": return "\\0";
12536         }
12537         return s;
12538     });
12539     if (ascii_only) str = to_ascii(str);
12540     if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'";
12541     else return '"' + str.replace(/\x22/g, '\\"') + '"';
12544 function to_ascii(str) {
12545     return str.replace(/[\u0080-\uffff]/g, function(ch) {
12546         var code = ch.charCodeAt(0).toString(16);
12547         while (code.length < 4) code = "0" + code;
12548         return "\\u" + code;
12549     });
12552 var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]);
12554 function gen_code(ast, options) {
12555     options = defaults(options, {
12556         indent_start : 0,
12557         indent_level : 4,
12558         quote_keys   : false,
12559         space_colon  : false,
12560         beautify     : false,
12561         ascii_only   : false,
12562         inline_script: false
12563     });
12564     var beautify = !!options.beautify;
12565     var indentation = 0,
12566     newline = beautify ? "\n" : "",
12567     space = beautify ? " " : "";
12569     function encode_string(str) {
12570         var ret = make_string(str, options.ascii_only);
12571         if (options.inline_script)
12572             ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
12573         return ret;
12574     };
12576     function make_name(name) {
12577         name = name.toString();
12578         if (options.ascii_only)
12579             name = to_ascii(name);
12580         return name;
12581     };
12583     function indent(line) {
12584         if (line == null)
12585             line = "";
12586         if (beautify)
12587             line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line;
12588         return line;
12589     };
12591     function with_indent(cont, incr) {
12592         if (incr == null) incr = 1;
12593         indentation += incr;
12594         try { return cont.apply(null, slice(arguments, 1)); }
12595         finally { indentation -= incr; }
12596     };
12598     function last_char(str) {
12599         str = str.toString();
12600         return str.charAt(str.length - 1);
12601     };
12603     function first_char(str) {
12604         return str.toString().charAt(0);
12605     };
12607     function add_spaces(a) {
12608         if (beautify)
12609             return a.join(" ");
12610         var b = [];
12611         for (var i = 0; i < a.length; ++i) {
12612             var next = a[i + 1];
12613             b.push(a[i]);
12614             if (next &&
12615                 ((is_identifier_char(last_char(a[i])) && (is_identifier_char(first_char(next))
12616                                                           || first_char(next) == "\\")) ||
12617                  (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString()) ||
12618                  last_char(a[i]) == "/" && first_char(next) == "/"))) {
12619                 b.push(" ");
12620             }
12621         }
12622         return b.join("");
12623     };
12625     function add_commas(a) {
12626         return a.join("," + space);
12627     };
12629     function parenthesize(expr) {
12630         var gen = make(expr);
12631         for (var i = 1; i < arguments.length; ++i) {
12632             var el = arguments[i];
12633             if ((el instanceof Function && el(expr)) || expr[0] == el)
12634                 return "(" + gen + ")";
12635         }
12636         return gen;
12637     };
12639     function best_of(a) {
12640         if (a.length == 1) {
12641             return a[0];
12642         }
12643         if (a.length == 2) {
12644             var b = a[1];
12645             a = a[0];
12646             return a.length <= b.length ? a : b;
12647         }
12648         return best_of([ a[0], best_of(a.slice(1)) ]);
12649     };
12651     function needs_parens(expr) {
12652         if (expr[0] == "function" || expr[0] == "object") {
12653             // dot/call on a literal function requires the
12654             // function literal itself to be parenthesized
12655             // only if it's the first "thing" in a
12656             // statement.  This means that the parent is
12657             // "stat", but it could also be a "seq" and
12658             // we're the first in this "seq" and the
12659             // parent is "stat", and so on.  Messy stuff,
12660             // but it worths the trouble.
12661             var a = slice(w.stack()), self = a.pop(), p = a.pop();
12662             while (p) {
12663                 if (p[0] == "stat") return true;
12664                 if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) ||
12665                     ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) {
12666                     self = p;
12667                     p = a.pop();
12668                 } else {
12669                     return false;
12670                 }
12671             }
12672         }
12673         return !HOP(DOT_CALL_NO_PARENS, expr[0]);
12674     };
12676     function make_num(num) {
12677         var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;
12678         if (Math.floor(num) === num) {
12679             if (num >= 0) {
12680                 a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
12681                        "0" + num.toString(8)); // same.
12682             } else {
12683                 a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
12684                        "-0" + (-num).toString(8)); // same.
12685             }
12686             if ((m = /^(.*?)(0+)$/.exec(num))) {
12687                 a.push(m[1] + "e" + m[2].length);
12688             }
12689         } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
12690             a.push(m[2] + "e-" + (m[1].length + m[2].length),
12691                    str.substr(str.indexOf(".")));
12692         }
12693         return best_of(a);
12694     };
12696     var w = ast_walker();
12697     var make = w.walk;
12698     return w.with_walkers({
12699         "string": encode_string,
12700         "num": make_num,
12701         "name": make_name,
12702         "debugger": function(){ return "debugger;" },
12703         "toplevel": function(statements) {
12704             return make_block_statements(statements)
12705                 .join(newline + newline);
12706         },
12707         "splice": function(statements) {
12708             var parent = w.parent();
12709             if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {
12710                 // we need block brackets in this case
12711                 return make_block.apply(this, arguments);
12712             } else {
12713                 return MAP(make_block_statements(statements, true),
12714                            function(line, i) {
12715                                // the first line is already indented
12716                                return i > 0 ? indent(line) : line;
12717                            }).join(newline);
12718             }
12719         },
12720         "block": make_block,
12721         "var": function(defs) {
12722             return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
12723         },
12724         "const": function(defs) {
12725             return "const " + add_commas(MAP(defs, make_1vardef)) + ";";
12726         },
12727         "try": function(tr, ca, fi) {
12728             var out = [ "try", make_block(tr) ];
12729             if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1]));
12730             if (fi) out.push("finally", make_block(fi));
12731             return add_spaces(out);
12732         },
12733         "throw": function(expr) {
12734             return add_spaces([ "throw", make(expr) ]) + ";";
12735         },
12736         "new": function(ctor, args) {
12737             args = args.length > 0 ? "(" + add_commas(MAP(args, function(expr){
12738                 return parenthesize(expr, "seq");
12739             })) + ")" : "";
12740             return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){
12741                 var w = ast_walker(), has_call = {};
12742                 try {
12743                     w.with_walkers({
12744                         "call": function() { throw has_call },
12745                         "function": function() { return this }
12746                     }, function(){
12747                         w.walk(expr);
12748                     });
12749                 } catch(ex) {
12750                     if (ex === has_call)
12751                         return true;
12752                     throw ex;
12753                 }
12754             }) + args ]);
12755         },
12756         "switch": function(expr, body) {
12757             return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]);
12758         },
12759         "break": function(label) {
12760             var out = "break";
12761             if (label != null)
12762                 out += " " + make_name(label);
12763             return out + ";";
12764         },
12765         "continue": function(label) {
12766             var out = "continue";
12767             if (label != null)
12768                 out += " " + make_name(label);
12769             return out + ";";
12770         },
12771         "conditional": function(co, th, el) {
12772             return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?",
12773                                 parenthesize(th, "seq"), ":",
12774                                 parenthesize(el, "seq") ]);
12775         },
12776         "assign": function(op, lvalue, rvalue) {
12777             if (op && op !== true) op += "=";
12778             else op = "=";
12779             return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]);
12780         },
12781         "dot": function(expr) {
12782             var out = make(expr), i = 1;
12783             if (expr[0] == "num") {
12784                 if (!/[a-f.]/i.test(out))
12785                     out += ".";
12786             } else if (expr[0] != "function" && needs_parens(expr))
12787                 out = "(" + out + ")";
12788             while (i < arguments.length)
12789                 out += "." + make_name(arguments[i++]);
12790             return out;
12791         },
12792         "call": function(func, args) {
12793             var f = make(func);
12794             if (f.charAt(0) != "(" && needs_parens(func))
12795                 f = "(" + f + ")";
12796             return f + "(" + add_commas(MAP(args, function(expr){
12797                 return parenthesize(expr, "seq");
12798             })) + ")";
12799         },
12800         "function": make_function,
12801         "defun": make_function,
12802         "if": function(co, th, el) {
12803             var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ];
12804             if (el) {
12805                 out.push("else", make(el));
12806             }
12807             return add_spaces(out);
12808         },
12809         "for": function(init, cond, step, block) {
12810             var out = [ "for" ];
12811             init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space);
12812             cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space);
12813             step = (step != null ? make(step) : "").replace(/;*\s*$/, "");
12814             var args = init + cond + step;
12815             if (args == "; ; ") args = ";;";
12816             out.push("(" + args + ")", make(block));
12817             return add_spaces(out);
12818         },
12819         "for-in": function(vvar, key, hash, block) {
12820             return add_spaces([ "for", "(" +
12821                                 (vvar ? make(vvar).replace(/;+$/, "") : make(key)),
12822                                 "in",
12823                                 make(hash) + ")", make(block) ]);
12824         },
12825         "while": function(condition, block) {
12826             return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]);
12827         },
12828         "do": function(condition, block) {
12829             return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";";
12830         },
12831         "return": function(expr) {
12832             var out = [ "return" ];
12833             if (expr != null) out.push(make(expr));
12834             return add_spaces(out) + ";";
12835         },
12836         "binary": function(operator, lvalue, rvalue) {
12837             var left = make(lvalue), right = make(rvalue);
12838             // XXX: I'm pretty sure other cases will bite here.
12839             //      we need to be smarter.
12840             //      adding parens all the time is the safest bet.
12841             if (member(lvalue[0], [ "assign", "conditional", "seq" ]) ||
12842                 lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] ||
12843                 lvalue[0] == "function" && needs_parens(this)) {
12844                 left = "(" + left + ")";
12845             }
12846             if (member(rvalue[0], [ "assign", "conditional", "seq" ]) ||
12847                 rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] &&
12848                 !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) {
12849                 right = "(" + right + ")";
12850             }
12851             else if (!beautify && options.inline_script && (operator == "<" || operator == "<<")
12852                      && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) {
12853                 right = " " + right;
12854             }
12855             return add_spaces([ left, operator, right ]);
12856         },
12857         "unary-prefix": function(operator, expr) {
12858             var val = make(expr);
12859             if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
12860                 val = "(" + val + ")";
12861             return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val;
12862         },
12863         "unary-postfix": function(operator, expr) {
12864             var val = make(expr);
12865             if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
12866                 val = "(" + val + ")";
12867             return val + operator;
12868         },
12869         "sub": function(expr, subscript) {
12870             var hash = make(expr);
12871             if (needs_parens(expr))
12872                 hash = "(" + hash + ")";
12873             return hash + "[" + make(subscript) + "]";
12874         },
12875         "object": function(props) {
12876             var obj_needs_parens = needs_parens(this);
12877             if (props.length == 0)
12878                 return obj_needs_parens ? "({})" : "{}";
12879             var out = "{" + newline + with_indent(function(){
12880                 return MAP(props, function(p){
12881                     if (p.length == 3) {
12882                         // getter/setter.  The name is in p[0], the arg.list in p[1][2], the
12883                         // body in p[1][3] and type ("get" / "set") in p[2].
12884                         return indent(make_function(p[0], p[1][2], p[1][3], p[2], true));
12885                     }
12886                     var key = p[0], val = parenthesize(p[1], "seq");
12887                     if (options.quote_keys) {
12888                         key = encode_string(key);
12889                     } else if ((typeof key == "number" || !beautify && +key + "" == key)
12890                                && parseFloat(key) >= 0) {
12891                         key = make_num(+key);
12892                     } else if (!is_identifier(key)) {
12893                         key = encode_string(key);
12894                     }
12895                     return indent(add_spaces(beautify && options.space_colon
12896                                              ? [ key, ":", val ]
12897                                              : [ key + ":", val ]));
12898                 }).join("," + newline);
12899             }) + newline + indent("}");
12900             return obj_needs_parens ? "(" + out + ")" : out;
12901         },
12902         "regexp": function(rx, mods) {
12903             if (options.ascii_only) rx = to_ascii(rx);
12904             return "/" + rx + "/" + mods;
12905         },
12906         "array": function(elements) {
12907             if (elements.length == 0) return "[]";
12908             return add_spaces([ "[", add_commas(MAP(elements, function(el, i){
12909                 if (!beautify && el[0] == "atom" && el[1] == "undefined") return i === elements.length - 1 ? "," : "";
12910                 return parenthesize(el, "seq");
12911             })), "]" ]);
12912         },
12913         "stat": function(stmt) {
12914             return stmt != null
12915                 ? make(stmt).replace(/;*\s*$/, ";")
12916                 : ";";
12917         },
12918         "seq": function() {
12919             return add_commas(MAP(slice(arguments), make));
12920         },
12921         "label": function(name, block) {
12922             return add_spaces([ make_name(name), ":", make(block) ]);
12923         },
12924         "with": function(expr, block) {
12925             return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]);
12926         },
12927         "atom": function(name) {
12928             return make_name(name);
12929         },
12930         "directive": function(dir) {
12931             return make_string(dir) + ";";
12932         }
12933     }, function(){ return make(ast) });
12935     // The squeezer replaces "block"-s that contain only a single
12936     // statement with the statement itself; technically, the AST
12937     // is correct, but this can create problems when we output an
12938     // IF having an ELSE clause where the THEN clause ends in an
12939     // IF *without* an ELSE block (then the outer ELSE would refer
12940     // to the inner IF).  This function checks for this case and
12941     // adds the block brackets if needed.
12942     function make_then(th) {
12943         if (th == null) return ";";
12944         if (th[0] == "do") {
12945             // https://github.com/mishoo/UglifyJS/issues/#issue/57
12946             // IE croaks with "syntax error" on code like this:
12947             //     if (foo) do ... while(cond); else ...
12948             // we need block brackets around do/while
12949             return make_block([ th ]);
12950         }
12951         var b = th;
12952         while (true) {
12953             var type = b[0];
12954             if (type == "if") {
12955                 if (!b[3])
12956                     // no else, we must add the block
12957                     return make([ "block", [ th ]]);
12958                 b = b[3];
12959             }
12960             else if (type == "while" || type == "do") b = b[2];
12961             else if (type == "for" || type == "for-in") b = b[4];
12962             else break;
12963         }
12964         return make(th);
12965     };
12967     function make_function(name, args, body, keyword, no_parens) {
12968         var out = keyword || "function";
12969         if (name) {
12970             out += " " + make_name(name);
12971         }
12972         out += "(" + add_commas(MAP(args, make_name)) + ")";
12973         out = add_spaces([ out, make_block(body) ]);
12974         return (!no_parens && needs_parens(this)) ? "(" + out + ")" : out;
12975     };
12977     function must_has_semicolon(node) {
12978         switch (node[0]) {
12979           case "with":
12980           case "while":
12981             return empty(node[2]) || must_has_semicolon(node[2]);
12982           case "for":
12983           case "for-in":
12984             return empty(node[4]) || must_has_semicolon(node[4]);
12985           case "if":
12986             if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else'
12987             if (node[3]) {
12988                 if (empty(node[3])) return true; // `else' present but empty
12989                 return must_has_semicolon(node[3]); // dive into the `else' branch
12990             }
12991             return must_has_semicolon(node[2]); // dive into the `then' branch
12992           case "directive":
12993             return true;
12994         }
12995     };
12997     function make_block_statements(statements, noindent) {
12998         for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {
12999             var stat = statements[i];
13000             var code = make(stat);
13001             if (code != ";") {
13002                 if (!beautify && i == last && !must_has_semicolon(stat)) {
13003                     code = code.replace(/;+\s*$/, "");
13004                 }
13005                 a.push(code);
13006             }
13007         }
13008         return noindent ? a : MAP(a, indent);
13009     };
13011     function make_switch_block(body) {
13012         var n = body.length;
13013         if (n == 0) return "{}";
13014         return "{" + newline + MAP(body, function(branch, i){
13015             var has_body = branch[1].length > 0, code = with_indent(function(){
13016                 return indent(branch[0]
13017                               ? add_spaces([ "case", make(branch[0]) + ":" ])
13018                               : "default:");
13019             }, 0.5) + (has_body ? newline + with_indent(function(){
13020                 return make_block_statements(branch[1]).join(newline);
13021             }) : "");
13022             if (!beautify && has_body && i < n - 1)
13023                 code += ";";
13024             return code;
13025         }).join(newline) + newline + indent("}");
13026     };
13028     function make_block(statements) {
13029         if (!statements) return ";";
13030         if (statements.length == 0) return "{}";
13031         return "{" + newline + with_indent(function(){
13032             return make_block_statements(statements).join(newline);
13033         }) + newline + indent("}");
13034     };
13036     function make_1vardef(def) {
13037         var name = def[0], val = def[1];
13038         if (val != null)
13039             name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]);
13040         return name;
13041     };
13045 function split_lines(code, max_line_length) {
13046     var splits = [ 0 ];
13047     jsp.parse(function(){
13048         var next_token = jsp.tokenizer(code);
13049         var last_split = 0;
13050         var prev_token;
13051         function current_length(tok) {
13052             return tok.pos - last_split;
13053         };
13054         function split_here(tok) {
13055             last_split = tok.pos;
13056             splits.push(last_split);
13057         };
13058         function custom(){
13059             var tok = next_token.apply(this, arguments);
13060             out: {
13061                 if (prev_token) {
13062                     if (prev_token.type == "keyword") break out;
13063                 }
13064                 if (current_length(tok) > max_line_length) {
13065                     switch (tok.type) {
13066                       case "keyword":
13067                       case "atom":
13068                       case "name":
13069                       case "punc":
13070                         split_here(tok);
13071                         break out;
13072                     }
13073                 }
13074             }
13075             prev_token = tok;
13076             return tok;
13077         };
13078         custom.context = function() {
13079             return next_token.context.apply(this, arguments);
13080         };
13081         return custom;
13082     }());
13083     return splits.map(function(pos, i){
13084         return code.substring(pos, splits[i + 1] || code.length);
13085     }).join("\n");
13088 /* -----[ Utilities ]----- */
13090 function repeat_string(str, i) {
13091     if (i <= 0) return "";
13092     if (i == 1) return str;
13093     var d = repeat_string(str, i >> 1);
13094     d += d;
13095     if (i & 1) d += str;
13096     return d;
13099 function defaults(args, defs) {
13100     var ret = {};
13101     if (args === true)
13102         args = {};
13103     for (var i in defs) if (HOP(defs, i)) {
13104         ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
13105     }
13106     return ret;
13109 function is_identifier(name) {
13110     return /^[a-z_$][a-z0-9_$]*$/i.test(name)
13111         && name != "this"
13112         && !HOP(jsp.KEYWORDS_ATOM, name)
13113         && !HOP(jsp.RESERVED_WORDS, name)
13114         && !HOP(jsp.KEYWORDS, name);
13117 function HOP(obj, prop) {
13118     return Object.prototype.hasOwnProperty.call(obj, prop);
13121 // some utilities
13123 var MAP;
13125 (function(){
13126     MAP = function(a, f, o) {
13127         var ret = [], top = [], i;
13128         function doit() {
13129             var val = f.call(o, a[i], i);
13130             if (val instanceof AtTop) {
13131                 val = val.v;
13132                 if (val instanceof Splice) {
13133                     top.push.apply(top, val.v);
13134                 } else {
13135                     top.push(val);
13136                 }
13137             }
13138             else if (val != skip) {
13139                 if (val instanceof Splice) {
13140                     ret.push.apply(ret, val.v);
13141                 } else {
13142                     ret.push(val);
13143                 }
13144             }
13145         };
13146         if (a instanceof Array) for (i = 0; i < a.length; ++i) doit();
13147         else for (i in a) if (HOP(a, i)) doit();
13148         return top.concat(ret);
13149     };
13150     MAP.at_top = function(val) { return new AtTop(val) };
13151     MAP.splice = function(val) { return new Splice(val) };
13152     var skip = MAP.skip = {};
13153     function AtTop(val) { this.v = val };
13154     function Splice(val) { this.v = val };
13155 })();
13157 /* -----[ Exports ]----- */
13159 exports.ast_walker = ast_walker;
13160 exports.ast_mangle = ast_mangle;
13161 exports.ast_squeeze = ast_squeeze;
13162 exports.ast_lift_variables = ast_lift_variables;
13163 exports.gen_code = gen_code;
13164 exports.ast_add_scope = ast_add_scope;
13165 exports.set_logger = function(logger) { warn = logger };
13166 exports.make_string = make_string;
13167 exports.split_lines = split_lines;
13168 exports.MAP = MAP;
13170 // keep this last!
13171 exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more;
13173 // Local variables:
13174 // js-indent-level: 4
13175 // End:
13177 define('uglifyjs/index', ["require", "exports", "module", "./parse-js", "./process", "./consolidator"], function(require, exports, module) {
13178 //convienence function(src, [options]);
13179 function uglify(orig_code, options){
13180   options || (options = {});
13181   var jsp = uglify.parser;
13182   var pro = uglify.uglify;
13184   var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST
13185   ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names
13186   ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations
13187   var final_code = pro.gen_code(ast, options.gen_options); // compressed code here
13188   return final_code;
13191 uglify.parser = require("./parse-js");
13192 uglify.uglify = require("./process");
13193 uglify.consolidator = require("./consolidator");
13195 module.exports = uglify
13196 });/* -*- Mode: js; js-indent-level: 2; -*- */
13198  * Copyright 2011 Mozilla Foundation and contributors
13199  * Licensed under the New BSD license. See LICENSE or:
13200  * http://opensource.org/licenses/BSD-3-Clause
13201  */
13203 define('source-map/array-set', function (require, exports, module) {
13205   var util = require('./util');
13207   /**
13208    * A data structure which is a combination of an array and a set. Adding a new
13209    * member is O(1), testing for membership is O(1), and finding the index of an
13210    * element is O(1). Removing elements from the set is not supported. Only
13211    * strings are supported for membership.
13212    */
13213   function ArraySet() {
13214     this._array = [];
13215     this._set = {};
13216   }
13218   /**
13219    * Static method for creating ArraySet instances from an existing array.
13220    */
13221   ArraySet.fromArray = function ArraySet_fromArray(aArray) {
13222     var set = new ArraySet();
13223     for (var i = 0, len = aArray.length; i < len; i++) {
13224       set.add(aArray[i]);
13225     }
13226     return set;
13227   };
13229   /**
13230    * Add the given string to this set.
13231    *
13232    * @param String aStr
13233    */
13234   ArraySet.prototype.add = function ArraySet_add(aStr) {
13235     if (this.has(aStr)) {
13236       // Already a member; nothing to do.
13237       return;
13238     }
13239     var idx = this._array.length;
13240     this._array.push(aStr);
13241     this._set[util.toSetString(aStr)] = idx;
13242   };
13244   /**
13245    * Is the given string a member of this set?
13246    *
13247    * @param String aStr
13248    */
13249   ArraySet.prototype.has = function ArraySet_has(aStr) {
13250     return Object.prototype.hasOwnProperty.call(this._set,
13251                                                 util.toSetString(aStr));
13252   };
13254   /**
13255    * What is the index of the given string in the array?
13256    *
13257    * @param String aStr
13258    */
13259   ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
13260     if (this.has(aStr)) {
13261       return this._set[util.toSetString(aStr)];
13262     }
13263     throw new Error('"' + aStr + '" is not in the set.');
13264   };
13266   /**
13267    * What is the element at the given index?
13268    *
13269    * @param Number aIdx
13270    */
13271   ArraySet.prototype.at = function ArraySet_at(aIdx) {
13272     if (aIdx >= 0 && aIdx < this._array.length) {
13273       return this._array[aIdx];
13274     }
13275     throw new Error('No element indexed by ' + aIdx);
13276   };
13278   /**
13279    * Returns the array representation of this set (which has the proper indices
13280    * indicated by indexOf). Note that this is a copy of the internal array used
13281    * for storing the members so that no one can mess with internal state.
13282    */
13283   ArraySet.prototype.toArray = function ArraySet_toArray() {
13284     return this._array.slice();
13285   };
13287   exports.ArraySet = ArraySet;
13290 /* -*- Mode: js; js-indent-level: 2; -*- */
13292  * Copyright 2011 Mozilla Foundation and contributors
13293  * Licensed under the New BSD license. See LICENSE or:
13294  * http://opensource.org/licenses/BSD-3-Clause
13296  * Based on the Base 64 VLQ implementation in Closure Compiler:
13297  * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
13299  * Copyright 2011 The Closure Compiler Authors. All rights reserved.
13300  * Redistribution and use in source and binary forms, with or without
13301  * modification, are permitted provided that the following conditions are
13302  * met:
13304  *  * Redistributions of source code must retain the above copyright
13305  *    notice, this list of conditions and the following disclaimer.
13306  *  * Redistributions in binary form must reproduce the above
13307  *    copyright notice, this list of conditions and the following
13308  *    disclaimer in the documentation and/or other materials provided
13309  *    with the distribution.
13310  *  * Neither the name of Google Inc. nor the names of its
13311  *    contributors may be used to endorse or promote products derived
13312  *    from this software without specific prior written permission.
13314  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
13315  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13316  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
13317  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
13318  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13319  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
13320  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
13321  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13322  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13323  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13324  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13325  */
13327 define('source-map/base64-vlq', function (require, exports, module) {
13329   var base64 = require('./base64');
13331   // A single base 64 digit can contain 6 bits of data. For the base 64 variable
13332   // length quantities we use in the source map spec, the first bit is the sign,
13333   // the next four bits are the actual value, and the 6th bit is the
13334   // continuation bit. The continuation bit tells us whether there are more
13335   // digits in this value following this digit.
13336   //
13337   //   Continuation
13338   //   |    Sign
13339   //   |    |
13340   //   V    V
13341   //   101011
13343   var VLQ_BASE_SHIFT = 5;
13345   // binary: 100000
13346   var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
13348   // binary: 011111
13349   var VLQ_BASE_MASK = VLQ_BASE - 1;
13351   // binary: 100000
13352   var VLQ_CONTINUATION_BIT = VLQ_BASE;
13354   /**
13355    * Converts from a two-complement value to a value where the sign bit is
13356    * is placed in the least significant bit.  For example, as decimals:
13357    *   1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
13358    *   2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
13359    */
13360   function toVLQSigned(aValue) {
13361     return aValue < 0
13362       ? ((-aValue) << 1) + 1
13363       : (aValue << 1) + 0;
13364   }
13366   /**
13367    * Converts to a two-complement value from a value where the sign bit is
13368    * is placed in the least significant bit.  For example, as decimals:
13369    *   2 (10 binary) becomes 1, 3 (11 binary) becomes -1
13370    *   4 (100 binary) becomes 2, 5 (101 binary) becomes -2
13371    */
13372   function fromVLQSigned(aValue) {
13373     var isNegative = (aValue & 1) === 1;
13374     var shifted = aValue >> 1;
13375     return isNegative
13376       ? -shifted
13377       : shifted;
13378   }
13380   /**
13381    * Returns the base 64 VLQ encoded value.
13382    */
13383   exports.encode = function base64VLQ_encode(aValue) {
13384     var encoded = "";
13385     var digit;
13387     var vlq = toVLQSigned(aValue);
13389     do {
13390       digit = vlq & VLQ_BASE_MASK;
13391       vlq >>>= VLQ_BASE_SHIFT;
13392       if (vlq > 0) {
13393         // There are still more digits in this value, so we must make sure the
13394         // continuation bit is marked.
13395         digit |= VLQ_CONTINUATION_BIT;
13396       }
13397       encoded += base64.encode(digit);
13398     } while (vlq > 0);
13400     return encoded;
13401   };
13403   /**
13404    * Decodes the next base 64 VLQ value from the given string and returns the
13405    * value and the rest of the string.
13406    */
13407   exports.decode = function base64VLQ_decode(aStr) {
13408     var i = 0;
13409     var strLen = aStr.length;
13410     var result = 0;
13411     var shift = 0;
13412     var continuation, digit;
13414     do {
13415       if (i >= strLen) {
13416         throw new Error("Expected more digits in base 64 VLQ value.");
13417       }
13418       digit = base64.decode(aStr.charAt(i++));
13419       continuation = !!(digit & VLQ_CONTINUATION_BIT);
13420       digit &= VLQ_BASE_MASK;
13421       result = result + (digit << shift);
13422       shift += VLQ_BASE_SHIFT;
13423     } while (continuation);
13425     return {
13426       value: fromVLQSigned(result),
13427       rest: aStr.slice(i)
13428     };
13429   };
13432 /* -*- Mode: js; js-indent-level: 2; -*- */
13434  * Copyright 2011 Mozilla Foundation and contributors
13435  * Licensed under the New BSD license. See LICENSE or:
13436  * http://opensource.org/licenses/BSD-3-Clause
13437  */
13439 define('source-map/base64', function (require, exports, module) {
13441   var charToIntMap = {};
13442   var intToCharMap = {};
13444   'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
13445     .split('')
13446     .forEach(function (ch, index) {
13447       charToIntMap[ch] = index;
13448       intToCharMap[index] = ch;
13449     });
13451   /**
13452    * Encode an integer in the range of 0 to 63 to a single base 64 digit.
13453    */
13454   exports.encode = function base64_encode(aNumber) {
13455     if (aNumber in intToCharMap) {
13456       return intToCharMap[aNumber];
13457     }
13458     throw new TypeError("Must be between 0 and 63: " + aNumber);
13459   };
13461   /**
13462    * Decode a single base 64 digit to an integer.
13463    */
13464   exports.decode = function base64_decode(aChar) {
13465     if (aChar in charToIntMap) {
13466       return charToIntMap[aChar];
13467     }
13468     throw new TypeError("Not a valid base 64 digit: " + aChar);
13469   };
13472 /* -*- Mode: js; js-indent-level: 2; -*- */
13474  * Copyright 2011 Mozilla Foundation and contributors
13475  * Licensed under the New BSD license. See LICENSE or:
13476  * http://opensource.org/licenses/BSD-3-Clause
13477  */
13479 define('source-map/binary-search', function (require, exports, module) {
13481   /**
13482    * Recursive implementation of binary search.
13483    *
13484    * @param aLow Indices here and lower do not contain the needle.
13485    * @param aHigh Indices here and higher do not contain the needle.
13486    * @param aNeedle The element being searched for.
13487    * @param aHaystack The non-empty array being searched.
13488    * @param aCompare Function which takes two elements and returns -1, 0, or 1.
13489    */
13490   function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) {
13491     // This function terminates when one of the following is true:
13492     //
13493     //   1. We find the exact element we are looking for.
13494     //
13495     //   2. We did not find the exact element, but we can return the next
13496     //      closest element that is less than that element.
13497     //
13498     //   3. We did not find the exact element, and there is no next-closest
13499     //      element which is less than the one we are searching for, so we
13500     //      return null.
13501     var mid = Math.floor((aHigh - aLow) / 2) + aLow;
13502     var cmp = aCompare(aNeedle, aHaystack[mid]);
13503     if (cmp === 0) {
13504       // Found the element we are looking for.
13505       return aHaystack[mid];
13506     }
13507     else if (cmp > 0) {
13508       // aHaystack[mid] is greater than our needle.
13509       if (aHigh - mid > 1) {
13510         // The element is in the upper half.
13511         return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare);
13512       }
13513       // We did not find an exact match, return the next closest one
13514       // (termination case 2).
13515       return aHaystack[mid];
13516     }
13517     else {
13518       // aHaystack[mid] is less than our needle.
13519       if (mid - aLow > 1) {
13520         // The element is in the lower half.
13521         return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare);
13522       }
13523       // The exact needle element was not found in this haystack. Determine if
13524       // we are in termination case (2) or (3) and return the appropriate thing.
13525       return aLow < 0
13526         ? null
13527         : aHaystack[aLow];
13528     }
13529   }
13531   /**
13532    * This is an implementation of binary search which will always try and return
13533    * the next lowest value checked if there is no exact hit. This is because
13534    * mappings between original and generated line/col pairs are single points,
13535    * and there is an implicit region between each of them, so a miss just means
13536    * that you aren't on the very start of a region.
13537    *
13538    * @param aNeedle The element you are looking for.
13539    * @param aHaystack The array that is being searched.
13540    * @param aCompare A function which takes the needle and an element in the
13541    *     array and returns -1, 0, or 1 depending on whether the needle is less
13542    *     than, equal to, or greater than the element, respectively.
13543    */
13544   exports.search = function search(aNeedle, aHaystack, aCompare) {
13545     return aHaystack.length > 0
13546       ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare)
13547       : null;
13548   };
13551 /* -*- Mode: js; js-indent-level: 2; -*- */
13553  * Copyright 2011 Mozilla Foundation and contributors
13554  * Licensed under the New BSD license. See LICENSE or:
13555  * http://opensource.org/licenses/BSD-3-Clause
13556  */
13558 define('source-map/source-map-consumer', function (require, exports, module) {
13560   var util = require('./util');
13561   var binarySearch = require('./binary-search');
13562   var ArraySet = require('./array-set').ArraySet;
13563   var base64VLQ = require('./base64-vlq');
13565   /**
13566    * A SourceMapConsumer instance represents a parsed source map which we can
13567    * query for information about the original file positions by giving it a file
13568    * position in the generated source.
13569    *
13570    * The only parameter is the raw source map (either as a JSON string, or
13571    * already parsed to an object). According to the spec, source maps have the
13572    * following attributes:
13573    *
13574    *   - version: Which version of the source map spec this map is following.
13575    *   - sources: An array of URLs to the original source files.
13576    *   - names: An array of identifiers which can be referrenced by individual mappings.
13577    *   - sourceRoot: Optional. The URL root from which all sources are relative.
13578    *   - sourcesContent: Optional. An array of contents of the original source files.
13579    *   - mappings: A string of base64 VLQs which contain the actual mappings.
13580    *   - file: The generated file this source map is associated with.
13581    *
13582    * Here is an example source map, taken from the source map spec[0]:
13583    *
13584    *     {
13585    *       version : 3,
13586    *       file: "out.js",
13587    *       sourceRoot : "",
13588    *       sources: ["foo.js", "bar.js"],
13589    *       names: ["src", "maps", "are", "fun"],
13590    *       mappings: "AA,AB;;ABCDE;"
13591    *     }
13592    *
13593    * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
13594    */
13595   function SourceMapConsumer(aSourceMap) {
13596     var sourceMap = aSourceMap;
13597     if (typeof aSourceMap === 'string') {
13598       sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
13599     }
13601     var version = util.getArg(sourceMap, 'version');
13602     var sources = util.getArg(sourceMap, 'sources');
13603     var names = util.getArg(sourceMap, 'names');
13604     var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
13605     var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
13606     var mappings = util.getArg(sourceMap, 'mappings');
13607     var file = util.getArg(sourceMap, 'file');
13609     if (version !== this._version) {
13610       throw new Error('Unsupported version: ' + version);
13611     }
13613     this._names = ArraySet.fromArray(names);
13614     this._sources = ArraySet.fromArray(sources);
13615     this.sourceRoot = sourceRoot;
13616     this.sourcesContent = sourcesContent;
13617     this.file = file;
13619     // `this._generatedMappings` and `this._originalMappings` hold the parsed
13620     // mapping coordinates from the source map's "mappings" attribute. Each
13621     // object in the array is of the form
13622     //
13623     //     {
13624     //       generatedLine: The line number in the generated code,
13625     //       generatedColumn: The column number in the generated code,
13626     //       source: The path to the original source file that generated this
13627     //               chunk of code,
13628     //       originalLine: The line number in the original source that
13629     //                     corresponds to this chunk of generated code,
13630     //       originalColumn: The column number in the original source that
13631     //                       corresponds to this chunk of generated code,
13632     //       name: The name of the original symbol which generated this chunk of
13633     //             code.
13634     //     }
13635     //
13636     // All properties except for `generatedLine` and `generatedColumn` can be
13637     // `null`.
13638     //
13639     // `this._generatedMappings` is ordered by the generated positions.
13640     //
13641     // `this._originalMappings` is ordered by the original positions.
13642     this._generatedMappings = [];
13643     this._originalMappings = [];
13644     this._parseMappings(mappings, sourceRoot);
13645   }
13647   /**
13648    * The version of the source mapping spec that we are consuming.
13649    */
13650   SourceMapConsumer.prototype._version = 3;
13652   /**
13653    * The list of original sources.
13654    */
13655   Object.defineProperty(SourceMapConsumer.prototype, 'sources', {
13656     get: function () {
13657       return this._sources.toArray().map(function (s) {
13658         return this.sourceRoot ? util.join(this.sourceRoot, s) : s;
13659       }, this);
13660     }
13661   });
13663   /**
13664    * Parse the mappings in a string in to a data structure which we can easily
13665    * query (an ordered list in this._generatedMappings).
13666    */
13667   SourceMapConsumer.prototype._parseMappings =
13668     function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
13669       var generatedLine = 1;
13670       var previousGeneratedColumn = 0;
13671       var previousOriginalLine = 0;
13672       var previousOriginalColumn = 0;
13673       var previousSource = 0;
13674       var previousName = 0;
13675       var mappingSeparator = /^[,;]/;
13676       var str = aStr;
13677       var mapping;
13678       var temp;
13680       while (str.length > 0) {
13681         if (str.charAt(0) === ';') {
13682           generatedLine++;
13683           str = str.slice(1);
13684           previousGeneratedColumn = 0;
13685         }
13686         else if (str.charAt(0) === ',') {
13687           str = str.slice(1);
13688         }
13689         else {
13690           mapping = {};
13691           mapping.generatedLine = generatedLine;
13693           // Generated column.
13694           temp = base64VLQ.decode(str);
13695           mapping.generatedColumn = previousGeneratedColumn + temp.value;
13696           previousGeneratedColumn = mapping.generatedColumn;
13697           str = temp.rest;
13699           if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
13700             // Original source.
13701             temp = base64VLQ.decode(str);
13702             mapping.source = this._sources.at(previousSource + temp.value);
13703             previousSource += temp.value;
13704             str = temp.rest;
13705             if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
13706               throw new Error('Found a source, but no line and column');
13707             }
13709             // Original line.
13710             temp = base64VLQ.decode(str);
13711             mapping.originalLine = previousOriginalLine + temp.value;
13712             previousOriginalLine = mapping.originalLine;
13713             // Lines are stored 0-based
13714             mapping.originalLine += 1;
13715             str = temp.rest;
13716             if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
13717               throw new Error('Found a source and line, but no column');
13718             }
13720             // Original column.
13721             temp = base64VLQ.decode(str);
13722             mapping.originalColumn = previousOriginalColumn + temp.value;
13723             previousOriginalColumn = mapping.originalColumn;
13724             str = temp.rest;
13726             if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
13727               // Original name.
13728               temp = base64VLQ.decode(str);
13729               mapping.name = this._names.at(previousName + temp.value);
13730               previousName += temp.value;
13731               str = temp.rest;
13732             }
13733           }
13735           this._generatedMappings.push(mapping);
13736           if (typeof mapping.originalLine === 'number') {
13737             this._originalMappings.push(mapping);
13738           }
13739         }
13740       }
13742       this._originalMappings.sort(this._compareOriginalPositions);
13743     };
13745   /**
13746    * Comparator between two mappings where the original positions are compared.
13747    */
13748   SourceMapConsumer.prototype._compareOriginalPositions =
13749     function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) {
13750       if (mappingA.source > mappingB.source) {
13751         return 1;
13752       }
13753       else if (mappingA.source < mappingB.source) {
13754         return -1;
13755       }
13756       else {
13757         var cmp = mappingA.originalLine - mappingB.originalLine;
13758         return cmp === 0
13759           ? mappingA.originalColumn - mappingB.originalColumn
13760           : cmp;
13761       }
13762     };
13764   /**
13765    * Comparator between two mappings where the generated positions are compared.
13766    */
13767   SourceMapConsumer.prototype._compareGeneratedPositions =
13768     function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) {
13769       var cmp = mappingA.generatedLine - mappingB.generatedLine;
13770       return cmp === 0
13771         ? mappingA.generatedColumn - mappingB.generatedColumn
13772         : cmp;
13773     };
13775   /**
13776    * Find the mapping that best matches the hypothetical "needle" mapping that
13777    * we are searching for in the given "haystack" of mappings.
13778    */
13779   SourceMapConsumer.prototype._findMapping =
13780     function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
13781                                            aColumnName, aComparator) {
13782       // To return the position we are searching for, we must first find the
13783       // mapping for the given position and then return the opposite position it
13784       // points to. Because the mappings are sorted, we can use binary search to
13785       // find the best mapping.
13787       if (aNeedle[aLineName] <= 0) {
13788         throw new TypeError('Line must be greater than or equal to 1, got '
13789                             + aNeedle[aLineName]);
13790       }
13791       if (aNeedle[aColumnName] < 0) {
13792         throw new TypeError('Column must be greater than or equal to 0, got '
13793                             + aNeedle[aColumnName]);
13794       }
13796       return binarySearch.search(aNeedle, aMappings, aComparator);
13797     };
13799   /**
13800    * Returns the original source, line, and column information for the generated
13801    * source's line and column positions provided. The only argument is an object
13802    * with the following properties:
13803    *
13804    *   - line: The line number in the generated source.
13805    *   - column: The column number in the generated source.
13806    *
13807    * and an object is returned with the following properties:
13808    *
13809    *   - source: The original source file, or null.
13810    *   - line: The line number in the original source, or null.
13811    *   - column: The column number in the original source, or null.
13812    *   - name: The original identifier, or null.
13813    */
13814   SourceMapConsumer.prototype.originalPositionFor =
13815     function SourceMapConsumer_originalPositionFor(aArgs) {
13816       var needle = {
13817         generatedLine: util.getArg(aArgs, 'line'),
13818         generatedColumn: util.getArg(aArgs, 'column')
13819       };
13821       var mapping = this._findMapping(needle,
13822                                       this._generatedMappings,
13823                                       "generatedLine",
13824                                       "generatedColumn",
13825                                       this._compareGeneratedPositions);
13827       if (mapping) {
13828         var source = util.getArg(mapping, 'source', null);
13829         if (source && this.sourceRoot) {
13830           source = util.join(this.sourceRoot, source);
13831         }
13832         return {
13833           source: source,
13834           line: util.getArg(mapping, 'originalLine', null),
13835           column: util.getArg(mapping, 'originalColumn', null),
13836           name: util.getArg(mapping, 'name', null)
13837         };
13838       }
13840       return {
13841         source: null,
13842         line: null,
13843         column: null,
13844         name: null
13845       };
13846     };
13848   /**
13849    * Returns the original source content. The only argument is the url of the
13850    * original source file. Returns null if no original source content is
13851    * availible.
13852    */
13853   SourceMapConsumer.prototype.sourceContentFor =
13854     function SourceMapConsumer_sourceContentFor(aSource) {
13855       if (!this.sourcesContent) {
13856         return null;
13857       }
13859       if (this.sourceRoot) {
13860         aSource = util.relative(this.sourceRoot, aSource);
13861       }
13863       if (this._sources.has(aSource)) {
13864         return this.sourcesContent[this._sources.indexOf(aSource)];
13865       }
13867       var url;
13868       if (this.sourceRoot
13869           && (url = util.urlParse(this.sourceRoot))) {
13870         // XXX: file:// URIs and absolute paths lead to unexpected behavior for
13871         // many users. We can help them out when they expect file:// URIs to
13872         // behave like it would if they were running a local HTTP server. See
13873         // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
13874         var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
13875         if (url.scheme == "file"
13876             && this._sources.has(fileUriAbsPath)) {
13877           return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
13878         }
13880         if ((!url.path || url.path == "/")
13881             && this._sources.has("/" + aSource)) {
13882           return this.sourcesContent[this._sources.indexOf("/" + aSource)];
13883         }
13884       }
13886       throw new Error('"' + aSource + '" is not in the SourceMap.');
13887     };
13889   /**
13890    * Returns the generated line and column information for the original source,
13891    * line, and column positions provided. The only argument is an object with
13892    * the following properties:
13893    *
13894    *   - source: The filename of the original source.
13895    *   - line: The line number in the original source.
13896    *   - column: The column number in the original source.
13897    *
13898    * and an object is returned with the following properties:
13899    *
13900    *   - line: The line number in the generated source, or null.
13901    *   - column: The column number in the generated source, or null.
13902    */
13903   SourceMapConsumer.prototype.generatedPositionFor =
13904     function SourceMapConsumer_generatedPositionFor(aArgs) {
13905       var needle = {
13906         source: util.getArg(aArgs, 'source'),
13907         originalLine: util.getArg(aArgs, 'line'),
13908         originalColumn: util.getArg(aArgs, 'column')
13909       };
13911       if (this.sourceRoot) {
13912         needle.source = util.relative(this.sourceRoot, needle.source);
13913       }
13915       var mapping = this._findMapping(needle,
13916                                       this._originalMappings,
13917                                       "originalLine",
13918                                       "originalColumn",
13919                                       this._compareOriginalPositions);
13921       if (mapping) {
13922         return {
13923           line: util.getArg(mapping, 'generatedLine', null),
13924           column: util.getArg(mapping, 'generatedColumn', null)
13925         };
13926       }
13928       return {
13929         line: null,
13930         column: null
13931       };
13932     };
13934   SourceMapConsumer.GENERATED_ORDER = 1;
13935   SourceMapConsumer.ORIGINAL_ORDER = 2;
13937   /**
13938    * Iterate over each mapping between an original source/line/column and a
13939    * generated line/column in this source map.
13940    *
13941    * @param Function aCallback
13942    *        The function that is called with each mapping.
13943    * @param Object aContext
13944    *        Optional. If specified, this object will be the value of `this` every
13945    *        time that `aCallback` is called.
13946    * @param aOrder
13947    *        Either `SourceMapConsumer.GENERATED_ORDER` or
13948    *        `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
13949    *        iterate over the mappings sorted by the generated file's line/column
13950    *        order or the original's source/line/column order, respectively. Defaults to
13951    *        `SourceMapConsumer.GENERATED_ORDER`.
13952    */
13953   SourceMapConsumer.prototype.eachMapping =
13954     function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
13955       var context = aContext || null;
13956       var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
13958       var mappings;
13959       switch (order) {
13960       case SourceMapConsumer.GENERATED_ORDER:
13961         mappings = this._generatedMappings;
13962         break;
13963       case SourceMapConsumer.ORIGINAL_ORDER:
13964         mappings = this._originalMappings;
13965         break;
13966       default:
13967         throw new Error("Unknown order of iteration.");
13968       }
13970       var sourceRoot = this.sourceRoot;
13971       mappings.map(function (mapping) {
13972         var source = mapping.source;
13973         if (source && sourceRoot) {
13974           source = util.join(sourceRoot, source);
13975         }
13976         return {
13977           source: source,
13978           generatedLine: mapping.generatedLine,
13979           generatedColumn: mapping.generatedColumn,
13980           originalLine: mapping.originalLine,
13981           originalColumn: mapping.originalColumn,
13982           name: mapping.name
13983         };
13984       }).forEach(aCallback, context);
13985     };
13987   exports.SourceMapConsumer = SourceMapConsumer;
13990 /* -*- Mode: js; js-indent-level: 2; -*- */
13992  * Copyright 2011 Mozilla Foundation and contributors
13993  * Licensed under the New BSD license. See LICENSE or:
13994  * http://opensource.org/licenses/BSD-3-Clause
13995  */
13997 define('source-map/source-map-generator', function (require, exports, module) {
13999   var base64VLQ = require('./base64-vlq');
14000   var util = require('./util');
14001   var ArraySet = require('./array-set').ArraySet;
14003   /**
14004    * An instance of the SourceMapGenerator represents a source map which is
14005    * being built incrementally. To create a new one, you must pass an object
14006    * with the following properties:
14007    *
14008    *   - file: The filename of the generated source.
14009    *   - sourceRoot: An optional root for all URLs in this source map.
14010    */
14011   function SourceMapGenerator(aArgs) {
14012     this._file = util.getArg(aArgs, 'file');
14013     this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
14014     this._sources = new ArraySet();
14015     this._names = new ArraySet();
14016     this._mappings = [];
14017     this._sourcesContents = null;
14018   }
14020   SourceMapGenerator.prototype._version = 3;
14022   /**
14023    * Creates a new SourceMapGenerator based on a SourceMapConsumer
14024    *
14025    * @param aSourceMapConsumer The SourceMap.
14026    */
14027   SourceMapGenerator.fromSourceMap =
14028     function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
14029       var sourceRoot = aSourceMapConsumer.sourceRoot;
14030       var generator = new SourceMapGenerator({
14031         file: aSourceMapConsumer.file,
14032         sourceRoot: sourceRoot
14033       });
14034       aSourceMapConsumer.eachMapping(function (mapping) {
14035         var newMapping = {
14036           generated: {
14037             line: mapping.generatedLine,
14038             column: mapping.generatedColumn
14039           }
14040         };
14042         if (mapping.source) {
14043           newMapping.source = mapping.source;
14044           if (sourceRoot) {
14045             newMapping.source = util.relative(sourceRoot, newMapping.source);
14046           }
14048           newMapping.original = {
14049             line: mapping.originalLine,
14050             column: mapping.originalColumn
14051           };
14053           if (mapping.name) {
14054             newMapping.name = mapping.name;
14055           }
14056         }
14058         generator.addMapping(newMapping);
14059       });
14060       aSourceMapConsumer.sources.forEach(function (sourceFile) {
14061         var content = aSourceMapConsumer.sourceContentFor(sourceFile);
14062         if (content) {
14063           generator.setSourceContent(sourceFile, content);
14064         }
14065       });
14066       return generator;
14067     };
14069   /**
14070    * Add a single mapping from original source line and column to the generated
14071    * source's line and column for this source map being created. The mapping
14072    * object should have the following properties:
14073    *
14074    *   - generated: An object with the generated line and column positions.
14075    *   - original: An object with the original line and column positions.
14076    *   - source: The original source file (relative to the sourceRoot).
14077    *   - name: An optional original token name for this mapping.
14078    */
14079   SourceMapGenerator.prototype.addMapping =
14080     function SourceMapGenerator_addMapping(aArgs) {
14081       var generated = util.getArg(aArgs, 'generated');
14082       var original = util.getArg(aArgs, 'original', null);
14083       var source = util.getArg(aArgs, 'source', null);
14084       var name = util.getArg(aArgs, 'name', null);
14086       this._validateMapping(generated, original, source, name);
14088       if (source && !this._sources.has(source)) {
14089         this._sources.add(source);
14090       }
14092       if (name && !this._names.has(name)) {
14093         this._names.add(name);
14094       }
14096       this._mappings.push({
14097         generated: generated,
14098         original: original,
14099         source: source,
14100         name: name
14101       });
14102     };
14104   /**
14105    * Set the source content for a source file.
14106    */
14107   SourceMapGenerator.prototype.setSourceContent =
14108     function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
14109       var source = aSourceFile;
14110       if (this._sourceRoot) {
14111         source = util.relative(this._sourceRoot, source);
14112       }
14114       if (aSourceContent !== null) {
14115         // Add the source content to the _sourcesContents map.
14116         // Create a new _sourcesContents map if the property is null.
14117         if (!this._sourcesContents) {
14118           this._sourcesContents = {};
14119         }
14120         this._sourcesContents[util.toSetString(source)] = aSourceContent;
14121       } else {
14122         // Remove the source file from the _sourcesContents map.
14123         // If the _sourcesContents map is empty, set the property to null.
14124         delete this._sourcesContents[util.toSetString(source)];
14125         if (Object.keys(this._sourcesContents).length === 0) {
14126           this._sourcesContents = null;
14127         }
14128       }
14129     };
14131   /**
14132    * Applies the mappings of a sub-source-map for a specific source file to the
14133    * source map being generated. Each mapping to the supplied source file is
14134    * rewritten using the supplied source map. Note: The resolution for the
14135    * resulting mappings is the minimium of this map and the supplied map.
14136    *
14137    * @param aSourceMapConsumer The source map to be applied.
14138    * @param aSourceFile Optional. The filename of the source file.
14139    *        If omitted, SourceMapConsumer's file property will be used.
14140    */
14141   SourceMapGenerator.prototype.applySourceMap =
14142     function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) {
14143       // If aSourceFile is omitted, we will use the file property of the SourceMap
14144       if (!aSourceFile) {
14145         aSourceFile = aSourceMapConsumer.file;
14146       }
14147       var sourceRoot = this._sourceRoot;
14148       // Make "aSourceFile" relative if an absolute Url is passed.
14149       if (sourceRoot) {
14150         aSourceFile = util.relative(sourceRoot, aSourceFile);
14151       }
14152       // Applying the SourceMap can add and remove items from the sources and
14153       // the names array.
14154       var newSources = new ArraySet();
14155       var newNames = new ArraySet();
14157       // Find mappings for the "aSourceFile"
14158       this._mappings.forEach(function (mapping) {
14159         if (mapping.source === aSourceFile && mapping.original) {
14160           // Check if it can be mapped by the source map, then update the mapping.
14161           var original = aSourceMapConsumer.originalPositionFor({
14162             line: mapping.original.line,
14163             column: mapping.original.column
14164           });
14165           if (original.source !== null) {
14166             // Copy mapping
14167             if (sourceRoot) {
14168               mapping.source = util.relative(sourceRoot, original.source);
14169             } else {
14170               mapping.source = original.source;
14171             }
14172             mapping.original.line = original.line;
14173             mapping.original.column = original.column;
14174             if (original.name !== null && mapping.name !== null) {
14175               // Only use the identifier name if it's an identifier
14176               // in both SourceMaps
14177               mapping.name = original.name;
14178             }
14179           }
14180         }
14182         var source = mapping.source;
14183         if (source && !newSources.has(source)) {
14184           newSources.add(source);
14185         }
14187         var name = mapping.name;
14188         if (name && !newNames.has(name)) {
14189           newNames.add(name);
14190         }
14192       }, this);
14193       this._sources = newSources;
14194       this._names = newNames;
14196       // Copy sourcesContents of applied map.
14197       aSourceMapConsumer.sources.forEach(function (sourceFile) {
14198         var content = aSourceMapConsumer.sourceContentFor(sourceFile);
14199         if (content) {
14200           if (sourceRoot) {
14201             sourceFile = util.relative(sourceRoot, sourceFile);
14202           }
14203           this.setSourceContent(sourceFile, content);
14204         }
14205       }, this);
14206     };
14208   /**
14209    * A mapping can have one of the three levels of data:
14210    *
14211    *   1. Just the generated position.
14212    *   2. The Generated position, original position, and original source.
14213    *   3. Generated and original position, original source, as well as a name
14214    *      token.
14215    *
14216    * To maintain consistency, we validate that any new mapping being added falls
14217    * in to one of these categories.
14218    */
14219   SourceMapGenerator.prototype._validateMapping =
14220     function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
14221                                                 aName) {
14222       if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
14223           && aGenerated.line > 0 && aGenerated.column >= 0
14224           && !aOriginal && !aSource && !aName) {
14225         // Case 1.
14226         return;
14227       }
14228       else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
14229                && aOriginal && 'line' in aOriginal && 'column' in aOriginal
14230                && aGenerated.line > 0 && aGenerated.column >= 0
14231                && aOriginal.line > 0 && aOriginal.column >= 0
14232                && aSource) {
14233         // Cases 2 and 3.
14234         return;
14235       }
14236       else {
14237         throw new Error('Invalid mapping.');
14238       }
14239     };
14241   function cmpLocation(loc1, loc2) {
14242     var cmp = (loc1 && loc1.line) - (loc2 && loc2.line);
14243     return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column);
14244   }
14246   function strcmp(str1, str2) {
14247     str1 = str1 || '';
14248     str2 = str2 || '';
14249     return (str1 > str2) - (str1 < str2);
14250   }
14252   function cmpMapping(mappingA, mappingB) {
14253     return cmpLocation(mappingA.generated, mappingB.generated) ||
14254       cmpLocation(mappingA.original, mappingB.original) ||
14255       strcmp(mappingA.source, mappingB.source) ||
14256       strcmp(mappingA.name, mappingB.name);
14257   }
14259   /**
14260    * Serialize the accumulated mappings in to the stream of base 64 VLQs
14261    * specified by the source map format.
14262    */
14263   SourceMapGenerator.prototype._serializeMappings =
14264     function SourceMapGenerator_serializeMappings() {
14265       var previousGeneratedColumn = 0;
14266       var previousGeneratedLine = 1;
14267       var previousOriginalColumn = 0;
14268       var previousOriginalLine = 0;
14269       var previousName = 0;
14270       var previousSource = 0;
14271       var result = '';
14272       var mapping;
14274       // The mappings must be guaranteed to be in sorted order before we start
14275       // serializing them or else the generated line numbers (which are defined
14276       // via the ';' separators) will be all messed up. Note: it might be more
14277       // performant to maintain the sorting as we insert them, rather than as we
14278       // serialize them, but the big O is the same either way.
14279       this._mappings.sort(cmpMapping);
14281       for (var i = 0, len = this._mappings.length; i < len; i++) {
14282         mapping = this._mappings[i];
14284         if (mapping.generated.line !== previousGeneratedLine) {
14285           previousGeneratedColumn = 0;
14286           while (mapping.generated.line !== previousGeneratedLine) {
14287             result += ';';
14288             previousGeneratedLine++;
14289           }
14290         }
14291         else {
14292           if (i > 0) {
14293             if (!cmpMapping(mapping, this._mappings[i - 1])) {
14294               continue;
14295             }
14296             result += ',';
14297           }
14298         }
14300         result += base64VLQ.encode(mapping.generated.column
14301                                    - previousGeneratedColumn);
14302         previousGeneratedColumn = mapping.generated.column;
14304         if (mapping.source && mapping.original) {
14305           result += base64VLQ.encode(this._sources.indexOf(mapping.source)
14306                                      - previousSource);
14307           previousSource = this._sources.indexOf(mapping.source);
14309           // lines are stored 0-based in SourceMap spec version 3
14310           result += base64VLQ.encode(mapping.original.line - 1
14311                                      - previousOriginalLine);
14312           previousOriginalLine = mapping.original.line - 1;
14314           result += base64VLQ.encode(mapping.original.column
14315                                      - previousOriginalColumn);
14316           previousOriginalColumn = mapping.original.column;
14318           if (mapping.name) {
14319             result += base64VLQ.encode(this._names.indexOf(mapping.name)
14320                                        - previousName);
14321             previousName = this._names.indexOf(mapping.name);
14322           }
14323         }
14324       }
14326       return result;
14327     };
14329   /**
14330    * Externalize the source map.
14331    */
14332   SourceMapGenerator.prototype.toJSON =
14333     function SourceMapGenerator_toJSON() {
14334       var map = {
14335         version: this._version,
14336         file: this._file,
14337         sources: this._sources.toArray(),
14338         names: this._names.toArray(),
14339         mappings: this._serializeMappings()
14340       };
14341       if (this._sourceRoot) {
14342         map.sourceRoot = this._sourceRoot;
14343       }
14344       if (this._sourcesContents) {
14345         map.sourcesContent = map.sources.map(function (source) {
14346           if (map.sourceRoot) {
14347             source = util.relative(map.sourceRoot, source);
14348           }
14349           return Object.prototype.hasOwnProperty.call(
14350             this._sourcesContents, util.toSetString(source))
14351             ? this._sourcesContents[util.toSetString(source)]
14352             : null;
14353         }, this);
14354       }
14355       return map;
14356     };
14358   /**
14359    * Render the source map being generated to a string.
14360    */
14361   SourceMapGenerator.prototype.toString =
14362     function SourceMapGenerator_toString() {
14363       return JSON.stringify(this);
14364     };
14366   exports.SourceMapGenerator = SourceMapGenerator;
14369 /* -*- Mode: js; js-indent-level: 2; -*- */
14371  * Copyright 2011 Mozilla Foundation and contributors
14372  * Licensed under the New BSD license. See LICENSE or:
14373  * http://opensource.org/licenses/BSD-3-Clause
14374  */
14376 define('source-map/source-node', function (require, exports, module) {
14378   var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;
14379   var util = require('./util');
14381   /**
14382    * SourceNodes provide a way to abstract over interpolating/concatenating
14383    * snippets of generated JavaScript source code while maintaining the line and
14384    * column information associated with the original source code.
14385    *
14386    * @param aLine The original line number.
14387    * @param aColumn The original column number.
14388    * @param aSource The original source's filename.
14389    * @param aChunks Optional. An array of strings which are snippets of
14390    *        generated JS, or other SourceNodes.
14391    * @param aName The original identifier.
14392    */
14393   function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
14394     this.children = [];
14395     this.sourceContents = {};
14396     this.line = aLine === undefined ? null : aLine;
14397     this.column = aColumn === undefined ? null : aColumn;
14398     this.source = aSource === undefined ? null : aSource;
14399     this.name = aName === undefined ? null : aName;
14400     if (aChunks != null) this.add(aChunks);
14401   }
14403   /**
14404    * Creates a SourceNode from generated code and a SourceMapConsumer.
14405    *
14406    * @param aGeneratedCode The generated code
14407    * @param aSourceMapConsumer The SourceMap for the generated code
14408    */
14409   SourceNode.fromStringWithSourceMap =
14410     function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) {
14411       // The SourceNode we want to fill with the generated code
14412       // and the SourceMap
14413       var node = new SourceNode();
14415       // The generated code
14416       // Processed fragments are removed from this array.
14417       var remainingLines = aGeneratedCode.split('\n');
14419       // We need to remember the position of "remainingLines"
14420       var lastGeneratedLine = 1, lastGeneratedColumn = 0;
14422       // The generate SourceNodes we need a code range.
14423       // To extract it current and last mapping is used.
14424       // Here we store the last mapping.
14425       var lastMapping = null;
14427       aSourceMapConsumer.eachMapping(function (mapping) {
14428         if (lastMapping === null) {
14429           // We add the generated code until the first mapping
14430           // to the SourceNode without any mapping.
14431           // Each line is added as separate string.
14432           while (lastGeneratedLine < mapping.generatedLine) {
14433             node.add(remainingLines.shift() + "\n");
14434             lastGeneratedLine++;
14435           }
14436           if (lastGeneratedColumn < mapping.generatedColumn) {
14437             var nextLine = remainingLines[0];
14438             node.add(nextLine.substr(0, mapping.generatedColumn));
14439             remainingLines[0] = nextLine.substr(mapping.generatedColumn);
14440             lastGeneratedColumn = mapping.generatedColumn;
14441           }
14442         } else {
14443           // We add the code from "lastMapping" to "mapping":
14444           // First check if there is a new line in between.
14445           if (lastGeneratedLine < mapping.generatedLine) {
14446             var code = "";
14447             // Associate full lines with "lastMapping"
14448             do {
14449               code += remainingLines.shift() + "\n";
14450               lastGeneratedLine++;
14451               lastGeneratedColumn = 0;
14452             } while (lastGeneratedLine < mapping.generatedLine);
14453             // When we reached the correct line, we add code until we
14454             // reach the correct column too.
14455             if (lastGeneratedColumn < mapping.generatedColumn) {
14456               var nextLine = remainingLines[0];
14457               code += nextLine.substr(0, mapping.generatedColumn);
14458               remainingLines[0] = nextLine.substr(mapping.generatedColumn);
14459               lastGeneratedColumn = mapping.generatedColumn;
14460             }
14461             // Create the SourceNode.
14462             addMappingWithCode(lastMapping, code);
14463           } else {
14464             // There is no new line in between.
14465             // Associate the code between "lastGeneratedColumn" and
14466             // "mapping.generatedColumn" with "lastMapping"
14467             var nextLine = remainingLines[0];
14468             var code = nextLine.substr(0, mapping.generatedColumn -
14469                                           lastGeneratedColumn);
14470             remainingLines[0] = nextLine.substr(mapping.generatedColumn -
14471                                                 lastGeneratedColumn);
14472             lastGeneratedColumn = mapping.generatedColumn;
14473             addMappingWithCode(lastMapping, code);
14474           }
14475         }
14476         lastMapping = mapping;
14477       }, this);
14478       // We have processed all mappings.
14479       // Associate the remaining code in the current line with "lastMapping"
14480       // and add the remaining lines without any mapping
14481       addMappingWithCode(lastMapping, remainingLines.join("\n"));
14483       // Copy sourcesContent into SourceNode
14484       aSourceMapConsumer.sources.forEach(function (sourceFile) {
14485         var content = aSourceMapConsumer.sourceContentFor(sourceFile);
14486         if (content) {
14487           node.setSourceContent(sourceFile, content);
14488         }
14489       });
14491       return node;
14493       function addMappingWithCode(mapping, code) {
14494         if (mapping.source === undefined) {
14495           node.add(code);
14496         } else {
14497           node.add(new SourceNode(mapping.originalLine,
14498                                   mapping.originalColumn,
14499                                   mapping.source,
14500                                   code,
14501                                   mapping.name));
14502         }
14503       }
14504     };
14506   /**
14507    * Add a chunk of generated JS to this source node.
14508    *
14509    * @param aChunk A string snippet of generated JS code, another instance of
14510    *        SourceNode, or an array where each member is one of those things.
14511    */
14512   SourceNode.prototype.add = function SourceNode_add(aChunk) {
14513     if (Array.isArray(aChunk)) {
14514       aChunk.forEach(function (chunk) {
14515         this.add(chunk);
14516       }, this);
14517     }
14518     else if (aChunk instanceof SourceNode || typeof aChunk === "string") {
14519       if (aChunk) {
14520         this.children.push(aChunk);
14521       }
14522     }
14523     else {
14524       throw new TypeError(
14525         "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
14526       );
14527     }
14528     return this;
14529   };
14531   /**
14532    * Add a chunk of generated JS to the beginning of this source node.
14533    *
14534    * @param aChunk A string snippet of generated JS code, another instance of
14535    *        SourceNode, or an array where each member is one of those things.
14536    */
14537   SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
14538     if (Array.isArray(aChunk)) {
14539       for (var i = aChunk.length-1; i >= 0; i--) {
14540         this.prepend(aChunk[i]);
14541       }
14542     }
14543     else if (aChunk instanceof SourceNode || typeof aChunk === "string") {
14544       this.children.unshift(aChunk);
14545     }
14546     else {
14547       throw new TypeError(
14548         "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
14549       );
14550     }
14551     return this;
14552   };
14554   /**
14555    * Walk over the tree of JS snippets in this node and its children. The
14556    * walking function is called once for each snippet of JS and is passed that
14557    * snippet and the its original associated source's line/column location.
14558    *
14559    * @param aFn The traversal function.
14560    */
14561   SourceNode.prototype.walk = function SourceNode_walk(aFn) {
14562     this.children.forEach(function (chunk) {
14563       if (chunk instanceof SourceNode) {
14564         chunk.walk(aFn);
14565       }
14566       else {
14567         if (chunk !== '') {
14568           aFn(chunk, { source: this.source,
14569                        line: this.line,
14570                        column: this.column,
14571                        name: this.name });
14572         }
14573       }
14574     }, this);
14575   };
14577   /**
14578    * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
14579    * each of `this.children`.
14580    *
14581    * @param aSep The separator.
14582    */
14583   SourceNode.prototype.join = function SourceNode_join(aSep) {
14584     var newChildren;
14585     var i;
14586     var len = this.children.length;
14587     if (len > 0) {
14588       newChildren = [];
14589       for (i = 0; i < len-1; i++) {
14590         newChildren.push(this.children[i]);
14591         newChildren.push(aSep);
14592       }
14593       newChildren.push(this.children[i]);
14594       this.children = newChildren;
14595     }
14596     return this;
14597   };
14599   /**
14600    * Call String.prototype.replace on the very right-most source snippet. Useful
14601    * for trimming whitespace from the end of a source node, etc.
14602    *
14603    * @param aPattern The pattern to replace.
14604    * @param aReplacement The thing to replace the pattern with.
14605    */
14606   SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
14607     var lastChild = this.children[this.children.length - 1];
14608     if (lastChild instanceof SourceNode) {
14609       lastChild.replaceRight(aPattern, aReplacement);
14610     }
14611     else if (typeof lastChild === 'string') {
14612       this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
14613     }
14614     else {
14615       this.children.push(''.replace(aPattern, aReplacement));
14616     }
14617     return this;
14618   };
14620   /**
14621    * Set the source content for a source file. This will be added to the SourceMapGenerator
14622    * in the sourcesContent field.
14623    *
14624    * @param aSourceFile The filename of the source file
14625    * @param aSourceContent The content of the source file
14626    */
14627   SourceNode.prototype.setSourceContent =
14628     function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
14629       this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
14630     };
14632   /**
14633    * Walk over the tree of SourceNodes. The walking function is called for each
14634    * source file content and is passed the filename and source content.
14635    *
14636    * @param aFn The traversal function.
14637    */
14638   SourceNode.prototype.walkSourceContents =
14639     function SourceNode_walkSourceContents(aFn) {
14640       this.children.forEach(function (chunk) {
14641         if (chunk instanceof SourceNode) {
14642           chunk.walkSourceContents(aFn);
14643         }
14644       }, this);
14645       Object.keys(this.sourceContents).forEach(function (sourceFileKey) {
14646         aFn(util.fromSetString(sourceFileKey), this.sourceContents[sourceFileKey]);
14647       }, this);
14648     };
14650   /**
14651    * Return the string representation of this source node. Walks over the tree
14652    * and concatenates all the various snippets together to one string.
14653    */
14654   SourceNode.prototype.toString = function SourceNode_toString() {
14655     var str = "";
14656     this.walk(function (chunk) {
14657       str += chunk;
14658     });
14659     return str;
14660   };
14662   /**
14663    * Returns the string representation of this source node along with a source
14664    * map.
14665    */
14666   SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
14667     var generated = {
14668       code: "",
14669       line: 1,
14670       column: 0
14671     };
14672     var map = new SourceMapGenerator(aArgs);
14673     var sourceMappingActive = false;
14674     this.walk(function (chunk, original) {
14675       generated.code += chunk;
14676       if (original.source !== null
14677           && original.line !== null
14678           && original.column !== null) {
14679         map.addMapping({
14680           source: original.source,
14681           original: {
14682             line: original.line,
14683             column: original.column
14684           },
14685           generated: {
14686             line: generated.line,
14687             column: generated.column
14688           },
14689           name: original.name
14690         });
14691         sourceMappingActive = true;
14692       } else if (sourceMappingActive) {
14693         map.addMapping({
14694           generated: {
14695             line: generated.line,
14696             column: generated.column
14697           }
14698         });
14699         sourceMappingActive = false;
14700       }
14701       chunk.split('').forEach(function (ch) {
14702         if (ch === '\n') {
14703           generated.line++;
14704           generated.column = 0;
14705         } else {
14706           generated.column++;
14707         }
14708       });
14709     });
14710     this.walkSourceContents(function (sourceFile, sourceContent) {
14711       map.setSourceContent(sourceFile, sourceContent);
14712     });
14714     return { code: generated.code, map: map };
14715   };
14717   exports.SourceNode = SourceNode;
14720 /* -*- Mode: js; js-indent-level: 2; -*- */
14722  * Copyright 2011 Mozilla Foundation and contributors
14723  * Licensed under the New BSD license. See LICENSE or:
14724  * http://opensource.org/licenses/BSD-3-Clause
14725  */
14727 define('source-map/util', function (require, exports, module) {
14729   /**
14730    * This is a helper function for getting values from parameter/options
14731    * objects.
14732    *
14733    * @param args The object we are extracting values from
14734    * @param name The name of the property we are getting.
14735    * @param defaultValue An optional value to return if the property is missing
14736    * from the object. If this is not specified and the property is missing, an
14737    * error will be thrown.
14738    */
14739   function getArg(aArgs, aName, aDefaultValue) {
14740     if (aName in aArgs) {
14741       return aArgs[aName];
14742     } else if (arguments.length === 3) {
14743       return aDefaultValue;
14744     } else {
14745       throw new Error('"' + aName + '" is a required argument.');
14746     }
14747   }
14748   exports.getArg = getArg;
14750   var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/;
14752   function urlParse(aUrl) {
14753     var match = aUrl.match(urlRegexp);
14754     if (!match) {
14755       return null;
14756     }
14757     return {
14758       scheme: match[1],
14759       auth: match[3],
14760       host: match[4],
14761       port: match[6],
14762       path: match[7]
14763     };
14764   }
14765   exports.urlParse = urlParse;
14767   function urlGenerate(aParsedUrl) {
14768     var url = aParsedUrl.scheme + "://";
14769     if (aParsedUrl.auth) {
14770       url += aParsedUrl.auth + "@"
14771     }
14772     if (aParsedUrl.host) {
14773       url += aParsedUrl.host;
14774     }
14775     if (aParsedUrl.port) {
14776       url += ":" + aParsedUrl.port
14777     }
14778     if (aParsedUrl.path) {
14779       url += aParsedUrl.path;
14780     }
14781     return url;
14782   }
14783   exports.urlGenerate = urlGenerate;
14785   function join(aRoot, aPath) {
14786     var url;
14788     if (aPath.match(urlRegexp)) {
14789       return aPath;
14790     }
14792     if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) {
14793       url.path = aPath;
14794       return urlGenerate(url);
14795     }
14797     return aRoot.replace(/\/$/, '') + '/' + aPath;
14798   }
14799   exports.join = join;
14801   /**
14802    * Because behavior goes wacky when you set `__proto__` on objects, we
14803    * have to prefix all the strings in our set with an arbitrary character.
14804    *
14805    * See https://github.com/mozilla/source-map/pull/31 and
14806    * https://github.com/mozilla/source-map/issues/30
14807    *
14808    * @param String aStr
14809    */
14810   function toSetString(aStr) {
14811     return '$' + aStr;
14812   }
14813   exports.toSetString = toSetString;
14815   function fromSetString(aStr) {
14816     return aStr.substr(1);
14817   }
14818   exports.fromSetString = fromSetString;
14820   function relative(aRoot, aPath) {
14821     aRoot = aRoot.replace(/\/$/, '');
14823     var url = urlParse(aRoot);
14824     if (aPath.charAt(0) == "/" && url && url.path == "/") {
14825       return aPath.slice(1);
14826     }
14828     return aPath.indexOf(aRoot + '/') === 0
14829       ? aPath.substr(aRoot.length + 1)
14830       : aPath;
14831   }
14832   exports.relative = relative;
14835 define('source-map', function (require, exports, module) {
14838  * Copyright 2009-2011 Mozilla Foundation and contributors
14839  * Licensed under the New BSD license. See LICENSE.txt or:
14840  * http://opensource.org/licenses/BSD-3-Clause
14841  */
14842 exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator;
14843 exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer;
14844 exports.SourceNode = require('./source-map/source-node').SourceNode;
14848 //Distributed under the BSD license:
14849 //Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
14850 define('uglifyjs2', ['exports', 'source-map', 'logger', 'env!env/file'], function (exports, MOZ_SourceMap, logger, rjsFile) {
14851 (function(exports, global) {
14852     global["UglifyJS"] = exports;
14853     "use strict";
14854     function array_to_hash(a) {
14855         var ret = Object.create(null);
14856         for (var i = 0; i < a.length; ++i) ret[a[i]] = true;
14857         return ret;
14858     }
14859     function slice(a, start) {
14860         return Array.prototype.slice.call(a, start || 0);
14861     }
14862     function characters(str) {
14863         return str.split("");
14864     }
14865     function member(name, array) {
14866         for (var i = array.length; --i >= 0; ) if (array[i] == name) return true;
14867         return false;
14868     }
14869     function find_if(func, array) {
14870         for (var i = 0, n = array.length; i < n; ++i) {
14871             if (func(array[i])) return array[i];
14872         }
14873     }
14874     function repeat_string(str, i) {
14875         if (i <= 0) return "";
14876         if (i == 1) return str;
14877         var d = repeat_string(str, i >> 1);
14878         d += d;
14879         if (i & 1) d += str;
14880         return d;
14881     }
14882     function DefaultsError(msg, defs) {
14883         this.msg = msg;
14884         this.defs = defs;
14885     }
14886     function defaults(args, defs, croak) {
14887         if (args === true) args = {};
14888         var ret = args || {};
14889         if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) throw new DefaultsError("`" + i + "` is not a supported option", defs);
14890         for (var i in defs) if (defs.hasOwnProperty(i)) {
14891             ret[i] = args && args.hasOwnProperty(i) ? args[i] : defs[i];
14892         }
14893         return ret;
14894     }
14895     function merge(obj, ext) {
14896         for (var i in ext) if (ext.hasOwnProperty(i)) {
14897             obj[i] = ext[i];
14898         }
14899         return obj;
14900     }
14901     function noop() {}
14902     var MAP = function() {
14903         function MAP(a, f, backwards) {
14904             var ret = [], top = [], i;
14905             function doit() {
14906                 var val = f(a[i], i);
14907                 var is_last = val instanceof Last;
14908                 if (is_last) val = val.v;
14909                 if (val instanceof AtTop) {
14910                     val = val.v;
14911                     if (val instanceof Splice) {
14912                         top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
14913                     } else {
14914                         top.push(val);
14915                     }
14916                 } else if (val !== skip) {
14917                     if (val instanceof Splice) {
14918                         ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
14919                     } else {
14920                         ret.push(val);
14921                     }
14922                 }
14923                 return is_last;
14924             }
14925             if (a instanceof Array) {
14926                 if (backwards) {
14927                     for (i = a.length; --i >= 0; ) if (doit()) break;
14928                     ret.reverse();
14929                     top.reverse();
14930                 } else {
14931                     for (i = 0; i < a.length; ++i) if (doit()) break;
14932                 }
14933             } else {
14934                 for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
14935             }
14936             return top.concat(ret);
14937         }
14938         MAP.at_top = function(val) {
14939             return new AtTop(val);
14940         };
14941         MAP.splice = function(val) {
14942             return new Splice(val);
14943         };
14944         MAP.last = function(val) {
14945             return new Last(val);
14946         };
14947         var skip = MAP.skip = {};
14948         function AtTop(val) {
14949             this.v = val;
14950         }
14951         function Splice(val) {
14952             this.v = val;
14953         }
14954         function Last(val) {
14955             this.v = val;
14956         }
14957         return MAP;
14958     }();
14959     function push_uniq(array, el) {
14960         if (array.indexOf(el) < 0) array.push(el);
14961     }
14962     function string_template(text, props) {
14963         return text.replace(/\{(.+?)\}/g, function(str, p) {
14964             return props[p];
14965         });
14966     }
14967     function remove(array, el) {
14968         for (var i = array.length; --i >= 0; ) {
14969             if (array[i] === el) array.splice(i, 1);
14970         }
14971     }
14972     function mergeSort(array, cmp) {
14973         if (array.length < 2) return array.slice();
14974         function merge(a, b) {
14975             var r = [], ai = 0, bi = 0, i = 0;
14976             while (ai < a.length && bi < b.length) {
14977                 cmp(a[ai], b[bi]) <= 0 ? r[i++] = a[ai++] : r[i++] = b[bi++];
14978             }
14979             if (ai < a.length) r.push.apply(r, a.slice(ai));
14980             if (bi < b.length) r.push.apply(r, b.slice(bi));
14981             return r;
14982         }
14983         function _ms(a) {
14984             if (a.length <= 1) return a;
14985             var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
14986             left = _ms(left);
14987             right = _ms(right);
14988             return merge(left, right);
14989         }
14990         return _ms(array);
14991     }
14992     function set_difference(a, b) {
14993         return a.filter(function(el) {
14994             return b.indexOf(el) < 0;
14995         });
14996     }
14997     function set_intersection(a, b) {
14998         return a.filter(function(el) {
14999             return b.indexOf(el) >= 0;
15000         });
15001     }
15002     function makePredicate(words) {
15003         if (!(words instanceof Array)) words = words.split(" ");
15004         var f = "", cats = [];
15005         out: for (var i = 0; i < words.length; ++i) {
15006             for (var j = 0; j < cats.length; ++j) if (cats[j][0].length == words[i].length) {
15007                 cats[j].push(words[i]);
15008                 continue out;
15009             }
15010             cats.push([ words[i] ]);
15011         }
15012         function compareTo(arr) {
15013             if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
15014             f += "switch(str){";
15015             for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
15016             f += "return true}return false;";
15017         }
15018         if (cats.length > 3) {
15019             cats.sort(function(a, b) {
15020                 return b.length - a.length;
15021             });
15022             f += "switch(str.length){";
15023             for (var i = 0; i < cats.length; ++i) {
15024                 var cat = cats[i];
15025                 f += "case " + cat[0].length + ":";
15026                 compareTo(cat);
15027             }
15028             f += "}";
15029         } else {
15030             compareTo(words);
15031         }
15032         return new Function("str", f);
15033     }
15034     function all(array, predicate) {
15035         for (var i = array.length; --i >= 0; ) if (!predicate(array[i])) return false;
15036         return true;
15037     }
15038     function Dictionary() {
15039         this._values = Object.create(null);
15040         this._size = 0;
15041     }
15042     Dictionary.prototype = {
15043         set: function(key, val) {
15044             if (!this.has(key)) ++this._size;
15045             this._values["$" + key] = val;
15046             return this;
15047         },
15048         add: function(key, val) {
15049             if (this.has(key)) {
15050                 this.get(key).push(val);
15051             } else {
15052                 this.set(key, [ val ]);
15053             }
15054             return this;
15055         },
15056         get: function(key) {
15057             return this._values["$" + key];
15058         },
15059         del: function(key) {
15060             if (this.has(key)) {
15061                 --this._size;
15062                 delete this._values["$" + key];
15063             }
15064             return this;
15065         },
15066         has: function(key) {
15067             return "$" + key in this._values;
15068         },
15069         each: function(f) {
15070             for (var i in this._values) f(this._values[i], i.substr(1));
15071         },
15072         size: function() {
15073             return this._size;
15074         },
15075         map: function(f) {
15076             var ret = [];
15077             for (var i in this._values) ret.push(f(this._values[i], i.substr(1)));
15078             return ret;
15079         }
15080     };
15081     "use strict";
15082     function DEFNODE(type, props, methods, base) {
15083         if (arguments.length < 4) base = AST_Node;
15084         if (!props) props = []; else props = props.split(/\s+/);
15085         var self_props = props;
15086         if (base && base.PROPS) props = props.concat(base.PROPS);
15087         var code = "return function AST_" + type + "(props){ if (props) { ";
15088         for (var i = props.length; --i >= 0; ) {
15089             code += "this." + props[i] + " = props." + props[i] + ";";
15090         }
15091         var proto = base && new base();
15092         if (proto && proto.initialize || methods && methods.initialize) code += "this.initialize();";
15093         code += "}}";
15094         var ctor = new Function(code)();
15095         if (proto) {
15096             ctor.prototype = proto;
15097             ctor.BASE = base;
15098         }
15099         if (base) base.SUBCLASSES.push(ctor);
15100         ctor.prototype.CTOR = ctor;
15101         ctor.PROPS = props || null;
15102         ctor.SELF_PROPS = self_props;
15103         ctor.SUBCLASSES = [];
15104         if (type) {
15105             ctor.prototype.TYPE = ctor.TYPE = type;
15106         }
15107         if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
15108             if (/^\$/.test(i)) {
15109                 ctor[i.substr(1)] = methods[i];
15110             } else {
15111                 ctor.prototype[i] = methods[i];
15112             }
15113         }
15114         ctor.DEFMETHOD = function(name, method) {
15115             this.prototype[name] = method;
15116         };
15117         return ctor;
15118     }
15119     var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", {}, null);
15120     var AST_Node = DEFNODE("Node", "start end", {
15121         clone: function() {
15122             return new this.CTOR(this);
15123         },
15124         $documentation: "Base class of all AST nodes",
15125         $propdoc: {
15126             start: "[AST_Token] The first token of this node",
15127             end: "[AST_Token] The last token of this node"
15128         },
15129         _walk: function(visitor) {
15130             return visitor._visit(this);
15131         },
15132         walk: function(visitor) {
15133             return this._walk(visitor);
15134         }
15135     }, null);
15136     AST_Node.warn_function = null;
15137     AST_Node.warn = function(txt, props) {
15138         if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
15139     };
15140     var AST_Statement = DEFNODE("Statement", null, {
15141         $documentation: "Base class of all statements"
15142     });
15143     var AST_Debugger = DEFNODE("Debugger", null, {
15144         $documentation: "Represents a debugger statement"
15145     }, AST_Statement);
15146     var AST_Directive = DEFNODE("Directive", "value scope", {
15147         $documentation: 'Represents a directive, like "use strict";',
15148         $propdoc: {
15149             value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
15150             scope: "[AST_Scope/S] The scope that this directive affects"
15151         }
15152     }, AST_Statement);
15153     var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
15154         $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
15155         $propdoc: {
15156             body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
15157         },
15158         _walk: function(visitor) {
15159             return visitor._visit(this, function() {
15160                 this.body._walk(visitor);
15161             });
15162         }
15163     }, AST_Statement);
15164     function walk_body(node, visitor) {
15165         if (node.body instanceof AST_Statement) {
15166             node.body._walk(visitor);
15167         } else node.body.forEach(function(stat) {
15168             stat._walk(visitor);
15169         });
15170     }
15171     var AST_Block = DEFNODE("Block", "body", {
15172         $documentation: "A body of statements (usually bracketed)",
15173         $propdoc: {
15174             body: "[AST_Statement*] an array of statements"
15175         },
15176         _walk: function(visitor) {
15177             return visitor._visit(this, function() {
15178                 walk_body(this, visitor);
15179             });
15180         }
15181     }, AST_Statement);
15182     var AST_BlockStatement = DEFNODE("BlockStatement", null, {
15183         $documentation: "A block statement"
15184     }, AST_Block);
15185     var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
15186         $documentation: "The empty statement (empty block or simply a semicolon)",
15187         _walk: function(visitor) {
15188             return visitor._visit(this);
15189         }
15190     }, AST_Statement);
15191     var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
15192         $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
15193         $propdoc: {
15194             body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
15195         },
15196         _walk: function(visitor) {
15197             return visitor._visit(this, function() {
15198                 this.body._walk(visitor);
15199             });
15200         }
15201     }, AST_Statement);
15202     var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
15203         $documentation: "Statement with a label",
15204         $propdoc: {
15205             label: "[AST_Label] a label definition"
15206         },
15207         _walk: function(visitor) {
15208             return visitor._visit(this, function() {
15209                 this.label._walk(visitor);
15210                 this.body._walk(visitor);
15211             });
15212         }
15213     }, AST_StatementWithBody);
15214     var AST_DWLoop = DEFNODE("DWLoop", "condition", {
15215         $documentation: "Base class for do/while statements",
15216         $propdoc: {
15217             condition: "[AST_Node] the loop condition.  Should not be instanceof AST_Statement"
15218         },
15219         _walk: function(visitor) {
15220             return visitor._visit(this, function() {
15221                 this.condition._walk(visitor);
15222                 this.body._walk(visitor);
15223             });
15224         }
15225     }, AST_StatementWithBody);
15226     var AST_Do = DEFNODE("Do", null, {
15227         $documentation: "A `do` statement"
15228     }, AST_DWLoop);
15229     var AST_While = DEFNODE("While", null, {
15230         $documentation: "A `while` statement"
15231     }, AST_DWLoop);
15232     var AST_For = DEFNODE("For", "init condition step", {
15233         $documentation: "A `for` statement",
15234         $propdoc: {
15235             init: "[AST_Node?] the `for` initialization code, or null if empty",
15236             condition: "[AST_Node?] the `for` termination clause, or null if empty",
15237             step: "[AST_Node?] the `for` update clause, or null if empty"
15238         },
15239         _walk: function(visitor) {
15240             return visitor._visit(this, function() {
15241                 if (this.init) this.init._walk(visitor);
15242                 if (this.condition) this.condition._walk(visitor);
15243                 if (this.step) this.step._walk(visitor);
15244                 this.body._walk(visitor);
15245             });
15246         }
15247     }, AST_StatementWithBody);
15248     var AST_ForIn = DEFNODE("ForIn", "init name object", {
15249         $documentation: "A `for ... in` statement",
15250         $propdoc: {
15251             init: "[AST_Node] the `for/in` initialization code",
15252             name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
15253             object: "[AST_Node] the object that we're looping through"
15254         },
15255         _walk: function(visitor) {
15256             return visitor._visit(this, function() {
15257                 this.init._walk(visitor);
15258                 this.object._walk(visitor);
15259                 this.body._walk(visitor);
15260             });
15261         }
15262     }, AST_StatementWithBody);
15263     var AST_With = DEFNODE("With", "expression", {
15264         $documentation: "A `with` statement",
15265         $propdoc: {
15266             expression: "[AST_Node] the `with` expression"
15267         },
15268         _walk: function(visitor) {
15269             return visitor._visit(this, function() {
15270                 this.expression._walk(visitor);
15271                 this.body._walk(visitor);
15272             });
15273         }
15274     }, AST_StatementWithBody);
15275     var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
15276         $documentation: "Base class for all statements introducing a lexical scope",
15277         $propdoc: {
15278             directives: "[string*/S] an array of directives declared in this scope",
15279             variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
15280             functions: "[Object/S] like `variables`, but only lists function declarations",
15281             uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
15282             uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
15283             parent_scope: "[AST_Scope?/S] link to the parent scope",
15284             enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
15285             cname: "[integer/S] current index for mangling variables (used internally by the mangler)"
15286         }
15287     }, AST_Block);
15288     var AST_Toplevel = DEFNODE("Toplevel", "globals", {
15289         $documentation: "The toplevel scope",
15290         $propdoc: {
15291             globals: "[Object/S] a map of name -> SymbolDef for all undeclared names"
15292         },
15293         wrap_enclose: function(arg_parameter_pairs) {
15294             var self = this;
15295             var args = [];
15296             var parameters = [];
15297             arg_parameter_pairs.forEach(function(pair) {
15298                 var split = pair.split(":");
15299                 args.push(split[0]);
15300                 parameters.push(split[1]);
15301             });
15302             var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
15303             wrapped_tl = parse(wrapped_tl);
15304             wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
15305                 if (node instanceof AST_Directive && node.value == "$ORIG") {
15306                     return MAP.splice(self.body);
15307                 }
15308             }));
15309             return wrapped_tl;
15310         },
15311         wrap_commonjs: function(name, export_all) {
15312             var self = this;
15313             var to_export = [];
15314             if (export_all) {
15315                 self.figure_out_scope();
15316                 self.walk(new TreeWalker(function(node) {
15317                     if (node instanceof AST_SymbolDeclaration && node.definition().global) {
15318                         if (!find_if(function(n) {
15319                             return n.name == node.name;
15320                         }, to_export)) to_export.push(node);
15321                     }
15322                 }));
15323             }
15324             var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
15325             wrapped_tl = parse(wrapped_tl);
15326             wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
15327                 if (node instanceof AST_SimpleStatement) {
15328                     node = node.body;
15329                     if (node instanceof AST_String) switch (node.getValue()) {
15330                       case "$ORIG":
15331                         return MAP.splice(self.body);
15333                       case "$EXPORTS":
15334                         var body = [];
15335                         to_export.forEach(function(sym) {
15336                             body.push(new AST_SimpleStatement({
15337                                 body: new AST_Assign({
15338                                     left: new AST_Sub({
15339                                         expression: new AST_SymbolRef({
15340                                             name: "exports"
15341                                         }),
15342                                         property: new AST_String({
15343                                             value: sym.name
15344                                         })
15345                                     }),
15346                                     operator: "=",
15347                                     right: new AST_SymbolRef(sym)
15348                                 })
15349                             }));
15350                         });
15351                         return MAP.splice(body);
15352                     }
15353                 }
15354             }));
15355             return wrapped_tl;
15356         }
15357     }, AST_Scope);
15358     var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
15359         $documentation: "Base class for functions",
15360         $propdoc: {
15361             name: "[AST_SymbolDeclaration?] the name of this function",
15362             argnames: "[AST_SymbolFunarg*] array of function arguments",
15363             uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
15364         },
15365         _walk: function(visitor) {
15366             return visitor._visit(this, function() {
15367                 if (this.name) this.name._walk(visitor);
15368                 this.argnames.forEach(function(arg) {
15369                     arg._walk(visitor);
15370                 });
15371                 walk_body(this, visitor);
15372             });
15373         }
15374     }, AST_Scope);
15375     var AST_Accessor = DEFNODE("Accessor", null, {
15376         $documentation: "A setter/getter function"
15377     }, AST_Lambda);
15378     var AST_Function = DEFNODE("Function", null, {
15379         $documentation: "A function expression"
15380     }, AST_Lambda);
15381     var AST_Defun = DEFNODE("Defun", null, {
15382         $documentation: "A function definition"
15383     }, AST_Lambda);
15384     var AST_Jump = DEFNODE("Jump", null, {
15385         $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
15386     }, AST_Statement);
15387     var AST_Exit = DEFNODE("Exit", "value", {
15388         $documentation: "Base class for “exits” (`return` and `throw`)",
15389         $propdoc: {
15390             value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
15391         },
15392         _walk: function(visitor) {
15393             return visitor._visit(this, this.value && function() {
15394                 this.value._walk(visitor);
15395             });
15396         }
15397     }, AST_Jump);
15398     var AST_Return = DEFNODE("Return", null, {
15399         $documentation: "A `return` statement"
15400     }, AST_Exit);
15401     var AST_Throw = DEFNODE("Throw", null, {
15402         $documentation: "A `throw` statement"
15403     }, AST_Exit);
15404     var AST_LoopControl = DEFNODE("LoopControl", "label", {
15405         $documentation: "Base class for loop control statements (`break` and `continue`)",
15406         $propdoc: {
15407             label: "[AST_LabelRef?] the label, or null if none"
15408         },
15409         _walk: function(visitor) {
15410             return visitor._visit(this, this.label && function() {
15411                 this.label._walk(visitor);
15412             });
15413         }
15414     }, AST_Jump);
15415     var AST_Break = DEFNODE("Break", null, {
15416         $documentation: "A `break` statement"
15417     }, AST_LoopControl);
15418     var AST_Continue = DEFNODE("Continue", null, {
15419         $documentation: "A `continue` statement"
15420     }, AST_LoopControl);
15421     var AST_If = DEFNODE("If", "condition alternative", {
15422         $documentation: "A `if` statement",
15423         $propdoc: {
15424             condition: "[AST_Node] the `if` condition",
15425             alternative: "[AST_Statement?] the `else` part, or null if not present"
15426         },
15427         _walk: function(visitor) {
15428             return visitor._visit(this, function() {
15429                 this.condition._walk(visitor);
15430                 this.body._walk(visitor);
15431                 if (this.alternative) this.alternative._walk(visitor);
15432             });
15433         }
15434     }, AST_StatementWithBody);
15435     var AST_Switch = DEFNODE("Switch", "expression", {
15436         $documentation: "A `switch` statement",
15437         $propdoc: {
15438             expression: "[AST_Node] the `switch` “discriminant”"
15439         },
15440         _walk: function(visitor) {
15441             return visitor._visit(this, function() {
15442                 this.expression._walk(visitor);
15443                 walk_body(this, visitor);
15444             });
15445         }
15446     }, AST_Block);
15447     var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
15448         $documentation: "Base class for `switch` branches"
15449     }, AST_Block);
15450     var AST_Default = DEFNODE("Default", null, {
15451         $documentation: "A `default` switch branch"
15452     }, AST_SwitchBranch);
15453     var AST_Case = DEFNODE("Case", "expression", {
15454         $documentation: "A `case` switch branch",
15455         $propdoc: {
15456             expression: "[AST_Node] the `case` expression"
15457         },
15458         _walk: function(visitor) {
15459             return visitor._visit(this, function() {
15460                 this.expression._walk(visitor);
15461                 walk_body(this, visitor);
15462             });
15463         }
15464     }, AST_SwitchBranch);
15465     var AST_Try = DEFNODE("Try", "bcatch bfinally", {
15466         $documentation: "A `try` statement",
15467         $propdoc: {
15468             bcatch: "[AST_Catch?] the catch block, or null if not present",
15469             bfinally: "[AST_Finally?] the finally block, or null if not present"
15470         },
15471         _walk: function(visitor) {
15472             return visitor._visit(this, function() {
15473                 walk_body(this, visitor);
15474                 if (this.bcatch) this.bcatch._walk(visitor);
15475                 if (this.bfinally) this.bfinally._walk(visitor);
15476             });
15477         }
15478     }, AST_Block);
15479     var AST_Catch = DEFNODE("Catch", "argname", {
15480         $documentation: "A `catch` node; only makes sense as part of a `try` statement",
15481         $propdoc: {
15482             argname: "[AST_SymbolCatch] symbol for the exception"
15483         },
15484         _walk: function(visitor) {
15485             return visitor._visit(this, function() {
15486                 this.argname._walk(visitor);
15487                 walk_body(this, visitor);
15488             });
15489         }
15490     }, AST_Block);
15491     var AST_Finally = DEFNODE("Finally", null, {
15492         $documentation: "A `finally` node; only makes sense as part of a `try` statement"
15493     }, AST_Block);
15494     var AST_Definitions = DEFNODE("Definitions", "definitions", {
15495         $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
15496         $propdoc: {
15497             definitions: "[AST_VarDef*] array of variable definitions"
15498         },
15499         _walk: function(visitor) {
15500             return visitor._visit(this, function() {
15501                 this.definitions.forEach(function(def) {
15502                     def._walk(visitor);
15503                 });
15504             });
15505         }
15506     }, AST_Statement);
15507     var AST_Var = DEFNODE("Var", null, {
15508         $documentation: "A `var` statement"
15509     }, AST_Definitions);
15510     var AST_Const = DEFNODE("Const", null, {
15511         $documentation: "A `const` statement"
15512     }, AST_Definitions);
15513     var AST_VarDef = DEFNODE("VarDef", "name value", {
15514         $documentation: "A variable declaration; only appears in a AST_Definitions node",
15515         $propdoc: {
15516             name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
15517             value: "[AST_Node?] initializer, or null of there's no initializer"
15518         },
15519         _walk: function(visitor) {
15520             return visitor._visit(this, function() {
15521                 this.name._walk(visitor);
15522                 if (this.value) this.value._walk(visitor);
15523             });
15524         }
15525     });
15526     var AST_Call = DEFNODE("Call", "expression args", {
15527         $documentation: "A function call expression",
15528         $propdoc: {
15529             expression: "[AST_Node] expression to invoke as function",
15530             args: "[AST_Node*] array of arguments"
15531         },
15532         _walk: function(visitor) {
15533             return visitor._visit(this, function() {
15534                 this.expression._walk(visitor);
15535                 this.args.forEach(function(arg) {
15536                     arg._walk(visitor);
15537                 });
15538             });
15539         }
15540     });
15541     var AST_New = DEFNODE("New", null, {
15542         $documentation: "An object instantiation.  Derives from a function call since it has exactly the same properties"
15543     }, AST_Call);
15544     var AST_Seq = DEFNODE("Seq", "car cdr", {
15545         $documentation: "A sequence expression (two comma-separated expressions)",
15546         $propdoc: {
15547             car: "[AST_Node] first element in sequence",
15548             cdr: "[AST_Node] second element in sequence"
15549         },
15550         $cons: function(x, y) {
15551             var seq = new AST_Seq(x);
15552             seq.car = x;
15553             seq.cdr = y;
15554             return seq;
15555         },
15556         $from_array: function(array) {
15557             if (array.length == 0) return null;
15558             if (array.length == 1) return array[0].clone();
15559             var list = null;
15560             for (var i = array.length; --i >= 0; ) {
15561                 list = AST_Seq.cons(array[i], list);
15562             }
15563             var p = list;
15564             while (p) {
15565                 if (p.cdr && !p.cdr.cdr) {
15566                     p.cdr = p.cdr.car;
15567                     break;
15568                 }
15569                 p = p.cdr;
15570             }
15571             return list;
15572         },
15573         to_array: function() {
15574             var p = this, a = [];
15575             while (p) {
15576                 a.push(p.car);
15577                 if (p.cdr && !(p.cdr instanceof AST_Seq)) {
15578                     a.push(p.cdr);
15579                     break;
15580                 }
15581                 p = p.cdr;
15582             }
15583             return a;
15584         },
15585         add: function(node) {
15586             var p = this;
15587             while (p) {
15588                 if (!(p.cdr instanceof AST_Seq)) {
15589                     var cell = AST_Seq.cons(p.cdr, node);
15590                     return p.cdr = cell;
15591                 }
15592                 p = p.cdr;
15593             }
15594         },
15595         _walk: function(visitor) {
15596             return visitor._visit(this, function() {
15597                 this.car._walk(visitor);
15598                 if (this.cdr) this.cdr._walk(visitor);
15599             });
15600         }
15601     });
15602     var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
15603         $documentation: 'Base class for property access expressions, i.e. `a.foo` or `a["foo"]`',
15604         $propdoc: {
15605             expression: "[AST_Node] the “container” expression",
15606             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"
15607         }
15608     });
15609     var AST_Dot = DEFNODE("Dot", null, {
15610         $documentation: "A dotted property access expression",
15611         _walk: function(visitor) {
15612             return visitor._visit(this, function() {
15613                 this.expression._walk(visitor);
15614             });
15615         }
15616     }, AST_PropAccess);
15617     var AST_Sub = DEFNODE("Sub", null, {
15618         $documentation: 'Index-style property access, i.e. `a["foo"]`',
15619         _walk: function(visitor) {
15620             return visitor._visit(this, function() {
15621                 this.expression._walk(visitor);
15622                 this.property._walk(visitor);
15623             });
15624         }
15625     }, AST_PropAccess);
15626     var AST_Unary = DEFNODE("Unary", "operator expression", {
15627         $documentation: "Base class for unary expressions",
15628         $propdoc: {
15629             operator: "[string] the operator",
15630             expression: "[AST_Node] expression that this unary operator applies to"
15631         },
15632         _walk: function(visitor) {
15633             return visitor._visit(this, function() {
15634                 this.expression._walk(visitor);
15635             });
15636         }
15637     });
15638     var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
15639         $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
15640     }, AST_Unary);
15641     var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
15642         $documentation: "Unary postfix expression, i.e. `i++`"
15643     }, AST_Unary);
15644     var AST_Binary = DEFNODE("Binary", "left operator right", {
15645         $documentation: "Binary expression, i.e. `a + b`",
15646         $propdoc: {
15647             left: "[AST_Node] left-hand side expression",
15648             operator: "[string] the operator",
15649             right: "[AST_Node] right-hand side expression"
15650         },
15651         _walk: function(visitor) {
15652             return visitor._visit(this, function() {
15653                 this.left._walk(visitor);
15654                 this.right._walk(visitor);
15655             });
15656         }
15657     });
15658     var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
15659         $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
15660         $propdoc: {
15661             condition: "[AST_Node]",
15662             consequent: "[AST_Node]",
15663             alternative: "[AST_Node]"
15664         },
15665         _walk: function(visitor) {
15666             return visitor._visit(this, function() {
15667                 this.condition._walk(visitor);
15668                 this.consequent._walk(visitor);
15669                 this.alternative._walk(visitor);
15670             });
15671         }
15672     });
15673     var AST_Assign = DEFNODE("Assign", null, {
15674         $documentation: "An assignment expression — `a = b + 5`"
15675     }, AST_Binary);
15676     var AST_Array = DEFNODE("Array", "elements", {
15677         $documentation: "An array literal",
15678         $propdoc: {
15679             elements: "[AST_Node*] array of elements"
15680         },
15681         _walk: function(visitor) {
15682             return visitor._visit(this, function() {
15683                 this.elements.forEach(function(el) {
15684                     el._walk(visitor);
15685                 });
15686             });
15687         }
15688     });
15689     var AST_Object = DEFNODE("Object", "properties", {
15690         $documentation: "An object literal",
15691         $propdoc: {
15692             properties: "[AST_ObjectProperty*] array of properties"
15693         },
15694         _walk: function(visitor) {
15695             return visitor._visit(this, function() {
15696                 this.properties.forEach(function(prop) {
15697                     prop._walk(visitor);
15698                 });
15699             });
15700         }
15701     });
15702     var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
15703         $documentation: "Base class for literal object properties",
15704         $propdoc: {
15705             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",
15706             value: "[AST_Node] property value.  For setters and getters this is an AST_Function."
15707         },
15708         _walk: function(visitor) {
15709             return visitor._visit(this, function() {
15710                 this.value._walk(visitor);
15711             });
15712         }
15713     });
15714     var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, {
15715         $documentation: "A key: value object property"
15716     }, AST_ObjectProperty);
15717     var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
15718         $documentation: "An object setter property"
15719     }, AST_ObjectProperty);
15720     var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
15721         $documentation: "An object getter property"
15722     }, AST_ObjectProperty);
15723     var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
15724         $propdoc: {
15725             name: "[string] name of this symbol",
15726             scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
15727             thedef: "[SymbolDef/S] the definition of this symbol"
15728         },
15729         $documentation: "Base class for all symbols"
15730     });
15731     var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
15732         $documentation: "The name of a property accessor (setter/getter function)"
15733     }, AST_Symbol);
15734     var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
15735         $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
15736         $propdoc: {
15737             init: "[AST_Node*/S] array of initializers for this declaration."
15738         }
15739     }, AST_Symbol);
15740     var AST_SymbolVar = DEFNODE("SymbolVar", null, {
15741         $documentation: "Symbol defining a variable"
15742     }, AST_SymbolDeclaration);
15743     var AST_SymbolConst = DEFNODE("SymbolConst", null, {
15744         $documentation: "A constant declaration"
15745     }, AST_SymbolDeclaration);
15746     var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
15747         $documentation: "Symbol naming a function argument"
15748     }, AST_SymbolVar);
15749     var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
15750         $documentation: "Symbol defining a function"
15751     }, AST_SymbolDeclaration);
15752     var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
15753         $documentation: "Symbol naming a function expression"
15754     }, AST_SymbolDeclaration);
15755     var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
15756         $documentation: "Symbol naming the exception in catch"
15757     }, AST_SymbolDeclaration);
15758     var AST_Label = DEFNODE("Label", "references", {
15759         $documentation: "Symbol naming a label (declaration)",
15760         $propdoc: {
15761             references: "[AST_LabelRef*] a list of nodes referring to this label"
15762         }
15763     }, AST_Symbol);
15764     var AST_SymbolRef = DEFNODE("SymbolRef", null, {
15765         $documentation: "Reference to some symbol (not definition/declaration)"
15766     }, AST_Symbol);
15767     var AST_LabelRef = DEFNODE("LabelRef", null, {
15768         $documentation: "Reference to a label symbol"
15769     }, AST_Symbol);
15770     var AST_This = DEFNODE("This", null, {
15771         $documentation: "The `this` symbol"
15772     }, AST_Symbol);
15773     var AST_Constant = DEFNODE("Constant", null, {
15774         $documentation: "Base class for all constants",
15775         getValue: function() {
15776             return this.value;
15777         }
15778     });
15779     var AST_String = DEFNODE("String", "value", {
15780         $documentation: "A string literal",
15781         $propdoc: {
15782             value: "[string] the contents of this string"
15783         }
15784     }, AST_Constant);
15785     var AST_Number = DEFNODE("Number", "value", {
15786         $documentation: "A number literal",
15787         $propdoc: {
15788             value: "[number] the numeric value"
15789         }
15790     }, AST_Constant);
15791     var AST_RegExp = DEFNODE("RegExp", "value", {
15792         $documentation: "A regexp literal",
15793         $propdoc: {
15794             value: "[RegExp] the actual regexp"
15795         }
15796     }, AST_Constant);
15797     var AST_Atom = DEFNODE("Atom", null, {
15798         $documentation: "Base class for atoms"
15799     }, AST_Constant);
15800     var AST_Null = DEFNODE("Null", null, {
15801         $documentation: "The `null` atom",
15802         value: null
15803     }, AST_Atom);
15804     var AST_NaN = DEFNODE("NaN", null, {
15805         $documentation: "The impossible value",
15806         value: 0 / 0
15807     }, AST_Atom);
15808     var AST_Undefined = DEFNODE("Undefined", null, {
15809         $documentation: "The `undefined` value",
15810         value: function() {}()
15811     }, AST_Atom);
15812     var AST_Hole = DEFNODE("Hole", null, {
15813         $documentation: "A hole in an array",
15814         value: function() {}()
15815     }, AST_Atom);
15816     var AST_Infinity = DEFNODE("Infinity", null, {
15817         $documentation: "The `Infinity` value",
15818         value: 1 / 0
15819     }, AST_Atom);
15820     var AST_Boolean = DEFNODE("Boolean", null, {
15821         $documentation: "Base class for booleans"
15822     }, AST_Atom);
15823     var AST_False = DEFNODE("False", null, {
15824         $documentation: "The `false` atom",
15825         value: false
15826     }, AST_Boolean);
15827     var AST_True = DEFNODE("True", null, {
15828         $documentation: "The `true` atom",
15829         value: true
15830     }, AST_Boolean);
15831     function TreeWalker(callback) {
15832         this.visit = callback;
15833         this.stack = [];
15834     }
15835     TreeWalker.prototype = {
15836         _visit: function(node, descend) {
15837             this.stack.push(node);
15838             var ret = this.visit(node, descend ? function() {
15839                 descend.call(node);
15840             } : noop);
15841             if (!ret && descend) {
15842                 descend.call(node);
15843             }
15844             this.stack.pop();
15845             return ret;
15846         },
15847         parent: function(n) {
15848             return this.stack[this.stack.length - 2 - (n || 0)];
15849         },
15850         push: function(node) {
15851             this.stack.push(node);
15852         },
15853         pop: function() {
15854             return this.stack.pop();
15855         },
15856         self: function() {
15857             return this.stack[this.stack.length - 1];
15858         },
15859         find_parent: function(type) {
15860             var stack = this.stack;
15861             for (var i = stack.length; --i >= 0; ) {
15862                 var x = stack[i];
15863                 if (x instanceof type) return x;
15864             }
15865         },
15866         in_boolean_context: function() {
15867             var stack = this.stack;
15868             var i = stack.length, self = stack[--i];
15869             while (i > 0) {
15870                 var p = stack[--i];
15871                 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) {
15872                     return true;
15873                 }
15874                 if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) return false;
15875                 self = p;
15876             }
15877         },
15878         loopcontrol_target: function(label) {
15879             var stack = this.stack;
15880             if (label) {
15881                 for (var i = stack.length; --i >= 0; ) {
15882                     var x = stack[i];
15883                     if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
15884                         return x.body;
15885                     }
15886                 }
15887             } else {
15888                 for (var i = stack.length; --i >= 0; ) {
15889                     var x = stack[i];
15890                     if (x instanceof AST_Switch || x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) return x;
15891                 }
15892             }
15893         }
15894     };
15895     "use strict";
15896     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";
15897     var KEYWORDS_ATOM = "false null true";
15898     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;
15899     var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case";
15900     KEYWORDS = makePredicate(KEYWORDS);
15901     RESERVED_WORDS = makePredicate(RESERVED_WORDS);
15902     KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
15903     KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
15904     var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
15905     var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
15906     var RE_OCT_NUMBER = /^0[0-7]+$/;
15907     var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
15908     var OPERATORS = makePredicate([ "in", "instanceof", "typeof", "new", "void", "delete", "++", "--", "+", "-", "!", "~", "&", "|", "^", "*", "/", "%", ">>", "<<", ">>>", "<", ">", "<=", ">=", "==", "===", "!=", "!==", "?", "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=", "&&", "||" ]);
15909     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"));
15910     var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
15911     var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
15912     var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
15913     var UNICODE = {
15914         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]"),
15915         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]"),
15916         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]"),
15917         connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
15918     };
15919     function is_letter(code) {
15920         return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 170 && UNICODE.letter.test(String.fromCharCode(code));
15921     }
15922     function is_digit(code) {
15923         return code >= 48 && code <= 57;
15924     }
15925     function is_alphanumeric_char(code) {
15926         return is_digit(code) || is_letter(code);
15927     }
15928     function is_unicode_combining_mark(ch) {
15929         return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
15930     }
15931     function is_unicode_connector_punctuation(ch) {
15932         return UNICODE.connector_punctuation.test(ch);
15933     }
15934     function is_identifier(name) {
15935         return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
15936     }
15937     function is_identifier_start(code) {
15938         return code == 36 || code == 95 || is_letter(code);
15939     }
15940     function is_identifier_char(ch) {
15941         var code = ch.charCodeAt(0);
15942         return is_identifier_start(code) || is_digit(code) || code == 8204 || code == 8205 || is_unicode_combining_mark(ch) || is_unicode_connector_punctuation(ch);
15943     }
15944     function is_identifier_string(str) {
15945         var i = str.length;
15946         if (i == 0) return false;
15947         if (is_digit(str.charCodeAt(0))) return false;
15948         while (--i >= 0) {
15949             if (!is_identifier_char(str.charAt(i))) return false;
15950         }
15951         return true;
15952     }
15953     function parse_js_number(num) {
15954         if (RE_HEX_NUMBER.test(num)) {
15955             return parseInt(num.substr(2), 16);
15956         } else if (RE_OCT_NUMBER.test(num)) {
15957             return parseInt(num.substr(1), 8);
15958         } else if (RE_DEC_NUMBER.test(num)) {
15959             return parseFloat(num);
15960         }
15961     }
15962     function JS_Parse_Error(message, line, col, pos) {
15963         this.message = message;
15964         this.line = line;
15965         this.col = col;
15966         this.pos = pos;
15967         this.stack = new Error().stack;
15968     }
15969     JS_Parse_Error.prototype.toString = function() {
15970         return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
15971     };
15972     function js_error(message, filename, line, col, pos) {
15973         throw new JS_Parse_Error(message, line, col, pos);
15974     }
15975     function is_token(token, type, val) {
15976         return token.type == type && (val == null || token.value == val);
15977     }
15978     var EX_EOF = {};
15979     function tokenizer($TEXT, filename) {
15980         var S = {
15981             text: $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ""),
15982             filename: filename,
15983             pos: 0,
15984             tokpos: 0,
15985             line: 1,
15986             tokline: 0,
15987             col: 0,
15988             tokcol: 0,
15989             newline_before: false,
15990             regex_allowed: false,
15991             comments_before: []
15992         };
15993         function peek() {
15994             return S.text.charAt(S.pos);
15995         }
15996         function next(signal_eof, in_string) {
15997             var ch = S.text.charAt(S.pos++);
15998             if (signal_eof && !ch) throw EX_EOF;
15999             if (ch == "\n") {
16000                 S.newline_before = S.newline_before || !in_string;
16001                 ++S.line;
16002                 S.col = 0;
16003             } else {
16004                 ++S.col;
16005             }
16006             return ch;
16007         }
16008         function find(what, signal_eof) {
16009             var pos = S.text.indexOf(what, S.pos);
16010             if (signal_eof && pos == -1) throw EX_EOF;
16011             return pos;
16012         }
16013         function start_token() {
16014             S.tokline = S.line;
16015             S.tokcol = S.col;
16016             S.tokpos = S.pos;
16017         }
16018         function token(type, value, is_comment) {
16019             S.regex_allowed = type == "operator" && !UNARY_POSTFIX[value] || type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value) || type == "punc" && PUNC_BEFORE_EXPRESSION(value);
16020             var ret = {
16021                 type: type,
16022                 value: value,
16023                 line: S.tokline,
16024                 col: S.tokcol,
16025                 pos: S.tokpos,
16026                 endpos: S.pos,
16027                 nlb: S.newline_before,
16028                 file: filename
16029             };
16030             if (!is_comment) {
16031                 ret.comments_before = S.comments_before;
16032                 S.comments_before = [];
16033                 for (var i = 0, len = ret.comments_before.length; i < len; i++) {
16034                     ret.nlb = ret.nlb || ret.comments_before[i].nlb;
16035                 }
16036             }
16037             S.newline_before = false;
16038             return new AST_Token(ret);
16039         }
16040         function skip_whitespace() {
16041             while (WHITESPACE_CHARS(peek())) next();
16042         }
16043         function read_while(pred) {
16044             var ret = "", ch, i = 0;
16045             while ((ch = peek()) && pred(ch, i++)) ret += next();
16046             return ret;
16047         }
16048         function parse_error(err) {
16049             js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
16050         }
16051         function read_num(prefix) {
16052             var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
16053             var num = read_while(function(ch, i) {
16054                 var code = ch.charCodeAt(0);
16055                 switch (code) {
16056                   case 120:
16057                   case 88:
16058                     return has_x ? false : has_x = true;
16060                   case 101:
16061                   case 69:
16062                     return has_x ? true : has_e ? false : has_e = after_e = true;
16064                   case 45:
16065                     return after_e || i == 0 && !prefix;
16067                   case 43:
16068                     return after_e;
16070                   case after_e = false, 46:
16071                     return !has_dot && !has_x && !has_e ? has_dot = true : false;
16072                 }
16073                 return is_alphanumeric_char(code);
16074             });
16075             if (prefix) num = prefix + num;
16076             var valid = parse_js_number(num);
16077             if (!isNaN(valid)) {
16078                 return token("num", valid);
16079             } else {
16080                 parse_error("Invalid syntax: " + num);
16081             }
16082         }
16083         function read_escaped_char(in_string) {
16084             var ch = next(true, in_string);
16085             switch (ch.charCodeAt(0)) {
16086               case 110:
16087                 return "\n";
16089               case 114:
16090                 return "\r";
16092               case 116:
16093                 return "        ";
16095               case 98:
16096                 return "\b";
16098               case 118:
16099                 return "\v";
16101               case 102:
16102                 return "\f";
16104               case 48:
16105                 return "\0";
16107               case 120:
16108                 return String.fromCharCode(hex_bytes(2));
16110               case 117:
16111                 return String.fromCharCode(hex_bytes(4));
16113               case 10:
16114                 return "";
16116               default:
16117                 return ch;
16118             }
16119         }
16120         function hex_bytes(n) {
16121             var num = 0;
16122             for (;n > 0; --n) {
16123                 var digit = parseInt(next(true), 16);
16124                 if (isNaN(digit)) parse_error("Invalid hex-character pattern in string");
16125                 num = num << 4 | digit;
16126             }
16127             return num;
16128         }
16129         var read_string = with_eof_error("Unterminated string constant", function() {
16130             var quote = next(), ret = "";
16131             for (;;) {
16132                 var ch = next(true);
16133                 if (ch == "\\") {
16134                     var octal_len = 0, first = null;
16135                     ch = read_while(function(ch) {
16136                         if (ch >= "0" && ch <= "7") {
16137                             if (!first) {
16138                                 first = ch;
16139                                 return ++octal_len;
16140                             } else if (first <= "3" && octal_len <= 2) return ++octal_len; else if (first >= "4" && octal_len <= 1) return ++octal_len;
16141                         }
16142                         return false;
16143                     });
16144                     if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); else ch = read_escaped_char(true);
16145                 } else if (ch == quote) break;
16146                 ret += ch;
16147             }
16148             return token("string", ret);
16149         });
16150         function read_line_comment() {
16151             next();
16152             var i = find("\n"), ret;
16153             if (i == -1) {
16154                 ret = S.text.substr(S.pos);
16155                 S.pos = S.text.length;
16156             } else {
16157                 ret = S.text.substring(S.pos, i);
16158                 S.pos = i;
16159             }
16160             return token("comment1", ret, true);
16161         }
16162         var read_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
16163             next();
16164             var i = find("*/", true);
16165             var text = S.text.substring(S.pos, i);
16166             var a = text.split("\n"), n = a.length;
16167             S.pos = i + 2;
16168             S.line += n - 1;
16169             if (n > 1) S.col = a[n - 1].length; else S.col += a[n - 1].length;
16170             S.col += 2;
16171             S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
16172             return token("comment2", text, true);
16173         });
16174         function read_name() {
16175             var backslash = false, name = "", ch, escaped = false, hex;
16176             while ((ch = peek()) != null) {
16177                 if (!backslash) {
16178                     if (ch == "\\") escaped = backslash = true, next(); else if (is_identifier_char(ch)) name += next(); else break;
16179                 } else {
16180                     if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
16181                     ch = read_escaped_char();
16182                     if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
16183                     name += ch;
16184                     backslash = false;
16185                 }
16186             }
16187             if (KEYWORDS(name) && escaped) {
16188                 hex = name.charCodeAt(0).toString(16).toUpperCase();
16189                 name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
16190             }
16191             return name;
16192         }
16193         var read_regexp = with_eof_error("Unterminated regular expression", function(regexp) {
16194             var prev_backslash = false, ch, in_class = false;
16195             while (ch = next(true)) if (prev_backslash) {
16196                 regexp += "\\" + ch;
16197                 prev_backslash = false;
16198             } else if (ch == "[") {
16199                 in_class = true;
16200                 regexp += ch;
16201             } else if (ch == "]" && in_class) {
16202                 in_class = false;
16203                 regexp += ch;
16204             } else if (ch == "/" && !in_class) {
16205                 break;
16206             } else if (ch == "\\") {
16207                 prev_backslash = true;
16208             } else {
16209                 regexp += ch;
16210             }
16211             var mods = read_name();
16212             return token("regexp", new RegExp(regexp, mods));
16213         });
16214         function read_operator(prefix) {
16215             function grow(op) {
16216                 if (!peek()) return op;
16217                 var bigger = op + peek();
16218                 if (OPERATORS(bigger)) {
16219                     next();
16220                     return grow(bigger);
16221                 } else {
16222                     return op;
16223                 }
16224             }
16225             return token("operator", grow(prefix || next()));
16226         }
16227         function handle_slash() {
16228             next();
16229             var regex_allowed = S.regex_allowed;
16230             switch (peek()) {
16231               case "/":
16232                 S.comments_before.push(read_line_comment());
16233                 S.regex_allowed = regex_allowed;
16234                 return next_token();
16236               case "*":
16237                 S.comments_before.push(read_multiline_comment());
16238                 S.regex_allowed = regex_allowed;
16239                 return next_token();
16240             }
16241             return S.regex_allowed ? read_regexp("") : read_operator("/");
16242         }
16243         function handle_dot() {
16244             next();
16245             return is_digit(peek().charCodeAt(0)) ? read_num(".") : token("punc", ".");
16246         }
16247         function read_word() {
16248             var word = read_name();
16249             return KEYWORDS_ATOM(word) ? token("atom", word) : !KEYWORDS(word) ? token("name", word) : OPERATORS(word) ? token("operator", word) : token("keyword", word);
16250         }
16251         function with_eof_error(eof_error, cont) {
16252             return function(x) {
16253                 try {
16254                     return cont(x);
16255                 } catch (ex) {
16256                     if (ex === EX_EOF) parse_error(eof_error); else throw ex;
16257                 }
16258             };
16259         }
16260         function next_token(force_regexp) {
16261             if (force_regexp != null) return read_regexp(force_regexp);
16262             skip_whitespace();
16263             start_token();
16264             var ch = peek();
16265             if (!ch) return token("eof");
16266             var code = ch.charCodeAt(0);
16267             switch (code) {
16268               case 34:
16269               case 39:
16270                 return read_string();
16272               case 46:
16273                 return handle_dot();
16275               case 47:
16276                 return handle_slash();
16277             }
16278             if (is_digit(code)) return read_num();
16279             if (PUNC_CHARS(ch)) return token("punc", next());
16280             if (OPERATOR_CHARS(ch)) return read_operator();
16281             if (code == 92 || is_identifier_start(code)) return read_word();
16282             parse_error("Unexpected character '" + ch + "'");
16283         }
16284         next_token.context = function(nc) {
16285             if (nc) S = nc;
16286             return S;
16287         };
16288         return next_token;
16289     }
16290     var UNARY_PREFIX = makePredicate([ "typeof", "void", "delete", "--", "++", "!", "~", "-", "+" ]);
16291     var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
16292     var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
16293     var PRECEDENCE = function(a, ret) {
16294         for (var i = 0, n = 1; i < a.length; ++i, ++n) {
16295             var b = a[i];
16296             for (var j = 0; j < b.length; ++j) {
16297                 ret[b[j]] = n;
16298             }
16299         }
16300         return ret;
16301     }([ [ "||" ], [ "&&" ], [ "|" ], [ "^" ], [ "&" ], [ "==", "===", "!=", "!==" ], [ "<", ">", "<=", ">=", "in", "instanceof" ], [ ">>", "<<", ">>>" ], [ "+", "-" ], [ "*", "/", "%" ] ], {});
16302     var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
16303     var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
16304     function parse($TEXT, options) {
16305         options = defaults(options, {
16306             strict: false,
16307             filename: null,
16308             toplevel: null,
16309             expression: false
16310         });
16311         var S = {
16312             input: typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT,
16313             token: null,
16314             prev: null,
16315             peeked: null,
16316             in_function: 0,
16317             in_directives: true,
16318             in_loop: 0,
16319             labels: []
16320         };
16321         S.token = next();
16322         function is(type, value) {
16323             return is_token(S.token, type, value);
16324         }
16325         function peek() {
16326             return S.peeked || (S.peeked = S.input());
16327         }
16328         function next() {
16329             S.prev = S.token;
16330             if (S.peeked) {
16331                 S.token = S.peeked;
16332                 S.peeked = null;
16333             } else {
16334                 S.token = S.input();
16335             }
16336             S.in_directives = S.in_directives && (S.token.type == "string" || is("punc", ";"));
16337             return S.token;
16338         }
16339         function prev() {
16340             return S.prev;
16341         }
16342         function croak(msg, line, col, pos) {
16343             var ctx = S.input.context();
16344             js_error(msg, ctx.filename, line != null ? line : ctx.tokline, col != null ? col : ctx.tokcol, pos != null ? pos : ctx.tokpos);
16345         }
16346         function token_error(token, msg) {
16347             croak(msg, token.line, token.col);
16348         }
16349         function unexpected(token) {
16350             if (token == null) token = S.token;
16351             token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
16352         }
16353         function expect_token(type, val) {
16354             if (is(type, val)) {
16355                 return next();
16356             }
16357             token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
16358         }
16359         function expect(punc) {
16360             return expect_token("punc", punc);
16361         }
16362         function can_insert_semicolon() {
16363             return !options.strict && (S.token.nlb || is("eof") || is("punc", "}"));
16364         }
16365         function semicolon() {
16366             if (is("punc", ";")) next(); else if (!can_insert_semicolon()) unexpected();
16367         }
16368         function parenthesised() {
16369             expect("(");
16370             var exp = expression(true);
16371             expect(")");
16372             return exp;
16373         }
16374         function embed_tokens(parser) {
16375             return function() {
16376                 var start = S.token;
16377                 var expr = parser();
16378                 var end = prev();
16379                 expr.start = start;
16380                 expr.end = end;
16381                 return expr;
16382             };
16383         }
16384         var statement = embed_tokens(function() {
16385             var tmp;
16386             if (is("operator", "/") || is("operator", "/=")) {
16387                 S.peeked = null;
16388                 S.token = S.input(S.token.value.substr(1));
16389             }
16390             switch (S.token.type) {
16391               case "string":
16392                 var dir = S.in_directives, stat = simple_statement();
16393                 if (dir && stat.body instanceof AST_String && !is("punc", ",")) return new AST_Directive({
16394                     value: stat.body.value
16395                 });
16396                 return stat;
16398               case "num":
16399               case "regexp":
16400               case "operator":
16401               case "atom":
16402                 return simple_statement();
16404               case "name":
16405                 return is_token(peek(), "punc", ":") ? labeled_statement() : simple_statement();
16407               case "punc":
16408                 switch (S.token.value) {
16409                   case "{":
16410                     return new AST_BlockStatement({
16411                         start: S.token,
16412                         body: block_(),
16413                         end: prev()
16414                     });
16416                   case "[":
16417                   case "(":
16418                     return simple_statement();
16420                   case ";":
16421                     next();
16422                     return new AST_EmptyStatement();
16424                   default:
16425                     unexpected();
16426                 }
16428               case "keyword":
16429                 switch (tmp = S.token.value, next(), tmp) {
16430                   case "break":
16431                     return break_cont(AST_Break);
16433                   case "continue":
16434                     return break_cont(AST_Continue);
16436                   case "debugger":
16437                     semicolon();
16438                     return new AST_Debugger();
16440                   case "do":
16441                     return new AST_Do({
16442                         body: in_loop(statement),
16443                         condition: (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(),
16444                         tmp)
16445                     });
16447                   case "while":
16448                     return new AST_While({
16449                         condition: parenthesised(),
16450                         body: in_loop(statement)
16451                     });
16453                   case "for":
16454                     return for_();
16456                   case "function":
16457                     return function_(true);
16459                   case "if":
16460                     return if_();
16462                   case "return":
16463                     if (S.in_function == 0) croak("'return' outside of function");
16464                     return new AST_Return({
16465                         value: is("punc", ";") ? (next(), null) : can_insert_semicolon() ? null : (tmp = expression(true),
16466                         semicolon(), tmp)
16467                     });
16469                   case "switch":
16470                     return new AST_Switch({
16471                         expression: parenthesised(),
16472                         body: in_loop(switch_body_)
16473                     });
16475                   case "throw":
16476                     if (S.token.nlb) croak("Illegal newline after 'throw'");
16477                     return new AST_Throw({
16478                         value: (tmp = expression(true), semicolon(), tmp)
16479                     });
16481                   case "try":
16482                     return try_();
16484                   case "var":
16485                     return tmp = var_(), semicolon(), tmp;
16487                   case "const":
16488                     return tmp = const_(), semicolon(), tmp;
16490                   case "with":
16491                     return new AST_With({
16492                         expression: parenthesised(),
16493                         body: statement()
16494                     });
16496                   default:
16497                     unexpected();
16498                 }
16499             }
16500         });
16501         function labeled_statement() {
16502             var label = as_symbol(AST_Label);
16503             if (find_if(function(l) {
16504                 return l.name == label.name;
16505             }, S.labels)) {
16506                 croak("Label " + label.name + " defined twice");
16507             }
16508             expect(":");
16509             S.labels.push(label);
16510             var stat = statement();
16511             S.labels.pop();
16512             return new AST_LabeledStatement({
16513                 body: stat,
16514                 label: label
16515             });
16516         }
16517         function simple_statement(tmp) {
16518             return new AST_SimpleStatement({
16519                 body: (tmp = expression(true), semicolon(), tmp)
16520             });
16521         }
16522         function break_cont(type) {
16523             var label = null;
16524             if (!can_insert_semicolon()) {
16525                 label = as_symbol(AST_LabelRef, true);
16526             }
16527             if (label != null) {
16528                 if (!find_if(function(l) {
16529                     return l.name == label.name;
16530                 }, S.labels)) croak("Undefined label " + label.name);
16531             } else if (S.in_loop == 0) croak(type.TYPE + " not inside a loop or switch");
16532             semicolon();
16533             return new type({
16534                 label: label
16535             });
16536         }
16537         function for_() {
16538             expect("(");
16539             var init = null;
16540             if (!is("punc", ";")) {
16541                 init = is("keyword", "var") ? (next(), var_(true)) : expression(true, true);
16542                 if (is("operator", "in")) {
16543                     if (init instanceof AST_Var && init.definitions.length > 1) croak("Only one variable declaration allowed in for..in loop");
16544                     next();
16545                     return for_in(init);
16546                 }
16547             }
16548             return regular_for(init);
16549         }
16550         function regular_for(init) {
16551             expect(";");
16552             var test = is("punc", ";") ? null : expression(true);
16553             expect(";");
16554             var step = is("punc", ")") ? null : expression(true);
16555             expect(")");
16556             return new AST_For({
16557                 init: init,
16558                 condition: test,
16559                 step: step,
16560                 body: in_loop(statement)
16561             });
16562         }
16563         function for_in(init) {
16564             var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
16565             var obj = expression(true);
16566             expect(")");
16567             return new AST_ForIn({
16568                 init: init,
16569                 name: lhs,
16570                 object: obj,
16571                 body: in_loop(statement)
16572             });
16573         }
16574         var function_ = function(in_statement, ctor) {
16575             var is_accessor = ctor === AST_Accessor;
16576             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;
16577             if (in_statement && !name) unexpected();
16578             expect("(");
16579             if (!ctor) ctor = in_statement ? AST_Defun : AST_Function;
16580             return new ctor({
16581                 name: name,
16582                 argnames: function(first, a) {
16583                     while (!is("punc", ")")) {
16584                         if (first) first = false; else expect(",");
16585                         a.push(as_symbol(AST_SymbolFunarg));
16586                     }
16587                     next();
16588                     return a;
16589                 }(true, []),
16590                 body: function(loop, labels) {
16591                     ++S.in_function;
16592                     S.in_directives = true;
16593                     S.in_loop = 0;
16594                     S.labels = [];
16595                     var a = block_();
16596                     --S.in_function;
16597                     S.in_loop = loop;
16598                     S.labels = labels;
16599                     return a;
16600                 }(S.in_loop, S.labels)
16601             });
16602         };
16603         function if_() {
16604             var cond = parenthesised(), body = statement(), belse = null;
16605             if (is("keyword", "else")) {
16606                 next();
16607                 belse = statement();
16608             }
16609             return new AST_If({
16610                 condition: cond,
16611                 body: body,
16612                 alternative: belse
16613             });
16614         }
16615         function block_() {
16616             expect("{");
16617             var a = [];
16618             while (!is("punc", "}")) {
16619                 if (is("eof")) unexpected();
16620                 a.push(statement());
16621             }
16622             next();
16623             return a;
16624         }
16625         function switch_body_() {
16626             expect("{");
16627             var a = [], cur = null, branch = null, tmp;
16628             while (!is("punc", "}")) {
16629                 if (is("eof")) unexpected();
16630                 if (is("keyword", "case")) {
16631                     if (branch) branch.end = prev();
16632                     cur = [];
16633                     branch = new AST_Case({
16634                         start: (tmp = S.token, next(), tmp),
16635                         expression: expression(true),
16636                         body: cur
16637                     });
16638                     a.push(branch);
16639                     expect(":");
16640                 } else if (is("keyword", "default")) {
16641                     if (branch) branch.end = prev();
16642                     cur = [];
16643                     branch = new AST_Default({
16644                         start: (tmp = S.token, next(), expect(":"), tmp),
16645                         body: cur
16646                     });
16647                     a.push(branch);
16648                 } else {
16649                     if (!cur) unexpected();
16650                     cur.push(statement());
16651                 }
16652             }
16653             if (branch) branch.end = prev();
16654             next();
16655             return a;
16656         }
16657         function try_() {
16658             var body = block_(), bcatch = null, bfinally = null;
16659             if (is("keyword", "catch")) {
16660                 var start = S.token;
16661                 next();
16662                 expect("(");
16663                 var name = as_symbol(AST_SymbolCatch);
16664                 expect(")");
16665                 bcatch = new AST_Catch({
16666                     start: start,
16667                     argname: name,
16668                     body: block_(),
16669                     end: prev()
16670                 });
16671             }
16672             if (is("keyword", "finally")) {
16673                 var start = S.token;
16674                 next();
16675                 bfinally = new AST_Finally({
16676                     start: start,
16677                     body: block_(),
16678                     end: prev()
16679                 });
16680             }
16681             if (!bcatch && !bfinally) croak("Missing catch/finally blocks");
16682             return new AST_Try({
16683                 body: body,
16684                 bcatch: bcatch,
16685                 bfinally: bfinally
16686             });
16687         }
16688         function vardefs(no_in, in_const) {
16689             var a = [];
16690             for (;;) {
16691                 a.push(new AST_VarDef({
16692                     start: S.token,
16693                     name: as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
16694                     value: is("operator", "=") ? (next(), expression(false, no_in)) : null,
16695                     end: prev()
16696                 }));
16697                 if (!is("punc", ",")) break;
16698                 next();
16699             }
16700             return a;
16701         }
16702         var var_ = function(no_in) {
16703             return new AST_Var({
16704                 start: prev(),
16705                 definitions: vardefs(no_in, false),
16706                 end: prev()
16707             });
16708         };
16709         var const_ = function() {
16710             return new AST_Const({
16711                 start: prev(),
16712                 definitions: vardefs(false, true),
16713                 end: prev()
16714             });
16715         };
16716         var new_ = function() {
16717             var start = S.token;
16718             expect_token("operator", "new");
16719             var newexp = expr_atom(false), args;
16720             if (is("punc", "(")) {
16721                 next();
16722                 args = expr_list(")");
16723             } else {
16724                 args = [];
16725             }
16726             return subscripts(new AST_New({
16727                 start: start,
16728                 expression: newexp,
16729                 args: args,
16730                 end: prev()
16731             }), true);
16732         };
16733         function as_atom_node() {
16734             var tok = S.token, ret;
16735             switch (tok.type) {
16736               case "name":
16737                 return as_symbol(AST_SymbolRef);
16739               case "num":
16740                 ret = new AST_Number({
16741                     start: tok,
16742                     end: tok,
16743                     value: tok.value
16744                 });
16745                 break;
16747               case "string":
16748                 ret = new AST_String({
16749                     start: tok,
16750                     end: tok,
16751                     value: tok.value
16752                 });
16753                 break;
16755               case "regexp":
16756                 ret = new AST_RegExp({
16757                     start: tok,
16758                     end: tok,
16759                     value: tok.value
16760                 });
16761                 break;
16763               case "atom":
16764                 switch (tok.value) {
16765                   case "false":
16766                     ret = new AST_False({
16767                         start: tok,
16768                         end: tok
16769                     });
16770                     break;
16772                   case "true":
16773                     ret = new AST_True({
16774                         start: tok,
16775                         end: tok
16776                     });
16777                     break;
16779                   case "null":
16780                     ret = new AST_Null({
16781                         start: tok,
16782                         end: tok
16783                     });
16784                     break;
16785                 }
16786                 break;
16787             }
16788             next();
16789             return ret;
16790         }
16791         var expr_atom = function(allow_calls) {
16792             if (is("operator", "new")) {
16793                 return new_();
16794             }
16795             var start = S.token;
16796             if (is("punc")) {
16797                 switch (start.value) {
16798                   case "(":
16799                     next();
16800                     var ex = expression(true);
16801                     ex.start = start;
16802                     ex.end = S.token;
16803                     expect(")");
16804                     return subscripts(ex, allow_calls);
16806                   case "[":
16807                     return subscripts(array_(), allow_calls);
16809                   case "{":
16810                     return subscripts(object_(), allow_calls);
16811                 }
16812                 unexpected();
16813             }
16814             if (is("keyword", "function")) {
16815                 next();
16816                 var func = function_(false);
16817                 func.start = start;
16818                 func.end = prev();
16819                 return subscripts(func, allow_calls);
16820             }
16821             if (ATOMIC_START_TOKEN[S.token.type]) {
16822                 return subscripts(as_atom_node(), allow_calls);
16823             }
16824             unexpected();
16825         };
16826         function expr_list(closing, allow_trailing_comma, allow_empty) {
16827             var first = true, a = [];
16828             while (!is("punc", closing)) {
16829                 if (first) first = false; else expect(",");
16830                 if (allow_trailing_comma && is("punc", closing)) break;
16831                 if (is("punc", ",") && allow_empty) {
16832                     a.push(new AST_Hole({
16833                         start: S.token,
16834                         end: S.token
16835                     }));
16836                 } else {
16837                     a.push(expression(false));
16838                 }
16839             }
16840             next();
16841             return a;
16842         }
16843         var array_ = embed_tokens(function() {
16844             expect("[");
16845             return new AST_Array({
16846                 elements: expr_list("]", !options.strict, true)
16847             });
16848         });
16849         var object_ = embed_tokens(function() {
16850             expect("{");
16851             var first = true, a = [];
16852             while (!is("punc", "}")) {
16853                 if (first) first = false; else expect(",");
16854                 if (!options.strict && is("punc", "}")) break;
16855                 var start = S.token;
16856                 var type = start.type;
16857                 var name = as_property_name();
16858                 if (type == "name" && !is("punc", ":")) {
16859                     if (name == "get") {
16860                         a.push(new AST_ObjectGetter({
16861                             start: start,
16862                             key: name,
16863                             value: function_(false, AST_Accessor),
16864                             end: prev()
16865                         }));
16866                         continue;
16867                     }
16868                     if (name == "set") {
16869                         a.push(new AST_ObjectSetter({
16870                             start: start,
16871                             key: name,
16872                             value: function_(false, AST_Accessor),
16873                             end: prev()
16874                         }));
16875                         continue;
16876                     }
16877                 }
16878                 expect(":");
16879                 a.push(new AST_ObjectKeyVal({
16880                     start: start,
16881                     key: name,
16882                     value: expression(false),
16883                     end: prev()
16884                 }));
16885             }
16886             next();
16887             return new AST_Object({
16888                 properties: a
16889             });
16890         });
16891         function as_property_name() {
16892             var tmp = S.token;
16893             next();
16894             switch (tmp.type) {
16895               case "num":
16896               case "string":
16897               case "name":
16898               case "operator":
16899               case "keyword":
16900               case "atom":
16901                 return tmp.value;
16903               default:
16904                 unexpected();
16905             }
16906         }
16907         function as_name() {
16908             var tmp = S.token;
16909             next();
16910             switch (tmp.type) {
16911               case "name":
16912               case "operator":
16913               case "keyword":
16914               case "atom":
16915                 return tmp.value;
16917               default:
16918                 unexpected();
16919             }
16920         }
16921         function as_symbol(type, noerror) {
16922             if (!is("name")) {
16923                 if (!noerror) croak("Name expected");
16924                 return null;
16925             }
16926             var name = S.token.value;
16927             var sym = new (name == "this" ? AST_This : type)({
16928                 name: String(S.token.value),
16929                 start: S.token,
16930                 end: S.token
16931             });
16932             next();
16933             return sym;
16934         }
16935         var subscripts = function(expr, allow_calls) {
16936             var start = expr.start;
16937             if (is("punc", ".")) {
16938                 next();
16939                 return subscripts(new AST_Dot({
16940                     start: start,
16941                     expression: expr,
16942                     property: as_name(),
16943                     end: prev()
16944                 }), allow_calls);
16945             }
16946             if (is("punc", "[")) {
16947                 next();
16948                 var prop = expression(true);
16949                 expect("]");
16950                 return subscripts(new AST_Sub({
16951                     start: start,
16952                     expression: expr,
16953                     property: prop,
16954                     end: prev()
16955                 }), allow_calls);
16956             }
16957             if (allow_calls && is("punc", "(")) {
16958                 next();
16959                 return subscripts(new AST_Call({
16960                     start: start,
16961                     expression: expr,
16962                     args: expr_list(")"),
16963                     end: prev()
16964                 }), true);
16965             }
16966             return expr;
16967         };
16968         var maybe_unary = function(allow_calls) {
16969             var start = S.token;
16970             if (is("operator") && UNARY_PREFIX(start.value)) {
16971                 next();
16972                 var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
16973                 ex.start = start;
16974                 ex.end = prev();
16975                 return ex;
16976             }
16977             var val = expr_atom(allow_calls);
16978             while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
16979                 val = make_unary(AST_UnaryPostfix, S.token.value, val);
16980                 val.start = start;
16981                 val.end = S.token;
16982                 next();
16983             }
16984             return val;
16985         };
16986         function make_unary(ctor, op, expr) {
16987             if ((op == "++" || op == "--") && !is_assignable(expr)) croak("Invalid use of " + op + " operator");
16988             return new ctor({
16989                 operator: op,
16990                 expression: expr
16991             });
16992         }
16993         var expr_op = function(left, min_prec, no_in) {
16994             var op = is("operator") ? S.token.value : null;
16995             if (op == "in" && no_in) op = null;
16996             var prec = op != null ? PRECEDENCE[op] : null;
16997             if (prec != null && prec > min_prec) {
16998                 next();
16999                 var right = expr_op(maybe_unary(true), prec, no_in);
17000                 return expr_op(new AST_Binary({
17001                     start: left.start,
17002                     left: left,
17003                     operator: op,
17004                     right: right,
17005                     end: right.end
17006                 }), min_prec, no_in);
17007             }
17008             return left;
17009         };
17010         function expr_ops(no_in) {
17011             return expr_op(maybe_unary(true), 0, no_in);
17012         }
17013         var maybe_conditional = function(no_in) {
17014             var start = S.token;
17015             var expr = expr_ops(no_in);
17016             if (is("operator", "?")) {
17017                 next();
17018                 var yes = expression(false);
17019                 expect(":");
17020                 return new AST_Conditional({
17021                     start: start,
17022                     condition: expr,
17023                     consequent: yes,
17024                     alternative: expression(false, no_in),
17025                     end: peek()
17026                 });
17027             }
17028             return expr;
17029         };
17030         function is_assignable(expr) {
17031             if (!options.strict) return true;
17032             if (expr instanceof AST_This) return false;
17033             return expr instanceof AST_PropAccess || expr instanceof AST_Symbol;
17034         }
17035         var maybe_assign = function(no_in) {
17036             var start = S.token;
17037             var left = maybe_conditional(no_in), val = S.token.value;
17038             if (is("operator") && ASSIGNMENT(val)) {
17039                 if (is_assignable(left)) {
17040                     next();
17041                     return new AST_Assign({
17042                         start: start,
17043                         left: left,
17044                         operator: val,
17045                         right: maybe_assign(no_in),
17046                         end: prev()
17047                     });
17048                 }
17049                 croak("Invalid assignment");
17050             }
17051             return left;
17052         };
17053         var expression = function(commas, no_in) {
17054             var start = S.token;
17055             var expr = maybe_assign(no_in);
17056             if (commas && is("punc", ",")) {
17057                 next();
17058                 return new AST_Seq({
17059                     start: start,
17060                     car: expr,
17061                     cdr: expression(true, no_in),
17062                     end: peek()
17063                 });
17064             }
17065             return expr;
17066         };
17067         function in_loop(cont) {
17068             ++S.in_loop;
17069             var ret = cont();
17070             --S.in_loop;
17071             return ret;
17072         }
17073         if (options.expression) {
17074             return expression(true);
17075         }
17076         return function() {
17077             var start = S.token;
17078             var body = [];
17079             while (!is("eof")) body.push(statement());
17080             var end = prev();
17081             var toplevel = options.toplevel;
17082             if (toplevel) {
17083                 toplevel.body = toplevel.body.concat(body);
17084                 toplevel.end = end;
17085             } else {
17086                 toplevel = new AST_Toplevel({
17087                     start: start,
17088                     body: body,
17089                     end: end
17090                 });
17091             }
17092             return toplevel;
17093         }();
17094     }
17095     "use strict";
17096     function TreeTransformer(before, after) {
17097         TreeWalker.call(this);
17098         this.before = before;
17099         this.after = after;
17100     }
17101     TreeTransformer.prototype = new TreeWalker();
17102     (function(undefined) {
17103         function _(node, descend) {
17104             node.DEFMETHOD("transform", function(tw, in_list) {
17105                 var x, y;
17106                 tw.push(this);
17107                 if (tw.before) x = tw.before(this, descend, in_list);
17108                 if (x === undefined) {
17109                     if (!tw.after) {
17110                         x = this;
17111                         descend(x, tw);
17112                     } else {
17113                         tw.stack[tw.stack.length - 1] = x = this.clone();
17114                         descend(x, tw);
17115                         y = tw.after(x, in_list);
17116                         if (y !== undefined) x = y;
17117                     }
17118                 }
17119                 tw.pop();
17120                 return x;
17121             });
17122         }
17123         function do_list(list, tw) {
17124             return MAP(list, function(node) {
17125                 return node.transform(tw, true);
17126             });
17127         }
17128         _(AST_Node, noop);
17129         _(AST_LabeledStatement, function(self, tw) {
17130             self.label = self.label.transform(tw);
17131             self.body = self.body.transform(tw);
17132         });
17133         _(AST_SimpleStatement, function(self, tw) {
17134             self.body = self.body.transform(tw);
17135         });
17136         _(AST_Block, function(self, tw) {
17137             self.body = do_list(self.body, tw);
17138         });
17139         _(AST_DWLoop, function(self, tw) {
17140             self.condition = self.condition.transform(tw);
17141             self.body = self.body.transform(tw);
17142         });
17143         _(AST_For, function(self, tw) {
17144             if (self.init) self.init = self.init.transform(tw);
17145             if (self.condition) self.condition = self.condition.transform(tw);
17146             if (self.step) self.step = self.step.transform(tw);
17147             self.body = self.body.transform(tw);
17148         });
17149         _(AST_ForIn, function(self, tw) {
17150             self.init = self.init.transform(tw);
17151             self.object = self.object.transform(tw);
17152             self.body = self.body.transform(tw);
17153         });
17154         _(AST_With, function(self, tw) {
17155             self.expression = self.expression.transform(tw);
17156             self.body = self.body.transform(tw);
17157         });
17158         _(AST_Exit, function(self, tw) {
17159             if (self.value) self.value = self.value.transform(tw);
17160         });
17161         _(AST_LoopControl, function(self, tw) {
17162             if (self.label) self.label = self.label.transform(tw);
17163         });
17164         _(AST_If, function(self, tw) {
17165             self.condition = self.condition.transform(tw);
17166             self.body = self.body.transform(tw);
17167             if (self.alternative) self.alternative = self.alternative.transform(tw);
17168         });
17169         _(AST_Switch, function(self, tw) {
17170             self.expression = self.expression.transform(tw);
17171             self.body = do_list(self.body, tw);
17172         });
17173         _(AST_Case, function(self, tw) {
17174             self.expression = self.expression.transform(tw);
17175             self.body = do_list(self.body, tw);
17176         });
17177         _(AST_Try, function(self, tw) {
17178             self.body = do_list(self.body, tw);
17179             if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
17180             if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
17181         });
17182         _(AST_Catch, function(self, tw) {
17183             self.argname = self.argname.transform(tw);
17184             self.body = do_list(self.body, tw);
17185         });
17186         _(AST_Definitions, function(self, tw) {
17187             self.definitions = do_list(self.definitions, tw);
17188         });
17189         _(AST_VarDef, function(self, tw) {
17190             if (self.value) self.value = self.value.transform(tw);
17191         });
17192         _(AST_Lambda, function(self, tw) {
17193             if (self.name) self.name = self.name.transform(tw);
17194             self.argnames = do_list(self.argnames, tw);
17195             self.body = do_list(self.body, tw);
17196         });
17197         _(AST_Call, function(self, tw) {
17198             self.expression = self.expression.transform(tw);
17199             self.args = do_list(self.args, tw);
17200         });
17201         _(AST_Seq, function(self, tw) {
17202             self.car = self.car.transform(tw);
17203             self.cdr = self.cdr.transform(tw);
17204         });
17205         _(AST_Dot, function(self, tw) {
17206             self.expression = self.expression.transform(tw);
17207         });
17208         _(AST_Sub, function(self, tw) {
17209             self.expression = self.expression.transform(tw);
17210             self.property = self.property.transform(tw);
17211         });
17212         _(AST_Unary, function(self, tw) {
17213             self.expression = self.expression.transform(tw);
17214         });
17215         _(AST_Binary, function(self, tw) {
17216             self.left = self.left.transform(tw);
17217             self.right = self.right.transform(tw);
17218         });
17219         _(AST_Conditional, function(self, tw) {
17220             self.condition = self.condition.transform(tw);
17221             self.consequent = self.consequent.transform(tw);
17222             self.alternative = self.alternative.transform(tw);
17223         });
17224         _(AST_Array, function(self, tw) {
17225             self.elements = do_list(self.elements, tw);
17226         });
17227         _(AST_Object, function(self, tw) {
17228             self.properties = do_list(self.properties, tw);
17229         });
17230         _(AST_ObjectProperty, function(self, tw) {
17231             self.value = self.value.transform(tw);
17232         });
17233     })();
17234     "use strict";
17235     function SymbolDef(scope, index, orig) {
17236         this.name = orig.name;
17237         this.orig = [ orig ];
17238         this.scope = scope;
17239         this.references = [];
17240         this.global = false;
17241         this.mangled_name = null;
17242         this.undeclared = false;
17243         this.constant = false;
17244         this.index = index;
17245     }
17246     SymbolDef.prototype = {
17247         unmangleable: function(options) {
17248             return this.global && !(options && options.toplevel) || this.undeclared || !(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with);
17249         },
17250         mangle: function(options) {
17251             if (!this.mangled_name && !this.unmangleable(options)) {
17252                 var s = this.scope;
17253                 if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8) s = s.parent_scope;
17254                 this.mangled_name = s.next_mangled(options);
17255             }
17256         }
17257     };
17258     AST_Toplevel.DEFMETHOD("figure_out_scope", function() {
17259         var self = this;
17260         var scope = self.parent_scope = null;
17261         var labels = new Dictionary();
17262         var nesting = 0;
17263         var tw = new TreeWalker(function(node, descend) {
17264             if (node instanceof AST_Scope) {
17265                 node.init_scope_vars(nesting);
17266                 var save_scope = node.parent_scope = scope;
17267                 var save_labels = labels;
17268                 ++nesting;
17269                 scope = node;
17270                 labels = new Dictionary();
17271                 descend();
17272                 labels = save_labels;
17273                 scope = save_scope;
17274                 --nesting;
17275                 return true;
17276             }
17277             if (node instanceof AST_Directive) {
17278                 node.scope = scope;
17279                 push_uniq(scope.directives, node.value);
17280                 return true;
17281             }
17282             if (node instanceof AST_With) {
17283                 for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
17284                 return;
17285             }
17286             if (node instanceof AST_LabeledStatement) {
17287                 var l = node.label;
17288                 if (labels.has(l.name)) throw new Error(string_template("Label {name} defined twice", l));
17289                 labels.set(l.name, l);
17290                 descend();
17291                 labels.del(l.name);
17292                 return true;
17293             }
17294             if (node instanceof AST_Symbol) {
17295                 node.scope = scope;
17296             }
17297             if (node instanceof AST_Label) {
17298                 node.thedef = node;
17299                 node.init_scope_vars();
17300             }
17301             if (node instanceof AST_SymbolLambda) {
17302                 scope.def_function(node);
17303             } else if (node instanceof AST_SymbolDefun) {
17304                 (node.scope = scope.parent_scope).def_function(node);
17305             } else if (node instanceof AST_SymbolVar || node instanceof AST_SymbolConst) {
17306                 var def = scope.def_variable(node);
17307                 def.constant = node instanceof AST_SymbolConst;
17308                 def.init = tw.parent().value;
17309             } else if (node instanceof AST_SymbolCatch) {
17310                 scope.def_variable(node);
17311             }
17312             if (node instanceof AST_LabelRef) {
17313                 var sym = labels.get(node.name);
17314                 if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
17315                     name: node.name,
17316                     line: node.start.line,
17317                     col: node.start.col
17318                 }));
17319                 node.thedef = sym;
17320             }
17321         });
17322         self.walk(tw);
17323         var func = null;
17324         var globals = self.globals = new Dictionary();
17325         var tw = new TreeWalker(function(node, descend) {
17326             if (node instanceof AST_Lambda) {
17327                 var prev_func = func;
17328                 func = node;
17329                 descend();
17330                 func = prev_func;
17331                 return true;
17332             }
17333             if (node instanceof AST_LabelRef) {
17334                 node.reference();
17335                 return true;
17336             }
17337             if (node instanceof AST_SymbolRef) {
17338                 var name = node.name;
17339                 var sym = node.scope.find_variable(name);
17340                 if (!sym) {
17341                     var g;
17342                     if (globals.has(name)) {
17343                         g = globals.get(name);
17344                     } else {
17345                         g = new SymbolDef(self, globals.size(), node);
17346                         g.undeclared = true;
17347                         g.global = true;
17348                         globals.set(name, g);
17349                     }
17350                     node.thedef = g;
17351                     if (name == "eval" && tw.parent() instanceof AST_Call) {
17352                         for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) s.uses_eval = true;
17353                     }
17354                     if (name == "arguments") {
17355                         func.uses_arguments = true;
17356                     }
17357                 } else {
17358                     node.thedef = sym;
17359                 }
17360                 node.reference();
17361                 return true;
17362             }
17363         });
17364         self.walk(tw);
17365     });
17366     AST_Scope.DEFMETHOD("init_scope_vars", function(nesting) {
17367         this.directives = [];
17368         this.variables = new Dictionary();
17369         this.functions = new Dictionary();
17370         this.uses_with = false;
17371         this.uses_eval = false;
17372         this.parent_scope = null;
17373         this.enclosed = [];
17374         this.cname = -1;
17375         this.nesting = nesting;
17376     });
17377     AST_Scope.DEFMETHOD("strict", function() {
17378         return this.has_directive("use strict");
17379     });
17380     AST_Lambda.DEFMETHOD("init_scope_vars", function() {
17381         AST_Scope.prototype.init_scope_vars.apply(this, arguments);
17382         this.uses_arguments = false;
17383     });
17384     AST_SymbolRef.DEFMETHOD("reference", function() {
17385         var def = this.definition();
17386         def.references.push(this);
17387         var s = this.scope;
17388         while (s) {
17389             push_uniq(s.enclosed, def);
17390             if (s === def.scope) break;
17391             s = s.parent_scope;
17392         }
17393         this.frame = this.scope.nesting - def.scope.nesting;
17394     });
17395     AST_Label.DEFMETHOD("init_scope_vars", function() {
17396         this.references = [];
17397     });
17398     AST_LabelRef.DEFMETHOD("reference", function() {
17399         this.thedef.references.push(this);
17400     });
17401     AST_Scope.DEFMETHOD("find_variable", function(name) {
17402         if (name instanceof AST_Symbol) name = name.name;
17403         return this.variables.get(name) || this.parent_scope && this.parent_scope.find_variable(name);
17404     });
17405     AST_Scope.DEFMETHOD("has_directive", function(value) {
17406         return this.parent_scope && this.parent_scope.has_directive(value) || (this.directives.indexOf(value) >= 0 ? this : null);
17407     });
17408     AST_Scope.DEFMETHOD("def_function", function(symbol) {
17409         this.functions.set(symbol.name, this.def_variable(symbol));
17410     });
17411     AST_Scope.DEFMETHOD("def_variable", function(symbol) {
17412         var def;
17413         if (!this.variables.has(symbol.name)) {
17414             def = new SymbolDef(this, this.variables.size(), symbol);
17415             this.variables.set(symbol.name, def);
17416             def.global = !this.parent_scope;
17417         } else {
17418             def = this.variables.get(symbol.name);
17419             def.orig.push(symbol);
17420         }
17421         return symbol.thedef = def;
17422     });
17423     AST_Scope.DEFMETHOD("next_mangled", function(options) {
17424         var ext = this.enclosed;
17425         out: while (true) {
17426             var m = base54(++this.cname);
17427             if (!is_identifier(m)) continue;
17428             for (var i = ext.length; --i >= 0; ) {
17429                 var sym = ext[i];
17430                 var name = sym.mangled_name || sym.unmangleable(options) && sym.name;
17431                 if (m == name) continue out;
17432             }
17433             return m;
17434         }
17435     });
17436     AST_Scope.DEFMETHOD("references", function(sym) {
17437         if (sym instanceof AST_Symbol) sym = sym.definition();
17438         return this.enclosed.indexOf(sym) < 0 ? null : sym;
17439     });
17440     AST_Symbol.DEFMETHOD("unmangleable", function(options) {
17441         return this.definition().unmangleable(options);
17442     });
17443     AST_SymbolAccessor.DEFMETHOD("unmangleable", function() {
17444         return true;
17445     });
17446     AST_Label.DEFMETHOD("unmangleable", function() {
17447         return false;
17448     });
17449     AST_Symbol.DEFMETHOD("unreferenced", function() {
17450         return this.definition().references.length == 0 && !(this.scope.uses_eval || this.scope.uses_with);
17451     });
17452     AST_Symbol.DEFMETHOD("undeclared", function() {
17453         return this.definition().undeclared;
17454     });
17455     AST_LabelRef.DEFMETHOD("undeclared", function() {
17456         return false;
17457     });
17458     AST_Label.DEFMETHOD("undeclared", function() {
17459         return false;
17460     });
17461     AST_Symbol.DEFMETHOD("definition", function() {
17462         return this.thedef;
17463     });
17464     AST_Symbol.DEFMETHOD("global", function() {
17465         return this.definition().global;
17466     });
17467     AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
17468         return defaults(options, {
17469             except: [],
17470             eval: false,
17471             sort: false,
17472             toplevel: false,
17473             screw_ie8: false
17474         });
17475     });
17476     AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
17477         options = this._default_mangler_options(options);
17478         var lname = -1;
17479         var to_mangle = [];
17480         var tw = new TreeWalker(function(node, descend) {
17481             if (node instanceof AST_LabeledStatement) {
17482                 var save_nesting = lname;
17483                 descend();
17484                 lname = save_nesting;
17485                 return true;
17486             }
17487             if (node instanceof AST_Scope) {
17488                 var p = tw.parent(), a = [];
17489                 node.variables.each(function(symbol) {
17490                     if (options.except.indexOf(symbol.name) < 0) {
17491                         a.push(symbol);
17492                     }
17493                 });
17494                 if (options.sort) a.sort(function(a, b) {
17495                     return b.references.length - a.references.length;
17496                 });
17497                 to_mangle.push.apply(to_mangle, a);
17498                 return;
17499             }
17500             if (node instanceof AST_Label) {
17501                 var name;
17502                 do name = base54(++lname); while (!is_identifier(name));
17503                 node.mangled_name = name;
17504                 return true;
17505             }
17506         });
17507         this.walk(tw);
17508         to_mangle.forEach(function(def) {
17509             def.mangle(options);
17510         });
17511     });
17512     AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
17513         options = this._default_mangler_options(options);
17514         var tw = new TreeWalker(function(node) {
17515             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) {
17516                 base54.consider("if");
17517                 if (node.alternative) base54.consider("else");
17518             } 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);
17519         });
17520         this.walk(tw);
17521         base54.sort();
17522     });
17523     var base54 = function() {
17524         var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
17525         var chars, frequency;
17526         function reset() {
17527             frequency = Object.create(null);
17528             chars = string.split("").map(function(ch) {
17529                 return ch.charCodeAt(0);
17530             });
17531             chars.forEach(function(ch) {
17532                 frequency[ch] = 0;
17533             });
17534         }
17535         base54.consider = function(str) {
17536             for (var i = str.length; --i >= 0; ) {
17537                 var code = str.charCodeAt(i);
17538                 if (code in frequency) ++frequency[code];
17539             }
17540         };
17541         base54.sort = function() {
17542             chars = mergeSort(chars, function(a, b) {
17543                 if (is_digit(a) && !is_digit(b)) return 1;
17544                 if (is_digit(b) && !is_digit(a)) return -1;
17545                 return frequency[b] - frequency[a];
17546             });
17547         };
17548         base54.reset = reset;
17549         reset();
17550         base54.get = function() {
17551             return chars;
17552         };
17553         base54.freq = function() {
17554             return frequency;
17555         };
17556         function base54(num) {
17557             var ret = "", base = 54;
17558             do {
17559                 ret += String.fromCharCode(chars[num % base]);
17560                 num = Math.floor(num / base);
17561                 base = 64;
17562             } while (num > 0);
17563             return ret;
17564         }
17565         return base54;
17566     }();
17567     AST_Toplevel.DEFMETHOD("scope_warnings", function(options) {
17568         options = defaults(options, {
17569             undeclared: false,
17570             unreferenced: true,
17571             assign_to_global: true,
17572             func_arguments: true,
17573             nested_defuns: true,
17574             eval: true
17575         });
17576         var tw = new TreeWalker(function(node) {
17577             if (options.undeclared && node instanceof AST_SymbolRef && node.undeclared()) {
17578                 AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
17579                     name: node.name,
17580                     file: node.start.file,
17581                     line: node.start.line,
17582                     col: node.start.col
17583                 });
17584             }
17585             if (options.assign_to_global) {
17586                 var sym = null;
17587                 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;
17588                 if (sym && (sym.undeclared() || sym.global() && sym.scope !== sym.definition().scope)) {
17589                     AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
17590                         msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
17591                         name: sym.name,
17592                         file: sym.start.file,
17593                         line: sym.start.line,
17594                         col: sym.start.col
17595                     });
17596                 }
17597             }
17598             if (options.eval && node instanceof AST_SymbolRef && node.undeclared() && node.name == "eval") {
17599                 AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
17600             }
17601             if (options.unreferenced && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) && node.unreferenced()) {
17602                 AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
17603                     type: node instanceof AST_Label ? "Label" : "Symbol",
17604                     name: node.name,
17605                     file: node.start.file,
17606                     line: node.start.line,
17607                     col: node.start.col
17608                 });
17609             }
17610             if (options.func_arguments && node instanceof AST_Lambda && node.uses_arguments) {
17611                 AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
17612                     name: node.name ? node.name.name : "anonymous",
17613                     file: node.start.file,
17614                     line: node.start.line,
17615                     col: node.start.col
17616                 });
17617             }
17618             if (options.nested_defuns && node instanceof AST_Defun && !(tw.parent() instanceof AST_Scope)) {
17619                 AST_Node.warn('Function {name} declared in nested statement "{type}" [{file}:{line},{col}]', {
17620                     name: node.name.name,
17621                     type: tw.parent().TYPE,
17622                     file: node.start.file,
17623                     line: node.start.line,
17624                     col: node.start.col
17625                 });
17626             }
17627         });
17628         this.walk(tw);
17629     });
17630     "use strict";
17631     function OutputStream(options) {
17632         options = defaults(options, {
17633             indent_start: 0,
17634             indent_level: 4,
17635             quote_keys: false,
17636             space_colon: true,
17637             ascii_only: false,
17638             inline_script: false,
17639             width: 80,
17640             max_line_len: 32e3,
17641             ie_proof: true,
17642             beautify: false,
17643             source_map: null,
17644             bracketize: false,
17645             semicolons: true,
17646             comments: false,
17647             preserve_line: false,
17648             negate_iife: !(options && options.beautify)
17649         }, true);
17650         var indentation = 0;
17651         var current_col = 0;
17652         var current_line = 1;
17653         var current_pos = 0;
17654         var OUTPUT = "";
17655         function to_ascii(str, identifier) {
17656             return str.replace(/[\u0080-\uffff]/g, function(ch) {
17657                 var code = ch.charCodeAt(0).toString(16);
17658                 if (code.length <= 2 && !identifier) {
17659                     while (code.length < 2) code = "0" + code;
17660                     return "\\x" + code;
17661                 } else {
17662                     while (code.length < 4) code = "0" + code;
17663                     return "\\u" + code;
17664                 }
17665             });
17666         }
17667         function make_string(str) {
17668             var dq = 0, sq = 0;
17669             str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s) {
17670                 switch (s) {
17671                   case "\\":
17672                     return "\\\\";
17674                   case "\b":
17675                     return "\\b";
17677                   case "\f":
17678                     return "\\f";
17680                   case "\n":
17681                     return "\\n";
17683                   case "\r":
17684                     return "\\r";
17686                   case "\u2028":
17687                     return "\\u2028";
17689                   case "\u2029":
17690                     return "\\u2029";
17692                   case '"':
17693                     ++dq;
17694                     return '"';
17696                   case "'":
17697                     ++sq;
17698                     return "'";
17700                   case "\0":
17701                     return "\\0";
17702                 }
17703                 return s;
17704             });
17705             if (options.ascii_only) str = to_ascii(str);
17706             if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; else return '"' + str.replace(/\x22/g, '\\"') + '"';
17707         }
17708         function encode_string(str) {
17709             var ret = make_string(str);
17710             if (options.inline_script) ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
17711             return ret;
17712         }
17713         function make_name(name) {
17714             name = name.toString();
17715             if (options.ascii_only) name = to_ascii(name, true);
17716             return name;
17717         }
17718         function make_indent(back) {
17719             return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
17720         }
17721         var might_need_space = false;
17722         var might_need_semicolon = false;
17723         var last = null;
17724         function last_char() {
17725             return last.charAt(last.length - 1);
17726         }
17727         function maybe_newline() {
17728             if (options.max_line_len && current_col > options.max_line_len) print("\n");
17729         }
17730         var requireSemicolonChars = makePredicate("( [ + * / - , .");
17731         function print(str) {
17732             str = String(str);
17733             var ch = str.charAt(0);
17734             if (might_need_semicolon) {
17735                 if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
17736                     if (options.semicolons || requireSemicolonChars(ch)) {
17737                         OUTPUT += ";";
17738                         current_col++;
17739                         current_pos++;
17740                     } else {
17741                         OUTPUT += "\n";
17742                         current_pos++;
17743                         current_line++;
17744                         current_col = 0;
17745                     }
17746                     if (!options.beautify) might_need_space = false;
17747                 }
17748                 might_need_semicolon = false;
17749                 maybe_newline();
17750             }
17751             if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
17752                 var target_line = stack[stack.length - 1].start.line;
17753                 while (current_line < target_line) {
17754                     OUTPUT += "\n";
17755                     current_pos++;
17756                     current_line++;
17757                     current_col = 0;
17758                     might_need_space = false;
17759                 }
17760             }
17761             if (might_need_space) {
17762                 var prev = last_char();
17763                 if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\") || /^[\+\-\/]$/.test(ch) && ch == prev) {
17764                     OUTPUT += " ";
17765                     current_col++;
17766                     current_pos++;
17767                 }
17768                 might_need_space = false;
17769             }
17770             var a = str.split(/\r?\n/), n = a.length - 1;
17771             current_line += n;
17772             if (n == 0) {
17773                 current_col += a[n].length;
17774             } else {
17775                 current_col = a[n].length;
17776             }
17777             current_pos += str.length;
17778             last = str;
17779             OUTPUT += str;
17780         }
17781         var space = options.beautify ? function() {
17782             print(" ");
17783         } : function() {
17784             might_need_space = true;
17785         };
17786         var indent = options.beautify ? function(half) {
17787             if (options.beautify) {
17788                 print(make_indent(half ? .5 : 0));
17789             }
17790         } : noop;
17791         var with_indent = options.beautify ? function(col, cont) {
17792             if (col === true) col = next_indent();
17793             var save_indentation = indentation;
17794             indentation = col;
17795             var ret = cont();
17796             indentation = save_indentation;
17797             return ret;
17798         } : function(col, cont) {
17799             return cont();
17800         };
17801         var newline = options.beautify ? function() {
17802             print("\n");
17803         } : noop;
17804         var semicolon = options.beautify ? function() {
17805             print(";");
17806         } : function() {
17807             might_need_semicolon = true;
17808         };
17809         function force_semicolon() {
17810             might_need_semicolon = false;
17811             print(";");
17812         }
17813         function next_indent() {
17814             return indentation + options.indent_level;
17815         }
17816         function with_block(cont) {
17817             var ret;
17818             print("{");
17819             newline();
17820             with_indent(next_indent(), function() {
17821                 ret = cont();
17822             });
17823             indent();
17824             print("}");
17825             return ret;
17826         }
17827         function with_parens(cont) {
17828             print("(");
17829             var ret = cont();
17830             print(")");
17831             return ret;
17832         }
17833         function with_square(cont) {
17834             print("[");
17835             var ret = cont();
17836             print("]");
17837             return ret;
17838         }
17839         function comma() {
17840             print(",");
17841             space();
17842         }
17843         function colon() {
17844             print(":");
17845             if (options.space_colon) space();
17846         }
17847         var add_mapping = options.source_map ? function(token, name) {
17848             try {
17849                 if (token) options.source_map.add(token.file || "?", current_line, current_col, token.line, token.col, !name && token.type == "name" ? token.value : name);
17850             } catch (ex) {
17851                 AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
17852                     file: token.file,
17853                     line: token.line,
17854                     col: token.col,
17855                     cline: current_line,
17856                     ccol: current_col,
17857                     name: name || ""
17858                 });
17859             }
17860         } : noop;
17861         function get() {
17862             return OUTPUT;
17863         }
17864         var stack = [];
17865         return {
17866             get: get,
17867             toString: get,
17868             indent: indent,
17869             indentation: function() {
17870                 return indentation;
17871             },
17872             current_width: function() {
17873                 return current_col - indentation;
17874             },
17875             should_break: function() {
17876                 return options.width && this.current_width() >= options.width;
17877             },
17878             newline: newline,
17879             print: print,
17880             space: space,
17881             comma: comma,
17882             colon: colon,
17883             last: function() {
17884                 return last;
17885             },
17886             semicolon: semicolon,
17887             force_semicolon: force_semicolon,
17888             to_ascii: to_ascii,
17889             print_name: function(name) {
17890                 print(make_name(name));
17891             },
17892             print_string: function(str) {
17893                 print(encode_string(str));
17894             },
17895             next_indent: next_indent,
17896             with_indent: with_indent,
17897             with_block: with_block,
17898             with_parens: with_parens,
17899             with_square: with_square,
17900             add_mapping: add_mapping,
17901             option: function(opt) {
17902                 return options[opt];
17903             },
17904             line: function() {
17905                 return current_line;
17906             },
17907             col: function() {
17908                 return current_col;
17909             },
17910             pos: function() {
17911                 return current_pos;
17912             },
17913             push_node: function(node) {
17914                 stack.push(node);
17915             },
17916             pop_node: function() {
17917                 return stack.pop();
17918             },
17919             stack: function() {
17920                 return stack;
17921             },
17922             parent: function(n) {
17923                 return stack[stack.length - 2 - (n || 0)];
17924             }
17925         };
17926     }
17927     (function() {
17928         function DEFPRINT(nodetype, generator) {
17929             nodetype.DEFMETHOD("_codegen", generator);
17930         }
17931         AST_Node.DEFMETHOD("print", function(stream, force_parens) {
17932             var self = this, generator = self._codegen;
17933             stream.push_node(self);
17934             var needs_parens = self.needs_parens(stream);
17935             var fc = self instanceof AST_Function && stream.option("negate_iife");
17936             if (force_parens || needs_parens && !fc) {
17937                 stream.with_parens(function() {
17938                     self.add_comments(stream);
17939                     self.add_source_map(stream);
17940                     generator(self, stream);
17941                 });
17942             } else {
17943                 self.add_comments(stream);
17944                 if (needs_parens && fc) stream.print("!");
17945                 self.add_source_map(stream);
17946                 generator(self, stream);
17947             }
17948             stream.pop_node();
17949         });
17950         AST_Node.DEFMETHOD("print_to_string", function(options) {
17951             var s = OutputStream(options);
17952             this.print(s);
17953             return s.get();
17954         });
17955         AST_Node.DEFMETHOD("add_comments", function(output) {
17956             var c = output.option("comments"), self = this;
17957             if (c) {
17958                 var start = self.start;
17959                 if (start && !start._comments_dumped) {
17960                     start._comments_dumped = true;
17961                     var comments = start.comments_before;
17962                     if (self instanceof AST_Exit && self.value && self.value.start.comments_before.length > 0) {
17963                         comments = (comments || []).concat(self.value.start.comments_before);
17964                         self.value.start.comments_before = [];
17965                     }
17966                     if (c.test) {
17967                         comments = comments.filter(function(comment) {
17968                             return c.test(comment.value);
17969                         });
17970                     } else if (typeof c == "function") {
17971                         comments = comments.filter(function(comment) {
17972                             return c(self, comment);
17973                         });
17974                     }
17975                     comments.forEach(function(c) {
17976                         if (c.type == "comment1") {
17977                             output.print("//" + c.value + "\n");
17978                             output.indent();
17979                         } else if (c.type == "comment2") {
17980                             output.print("/*" + c.value + "*/");
17981                             if (start.nlb) {
17982                                 output.print("\n");
17983                                 output.indent();
17984                             } else {
17985                                 output.space();
17986                             }
17987                         }
17988                     });
17989                 }
17990             }
17991         });
17992         function PARENS(nodetype, func) {
17993             nodetype.DEFMETHOD("needs_parens", func);
17994         }
17995         PARENS(AST_Node, function() {
17996             return false;
17997         });
17998         PARENS(AST_Function, function(output) {
17999             return first_in_statement(output);
18000         });
18001         PARENS(AST_Object, function(output) {
18002             return first_in_statement(output);
18003         });
18004         PARENS(AST_Unary, function(output) {
18005             var p = output.parent();
18006             return p instanceof AST_PropAccess && p.expression === this;
18007         });
18008         PARENS(AST_Seq, function(output) {
18009             var p = output.parent();
18010             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;
18011         });
18012         PARENS(AST_Binary, function(output) {
18013             var p = output.parent();
18014             if (p instanceof AST_Call && p.expression === this) return true;
18015             if (p instanceof AST_Unary) return true;
18016             if (p instanceof AST_PropAccess && p.expression === this) return true;
18017             if (p instanceof AST_Binary) {
18018                 var po = p.operator, pp = PRECEDENCE[po];
18019                 var so = this.operator, sp = PRECEDENCE[so];
18020                 if (pp > sp || pp == sp && this === p.right && !(so == po && (so == "*" || so == "&&" || so == "||"))) {
18021                     return true;
18022                 }
18023             }
18024         });
18025         PARENS(AST_PropAccess, function(output) {
18026             var p = output.parent();
18027             if (p instanceof AST_New && p.expression === this) {
18028                 try {
18029                     this.walk(new TreeWalker(function(node) {
18030                         if (node instanceof AST_Call) throw p;
18031                     }));
18032                 } catch (ex) {
18033                     if (ex !== p) throw ex;
18034                     return true;
18035                 }
18036             }
18037         });
18038         PARENS(AST_Call, function(output) {
18039             var p = output.parent();
18040             return p instanceof AST_New && p.expression === this;
18041         });
18042         PARENS(AST_New, function(output) {
18043             var p = output.parent();
18044             if (no_constructor_parens(this, output) && (p instanceof AST_PropAccess || p instanceof AST_Call && p.expression === this)) return true;
18045         });
18046         PARENS(AST_Number, function(output) {
18047             var p = output.parent();
18048             if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) return true;
18049         });
18050         PARENS(AST_NaN, function(output) {
18051             var p = output.parent();
18052             if (p instanceof AST_PropAccess && p.expression === this) return true;
18053         });
18054         function assign_and_conditional_paren_rules(output) {
18055             var p = output.parent();
18056             if (p instanceof AST_Unary) return true;
18057             if (p instanceof AST_Binary && !(p instanceof AST_Assign)) return true;
18058             if (p instanceof AST_Call && p.expression === this) return true;
18059             if (p instanceof AST_Conditional && p.condition === this) return true;
18060             if (p instanceof AST_PropAccess && p.expression === this) return true;
18061         }
18062         PARENS(AST_Assign, assign_and_conditional_paren_rules);
18063         PARENS(AST_Conditional, assign_and_conditional_paren_rules);
18064         DEFPRINT(AST_Directive, function(self, output) {
18065             output.print_string(self.value);
18066             output.semicolon();
18067         });
18068         DEFPRINT(AST_Debugger, function(self, output) {
18069             output.print("debugger");
18070             output.semicolon();
18071         });
18072         function display_body(body, is_toplevel, output) {
18073             var last = body.length - 1;
18074             body.forEach(function(stmt, i) {
18075                 if (!(stmt instanceof AST_EmptyStatement)) {
18076                     output.indent();
18077                     stmt.print(output);
18078                     if (!(i == last && is_toplevel)) {
18079                         output.newline();
18080                         if (is_toplevel) output.newline();
18081                     }
18082                 }
18083             });
18084         }
18085         AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
18086             force_statement(this.body, output);
18087         });
18088         DEFPRINT(AST_Statement, function(self, output) {
18089             self.body.print(output);
18090             output.semicolon();
18091         });
18092         DEFPRINT(AST_Toplevel, function(self, output) {
18093             display_body(self.body, true, output);
18094             output.print("");
18095         });
18096         DEFPRINT(AST_LabeledStatement, function(self, output) {
18097             self.label.print(output);
18098             output.colon();
18099             self.body.print(output);
18100         });
18101         DEFPRINT(AST_SimpleStatement, function(self, output) {
18102             self.body.print(output);
18103             output.semicolon();
18104         });
18105         function print_bracketed(body, output) {
18106             if (body.length > 0) output.with_block(function() {
18107                 display_body(body, false, output);
18108             }); else output.print("{}");
18109         }
18110         DEFPRINT(AST_BlockStatement, function(self, output) {
18111             print_bracketed(self.body, output);
18112         });
18113         DEFPRINT(AST_EmptyStatement, function(self, output) {
18114             output.semicolon();
18115         });
18116         DEFPRINT(AST_Do, function(self, output) {
18117             output.print("do");
18118             output.space();
18119             self._do_print_body(output);
18120             output.space();
18121             output.print("while");
18122             output.space();
18123             output.with_parens(function() {
18124                 self.condition.print(output);
18125             });
18126             output.semicolon();
18127         });
18128         DEFPRINT(AST_While, function(self, output) {
18129             output.print("while");
18130             output.space();
18131             output.with_parens(function() {
18132                 self.condition.print(output);
18133             });
18134             output.space();
18135             self._do_print_body(output);
18136         });
18137         DEFPRINT(AST_For, function(self, output) {
18138             output.print("for");
18139             output.space();
18140             output.with_parens(function() {
18141                 if (self.init) {
18142                     if (self.init instanceof AST_Definitions) {
18143                         self.init.print(output);
18144                     } else {
18145                         parenthesize_for_noin(self.init, output, true);
18146                     }
18147                     output.print(";");
18148                     output.space();
18149                 } else {
18150                     output.print(";");
18151                 }
18152                 if (self.condition) {
18153                     self.condition.print(output);
18154                     output.print(";");
18155                     output.space();
18156                 } else {
18157                     output.print(";");
18158                 }
18159                 if (self.step) {
18160                     self.step.print(output);
18161                 }
18162             });
18163             output.space();
18164             self._do_print_body(output);
18165         });
18166         DEFPRINT(AST_ForIn, function(self, output) {
18167             output.print("for");
18168             output.space();
18169             output.with_parens(function() {
18170                 self.init.print(output);
18171                 output.space();
18172                 output.print("in");
18173                 output.space();
18174                 self.object.print(output);
18175             });
18176             output.space();
18177             self._do_print_body(output);
18178         });
18179         DEFPRINT(AST_With, function(self, output) {
18180             output.print("with");
18181             output.space();
18182             output.with_parens(function() {
18183                 self.expression.print(output);
18184             });
18185             output.space();
18186             self._do_print_body(output);
18187         });
18188         AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
18189             var self = this;
18190             if (!nokeyword) {
18191                 output.print("function");
18192             }
18193             if (self.name) {
18194                 output.space();
18195                 self.name.print(output);
18196             }
18197             output.with_parens(function() {
18198                 self.argnames.forEach(function(arg, i) {
18199                     if (i) output.comma();
18200                     arg.print(output);
18201                 });
18202             });
18203             output.space();
18204             print_bracketed(self.body, output);
18205         });
18206         DEFPRINT(AST_Lambda, function(self, output) {
18207             self._do_print(output);
18208         });
18209         AST_Exit.DEFMETHOD("_do_print", function(output, kind) {
18210             output.print(kind);
18211             if (this.value) {
18212                 output.space();
18213                 this.value.print(output);
18214             }
18215             output.semicolon();
18216         });
18217         DEFPRINT(AST_Return, function(self, output) {
18218             self._do_print(output, "return");
18219         });
18220         DEFPRINT(AST_Throw, function(self, output) {
18221             self._do_print(output, "throw");
18222         });
18223         AST_LoopControl.DEFMETHOD("_do_print", function(output, kind) {
18224             output.print(kind);
18225             if (this.label) {
18226                 output.space();
18227                 this.label.print(output);
18228             }
18229             output.semicolon();
18230         });
18231         DEFPRINT(AST_Break, function(self, output) {
18232             self._do_print(output, "break");
18233         });
18234         DEFPRINT(AST_Continue, function(self, output) {
18235             self._do_print(output, "continue");
18236         });
18237         function make_then(self, output) {
18238             if (output.option("bracketize")) {
18239                 make_block(self.body, output);
18240                 return;
18241             }
18242             if (!self.body) return output.force_semicolon();
18243             if (self.body instanceof AST_Do && output.option("ie_proof")) {
18244                 make_block(self.body, output);
18245                 return;
18246             }
18247             var b = self.body;
18248             while (true) {
18249                 if (b instanceof AST_If) {
18250                     if (!b.alternative) {
18251                         make_block(self.body, output);
18252                         return;
18253                     }
18254                     b = b.alternative;
18255                 } else if (b instanceof AST_StatementWithBody) {
18256                     b = b.body;
18257                 } else break;
18258             }
18259             force_statement(self.body, output);
18260         }
18261         DEFPRINT(AST_If, function(self, output) {
18262             output.print("if");
18263             output.space();
18264             output.with_parens(function() {
18265                 self.condition.print(output);
18266             });
18267             output.space();
18268             if (self.alternative) {
18269                 make_then(self, output);
18270                 output.space();
18271                 output.print("else");
18272                 output.space();
18273                 force_statement(self.alternative, output);
18274             } else {
18275                 self._do_print_body(output);
18276             }
18277         });
18278         DEFPRINT(AST_Switch, function(self, output) {
18279             output.print("switch");
18280             output.space();
18281             output.with_parens(function() {
18282                 self.expression.print(output);
18283             });
18284             output.space();
18285             if (self.body.length > 0) output.with_block(function() {
18286                 self.body.forEach(function(stmt, i) {
18287                     if (i) output.newline();
18288                     output.indent(true);
18289                     stmt.print(output);
18290                 });
18291             }); else output.print("{}");
18292         });
18293         AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
18294             if (this.body.length > 0) {
18295                 output.newline();
18296                 this.body.forEach(function(stmt) {
18297                     output.indent();
18298                     stmt.print(output);
18299                     output.newline();
18300                 });
18301             }
18302         });
18303         DEFPRINT(AST_Default, function(self, output) {
18304             output.print("default:");
18305             self._do_print_body(output);
18306         });
18307         DEFPRINT(AST_Case, function(self, output) {
18308             output.print("case");
18309             output.space();
18310             self.expression.print(output);
18311             output.print(":");
18312             self._do_print_body(output);
18313         });
18314         DEFPRINT(AST_Try, function(self, output) {
18315             output.print("try");
18316             output.space();
18317             print_bracketed(self.body, output);
18318             if (self.bcatch) {
18319                 output.space();
18320                 self.bcatch.print(output);
18321             }
18322             if (self.bfinally) {
18323                 output.space();
18324                 self.bfinally.print(output);
18325             }
18326         });
18327         DEFPRINT(AST_Catch, function(self, output) {
18328             output.print("catch");
18329             output.space();
18330             output.with_parens(function() {
18331                 self.argname.print(output);
18332             });
18333             output.space();
18334             print_bracketed(self.body, output);
18335         });
18336         DEFPRINT(AST_Finally, function(self, output) {
18337             output.print("finally");
18338             output.space();
18339             print_bracketed(self.body, output);
18340         });
18341         AST_Definitions.DEFMETHOD("_do_print", function(output, kind) {
18342             output.print(kind);
18343             output.space();
18344             this.definitions.forEach(function(def, i) {
18345                 if (i) output.comma();
18346                 def.print(output);
18347             });
18348             var p = output.parent();
18349             var in_for = p instanceof AST_For || p instanceof AST_ForIn;
18350             var avoid_semicolon = in_for && p.init === this;
18351             if (!avoid_semicolon) output.semicolon();
18352         });
18353         DEFPRINT(AST_Var, function(self, output) {
18354             self._do_print(output, "var");
18355         });
18356         DEFPRINT(AST_Const, function(self, output) {
18357             self._do_print(output, "const");
18358         });
18359         function parenthesize_for_noin(node, output, noin) {
18360             if (!noin) node.print(output); else try {
18361                 node.walk(new TreeWalker(function(node) {
18362                     if (node instanceof AST_Binary && node.operator == "in") throw output;
18363                 }));
18364                 node.print(output);
18365             } catch (ex) {
18366                 if (ex !== output) throw ex;
18367                 node.print(output, true);
18368             }
18369         }
18370         DEFPRINT(AST_VarDef, function(self, output) {
18371             self.name.print(output);
18372             if (self.value) {
18373                 output.space();
18374                 output.print("=");
18375                 output.space();
18376                 var p = output.parent(1);
18377                 var noin = p instanceof AST_For || p instanceof AST_ForIn;
18378                 parenthesize_for_noin(self.value, output, noin);
18379             }
18380         });
18381         DEFPRINT(AST_Call, function(self, output) {
18382             self.expression.print(output);
18383             if (self instanceof AST_New && no_constructor_parens(self, output)) return;
18384             output.with_parens(function() {
18385                 self.args.forEach(function(expr, i) {
18386                     if (i) output.comma();
18387                     expr.print(output);
18388                 });
18389             });
18390         });
18391         DEFPRINT(AST_New, function(self, output) {
18392             output.print("new");
18393             output.space();
18394             AST_Call.prototype._codegen(self, output);
18395         });
18396         AST_Seq.DEFMETHOD("_do_print", function(output) {
18397             this.car.print(output);
18398             if (this.cdr) {
18399                 output.comma();
18400                 if (output.should_break()) {
18401                     output.newline();
18402                     output.indent();
18403                 }
18404                 this.cdr.print(output);
18405             }
18406         });
18407         DEFPRINT(AST_Seq, function(self, output) {
18408             self._do_print(output);
18409         });
18410         DEFPRINT(AST_Dot, function(self, output) {
18411             var expr = self.expression;
18412             expr.print(output);
18413             if (expr instanceof AST_Number && expr.getValue() >= 0) {
18414                 if (!/[xa-f.]/i.test(output.last())) {
18415                     output.print(".");
18416                 }
18417             }
18418             output.print(".");
18419             output.add_mapping(self.end);
18420             output.print_name(self.property);
18421         });
18422         DEFPRINT(AST_Sub, function(self, output) {
18423             self.expression.print(output);
18424             output.print("[");
18425             self.property.print(output);
18426             output.print("]");
18427         });
18428         DEFPRINT(AST_UnaryPrefix, function(self, output) {
18429             var op = self.operator;
18430             output.print(op);
18431             if (/^[a-z]/i.test(op)) output.space();
18432             self.expression.print(output);
18433         });
18434         DEFPRINT(AST_UnaryPostfix, function(self, output) {
18435             self.expression.print(output);
18436             output.print(self.operator);
18437         });
18438         DEFPRINT(AST_Binary, function(self, output) {
18439             self.left.print(output);
18440             output.space();
18441             output.print(self.operator);
18442             output.space();
18443             self.right.print(output);
18444         });
18445         DEFPRINT(AST_Conditional, function(self, output) {
18446             self.condition.print(output);
18447             output.space();
18448             output.print("?");
18449             output.space();
18450             self.consequent.print(output);
18451             output.space();
18452             output.colon();
18453             self.alternative.print(output);
18454         });
18455         DEFPRINT(AST_Array, function(self, output) {
18456             output.with_square(function() {
18457                 var a = self.elements, len = a.length;
18458                 if (len > 0) output.space();
18459                 a.forEach(function(exp, i) {
18460                     if (i) output.comma();
18461                     exp.print(output);
18462                 });
18463                 if (len > 0) output.space();
18464             });
18465         });
18466         DEFPRINT(AST_Object, function(self, output) {
18467             if (self.properties.length > 0) output.with_block(function() {
18468                 self.properties.forEach(function(prop, i) {
18469                     if (i) {
18470                         output.print(",");
18471                         output.newline();
18472                     }
18473                     output.indent();
18474                     prop.print(output);
18475                 });
18476                 output.newline();
18477             }); else output.print("{}");
18478         });
18479         DEFPRINT(AST_ObjectKeyVal, function(self, output) {
18480             var key = self.key;
18481             if (output.option("quote_keys")) {
18482                 output.print_string(key + "");
18483             } else if ((typeof key == "number" || !output.option("beautify") && +key + "" == key) && parseFloat(key) >= 0) {
18484                 output.print(make_num(key));
18485             } else if (!is_identifier(key)) {
18486                 output.print_string(key);
18487             } else {
18488                 output.print_name(key);
18489             }
18490             output.colon();
18491             self.value.print(output);
18492         });
18493         DEFPRINT(AST_ObjectSetter, function(self, output) {
18494             output.print("set");
18495             self.value._do_print(output, true);
18496         });
18497         DEFPRINT(AST_ObjectGetter, function(self, output) {
18498             output.print("get");
18499             self.value._do_print(output, true);
18500         });
18501         DEFPRINT(AST_Symbol, function(self, output) {
18502             var def = self.definition();
18503             output.print_name(def ? def.mangled_name || def.name : self.name);
18504         });
18505         DEFPRINT(AST_Undefined, function(self, output) {
18506             output.print("void 0");
18507         });
18508         DEFPRINT(AST_Hole, noop);
18509         DEFPRINT(AST_Infinity, function(self, output) {
18510             output.print("1/0");
18511         });
18512         DEFPRINT(AST_NaN, function(self, output) {
18513             output.print("0/0");
18514         });
18515         DEFPRINT(AST_This, function(self, output) {
18516             output.print("this");
18517         });
18518         DEFPRINT(AST_Constant, function(self, output) {
18519             output.print(self.getValue());
18520         });
18521         DEFPRINT(AST_String, function(self, output) {
18522             output.print_string(self.getValue());
18523         });
18524         DEFPRINT(AST_Number, function(self, output) {
18525             output.print(make_num(self.getValue()));
18526         });
18527         DEFPRINT(AST_RegExp, function(self, output) {
18528             var str = self.getValue().toString();
18529             if (output.option("ascii_only")) str = output.to_ascii(str);
18530             output.print(str);
18531             var p = output.parent();
18532             if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) output.print(" ");
18533         });
18534         function force_statement(stat, output) {
18535             if (output.option("bracketize")) {
18536                 if (!stat || stat instanceof AST_EmptyStatement) output.print("{}"); else if (stat instanceof AST_BlockStatement) stat.print(output); else output.with_block(function() {
18537                     output.indent();
18538                     stat.print(output);
18539                     output.newline();
18540                 });
18541             } else {
18542                 if (!stat || stat instanceof AST_EmptyStatement) output.force_semicolon(); else stat.print(output);
18543             }
18544         }
18545         function first_in_statement(output) {
18546             var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
18547             while (i > 0) {
18548                 if (p instanceof AST_Statement && p.body === node) return true;
18549                 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) {
18550                     node = p;
18551                     p = a[--i];
18552                 } else {
18553                     return false;
18554                 }
18555             }
18556         }
18557         function no_constructor_parens(self, output) {
18558             return self.args.length == 0 && !output.option("beautify");
18559         }
18560         function best_of(a) {
18561             var best = a[0], len = best.length;
18562             for (var i = 1; i < a.length; ++i) {
18563                 if (a[i].length < len) {
18564                     best = a[i];
18565                     len = best.length;
18566                 }
18567             }
18568             return best;
18569         }
18570         function make_num(num) {
18571             var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace("e+", "e") ], m;
18572             if (Math.floor(num) === num) {
18573                 if (num >= 0) {
18574                     a.push("0x" + num.toString(16).toLowerCase(), "0" + num.toString(8));
18575                 } else {
18576                     a.push("-0x" + (-num).toString(16).toLowerCase(), "-0" + (-num).toString(8));
18577                 }
18578                 if (m = /^(.*?)(0+)$/.exec(num)) {
18579                     a.push(m[1] + "e" + m[2].length);
18580                 }
18581             } else if (m = /^0?\.(0+)(.*)$/.exec(num)) {
18582                 a.push(m[2] + "e-" + (m[1].length + m[2].length), str.substr(str.indexOf(".")));
18583             }
18584             return best_of(a);
18585         }
18586         function make_block(stmt, output) {
18587             if (stmt instanceof AST_BlockStatement) {
18588                 stmt.print(output);
18589                 return;
18590             }
18591             output.with_block(function() {
18592                 output.indent();
18593                 stmt.print(output);
18594                 output.newline();
18595             });
18596         }
18597         function DEFMAP(nodetype, generator) {
18598             nodetype.DEFMETHOD("add_source_map", function(stream) {
18599                 generator(this, stream);
18600             });
18601         }
18602         DEFMAP(AST_Node, noop);
18603         function basic_sourcemap_gen(self, output) {
18604             output.add_mapping(self.start);
18605         }
18606         DEFMAP(AST_Directive, basic_sourcemap_gen);
18607         DEFMAP(AST_Debugger, basic_sourcemap_gen);
18608         DEFMAP(AST_Symbol, basic_sourcemap_gen);
18609         DEFMAP(AST_Jump, basic_sourcemap_gen);
18610         DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
18611         DEFMAP(AST_LabeledStatement, noop);
18612         DEFMAP(AST_Lambda, basic_sourcemap_gen);
18613         DEFMAP(AST_Switch, basic_sourcemap_gen);
18614         DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
18615         DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
18616         DEFMAP(AST_Toplevel, noop);
18617         DEFMAP(AST_New, basic_sourcemap_gen);
18618         DEFMAP(AST_Try, basic_sourcemap_gen);
18619         DEFMAP(AST_Catch, basic_sourcemap_gen);
18620         DEFMAP(AST_Finally, basic_sourcemap_gen);
18621         DEFMAP(AST_Definitions, basic_sourcemap_gen);
18622         DEFMAP(AST_Constant, basic_sourcemap_gen);
18623         DEFMAP(AST_ObjectProperty, function(self, output) {
18624             output.add_mapping(self.start, self.key);
18625         });
18626     })();
18627     "use strict";
18628     function Compressor(options, false_by_default) {
18629         if (!(this instanceof Compressor)) return new Compressor(options, false_by_default);
18630         TreeTransformer.call(this, this.before, this.after);
18631         this.options = defaults(options, {
18632             sequences: !false_by_default,
18633             properties: !false_by_default,
18634             dead_code: !false_by_default,
18635             drop_debugger: !false_by_default,
18636             unsafe: false,
18637             unsafe_comps: false,
18638             conditionals: !false_by_default,
18639             comparisons: !false_by_default,
18640             evaluate: !false_by_default,
18641             booleans: !false_by_default,
18642             loops: !false_by_default,
18643             unused: !false_by_default,
18644             hoist_funs: !false_by_default,
18645             hoist_vars: false,
18646             if_return: !false_by_default,
18647             join_vars: !false_by_default,
18648             cascade: !false_by_default,
18649             side_effects: !false_by_default,
18650             screw_ie8: false,
18651             warnings: true,
18652             global_defs: {}
18653         }, true);
18654     }
18655     Compressor.prototype = new TreeTransformer();
18656     merge(Compressor.prototype, {
18657         option: function(key) {
18658             return this.options[key];
18659         },
18660         warn: function() {
18661             if (this.options.warnings) AST_Node.warn.apply(AST_Node, arguments);
18662         },
18663         before: function(node, descend, in_list) {
18664             if (node._squeezed) return node;
18665             if (node instanceof AST_Scope) {
18666                 node.drop_unused(this);
18667                 node = node.hoist_declarations(this);
18668             }
18669             descend(node, this);
18670             node = node.optimize(this);
18671             if (node instanceof AST_Scope) {
18672                 var save_warnings = this.options.warnings;
18673                 this.options.warnings = false;
18674                 node.drop_unused(this);
18675                 this.options.warnings = save_warnings;
18676             }
18677             node._squeezed = true;
18678             return node;
18679         }
18680     });
18681     (function() {
18682         function OPT(node, optimizer) {
18683             node.DEFMETHOD("optimize", function(compressor) {
18684                 var self = this;
18685                 if (self._optimized) return self;
18686                 var opt = optimizer(self, compressor);
18687                 opt._optimized = true;
18688                 if (opt === self) return opt;
18689                 return opt.transform(compressor);
18690             });
18691         }
18692         OPT(AST_Node, function(self, compressor) {
18693             return self;
18694         });
18695         AST_Node.DEFMETHOD("equivalent_to", function(node) {
18696             return this.print_to_string() == node.print_to_string();
18697         });
18698         function make_node(ctor, orig, props) {
18699             if (!props) props = {};
18700             if (orig) {
18701                 if (!props.start) props.start = orig.start;
18702                 if (!props.end) props.end = orig.end;
18703             }
18704             return new ctor(props);
18705         }
18706         function make_node_from_constant(compressor, val, orig) {
18707             if (val instanceof AST_Node) return val.transform(compressor);
18708             switch (typeof val) {
18709               case "string":
18710                 return make_node(AST_String, orig, {
18711                     value: val
18712                 }).optimize(compressor);
18714               case "number":
18715                 return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, {
18716                     value: val
18717                 }).optimize(compressor);
18719               case "boolean":
18720                 return make_node(val ? AST_True : AST_False, orig).optimize(compressor);
18722               case "undefined":
18723                 return make_node(AST_Undefined, orig).optimize(compressor);
18725               default:
18726                 if (val === null) {
18727                     return make_node(AST_Null, orig).optimize(compressor);
18728                 }
18729                 if (val instanceof RegExp) {
18730                     return make_node(AST_RegExp, orig).optimize(compressor);
18731                 }
18732                 throw new Error(string_template("Can't handle constant of type: {type}", {
18733                     type: typeof val
18734                 }));
18735             }
18736         }
18737         function as_statement_array(thing) {
18738             if (thing === null) return [];
18739             if (thing instanceof AST_BlockStatement) return thing.body;
18740             if (thing instanceof AST_EmptyStatement) return [];
18741             if (thing instanceof AST_Statement) return [ thing ];
18742             throw new Error("Can't convert thing to statement array");
18743         }
18744         function is_empty(thing) {
18745             if (thing === null) return true;
18746             if (thing instanceof AST_EmptyStatement) return true;
18747             if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
18748             return false;
18749         }
18750         function loop_body(x) {
18751             if (x instanceof AST_Switch) return x;
18752             if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
18753                 return x.body instanceof AST_BlockStatement ? x.body : x;
18754             }
18755             return x;
18756         }
18757         function tighten_body(statements, compressor) {
18758             var CHANGED;
18759             do {
18760                 CHANGED = false;
18761                 statements = eliminate_spurious_blocks(statements);
18762                 if (compressor.option("dead_code")) {
18763                     statements = eliminate_dead_code(statements, compressor);
18764                 }
18765                 if (compressor.option("if_return")) {
18766                     statements = handle_if_return(statements, compressor);
18767                 }
18768                 if (compressor.option("sequences")) {
18769                     statements = sequencesize(statements, compressor);
18770                 }
18771                 if (compressor.option("join_vars")) {
18772                     statements = join_consecutive_vars(statements, compressor);
18773                 }
18774             } while (CHANGED);
18775             return statements;
18776             function eliminate_spurious_blocks(statements) {
18777                 var seen_dirs = [];
18778                 return statements.reduce(function(a, stat) {
18779                     if (stat instanceof AST_BlockStatement) {
18780                         CHANGED = true;
18781                         a.push.apply(a, eliminate_spurious_blocks(stat.body));
18782                     } else if (stat instanceof AST_EmptyStatement) {
18783                         CHANGED = true;
18784                     } else if (stat instanceof AST_Directive) {
18785                         if (seen_dirs.indexOf(stat.value) < 0) {
18786                             a.push(stat);
18787                             seen_dirs.push(stat.value);
18788                         } else {
18789                             CHANGED = true;
18790                         }
18791                     } else {
18792                         a.push(stat);
18793                     }
18794                     return a;
18795                 }, []);
18796             }
18797             function handle_if_return(statements, compressor) {
18798                 var self = compressor.self();
18799                 var in_lambda = self instanceof AST_Lambda;
18800                 var ret = [];
18801                 loop: for (var i = statements.length; --i >= 0; ) {
18802                     var stat = statements[i];
18803                     switch (true) {
18804                       case in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0:
18805                         CHANGED = true;
18806                         continue loop;
18808                       case stat instanceof AST_If:
18809                         if (stat.body instanceof AST_Return) {
18810                             if ((in_lambda && ret.length == 0 || ret[0] instanceof AST_Return && !ret[0].value) && !stat.body.value && !stat.alternative) {
18811                                 CHANGED = true;
18812                                 var cond = make_node(AST_SimpleStatement, stat.condition, {
18813                                     body: stat.condition
18814                                 });
18815                                 ret.unshift(cond);
18816                                 continue loop;
18817                             }
18818                             if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
18819                                 CHANGED = true;
18820                                 stat = stat.clone();
18821                                 stat.alternative = ret[0];
18822                                 ret[0] = stat.transform(compressor);
18823                                 continue loop;
18824                             }
18825                             if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) {
18826                                 CHANGED = true;
18827                                 stat = stat.clone();
18828                                 stat.alternative = ret[0] || make_node(AST_Return, stat, {
18829                                     value: make_node(AST_Undefined, stat)
18830                                 });
18831                                 ret[0] = stat.transform(compressor);
18832                                 continue loop;
18833                             }
18834                             if (!stat.body.value && in_lambda) {
18835                                 CHANGED = true;
18836                                 stat = stat.clone();
18837                                 stat.condition = stat.condition.negate(compressor);
18838                                 stat.body = make_node(AST_BlockStatement, stat, {
18839                                     body: as_statement_array(stat.alternative).concat(ret)
18840                                 });
18841                                 stat.alternative = null;
18842                                 ret = [ stat.transform(compressor) ];
18843                                 continue loop;
18844                             }
18845                             if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
18846                                 CHANGED = true;
18847                                 ret.push(make_node(AST_Return, ret[0], {
18848                                     value: make_node(AST_Undefined, ret[0])
18849                                 }).transform(compressor));
18850                                 ret = as_statement_array(stat.alternative).concat(ret);
18851                                 ret.unshift(stat);
18852                                 continue loop;
18853                             }
18854                         }
18855                         var ab = aborts(stat.body);
18856                         var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
18857                         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)) {
18858                             if (ab.label) {
18859                                 remove(ab.label.thedef.references, ab.label);
18860                             }
18861                             CHANGED = true;
18862                             var body = as_statement_array(stat.body).slice(0, -1);
18863                             stat = stat.clone();
18864                             stat.condition = stat.condition.negate(compressor);
18865                             stat.body = make_node(AST_BlockStatement, stat, {
18866                                 body: ret
18867                             });
18868                             stat.alternative = make_node(AST_BlockStatement, stat, {
18869                                 body: body
18870                             });
18871                             ret = [ stat.transform(compressor) ];
18872                             continue loop;
18873                         }
18874                         var ab = aborts(stat.alternative);
18875                         var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
18876                         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)) {
18877                             if (ab.label) {
18878                                 remove(ab.label.thedef.references, ab.label);
18879                             }
18880                             CHANGED = true;
18881                             stat = stat.clone();
18882                             stat.body = make_node(AST_BlockStatement, stat.body, {
18883                                 body: as_statement_array(stat.body).concat(ret)
18884                             });
18885                             stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
18886                                 body: as_statement_array(stat.alternative).slice(0, -1)
18887                             });
18888                             ret = [ stat.transform(compressor) ];
18889                             continue loop;
18890                         }
18891                         ret.unshift(stat);
18892                         break;
18894                       default:
18895                         ret.unshift(stat);
18896                         break;
18897                     }
18898                 }
18899                 return ret;
18900             }
18901             function eliminate_dead_code(statements, compressor) {
18902                 var has_quit = false;
18903                 var orig = statements.length;
18904                 var self = compressor.self();
18905                 statements = statements.reduce(function(a, stat) {
18906                     if (has_quit) {
18907                         extract_declarations_from_unreachable_code(compressor, stat, a);
18908                     } else {
18909                         if (stat instanceof AST_LoopControl) {
18910                             var lct = compressor.loopcontrol_target(stat.label);
18911                             if (stat instanceof AST_Break && lct instanceof AST_BlockStatement && loop_body(lct) === self || stat instanceof AST_Continue && loop_body(lct) === self) {
18912                                 if (stat.label) {
18913                                     remove(stat.label.thedef.references, stat.label);
18914                                 }
18915                             } else {
18916                                 a.push(stat);
18917                             }
18918                         } else {
18919                             a.push(stat);
18920                         }
18921                         if (aborts(stat)) has_quit = true;
18922                     }
18923                     return a;
18924                 }, []);
18925                 CHANGED = statements.length != orig;
18926                 return statements;
18927             }
18928             function sequencesize(statements, compressor) {
18929                 if (statements.length < 2) return statements;
18930                 var seq = [], ret = [];
18931                 function push_seq() {
18932                     seq = AST_Seq.from_array(seq);
18933                     if (seq) ret.push(make_node(AST_SimpleStatement, seq, {
18934                         body: seq
18935                     }));
18936                     seq = [];
18937                 }
18938                 statements.forEach(function(stat) {
18939                     if (stat instanceof AST_SimpleStatement) seq.push(stat.body); else push_seq(), ret.push(stat);
18940                 });
18941                 push_seq();
18942                 ret = sequencesize_2(ret, compressor);
18943                 CHANGED = ret.length != statements.length;
18944                 return ret;
18945             }
18946             function sequencesize_2(statements, compressor) {
18947                 function cons_seq(right) {
18948                     ret.pop();
18949                     var left = prev.body;
18950                     if (left instanceof AST_Seq) {
18951                         left.add(right);
18952                     } else {
18953                         left = AST_Seq.cons(left, right);
18954                     }
18955                     return left.transform(compressor);
18956                 }
18957                 var ret = [], prev = null;
18958                 statements.forEach(function(stat) {
18959                     if (prev) {
18960                         if (stat instanceof AST_For) {
18961                             var opera = {};
18962                             try {
18963                                 prev.body.walk(new TreeWalker(function(node) {
18964                                     if (node instanceof AST_Binary && node.operator == "in") throw opera;
18965                                 }));
18966                                 if (stat.init && !(stat.init instanceof AST_Definitions)) {
18967                                     stat.init = cons_seq(stat.init);
18968                                 } else if (!stat.init) {
18969                                     stat.init = prev.body;
18970                                     ret.pop();
18971                                 }
18972                             } catch (ex) {
18973                                 if (ex !== opera) throw ex;
18974                             }
18975                         } else if (stat instanceof AST_If) {
18976                             stat.condition = cons_seq(stat.condition);
18977                         } else if (stat instanceof AST_With) {
18978                             stat.expression = cons_seq(stat.expression);
18979                         } else if (stat instanceof AST_Exit && stat.value) {
18980                             stat.value = cons_seq(stat.value);
18981                         } else if (stat instanceof AST_Exit) {
18982                             stat.value = cons_seq(make_node(AST_Undefined, stat));
18983                         } else if (stat instanceof AST_Switch) {
18984                             stat.expression = cons_seq(stat.expression);
18985                         }
18986                     }
18987                     ret.push(stat);
18988                     prev = stat instanceof AST_SimpleStatement ? stat : null;
18989                 });
18990                 return ret;
18991             }
18992             function join_consecutive_vars(statements, compressor) {
18993                 var prev = null;
18994                 return statements.reduce(function(a, stat) {
18995                     if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
18996                         prev.definitions = prev.definitions.concat(stat.definitions);
18997                         CHANGED = true;
18998                     } else if (stat instanceof AST_For && prev instanceof AST_Definitions && (!stat.init || stat.init.TYPE == prev.TYPE)) {
18999                         CHANGED = true;
19000                         a.pop();
19001                         if (stat.init) {
19002                             stat.init.definitions = prev.definitions.concat(stat.init.definitions);
19003                         } else {
19004                             stat.init = prev;
19005                         }
19006                         a.push(stat);
19007                         prev = stat;
19008                     } else {
19009                         prev = stat;
19010                         a.push(stat);
19011                     }
19012                     return a;
19013                 }, []);
19014             }
19015         }
19016         function extract_declarations_from_unreachable_code(compressor, stat, target) {
19017             compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
19018             stat.walk(new TreeWalker(function(node) {
19019                 if (node instanceof AST_Definitions) {
19020                     compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
19021                     node.remove_initializers();
19022                     target.push(node);
19023                     return true;
19024                 }
19025                 if (node instanceof AST_Defun) {
19026                     target.push(node);
19027                     return true;
19028                 }
19029                 if (node instanceof AST_Scope) {
19030                     return true;
19031                 }
19032             }));
19033         }
19034         (function(def) {
19035             var unary_bool = [ "!", "delete" ];
19036             var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
19037             def(AST_Node, function() {
19038                 return false;
19039             });
19040             def(AST_UnaryPrefix, function() {
19041                 return member(this.operator, unary_bool);
19042             });
19043             def(AST_Binary, function() {
19044                 return member(this.operator, binary_bool) || (this.operator == "&&" || this.operator == "||") && this.left.is_boolean() && this.right.is_boolean();
19045             });
19046             def(AST_Conditional, function() {
19047                 return this.consequent.is_boolean() && this.alternative.is_boolean();
19048             });
19049             def(AST_Assign, function() {
19050                 return this.operator == "=" && this.right.is_boolean();
19051             });
19052             def(AST_Seq, function() {
19053                 return this.cdr.is_boolean();
19054             });
19055             def(AST_True, function() {
19056                 return true;
19057             });
19058             def(AST_False, function() {
19059                 return true;
19060             });
19061         })(function(node, func) {
19062             node.DEFMETHOD("is_boolean", func);
19063         });
19064         (function(def) {
19065             def(AST_Node, function() {
19066                 return false;
19067             });
19068             def(AST_String, function() {
19069                 return true;
19070             });
19071             def(AST_UnaryPrefix, function() {
19072                 return this.operator == "typeof";
19073             });
19074             def(AST_Binary, function(compressor) {
19075                 return this.operator == "+" && (this.left.is_string(compressor) || this.right.is_string(compressor));
19076             });
19077             def(AST_Assign, function(compressor) {
19078                 return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
19079             });
19080             def(AST_Seq, function(compressor) {
19081                 return this.cdr.is_string(compressor);
19082             });
19083             def(AST_Conditional, function(compressor) {
19084                 return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
19085             });
19086             def(AST_Call, function(compressor) {
19087                 return compressor.option("unsafe") && this.expression instanceof AST_SymbolRef && this.expression.name == "String" && this.expression.undeclared();
19088             });
19089         })(function(node, func) {
19090             node.DEFMETHOD("is_string", func);
19091         });
19092         function best_of(ast1, ast2) {
19093             return ast1.print_to_string().length > ast2.print_to_string().length ? ast2 : ast1;
19094         }
19095         (function(def) {
19096             AST_Node.DEFMETHOD("evaluate", function(compressor) {
19097                 if (!compressor.option("evaluate")) return [ this ];
19098                 try {
19099                     var val = this._eval(), ast = make_node_from_constant(compressor, val, this);
19100                     return [ best_of(ast, this), val ];
19101                 } catch (ex) {
19102                     if (ex !== def) throw ex;
19103                     return [ this ];
19104                 }
19105             });
19106             def(AST_Statement, function() {
19107                 throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
19108             });
19109             def(AST_Function, function() {
19110                 return [ this ];
19111             });
19112             function ev(node) {
19113                 return node._eval();
19114             }
19115             def(AST_Node, function() {
19116                 throw def;
19117             });
19118             def(AST_Constant, function() {
19119                 return this.getValue();
19120             });
19121             def(AST_UnaryPrefix, function() {
19122                 var e = this.expression;
19123                 switch (this.operator) {
19124                   case "!":
19125                     return !ev(e);
19127                   case "typeof":
19128                     if (e instanceof AST_Function) return typeof function() {};
19129                     e = ev(e);
19130                     if (e instanceof RegExp) throw def;
19131                     return typeof e;
19133                   case "void":
19134                     return void ev(e);
19136                   case "~":
19137                     return ~ev(e);
19139                   case "-":
19140                     e = ev(e);
19141                     if (e === 0) throw def;
19142                     return -e;
19144                   case "+":
19145                     return +ev(e);
19146                 }
19147                 throw def;
19148             });
19149             def(AST_Binary, function() {
19150                 var left = this.left, right = this.right;
19151                 switch (this.operator) {
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 "-":
19180                     return ev(left) - ev(right);
19182                   case "<<":
19183                     return ev(left) << ev(right);
19185                   case ">>":
19186                     return ev(left) >> ev(right);
19188                   case ">>>":
19189                     return ev(left) >>> ev(right);
19191                   case "==":
19192                     return ev(left) == ev(right);
19194                   case "===":
19195                     return ev(left) === ev(right);
19197                   case "!=":
19198                     return ev(left) != ev(right);
19200                   case "!==":
19201                     return ev(left) !== ev(right);
19203                   case "<":
19204                     return ev(left) < ev(right);
19206                   case "<=":
19207                     return ev(left) <= ev(right);
19209                   case ">":
19210                     return ev(left) > ev(right);
19212                   case ">=":
19213                     return ev(left) >= ev(right);
19215                   case "in":
19216                     return ev(left) in ev(right);
19218                   case "instanceof":
19219                     return ev(left) instanceof ev(right);
19220                 }
19221                 throw def;
19222             });
19223             def(AST_Conditional, function() {
19224                 return ev(this.condition) ? ev(this.consequent) : ev(this.alternative);
19225             });
19226             def(AST_SymbolRef, function() {
19227                 var d = this.definition();
19228                 if (d && d.constant && d.init) return ev(d.init);
19229                 throw def;
19230             });
19231         })(function(node, func) {
19232             node.DEFMETHOD("_eval", func);
19233         });
19234         (function(def) {
19235             function basic_negation(exp) {
19236                 return make_node(AST_UnaryPrefix, exp, {
19237                     operator: "!",
19238                     expression: exp
19239                 });
19240             }
19241             def(AST_Node, function() {
19242                 return basic_negation(this);
19243             });
19244             def(AST_Statement, function() {
19245                 throw new Error("Cannot negate a statement");
19246             });
19247             def(AST_Function, function() {
19248                 return basic_negation(this);
19249             });
19250             def(AST_UnaryPrefix, function() {
19251                 if (this.operator == "!") return this.expression;
19252                 return basic_negation(this);
19253             });
19254             def(AST_Seq, function(compressor) {
19255                 var self = this.clone();
19256                 self.cdr = self.cdr.negate(compressor);
19257                 return self;
19258             });
19259             def(AST_Conditional, function(compressor) {
19260                 var self = this.clone();
19261                 self.consequent = self.consequent.negate(compressor);
19262                 self.alternative = self.alternative.negate(compressor);
19263                 return best_of(basic_negation(this), self);
19264             });
19265             def(AST_Binary, function(compressor) {
19266                 var self = this.clone(), op = this.operator;
19267                 if (compressor.option("unsafe_comps")) {
19268                     switch (op) {
19269                       case "<=":
19270                         self.operator = ">";
19271                         return self;
19273                       case "<":
19274                         self.operator = ">=";
19275                         return self;
19277                       case ">=":
19278                         self.operator = "<";
19279                         return self;
19281                       case ">":
19282                         self.operator = "<=";
19283                         return self;
19284                     }
19285                 }
19286                 switch (op) {
19287                   case "==":
19288                     self.operator = "!=";
19289                     return self;
19291                   case "!=":
19292                     self.operator = "==";
19293                     return self;
19295                   case "===":
19296                     self.operator = "!==";
19297                     return self;
19299                   case "!==":
19300                     self.operator = "===";
19301                     return self;
19303                   case "&&":
19304                     self.operator = "||";
19305                     self.left = self.left.negate(compressor);
19306                     self.right = self.right.negate(compressor);
19307                     return best_of(basic_negation(this), self);
19309                   case "||":
19310                     self.operator = "&&";
19311                     self.left = self.left.negate(compressor);
19312                     self.right = self.right.negate(compressor);
19313                     return best_of(basic_negation(this), self);
19314                 }
19315                 return basic_negation(this);
19316             });
19317         })(function(node, func) {
19318             node.DEFMETHOD("negate", function(compressor) {
19319                 return func.call(this, compressor);
19320             });
19321         });
19322         (function(def) {
19323             def(AST_Node, function() {
19324                 return true;
19325             });
19326             def(AST_EmptyStatement, function() {
19327                 return false;
19328             });
19329             def(AST_Constant, function() {
19330                 return false;
19331             });
19332             def(AST_This, function() {
19333                 return false;
19334             });
19335             def(AST_Block, function() {
19336                 for (var i = this.body.length; --i >= 0; ) {
19337                     if (this.body[i].has_side_effects()) return true;
19338                 }
19339                 return false;
19340             });
19341             def(AST_SimpleStatement, function() {
19342                 return this.body.has_side_effects();
19343             });
19344             def(AST_Defun, function() {
19345                 return true;
19346             });
19347             def(AST_Function, function() {
19348                 return false;
19349             });
19350             def(AST_Binary, function() {
19351                 return this.left.has_side_effects() || this.right.has_side_effects();
19352             });
19353             def(AST_Assign, function() {
19354                 return true;
19355             });
19356             def(AST_Conditional, function() {
19357                 return this.condition.has_side_effects() || this.consequent.has_side_effects() || this.alternative.has_side_effects();
19358             });
19359             def(AST_Unary, function() {
19360                 return this.operator == "delete" || this.operator == "++" || this.operator == "--" || this.expression.has_side_effects();
19361             });
19362             def(AST_SymbolRef, function() {
19363                 return false;
19364             });
19365             def(AST_Object, function() {
19366                 for (var i = this.properties.length; --i >= 0; ) if (this.properties[i].has_side_effects()) return true;
19367                 return false;
19368             });
19369             def(AST_ObjectProperty, function() {
19370                 return this.value.has_side_effects();
19371             });
19372             def(AST_Array, function() {
19373                 for (var i = this.elements.length; --i >= 0; ) if (this.elements[i].has_side_effects()) return true;
19374                 return false;
19375             });
19376             def(AST_PropAccess, function() {
19377                 return true;
19378             });
19379             def(AST_Seq, function() {
19380                 return this.car.has_side_effects() || this.cdr.has_side_effects();
19381             });
19382         })(function(node, func) {
19383             node.DEFMETHOD("has_side_effects", func);
19384         });
19385         function aborts(thing) {
19386             return thing && thing.aborts();
19387         }
19388         (function(def) {
19389             def(AST_Statement, function() {
19390                 return null;
19391             });
19392             def(AST_Jump, function() {
19393                 return this;
19394             });
19395             function block_aborts() {
19396                 var n = this.body.length;
19397                 return n > 0 && aborts(this.body[n - 1]);
19398             }
19399             def(AST_BlockStatement, block_aborts);
19400             def(AST_SwitchBranch, block_aborts);
19401             def(AST_If, function() {
19402                 return this.alternative && aborts(this.body) && aborts(this.alternative);
19403             });
19404         })(function(node, func) {
19405             node.DEFMETHOD("aborts", func);
19406         });
19407         OPT(AST_Directive, function(self, compressor) {
19408             if (self.scope.has_directive(self.value) !== self.scope) {
19409                 return make_node(AST_EmptyStatement, self);
19410             }
19411             return self;
19412         });
19413         OPT(AST_Debugger, function(self, compressor) {
19414             if (compressor.option("drop_debugger")) return make_node(AST_EmptyStatement, self);
19415             return self;
19416         });
19417         OPT(AST_LabeledStatement, function(self, compressor) {
19418             if (self.body instanceof AST_Break && compressor.loopcontrol_target(self.body.label) === self.body) {
19419                 return make_node(AST_EmptyStatement, self);
19420             }
19421             return self.label.references.length == 0 ? self.body : self;
19422         });
19423         OPT(AST_Block, function(self, compressor) {
19424             self.body = tighten_body(self.body, compressor);
19425             return self;
19426         });
19427         OPT(AST_BlockStatement, function(self, compressor) {
19428             self.body = tighten_body(self.body, compressor);
19429             switch (self.body.length) {
19430               case 1:
19431                 return self.body[0];
19433               case 0:
19434                 return make_node(AST_EmptyStatement, self);
19435             }
19436             return self;
19437         });
19438         AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
19439             var self = this;
19440             if (compressor.option("unused") && !(self instanceof AST_Toplevel) && !self.uses_eval) {
19441                 var in_use = [];
19442                 var initializations = new Dictionary();
19443                 var scope = this;
19444                 var tw = new TreeWalker(function(node, descend) {
19445                     if (node !== self) {
19446                         if (node instanceof AST_Defun) {
19447                             initializations.add(node.name.name, node);
19448                             return true;
19449                         }
19450                         if (node instanceof AST_Definitions && scope === self) {
19451                             node.definitions.forEach(function(def) {
19452                                 if (def.value) {
19453                                     initializations.add(def.name.name, def.value);
19454                                     if (def.value.has_side_effects()) {
19455                                         def.value.walk(tw);
19456                                     }
19457                                 }
19458                             });
19459                             return true;
19460                         }
19461                         if (node instanceof AST_SymbolRef) {
19462                             push_uniq(in_use, node.definition());
19463                             return true;
19464                         }
19465                         if (node instanceof AST_Scope) {
19466                             var save_scope = scope;
19467                             scope = node;
19468                             descend();
19469                             scope = save_scope;
19470                             return true;
19471                         }
19472                     }
19473                 });
19474                 self.walk(tw);
19475                 for (var i = 0; i < in_use.length; ++i) {
19476                     in_use[i].orig.forEach(function(decl) {
19477                         var init = initializations.get(decl.name);
19478                         if (init) init.forEach(function(init) {
19479                             var tw = new TreeWalker(function(node) {
19480                                 if (node instanceof AST_SymbolRef) {
19481                                     push_uniq(in_use, node.definition());
19482                                 }
19483                             });
19484                             init.walk(tw);
19485                         });
19486                     });
19487                 }
19488                 var tt = new TreeTransformer(function before(node, descend, in_list) {
19489                     if (node instanceof AST_Lambda) {
19490                         for (var a = node.argnames, i = a.length; --i >= 0; ) {
19491                             var sym = a[i];
19492                             if (sym.unreferenced()) {
19493                                 a.pop();
19494                                 compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
19495                                     name: sym.name,
19496                                     file: sym.start.file,
19497                                     line: sym.start.line,
19498                                     col: sym.start.col
19499                                 });
19500                             } else break;
19501                         }
19502                     }
19503                     if (node instanceof AST_Defun && node !== self) {
19504                         if (!member(node.name.definition(), in_use)) {
19505                             compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", {
19506                                 name: node.name.name,
19507                                 file: node.name.start.file,
19508                                 line: node.name.start.line,
19509                                 col: node.name.start.col
19510                             });
19511                             return make_node(AST_EmptyStatement, node);
19512                         }
19513                         return node;
19514                     }
19515                     if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
19516                         var def = node.definitions.filter(function(def) {
19517                             if (member(def.name.definition(), in_use)) return true;
19518                             var w = {
19519                                 name: def.name.name,
19520                                 file: def.name.start.file,
19521                                 line: def.name.start.line,
19522                                 col: def.name.start.col
19523                             };
19524                             if (def.value && def.value.has_side_effects()) {
19525                                 def._unused_side_effects = true;
19526                                 compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
19527                                 return true;
19528                             }
19529                             compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w);
19530                             return false;
19531                         });
19532                         def = mergeSort(def, function(a, b) {
19533                             if (!a.value && b.value) return -1;
19534                             if (!b.value && a.value) return 1;
19535                             return 0;
19536                         });
19537                         var side_effects = [];
19538                         for (var i = 0; i < def.length; ) {
19539                             var x = def[i];
19540                             if (x._unused_side_effects) {
19541                                 side_effects.push(x.value);
19542                                 def.splice(i, 1);
19543                             } else {
19544                                 if (side_effects.length > 0) {
19545                                     side_effects.push(x.value);
19546                                     x.value = AST_Seq.from_array(side_effects);
19547                                     side_effects = [];
19548                                 }
19549                                 ++i;
19550                             }
19551                         }
19552                         if (side_effects.length > 0) {
19553                             side_effects = make_node(AST_BlockStatement, node, {
19554                                 body: [ make_node(AST_SimpleStatement, node, {
19555                                     body: AST_Seq.from_array(side_effects)
19556                                 }) ]
19557                             });
19558                         } else {
19559                             side_effects = null;
19560                         }
19561                         if (def.length == 0 && !side_effects) {
19562                             return make_node(AST_EmptyStatement, node);
19563                         }
19564                         if (def.length == 0) {
19565                             return side_effects;
19566                         }
19567                         node.definitions = def;
19568                         if (side_effects) {
19569                             side_effects.body.unshift(node);
19570                             node = side_effects;
19571                         }
19572                         return node;
19573                     }
19574                     if (node instanceof AST_For && node.init instanceof AST_BlockStatement) {
19575                         descend(node, this);
19576                         var body = node.init.body.slice(0, -1);
19577                         node.init = node.init.body.slice(-1)[0].body;
19578                         body.push(node);
19579                         return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
19580                             body: body
19581                         });
19582                     }
19583                     if (node instanceof AST_Scope && node !== self) return node;
19584                 });
19585                 self.transform(tt);
19586             }
19587         });
19588         AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) {
19589             var hoist_funs = compressor.option("hoist_funs");
19590             var hoist_vars = compressor.option("hoist_vars");
19591             var self = this;
19592             if (hoist_funs || hoist_vars) {
19593                 var dirs = [];
19594                 var hoisted = [];
19595                 var vars = new Dictionary(), vars_found = 0, var_decl = 0;
19596                 self.walk(new TreeWalker(function(node) {
19597                     if (node instanceof AST_Scope && node !== self) return true;
19598                     if (node instanceof AST_Var) {
19599                         ++var_decl;
19600                         return true;
19601                     }
19602                 }));
19603                 hoist_vars = hoist_vars && var_decl > 1;
19604                 var tt = new TreeTransformer(function before(node) {
19605                     if (node !== self) {
19606                         if (node instanceof AST_Directive) {
19607                             dirs.push(node);
19608                             return make_node(AST_EmptyStatement, node);
19609                         }
19610                         if (node instanceof AST_Defun && hoist_funs) {
19611                             hoisted.push(node);
19612                             return make_node(AST_EmptyStatement, node);
19613                         }
19614                         if (node instanceof AST_Var && hoist_vars) {
19615                             node.definitions.forEach(function(def) {
19616                                 vars.set(def.name.name, def);
19617                                 ++vars_found;
19618                             });
19619                             var seq = node.to_assignments();
19620                             var p = tt.parent();
19621                             if (p instanceof AST_ForIn && p.init === node) {
19622                                 if (seq == null) return node.definitions[0].name;
19623                                 return seq;
19624                             }
19625                             if (p instanceof AST_For && p.init === node) {
19626                                 return seq;
19627                             }
19628                             if (!seq) return make_node(AST_EmptyStatement, node);
19629                             return make_node(AST_SimpleStatement, node, {
19630                                 body: seq
19631                             });
19632                         }
19633                         if (node instanceof AST_Scope) return node;
19634                     }
19635                 });
19636                 self = self.transform(tt);
19637                 if (vars_found > 0) {
19638                     var defs = [];
19639                     vars.each(function(def, name) {
19640                         if (self instanceof AST_Lambda && find_if(function(x) {
19641                             return x.name == def.name.name;
19642                         }, self.argnames)) {
19643                             vars.del(name);
19644                         } else {
19645                             def = def.clone();
19646                             def.value = null;
19647                             defs.push(def);
19648                             vars.set(name, def);
19649                         }
19650                     });
19651                     if (defs.length > 0) {
19652                         for (var i = 0; i < self.body.length; ) {
19653                             if (self.body[i] instanceof AST_SimpleStatement) {
19654                                 var expr = self.body[i].body, sym, assign;
19655                                 if (expr instanceof AST_Assign && expr.operator == "=" && (sym = expr.left) instanceof AST_Symbol && vars.has(sym.name)) {
19656                                     var def = vars.get(sym.name);
19657                                     if (def.value) break;
19658                                     def.value = expr.right;
19659                                     remove(defs, def);
19660                                     defs.push(def);
19661                                     self.body.splice(i, 1);
19662                                     continue;
19663                                 }
19664                                 if (expr instanceof AST_Seq && (assign = expr.car) instanceof AST_Assign && assign.operator == "=" && (sym = assign.left) instanceof AST_Symbol && vars.has(sym.name)) {
19665                                     var def = vars.get(sym.name);
19666                                     if (def.value) break;
19667                                     def.value = assign.right;
19668                                     remove(defs, def);
19669                                     defs.push(def);
19670                                     self.body[i].body = expr.cdr;
19671                                     continue;
19672                                 }
19673                             }
19674                             if (self.body[i] instanceof AST_EmptyStatement) {
19675                                 self.body.splice(i, 1);
19676                                 continue;
19677                             }
19678                             if (self.body[i] instanceof AST_BlockStatement) {
19679                                 var tmp = [ i, 1 ].concat(self.body[i].body);
19680                                 self.body.splice.apply(self.body, tmp);
19681                                 continue;
19682                             }
19683                             break;
19684                         }
19685                         defs = make_node(AST_Var, self, {
19686                             definitions: defs
19687                         });
19688                         hoisted.push(defs);
19689                     }
19690                 }
19691                 self.body = dirs.concat(hoisted, self.body);
19692             }
19693             return self;
19694         });
19695         OPT(AST_SimpleStatement, function(self, compressor) {
19696             if (compressor.option("side_effects")) {
19697                 if (!self.body.has_side_effects()) {
19698                     compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
19699                     return make_node(AST_EmptyStatement, self);
19700                 }
19701             }
19702             return self;
19703         });
19704         OPT(AST_DWLoop, function(self, compressor) {
19705             var cond = self.condition.evaluate(compressor);
19706             self.condition = cond[0];
19707             if (!compressor.option("loops")) return self;
19708             if (cond.length > 1) {
19709                 if (cond[1]) {
19710                     return make_node(AST_For, self, {
19711                         body: self.body
19712                     });
19713                 } else if (self instanceof AST_While) {
19714                     if (compressor.option("dead_code")) {
19715                         var a = [];
19716                         extract_declarations_from_unreachable_code(compressor, self.body, a);
19717                         return make_node(AST_BlockStatement, self, {
19718                             body: a
19719                         });
19720                     }
19721                 }
19722             }
19723             return self;
19724         });
19725         function if_break_in_loop(self, compressor) {
19726             function drop_it(rest) {
19727                 rest = as_statement_array(rest);
19728                 if (self.body instanceof AST_BlockStatement) {
19729                     self.body = self.body.clone();
19730                     self.body.body = rest.concat(self.body.body.slice(1));
19731                     self.body = self.body.transform(compressor);
19732                 } else {
19733                     self.body = make_node(AST_BlockStatement, self.body, {
19734                         body: rest
19735                     }).transform(compressor);
19736                 }
19737                 if_break_in_loop(self, compressor);
19738             }
19739             var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
19740             if (first instanceof AST_If) {
19741                 if (first.body instanceof AST_Break && compressor.loopcontrol_target(first.body.label) === self) {
19742                     if (self.condition) {
19743                         self.condition = make_node(AST_Binary, self.condition, {
19744                             left: self.condition,
19745                             operator: "&&",
19746                             right: first.condition.negate(compressor)
19747                         });
19748                     } else {
19749                         self.condition = first.condition.negate(compressor);
19750                     }
19751                     drop_it(first.alternative);
19752                 } else if (first.alternative instanceof AST_Break && compressor.loopcontrol_target(first.alternative.label) === self) {
19753                     if (self.condition) {
19754                         self.condition = make_node(AST_Binary, self.condition, {
19755                             left: self.condition,
19756                             operator: "&&",
19757                             right: first.condition
19758                         });
19759                     } else {
19760                         self.condition = first.condition;
19761                     }
19762                     drop_it(first.body);
19763                 }
19764             }
19765         }
19766         OPT(AST_While, function(self, compressor) {
19767             if (!compressor.option("loops")) return self;
19768             self = AST_DWLoop.prototype.optimize.call(self, compressor);
19769             if (self instanceof AST_While) {
19770                 if_break_in_loop(self, compressor);
19771                 self = make_node(AST_For, self, self).transform(compressor);
19772             }
19773             return self;
19774         });
19775         OPT(AST_For, function(self, compressor) {
19776             var cond = self.condition;
19777             if (cond) {
19778                 cond = cond.evaluate(compressor);
19779                 self.condition = cond[0];
19780             }
19781             if (!compressor.option("loops")) return self;
19782             if (cond) {
19783                 if (cond.length > 1 && !cond[1]) {
19784                     if (compressor.option("dead_code")) {
19785                         var a = [];
19786                         if (self.init instanceof AST_Statement) {
19787                             a.push(self.init);
19788                         } else if (self.init) {
19789                             a.push(make_node(AST_SimpleStatement, self.init, {
19790                                 body: self.init
19791                             }));
19792                         }
19793                         extract_declarations_from_unreachable_code(compressor, self.body, a);
19794                         return make_node(AST_BlockStatement, self, {
19795                             body: a
19796                         });
19797                     }
19798                 }
19799             }
19800             if_break_in_loop(self, compressor);
19801             return self;
19802         });
19803         OPT(AST_If, function(self, compressor) {
19804             if (!compressor.option("conditionals")) return self;
19805             var cond = self.condition.evaluate(compressor);
19806             self.condition = cond[0];
19807             if (cond.length > 1) {
19808                 if (cond[1]) {
19809                     compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
19810                     if (compressor.option("dead_code")) {
19811                         var a = [];
19812                         if (self.alternative) {
19813                             extract_declarations_from_unreachable_code(compressor, self.alternative, a);
19814                         }
19815                         a.push(self.body);
19816                         return make_node(AST_BlockStatement, self, {
19817                             body: a
19818                         }).transform(compressor);
19819                     }
19820                 } else {
19821                     compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
19822                     if (compressor.option("dead_code")) {
19823                         var a = [];
19824                         extract_declarations_from_unreachable_code(compressor, self.body, a);
19825                         if (self.alternative) a.push(self.alternative);
19826                         return make_node(AST_BlockStatement, self, {
19827                             body: a
19828                         }).transform(compressor);
19829                     }
19830                 }
19831             }
19832             if (is_empty(self.alternative)) self.alternative = null;
19833             var negated = self.condition.negate(compressor);
19834             var negated_is_best = best_of(self.condition, negated) === negated;
19835             if (self.alternative && negated_is_best) {
19836                 negated_is_best = false;
19837                 self.condition = negated;
19838                 var tmp = self.body;
19839                 self.body = self.alternative || make_node(AST_EmptyStatement);
19840                 self.alternative = tmp;
19841             }
19842             if (is_empty(self.body) && is_empty(self.alternative)) {
19843                 return make_node(AST_SimpleStatement, self.condition, {
19844                     body: self.condition
19845                 }).transform(compressor);
19846             }
19847             if (self.body instanceof AST_SimpleStatement && self.alternative instanceof AST_SimpleStatement) {
19848                 return make_node(AST_SimpleStatement, self, {
19849                     body: make_node(AST_Conditional, self, {
19850                         condition: self.condition,
19851                         consequent: self.body.body,
19852                         alternative: self.alternative.body
19853                     })
19854                 }).transform(compressor);
19855             }
19856             if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
19857                 if (negated_is_best) return make_node(AST_SimpleStatement, self, {
19858                     body: make_node(AST_Binary, self, {
19859                         operator: "||",
19860                         left: negated,
19861                         right: self.body.body
19862                     })
19863                 }).transform(compressor);
19864                 return make_node(AST_SimpleStatement, self, {
19865                     body: make_node(AST_Binary, self, {
19866                         operator: "&&",
19867                         left: self.condition,
19868                         right: self.body.body
19869                     })
19870                 }).transform(compressor);
19871             }
19872             if (self.body instanceof AST_EmptyStatement && self.alternative && self.alternative instanceof AST_SimpleStatement) {
19873                 return make_node(AST_SimpleStatement, self, {
19874                     body: make_node(AST_Binary, self, {
19875                         operator: "||",
19876                         left: self.condition,
19877                         right: self.alternative.body
19878                     })
19879                 }).transform(compressor);
19880             }
19881             if (self.body instanceof AST_Exit && self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
19882                 return make_node(self.body.CTOR, self, {
19883                     value: make_node(AST_Conditional, self, {
19884                         condition: self.condition,
19885                         consequent: self.body.value || make_node(AST_Undefined, self.body).optimize(compressor),
19886                         alternative: self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor)
19887                     })
19888                 }).transform(compressor);
19889             }
19890             if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
19891                 self.condition = make_node(AST_Binary, self.condition, {
19892                     operator: "&&",
19893                     left: self.condition,
19894                     right: self.body.condition
19895                 }).transform(compressor);
19896                 self.body = self.body.body;
19897             }
19898             if (aborts(self.body)) {
19899                 if (self.alternative) {
19900                     var alt = self.alternative;
19901                     self.alternative = null;
19902                     return make_node(AST_BlockStatement, self, {
19903                         body: [ self, alt ]
19904                     }).transform(compressor);
19905                 }
19906             }
19907             if (aborts(self.alternative)) {
19908                 var body = self.body;
19909                 self.body = self.alternative;
19910                 self.condition = negated_is_best ? negated : self.condition.negate(compressor);
19911                 self.alternative = null;
19912                 return make_node(AST_BlockStatement, self, {
19913                     body: [ self, body ]
19914                 }).transform(compressor);
19915             }
19916             return self;
19917         });
19918         OPT(AST_Switch, function(self, compressor) {
19919             if (self.body.length == 0 && compressor.option("conditionals")) {
19920                 return make_node(AST_SimpleStatement, self, {
19921                     body: self.expression
19922                 }).transform(compressor);
19923             }
19924             for (;;) {
19925                 var last_branch = self.body[self.body.length - 1];
19926                 if (last_branch) {
19927                     var stat = last_branch.body[last_branch.body.length - 1];
19928                     if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) last_branch.body.pop();
19929                     if (last_branch instanceof AST_Default && last_branch.body.length == 0) {
19930                         self.body.pop();
19931                         continue;
19932                     }
19933                 }
19934                 break;
19935             }
19936             var exp = self.expression.evaluate(compressor);
19937             out: if (exp.length == 2) try {
19938                 self.expression = exp[0];
19939                 if (!compressor.option("dead_code")) break out;
19940                 var value = exp[1];
19941                 var in_if = false;
19942                 var in_block = false;
19943                 var started = false;
19944                 var stopped = false;
19945                 var ruined = false;
19946                 var tt = new TreeTransformer(function(node, descend, in_list) {
19947                     if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) {
19948                         return node;
19949                     } else if (node instanceof AST_Switch && node === self) {
19950                         node = node.clone();
19951                         descend(node, this);
19952                         return ruined ? node : make_node(AST_BlockStatement, node, {
19953                             body: node.body.reduce(function(a, branch) {
19954                                 return a.concat(branch.body);
19955                             }, [])
19956                         }).transform(compressor);
19957                     } else if (node instanceof AST_If || node instanceof AST_Try) {
19958                         var save = in_if;
19959                         in_if = !in_block;
19960                         descend(node, this);
19961                         in_if = save;
19962                         return node;
19963                     } else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) {
19964                         var save = in_block;
19965                         in_block = true;
19966                         descend(node, this);
19967                         in_block = save;
19968                         return node;
19969                     } else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) {
19970                         if (in_if) {
19971                             ruined = true;
19972                             return node;
19973                         }
19974                         if (in_block) return node;
19975                         stopped = true;
19976                         return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
19977                     } else if (node instanceof AST_SwitchBranch && this.parent() === self) {
19978                         if (stopped) return MAP.skip;
19979                         if (node instanceof AST_Case) {
19980                             var exp = node.expression.evaluate(compressor);
19981                             if (exp.length < 2) {
19982                                 throw self;
19983                             }
19984                             if (exp[1] === value || started) {
19985                                 started = true;
19986                                 if (aborts(node)) stopped = true;
19987                                 descend(node, this);
19988                                 return node;
19989                             }
19990                             return MAP.skip;
19991                         }
19992                         descend(node, this);
19993                         return node;
19994                     }
19995                 });
19996                 tt.stack = compressor.stack.slice();
19997                 self = self.transform(tt);
19998             } catch (ex) {
19999                 if (ex !== self) throw ex;
20000             }
20001             return self;
20002         });
20003         OPT(AST_Case, function(self, compressor) {
20004             self.body = tighten_body(self.body, compressor);
20005             return self;
20006         });
20007         OPT(AST_Try, function(self, compressor) {
20008             self.body = tighten_body(self.body, compressor);
20009             return self;
20010         });
20011         AST_Definitions.DEFMETHOD("remove_initializers", function() {
20012             this.definitions.forEach(function(def) {
20013                 def.value = null;
20014             });
20015         });
20016         AST_Definitions.DEFMETHOD("to_assignments", function() {
20017             var assignments = this.definitions.reduce(function(a, def) {
20018                 if (def.value) {
20019                     var name = make_node(AST_SymbolRef, def.name, def.name);
20020                     a.push(make_node(AST_Assign, def, {
20021                         operator: "=",
20022                         left: name,
20023                         right: def.value
20024                     }));
20025                 }
20026                 return a;
20027             }, []);
20028             if (assignments.length == 0) return null;
20029             return AST_Seq.from_array(assignments);
20030         });
20031         OPT(AST_Definitions, function(self, compressor) {
20032             if (self.definitions.length == 0) return make_node(AST_EmptyStatement, self);
20033             return self;
20034         });
20035         OPT(AST_Function, function(self, compressor) {
20036             self = AST_Lambda.prototype.optimize.call(self, compressor);
20037             if (compressor.option("unused")) {
20038                 if (self.name && self.name.unreferenced()) {
20039                     self.name = null;
20040                 }
20041             }
20042             return self;
20043         });
20044         OPT(AST_Call, function(self, compressor) {
20045             if (compressor.option("unsafe")) {
20046                 var exp = self.expression;
20047                 if (exp instanceof AST_SymbolRef && exp.undeclared()) {
20048                     switch (exp.name) {
20049                       case "Array":
20050                         if (self.args.length != 1) {
20051                             return make_node(AST_Array, self, {
20052                                 elements: self.args
20053                             });
20054                         }
20055                         break;
20057                       case "Object":
20058                         if (self.args.length == 0) {
20059                             return make_node(AST_Object, self, {
20060                                 properties: []
20061                             });
20062                         }
20063                         break;
20065                       case "String":
20066                         if (self.args.length == 0) return make_node(AST_String, self, {
20067                             value: ""
20068                         });
20069                         return make_node(AST_Binary, self, {
20070                             left: self.args[0],
20071                             operator: "+",
20072                             right: make_node(AST_String, self, {
20073                                 value: ""
20074                             })
20075                         });
20077                       case "Function":
20078                         if (all(self.args, function(x) {
20079                             return x instanceof AST_String;
20080                         })) {
20081                             try {
20082                                 var code = "(function(" + self.args.slice(0, -1).map(function(arg) {
20083                                     return arg.value;
20084                                 }).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
20085                                 var ast = parse(code);
20086                                 ast.figure_out_scope();
20087                                 var comp = new Compressor(compressor.options);
20088                                 ast = ast.transform(comp);
20089                                 ast.figure_out_scope();
20090                                 ast.mangle_names();
20091                                 var fun = ast.body[0].body.expression;
20092                                 var args = fun.argnames.map(function(arg, i) {
20093                                     return make_node(AST_String, self.args[i], {
20094                                         value: arg.print_to_string()
20095                                     });
20096                                 });
20097                                 var code = OutputStream();
20098                                 AST_BlockStatement.prototype._codegen.call(fun, fun, code);
20099                                 code = code.toString().replace(/^\{|\}$/g, "");
20100                                 args.push(make_node(AST_String, self.args[self.args.length - 1], {
20101                                     value: code
20102                                 }));
20103                                 self.args = args;
20104                                 return self;
20105                             } catch (ex) {
20106                                 if (ex instanceof JS_Parse_Error) {
20107                                     compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
20108                                     compressor.warn(ex.toString());
20109                                 } else {
20110                                     console.log(ex);
20111                                 }
20112                             }
20113                         }
20114                         break;
20115                     }
20116                 } else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
20117                     return make_node(AST_Binary, self, {
20118                         left: make_node(AST_String, self, {
20119                             value: ""
20120                         }),
20121                         operator: "+",
20122                         right: exp.expression
20123                     }).transform(compressor);
20124                 }
20125             }
20126             if (compressor.option("side_effects")) {
20127                 if (self.expression instanceof AST_Function && self.args.length == 0 && !AST_Block.prototype.has_side_effects.call(self.expression)) {
20128                     return make_node(AST_Undefined, self).transform(compressor);
20129                 }
20130             }
20131             return self;
20132         });
20133         OPT(AST_New, function(self, compressor) {
20134             if (compressor.option("unsafe")) {
20135                 var exp = self.expression;
20136                 if (exp instanceof AST_SymbolRef && exp.undeclared()) {
20137                     switch (exp.name) {
20138                       case "Object":
20139                       case "RegExp":
20140                       case "Function":
20141                       case "Error":
20142                       case "Array":
20143                         return make_node(AST_Call, self, self).transform(compressor);
20144                     }
20145                 }
20146             }
20147             return self;
20148         });
20149         OPT(AST_Seq, function(self, compressor) {
20150             if (!compressor.option("side_effects")) return self;
20151             if (!self.car.has_side_effects()) {
20152                 var p;
20153                 if (!(self.cdr instanceof AST_SymbolRef && self.cdr.name == "eval" && self.cdr.undeclared() && (p = compressor.parent()) instanceof AST_Call && p.expression === self)) {
20154                     return self.cdr;
20155                 }
20156             }
20157             if (compressor.option("cascade")) {
20158                 if (self.car instanceof AST_Assign && !self.car.left.has_side_effects() && self.car.left.equivalent_to(self.cdr)) {
20159                     return self.car;
20160                 }
20161                 if (!self.car.has_side_effects() && !self.cdr.has_side_effects() && self.car.equivalent_to(self.cdr)) {
20162                     return self.car;
20163                 }
20164             }
20165             return self;
20166         });
20167         AST_Unary.DEFMETHOD("lift_sequences", function(compressor) {
20168             if (compressor.option("sequences")) {
20169                 if (this.expression instanceof AST_Seq) {
20170                     var seq = this.expression;
20171                     var x = seq.to_array();
20172                     this.expression = x.pop();
20173                     x.push(this);
20174                     seq = AST_Seq.from_array(x).transform(compressor);
20175                     return seq;
20176                 }
20177             }
20178             return this;
20179         });
20180         OPT(AST_UnaryPostfix, function(self, compressor) {
20181             return self.lift_sequences(compressor);
20182         });
20183         OPT(AST_UnaryPrefix, function(self, compressor) {
20184             self = self.lift_sequences(compressor);
20185             var e = self.expression;
20186             if (compressor.option("booleans") && compressor.in_boolean_context()) {
20187                 switch (self.operator) {
20188                   case "!":
20189                     if (e instanceof AST_UnaryPrefix && e.operator == "!") {
20190                         return e.expression;
20191                     }
20192                     break;
20194                   case "typeof":
20195                     compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
20196                     return make_node(AST_True, self);
20197                 }
20198                 if (e instanceof AST_Binary && self.operator == "!") {
20199                     self = best_of(self, e.negate(compressor));
20200                 }
20201             }
20202             return self.evaluate(compressor)[0];
20203         });
20204         AST_Binary.DEFMETHOD("lift_sequences", function(compressor) {
20205             if (compressor.option("sequences")) {
20206                 if (this.left instanceof AST_Seq) {
20207                     var seq = this.left;
20208                     var x = seq.to_array();
20209                     this.left = x.pop();
20210                     x.push(this);
20211                     seq = AST_Seq.from_array(x).transform(compressor);
20212                     return seq;
20213                 }
20214                 if (this.right instanceof AST_Seq && !(this.operator == "||" || this.operator == "&&") && !this.left.has_side_effects()) {
20215                     var seq = this.right;
20216                     var x = seq.to_array();
20217                     this.right = x.pop();
20218                     x.push(this);
20219                     seq = AST_Seq.from_array(x).transform(compressor);
20220                     return seq;
20221                 }
20222             }
20223             return this;
20224         });
20225         var commutativeOperators = makePredicate("== === != !== * & | ^");
20226         OPT(AST_Binary, function(self, compressor) {
20227             function reverse(op, force) {
20228                 if (force || !(self.left.has_side_effects() || self.right.has_side_effects())) {
20229                     if (op) self.operator = op;
20230                     var tmp = self.left;
20231                     self.left = self.right;
20232                     self.right = tmp;
20233                 }
20234             }
20235             if (commutativeOperators(self.operator)) {
20236                 if (self.right instanceof AST_Constant && !(self.left instanceof AST_Constant)) {
20237                     reverse(null, true);
20238                 }
20239             }
20240             self = self.lift_sequences(compressor);
20241             if (compressor.option("comparisons")) switch (self.operator) {
20242               case "===":
20243               case "!==":
20244                 if (self.left.is_string(compressor) && self.right.is_string(compressor) || self.left.is_boolean() && self.right.is_boolean()) {
20245                     self.operator = self.operator.substr(0, 2);
20246                 }
20248               case "==":
20249               case "!=":
20250                 if (self.left instanceof AST_String && self.left.value == "undefined" && self.right instanceof AST_UnaryPrefix && self.right.operator == "typeof" && compressor.option("unsafe")) {
20251                     if (!(self.right.expression instanceof AST_SymbolRef) || !self.right.expression.undeclared()) {
20252                         self.right = self.right.expression;
20253                         self.left = make_node(AST_Undefined, self.left).optimize(compressor);
20254                         if (self.operator.length == 2) self.operator += "=";
20255                     }
20256                 }
20257                 break;
20258             }
20259             if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
20260               case "&&":
20261                 var ll = self.left.evaluate(compressor);
20262                 var rr = self.right.evaluate(compressor);
20263                 if (ll.length > 1 && !ll[1] || rr.length > 1 && !rr[1]) {
20264                     compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
20265                     return make_node(AST_False, self);
20266                 }
20267                 if (ll.length > 1 && ll[1]) {
20268                     return rr[0];
20269                 }
20270                 if (rr.length > 1 && rr[1]) {
20271                     return ll[0];
20272                 }
20273                 break;
20275               case "||":
20276                 var ll = self.left.evaluate(compressor);
20277                 var rr = self.right.evaluate(compressor);
20278                 if (ll.length > 1 && ll[1] || rr.length > 1 && rr[1]) {
20279                     compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
20280                     return make_node(AST_True, self);
20281                 }
20282                 if (ll.length > 1 && !ll[1]) {
20283                     return rr[0];
20284                 }
20285                 if (rr.length > 1 && !rr[1]) {
20286                     return ll[0];
20287                 }
20288                 break;
20290               case "+":
20291                 var ll = self.left.evaluate(compressor);
20292                 var rr = self.right.evaluate(compressor);
20293                 if (ll.length > 1 && ll[0] instanceof AST_String && ll[1] || rr.length > 1 && rr[0] instanceof AST_String && rr[1]) {
20294                     compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
20295                     return make_node(AST_True, self);
20296                 }
20297                 break;
20298             }
20299             var exp = self.evaluate(compressor);
20300             if (exp.length > 1) {
20301                 if (best_of(exp[0], self) !== self) return exp[0];
20302             }
20303             if (compressor.option("comparisons")) {
20304                 if (!(compressor.parent() instanceof AST_Binary) || compressor.parent() instanceof AST_Assign) {
20305                     var negated = make_node(AST_UnaryPrefix, self, {
20306                         operator: "!",
20307                         expression: self.negate(compressor)
20308                     });
20309                     self = best_of(self, negated);
20310                 }
20311                 switch (self.operator) {
20312                   case "<":
20313                     reverse(">");
20314                     break;
20316                   case "<=":
20317                     reverse(">=");
20318                     break;
20319                 }
20320             }
20321             if (self.operator == "+" && self.right instanceof AST_String && self.right.getValue() === "" && self.left instanceof AST_Binary && self.left.operator == "+" && self.left.is_string(compressor)) {
20322                 return self.left;
20323             }
20324             return self;
20325         });
20326         OPT(AST_SymbolRef, function(self, compressor) {
20327             if (self.undeclared()) {
20328                 var defines = compressor.option("global_defs");
20329                 if (defines && defines.hasOwnProperty(self.name)) {
20330                     return make_node_from_constant(compressor, defines[self.name], self);
20331                 }
20332                 switch (self.name) {
20333                   case "undefined":
20334                     return make_node(AST_Undefined, self);
20336                   case "NaN":
20337                     return make_node(AST_NaN, self);
20339                   case "Infinity":
20340                     return make_node(AST_Infinity, self);
20341                 }
20342             }
20343             return self;
20344         });
20345         OPT(AST_Undefined, function(self, compressor) {
20346             if (compressor.option("unsafe")) {
20347                 var scope = compressor.find_parent(AST_Scope);
20348                 var undef = scope.find_variable("undefined");
20349                 if (undef) {
20350                     var ref = make_node(AST_SymbolRef, self, {
20351                         name: "undefined",
20352                         scope: scope,
20353                         thedef: undef
20354                     });
20355                     ref.reference();
20356                     return ref;
20357                 }
20358             }
20359             return self;
20360         });
20361         var ASSIGN_OPS = [ "+", "-", "/", "*", "%", ">>", "<<", ">>>", "|", "^", "&" ];
20362         OPT(AST_Assign, function(self, compressor) {
20363             self = self.lift_sequences(compressor);
20364             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)) {
20365                 self.operator = self.right.operator + "=";
20366                 self.right = self.right.right;
20367             }
20368             return self;
20369         });
20370         OPT(AST_Conditional, function(self, compressor) {
20371             if (!compressor.option("conditionals")) return self;
20372             if (self.condition instanceof AST_Seq) {
20373                 var car = self.condition.car;
20374                 self.condition = self.condition.cdr;
20375                 return AST_Seq.cons(car, self);
20376             }
20377             var cond = self.condition.evaluate(compressor);
20378             if (cond.length > 1) {
20379                 if (cond[1]) {
20380                     compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
20381                     return self.consequent;
20382                 } else {
20383                     compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
20384                     return self.alternative;
20385                 }
20386             }
20387             var negated = cond[0].negate(compressor);
20388             if (best_of(cond[0], negated) === negated) {
20389                 self = make_node(AST_Conditional, self, {
20390                     condition: negated,
20391                     consequent: self.alternative,
20392                     alternative: self.consequent
20393                 });
20394             }
20395             var consequent = self.consequent;
20396             var alternative = self.alternative;
20397             if (consequent instanceof AST_Assign && alternative instanceof AST_Assign && consequent.operator == alternative.operator && consequent.left.equivalent_to(alternative.left)) {
20398                 self = make_node(AST_Assign, self, {
20399                     operator: consequent.operator,
20400                     left: consequent.left,
20401                     right: make_node(AST_Conditional, self, {
20402                         condition: self.condition,
20403                         consequent: consequent.right,
20404                         alternative: alternative.right
20405                     })
20406                 });
20407             }
20408             return self;
20409         });
20410         OPT(AST_Boolean, function(self, compressor) {
20411             if (compressor.option("booleans")) {
20412                 var p = compressor.parent();
20413                 if (p instanceof AST_Binary && (p.operator == "==" || p.operator == "!=")) {
20414                     compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
20415                         operator: p.operator,
20416                         value: self.value,
20417                         file: p.start.file,
20418                         line: p.start.line,
20419                         col: p.start.col
20420                     });
20421                     return make_node(AST_Number, self, {
20422                         value: +self.value
20423                     });
20424                 }
20425                 return make_node(AST_UnaryPrefix, self, {
20426                     operator: "!",
20427                     expression: make_node(AST_Number, self, {
20428                         value: 1 - self.value
20429                     })
20430                 });
20431             }
20432             return self;
20433         });
20434         OPT(AST_Sub, function(self, compressor) {
20435             var prop = self.property;
20436             if (prop instanceof AST_String && compressor.option("properties")) {
20437                 prop = prop.getValue();
20438                 if (compressor.option("screw_ie8") && RESERVED_WORDS(prop) || !RESERVED_WORDS(prop) && is_identifier_string(prop)) {
20439                     return make_node(AST_Dot, self, {
20440                         expression: self.expression,
20441                         property: prop
20442                     });
20443                 }
20444             }
20445             return self;
20446         });
20447         function literals_in_boolean_context(self, compressor) {
20448             if (compressor.option("booleans") && compressor.in_boolean_context()) {
20449                 return make_node(AST_True, self);
20450             }
20451             return self;
20452         }
20453         OPT(AST_Array, literals_in_boolean_context);
20454         OPT(AST_Object, literals_in_boolean_context);
20455         OPT(AST_RegExp, literals_in_boolean_context);
20456     })();
20457     "use strict";
20458     function SourceMap(options) {
20459         options = defaults(options, {
20460             file: null,
20461             root: null,
20462             orig: null
20463         });
20464         var generator = new MOZ_SourceMap.SourceMapGenerator({
20465             file: options.file,
20466             sourceRoot: options.root
20467         });
20468         var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
20469         function add(source, gen_line, gen_col, orig_line, orig_col, name) {
20470             if (orig_map) {
20471                 var info = orig_map.originalPositionFor({
20472                     line: orig_line,
20473                     column: orig_col
20474                 });
20475                 source = info.source;
20476                 orig_line = info.line;
20477                 orig_col = info.column;
20478                 name = info.name;
20479             }
20480             generator.addMapping({
20481                 generated: {
20482                     line: gen_line,
20483                     column: gen_col
20484                 },
20485                 original: {
20486                     line: orig_line,
20487                     column: orig_col
20488                 },
20489                 source: source,
20490                 name: name
20491             });
20492         }
20493         return {
20494             add: add,
20495             get: function() {
20496                 return generator;
20497             },
20498             toString: function() {
20499                 return generator.toString();
20500             }
20501         };
20502     }
20503     "use strict";
20504     (function() {
20505         var MOZ_TO_ME = {
20506             TryStatement: function(M) {
20507                 return new AST_Try({
20508                     start: my_start_token(M),
20509                     end: my_end_token(M),
20510                     body: from_moz(M.block).body,
20511                     bcatch: from_moz(M.handlers[0]),
20512                     bfinally: M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
20513                 });
20514             },
20515             CatchClause: function(M) {
20516                 return new AST_Catch({
20517                     start: my_start_token(M),
20518                     end: my_end_token(M),
20519                     argname: from_moz(M.param),
20520                     body: from_moz(M.body).body
20521                 });
20522             },
20523             ObjectExpression: function(M) {
20524                 return new AST_Object({
20525                     start: my_start_token(M),
20526                     end: my_end_token(M),
20527                     properties: M.properties.map(function(prop) {
20528                         var key = prop.key;
20529                         var name = key.type == "Identifier" ? key.name : key.value;
20530                         var args = {
20531                             start: my_start_token(key),
20532                             end: my_end_token(prop.value),
20533                             key: name,
20534                             value: from_moz(prop.value)
20535                         };
20536                         switch (prop.kind) {
20537                           case "init":
20538                             return new AST_ObjectKeyVal(args);
20540                           case "set":
20541                             args.value.name = from_moz(key);
20542                             return new AST_ObjectSetter(args);
20544                           case "get":
20545                             args.value.name = from_moz(key);
20546                             return new AST_ObjectGetter(args);
20547                         }
20548                     })
20549                 });
20550             },
20551             SequenceExpression: function(M) {
20552                 return AST_Seq.from_array(M.expressions.map(from_moz));
20553             },
20554             MemberExpression: function(M) {
20555                 return new (M.computed ? AST_Sub : AST_Dot)({
20556                     start: my_start_token(M),
20557                     end: my_end_token(M),
20558                     property: M.computed ? from_moz(M.property) : M.property.name,
20559                     expression: from_moz(M.object)
20560                 });
20561             },
20562             SwitchCase: function(M) {
20563                 return new (M.test ? AST_Case : AST_Default)({
20564                     start: my_start_token(M),
20565                     end: my_end_token(M),
20566                     expression: from_moz(M.test),
20567                     body: M.consequent.map(from_moz)
20568                 });
20569             },
20570             Literal: function(M) {
20571                 var val = M.value, args = {
20572                     start: my_start_token(M),
20573                     end: my_end_token(M)
20574                 };
20575                 if (val === null) return new AST_Null(args);
20576                 switch (typeof val) {
20577                   case "string":
20578                     args.value = val;
20579                     return new AST_String(args);
20581                   case "number":
20582                     args.value = val;
20583                     return new AST_Number(args);
20585                   case "boolean":
20586                     return new (val ? AST_True : AST_False)(args);
20588                   default:
20589                     args.value = val;
20590                     return new AST_RegExp(args);
20591                 }
20592             },
20593             UnaryExpression: From_Moz_Unary,
20594             UpdateExpression: From_Moz_Unary,
20595             Identifier: function(M) {
20596                 var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
20597                 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)({
20598                     start: my_start_token(M),
20599                     end: my_end_token(M),
20600                     name: M.name
20601                 });
20602             }
20603         };
20604         function From_Moz_Unary(M) {
20605             var prefix = "prefix" in M ? M.prefix : M.type == "UnaryExpression" ? true : false;
20606             return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
20607                 start: my_start_token(M),
20608                 end: my_end_token(M),
20609                 operator: M.operator,
20610                 expression: from_moz(M.argument)
20611             });
20612         }
20613         var ME_TO_MOZ = {};
20614         map("Node", AST_Node);
20615         map("Program", AST_Toplevel, "body@body");
20616         map("Function", AST_Function, "id>name, params@argnames, body%body");
20617         map("EmptyStatement", AST_EmptyStatement);
20618         map("BlockStatement", AST_BlockStatement, "body@body");
20619         map("ExpressionStatement", AST_SimpleStatement, "expression>body");
20620         map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
20621         map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
20622         map("BreakStatement", AST_Break, "label>label");
20623         map("ContinueStatement", AST_Continue, "label>label");
20624         map("WithStatement", AST_With, "object>expression, body>body");
20625         map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
20626         map("ReturnStatement", AST_Return, "argument>value");
20627         map("ThrowStatement", AST_Throw, "argument>value");
20628         map("WhileStatement", AST_While, "test>condition, body>body");
20629         map("DoWhileStatement", AST_Do, "test>condition, body>body");
20630         map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
20631         map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
20632         map("DebuggerStatement", AST_Debugger);
20633         map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
20634         map("VariableDeclaration", AST_Var, "declarations@definitions");
20635         map("VariableDeclarator", AST_VarDef, "id>name, init>value");
20636         map("ThisExpression", AST_This);
20637         map("ArrayExpression", AST_Array, "elements@elements");
20638         map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
20639         map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
20640         map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
20641         map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
20642         map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
20643         map("NewExpression", AST_New, "callee>expression, arguments@args");
20644         map("CallExpression", AST_Call, "callee>expression, arguments@args");
20645         function my_start_token(moznode) {
20646             return new AST_Token({
20647                 file: moznode.loc && moznode.loc.source,
20648                 line: moznode.loc && moznode.loc.start.line,
20649                 col: moznode.loc && moznode.loc.start.column,
20650                 pos: moznode.start,
20651                 endpos: moznode.start
20652             });
20653         }
20654         function my_end_token(moznode) {
20655             return new AST_Token({
20656                 file: moznode.loc && moznode.loc.source,
20657                 line: moznode.loc && moznode.loc.end.line,
20658                 col: moznode.loc && moznode.loc.end.column,
20659                 pos: moznode.end,
20660                 endpos: moznode.end
20661             });
20662         }
20663         function map(moztype, mytype, propmap) {
20664             var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
20665             moz_to_me += "return new mytype({\n" + "start: my_start_token(M),\n" + "end: my_end_token(M)";
20666             if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
20667                 var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
20668                 if (!m) throw new Error("Can't understand property map: " + prop);
20669                 var moz = "M." + m[1], how = m[2], my = m[3];
20670                 moz_to_me += ",\n" + my + ": ";
20671                 if (how == "@") {
20672                     moz_to_me += moz + ".map(from_moz)";
20673                 } else if (how == ">") {
20674                     moz_to_me += "from_moz(" + moz + ")";
20675                 } else if (how == "=") {
20676                     moz_to_me += moz;
20677                 } else if (how == "%") {
20678                     moz_to_me += "from_moz(" + moz + ").body";
20679                 } else throw new Error("Can't understand operator in propmap: " + prop);
20680             });
20681             moz_to_me += "\n})}";
20682             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);
20683             return MOZ_TO_ME[moztype] = moz_to_me;
20684         }
20685         var FROM_MOZ_STACK = null;
20686         function from_moz(node) {
20687             FROM_MOZ_STACK.push(node);
20688             var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
20689             FROM_MOZ_STACK.pop();
20690             return ret;
20691         }
20692         AST_Node.from_mozilla_ast = function(node) {
20693             var save_stack = FROM_MOZ_STACK;
20694             FROM_MOZ_STACK = [];
20695             var ast = from_moz(node);
20696             FROM_MOZ_STACK = save_stack;
20697             return ast;
20698         };
20699     })();
20700     exports["array_to_hash"] = array_to_hash;
20701     exports["slice"] = slice;
20702     exports["characters"] = characters;
20703     exports["member"] = member;
20704     exports["find_if"] = find_if;
20705     exports["repeat_string"] = repeat_string;
20706     exports["DefaultsError"] = DefaultsError;
20707     exports["defaults"] = defaults;
20708     exports["merge"] = merge;
20709     exports["noop"] = noop;
20710     exports["MAP"] = MAP;
20711     exports["push_uniq"] = push_uniq;
20712     exports["string_template"] = string_template;
20713     exports["remove"] = remove;
20714     exports["mergeSort"] = mergeSort;
20715     exports["set_difference"] = set_difference;
20716     exports["set_intersection"] = set_intersection;
20717     exports["makePredicate"] = makePredicate;
20718     exports["all"] = all;
20719     exports["Dictionary"] = Dictionary;
20720     exports["DEFNODE"] = DEFNODE;
20721     exports["AST_Token"] = AST_Token;
20722     exports["AST_Node"] = AST_Node;
20723     exports["AST_Statement"] = AST_Statement;
20724     exports["AST_Debugger"] = AST_Debugger;
20725     exports["AST_Directive"] = AST_Directive;
20726     exports["AST_SimpleStatement"] = AST_SimpleStatement;
20727     exports["walk_body"] = walk_body;
20728     exports["AST_Block"] = AST_Block;
20729     exports["AST_BlockStatement"] = AST_BlockStatement;
20730     exports["AST_EmptyStatement"] = AST_EmptyStatement;
20731     exports["AST_StatementWithBody"] = AST_StatementWithBody;
20732     exports["AST_LabeledStatement"] = AST_LabeledStatement;
20733     exports["AST_DWLoop"] = AST_DWLoop;
20734     exports["AST_Do"] = AST_Do;
20735     exports["AST_While"] = AST_While;
20736     exports["AST_For"] = AST_For;
20737     exports["AST_ForIn"] = AST_ForIn;
20738     exports["AST_With"] = AST_With;
20739     exports["AST_Scope"] = AST_Scope;
20740     exports["AST_Toplevel"] = AST_Toplevel;
20741     exports["AST_Lambda"] = AST_Lambda;
20742     exports["AST_Accessor"] = AST_Accessor;
20743     exports["AST_Function"] = AST_Function;
20744     exports["AST_Defun"] = AST_Defun;
20745     exports["AST_Jump"] = AST_Jump;
20746     exports["AST_Exit"] = AST_Exit;
20747     exports["AST_Return"] = AST_Return;
20748     exports["AST_Throw"] = AST_Throw;
20749     exports["AST_LoopControl"] = AST_LoopControl;
20750     exports["AST_Break"] = AST_Break;
20751     exports["AST_Continue"] = AST_Continue;
20752     exports["AST_If"] = AST_If;
20753     exports["AST_Switch"] = AST_Switch;
20754     exports["AST_SwitchBranch"] = AST_SwitchBranch;
20755     exports["AST_Default"] = AST_Default;
20756     exports["AST_Case"] = AST_Case;
20757     exports["AST_Try"] = AST_Try;
20758     exports["AST_Catch"] = AST_Catch;
20759     exports["AST_Finally"] = AST_Finally;
20760     exports["AST_Definitions"] = AST_Definitions;
20761     exports["AST_Var"] = AST_Var;
20762     exports["AST_Const"] = AST_Const;
20763     exports["AST_VarDef"] = AST_VarDef;
20764     exports["AST_Call"] = AST_Call;
20765     exports["AST_New"] = AST_New;
20766     exports["AST_Seq"] = AST_Seq;
20767     exports["AST_PropAccess"] = AST_PropAccess;
20768     exports["AST_Dot"] = AST_Dot;
20769     exports["AST_Sub"] = AST_Sub;
20770     exports["AST_Unary"] = AST_Unary;
20771     exports["AST_UnaryPrefix"] = AST_UnaryPrefix;
20772     exports["AST_UnaryPostfix"] = AST_UnaryPostfix;
20773     exports["AST_Binary"] = AST_Binary;
20774     exports["AST_Conditional"] = AST_Conditional;
20775     exports["AST_Assign"] = AST_Assign;
20776     exports["AST_Array"] = AST_Array;
20777     exports["AST_Object"] = AST_Object;
20778     exports["AST_ObjectProperty"] = AST_ObjectProperty;
20779     exports["AST_ObjectKeyVal"] = AST_ObjectKeyVal;
20780     exports["AST_ObjectSetter"] = AST_ObjectSetter;
20781     exports["AST_ObjectGetter"] = AST_ObjectGetter;
20782     exports["AST_Symbol"] = AST_Symbol;
20783     exports["AST_SymbolAccessor"] = AST_SymbolAccessor;
20784     exports["AST_SymbolDeclaration"] = AST_SymbolDeclaration;
20785     exports["AST_SymbolVar"] = AST_SymbolVar;
20786     exports["AST_SymbolConst"] = AST_SymbolConst;
20787     exports["AST_SymbolFunarg"] = AST_SymbolFunarg;
20788     exports["AST_SymbolDefun"] = AST_SymbolDefun;
20789     exports["AST_SymbolLambda"] = AST_SymbolLambda;
20790     exports["AST_SymbolCatch"] = AST_SymbolCatch;
20791     exports["AST_Label"] = AST_Label;
20792     exports["AST_SymbolRef"] = AST_SymbolRef;
20793     exports["AST_LabelRef"] = AST_LabelRef;
20794     exports["AST_This"] = AST_This;
20795     exports["AST_Constant"] = AST_Constant;
20796     exports["AST_String"] = AST_String;
20797     exports["AST_Number"] = AST_Number;
20798     exports["AST_RegExp"] = AST_RegExp;
20799     exports["AST_Atom"] = AST_Atom;
20800     exports["AST_Null"] = AST_Null;
20801     exports["AST_NaN"] = AST_NaN;
20802     exports["AST_Undefined"] = AST_Undefined;
20803     exports["AST_Hole"] = AST_Hole;
20804     exports["AST_Infinity"] = AST_Infinity;
20805     exports["AST_Boolean"] = AST_Boolean;
20806     exports["AST_False"] = AST_False;
20807     exports["AST_True"] = AST_True;
20808     exports["TreeWalker"] = TreeWalker;
20809     exports["KEYWORDS"] = KEYWORDS;
20810     exports["KEYWORDS_ATOM"] = KEYWORDS_ATOM;
20811     exports["RESERVED_WORDS"] = RESERVED_WORDS;
20812     exports["KEYWORDS_BEFORE_EXPRESSION"] = KEYWORDS_BEFORE_EXPRESSION;
20813     exports["OPERATOR_CHARS"] = OPERATOR_CHARS;
20814     exports["RE_HEX_NUMBER"] = RE_HEX_NUMBER;
20815     exports["RE_OCT_NUMBER"] = RE_OCT_NUMBER;
20816     exports["RE_DEC_NUMBER"] = RE_DEC_NUMBER;
20817     exports["OPERATORS"] = OPERATORS;
20818     exports["WHITESPACE_CHARS"] = WHITESPACE_CHARS;
20819     exports["PUNC_BEFORE_EXPRESSION"] = PUNC_BEFORE_EXPRESSION;
20820     exports["PUNC_CHARS"] = PUNC_CHARS;
20821     exports["REGEXP_MODIFIERS"] = REGEXP_MODIFIERS;
20822     exports["UNICODE"] = UNICODE;
20823     exports["is_letter"] = is_letter;
20824     exports["is_digit"] = is_digit;
20825     exports["is_alphanumeric_char"] = is_alphanumeric_char;
20826     exports["is_unicode_combining_mark"] = is_unicode_combining_mark;
20827     exports["is_unicode_connector_punctuation"] = is_unicode_connector_punctuation;
20828     exports["is_identifier"] = is_identifier;
20829     exports["is_identifier_start"] = is_identifier_start;
20830     exports["is_identifier_char"] = is_identifier_char;
20831     exports["is_identifier_string"] = is_identifier_string;
20832     exports["parse_js_number"] = parse_js_number;
20833     exports["JS_Parse_Error"] = JS_Parse_Error;
20834     exports["js_error"] = js_error;
20835     exports["is_token"] = is_token;
20836     exports["EX_EOF"] = EX_EOF;
20837     exports["tokenizer"] = tokenizer;
20838     exports["UNARY_PREFIX"] = UNARY_PREFIX;
20839     exports["UNARY_POSTFIX"] = UNARY_POSTFIX;
20840     exports["ASSIGNMENT"] = ASSIGNMENT;
20841     exports["PRECEDENCE"] = PRECEDENCE;
20842     exports["STATEMENTS_WITH_LABELS"] = STATEMENTS_WITH_LABELS;
20843     exports["ATOMIC_START_TOKEN"] = ATOMIC_START_TOKEN;
20844     exports["parse"] = parse;
20845     exports["TreeTransformer"] = TreeTransformer;
20846     exports["SymbolDef"] = SymbolDef;
20847     exports["base54"] = base54;
20848     exports["OutputStream"] = OutputStream;
20849     exports["Compressor"] = Compressor;
20850     exports["SourceMap"] = SourceMap;
20851 })({}, function() {
20852     return exports;
20853 }());
20855 var UglifyJS = exports.UglifyJS;
20857 UglifyJS.AST_Node.warn_function = function(txt) {
20858     logger.error("uglifyjs2 WARN: " + txt);
20861 //JRB: MODIFIED FROM UGLIFY SOURCE
20862 //to take a name for the file, and then set toplevel.filename to be that name.
20863 exports.minify = function(files, options, name) {
20864     options = UglifyJS.defaults(options, {
20865         outSourceMap : null,
20866         sourceRoot   : null,
20867         inSourceMap  : null,
20868         fromString   : false,
20869         warnings     : false,
20870         mangle       : {},
20871         output       : null,
20872         compress     : {}
20873     });
20874     if (typeof files == "string")
20875         files = [ files ];
20877     // 1. parse
20878     var toplevel = null;
20879     files.forEach(function(file){
20880         var code = options.fromString
20881             ? file
20882             : rjsFile.readFile(file, "utf8");
20883         toplevel = UglifyJS.parse(code, {
20884             filename: options.fromString ? name : file,
20885             toplevel: toplevel
20886         });
20887     });
20889     // 2. compress
20890     if (options.compress) {
20891         var compress = { warnings: options.warnings };
20892         UglifyJS.merge(compress, options.compress);
20893         toplevel.figure_out_scope();
20894         var sq = UglifyJS.Compressor(compress);
20895         toplevel = toplevel.transform(sq);
20896     }
20898     // 3. mangle
20899     if (options.mangle) {
20900         toplevel.figure_out_scope();
20901         toplevel.compute_char_frequency();
20902         toplevel.mangle_names(options.mangle);
20903     }
20905     // 4. output
20906     var map = null;
20907     var inMap = null;
20908     if (options.inSourceMap) {
20909         inMap = rjsFile.readFile(options.inSourceMap, "utf8");
20910     }
20911     if (options.outSourceMap) map = UglifyJS.SourceMap({
20912         file: options.outSourceMap,
20913         orig: inMap,
20914         root: options.sourceRoot
20915     });
20916     var output = { source_map: map };
20917     if (options.output) {
20918         UglifyJS.merge(output, options.output);
20919     }
20920     var stream = UglifyJS.OutputStream(output);
20921     toplevel.print(stream);
20922     return {
20923         code : stream + "",
20924         map  : map + ""
20925     };
20928 // exports.describe_ast = function() {
20929 //     function doitem(ctor) {
20930 //         var sub = {};
20931 //         ctor.SUBCLASSES.forEach(function(ctor){
20932 //             sub[ctor.TYPE] = doitem(ctor);
20933 //         });
20934 //         var ret = {};
20935 //         if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS;
20936 //         if (ctor.SUBCLASSES.length > 0) ret.sub = sub;
20937 //         return ret;
20938 //     }
20939 //     return doitem(UglifyJS.AST_Node).sub;
20940 // }
20942 exports.describe_ast = function() {
20943     var out = UglifyJS.OutputStream({ beautify: true });
20944     function doitem(ctor) {
20945         out.print("AST_" + ctor.TYPE);
20946         var props = ctor.SELF_PROPS.filter(function(prop){
20947             return !/^\$/.test(prop);
20948         });
20949         if (props.length > 0) {
20950             out.space();
20951             out.with_parens(function(){
20952                 props.forEach(function(prop, i){
20953                     if (i) out.space();
20954                     out.print(prop);
20955                 });
20956             });
20957         }
20958         if (ctor.documentation) {
20959             out.space();
20960             out.print_string(ctor.documentation);
20961         }
20962         if (ctor.SUBCLASSES.length > 0) {
20963             out.space();
20964             out.with_block(function(){
20965                 ctor.SUBCLASSES.forEach(function(ctor, i){
20966                     out.indent();
20967                     doitem(ctor);
20968                     out.newline();
20969                 });
20970             });
20971         }
20972     };
20973     doitem(UglifyJS.AST_Node);
20974     return out + "";
20979  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
20980  * Available via the MIT or new BSD license.
20981  * see: http://github.com/jrburke/requirejs for details
20982  */
20984 /*jslint plusplus: true */
20985 /*global define: false */
20987 define('parse', ['./esprimaAdapter', 'lang'], function (esprima, lang) {
20988     'use strict';
20990     function arrayToString(ary) {
20991         var output = '[';
20992         if (ary) {
20993             ary.forEach(function (item, i) {
20994                 output += (i > 0 ? ',' : '') + '"' + lang.jsEscape(item) + '"';
20995             });
20996         }
20997         output += ']';
20999         return output;
21000     }
21002     //This string is saved off because JSLint complains
21003     //about obj.arguments use, as 'reserved word'
21004     var argPropName = 'arguments';
21006     //From an esprima example for traversing its ast.
21007     function traverse(object, visitor) {
21008         var key, child;
21010         if (!object) {
21011             return;
21012         }
21014         if (visitor.call(null, object) === false) {
21015             return false;
21016         }
21017         for (key in object) {
21018             if (object.hasOwnProperty(key)) {
21019                 child = object[key];
21020                 if (typeof child === 'object' && child !== null) {
21021                     if (traverse(child, visitor) === false) {
21022                         return false;
21023                     }
21024                 }
21025             }
21026         }
21027     }
21029     //Like traverse, but visitor returning false just
21030     //stops that subtree analysis, not the rest of tree
21031     //visiting.
21032     function traverseBroad(object, visitor) {
21033         var key, child;
21035         if (!object) {
21036             return;
21037         }
21039         if (visitor.call(null, object) === false) {
21040             return false;
21041         }
21042         for (key in object) {
21043             if (object.hasOwnProperty(key)) {
21044                 child = object[key];
21045                 if (typeof child === 'object' && child !== null) {
21046                     traverse(child, visitor);
21047                 }
21048             }
21049         }
21050     }
21052     /**
21053      * Pulls out dependencies from an array literal with just string members.
21054      * If string literals, will just return those string values in an array,
21055      * skipping other items in the array.
21056      *
21057      * @param {Node} node an AST node.
21058      *
21059      * @returns {Array} an array of strings.
21060      * If null is returned, then it means the input node was not a valid
21061      * dependency.
21062      */
21063     function getValidDeps(node) {
21064         if (!node || node.type !== 'ArrayExpression' || !node.elements) {
21065             return;
21066         }
21068         var deps = [];
21070         node.elements.some(function (elem) {
21071             if (elem.type === 'Literal') {
21072                 deps.push(elem.value);
21073             }
21074         });
21076         return deps.length ? deps : undefined;
21077     }
21079     /**
21080      * Main parse function. Returns a string of any valid require or
21081      * define/require.def calls as part of one JavaScript source string.
21082      * @param {String} moduleName the module name that represents this file.
21083      * It is used to create a default define if there is not one already for the
21084      * file. This allows properly tracing dependencies for builds. Otherwise, if
21085      * the file just has a require() call, the file dependencies will not be
21086      * properly reflected: the file will come before its dependencies.
21087      * @param {String} moduleName
21088      * @param {String} fileName
21089      * @param {String} fileContents
21090      * @param {Object} options optional options. insertNeedsDefine: true will
21091      * add calls to require.needsDefine() if appropriate.
21092      * @returns {String} JS source string or null, if no require or
21093      * define/require.def calls are found.
21094      */
21095     function parse(moduleName, fileName, fileContents, options) {
21096         options = options || {};
21098         //Set up source input
21099         var i, moduleCall, depString,
21100             moduleDeps = [],
21101             result = '',
21102             moduleList = [],
21103             needsDefine = true,
21104             astRoot = esprima.parse(fileContents);
21106         parse.recurse(astRoot, function (callName, config, name, deps) {
21107             if (!deps) {
21108                 deps = [];
21109             }
21111             if (callName === 'define' && (!name || name === moduleName)) {
21112                 needsDefine = false;
21113             }
21115             if (!name) {
21116                 //If there is no module name, the dependencies are for
21117                 //this file/default module name.
21118                 moduleDeps = moduleDeps.concat(deps);
21119             } else {
21120                 moduleList.push({
21121                     name: name,
21122                     deps: deps
21123                 });
21124             }
21126             //If define was found, no need to dive deeper, unless
21127             //the config explicitly wants to dig deeper.
21128             return !!options.findNestedDependencies;
21129         }, options);
21131         if (options.insertNeedsDefine && needsDefine) {
21132             result += 'require.needsDefine("' + moduleName + '");';
21133         }
21135         if (moduleDeps.length || moduleList.length) {
21136             for (i = 0; i < moduleList.length; i++) {
21137                 moduleCall = moduleList[i];
21138                 if (result) {
21139                     result += '\n';
21140                 }
21142                 //If this is the main module for this file, combine any
21143                 //"anonymous" dependencies (could come from a nested require
21144                 //call) with this module.
21145                 if (moduleCall.name === moduleName) {
21146                     moduleCall.deps = moduleCall.deps.concat(moduleDeps);
21147                     moduleDeps = [];
21148                 }
21150                 depString = arrayToString(moduleCall.deps);
21151                 result += 'define("' + moduleCall.name + '",' +
21152                           depString + ');';
21153             }
21154             if (moduleDeps.length) {
21155                 if (result) {
21156                     result += '\n';
21157                 }
21158                 depString = arrayToString(moduleDeps);
21159                 result += 'define("' + moduleName + '",' + depString + ');';
21160             }
21161         }
21163         return result || null;
21164     }
21166     parse.traverse = traverse;
21167     parse.traverseBroad = traverseBroad;
21169     /**
21170      * Handles parsing a file recursively for require calls.
21171      * @param {Array} parentNode the AST node to start with.
21172      * @param {Function} onMatch function to call on a parse match.
21173      * @param {Object} [options] This is normally the build config options if
21174      * it is passed.
21175      */
21176     parse.recurse = function (object, onMatch, options) {
21177         //Like traverse, but skips if branches that would not be processed
21178         //after has application that results in tests of true or false boolean
21179         //literal values.
21180         var key, child,
21181             hasHas = options && options.has;
21183         if (!object) {
21184             return;
21185         }
21187         //If has replacement has resulted in if(true){} or if(false){}, take
21188         //the appropriate branch and skip the other one.
21189         if (hasHas && object.type === 'IfStatement' && object.test.type &&
21190                 object.test.type === 'Literal') {
21191             if (object.test.value) {
21192                 //Take the if branch
21193                 this.recurse(object.consequent, onMatch, options);
21194             } else {
21195                 //Take the else branch
21196                 this.recurse(object.alternate, onMatch, options);
21197             }
21198         } else {
21199             if (this.parseNode(object, onMatch) === false) {
21200                 return;
21201             }
21202             for (key in object) {
21203                 if (object.hasOwnProperty(key)) {
21204                     child = object[key];
21205                     if (typeof child === 'object' && child !== null) {
21206                         this.recurse(child, onMatch, options);
21207                     }
21208                 }
21209             }
21210         }
21211     };
21213     /**
21214      * Determines if the file defines the require/define module API.
21215      * Specifically, it looks for the `define.amd = ` expression.
21216      * @param {String} fileName
21217      * @param {String} fileContents
21218      * @returns {Boolean}
21219      */
21220     parse.definesRequire = function (fileName, fileContents) {
21221         var found = false;
21223         traverse(esprima.parse(fileContents), function (node) {
21224             if (parse.hasDefineAmd(node)) {
21225                 found = true;
21227                 //Stop traversal
21228                 return false;
21229             }
21230         });
21232         return found;
21233     };
21235     /**
21236      * Finds require("") calls inside a CommonJS anonymous module wrapped in a
21237      * define(function(require, exports, module){}) wrapper. These dependencies
21238      * will be added to a modified define() call that lists the dependencies
21239      * on the outside of the function.
21240      * @param {String} fileName
21241      * @param {String|Object} fileContents: a string of contents, or an already
21242      * parsed AST tree.
21243      * @returns {Array} an array of module names that are dependencies. Always
21244      * returns an array, but could be of length zero.
21245      */
21246     parse.getAnonDeps = function (fileName, fileContents) {
21247         var astRoot = typeof fileContents === 'string' ?
21248                       esprima.parse(fileContents) : fileContents,
21249             defFunc = this.findAnonDefineFactory(astRoot);
21251         return parse.getAnonDepsFromNode(defFunc);
21252     };
21254     /**
21255      * Finds require("") calls inside a CommonJS anonymous module wrapped
21256      * in a define function, given an AST node for the definition function.
21257      * @param {Node} node the AST node for the definition function.
21258      * @returns {Array} and array of dependency names. Can be of zero length.
21259      */
21260     parse.getAnonDepsFromNode = function (node) {
21261         var deps = [],
21262             funcArgLength;
21264         if (node) {
21265             this.findRequireDepNames(node, deps);
21267             //If no deps, still add the standard CommonJS require, exports,
21268             //module, in that order, to the deps, but only if specified as
21269             //function args. In particular, if exports is used, it is favored
21270             //over the return value of the function, so only add it if asked.
21271             funcArgLength = node.params && node.params.length;
21272             if (funcArgLength) {
21273                 deps = (funcArgLength > 1 ? ["require", "exports", "module"] :
21274                         ["require"]).concat(deps);
21275             }
21276         }
21277         return deps;
21278     };
21280     parse.isDefineNodeWithArgs = function (node) {
21281         return node && node.type === 'CallExpression' &&
21282                node.callee && node.callee.type === 'Identifier' &&
21283                node.callee.name === 'define' && node[argPropName];
21284     };
21286     /**
21287      * Finds the function in define(function (require, exports, module){});
21288      * @param {Array} node
21289      * @returns {Boolean}
21290      */
21291     parse.findAnonDefineFactory = function (node) {
21292         var match;
21294         traverse(node, function (node) {
21295             var arg0, arg1;
21297             if (parse.isDefineNodeWithArgs(node)) {
21299                 //Just the factory function passed to define
21300                 arg0 = node[argPropName][0];
21301                 if (arg0 && arg0.type === 'FunctionExpression') {
21302                     match = arg0;
21303                     return false;
21304                 }
21306                 //A string literal module ID followed by the factory function.
21307                 arg1 = node[argPropName][1];
21308                 if (arg0.type === 'Literal' &&
21309                         arg1 && arg1.type === 'FunctionExpression') {
21310                     match = arg1;
21311                     return false;
21312                 }
21313             }
21314         });
21316         return match;
21317     };
21319     /**
21320      * Finds any config that is passed to requirejs. That includes calls to
21321      * require/requirejs.config(), as well as require({}, ...) and
21322      * requirejs({}, ...)
21323      * @param {String} fileContents
21324      *
21325      * @returns {Object} a config details object with the following properties:
21326      * - config: {Object} the config object found. Can be undefined if no
21327      * config found.
21328      * - range: {Array} the start index and end index in the contents where
21329      * the config was found. Can be undefined if no config found.
21330      * Can throw an error if the config in the file cannot be evaluated in
21331      * a build context to valid JavaScript.
21332      */
21333     parse.findConfig = function (fileContents) {
21334         /*jslint evil: true */
21335         var jsConfig, foundConfig, stringData, foundRange, quote, quoteMatch,
21336             quoteRegExp = /(:\s|\[\s*)(['"])/,
21337             astRoot = esprima.parse(fileContents, {
21338                 loc: true
21339             });
21341         traverse(astRoot, function (node) {
21342             var arg,
21343                 requireType = parse.hasRequire(node);
21345             if (requireType && (requireType === 'require' ||
21346                     requireType === 'requirejs' ||
21347                     requireType === 'requireConfig' ||
21348                     requireType === 'requirejsConfig')) {
21350                 arg = node[argPropName] && node[argPropName][0];
21352                 if (arg && arg.type === 'ObjectExpression') {
21353                     stringData = parse.nodeToString(fileContents, arg);
21354                     jsConfig = stringData.value;
21355                     foundRange = stringData.range;
21356                     return false;
21357                 }
21358             } else {
21359                 arg = parse.getRequireObjectLiteral(node);
21360                 if (arg) {
21361                     stringData = parse.nodeToString(fileContents, arg);
21362                     jsConfig = stringData.value;
21363                     foundRange = stringData.range;
21364                     return false;
21365                 }
21366             }
21367         });
21369         if (jsConfig) {
21370             // Eval the config
21371             quoteMatch = quoteRegExp.exec(jsConfig);
21372             quote = (quoteMatch && quoteMatch[2]) || '"';
21373             foundConfig = eval('(' + jsConfig + ')');
21374         }
21376         return {
21377             config: foundConfig,
21378             range: foundRange,
21379             quote: quote
21380         };
21381     };
21383     /** Returns the node for the object literal assigned to require/requirejs,
21384      * for holding a declarative config.
21385      */
21386     parse.getRequireObjectLiteral = function (node) {
21387         if (node.id && node.id.type === 'Identifier' &&
21388                 (node.id.name === 'require' || node.id.name === 'requirejs') &&
21389                 node.init && node.init.type === 'ObjectExpression') {
21390             return node.init;
21391         }
21392     };
21394     /**
21395      * Renames require/requirejs/define calls to be ns + '.' + require/requirejs/define
21396      * Does *not* do .config calls though. See pragma.namespace for the complete
21397      * set of namespace transforms. This function is used because require calls
21398      * inside a define() call should not be renamed, so a simple regexp is not
21399      * good enough.
21400      * @param  {String} fileContents the contents to transform.
21401      * @param  {String} ns the namespace, *not* including trailing dot.
21402      * @return {String} the fileContents with the namespace applied
21403      */
21404     parse.renameNamespace = function (fileContents, ns) {
21405         var lines,
21406             locs = [],
21407             astRoot = esprima.parse(fileContents, {
21408                 loc: true
21409             });
21411         parse.recurse(astRoot, function (callName, config, name, deps, node) {
21412             locs.push(node.loc);
21413             //Do not recurse into define functions, they should be using
21414             //local defines.
21415             return callName !== 'define';
21416         }, {});
21418         if (locs.length) {
21419             lines = fileContents.split('\n');
21421             //Go backwards through the found locs, adding in the namespace name
21422             //in front.
21423             locs.reverse();
21424             locs.forEach(function (loc) {
21425                 var startIndex = loc.start.column,
21426                 //start.line is 1-based, not 0 based.
21427                 lineIndex = loc.start.line - 1,
21428                 line = lines[lineIndex];
21430                 lines[lineIndex] = line.substring(0, startIndex) +
21431                                    ns + '.' +
21432                                    line.substring(startIndex,
21433                                                       line.length);
21434             });
21436             fileContents = lines.join('\n');
21437         }
21439         return fileContents;
21440     };
21442     /**
21443      * Finds all dependencies specified in dependency arrays and inside
21444      * simplified commonjs wrappers.
21445      * @param {String} fileName
21446      * @param {String} fileContents
21447      *
21448      * @returns {Array} an array of dependency strings. The dependencies
21449      * have not been normalized, they may be relative IDs.
21450      */
21451     parse.findDependencies = function (fileName, fileContents, options) {
21452         var dependencies = [],
21453             astRoot = esprima.parse(fileContents);
21455         parse.recurse(astRoot, function (callName, config, name, deps) {
21456             if (deps) {
21457                 dependencies = dependencies.concat(deps);
21458             }
21459         }, options);
21461         return dependencies;
21462     };
21464     /**
21465      * Finds only CJS dependencies, ones that are the form
21466      * require('stringLiteral')
21467      */
21468     parse.findCjsDependencies = function (fileName, fileContents) {
21469         var dependencies = [];
21471         traverse(esprima.parse(fileContents), function (node) {
21472             var arg;
21474             if (node && node.type === 'CallExpression' && node.callee &&
21475                     node.callee.type === 'Identifier' &&
21476                     node.callee.name === 'require' && node[argPropName] &&
21477                     node[argPropName].length === 1) {
21478                 arg = node[argPropName][0];
21479                 if (arg.type === 'Literal') {
21480                     dependencies.push(arg.value);
21481                 }
21482             }
21483         });
21485         return dependencies;
21486     };
21488     //function define() {}
21489     parse.hasDefDefine = function (node) {
21490         return node.type === 'FunctionDeclaration' && node.id &&
21491                     node.id.type === 'Identifier' && node.id.name === 'define';
21492     };
21494     //define.amd = ...
21495     parse.hasDefineAmd = function (node) {
21496         return node && node.type === 'AssignmentExpression' &&
21497             node.left && node.left.type === 'MemberExpression' &&
21498             node.left.object && node.left.object.name === 'define' &&
21499             node.left.property && node.left.property.name === 'amd';
21500     };
21502     //define.amd reference, as in: if (define.amd)
21503     parse.refsDefineAmd = function (node) {
21504         return node && node.type === 'MemberExpression' &&
21505         node.object && node.object.name === 'define' &&
21506         node.object.type === 'Identifier' &&
21507         node.property && node.property.name === 'amd' &&
21508         node.property.type === 'Identifier';
21509     };
21511     //require(), requirejs(), require.config() and requirejs.config()
21512     parse.hasRequire = function (node) {
21513         var callName,
21514             c = node && node.callee;
21516         if (node && node.type === 'CallExpression' && c) {
21517             if (c.type === 'Identifier' &&
21518                     (c.name === 'require' ||
21519                     c.name === 'requirejs')) {
21520                 //A require/requirejs({}, ...) call
21521                 callName = c.name;
21522             } else if (c.type === 'MemberExpression' &&
21523                     c.object &&
21524                     c.object.type === 'Identifier' &&
21525                     (c.object.name === 'require' ||
21526                         c.object.name === 'requirejs') &&
21527                     c.property && c.property.name === 'config') {
21528                 // require/requirejs.config({}) call
21529                 callName = c.object.name + 'Config';
21530             }
21531         }
21533         return callName;
21534     };
21536     //define()
21537     parse.hasDefine = function (node) {
21538         return node && node.type === 'CallExpression' && node.callee &&
21539             node.callee.type === 'Identifier' &&
21540             node.callee.name === 'define';
21541     };
21543     /**
21544      * If there is a named define in the file, returns the name. Does not
21545      * scan for mulitple names, just the first one.
21546      */
21547     parse.getNamedDefine = function (fileContents) {
21548         var name;
21549         traverse(esprima.parse(fileContents), function (node) {
21550             if (node && node.type === 'CallExpression' && node.callee &&
21551             node.callee.type === 'Identifier' &&
21552             node.callee.name === 'define' &&
21553             node[argPropName] && node[argPropName][0] &&
21554             node[argPropName][0].type === 'Literal') {
21555                 name = node[argPropName][0].value;
21556                 return false;
21557             }
21558         });
21560         return name;
21561     };
21563     /**
21564      * Determines if define(), require({}|[]) or requirejs was called in the
21565      * file. Also finds out if define() is declared and if define.amd is called.
21566      */
21567     parse.usesAmdOrRequireJs = function (fileName, fileContents) {
21568         var uses;
21570         traverse(esprima.parse(fileContents), function (node) {
21571             var type, callName, arg;
21573             if (parse.hasDefDefine(node)) {
21574                 //function define() {}
21575                 type = 'declaresDefine';
21576             } else if (parse.hasDefineAmd(node)) {
21577                 type = 'defineAmd';
21578             } else {
21579                 callName = parse.hasRequire(node);
21580                 if (callName) {
21581                     arg = node[argPropName] && node[argPropName][0];
21582                     if (arg && (arg.type === 'ObjectExpression' ||
21583                             arg.type === 'ArrayExpression')) {
21584                         type = callName;
21585                     }
21586                 } else if (parse.hasDefine(node)) {
21587                     type = 'define';
21588                 }
21589             }
21591             if (type) {
21592                 if (!uses) {
21593                     uses = {};
21594                 }
21595                 uses[type] = true;
21596             }
21597         });
21599         return uses;
21600     };
21602     /**
21603      * Determines if require(''), exports.x =, module.exports =,
21604      * __dirname, __filename are used. So, not strictly traditional CommonJS,
21605      * also checks for Node variants.
21606      */
21607     parse.usesCommonJs = function (fileName, fileContents) {
21608         var uses = null,
21609             assignsExports = false;
21612         traverse(esprima.parse(fileContents), function (node) {
21613             var type,
21614                 exp = node.expression || node.init;
21616             if (node.type === 'Identifier' &&
21617                     (node.name === '__dirname' || node.name === '__filename')) {
21618                 type = node.name.substring(2);
21619             } else if (node.type === 'VariableDeclarator' && node.id &&
21620                     node.id.type === 'Identifier' &&
21621                         node.id.name === 'exports') {
21622                 //Hmm, a variable assignment for exports, so does not use cjs
21623                 //exports.
21624                 type = 'varExports';
21625             } else if (exp && exp.type === 'AssignmentExpression' && exp.left &&
21626                     exp.left.type === 'MemberExpression' && exp.left.object) {
21627                 if (exp.left.object.name === 'module' && exp.left.property &&
21628                         exp.left.property.name === 'exports') {
21629                     type = 'moduleExports';
21630                 } else if (exp.left.object.name === 'exports' &&
21631                         exp.left.property) {
21632                     type = 'exports';
21633                 }
21635             } else if (node && node.type === 'CallExpression' && node.callee &&
21636                     node.callee.type === 'Identifier' &&
21637                     node.callee.name === 'require' && node[argPropName] &&
21638                     node[argPropName].length === 1 &&
21639                     node[argPropName][0].type === 'Literal') {
21640                 type = 'require';
21641             }
21643             if (type) {
21644                 if (type === 'varExports') {
21645                     assignsExports = true;
21646                 } else if (type !== 'exports' || !assignsExports) {
21647                     if (!uses) {
21648                         uses = {};
21649                     }
21650                     uses[type] = true;
21651                 }
21652             }
21653         });
21655         return uses;
21656     };
21659     parse.findRequireDepNames = function (node, deps) {
21660         traverse(node, function (node) {
21661             var arg;
21663             if (node && node.type === 'CallExpression' && node.callee &&
21664                     node.callee.type === 'Identifier' &&
21665                     node.callee.name === 'require' &&
21666                     node[argPropName] && node[argPropName].length === 1) {
21668                 arg = node[argPropName][0];
21669                 if (arg.type === 'Literal') {
21670                     deps.push(arg.value);
21671                 }
21672             }
21673         });
21674     };
21676     /**
21677      * Determines if a specific node is a valid require or define/require.def
21678      * call.
21679      * @param {Array} node
21680      * @param {Function} onMatch a function to call when a match is found.
21681      * It is passed the match name, and the config, name, deps possible args.
21682      * The config, name and deps args are not normalized.
21683      *
21684      * @returns {String} a JS source string with the valid require/define call.
21685      * Otherwise null.
21686      */
21687     parse.parseNode = function (node, onMatch) {
21688         var name, deps, cjsDeps, arg, factory, exp, refsDefine, bodyNode,
21689             args = node && node[argPropName],
21690             callName = parse.hasRequire(node);
21692         if (callName === 'require' || callName === 'requirejs') {
21693             //A plain require/requirejs call
21694             arg = node[argPropName] && node[argPropName][0];
21695             if (arg.type !== 'ArrayExpression') {
21696                 if (arg.type === 'ObjectExpression') {
21697                     //A config call, try the second arg.
21698                     arg = node[argPropName][1];
21699                 }
21700             }
21702             deps = getValidDeps(arg);
21703             if (!deps) {
21704                 return;
21705             }
21707             return onMatch("require", null, null, deps, node);
21708         } else if (parse.hasDefine(node) && args && args.length) {
21709             name = args[0];
21710             deps = args[1];
21711             factory = args[2];
21713             if (name.type === 'ArrayExpression') {
21714                 //No name, adjust args
21715                 factory = deps;
21716                 deps = name;
21717                 name = null;
21718             } else if (name.type === 'FunctionExpression') {
21719                 //Just the factory, no name or deps
21720                 factory = name;
21721                 name = deps = null;
21722             } else if (name.type !== 'Literal') {
21723                  //An object literal, just null out
21724                 name = deps = factory = null;
21725             }
21727             if (name && name.type === 'Literal' && deps) {
21728                 if (deps.type === 'FunctionExpression') {
21729                     //deps is the factory
21730                     factory = deps;
21731                     deps = null;
21732                 } else if (deps.type === 'ObjectExpression') {
21733                     //deps is object literal, null out
21734                     deps = factory = null;
21735                 } else if (deps.type === 'Identifier' && args.length === 2) {
21736                     // define('id', factory)
21737                     deps = factory = null;
21738                 }
21739             }
21741             if (deps && deps.type === 'ArrayExpression') {
21742                 deps = getValidDeps(deps);
21743             } else if (factory && factory.type === 'FunctionExpression') {
21744                 //If no deps and a factory function, could be a commonjs sugar
21745                 //wrapper, scan the function for dependencies.
21746                 cjsDeps = parse.getAnonDepsFromNode(factory);
21747                 if (cjsDeps.length) {
21748                     deps = cjsDeps;
21749                 }
21750             } else if (deps || factory) {
21751                 //Does not match the shape of an AMD call.
21752                 return;
21753             }
21755             //Just save off the name as a string instead of an AST object.
21756             if (name && name.type === 'Literal') {
21757                 name = name.value;
21758             }
21760             return onMatch("define", null, name, deps, node);
21761         } else if (node.type === 'CallExpression' && node.callee &&
21762                    node.callee.type === 'FunctionExpression' &&
21763                    node.callee.body && node.callee.body.body &&
21764                    node.callee.body.body.length === 1 &&
21765                    node.callee.body.body[0].type === 'IfStatement') {
21766             bodyNode = node.callee.body.body[0];
21767             //Look for a define(Identifier) case, but only if inside an
21768             //if that has a define.amd test
21769             if (bodyNode.consequent && bodyNode.consequent.body) {
21770                 exp = bodyNode.consequent.body[0];
21771                 if (exp.type === 'ExpressionStatement' && exp.expression &&
21772                     parse.hasDefine(exp.expression) &&
21773                     exp.expression.arguments &&
21774                     exp.expression.arguments.length === 1 &&
21775                     exp.expression.arguments[0].type === 'Identifier') {
21777                     //Calls define(Identifier) as first statement in body.
21778                     //Confirm the if test references define.amd
21779                     traverse(bodyNode.test, function (node) {
21780                         if (parse.refsDefineAmd(node)) {
21781                             refsDefine = true;
21782                             return false;
21783                         }
21784                     });
21786                     if (refsDefine) {
21787                         return onMatch("define", null, null, null, exp.expression);
21788                     }
21789                 }
21790             }
21791         }
21792     };
21794     /**
21795      * Converts an AST node into a JS source string by extracting
21796      * the node's location from the given contents string. Assumes
21797      * esprima.parse() with loc was done.
21798      * @param {String} contents
21799      * @param {Object} node
21800      * @returns {String} a JS source string.
21801      */
21802     parse.nodeToString = function (contents, node) {
21803         var loc = node.loc,
21804             lines = contents.split('\n'),
21805             firstLine = loc.start.line > 1 ?
21806                         lines.slice(0, loc.start.line - 1).join('\n') + '\n' :
21807                         '',
21808             preamble = firstLine +
21809                        lines[loc.start.line - 1].substring(0, loc.start.column),
21810             extracted =  lines[loc.start.line - 1].substring(loc.start.column) +
21811                      '\n' +
21812                      lines.slice(loc.start.line, loc.end.line - 1).join('\n') +
21813                      '\n' +
21814                      lines[loc.end.line - 1].substring(0, loc.end.column);
21816         return {
21817             value: extracted,
21818             range: [
21819                 preamble.length,
21820                 preamble.length + extracted.length
21821             ]
21822         };
21823     };
21825     /**
21826      * Extracts license comments from JS text.
21827      * @param {String} fileName
21828      * @param {String} contents
21829      * @returns {String} a string of license comments.
21830      */
21831     parse.getLicenseComments = function (fileName, contents) {
21832         var commentNode, refNode, subNode, value, i, j,
21833             //xpconnect's Reflect does not support comment or range, but
21834             //prefer continued operation vs strict parity of operation,
21835             //as license comments can be expressed in other ways, like
21836             //via wrap args, or linked via sourcemaps.
21837             ast = esprima.parse(contents, {
21838                 comment: true,
21839                 range: true
21840             }),
21841             result = '',
21842             existsMap = {},
21843             lineEnd = contents.indexOf('\r') === -1 ? '\n' : '\r\n';
21845         if (ast.comments) {
21846             for (i = 0; i < ast.comments.length; i++) {
21847                 commentNode = ast.comments[i];
21849                 if (commentNode.type === 'Line') {
21850                     value = '//' + commentNode.value + lineEnd;
21851                     refNode = commentNode;
21853                     if (i + 1 >= ast.comments.length) {
21854                         value += lineEnd;
21855                     } else {
21856                         //Look for immediately adjacent single line comments
21857                         //since it could from a multiple line comment made out
21858                         //of single line comments. Like this comment.
21859                         for (j = i + 1; j < ast.comments.length; j++) {
21860                             subNode = ast.comments[j];
21861                             if (subNode.type === 'Line' &&
21862                                     subNode.range[0] === refNode.range[1] + 1) {
21863                                 //Adjacent single line comment. Collect it.
21864                                 value += '//' + subNode.value + lineEnd;
21865                                 refNode = subNode;
21866                             } else {
21867                                 //No more single line comment blocks. Break out
21868                                 //and continue outer looping.
21869                                 break;
21870                             }
21871                         }
21872                         value += lineEnd;
21873                         i = j - 1;
21874                     }
21875                 } else {
21876                     value = '/*' + commentNode.value + '*/' + lineEnd + lineEnd;
21877                 }
21879                 if (!existsMap[value] && (value.indexOf('license') !== -1 ||
21880                         (commentNode.type === 'Block' &&
21881                             value.indexOf('/*!') === 0) ||
21882                         value.indexOf('opyright') !== -1 ||
21883                         value.indexOf('(c)') !== -1)) {
21885                     result += value;
21886                     existsMap[value] = true;
21887                 }
21889             }
21890         }
21892         return result;
21893     };
21895     return parse;
21898  * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
21899  * Available via the MIT or new BSD license.
21900  * see: http://github.com/jrburke/requirejs for details
21901  */
21903 /*global define */
21905 define('transform', [ './esprimaAdapter', './parse', 'logger', 'lang'],
21906 function (esprima, parse, logger, lang) {
21907     'use strict';
21908     var transform,
21909         baseIndentRegExp = /^([ \t]+)/,
21910         indentRegExp = /\{[\r\n]+([ \t]+)/,
21911         keyRegExp = /^[_A-Za-z]([A-Za-z\d_]*)$/,
21912         bulkIndentRegExps = {
21913             '\n': /\n/g,
21914             '\r\n': /\r\n/g
21915         };
21917     function applyIndent(str, indent, lineReturn) {
21918         var regExp = bulkIndentRegExps[lineReturn];
21919         return str.replace(regExp, '$&' + indent);
21920     }
21922     transform = {
21923         toTransport: function (namespace, moduleName, path, contents, onFound, options) {
21924             options = options || {};
21926             var astRoot, contentLines, modLine,
21927                 foundAnon,
21928                 scanCount = 0,
21929                 scanReset = false,
21930                 defineInfos = [];
21932             try {
21933                 astRoot = esprima.parse(contents, {
21934                     loc: true
21935                 });
21936             } catch (e) {
21937                 logger.trace('toTransport skipping ' + path + ': ' +
21938                              e.toString());
21939                 return contents;
21940             }
21942             //Find the define calls and their position in the files.
21943             parse.traverseBroad(astRoot, function (node) {
21944                 var args, firstArg, firstArgLoc, factoryNode,
21945                     needsId, depAction, foundId,
21946                     sourceUrlData, range,
21947                     namespaceExists = false;
21949                 namespaceExists = namespace &&
21950                                 node.type === 'CallExpression' &&
21951                                 node.callee  && node.callee.object &&
21952                                 node.callee.object.type === 'Identifier' &&
21953                                 node.callee.object.name === namespace &&
21954                                 node.callee.property.type === 'Identifier' &&
21955                                 node.callee.property.name === 'define';
21957                 if (namespaceExists || parse.isDefineNodeWithArgs(node)) {
21958                     //The arguments are where its at.
21959                     args = node.arguments;
21960                     if (!args || !args.length) {
21961                         return;
21962                     }
21964                     firstArg = args[0];
21965                     firstArgLoc = firstArg.loc;
21967                     if (args.length === 1) {
21968                         if (firstArg.type === 'Identifier') {
21969                             //The define(factory) case, but
21970                             //only allow it if one Identifier arg,
21971                             //to limit impact of false positives.
21972                             needsId = true;
21973                             depAction = 'empty';
21974                         } else if (firstArg.type === 'FunctionExpression') {
21975                             //define(function(){})
21976                             factoryNode = firstArg;
21977                             needsId = true;
21978                             depAction = 'scan';
21979                         } else if (firstArg.type === 'ObjectExpression') {
21980                             //define({});
21981                             needsId = true;
21982                             depAction = 'skip';
21983                         } else if (firstArg.type === 'Literal' &&
21984                                    typeof firstArg.value === 'number') {
21985                             //define('12345');
21986                             needsId = true;
21987                             depAction = 'skip';
21988                         } else if (firstArg.type === 'UnaryExpression' &&
21989                                    firstArg.operator === '-' &&
21990                                    firstArg.argument &&
21991                                    firstArg.argument.type === 'Literal' &&
21992                                    typeof firstArg.argument.value === 'number') {
21993                             //define('-12345');
21994                             needsId = true;
21995                             depAction = 'skip';
21996                         } else if (firstArg.type === 'MemberExpression' &&
21997                                    firstArg.object &&
21998                                    firstArg.property &&
21999                                    firstArg.property.type === 'Identifier') {
22000                             //define(this.key);
22001                             needsId = true;
22002                             depAction = 'empty';
22003                         }
22004                     } else if (firstArg.type === 'ArrayExpression') {
22005                         //define([], ...);
22006                         needsId = true;
22007                         depAction = 'skip';
22008                     } else if (firstArg.type === 'Literal' &&
22009                                typeof firstArg.value === 'string') {
22010                         //define('string', ....)
22011                         //Already has an ID.
22012                         needsId = false;
22013                         if (args.length === 2 &&
22014                             args[1].type === 'FunctionExpression') {
22015                             //Needs dependency scanning.
22016                             factoryNode = args[1];
22017                             depAction = 'scan';
22018                         } else {
22019                             depAction = 'skip';
22020                         }
22021                     } else {
22022                         //Unknown define entity, keep looking, even
22023                         //in the subtree for this node.
22024                         return;
22025                     }
22027                     range = {
22028                         foundId: foundId,
22029                         needsId: needsId,
22030                         depAction: depAction,
22031                         namespaceExists: namespaceExists,
22032                         node: node,
22033                         defineLoc: node.loc,
22034                         firstArgLoc: firstArgLoc,
22035                         factoryNode: factoryNode,
22036                         sourceUrlData: sourceUrlData
22037                     };
22039                     //Only transform ones that do not have IDs. If it has an
22040                     //ID but no dependency array, assume it is something like
22041                     //a phonegap implementation, that has its own internal
22042                     //define that cannot handle dependency array constructs,
22043                     //and if it is a named module, then it means it has been
22044                     //set for transport form.
22045                     if (range.needsId) {
22046                         if (foundAnon) {
22047                             logger.trace(path + ' has more than one anonymous ' +
22048                                 'define. May be a built file from another ' +
22049                                 'build system like, Ender. Skipping normalization.');
22050                             defineInfos = [];
22051                             return false;
22052                         } else {
22053                             foundAnon = range;
22054                             defineInfos.push(range);
22055                         }
22056                     } else if (depAction === 'scan') {
22057                         scanCount += 1;
22058                         if (scanCount > 1) {
22059                             //Just go back to an array that just has the
22060                             //anon one, since this is an already optimized
22061                             //file like the phonegap one.
22062                             if (!scanReset) {
22063                                 defineInfos =  foundAnon ? [foundAnon] : [];
22064                                 scanReset = true;
22065                             }
22066                         } else {
22067                             defineInfos.push(range);
22068                         }
22069                     }
22070                 }
22071             });
22073             if (!defineInfos.length) {
22074                 return contents;
22075             }
22077             //Reverse the matches, need to start from the bottom of
22078             //the file to modify it, so that the ranges are still true
22079             //further up.
22080             defineInfos.reverse();
22082             contentLines = contents.split('\n');
22084             modLine = function (loc, contentInsertion) {
22085                 var startIndex = loc.start.column,
22086                 //start.line is 1-based, not 0 based.
22087                 lineIndex = loc.start.line - 1,
22088                 line = contentLines[lineIndex];
22089                 contentLines[lineIndex] = line.substring(0, startIndex) +
22090                                            contentInsertion +
22091                                            line.substring(startIndex,
22092                                                               line.length);
22093             };
22095             defineInfos.forEach(function (info) {
22096                 var deps,
22097                     contentInsertion = '',
22098                     depString = '';
22100                 //Do the modifications "backwards", in other words, start with the
22101                 //one that is farthest down and work up, so that the ranges in the
22102                 //defineInfos still apply. So that means deps, id, then namespace.
22103                 if (info.needsId && moduleName) {
22104                     contentInsertion += "'" + moduleName + "',";
22105                 }
22107                 if (info.depAction === 'scan') {
22108                     deps = parse.getAnonDepsFromNode(info.factoryNode);
22110                     if (deps.length) {
22111                         depString = '[' + deps.map(function (dep) {
22112                             return "'" + dep + "'";
22113                         }) + ']';
22114                     } else {
22115                         depString = '[]';
22116                     }
22117                     depString +=  ',';
22119                     if (info.factoryNode) {
22120                         //Already have a named module, need to insert the
22121                         //dependencies after the name.
22122                         modLine(info.factoryNode.loc, depString);
22123                     } else {
22124                         contentInsertion += depString;
22125                     }
22126                 }
22128                 if (contentInsertion) {
22129                     modLine(info.firstArgLoc, contentInsertion);
22130                 }
22132                 //Do namespace last so that ui does not mess upthe parenRange
22133                 //used above.
22134                 if (namespace && !info.namespaceExists) {
22135                     modLine(info.defineLoc, namespace + '.');
22136                 }
22138                 //Notify any listener for the found info
22139                 if (onFound) {
22140                     onFound(info);
22141                 }
22142             });
22144             contents = contentLines.join('\n');
22146             if (options.useSourceUrl) {
22147                 contents = 'eval("' + lang.jsEscape(contents) +
22148                     '\\n//# sourceURL=' + (path.indexOf('/') === 0 ? '' : '/') +
22149                     path +
22150                     '");\n';
22151             }
22153             return contents;
22154         },
22156         /**
22157          * Modify the contents of a require.config/requirejs.config call. This
22158          * call will LOSE any existing comments that are in the config string.
22159          *
22160          * @param  {String} fileContents String that may contain a config call
22161          * @param  {Function} onConfig Function called when the first config
22162          * call is found. It will be passed an Object which is the current
22163          * config, and the onConfig function should return an Object to use
22164          * as the config.
22165          * @return {String} the fileContents with the config changes applied.
22166          */
22167         modifyConfig: function (fileContents, onConfig) {
22168             var details = parse.findConfig(fileContents),
22169                 config = details.config;
22171             if (config) {
22172                 config = onConfig(config);
22173                 if (config) {
22174                     return transform.serializeConfig(config,
22175                                               fileContents,
22176                                               details.range[0],
22177                                               details.range[1],
22178                                               {
22179                                                 quote: details.quote
22180                                               });
22181                 }
22182             }
22184             return fileContents;
22185         },
22187         serializeConfig: function (config, fileContents, start, end, options) {
22188             //Calculate base level of indent
22189             var indent, match, configString, outDentRegExp,
22190                 baseIndent = '',
22191                 startString = fileContents.substring(0, start),
22192                 existingConfigString = fileContents.substring(start, end),
22193                 lineReturn = existingConfigString.indexOf('\r') === -1 ? '\n' : '\r\n',
22194                 lastReturnIndex = startString.lastIndexOf('\n');
22196             //Get the basic amount of indent for the require config call.
22197             if (lastReturnIndex === -1) {
22198                 lastReturnIndex = 0;
22199             }
22201             match = baseIndentRegExp.exec(startString.substring(lastReturnIndex + 1, start));
22202             if (match && match[1]) {
22203                 baseIndent = match[1];
22204             }
22206             //Calculate internal indentation for config
22207             match = indentRegExp.exec(existingConfigString);
22208             if (match && match[1]) {
22209                 indent = match[1];
22210             }
22212             if (!indent || indent.length < baseIndent) {
22213                 indent = '  ';
22214             } else {
22215                 indent = indent.substring(baseIndent.length);
22216             }
22218             outDentRegExp = new RegExp('(' + lineReturn + ')' + indent, 'g');
22220             configString = transform.objectToString(config, {
22221                                                     indent: indent,
22222                                                     lineReturn: lineReturn,
22223                                                     outDentRegExp: outDentRegExp,
22224                                                     quote: options && options.quote
22225                                                 });
22227             //Add in the base indenting level.
22228             configString = applyIndent(configString, baseIndent, lineReturn);
22230             return startString + configString + fileContents.substring(end);
22231         },
22233         /**
22234          * Tries converting a JS object to a string. This will likely suck, and
22235          * is tailored to the type of config expected in a loader config call.
22236          * So, hasOwnProperty fields, strings, numbers, arrays and functions,
22237          * no weird recursively referenced stuff.
22238          * @param  {Object} obj        the object to convert
22239          * @param  {Object} options    options object with the following values:
22240          *         {String} indent     the indentation to use for each level
22241          *         {String} lineReturn the type of line return to use
22242          *         {outDentRegExp} outDentRegExp the regexp to use to outdent functions
22243          *         {String} quote      the quote type to use, ' or ". Optional. Default is "
22244          * @param  {String} totalIndent the total indent to print for this level
22245          * @return {String}            a string representation of the object.
22246          */
22247         objectToString: function (obj, options, totalIndent) {
22248             var startBrace, endBrace, nextIndent,
22249                 first = true,
22250                 value = '',
22251                 lineReturn = options.lineReturn,
22252                 indent = options.indent,
22253                 outDentRegExp = options.outDentRegExp,
22254                 quote = options.quote || '"';
22256             totalIndent = totalIndent || '';
22257             nextIndent = totalIndent + indent;
22259             if (obj === null) {
22260                 value = 'null';
22261             } else if (obj === undefined) {
22262                 value = 'undefined';
22263             } else if (typeof obj === 'number' || typeof obj === 'boolean') {
22264                 value = obj;
22265             } else if (typeof obj === 'string') {
22266                 //Use double quotes in case the config may also work as JSON.
22267                 value = quote + lang.jsEscape(obj) + quote;
22268             } else if (lang.isArray(obj)) {
22269                 lang.each(obj, function (item, i) {
22270                     value += (i !== 0 ? ',' + lineReturn : '' ) +
22271                         nextIndent +
22272                         transform.objectToString(item,
22273                                                  options,
22274                                                  nextIndent);
22275                 });
22277                 startBrace = '[';
22278                 endBrace = ']';
22279             } else if (lang.isFunction(obj) || lang.isRegExp(obj)) {
22280                 //The outdent regexp just helps pretty up the conversion
22281                 //just in node. Rhino strips comments and does a different
22282                 //indent scheme for Function toString, so not really helpful
22283                 //there.
22284                 value = obj.toString().replace(outDentRegExp, '$1');
22285             } else {
22286                 //An object
22287                 lang.eachProp(obj, function (v, prop) {
22288                     value += (first ? '': ',' + lineReturn) +
22289                         nextIndent +
22290                         (keyRegExp.test(prop) ? prop : quote + lang.jsEscape(prop) + quote )+
22291                         ': ' +
22292                         transform.objectToString(v,
22293                                                  options,
22294                                                  nextIndent);
22295                     first = false;
22296                 });
22297                 startBrace = '{';
22298                 endBrace = '}';
22299             }
22301             if (startBrace) {
22302                 value = startBrace +
22303                         lineReturn +
22304                         value +
22305                         lineReturn + totalIndent +
22306                         endBrace;
22307             }
22309             return value;
22310         }
22311     };
22313     return transform;
22316  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22317  * Available via the MIT or new BSD license.
22318  * see: http://github.com/jrburke/requirejs for details
22319  */
22321 /*jslint regexp: true, plusplus: true  */
22322 /*global define: false */
22324 define('pragma', ['parse', 'logger'], function (parse, logger) {
22325     'use strict';
22326     function Temp() {}
22328     function create(obj, mixin) {
22329         Temp.prototype = obj;
22330         var temp = new Temp(), prop;
22332         //Avoid any extra memory hanging around
22333         Temp.prototype = null;
22335         if (mixin) {
22336             for (prop in mixin) {
22337                 if (mixin.hasOwnProperty(prop) && !temp.hasOwnProperty(prop)) {
22338                     temp[prop] = mixin[prop];
22339                 }
22340             }
22341         }
22343         return temp; // Object
22344     }
22346     var pragma = {
22347         conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
22348         useStrictRegExp: /['"]use strict['"];/g,
22349         hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
22350         configRegExp: /(^|[^\.])(requirejs|require)(\.config)\s*\(/g,
22351         nsWrapRegExp: /\/\*requirejs namespace: true \*\//,
22352         apiDefRegExp: /var requirejs, require, define;/,
22353         defineCheckRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd/g,
22354         defineStringCheckRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\[\s*["']amd["']\s*\]/g,
22355         defineTypeFirstCheckRegExp: /\s*["']function["']\s*===\s*typeof\s+define\s*&&\s*define\s*\.\s*amd/g,
22356         defineJQueryRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd\s*&&\s*define\s*\.\s*amd\s*\.\s*jQuery/g,
22357         defineHasRegExp: /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g,
22358         defineTernaryRegExp: /typeof\s+define\s*===\s*['"]function["']\s*&&\s*define\s*\.\s*amd\s*\?\s*define/,
22359         amdefineRegExp: /if\s*\(\s*typeof define\s*\!==\s*'function'\s*\)\s*\{\s*[^\{\}]+amdefine[^\{\}]+\}/g,
22361         removeStrict: function (contents, config) {
22362             return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '');
22363         },
22365         namespace: function (fileContents, ns, onLifecycleName) {
22366             if (ns) {
22367                 //Namespace require/define calls
22368                 fileContents = fileContents.replace(pragma.configRegExp, '$1' + ns + '.$2$3(');
22371                 fileContents = parse.renameNamespace(fileContents, ns);
22373                 //Namespace define ternary use:
22374                 fileContents = fileContents.replace(pragma.defineTernaryRegExp,
22375                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd ? " + ns + ".define");
22377                 //Namespace define jquery use:
22378                 fileContents = fileContents.replace(pragma.defineJQueryRegExp,
22379                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd && " + ns + ".define.amd.jQuery");
22381                 //Namespace has.js define use:
22382                 fileContents = fileContents.replace(pragma.defineHasRegExp,
22383                                                     "typeof " + ns + ".define === 'function' && typeof " + ns + ".define.amd === 'object' && " + ns + ".define.amd");
22385                 //Namespace define checks.
22386                 //Do these ones last, since they are a subset of the more specific
22387                 //checks above.
22388                 fileContents = fileContents.replace(pragma.defineCheckRegExp,
22389                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd");
22390                 fileContents = fileContents.replace(pragma.defineStringCheckRegExp,
22391                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define['amd']");
22392                 fileContents = fileContents.replace(pragma.defineTypeFirstCheckRegExp,
22393                                                     "'function' === typeof " + ns + ".define && " + ns + ".define.amd");
22395                 //Check for require.js with the require/define definitions
22396                 if (pragma.apiDefRegExp.test(fileContents) &&
22397                     fileContents.indexOf("if (!" + ns + " || !" + ns + ".requirejs)") === -1) {
22398                     //Wrap the file contents in a typeof check, and a function
22399                     //to contain the API globals.
22400                     fileContents = "var " + ns + ";(function () { if (!" + ns + " || !" + ns + ".requirejs) {\n" +
22401                                     "if (!" + ns + ") { " + ns + ' = {}; } else { require = ' + ns + '; }\n' +
22402                                     fileContents +
22403                                     "\n" +
22404                                     ns + ".requirejs = requirejs;" +
22405                                     ns + ".require = require;" +
22406                                     ns + ".define = define;\n" +
22407                                     "}\n}());";
22408                 }
22410                 //Finally, if the file wants a special wrapper because it ties
22411                 //in to the requirejs internals in a way that would not fit
22412                 //the above matches, do that. Look for /*requirejs namespace: true*/
22413                 if (pragma.nsWrapRegExp.test(fileContents)) {
22414                     //Remove the pragma.
22415                     fileContents = fileContents.replace(pragma.nsWrapRegExp, '');
22417                     //Alter the contents.
22418                     fileContents = '(function () {\n' +
22419                                    'var require = ' + ns + '.require,' +
22420                                    'requirejs = ' + ns + '.requirejs,' +
22421                                    'define = ' + ns + '.define;\n' +
22422                                    fileContents +
22423                                    '\n}());';
22424                 }
22425             }
22427             return fileContents;
22428         },
22430         /**
22431          * processes the fileContents for some //>> conditional statements
22432          */
22433         process: function (fileName, fileContents, config, onLifecycleName, pluginCollector) {
22434             /*jslint evil: true */
22435             var foundIndex = -1, startIndex = 0, lineEndIndex, conditionLine,
22436                 matches, type, marker, condition, isTrue, endRegExp, endMatches,
22437                 endMarkerIndex, shouldInclude, startLength, lifecycleHas, deps,
22438                 i, dep, moduleName, collectorMod,
22439                 lifecyclePragmas, pragmas = config.pragmas, hasConfig = config.has,
22440                 //Legacy arg defined to help in dojo conversion script. Remove later
22441                 //when dojo no longer needs conversion:
22442                 kwArgs = pragmas;
22444             //Mix in a specific lifecycle scoped object, to allow targeting
22445             //some pragmas/has tests to only when files are saved, or at different
22446             //lifecycle events. Do not bother with kwArgs in this section, since
22447             //the old dojo kwArgs were for all points in the build lifecycle.
22448             if (onLifecycleName) {
22449                 lifecyclePragmas = config['pragmas' + onLifecycleName];
22450                 lifecycleHas = config['has' + onLifecycleName];
22452                 if (lifecyclePragmas) {
22453                     pragmas = create(pragmas || {}, lifecyclePragmas);
22454                 }
22456                 if (lifecycleHas) {
22457                     hasConfig = create(hasConfig || {}, lifecycleHas);
22458                 }
22459             }
22461             //Replace has references if desired
22462             if (hasConfig) {
22463                 fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) {
22464                     if (hasConfig.hasOwnProperty(test)) {
22465                         return !!hasConfig[test];
22466                     }
22467                     return match;
22468                 });
22469             }
22471             if (!config.skipPragmas) {
22473                 while ((foundIndex = fileContents.indexOf("//>>", startIndex)) !== -1) {
22474                     //Found a conditional. Get the conditional line.
22475                     lineEndIndex = fileContents.indexOf("\n", foundIndex);
22476                     if (lineEndIndex === -1) {
22477                         lineEndIndex = fileContents.length - 1;
22478                     }
22480                     //Increment startIndex past the line so the next conditional search can be done.
22481                     startIndex = lineEndIndex + 1;
22483                     //Break apart the conditional.
22484                     conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
22485                     matches = conditionLine.match(pragma.conditionalRegExp);
22486                     if (matches) {
22487                         type = matches[1];
22488                         marker = matches[2];
22489                         condition = matches[3];
22490                         isTrue = false;
22491                         //See if the condition is true.
22492                         try {
22493                             isTrue = !!eval("(" + condition + ")");
22494                         } catch (e) {
22495                             throw "Error in file: " +
22496                                    fileName +
22497                                    ". Conditional comment: " +
22498                                    conditionLine +
22499                                    " failed with this error: " + e;
22500                         }
22502                         //Find the endpoint marker.
22503                         endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
22504                         endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
22505                         if (endMatches) {
22506                             endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
22508                             //Find the next line return based on the match position.
22509                             lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
22510                             if (lineEndIndex === -1) {
22511                                 lineEndIndex = fileContents.length - 1;
22512                             }
22514                             //Should we include the segment?
22515                             shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue));
22517                             //Remove the conditional comments, and optionally remove the content inside
22518                             //the conditional comments.
22519                             startLength = startIndex - foundIndex;
22520                             fileContents = fileContents.substring(0, foundIndex) +
22521                                 (shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") +
22522                                 fileContents.substring(lineEndIndex + 1, fileContents.length);
22524                             //Move startIndex to foundIndex, since that is the new position in the file
22525                             //where we need to look for more conditionals in the next while loop pass.
22526                             startIndex = foundIndex;
22527                         } else {
22528                             throw "Error in file: " +
22529                                   fileName +
22530                                   ". Cannot find end marker for conditional comment: " +
22531                                   conditionLine;
22533                         }
22534                     }
22535                 }
22536             }
22538             //If need to find all plugin resources to optimize, do that now,
22539             //before namespacing, since the namespacing will change the API
22540             //names.
22541             //If there is a plugin collector, scan the file for plugin resources.
22542             if (config.optimizeAllPluginResources && pluginCollector) {
22543                 try {
22544                     deps = parse.findDependencies(fileName, fileContents);
22545                     if (deps.length) {
22546                         for (i = 0; i < deps.length; i++) {
22547                             dep = deps[i];
22548                             if (dep.indexOf('!') !== -1) {
22549                                 moduleName = dep.split('!')[0];
22550                                 collectorMod = pluginCollector[moduleName];
22551                                 if (!collectorMod) {
22552                                  collectorMod = pluginCollector[moduleName] = [];
22553                                 }
22554                                 collectorMod.push(dep);
22555                             }
22556                         }
22557                     }
22558                 } catch (eDep) {
22559                     logger.error('Parse error looking for plugin resources in ' +
22560                                  fileName + ', skipping.');
22561                 }
22562             }
22564             //Strip amdefine use for node-shared modules.
22565             fileContents = fileContents.replace(pragma.amdefineRegExp, '');
22567             //Do namespacing
22568             if (onLifecycleName === 'OnSave' && config.namespace) {
22569                 fileContents = pragma.namespace(fileContents, config.namespace, onLifecycleName);
22570             }
22573             return pragma.removeStrict(fileContents, config);
22574         }
22575     };
22577     return pragma;
22579 if(env === 'browser') {
22581  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22582  * Available via the MIT or new BSD license.
22583  * see: http://github.com/jrburke/requirejs for details
22584  */
22586 /*jslint strict: false */
22587 /*global define: false */
22589 define('browser/optimize', {});
22593 if(env === 'node') {
22595  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22596  * Available via the MIT or new BSD license.
22597  * see: http://github.com/jrburke/requirejs for details
22598  */
22600 /*jslint strict: false */
22601 /*global define: false */
22603 define('node/optimize', {});
22607 if(env === 'rhino') {
22609  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22610  * Available via the MIT or new BSD license.
22611  * see: http://github.com/jrburke/requirejs for details
22612  */
22614 /*jslint sloppy: true, plusplus: true */
22615 /*global define, java, Packages, com */
22617 define('rhino/optimize', ['logger', 'env!env/file'], function (logger, file) {
22619     //Add .reduce to Rhino so UglifyJS can run in Rhino,
22620     //inspired by https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
22621     //but rewritten for brevity, and to be good enough for use by UglifyJS.
22622     if (!Array.prototype.reduce) {
22623         Array.prototype.reduce = function (fn /*, initialValue */) {
22624             var i = 0,
22625                 length = this.length,
22626                 accumulator;
22628             if (arguments.length >= 2) {
22629                 accumulator = arguments[1];
22630             } else {
22631                 if (length) {
22632                     while (!(i in this)) {
22633                         i++;
22634                     }
22635                     accumulator = this[i++];
22636                 }
22637             }
22639             for (; i < length; i++) {
22640                 if (i in this) {
22641                     accumulator = fn.call(undefined, accumulator, this[i], i, this);
22642                 }
22643             }
22645             return accumulator;
22646         };
22647     }
22649     var JSSourceFilefromCode, optimize,
22650         mapRegExp = /"file":"[^"]+"/;
22652     //Bind to Closure compiler, but if it is not available, do not sweat it.
22653     try {
22654         JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]);
22655     } catch (e) {}
22657     //Helper for closure compiler, because of weird Java-JavaScript interactions.
22658     function closurefromCode(filename, content) {
22659         return JSSourceFilefromCode.invoke(null, [filename, content]);
22660     }
22663     function getFileWriter(fileName, encoding) {
22664         var outFile = new java.io.File(fileName), outWriter, parentDir;
22666         parentDir = outFile.getAbsoluteFile().getParentFile();
22667         if (!parentDir.exists()) {
22668             if (!parentDir.mkdirs()) {
22669                 throw "Could not create directory: " + parentDir.getAbsolutePath();
22670             }
22671         }
22673         if (encoding) {
22674             outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
22675         } else {
22676             outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
22677         }
22679         return new java.io.BufferedWriter(outWriter);
22680     }
22682     optimize = {
22683         closure: function (fileName, fileContents, outFileName, keepLines, config) {
22684             config = config || {};
22685             var result, mappings, optimized, compressed, baseName, writer,
22686                 outBaseName, outFileNameMap, outFileNameMapContent,
22687                 jscomp = Packages.com.google.javascript.jscomp,
22688                 flags = Packages.com.google.common.flags,
22689                 //Fake extern
22690                 externSourceFile = closurefromCode("fakeextern.js", " "),
22691                 //Set up source input
22692                 jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
22693                 options, option, FLAG_compilation_level, compiler,
22694                 Compiler = Packages.com.google.javascript.jscomp.Compiler;
22696             logger.trace("Minifying file: " + fileName);
22698             baseName = (new java.io.File(fileName)).getName();
22700             //Set up options
22701             options = new jscomp.CompilerOptions();
22702             for (option in config.CompilerOptions) {
22703                 // options are false by default and jslint wanted an if statement in this for loop
22704                 if (config.CompilerOptions[option]) {
22705                     options[option] = config.CompilerOptions[option];
22706                 }
22708             }
22709             options.prettyPrint = keepLines || options.prettyPrint;
22711             FLAG_compilation_level = jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS'];
22712             FLAG_compilation_level.setOptionsForCompilationLevel(options);
22714             if (config.generateSourceMaps) {
22715                 mappings = new java.util.ArrayList();
22717                 mappings.add(new com.google.javascript.jscomp.SourceMap.LocationMapping(fileName, baseName + ".src"));
22718                 options.setSourceMapLocationMappings(mappings);
22719                 options.setSourceMapOutputPath(fileName + ".map");
22720             }
22722             //Trigger the compiler
22723             Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']);
22724             compiler = new Compiler();
22726             result = compiler.compile(externSourceFile, jsSourceFile, options);
22727             if (result.success) {
22728                 optimized = String(compiler.toSource());
22730                 if (config.generateSourceMaps && result.sourceMap && outFileName) {
22731                     outBaseName = (new java.io.File(outFileName)).getName();
22733                     file.saveUtf8File(outFileName + ".src", fileContents);
22735                     outFileNameMap = outFileName + ".map";
22736                     writer = getFileWriter(outFileNameMap, "utf-8");
22737                     result.sourceMap.appendTo(writer, outFileName);
22738                     writer.close();
22740                     //Not sure how better to do this, but right now the .map file
22741                     //leaks the full OS path in the "file" property. Manually
22742                     //modify it to not do that.
22743                     file.saveFile(outFileNameMap,
22744                         file.readFile(outFileNameMap).replace(mapRegExp, '"file":"' + baseName + '"'));
22746                     fileContents = optimized + "\n//# sourceMappingURL=" + outBaseName + ".map";
22747                 } else {
22748                     fileContents = optimized;
22749                 }
22750                 return fileContents;
22751             } else {
22752                 throw new Error('Cannot closure compile file: ' + fileName + '. Skipping it.');
22753             }
22755             return fileContents;
22756         }
22757     };
22759     return optimize;
22763 if(env === 'xpconnect') {
22764 define('xpconnect/optimize', {});
22767  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22768  * Available via the MIT or new BSD license.
22769  * see: http://github.com/jrburke/requirejs for details
22770  */
22772 /*jslint plusplus: true, nomen: true, regexp: true */
22773 /*global define: false */
22775 define('optimize', [ 'lang', 'logger', 'env!env/optimize', 'env!env/file', 'parse',
22776          'pragma', 'uglifyjs/index', 'uglifyjs2',
22777          'source-map'],
22778 function (lang,   logger,   envOptimize,        file,           parse,
22779           pragma, uglify,             uglify2,
22780           sourceMap) {
22781     'use strict';
22783     var optimize,
22784         cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/ig,
22785         cssCommentImportRegExp = /\/\*[^\*]*@import[^\*]*\*\//g,
22786         cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g,
22787         SourceMapGenerator = sourceMap.SourceMapGenerator,
22788         SourceMapConsumer =sourceMap.SourceMapConsumer;
22790     /**
22791      * If an URL from a CSS url value contains start/end quotes, remove them.
22792      * This is not done in the regexp, since my regexp fu is not that strong,
22793      * and the CSS spec allows for ' and " in the URL if they are backslash escaped.
22794      * @param {String} url
22795      */
22796     function cleanCssUrlQuotes(url) {
22797         //Make sure we are not ending in whitespace.
22798         //Not very confident of the css regexps above that there will not be ending
22799         //whitespace.
22800         url = url.replace(/\s+$/, "");
22802         if (url.charAt(0) === "'" || url.charAt(0) === "\"") {
22803             url = url.substring(1, url.length - 1);
22804         }
22806         return url;
22807     }
22809     /**
22810      * Inlines nested stylesheets that have @import calls in them.
22811      * @param {String} fileName the file name
22812      * @param {String} fileContents the file contents
22813      * @param {String} cssImportIgnore comma delimited string of files to ignore
22814      * @param {String} cssPrefix string to be prefixed before relative URLs
22815      * @param {Object} included an object used to track the files already imported
22816      */
22817     function flattenCss(fileName, fileContents, cssImportIgnore, cssPrefix, included) {
22818         //Find the last slash in the name.
22819         fileName = fileName.replace(lang.backSlashRegExp, "/");
22820         var endIndex = fileName.lastIndexOf("/"),
22821             //Make a file path based on the last slash.
22822             //If no slash, so must be just a file name. Use empty string then.
22823             filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "",
22824             //store a list of merged files
22825             importList = [],
22826             skippedList = [];
22828         //First make a pass by removing an commented out @import calls.
22829         fileContents = fileContents.replace(cssCommentImportRegExp, '');
22831         //Make sure we have a delimited ignore list to make matching faster
22832         if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") {
22833             cssImportIgnore += ",";
22834         }
22836         fileContents = fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) {
22837             //Only process media type "all" or empty media type rules.
22838             if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) {
22839                 skippedList.push(fileName);
22840                 return fullMatch;
22841             }
22843             importFileName = cleanCssUrlQuotes(importFileName);
22845             //Ignore the file import if it is part of an ignore list.
22846             if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) {
22847                 return fullMatch;
22848             }
22850             //Make sure we have a unix path for the rest of the operation.
22851             importFileName = importFileName.replace(lang.backSlashRegExp, "/");
22853             try {
22854                 //if a relative path, then tack on the filePath.
22855                 //If it is not a relative path, then the readFile below will fail,
22856                 //and we will just skip that import.
22857                 var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName,
22858                     importContents = file.readFile(fullImportFileName), i,
22859                     importEndIndex, importPath, fixedUrlMatch, colonIndex, parts, flat;
22861                 //Skip the file if it has already been included.
22862                 if (included[fullImportFileName]) {
22863                     return '';
22864                 }
22865                 included[fullImportFileName] = true;
22867                 //Make sure to flatten any nested imports.
22868                 flat = flattenCss(fullImportFileName, importContents, cssImportIgnore, cssPrefix, included);
22869                 importContents = flat.fileContents;
22871                 if (flat.importList.length) {
22872                     importList.push.apply(importList, flat.importList);
22873                 }
22874                 if (flat.skippedList.length) {
22875                     skippedList.push.apply(skippedList, flat.skippedList);
22876                 }
22878                 //Make the full import path
22879                 importEndIndex = importFileName.lastIndexOf("/");
22881                 //Make a file path based on the last slash.
22882                 //If no slash, so must be just a file name. Use empty string then.
22883                 importPath = (importEndIndex !== -1) ? importFileName.substring(0, importEndIndex + 1) : "";
22885                 //fix url() on relative import (#5)
22886                 importPath = importPath.replace(/^\.\//, '');
22888                 //Modify URL paths to match the path represented by this file.
22889                 importContents = importContents.replace(cssUrlRegExp, function (fullMatch, urlMatch) {
22890                     fixedUrlMatch = cleanCssUrlQuotes(urlMatch);
22891                     fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/");
22893                     //Only do the work for relative URLs. Skip things that start with / or have
22894                     //a protocol.
22895                     colonIndex = fixedUrlMatch.indexOf(":");
22896                     if (fixedUrlMatch.charAt(0) !== "/" && (colonIndex === -1 || colonIndex > fixedUrlMatch.indexOf("/"))) {
22897                         //It is a relative URL, tack on the cssPrefix and path prefix
22898                         urlMatch = cssPrefix + importPath + fixedUrlMatch;
22900                     } else {
22901                         logger.trace(importFileName + "\n  URL not a relative URL, skipping: " + urlMatch);
22902                     }
22904                     //Collapse .. and .
22905                     parts = urlMatch.split("/");
22906                     for (i = parts.length - 1; i > 0; i--) {
22907                         if (parts[i] === ".") {
22908                             parts.splice(i, 1);
22909                         } else if (parts[i] === "..") {
22910                             if (i !== 0 && parts[i - 1] !== "..") {
22911                                 parts.splice(i - 1, 2);
22912                                 i -= 1;
22913                             }
22914                         }
22915                     }
22917                     return "url(" + parts.join("/") + ")";
22918                 });
22920                 importList.push(fullImportFileName);
22921                 return importContents;
22922             } catch (e) {
22923                 logger.warn(fileName + "\n  Cannot inline css import, skipping: " + importFileName);
22924                 return fullMatch;
22925             }
22926         });
22928         return {
22929             importList : importList,
22930             skippedList: skippedList,
22931             fileContents : fileContents
22932         };
22933     }
22935     optimize = {
22936         /**
22937          * Optimizes a file that contains JavaScript content. Optionally collects
22938          * plugin resources mentioned in a file, and then passes the content
22939          * through an minifier if one is specified via config.optimize.
22940          *
22941          * @param {String} fileName the name of the file to optimize
22942          * @param {String} fileContents the contents to optimize. If this is
22943          * a null value, then fileName will be used to read the fileContents.
22944          * @param {String} outFileName the name of the file to use for the
22945          * saved optimized content.
22946          * @param {Object} config the build config object.
22947          * @param {Array} [pluginCollector] storage for any plugin resources
22948          * found.
22949          */
22950         jsFile: function (fileName, fileContents, outFileName, config, pluginCollector) {
22951             if (!fileContents) {
22952                 fileContents = file.readFile(fileName);
22953             }
22955             fileContents = optimize.js(fileName, fileContents, outFileName, config, pluginCollector);
22957             file.saveUtf8File(outFileName, fileContents);
22958         },
22960         /**
22961          * Optimizes a file that contains JavaScript content. Optionally collects
22962          * plugin resources mentioned in a file, and then passes the content
22963          * through an minifier if one is specified via config.optimize.
22964          *
22965          * @param {String} fileName the name of the file that matches the
22966          * fileContents.
22967          * @param {String} fileContents the string of JS to optimize.
22968          * @param {Object} [config] the build config object.
22969          * @param {Array} [pluginCollector] storage for any plugin resources
22970          * found.
22971          */
22972         js: function (fileName, fileContents, outFileName, config, pluginCollector) {
22973             var optFunc, optConfig,
22974                 parts = (String(config.optimize)).split('.'),
22975                 optimizerName = parts[0],
22976                 keepLines = parts[1] === 'keepLines',
22977                 licenseContents = '';
22979             config = config || {};
22981             //Apply pragmas/namespace renaming
22982             fileContents = pragma.process(fileName, fileContents, config, 'OnSave', pluginCollector);
22984             //Optimize the JS files if asked.
22985             if (optimizerName && optimizerName !== 'none') {
22986                 optFunc = envOptimize[optimizerName] || optimize.optimizers[optimizerName];
22987                 if (!optFunc) {
22988                     throw new Error('optimizer with name of "' +
22989                                     optimizerName +
22990                                     '" not found for this environment');
22991                 }
22993                 optConfig = config[optimizerName] || {};
22994                 if (config.generateSourceMaps) {
22995                     optConfig.generateSourceMaps = !!config.generateSourceMaps;
22996                 }
22998                 try {
22999                     if (config.preserveLicenseComments) {
23000                         //Pull out any license comments for prepending after optimization.
23001                         try {
23002                             licenseContents = parse.getLicenseComments(fileName, fileContents);
23003                         } catch (e) {
23004                             throw new Error('Cannot parse file: ' + fileName + ' for comments. Skipping it. Error is:\n' + e.toString());
23005                         }
23006                     }
23008                     fileContents = licenseContents + optFunc(fileName,
23009                                                              fileContents,
23010                                                              outFileName,
23011                                                              keepLines,
23012                                                              optConfig);
23013                 } catch (e) {
23014                     if (config.throwWhen && config.throwWhen.optimize) {
23015                         throw e;
23016                     } else {
23017                         logger.error(e);
23018                     }
23019                 }
23020             }
23022             return fileContents;
23023         },
23025         /**
23026          * Optimizes one CSS file, inlining @import calls, stripping comments, and
23027          * optionally removes line returns.
23028          * @param {String} fileName the path to the CSS file to optimize
23029          * @param {String} outFileName the path to save the optimized file.
23030          * @param {Object} config the config object with the optimizeCss and
23031          * cssImportIgnore options.
23032          */
23033         cssFile: function (fileName, outFileName, config) {
23035             //Read in the file. Make sure we have a JS string.
23036             var originalFileContents = file.readFile(fileName),
23037                 flat = flattenCss(fileName, originalFileContents, config.cssImportIgnore, config.cssPrefix, {}),
23038                 //Do not use the flattened CSS if there was one that was skipped.
23039                 fileContents = flat.skippedList.length ? originalFileContents : flat.fileContents,
23040                 startIndex, endIndex, buildText, comment;
23042             if (flat.skippedList.length) {
23043                 logger.warn('Cannot inline @imports for ' + fileName +
23044                             ',\nthe following files had media queries in them:\n' +
23045                             flat.skippedList.join('\n'));
23046             }
23048             //Do comment removal.
23049             try {
23050                 if (config.optimizeCss.indexOf(".keepComments") === -1) {
23051                     startIndex = 0;
23052                     //Get rid of comments.
23053                     while ((startIndex = fileContents.indexOf("/*", startIndex)) !== -1) {
23054                         endIndex = fileContents.indexOf("*/", startIndex + 2);
23055                         if (endIndex === -1) {
23056                             throw "Improper comment in CSS file: " + fileName;
23057                         }
23058                         comment = fileContents.substring(startIndex, endIndex);
23060                         if (config.preserveLicenseComments &&
23061                             (comment.indexOf('license') !== -1 ||
23062                              comment.indexOf('opyright') !== -1 ||
23063                              comment.indexOf('(c)') !== -1)) {
23064                             //Keep the comment, just increment the startIndex
23065                             startIndex = endIndex;
23066                         } else {
23067                             fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length);
23068                             startIndex = 0;
23069                         }
23070                     }
23071                 }
23072                 //Get rid of newlines.
23073                 if (config.optimizeCss.indexOf(".keepLines") === -1) {
23074                     fileContents = fileContents.replace(/[\r\n]/g, "");
23075                     fileContents = fileContents.replace(/\s+/g, " ");
23076                     fileContents = fileContents.replace(/\{\s/g, "{");
23077                     fileContents = fileContents.replace(/\s\}/g, "}");
23078                 } else {
23079                     //Remove multiple empty lines.
23080                     fileContents = fileContents.replace(/(\r\n)+/g, "\r\n");
23081                     fileContents = fileContents.replace(/(\n)+/g, "\n");
23082                 }
23083             } catch (e) {
23084                 fileContents = originalFileContents;
23085                 logger.error("Could not optimized CSS file: " + fileName + ", error: " + e);
23086             }
23088             file.saveUtf8File(outFileName, fileContents);
23090             //text output to stdout and/or written to build.txt file
23091             buildText = "\n"+ outFileName.replace(config.dir, "") +"\n----------------\n";
23092             flat.importList.push(fileName);
23093             buildText += flat.importList.map(function(path){
23094                 return path.replace(config.dir, "");
23095             }).join("\n");
23097             return {
23098                 importList: flat.importList,
23099                 buildText: buildText +"\n"
23100             };
23101         },
23103         /**
23104          * Optimizes CSS files, inlining @import calls, stripping comments, and
23105          * optionally removes line returns.
23106          * @param {String} startDir the path to the top level directory
23107          * @param {Object} config the config object with the optimizeCss and
23108          * cssImportIgnore options.
23109          */
23110         css: function (startDir, config) {
23111             var buildText = "",
23112                 importList = [],
23113                 shouldRemove = config.dir && config.removeCombined,
23114                 i, fileName, result, fileList;
23115             if (config.optimizeCss.indexOf("standard") !== -1) {
23116                 fileList = file.getFilteredFileList(startDir, /\.css$/, true);
23117                 if (fileList) {
23118                     for (i = 0; i < fileList.length; i++) {
23119                         fileName = fileList[i];
23120                         logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName);
23121                         result = optimize.cssFile(fileName, fileName, config);
23122                         buildText += result.buildText;
23123                         if (shouldRemove) {
23124                             result.importList.pop();
23125                             importList = importList.concat(result.importList);
23126                         }
23127                     }
23128                 }
23130                 if (shouldRemove) {
23131                     importList.forEach(function (path) {
23132                         if (file.exists(path)) {
23133                             file.deleteFile(path);
23134                         }
23135                     });
23136                 }
23137             }
23138             return buildText;
23139         },
23141         optimizers: {
23142             uglify: function (fileName, fileContents, outFileName, keepLines, config) {
23143                 var parser = uglify.parser,
23144                     processor = uglify.uglify,
23145                     ast, errMessage, errMatch;
23147                 config = config || {};
23149                 logger.trace("Uglifying file: " + fileName);
23151                 try {
23152                     ast = parser.parse(fileContents, config.strict_semicolons);
23153                     if (config.no_mangle !== true) {
23154                         ast = processor.ast_mangle(ast, config);
23155                     }
23156                     ast = processor.ast_squeeze(ast, config);
23158                     fileContents = processor.gen_code(ast, config);
23160                     if (config.max_line_length) {
23161                         fileContents = processor.split_lines(fileContents, config.max_line_length);
23162                     }
23164                     //Add trailing semicolon to match uglifyjs command line version
23165                     fileContents += ';';
23166                 } catch (e) {
23167                     errMessage = e.toString();
23168                     errMatch = /\nError(\r)?\n/.exec(errMessage);
23169                     if (errMatch) {
23170                         errMessage = errMessage.substring(0, errMatch.index);
23171                     }
23172                     throw new Error('Cannot uglify file: ' + fileName + '. Skipping it. Error is:\n' + errMessage);
23173                 }
23174                 return fileContents;
23175             },
23176             uglify2: function (fileName, fileContents, outFileName, keepLines, config) {
23177                 var result, existingMap, resultMap, finalMap, sourceIndex,
23178                     uconfig = {},
23179                     existingMapPath = outFileName + '.map',
23180                     baseName = fileName && fileName.split('/').pop();
23182                 config = config || {};
23184                 lang.mixin(uconfig, config, true);
23186                 uconfig.fromString = true;
23188                 if (config.generateSourceMaps && outFileName) {
23189                     uconfig.outSourceMap = baseName;
23191                     if (file.exists(existingMapPath)) {
23192                         uconfig.inSourceMap = existingMapPath;
23193                         existingMap = JSON.parse(file.readFile(existingMapPath));
23194                     }
23195                 }
23197                 logger.trace("Uglify2 file: " + fileName);
23199                 try {
23200                     //var tempContents = fileContents.replace(/\/\/\# sourceMappingURL=.*$/, '');
23201                     result = uglify2.minify(fileContents, uconfig, baseName + '.src.js');
23202                     if (uconfig.outSourceMap && result.map) {
23203                         resultMap = result.map;
23204                         if (existingMap) {
23205                             resultMap = JSON.parse(resultMap);
23206                             finalMap = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(resultMap));
23207                             finalMap.applySourceMap(new SourceMapConsumer(existingMap));
23208                             resultMap = finalMap.toString();
23209                         } else {
23210                             file.saveFile(outFileName + '.src.js', fileContents);
23211                         }
23212                         file.saveFile(outFileName + '.map', resultMap);
23213                         fileContents = result.code + "\n//# sourceMappingURL=" + baseName + ".map";
23214                     } else {
23215                         fileContents = result.code;
23216                     }
23217                 } catch (e) {
23218                     throw new Error('Cannot uglify2 file: ' + fileName + '. Skipping it. Error is:\n' + e.toString());
23219                 }
23220                 return fileContents;
23221             }
23222         }
23223     };
23225     return optimize;
23228  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
23229  * Available via the MIT or new BSD license.
23230  * see: http://github.com/jrburke/requirejs for details
23231  */
23233  * This file patches require.js to communicate with the build system.
23234  */
23236 //Using sloppy since this uses eval for some code like plugins,
23237 //which may not be strict mode compliant. So if use strict is used
23238 //below they will have strict rules applied and may cause an error.
23239 /*jslint sloppy: true, nomen: true, plusplus: true, regexp: true */
23240 /*global require, define: true */
23242 //NOT asking for require as a dependency since the goal is to modify the
23243 //global require below
23244 define('requirePatch', [ 'env!env/file', 'pragma', 'parse', 'lang', 'logger', 'commonJs', 'prim'], function (
23245     file,
23246     pragma,
23247     parse,
23248     lang,
23249     logger,
23250     commonJs,
23251     prim
23252 ) {
23254     var allowRun = true,
23255         hasProp = lang.hasProp,
23256         falseProp = lang.falseProp,
23257         getOwn = lang.getOwn;
23259     //This method should be called when the patches to require should take hold.
23260     return function () {
23261         if (!allowRun) {
23262             return;
23263         }
23264         allowRun = false;
23266         var layer,
23267             pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/,
23268             oldNewContext = require.s.newContext,
23269             oldDef,
23271             //create local undefined values for module and exports,
23272             //so that when files are evaled in this function they do not
23273             //see the node values used for r.js
23274             exports,
23275             module;
23277         /**
23278          * Reset "global" build caches that are kept around between
23279          * build layer builds. Useful to do when there are multiple
23280          * top level requirejs.optimize() calls.
23281          */
23282         require._cacheReset = function () {
23283             //Stored raw text caches, used by browser use.
23284             require._cachedRawText = {};
23285             //Stored cached file contents for reuse in other layers.
23286             require._cachedFileContents = {};
23287             //Store which cached files contain a require definition.
23288             require._cachedDefinesRequireUrls = {};
23289         };
23290         require._cacheReset();
23292         /**
23293          * Makes sure the URL is something that can be supported by the
23294          * optimization tool.
23295          * @param {String} url
23296          * @returns {Boolean}
23297          */
23298         require._isSupportedBuildUrl = function (url) {
23299             //Ignore URLs with protocols, hosts or question marks, means either network
23300             //access is needed to fetch it or it is too dynamic. Note that
23301             //on Windows, full paths are used for some urls, which include
23302             //the drive, like c:/something, so need to test for something other
23303             //than just a colon.
23304             if (url.indexOf("://") === -1 && url.indexOf("?") === -1 &&
23305                     url.indexOf('empty:') !== 0 && url.indexOf('//') !== 0) {
23306                 return true;
23307             } else {
23308                 if (!layer.ignoredUrls[url]) {
23309                     if (url.indexOf('empty:') === -1) {
23310                         logger.info('Cannot optimize network URL, skipping: ' + url);
23311                     }
23312                     layer.ignoredUrls[url] = true;
23313                 }
23314                 return false;
23315             }
23316         };
23318         function normalizeUrlWithBase(context, moduleName, url) {
23319             //Adjust the URL if it was not transformed to use baseUrl.
23320             if (require.jsExtRegExp.test(moduleName)) {
23321                 url = (context.config.dir || context.config.dirBaseUrl) + url;
23322             }
23323             return url;
23324         }
23326         //Overrides the new context call to add existing tracking features.
23327         require.s.newContext = function (name) {
23328             var context = oldNewContext(name),
23329                 oldEnable = context.enable,
23330                 moduleProto = context.Module.prototype,
23331                 oldInit = moduleProto.init,
23332                 oldCallPlugin = moduleProto.callPlugin;
23334             //Only do this for the context used for building.
23335             if (name === '_') {
23336                 //For build contexts, do everything sync
23337                 context.nextTick = function (fn) {
23338                     fn();
23339                 };
23341                 context.needFullExec = {};
23342                 context.fullExec = {};
23343                 context.plugins = {};
23344                 context.buildShimExports = {};
23346                 //Override the shim exports function generator to just
23347                 //spit out strings that can be used in the stringified
23348                 //build output.
23349                 context.makeShimExports = function (value) {
23350                     function fn() {
23351                         return '(function (global) {\n' +
23352                             '    return function () {\n' +
23353                             '        var ret, fn;\n' +
23354                             (value.init ?
23355                                     ('       fn = ' + value.init.toString() + ';\n' +
23356                                     '        ret = fn.apply(global, arguments);\n') : '') +
23357                             (value.exports ?
23358                                     '        return ret || global.' + value.exports + ';\n' :
23359                                     '        return ret;\n') +
23360                             '    };\n' +
23361                             '}(this))';
23362                     }
23364                     return fn;
23365                 };
23367                 context.enable = function (depMap, parent) {
23368                     var id = depMap.id,
23369                         parentId = parent && parent.map.id,
23370                         needFullExec = context.needFullExec,
23371                         fullExec = context.fullExec,
23372                         mod = getOwn(context.registry, id);
23374                     if (mod && !mod.defined) {
23375                         if (parentId && getOwn(needFullExec, parentId)) {
23376                             needFullExec[id] = true;
23377                         }
23379                     } else if ((getOwn(needFullExec, id) && falseProp(fullExec, id)) ||
23380                                (parentId && getOwn(needFullExec, parentId) &&
23381                                 falseProp(fullExec, id))) {
23382                         context.require.undef(id);
23383                     }
23385                     return oldEnable.apply(context, arguments);
23386                 };
23388                 //Override load so that the file paths can be collected.
23389                 context.load = function (moduleName, url) {
23390                     /*jslint evil: true */
23391                     var contents, pluginBuilderMatch, builderName,
23392                         shim, shimExports;
23394                     //Do not mark the url as fetched if it is
23395                     //not an empty: URL, used by the optimizer.
23396                     //In that case we need to be sure to call
23397                     //load() for each module that is mapped to
23398                     //empty: so that dependencies are satisfied
23399                     //correctly.
23400                     if (url.indexOf('empty:') === 0) {
23401                         delete context.urlFetched[url];
23402                     }
23404                     //Only handle urls that can be inlined, so that means avoiding some
23405                     //URLs like ones that require network access or may be too dynamic,
23406                     //like JSONP
23407                     if (require._isSupportedBuildUrl(url)) {
23408                         //Adjust the URL if it was not transformed to use baseUrl.
23409                         url = normalizeUrlWithBase(context, moduleName, url);
23411                         //Save the module name to path  and path to module name mappings.
23412                         layer.buildPathMap[moduleName] = url;
23413                         layer.buildFileToModule[url] = moduleName;
23415                         if (hasProp(context.plugins, moduleName)) {
23416                             //plugins need to have their source evaled as-is.
23417                             context.needFullExec[moduleName] = true;
23418                         }
23420                         prim().start(function () {
23421                             if (hasProp(require._cachedFileContents, url) &&
23422                                     (falseProp(context.needFullExec, moduleName) ||
23423                                     getOwn(context.fullExec, moduleName))) {
23424                                 contents = require._cachedFileContents[url];
23426                                 //If it defines require, mark it so it can be hoisted.
23427                                 //Done here and in the else below, before the
23428                                 //else block removes code from the contents.
23429                                 //Related to #263
23430                                 if (!layer.existingRequireUrl && require._cachedDefinesRequireUrls[url]) {
23431                                     layer.existingRequireUrl = url;
23432                                 }
23433                             } else {
23434                                 //Load the file contents, process for conditionals, then
23435                                 //evaluate it.
23436                                 return require._cacheReadAsync(url).then(function (text) {
23437                                     contents = text;
23439                                     if (context.config.cjsTranslate &&
23440                                         (!context.config.shim || !lang.hasProp(context.config.shim, moduleName))) {
23441                                         contents = commonJs.convert(url, contents);
23442                                     }
23444                                     //If there is a read filter, run it now.
23445                                     if (context.config.onBuildRead) {
23446                                         contents = context.config.onBuildRead(moduleName, url, contents);
23447                                     }
23449                                     contents = pragma.process(url, contents, context.config, 'OnExecute');
23451                                     //Find out if the file contains a require() definition. Need to know
23452                                     //this so we can inject plugins right after it, but before they are needed,
23453                                     //and to make sure this file is first, so that define calls work.
23454                                     try {
23455                                         if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) {
23456                                             layer.existingRequireUrl = url;
23457                                             require._cachedDefinesRequireUrls[url] = true;
23458                                         }
23459                                     } catch (e1) {
23460                                         throw new Error('Parse error using esprima ' +
23461                                                         'for file: ' + url + '\n' + e1);
23462                                     }
23463                                 }).then(function () {
23464                                     if (hasProp(context.plugins, moduleName)) {
23465                                         //This is a loader plugin, check to see if it has a build extension,
23466                                         //otherwise the plugin will act as the plugin builder too.
23467                                         pluginBuilderMatch = pluginBuilderRegExp.exec(contents);
23468                                         if (pluginBuilderMatch) {
23469                                             //Load the plugin builder for the plugin contents.
23470                                             builderName = context.makeModuleMap(pluginBuilderMatch[3],
23471                                                                                 context.makeModuleMap(moduleName),
23472                                                                                 null,
23473                                                                                 true).id;
23474                                             return require._cacheReadAsync(context.nameToUrl(builderName));
23475                                         }
23476                                     }
23477                                     return contents;
23478                                 }).then(function (text) {
23479                                     contents = text;
23481                                     //Parse out the require and define calls.
23482                                     //Do this even for plugins in case they have their own
23483                                     //dependencies that may be separate to how the pluginBuilder works.
23484                                     try {
23485                                         if (falseProp(context.needFullExec, moduleName)) {
23486                                             contents = parse(moduleName, url, contents, {
23487                                                 insertNeedsDefine: true,
23488                                                 has: context.config.has,
23489                                                 findNestedDependencies: context.config.findNestedDependencies
23490                                             });
23491                                         }
23492                                     } catch (e2) {
23493                                         throw new Error('Parse error using esprima ' +
23494                                                         'for file: ' + url + '\n' + e2);
23495                                     }
23497                                     require._cachedFileContents[url] = contents;
23498                                 });
23499                             }
23500                         }).then(function () {
23501                             if (contents) {
23502                                 eval(contents);
23503                             }
23505                             try {
23506                                 //If have a string shim config, and this is
23507                                 //a fully executed module, try to see if
23508                                 //it created a variable in this eval scope
23509                                 if (getOwn(context.needFullExec, moduleName)) {
23510                                     shim = getOwn(context.config.shim, moduleName);
23511                                     if (shim && shim.exports) {
23512                                         shimExports = eval(shim.exports);
23513                                         if (typeof shimExports !== 'undefined') {
23514                                             context.buildShimExports[moduleName] = shimExports;
23515                                         }
23516                                     }
23517                                 }
23519                                 //Need to close out completion of this module
23520                                 //so that listeners will get notified that it is available.
23521                                 context.completeLoad(moduleName);
23522                             } catch (e) {
23523                                 //Track which module could not complete loading.
23524                                 if (!e.moduleTree) {
23525                                     e.moduleTree = [];
23526                                 }
23527                                 e.moduleTree.push(moduleName);
23528                                 throw e;
23529                             }
23530                         }).then(null, function (eOuter) {
23532                             if (!eOuter.fileName) {
23533                                 eOuter.fileName = url;
23534                             }
23535                             throw eOuter;
23536                         }).end();
23537                     } else {
23538                         //With unsupported URLs still need to call completeLoad to
23539                         //finish loading.
23540                         context.completeLoad(moduleName);
23541                     }
23542                 };
23544                 //Marks module has having a name, and optionally executes the
23545                 //callback, but only if it meets certain criteria.
23546                 context.execCb = function (name, cb, args, exports) {
23547                     var buildShimExports = getOwn(layer.context.buildShimExports, name);
23549                     if (buildShimExports) {
23550                         return buildShimExports;
23551                     } else if (cb.__requireJsBuild || getOwn(layer.context.needFullExec, name)) {
23552                         return cb.apply(exports, args);
23553                     }
23554                     return undefined;
23555                 };
23557                 moduleProto.init = function (depMaps) {
23558                     if (context.needFullExec[this.map.id]) {
23559                         lang.each(depMaps, lang.bind(this, function (depMap) {
23560                             if (typeof depMap === 'string') {
23561                                 depMap = context.makeModuleMap(depMap,
23562                                                (this.map.isDefine ? this.map : this.map.parentMap));
23563                             }
23565                             if (!context.fullExec[depMap.id]) {
23566                                 context.require.undef(depMap.id);
23567                             }
23568                         }));
23569                     }
23571                     return oldInit.apply(this, arguments);
23572                 };
23574                 moduleProto.callPlugin = function () {
23575                     var map = this.map,
23576                         pluginMap = context.makeModuleMap(map.prefix),
23577                         pluginId = pluginMap.id,
23578                         pluginMod = getOwn(context.registry, pluginId);
23580                     context.plugins[pluginId] = true;
23581                     context.needFullExec[pluginId] = true;
23583                     //If the module is not waiting to finish being defined,
23584                     //undef it and start over, to get full execution.
23585                     if (falseProp(context.fullExec, pluginId) && (!pluginMod || pluginMod.defined)) {
23586                         context.require.undef(pluginMap.id);
23587                     }
23589                     return oldCallPlugin.apply(this, arguments);
23590                 };
23591             }
23593             return context;
23594         };
23596         //Clear up the existing context so that the newContext modifications
23597         //above will be active.
23598         delete require.s.contexts._;
23600         /** Reset state for each build layer pass. */
23601         require._buildReset = function () {
23602             var oldContext = require.s.contexts._;
23604             //Clear up the existing context.
23605             delete require.s.contexts._;
23607             //Set up new context, so the layer object can hold onto it.
23608             require({});
23610             layer = require._layer = {
23611                 buildPathMap: {},
23612                 buildFileToModule: {},
23613                 buildFilePaths: [],
23614                 pathAdded: {},
23615                 modulesWithNames: {},
23616                 needsDefine: {},
23617                 existingRequireUrl: "",
23618                 ignoredUrls: {},
23619                 context: require.s.contexts._
23620             };
23622             //Return the previous context in case it is needed, like for
23623             //the basic config object.
23624             return oldContext;
23625         };
23627         require._buildReset();
23629         //Override define() to catch modules that just define an object, so that
23630         //a dummy define call is not put in the build file for them. They do
23631         //not end up getting defined via context.execCb, so we need to catch them
23632         //at the define call.
23633         oldDef = define;
23635         //This function signature does not have to be exact, just match what we
23636         //are looking for.
23637         define = function (name) {
23638             if (typeof name === "string" && falseProp(layer.needsDefine, name)) {
23639                 layer.modulesWithNames[name] = true;
23640             }
23641             return oldDef.apply(require, arguments);
23642         };
23644         define.amd = oldDef.amd;
23646         //Add some utilities for plugins
23647         require._readFile = file.readFile;
23648         require._fileExists = function (path) {
23649             return file.exists(path);
23650         };
23652         //Called when execManager runs for a dependency. Used to figure out
23653         //what order of execution.
23654         require.onResourceLoad = function (context, map) {
23655             var id = map.id,
23656                 url;
23658             //If build needed a full execution, indicate it
23659             //has been done now. But only do it if the context is tracking
23660             //that. Only valid for the context used in a build, not for
23661             //other contexts being run, like for useLib, plain requirejs
23662             //use in node/rhino.
23663             if (context.needFullExec && getOwn(context.needFullExec, id)) {
23664                 context.fullExec[id] = true;
23665             }
23667             //A plugin.
23668             if (map.prefix) {
23669                 if (falseProp(layer.pathAdded, id)) {
23670                     layer.buildFilePaths.push(id);
23671                     //For plugins the real path is not knowable, use the name
23672                     //for both module to file and file to module mappings.
23673                     layer.buildPathMap[id] = id;
23674                     layer.buildFileToModule[id] = id;
23675                     layer.modulesWithNames[id] = true;
23676                     layer.pathAdded[id] = true;
23677                 }
23678             } else if (map.url && require._isSupportedBuildUrl(map.url)) {
23679                 //If the url has not been added to the layer yet, and it
23680                 //is from an actual file that was loaded, add it now.
23681                 url = normalizeUrlWithBase(context, id, map.url);
23682                 if (!layer.pathAdded[url] && getOwn(layer.buildPathMap, id)) {
23683                     //Remember the list of dependencies for this layer.
23684                     layer.buildFilePaths.push(url);
23685                     layer.pathAdded[url] = true;
23686                 }
23687             }
23688         };
23690         //Called by output of the parse() function, when a file does not
23691         //explicitly call define, probably just require, but the parse()
23692         //function normalizes on define() for dependency mapping and file
23693         //ordering works correctly.
23694         require.needsDefine = function (moduleName) {
23695             layer.needsDefine[moduleName] = true;
23696         };
23697     };
23700  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
23701  * Available via the MIT or new BSD license.
23702  * see: http://github.com/jrburke/requirejs for details
23703  */
23705 /*jslint */
23706 /*global define: false, console: false */
23708 define('commonJs', ['env!env/file', 'parse'], function (file, parse) {
23709     'use strict';
23710     var commonJs = {
23711         //Set to false if you do not want this file to log. Useful in environments
23712         //like node where you want the work to happen without noise.
23713         useLog: true,
23715         convertDir: function (commonJsPath, savePath) {
23716             var fileList, i,
23717                 jsFileRegExp = /\.js$/,
23718                 fileName, convertedFileName, fileContents;
23720             //Get list of files to convert.
23721             fileList = file.getFilteredFileList(commonJsPath, /\w/, true);
23723             //Normalize on front slashes and make sure the paths do not end in a slash.
23724             commonJsPath = commonJsPath.replace(/\\/g, "/");
23725             savePath = savePath.replace(/\\/g, "/");
23726             if (commonJsPath.charAt(commonJsPath.length - 1) === "/") {
23727                 commonJsPath = commonJsPath.substring(0, commonJsPath.length - 1);
23728             }
23729             if (savePath.charAt(savePath.length - 1) === "/") {
23730                 savePath = savePath.substring(0, savePath.length - 1);
23731             }
23733             //Cycle through all the JS files and convert them.
23734             if (!fileList || !fileList.length) {
23735                 if (commonJs.useLog) {
23736                     if (commonJsPath === "convert") {
23737                         //A request just to convert one file.
23738                         console.log('\n\n' + commonJs.convert(savePath, file.readFile(savePath)));
23739                     } else {
23740                         console.log("No files to convert in directory: " + commonJsPath);
23741                     }
23742                 }
23743             } else {
23744                 for (i = 0; i < fileList.length; i++) {
23745                     fileName = fileList[i];
23746                     convertedFileName = fileName.replace(commonJsPath, savePath);
23748                     //Handle JS files.
23749                     if (jsFileRegExp.test(fileName)) {
23750                         fileContents = file.readFile(fileName);
23751                         fileContents = commonJs.convert(fileName, fileContents);
23752                         file.saveUtf8File(convertedFileName, fileContents);
23753                     } else {
23754                         //Just copy the file over.
23755                         file.copyFile(fileName, convertedFileName, true);
23756                     }
23757                 }
23758             }
23759         },
23761         /**
23762          * Does the actual file conversion.
23763          *
23764          * @param {String} fileName the name of the file.
23765          *
23766          * @param {String} fileContents the contents of a file :)
23767          *
23768          * @returns {String} the converted contents
23769          */
23770         convert: function (fileName, fileContents) {
23771             //Strip out comments.
23772             try {
23773                 var preamble = '',
23774                     commonJsProps = parse.usesCommonJs(fileName, fileContents);
23776                 //First see if the module is not already RequireJS-formatted.
23777                 if (parse.usesAmdOrRequireJs(fileName, fileContents) || !commonJsProps) {
23778                     return fileContents;
23779                 }
23781                 if (commonJsProps.dirname || commonJsProps.filename) {
23782                     preamble = 'var __filename = module.uri || "", ' +
23783                                '__dirname = __filename.substring(0, __filename.lastIndexOf("/") + 1); ';
23784                 }
23786                 //Construct the wrapper boilerplate.
23787                 fileContents = 'define(function (require, exports, module) {' +
23788                     preamble +
23789                     fileContents +
23790                     '\n});\n';
23792             } catch (e) {
23793                 console.log("commonJs.convert: COULD NOT CONVERT: " + fileName + ", so skipping it. Error was: " + e);
23794                 return fileContents;
23795             }
23797             return fileContents;
23798         }
23799     };
23801     return commonJs;
23804  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
23805  * Available via the MIT or new BSD license.
23806  * see: http://github.com/jrburke/requirejs for details
23807  */
23809 /*jslint plusplus: true, nomen: true, regexp: true  */
23810 /*global define, requirejs */
23813 define('build', function (require) {
23814     'use strict';
23816     var build, buildBaseConfig,
23817         lang = require('lang'),
23818         prim = require('prim'),
23819         logger = require('logger'),
23820         file = require('env!env/file'),
23821         parse = require('parse'),
23822         optimize = require('optimize'),
23823         pragma = require('pragma'),
23824         transform = require('transform'),
23825         requirePatch = require('requirePatch'),
23826         env = require('env'),
23827         commonJs = require('commonJs'),
23828         SourceMapGenerator = require('source-map/source-map-generator'),
23829         hasProp = lang.hasProp,
23830         getOwn = lang.getOwn,
23831         falseProp = lang.falseProp,
23832         endsWithSemiColonRegExp = /;\s*$/;
23834     prim.nextTick = function (fn) {
23835         fn();
23836     };
23838     //Now map require to the outermost requirejs, now that we have
23839     //local dependencies for this module. The rest of the require use is
23840     //manipulating the requirejs loader.
23841     require = requirejs;
23843     //Caching function for performance. Attached to
23844     //require so it can be reused in requirePatch.js. _cachedRawText
23845     //set up by requirePatch.js
23846     require._cacheReadAsync = function (path, encoding) {
23847         var d;
23849         if (lang.hasProp(require._cachedRawText, path)) {
23850             d = prim();
23851             d.resolve(require._cachedRawText[path]);
23852             return d.promise;
23853         } else {
23854             return file.readFileAsync(path, encoding).then(function (text) {
23855                 require._cachedRawText[path] = text;
23856                 return text;
23857             });
23858         }
23859     };
23861     buildBaseConfig = {
23862         appDir: "",
23863         pragmas: {},
23864         paths: {},
23865         optimize: "uglify",
23866         optimizeCss: "standard.keepLines",
23867         inlineText: true,
23868         isBuild: true,
23869         optimizeAllPluginResources: false,
23870         findNestedDependencies: false,
23871         preserveLicenseComments: true,
23872         //By default, all files/directories are copied, unless
23873         //they match this regexp, by default just excludes .folders
23874         dirExclusionRegExp: file.dirExclusionRegExp,
23875         _buildPathToModuleIndex: {}
23876     };
23878     /**
23879      * Some JS may not be valid if concatenated with other JS, in particular
23880      * the style of omitting semicolons and rely on ASI. Add a semicolon in
23881      * those cases.
23882      */
23883     function addSemiColon(text, config) {
23884         if (config.skipSemiColonInsertion || endsWithSemiColonRegExp.test(text)) {
23885             return text;
23886         } else {
23887             return text + ";";
23888         }
23889     }
23891     function endsWithSlash(dirName) {
23892         if (dirName.charAt(dirName.length - 1) !== "/") {
23893             dirName += "/";
23894         }
23895         return dirName;
23896     }
23898     //Method used by plugin writeFile calls, defined up here to avoid
23899     //jslint warning about "making a function in a loop".
23900     function makeWriteFile(namespace, layer) {
23901         function writeFile(name, contents) {
23902             logger.trace('Saving plugin-optimized file: ' + name);
23903             file.saveUtf8File(name, contents);
23904         }
23906         writeFile.asModule = function (moduleName, fileName, contents) {
23907             writeFile(fileName,
23908                 build.toTransport(namespace, moduleName, fileName, contents, layer));
23909         };
23911         return writeFile;
23912     }
23914     /**
23915      * Main API entry point into the build. The args argument can either be
23916      * an array of arguments (like the onese passed on a command-line),
23917      * or it can be a JavaScript object that has the format of a build profile
23918      * file.
23919      *
23920      * If it is an object, then in addition to the normal properties allowed in
23921      * a build profile file, the object should contain one other property:
23922      *
23923      * The object could also contain a "buildFile" property, which is a string
23924      * that is the file path to a build profile that contains the rest
23925      * of the build profile directives.
23926      *
23927      * This function does not return a status, it should throw an error if
23928      * there is a problem completing the build.
23929      */
23930     build = function (args) {
23931         var buildFile, cmdConfig, errorMsg, errorStack, stackMatch, errorTree,
23932             i, j, errorMod,
23933             stackRegExp = /( {4}at[^\n]+)\n/,
23934             standardIndent = '  ';
23936         return prim().start(function () {
23937             if (!args || lang.isArray(args)) {
23938                 if (!args || args.length < 1) {
23939                     logger.error("build.js buildProfile.js\n" +
23940                           "where buildProfile.js is the name of the build file (see example.build.js for hints on how to make a build file).");
23941                     return undefined;
23942                 }
23944                 //Next args can include a build file path as well as other build args.
23945                 //build file path comes first. If it does not contain an = then it is
23946                 //a build file path. Otherwise, just all build args.
23947                 if (args[0].indexOf("=") === -1) {
23948                     buildFile = args[0];
23949                     args.splice(0, 1);
23950                 }
23952                 //Remaining args are options to the build
23953                 cmdConfig = build.convertArrayToObject(args);
23954                 cmdConfig.buildFile = buildFile;
23955             } else {
23956                 cmdConfig = args;
23957             }
23959             return build._run(cmdConfig);
23960         }).then(null, function (e) {
23961             errorMsg = e.toString();
23962             errorTree = e.moduleTree;
23963             stackMatch = stackRegExp.exec(errorMsg);
23965             if (stackMatch) {
23966                 errorMsg += errorMsg.substring(0, stackMatch.index + stackMatch[0].length + 1);
23967             }
23969             //If a module tree that shows what module triggered the error,
23970             //print it out.
23971             if (errorTree && errorTree.length > 0) {
23972                 errorMsg += '\nIn module tree:\n';
23974                 for (i = errorTree.length - 1; i > -1; i--) {
23975                     errorMod = errorTree[i];
23976                     if (errorMod) {
23977                         for (j = errorTree.length - i; j > -1; j--) {
23978                             errorMsg += standardIndent;
23979                         }
23980                         errorMsg += errorMod + '\n';
23981                     }
23982                 }
23984                 logger.error(errorMsg);
23985             }
23987             errorStack = e.stack;
23989             if (typeof args === 'string' && args.indexOf('stacktrace=true') !== -1) {
23990                 errorMsg += '\n' + errorStack;
23991             } else {
23992                 if (!stackMatch && errorStack) {
23993                     //Just trim out the first "at" in the stack.
23994                     stackMatch = stackRegExp.exec(errorStack);
23995                     if (stackMatch) {
23996                         errorMsg += '\n' + stackMatch[0] || '';
23997                     }
23998                 }
23999             }
24001             throw new Error(errorMsg);
24002         });
24003     };
24005     build._run = function (cmdConfig) {
24006         var buildPaths, fileName, fileNames,
24007             paths, i,
24008             baseConfig, config,
24009             modules, srcPath, buildContext,
24010             destPath, moduleMap, parentModuleMap, context,
24011             resources, resource, plugin, fileContents,
24012             pluginProcessed = {},
24013             buildFileContents = "",
24014             pluginCollector = {};
24016         return prim().start(function () {
24017             var prop;
24019             //Can now run the patches to require.js to allow it to be used for
24020             //build generation. Do it here instead of at the top of the module
24021             //because we want normal require behavior to load the build tool
24022             //then want to switch to build mode.
24023             requirePatch();
24025             config = build.createConfig(cmdConfig);
24026             paths = config.paths;
24028             //Remove the previous build dir, in case it contains source transforms,
24029             //like the ones done with onBuildRead and onBuildWrite.
24030             if (config.dir && !config.keepBuildDir && file.exists(config.dir)) {
24031                 file.deleteFile(config.dir);
24032             }
24034             if (!config.out && !config.cssIn) {
24035                 //This is not just a one-off file build but a full build profile, with
24036                 //lots of files to process.
24038                 //First copy all the baseUrl content
24039                 file.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true);
24041                 //Adjust baseUrl if config.appDir is in play, and set up build output paths.
24042                 buildPaths = {};
24043                 if (config.appDir) {
24044                     //All the paths should be inside the appDir, so just adjust
24045                     //the paths to use the dirBaseUrl
24046                     for (prop in paths) {
24047                         if (hasProp(paths, prop)) {
24048                             buildPaths[prop] = paths[prop].replace(config.appDir, config.dir);
24049                         }
24050                     }
24051                 } else {
24052                     //If no appDir, then make sure to copy the other paths to this directory.
24053                     for (prop in paths) {
24054                         if (hasProp(paths, prop)) {
24055                             //Set up build path for each path prefix, but only do so
24056                             //if the path falls out of the current baseUrl
24057                             if (paths[prop].indexOf(config.baseUrl) === 0) {
24058                                 buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl);
24059                             } else {
24060                                 buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop.replace(/\./g, "/");
24062                                 //Make sure source path is fully formed with baseUrl,
24063                                 //if it is a relative URL.
24064                                 srcPath = paths[prop];
24065                                 if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) {
24066                                     srcPath = config.baseUrl + srcPath;
24067                                 }
24069                                 destPath = config.dirBaseUrl + buildPaths[prop];
24071                                 //Skip empty: paths
24072                                 if (srcPath !== 'empty:') {
24073                                     //If the srcPath is a directory, copy the whole directory.
24074                                     if (file.exists(srcPath) && file.isDirectory(srcPath)) {
24075                                         //Copy files to build area. Copy all files (the /\w/ regexp)
24076                                         file.copyDir(srcPath, destPath, /\w/, true);
24077                                     } else {
24078                                         //Try a .js extension
24079                                         srcPath += '.js';
24080                                         destPath += '.js';
24081                                         file.copyFile(srcPath, destPath);
24082                                     }
24083                                 }
24084                             }
24085                         }
24086                     }
24087                 }
24088             }
24090             //Figure out source file location for each module layer. Do this by seeding require
24091             //with source area configuration. This is needed so that later the module layers
24092             //can be manually copied over to the source area, since the build may be
24093             //require multiple times and the above copyDir call only copies newer files.
24094             require({
24095                 baseUrl: config.baseUrl,
24096                 paths: paths,
24097                 packagePaths: config.packagePaths,
24098                 packages: config.packages
24099             });
24100             buildContext = require.s.contexts._;
24101             modules = config.modules;
24103             if (modules) {
24104                 modules.forEach(function (module) {
24105                     if (module.name) {
24106                         module._sourcePath = buildContext.nameToUrl(module.name);
24107                         //If the module does not exist, and this is not a "new" module layer,
24108                         //as indicated by a true "create" property on the module, and
24109                         //it is not a plugin-loaded resource, and there is no
24110                         //'rawText' containing the module's source then throw an error.
24111                         if (!file.exists(module._sourcePath) && !module.create &&
24112                                 module.name.indexOf('!') === -1 &&
24113                                 (!config.rawText || !lang.hasProp(config.rawText, module.name))) {
24114                             throw new Error("ERROR: module path does not exist: " +
24115                                             module._sourcePath + " for module named: " + module.name +
24116                                             ". Path is relative to: " + file.absPath('.'));
24117                         }
24118                     }
24119                 });
24120             }
24122             if (config.out) {
24123                 //Just set up the _buildPath for the module layer.
24124                 require(config);
24125                 if (!config.cssIn) {
24126                     config.modules[0]._buildPath = typeof config.out === 'function' ?
24127                                                    'FUNCTION' : config.out;
24128                 }
24129             } else if (!config.cssIn) {
24130                 //Now set up the config for require to use the build area, and calculate the
24131                 //build file locations. Pass along any config info too.
24132                 baseConfig = {
24133                     baseUrl: config.dirBaseUrl,
24134                     paths: buildPaths
24135                 };
24137                 lang.mixin(baseConfig, config);
24138                 require(baseConfig);
24140                 if (modules) {
24141                     modules.forEach(function (module) {
24142                         if (module.name) {
24143                             module._buildPath = buildContext.nameToUrl(module.name, null);
24144                             if (!module.create) {
24145                                 file.copyFile(module._sourcePath, module._buildPath);
24146                             }
24147                         }
24148                     });
24149                 }
24150             }
24152             //Run CSS optimizations before doing JS module tracing, to allow
24153             //things like text loader plugins loading CSS to get the optimized
24154             //CSS.
24155             if (config.optimizeCss && config.optimizeCss !== "none" && config.dir) {
24156                 buildFileContents += optimize.css(config.dir, config);
24157             }
24158         }).then(function() {
24159             baseConfig = lang.deeplikeCopy(require.s.contexts._.config);
24160         }).then(function () {
24161             var actions = [];
24163             if (modules) {
24164                 actions = modules.map(function (module, i) {
24165                     return function () {
24166                         //Save off buildPath to module index in a hash for quicker
24167                         //lookup later.
24168                         config._buildPathToModuleIndex[file.normalize(module._buildPath)] = i;
24170                         //Call require to calculate dependencies.
24171                         return build.traceDependencies(module, config, baseConfig)
24172                             .then(function (layer) {
24173                                 module.layer = layer;
24174                             });
24175                     };
24176                 });
24178                 return prim.serial(actions);
24179             }
24180         }).then(function () {
24181             var actions;
24183             if (modules) {
24184                 //Now build up shadow layers for anything that should be excluded.
24185                 //Do this after tracing dependencies for each module, in case one
24186                 //of those modules end up being one of the excluded values.
24187                 actions = modules.map(function (module) {
24188                     return function () {
24189                         if (module.exclude) {
24190                             module.excludeLayers = [];
24191                             return prim.serial(module.exclude.map(function (exclude, i) {
24192                                 return function () {
24193                                     //See if it is already in the list of modules.
24194                                     //If not trace dependencies for it.
24195                                     var found = build.findBuildModule(exclude, modules);
24196                                     if (found) {
24197                                         module.excludeLayers[i] = found;
24198                                     } else {
24199                                         return build.traceDependencies({name: exclude}, config, baseConfig)
24200                                             .then(function (layer) {
24201                                                 module.excludeLayers[i] = { layer: layer };
24202                                             });
24203                                     }
24204                                 };
24205                             }));
24206                         }
24207                     };
24208                 });
24210                 return prim.serial(actions);
24211             }
24212         }).then(function () {
24213             if (modules) {
24214                 return prim.serial(modules.map(function (module) {
24215                     return function () {
24216                         if (module.exclude) {
24217                             //module.exclude is an array of module names. For each one,
24218                             //get the nested dependencies for it via a matching entry
24219                             //in the module.excludeLayers array.
24220                             module.exclude.forEach(function (excludeModule, i) {
24221                                 var excludeLayer = module.excludeLayers[i].layer,
24222                                     map = excludeLayer.buildFileToModule;
24223                                 excludeLayer.buildFilePaths.forEach(function(filePath){
24224                                     build.removeModulePath(map[filePath], filePath, module.layer);
24225                                 });
24226                             });
24227                         }
24228                         if (module.excludeShallow) {
24229                             //module.excludeShallow is an array of module names.
24230                             //shallow exclusions are just that module itself, and not
24231                             //its nested dependencies.
24232                             module.excludeShallow.forEach(function (excludeShallowModule) {
24233                                 var path = getOwn(module.layer.buildPathMap, excludeShallowModule);
24234                                 if (path) {
24235                                     build.removeModulePath(excludeShallowModule, path, module.layer);
24236                                 }
24237                             });
24238                         }
24240                         //Flatten them and collect the build output for each module.
24241                         return build.flattenModule(module, module.layer, config).then(function (builtModule) {
24242                             var finalText, baseName;
24243                             //Save it to a temp file for now, in case there are other layers that
24244                             //contain optimized content that should not be included in later
24245                             //layer optimizations. See issue #56.
24246                             if (module._buildPath === 'FUNCTION') {
24247                                 module._buildText = builtModule.text;
24248                                 module._buildSourceMap = builtModule.sourceMap;
24249                             } else {
24250                                 finalText = builtModule.text;
24251                                 if (builtModule.sourceMap) {
24252                                     baseName = module._buildPath.split('/');
24253                                     baseName = baseName.pop();
24254                                     finalText += '\n//# sourceMappingURL=' + baseName + '.map';
24255                                     file.saveUtf8File(module._buildPath + '.map', builtModule.sourceMap);
24256                                 }
24257                                 file.saveUtf8File(module._buildPath + '-temp', finalText);
24259                             }
24260                             buildFileContents += builtModule.buildText;
24261                         });
24262                     };
24263                 }));
24264             }
24265         }).then(function () {
24266             var moduleName;
24267             if (modules) {
24268                 //Now move the build layers to their final position.
24269                 modules.forEach(function (module) {
24270                     var finalPath = module._buildPath;
24271                     if (finalPath !== 'FUNCTION') {
24272                         if (file.exists(finalPath)) {
24273                             file.deleteFile(finalPath);
24274                         }
24275                         file.renameFile(finalPath + '-temp', finalPath);
24277                         //And finally, if removeCombined is specified, remove
24278                         //any of the files that were used in this layer.
24279                         //Be sure not to remove other build layers.
24280                         if (config.removeCombined) {
24281                             module.layer.buildFilePaths.forEach(function (path) {
24282                                 var isLayer = modules.some(function (mod) {
24283                                         return mod._buildPath === path;
24284                                     }),
24285                                     relPath = build.makeRelativeFilePath(config.dir, path);
24287                                 if (file.exists(path) &&
24288                                     // not a build layer target
24289                                     !isLayer &&
24290                                     // not outside the build directory
24291                                     relPath.indexOf('..') !== 0) {
24292                                     file.deleteFile(path);
24293                                 }
24294                             });
24295                         }
24296                     }
24298                     //Signal layer is done
24299                     if (config.onModuleBundleComplete) {
24300                         config.onModuleBundleComplete(module.onCompleteData);
24301                     }
24302                 });
24303             }
24305             //If removeCombined in play, remove any empty directories that
24306             //may now exist because of its use
24307             if (config.removeCombined && !config.out && config.dir) {
24308                 file.deleteEmptyDirs(config.dir);
24309             }
24311             //Do other optimizations.
24312             if (config.out && !config.cssIn) {
24313                 //Just need to worry about one JS file.
24314                 fileName = config.modules[0]._buildPath;
24315                 if (fileName === 'FUNCTION') {
24316                     config.modules[0]._buildText = optimize.js(fileName,
24317                                                                config.modules[0]._buildText,
24318                                                                null,
24319                                                                config);
24320                 } else {
24321                     optimize.jsFile(fileName, null, fileName, config);
24322                 }
24323             } else if (!config.cssIn) {
24324                 //Normal optimizations across modules.
24326                 //JS optimizations.
24327                 fileNames = file.getFilteredFileList(config.dir, /\.js$/, true);
24328                 fileNames.forEach(function (fileName) {
24329                     var cfg, override, moduleIndex;
24331                     //Generate the module name from the config.dir root.
24332                     moduleName = fileName.replace(config.dir, '');
24333                     //Get rid of the extension
24334                     moduleName = moduleName.substring(0, moduleName.length - 3);
24336                     //If there is an override for a specific layer build module,
24337                     //and this file is that module, mix in the override for use
24338                     //by optimize.jsFile.
24339                     moduleIndex = getOwn(config._buildPathToModuleIndex, fileName);
24340                     //Normalize, since getOwn could have returned undefined
24341                     moduleIndex = moduleIndex === 0 || moduleIndex > 0 ? moduleIndex : -1;
24343                     //Try to avoid extra work if the other files do not need to
24344                     //be read. Build layers should be processed at the very
24345                     //least for optimization.
24346                     if (moduleIndex > -1 || !config.skipDirOptimize ||
24347                             config.normalizeDirDefines === "all" ||
24348                             config.cjsTranslate) {
24349                         //Convert the file to transport format, but without a name
24350                         //inserted (by passing null for moduleName) since the files are
24351                         //standalone, one module per file.
24352                         fileContents = file.readFile(fileName);
24355                         //For builds, if wanting cjs translation, do it now, so that
24356                         //the individual modules can be loaded cross domain via
24357                         //plain script tags.
24358                         if (config.cjsTranslate &&
24359                             (!config.shim || !lang.hasProp(config.shim, moduleName))) {
24360                             fileContents = commonJs.convert(fileName, fileContents);
24361                         }
24363                         if (moduleIndex === -1) {
24364                             if (config.onBuildRead) {
24365                                 fileContents = config.onBuildRead(moduleName,
24366                                                                   fileName,
24367                                                                   fileContents);
24368                             }
24370                             //Only do transport normalization if this is not a build
24371                             //layer (since it was already normalized) and if
24372                             //normalizeDirDefines indicated all should be done.
24373                             if (config.normalizeDirDefines === "all") {
24374                                 fileContents = build.toTransport(config.namespace,
24375                                                              null,
24376                                                              fileName,
24377                                                              fileContents);
24378                             }
24380                             if (config.onBuildWrite) {
24381                                 fileContents = config.onBuildWrite(moduleName,
24382                                                                    fileName,
24383                                                                    fileContents);
24384                             }
24385                         }
24387                         override = moduleIndex > -1 ?
24388                                    config.modules[moduleIndex].override : null;
24389                         if (override) {
24390                             cfg = build.createOverrideConfig(config, override);
24391                         } else {
24392                             cfg = config;
24393                         }
24395                         if (moduleIndex > -1 || !config.skipDirOptimize) {
24396                             optimize.jsFile(fileName, fileContents, fileName, cfg, pluginCollector);
24397                         }
24398                     }
24399                 });
24401                 //Normalize all the plugin resources.
24402                 context = require.s.contexts._;
24404                 for (moduleName in pluginCollector) {
24405                     if (hasProp(pluginCollector, moduleName)) {
24406                         parentModuleMap = context.makeModuleMap(moduleName);
24407                         resources = pluginCollector[moduleName];
24408                         for (i = 0; i < resources.length; i++) {
24409                             resource = resources[i];
24410                             moduleMap = context.makeModuleMap(resource, parentModuleMap);
24411                             if (falseProp(context.plugins, moduleMap.prefix)) {
24412                                 //Set the value in context.plugins so it
24413                                 //will be evaluated as a full plugin.
24414                                 context.plugins[moduleMap.prefix] = true;
24416                                 //Do not bother if the plugin is not available.
24417                                 if (!file.exists(require.toUrl(moduleMap.prefix + '.js'))) {
24418                                     continue;
24419                                 }
24421                                 //Rely on the require in the build environment
24422                                 //to be synchronous
24423                                 context.require([moduleMap.prefix]);
24425                                 //Now that the plugin is loaded, redo the moduleMap
24426                                 //since the plugin will need to normalize part of the path.
24427                                 moduleMap = context.makeModuleMap(resource, parentModuleMap);
24428                             }
24430                             //Only bother with plugin resources that can be handled
24431                             //processed by the plugin, via support of the writeFile
24432                             //method.
24433                             if (falseProp(pluginProcessed, moduleMap.id)) {
24434                                 //Only do the work if the plugin was really loaded.
24435                                 //Using an internal access because the file may
24436                                 //not really be loaded.
24437                                 plugin = getOwn(context.defined, moduleMap.prefix);
24438                                 if (plugin && plugin.writeFile) {
24439                                     plugin.writeFile(
24440                                         moduleMap.prefix,
24441                                         moduleMap.name,
24442                                         require,
24443                                         makeWriteFile(
24444                                             config.namespace
24445                                         ),
24446                                         context.config
24447                                     );
24448                                 }
24450                                 pluginProcessed[moduleMap.id] = true;
24451                             }
24452                         }
24454                     }
24455                 }
24457                 //console.log('PLUGIN COLLECTOR: ' + JSON.stringify(pluginCollector, null, "  "));
24460                 //All module layers are done, write out the build.txt file.
24461                 file.saveUtf8File(config.dir + "build.txt", buildFileContents);
24462             }
24464             //If just have one CSS file to optimize, do that here.
24465             if (config.cssIn) {
24466                 buildFileContents += optimize.cssFile(config.cssIn, config.out, config).buildText;
24467             }
24469             if (typeof config.out === 'function') {
24470                 config.out(config.modules[0]._buildText);
24471             }
24473             //Print out what was built into which layers.
24474             if (buildFileContents) {
24475                 logger.info(buildFileContents);
24476                 return buildFileContents;
24477             }
24479             return '';
24480         });
24481     };
24483     /**
24484      * Converts command line args like "paths.foo=../some/path"
24485      * result.paths = { foo: '../some/path' } where prop = paths,
24486      * name = paths.foo and value = ../some/path, so it assumes the
24487      * name=value splitting has already happened.
24488      */
24489     function stringDotToObj(result, name, value) {
24490         var parts = name.split('.');
24492         parts.forEach(function (prop, i) {
24493             if (i === parts.length - 1) {
24494                 result[prop] = value;
24495             } else {
24496                 if (falseProp(result, prop)) {
24497                     result[prop] = {};
24498                 }
24499                 result = result[prop];
24500             }
24502         });
24503     }
24505     build.objProps = {
24506         paths: true,
24507         wrap: true,
24508         pragmas: true,
24509         pragmasOnSave: true,
24510         has: true,
24511         hasOnSave: true,
24512         uglify: true,
24513         uglify2: true,
24514         closure: true,
24515         map: true,
24516         throwWhen: true
24517     };
24519     build.hasDotPropMatch = function (prop) {
24520         var dotProp,
24521             index = prop.indexOf('.');
24523         if (index !== -1) {
24524             dotProp = prop.substring(0, index);
24525             return hasProp(build.objProps, dotProp);
24526         }
24527         return false;
24528     };
24530     /**
24531      * Converts an array that has String members of "name=value"
24532      * into an object, where the properties on the object are the names in the array.
24533      * Also converts the strings "true" and "false" to booleans for the values.
24534      * member name/value pairs, and converts some comma-separated lists into
24535      * arrays.
24536      * @param {Array} ary
24537      */
24538     build.convertArrayToObject = function (ary) {
24539         var result = {}, i, separatorIndex, prop, value,
24540             needArray = {
24541                 "include": true,
24542                 "exclude": true,
24543                 "excludeShallow": true,
24544                 "insertRequire": true,
24545                 "stubModules": true,
24546                 "deps": true
24547             };
24549         for (i = 0; i < ary.length; i++) {
24550             separatorIndex = ary[i].indexOf("=");
24551             if (separatorIndex === -1) {
24552                 throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value";
24553             }
24555             value = ary[i].substring(separatorIndex + 1, ary[i].length);
24556             if (value === "true") {
24557                 value = true;
24558             } else if (value === "false") {
24559                 value = false;
24560             }
24562             prop = ary[i].substring(0, separatorIndex);
24564             //Convert to array if necessary
24565             if (getOwn(needArray, prop)) {
24566                 value = value.split(",");
24567             }
24569             if (build.hasDotPropMatch(prop)) {
24570                 stringDotToObj(result, prop, value);
24571             } else {
24572                 result[prop] = value;
24573             }
24574         }
24575         return result; //Object
24576     };
24578     build.makeAbsPath = function (path, absFilePath) {
24579         if (!absFilePath) {
24580             return path;
24581         }
24583         //Add abspath if necessary. If path starts with a slash or has a colon,
24584         //then already is an abolute path.
24585         if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) {
24586             path = absFilePath +
24587                    (absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') +
24588                    path;
24589             path = file.normalize(path);
24590         }
24591         return path.replace(lang.backSlashRegExp, '/');
24592     };
24594     build.makeAbsObject = function (props, obj, absFilePath) {
24595         var i, prop;
24596         if (obj) {
24597             for (i = 0; i < props.length; i++) {
24598                 prop = props[i];
24599                 if (hasProp(obj, prop) && typeof obj[prop] === 'string') {
24600                     obj[prop] = build.makeAbsPath(obj[prop], absFilePath);
24601                 }
24602             }
24603         }
24604     };
24606     /**
24607      * For any path in a possible config, make it absolute relative
24608      * to the absFilePath passed in.
24609      */
24610     build.makeAbsConfig = function (config, absFilePath) {
24611         var props, prop, i;
24613         props = ["appDir", "dir", "baseUrl"];
24614         for (i = 0; i < props.length; i++) {
24615             prop = props[i];
24617             if (getOwn(config, prop)) {
24618                 //Add abspath if necessary, make sure these paths end in
24619                 //slashes
24620                 if (prop === "baseUrl") {
24621                     config.originalBaseUrl = config.baseUrl;
24622                     if (config.appDir) {
24623                         //If baseUrl with an appDir, the baseUrl is relative to
24624                         //the appDir, *not* the absFilePath. appDir and dir are
24625                         //made absolute before baseUrl, so this will work.
24626                         config.baseUrl = build.makeAbsPath(config.originalBaseUrl, config.appDir);
24627                     } else {
24628                         //The dir output baseUrl is same as regular baseUrl, both
24629                         //relative to the absFilePath.
24630                         config.baseUrl = build.makeAbsPath(config[prop], absFilePath);
24631                     }
24632                 } else {
24633                     config[prop] = build.makeAbsPath(config[prop], absFilePath);
24634                 }
24636                 config[prop] = endsWithSlash(config[prop]);
24637             }
24638         }
24640         build.makeAbsObject(["out", "cssIn"], config, absFilePath);
24641         build.makeAbsObject(["startFile", "endFile"], config.wrap, absFilePath);
24642     };
24644     /**
24645      * Creates a relative path to targetPath from refPath.
24646      * Only deals with file paths, not folders. If folders,
24647      * make sure paths end in a trailing '/'.
24648      */
24649     build.makeRelativeFilePath = function (refPath, targetPath) {
24650         var i, dotLength, finalParts, length,
24651             refParts = refPath.split('/'),
24652             targetParts = targetPath.split('/'),
24653             //Pull off file name
24654             targetName = targetParts.pop(),
24655             dotParts = [];
24657         //Also pop off the ref file name to make the matches against
24658         //targetParts equivalent.
24659         refParts.pop();
24661         length = refParts.length;
24663         for (i = 0; i < length; i += 1) {
24664             if (refParts[i] !== targetParts[i]) {
24665                 break;
24666             }
24667         }
24669         //Now i is the index in which they diverge.
24670         finalParts = targetParts.slice(i);
24672         dotLength = length - i;
24673         for (i = 0; i > -1 && i < dotLength; i += 1) {
24674             dotParts.push('..');
24675         }
24677         return dotParts.join('/') + (dotParts.length ? '/' : '') +
24678                finalParts.join('/') + (finalParts.length ? '/' : '') +
24679                targetName;
24680     };
24682     build.nestedMix = {
24683         paths: true,
24684         has: true,
24685         hasOnSave: true,
24686         pragmas: true,
24687         pragmasOnSave: true
24688     };
24690     /**
24691      * Mixes additional source config into target config, and merges some
24692      * nested config, like paths, correctly.
24693      */
24694     function mixConfig(target, source) {
24695         var prop, value;
24697         for (prop in source) {
24698             if (hasProp(source, prop)) {
24699                 //If the value of the property is a plain object, then
24700                 //allow a one-level-deep mixing of it.
24701                 value = source[prop];
24702                 if (typeof value === 'object' && value &&
24703                         !lang.isArray(value) && !lang.isFunction(value) &&
24704                         !lang.isRegExp(value)) {
24705                     target[prop] = lang.mixin({}, target[prop], value, true);
24706                 } else {
24707                     target[prop] = value;
24708                 }
24709             }
24710         }
24712         //Set up log level since it can affect if errors are thrown
24713         //or caught and passed to errbacks while doing config setup.
24714         if (lang.hasProp(target, 'logLevel')) {
24715             logger.logLevel(target.logLevel);
24716         }
24717     }
24719     /**
24720      * Converts a wrap.startFile or endFile to be start/end as a string.
24721      * the startFile/endFile values can be arrays.
24722      */
24723     function flattenWrapFile(wrap, keyName, absFilePath) {
24724         var keyFileName = keyName + 'File';
24726         if (typeof wrap[keyName] !== 'string' && wrap[keyFileName]) {
24727             wrap[keyName] = '';
24728             if (typeof wrap[keyFileName] === 'string') {
24729                 wrap[keyFileName] = [wrap[keyFileName]];
24730             }
24731             wrap[keyFileName].forEach(function (fileName) {
24732                 wrap[keyName] += (wrap[keyName] ? '\n' : '') +
24733                     file.readFile(build.makeAbsPath(fileName, absFilePath));
24734             });
24735         } else if (wrap[keyName] === null ||  wrap[keyName] === undefined) {
24736             //Allow missing one, just set to empty string.
24737             wrap[keyName] = '';
24738         } else if (typeof wrap[keyName] !== 'string') {
24739             throw new Error('wrap.' + keyName + ' or wrap.' + keyFileName + ' malformed');
24740         }
24741     }
24743     /**
24744      * Creates a config object for an optimization build.
24745      * It will also read the build profile if it is available, to create
24746      * the configuration.
24747      *
24748      * @param {Object} cfg config options that take priority
24749      * over defaults and ones in the build file. These options could
24750      * be from a command line, for instance.
24751      *
24752      * @param {Object} the created config object.
24753      */
24754     build.createConfig = function (cfg) {
24755         /*jslint evil: true */
24756         var config = {}, buildFileContents, buildFileConfig, mainConfig,
24757             mainConfigFile, mainConfigPath, buildFile, absFilePath;
24759         //Make sure all paths are relative to current directory.
24760         absFilePath = file.absPath('.');
24761         build.makeAbsConfig(cfg, absFilePath);
24762         build.makeAbsConfig(buildBaseConfig, absFilePath);
24764         lang.mixin(config, buildBaseConfig);
24765         lang.mixin(config, cfg, true);
24767         //Set up log level early since it can affect if errors are thrown
24768         //or caught and passed to errbacks, even while constructing config.
24769         if (lang.hasProp(config, 'logLevel')) {
24770             logger.logLevel(config.logLevel);
24771         }
24773         if (config.buildFile) {
24774             //A build file exists, load it to get more config.
24775             buildFile = file.absPath(config.buildFile);
24777             //Find the build file, and make sure it exists, if this is a build
24778             //that has a build profile, and not just command line args with an in=path
24779             if (!file.exists(buildFile)) {
24780                 throw new Error("ERROR: build file does not exist: " + buildFile);
24781             }
24783             absFilePath = config.baseUrl = file.absPath(file.parent(buildFile));
24785             //Load build file options.
24786             buildFileContents = file.readFile(buildFile);
24787             try {
24788                 buildFileConfig = eval("(" + buildFileContents + ")");
24789                 build.makeAbsConfig(buildFileConfig, absFilePath);
24791                 //Mix in the config now so that items in mainConfigFile can
24792                 //be resolved relative to them if necessary, like if appDir
24793                 //is set here, but the baseUrl is in mainConfigFile. Will
24794                 //re-mix in the same build config later after mainConfigFile
24795                 //is processed, since build config should take priority.
24796                 mixConfig(config, buildFileConfig);
24797             } catch (e) {
24798                 throw new Error("Build file " + buildFile + " is malformed: " + e);
24799             }
24800         }
24802         mainConfigFile = config.mainConfigFile || (buildFileConfig && buildFileConfig.mainConfigFile);
24803         if (mainConfigFile) {
24804             mainConfigFile = build.makeAbsPath(mainConfigFile, absFilePath);
24805             if (!file.exists(mainConfigFile)) {
24806                 throw new Error(mainConfigFile + ' does not exist.');
24807             }
24808             try {
24809                 mainConfig = parse.findConfig(file.readFile(mainConfigFile)).config;
24810             } catch (configError) {
24811                 throw new Error('The config in mainConfigFile ' +
24812                         mainConfigFile +
24813                         ' cannot be used because it cannot be evaluated' +
24814                         ' correctly while running in the optimizer. Try only' +
24815                         ' using a config that is also valid JSON, or do not use' +
24816                         ' mainConfigFile and instead copy the config values needed' +
24817                         ' into a build file or command line arguments given to the optimizer.\n' +
24818                         'Source error from parsing: ' + mainConfigFile + ': ' + configError);
24819             }
24820             if (mainConfig) {
24821                 mainConfigPath = mainConfigFile.substring(0, mainConfigFile.lastIndexOf('/'));
24823                 //Add in some existing config, like appDir, since they can be
24824                 //used inside the mainConfigFile -- paths and baseUrl are
24825                 //relative to them.
24826                 if (config.appDir && !mainConfig.appDir) {
24827                     mainConfig.appDir = config.appDir;
24828                 }
24830                 //If no baseUrl, then use the directory holding the main config.
24831                 if (!mainConfig.baseUrl) {
24832                     mainConfig.baseUrl = mainConfigPath;
24833                 }
24835                 build.makeAbsConfig(mainConfig, mainConfigPath);
24836                 mixConfig(config, mainConfig);
24837             }
24838         }
24840         //Mix in build file config, but only after mainConfig has been mixed in.
24841         if (buildFileConfig) {
24842             mixConfig(config, buildFileConfig);
24843         }
24845         //Re-apply the override config values. Command line
24846         //args should take precedence over build file values.
24847         mixConfig(config, cfg);
24849         //Fix paths to full paths so that they can be adjusted consistently
24850         //lately to be in the output area.
24851         lang.eachProp(config.paths, function (value, prop) {
24852             if (lang.isArray(value)) {
24853                 throw new Error('paths fallback not supported in optimizer. ' +
24854                                 'Please provide a build config path override ' +
24855                                 'for ' + prop);
24856             }
24857             config.paths[prop] = build.makeAbsPath(value, config.baseUrl);
24858         });
24860         //Set final output dir
24861         if (hasProp(config, "baseUrl")) {
24862             if (config.appDir) {
24863                 config.dirBaseUrl = build.makeAbsPath(config.originalBaseUrl, config.dir);
24864             } else {
24865                 config.dirBaseUrl = config.dir || config.baseUrl;
24866             }
24867             //Make sure dirBaseUrl ends in a slash, since it is
24868             //concatenated with other strings.
24869             config.dirBaseUrl = endsWithSlash(config.dirBaseUrl);
24870         }
24872         //Check for errors in config
24873         if (config.main) {
24874             throw new Error('"main" passed as an option, but the ' +
24875                             'supported option is called "name".');
24876         }
24877         if (config.out && !config.name && !config.modules && !config.include &&
24878                 !config.cssIn) {
24879             throw new Error('Missing either a "name", "include" or "modules" ' +
24880                             'option');
24881         }
24882         if (config.cssIn) {
24883             if (config.dir || config.appDir) {
24884                 throw new Error('cssIn is only for the output of single file ' +
24885                     'CSS optimizations and is not compatible with "dir" or "appDir" configuration.');
24886             }
24887             if (!config.out) {
24888                 throw new Error('"out" option missing.');
24889             }
24890         }
24891         if (!config.cssIn && !config.baseUrl) {
24892             //Just use the current directory as the baseUrl
24893             config.baseUrl = './';
24894         }
24895         if (!config.out && !config.dir) {
24896             throw new Error('Missing either an "out" or "dir" config value. ' +
24897                             'If using "appDir" for a full project optimization, ' +
24898                             'use "dir". If you want to optimize to one file, ' +
24899                             'use "out".');
24900         }
24901         if (config.appDir && config.out) {
24902             throw new Error('"appDir" is not compatible with "out". Use "dir" ' +
24903                             'instead. appDir is used to copy whole projects, ' +
24904                             'where "out" with "baseUrl" is used to just ' +
24905                             'optimize to one file.');
24906         }
24907         if (config.out && config.dir) {
24908             throw new Error('The "out" and "dir" options are incompatible.' +
24909                             ' Use "out" if you are targeting a single file for' +
24910                             ' for optimization, and "dir" if you want the appDir' +
24911                             ' or baseUrl directories optimized.');
24912         }
24914         if (config.dir) {
24915             // Make sure the output dir is not set to a parent of the
24916             // source dir or the same dir, as it will result in source
24917             // code deletion.
24918             if (config.dir === config.baseUrl ||
24919                 config.dir === config.appDir ||
24920                 (config.baseUrl && build.makeRelativeFilePath(config.dir,
24921                                            config.baseUrl).indexOf('..') !== 0) ||
24922                 (config.appDir &&
24923                     build.makeRelativeFilePath(config.dir, config.appDir).indexOf('..') !== 0)) {
24924                 throw new Error('"dir" is set to a parent or same directory as' +
24925                                 ' "appDir" or "baseUrl". This can result in' +
24926                                 ' the deletion of source code. Stopping.');
24927             }
24928         }
24930         if (config.insertRequire && !lang.isArray(config.insertRequire)) {
24931             throw new Error('insertRequire should be a list of module IDs' +
24932                             ' to insert in to a require([]) call.');
24933         }
24935         if (config.generateSourceMaps) {
24936             if (config.preserveLicenseComments && config.optimize !== 'none') {
24937                 throw new Error('Cannot use preserveLicenseComments and ' +
24938                     'generateSourceMaps together. Either explcitly set ' +
24939                     'preserveLicenseComments to false (default is true) or ' +
24940                     'turn off generateSourceMaps. If you want source maps with ' +
24941                     'license comments, see: ' +
24942                     'http://requirejs.org/docs/errors.html#sourcemapcomments');
24943             } else if (config.optimize !== 'none' &&
24944                        config.optimize !== 'closure' &&
24945                        config.optimize !== 'uglify2') {
24946                 //Allow optimize: none to pass, since it is useful when toggling
24947                 //minification on and off to debug something, and it implicitly
24948                 //works, since it does not need a source map.
24949                 throw new Error('optimize: "' + config.optimize +
24950                     '" does not support generateSourceMaps.');
24951             }
24952         }
24954         if ((config.name || config.include) && !config.modules) {
24955             //Just need to build one file, but may be part of a whole appDir/
24956             //baseUrl copy, but specified on the command line, so cannot do
24957             //the modules array setup. So create a modules section in that
24958             //case.
24959             config.modules = [
24960                 {
24961                     name: config.name,
24962                     out: config.out,
24963                     create: config.create,
24964                     include: config.include,
24965                     exclude: config.exclude,
24966                     excludeShallow: config.excludeShallow,
24967                     insertRequire: config.insertRequire,
24968                     stubModules: config.stubModules
24969                 }
24970             ];
24971             delete config.stubModules;
24972         } else if (config.modules && config.out) {
24973             throw new Error('If the "modules" option is used, then there ' +
24974                             'should be a "dir" option set and "out" should ' +
24975                             'not be used since "out" is only for single file ' +
24976                             'optimization output.');
24977         } else if (config.modules && config.name) {
24978             throw new Error('"name" and "modules" options are incompatible. ' +
24979                             'Either use "name" if doing a single file ' +
24980                             'optimization, or "modules" if you want to target ' +
24981                             'more than one file for optimization.');
24982         }
24984         if (config.out && !config.cssIn) {
24985             //Just one file to optimize.
24987             //Does not have a build file, so set up some defaults.
24988             //Optimizing CSS should not be allowed, unless explicitly
24989             //asked for on command line. In that case the only task is
24990             //to optimize a CSS file.
24991             if (!cfg.optimizeCss) {
24992                 config.optimizeCss = "none";
24993             }
24994         }
24996         //Normalize cssPrefix
24997         if (config.cssPrefix) {
24998             //Make sure cssPrefix ends in a slash
24999             config.cssPrefix = endsWithSlash(config.cssPrefix);
25000         } else {
25001             config.cssPrefix = '';
25002         }
25004         //Cycle through modules and combine any local stubModules with
25005         //global values.
25006         if (config.modules && config.modules.length) {
25007             config.modules.forEach(function (mod) {
25008                 if (config.stubModules) {
25009                     mod.stubModules = config.stubModules.concat(mod.stubModules || []);
25010                 }
25012                 //Create a hash lookup for the stubModules config to make lookup
25013                 //cheaper later.
25014                 if (mod.stubModules) {
25015                     mod.stubModules._byName = {};
25016                     mod.stubModules.forEach(function (id) {
25017                         mod.stubModules._byName[id] = true;
25018                     });
25019                 }
25020             });
25021         }
25023         //Get any wrap text.
25024         try {
25025             if (config.wrap) {
25026                 if (config.wrap === true) {
25027                     //Use default values.
25028                     config.wrap = {
25029                         start: '(function () {',
25030                         end: '}());'
25031                     };
25032                 } else {
25033                     flattenWrapFile(config.wrap, 'start', absFilePath);
25034                     flattenWrapFile(config.wrap, 'end', absFilePath);
25035                 }
25036             }
25037         } catch (wrapError) {
25038             throw new Error('Malformed wrap config: ' + wrapError.toString());
25039         }
25041         //Do final input verification
25042         if (config.context) {
25043             throw new Error('The build argument "context" is not supported' +
25044                             ' in a build. It should only be used in web' +
25045                             ' pages.');
25046         }
25048         //Set up normalizeDirDefines. If not explicitly set, if optimize "none",
25049         //set to "skip" otherwise set to "all".
25050         if (!hasProp(config, 'normalizeDirDefines')) {
25051             if (config.optimize === 'none' || config.skipDirOptimize) {
25052                 config.normalizeDirDefines = 'skip';
25053             } else {
25054                 config.normalizeDirDefines = 'all';
25055             }
25056         }
25058         //Set file.fileExclusionRegExp if desired
25059         if (hasProp(config, 'fileExclusionRegExp')) {
25060             if (typeof config.fileExclusionRegExp === "string") {
25061                 file.exclusionRegExp = new RegExp(config.fileExclusionRegExp);
25062             } else {
25063                 file.exclusionRegExp = config.fileExclusionRegExp;
25064             }
25065         } else if (hasProp(config, 'dirExclusionRegExp')) {
25066             //Set file.dirExclusionRegExp if desired, this is the old
25067             //name for fileExclusionRegExp before 1.0.2. Support for backwards
25068             //compatibility
25069             file.exclusionRegExp = config.dirExclusionRegExp;
25070         }
25072         //Remove things that may cause problems in the build.
25073         delete config.jQuery;
25074         delete config.enforceDefine;
25075         delete config.urlArgs;
25077         return config;
25078     };
25080     /**
25081      * finds the module being built/optimized with the given moduleName,
25082      * or returns null.
25083      * @param {String} moduleName
25084      * @param {Array} modules
25085      * @returns {Object} the module object from the build profile, or null.
25086      */
25087     build.findBuildModule = function (moduleName, modules) {
25088         var i, module;
25089         for (i = 0; i < modules.length; i++) {
25090             module = modules[i];
25091             if (module.name === moduleName) {
25092                 return module;
25093             }
25094         }
25095         return null;
25096     };
25098     /**
25099      * Removes a module name and path from a layer, if it is supposed to be
25100      * excluded from the layer.
25101      * @param {String} moduleName the name of the module
25102      * @param {String} path the file path for the module
25103      * @param {Object} layer the layer to remove the module/path from
25104      */
25105     build.removeModulePath = function (module, path, layer) {
25106         var index = layer.buildFilePaths.indexOf(path);
25107         if (index !== -1) {
25108             layer.buildFilePaths.splice(index, 1);
25109         }
25110     };
25112     /**
25113      * Uses the module build config object to trace the dependencies for the
25114      * given module.
25115      *
25116      * @param {Object} module the module object from the build config info.
25117      * @param {Object} config the build config object.
25118      * @param {Object} [baseLoaderConfig] the base loader config to use for env resets.
25119      *
25120      * @returns {Object} layer information about what paths and modules should
25121      * be in the flattened module.
25122      */
25123     build.traceDependencies = function (module, config, baseLoaderConfig) {
25124         var include, override, layer, context, oldContext,
25125             rawTextByIds,
25126             syncChecks = {
25127                 rhino: true,
25128                 node: true,
25129                 xpconnect: true
25130             },
25131             deferred = prim();
25133         //Reset some state set up in requirePatch.js, and clean up require's
25134         //current context.
25135         oldContext = require._buildReset();
25137         //Grab the reset layer and context after the reset, but keep the
25138         //old config to reuse in the new context.
25139         layer = require._layer;
25140         context = layer.context;
25142         //Put back basic config, use a fresh object for it.
25143         if (baseLoaderConfig) {
25144             require(lang.deeplikeCopy(baseLoaderConfig));
25145         }
25147         logger.trace("\nTracing dependencies for: " + (module.name || module.out));
25148         include = module.name && !module.create ? [module.name] : [];
25149         if (module.include) {
25150             include = include.concat(module.include);
25151         }
25153         //If there are overrides to basic config, set that up now.;
25154         if (module.override) {
25155             if (baseLoaderConfig) {
25156                 override = build.createOverrideConfig(baseLoaderConfig, module.override);
25157             } else {
25158                 override = lang.deeplikeCopy(module.override);
25159             }
25160             require(override);
25161         }
25163         //Now, populate the rawText cache with any values explicitly passed in
25164         //via config.
25165         rawTextByIds = require.s.contexts._.config.rawText;
25166         if (rawTextByIds) {
25167             lang.eachProp(rawTextByIds, function (contents, id) {
25168                 var url = require.toUrl(id) + '.js';
25169                 require._cachedRawText[url] = contents;
25170             });
25171         }
25174         //Configure the callbacks to be called.
25175         deferred.reject.__requireJsBuild = true;
25177         //Use a wrapping function so can check for errors.
25178         function includeFinished(value) {
25179             //If a sync build environment, check for errors here, instead of
25180             //in the then callback below, since some errors, like two IDs pointed
25181             //to same URL but only one anon ID will leave the loader in an
25182             //unresolved state since a setTimeout cannot be used to check for
25183             //timeout.
25184             var hasError = false;
25185             if (syncChecks[env.get()]) {
25186                 try {
25187                     build.checkForErrors(context);
25188                 } catch (e) {
25189                     hasError = true;
25190                     deferred.reject(e);
25191                 }
25192             }
25194             if (!hasError) {
25195                 deferred.resolve(value);
25196             }
25197         }
25198         includeFinished.__requireJsBuild = true;
25200         //Figure out module layer dependencies by calling require to do the work.
25201         require(include, includeFinished, deferred.reject);
25203         return deferred.promise.then(function () {
25204             //Reset config
25205             if (module.override && baseLoaderConfig) {
25206                 require(lang.deeplikeCopy(baseLoaderConfig));
25207             }
25209             build.checkForErrors(context);
25211             return layer;
25212         });
25213     };
25215     build.checkForErrors = function (context) {
25216         //Check to see if it all loaded. If not, then throw, and give
25217         //a message on what is left.
25218         var id, prop, mod, errUrl, idParts, pluginId,
25219             errMessage = '',
25220             failedPluginMap = {},
25221             failedPluginIds = [],
25222             errIds = [],
25223             errUrlMap = {},
25224             errUrlConflicts = {},
25225             hasErrUrl = false,
25226             registry = context.registry;
25228         for (id in registry) {
25229             if (hasProp(registry, id) && id.indexOf('_@r') !== 0) {
25230                 mod = getOwn(registry, id);
25231                 if (id.indexOf('_unnormalized') === -1 && mod && mod.enabled) {
25232                     errIds.push(id);
25233                     errUrl = mod.map.url;
25235                     if (errUrlMap[errUrl]) {
25236                         hasErrUrl = true;
25237                         //This error module has the same URL as another
25238                         //error module, could be misconfiguration.
25239                         if (!errUrlConflicts[errUrl]) {
25240                             errUrlConflicts[errUrl] = [];
25241                             //Store the original module that had the same URL.
25242                             errUrlConflicts[errUrl].push(errUrlMap[errUrl]);
25243                         }
25244                         errUrlConflicts[errUrl].push(id);
25245                     } else {
25246                         errUrlMap[errUrl] = id;
25247                     }
25248                 }
25250                 //Look for plugins that did not call load()
25251                 idParts = id.split('!');
25252                 pluginId = idParts[0];
25253                 if (idParts.length > 1 && falseProp(failedPluginMap, pluginId)) {
25254                     failedPluginIds.push(pluginId);
25255                     failedPluginMap[pluginId] = true;
25256                 }
25257             }
25258         }
25260         if (errIds.length || failedPluginIds.length) {
25261             if (failedPluginIds.length) {
25262                 errMessage += 'Loader plugin' +
25263                     (failedPluginIds.length === 1 ? '' : 's') +
25264                     ' did not call ' +
25265                     'the load callback in the build: ' +
25266                     failedPluginIds.join(', ') + '\n';
25267             }
25268             errMessage += 'Module loading did not complete for: ' + errIds.join(', ');
25270             if (hasErrUrl) {
25271                 errMessage += '\nThe following modules share the same URL. This ' +
25272                               'could be a misconfiguration if that URL only has ' +
25273                               'one anonymous module in it:';
25274                 for (prop in errUrlConflicts) {
25275                     if (hasProp(errUrlConflicts, prop)) {
25276                         errMessage += '\n' + prop + ': ' +
25277                                       errUrlConflicts[prop].join(', ');
25278                     }
25279                 }
25280             }
25281             throw new Error(errMessage);
25282         }
25284     };
25286     build.createOverrideConfig = function (config, override) {
25287         var cfg = lang.deeplikeCopy(config),
25288             oride = lang.deeplikeCopy(override);
25290         lang.eachProp(oride, function (value, prop) {
25291             if (hasProp(build.objProps, prop)) {
25292                 //An object property, merge keys. Start a new object
25293                 //so that source object in config does not get modified.
25294                 cfg[prop] = {};
25295                 lang.mixin(cfg[prop], config[prop], true);
25296                 lang.mixin(cfg[prop], override[prop], true);
25297             } else {
25298                 cfg[prop] = override[prop];
25299             }
25300         });
25302         return cfg;
25303     };
25305     /**
25306      * Uses the module build config object to create an flattened version
25307      * of the module, with deep dependencies included.
25308      *
25309      * @param {Object} module the module object from the build config info.
25310      *
25311      * @param {Object} layer the layer object returned from build.traceDependencies.
25312      *
25313      * @param {Object} the build config object.
25314      *
25315      * @returns {Object} with two properties: "text", the text of the flattened
25316      * module, and "buildText", a string of text representing which files were
25317      * included in the flattened module text.
25318      */
25319     build.flattenModule = function (module, layer, config) {
25320         var fileContents, sourceMapGenerator,
25321             sourceMapBase,
25322             buildFileContents = '';
25324         return prim().start(function () {
25325             var reqIndex, currContents,
25326                 moduleName, shim, packageConfig, nonPackageName,
25327                 parts, builder, writeApi,
25328                 namespace, namespaceWithDot, stubModulesByName,
25329                 context = layer.context,
25330                 onLayerEnds = [],
25331                 onLayerEndAdded = {};
25333             //Use override settings, particularly for pragmas
25334             //Do this before the var readings since it reads config values.
25335             if (module.override) {
25336                 config = build.createOverrideConfig(config, module.override);
25337             }
25339             namespace = config.namespace || '';
25340             namespaceWithDot = namespace ? namespace + '.' : '';
25341             stubModulesByName = (module.stubModules && module.stubModules._byName) || {};
25343             //Start build output for the module.
25344             module.onCompleteData = {
25345                 name: module.name,
25346                 path: (config.dir ? module._buildPath.replace(config.dir, "") : module._buildPath),
25347                 included: []
25348             };
25350             buildFileContents += "\n" +
25351                                   module.onCompleteData.path +
25352                                  "\n----------------\n";
25354             //If there was an existing file with require in it, hoist to the top.
25355             if (layer.existingRequireUrl) {
25356                 reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl);
25357                 if (reqIndex !== -1) {
25358                     layer.buildFilePaths.splice(reqIndex, 1);
25359                     layer.buildFilePaths.unshift(layer.existingRequireUrl);
25360                 }
25361             }
25363             if (config.generateSourceMaps) {
25364                 sourceMapBase = config.dir || config.baseUrl;
25365                 sourceMapGenerator = new SourceMapGenerator.SourceMapGenerator({
25366                     file: module._buildPath.replace(sourceMapBase, '')
25367                 });
25368             }
25370             //Write the built module to disk, and build up the build output.
25371             fileContents = "";
25372             return prim.serial(layer.buildFilePaths.map(function (path) {
25373                 return function () {
25374                     var lineCount,
25375                         singleContents = '';
25377                     moduleName = layer.buildFileToModule[path];
25378                     //If the moduleName is for a package main, then update it to the
25379                     //real main value.
25380                     packageConfig = layer.context.config.pkgs &&
25381                                     getOwn(layer.context.config.pkgs, moduleName);
25382                     if (packageConfig) {
25383                         nonPackageName = moduleName;
25384                         moduleName += '/' + packageConfig.main;
25385                     }
25387                     return prim().start(function () {
25388                         //Figure out if the module is a result of a build plugin, and if so,
25389                         //then delegate to that plugin.
25390                         parts = context.makeModuleMap(moduleName);
25391                         builder = parts.prefix && getOwn(context.defined, parts.prefix);
25392                         if (builder) {
25393                             if (builder.onLayerEnd && falseProp(onLayerEndAdded, parts.prefix)) {
25394                                 onLayerEnds.push(builder);
25395                                 onLayerEndAdded[parts.prefix] = true;
25396                             }
25398                             if (builder.write) {
25399                                 writeApi = function (input) {
25400                                     singleContents += "\n" + addSemiColon(input, config);
25401                                     if (config.onBuildWrite) {
25402                                         singleContents = config.onBuildWrite(moduleName, path, singleContents);
25403                                     }
25404                                 };
25405                                 writeApi.asModule = function (moduleName, input) {
25406                                     singleContents += "\n" +
25407                                         addSemiColon(build.toTransport(namespace, moduleName, path, input, layer, {
25408                                             useSourceUrl: layer.context.config.useSourceUrl
25409                                         }), config);
25410                                     if (config.onBuildWrite) {
25411                                         singleContents = config.onBuildWrite(moduleName, path, singleContents);
25412                                     }
25413                                 };
25414                                 builder.write(parts.prefix, parts.name, writeApi);
25415                             }
25416                             return;
25417                         } else {
25418                             return prim().start(function () {
25419                                 if (hasProp(stubModulesByName, moduleName)) {
25420                                     //Just want to insert a simple module definition instead
25421                                     //of the source module. Useful for plugins that inline
25422                                     //all their resources.
25423                                     if (hasProp(layer.context.plugins, moduleName)) {
25424                                         //Slightly different content for plugins, to indicate
25425                                         //that dynamic loading will not work.
25426                                         return 'define({load: function(id){throw new Error("Dynamic load not allowed: " + id);}});';
25427                                     } else {
25428                                         return 'define({});';
25429                                     }
25430                                 } else {
25431                                     return require._cacheReadAsync(path);
25432                                 }
25433                             }).then(function (text) {
25434                                 var hasPackageName;
25436                                 currContents = text;
25438                                 if (config.cjsTranslate &&
25439                                     (!config.shim || !lang.hasProp(config.shim, moduleName))) {
25440                                     currContents = commonJs.convert(path, currContents);
25441                                 }
25443                                 if (config.onBuildRead) {
25444                                     currContents = config.onBuildRead(moduleName, path, currContents);
25445                                 }
25447                                 if (packageConfig) {
25448                                     hasPackageName = (nonPackageName === parse.getNamedDefine(currContents));
25449                                 }
25451                                 if (namespace) {
25452                                     currContents = pragma.namespace(currContents, namespace);
25453                                 }
25455                                 currContents = build.toTransport(namespace, moduleName, path, currContents, layer, {
25456                                     useSourceUrl: config.useSourceUrl
25457                                 });
25459                                 if (packageConfig && !hasPackageName) {
25460                                     currContents = addSemiColon(currContents, config) + '\n';
25461                                     currContents += namespaceWithDot + "define('" +
25462                                                     packageConfig.name + "', ['" + moduleName +
25463                                                     "'], function (main) { return main; });\n";
25464                                 }
25466                                 if (config.onBuildWrite) {
25467                                     currContents = config.onBuildWrite(moduleName, path, currContents);
25468                                 }
25470                                 //Semicolon is for files that are not well formed when
25471                                 //concatenated with other content.
25472                                 singleContents += "\n" + addSemiColon(currContents, config);
25473                             });
25474                         }
25475                     }).then(function () {
25476                         var sourceMapPath, sourceMapLineNumber,
25477                             shortPath = path.replace(config.dir, "");
25479                         module.onCompleteData.included.push(shortPath);
25480                         buildFileContents += shortPath + "\n";
25482                         //Some files may not have declared a require module, and if so,
25483                         //put in a placeholder call so the require does not try to load them
25484                         //after the module is processed.
25485                         //If we have a name, but no defined module, then add in the placeholder.
25486                         if (moduleName && falseProp(layer.modulesWithNames, moduleName) && !config.skipModuleInsertion) {
25487                             shim = config.shim && (getOwn(config.shim, moduleName) || (packageConfig && getOwn(config.shim, nonPackageName)));
25488                             if (shim) {
25489                                 singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", ' +
25490                                                  (shim.deps && shim.deps.length ?
25491                                                         build.makeJsArrayString(shim.deps) + ', ' : '') +
25492                                                  (shim.exportsFn ? shim.exportsFn() : 'function(){}') +
25493                                                  ');\n';
25494                             } else {
25495                                 singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", function(){});\n';
25496                             }
25497                         }
25499                         //Add to the source map
25500                         if (sourceMapGenerator) {
25501                             sourceMapPath = build.makeRelativeFilePath(module._buildPath, path);
25502                             sourceMapLineNumber = fileContents.split('\n').length - 1;
25503                             lineCount = singleContents.split('\n').length;
25504                             for (var i = 1; i <= lineCount; i += 1) {
25505                                 sourceMapGenerator.addMapping({
25506                                     generated: {
25507                                         line: sourceMapLineNumber + i,
25508                                         column: 0
25509                                     },
25510                                     original: {
25511                                         line: i,
25512                                         column: 0
25513                                     },
25514                                     source: sourceMapPath
25515                                 });
25516                             }
25518                             //Store the content of the original in the source
25519                             //map since other transforms later like minification
25520                             //can mess up translating back to the original
25521                             //source
25522                             sourceMapGenerator.setSourceContent(sourceMapPath, singleContents);
25523                         }
25525                         //Add the file to the final contents
25526                         fileContents += singleContents;
25527                     });
25528                 };
25529             })).then(function () {
25530                 if (onLayerEnds.length) {
25531                     onLayerEnds.forEach(function (builder) {
25532                         var path;
25533                         if (typeof module.out === 'string') {
25534                             path = module.out;
25535                         } else if (typeof module._buildPath === 'string') {
25536                             path = module._buildPath;
25537                         }
25538                         builder.onLayerEnd(function (input) {
25539                             fileContents += "\n" + addSemiColon(input, config);
25540                         }, {
25541                             name: module.name,
25542                             path: path
25543                         });
25544                     });
25545                 }
25547                 if (module.create) {
25548                     //The ID is for a created layer. Write out
25549                     //a module definition for it in case the
25550                     //built file is used with enforceDefine
25551                     //(#432)
25552                     fileContents += '\n' + namespaceWithDot + 'define("' + module.name + '", function(){});\n';
25553                 }
25555                 //Add a require at the end to kick start module execution, if that
25556                 //was desired. Usually this is only specified when using small shim
25557                 //loaders like almond.
25558                 if (module.insertRequire) {
25559                     fileContents += '\n' + namespaceWithDot + 'require(["' + module.insertRequire.join('", "') + '"]);\n';
25560                 }
25561             });
25562         }).then(function () {
25563             return {
25564                 text: config.wrap ?
25565                         config.wrap.start + fileContents + config.wrap.end :
25566                         fileContents,
25567                 buildText: buildFileContents,
25568                 sourceMap: sourceMapGenerator ?
25569                               JSON.stringify(sourceMapGenerator.toJSON(), null, '  ') :
25570                               undefined
25571             };
25572         });
25573     };
25575     //Converts an JS array of strings to a string representation.
25576     //Not using JSON.stringify() for Rhino's sake.
25577     build.makeJsArrayString = function (ary) {
25578         return '["' + ary.map(function (item) {
25579             //Escape any double quotes, backslashes
25580             return lang.jsEscape(item);
25581         }).join('","') + '"]';
25582     };
25584     build.toTransport = function (namespace, moduleName, path, contents, layer, options) {
25585         var baseUrl = layer && layer.context.config.baseUrl;
25587         function onFound(info) {
25588             //Only mark this module as having a name if not a named module,
25589             //or if a named module and the name matches expectations.
25590             if (layer && (info.needsId || info.foundId === moduleName)) {
25591                 layer.modulesWithNames[moduleName] = true;
25592             }
25593         }
25595         //Convert path to be a local one to the baseUrl, useful for
25596         //useSourceUrl.
25597         if (baseUrl) {
25598             path = path.replace(baseUrl, '');
25599         }
25601         return transform.toTransport(namespace, moduleName, path, contents, onFound, options);
25602     };
25604     return build;
25607     }
25610     /**
25611      * Sets the default baseUrl for requirejs to be directory of top level
25612      * script.
25613      */
25614     function setBaseUrl(fileName) {
25615         //Use the file name's directory as the baseUrl if available.
25616         dir = fileName.replace(/\\/g, '/');
25617         if (dir.indexOf('/') !== -1) {
25618             dir = dir.split('/');
25619             dir.pop();
25620             dir = dir.join('/');
25621             //Make sure dir is JS-escaped, since it will be part of a JS string.
25622             exec("require({baseUrl: '" + dir.replace(/[\\"']/g, '\\$&') + "'});");
25623         }
25624     }
25626     function createRjsApi() {
25627         //Create a method that will run the optimzer given an object
25628         //config.
25629         requirejs.optimize = function (config, callback, errback) {
25630             if (!loadedOptimizedLib) {
25631                 loadLib();
25632                 loadedOptimizedLib = true;
25633             }
25635             //Create the function that will be called once build modules
25636             //have been loaded.
25637             var runBuild = function (build, logger, quit) {
25638                 //Make sure config has a log level, and if not,
25639                 //make it "silent" by default.
25640                 config.logLevel = config.hasOwnProperty('logLevel') ?
25641                                   config.logLevel : logger.SILENT;
25643                 //Reset build internals first in case this is part
25644                 //of a long-running server process that could have
25645                 //exceptioned out in a bad state. It is only defined
25646                 //after the first call though.
25647                 if (requirejs._buildReset) {
25648                     requirejs._buildReset();
25649                     requirejs._cacheReset();
25650                 }
25652                 function done(result) {
25653                     //And clean up, in case something else triggers
25654                     //a build in another pathway.
25655                     if (requirejs._buildReset) {
25656                         requirejs._buildReset();
25657                         requirejs._cacheReset();
25658                     }
25660                     // Ensure errors get propagated to the errback
25661                     if (result instanceof Error) {
25662                       throw result;
25663                     }
25665                     return result;
25666                 }
25668                 errback = errback || function (err) {
25669                     // Using console here since logger may have
25670                     // turned off error logging. Since quit is
25671                     // called want to be sure a message is printed.
25672                     console.log(err);
25673                     quit(1);
25674                 };
25676                 build(config).then(done, done).then(callback, errback);
25677             };
25679             requirejs({
25680                 context: 'build'
25681             }, ['build', 'logger', 'env!env/quit'], runBuild);
25682         };
25684         requirejs.tools = {
25685             useLib: function (contextName, callback) {
25686                 if (!callback) {
25687                     callback = contextName;
25688                     contextName = 'uselib';
25689                 }
25691                 if (!useLibLoaded[contextName]) {
25692                     loadLib();
25693                     useLibLoaded[contextName] = true;
25694                 }
25696                 var req = requirejs({
25697                     context: contextName
25698                 });
25700                 req(['build'], function () {
25701                     callback(req);
25702                 });
25703             }
25704         };
25706         requirejs.define = define;
25707     }
25709     //If in Node, and included via a require('requirejs'), just export and
25710     //THROW IT ON THE GROUND!
25711     if (env === 'node' && reqMain !== module) {
25712         setBaseUrl(path.resolve(reqMain ? reqMain.filename : '.'));
25714         createRjsApi();
25716         module.exports = requirejs;
25717         return;
25718     } else if (env === 'browser') {
25719         //Only option is to use the API.
25720         setBaseUrl(location.href);
25721         createRjsApi();
25722         return;
25723     } else if ((env === 'rhino' || env === 'xpconnect') &&
25724             //User sets up requirejsAsLib variable to indicate it is loaded
25725             //via load() to be used as a library.
25726             typeof requirejsAsLib !== 'undefined' && requirejsAsLib) {
25727         //This script is loaded via rhino's load() method, expose the
25728         //API and get out.
25729         setBaseUrl(fileName);
25730         createRjsApi();
25731         return;
25732     }
25734     if (commandOption === 'o') {
25735         //Do the optimizer work.
25736         loadLib();
25738         /**
25739  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
25740  * Available via the MIT or new BSD license.
25741  * see: http://github.com/jrburke/requirejs for details
25742  */
25745  * Create a build.js file that has the build options you want and pass that
25746  * build file to this file to do the build. See example.build.js for more information.
25747  */
25749 /*jslint strict: false, nomen: false */
25750 /*global require: false */
25752 require({
25753     baseUrl: require.s.contexts._.config.baseUrl,
25754     //Use a separate context than the default context so that the
25755     //build can use the default context.
25756     context: 'build',
25757     catchError: {
25758         define: true
25759     }
25760 },       ['env!env/args', 'env!env/quit', 'logger', 'build'],
25761 function (args, quit, logger, build) {
25762     build(args).then(function () {}, function (err) {
25763         logger.error(err);
25764         quit(1);
25765     });
25769     } else if (commandOption === 'v') {
25770         console.log('r.js: ' + version +
25771                     ', RequireJS: ' + this.requirejsVars.require.version +
25772                     ', UglifyJS2: 2.3.6, UglifyJS: 1.3.4');
25773     } else if (commandOption === 'convert') {
25774         loadLib();
25776         this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'],
25777             function (args, commonJs, print) {
25779                 var srcDir, outDir;
25780                 srcDir = args[0];
25781                 outDir = args[1];
25783                 if (!srcDir || !outDir) {
25784                     print('Usage: path/to/commonjs/modules output/dir');
25785                     return;
25786                 }
25788                 commonJs.convertDir(args[0], args[1]);
25789             });
25790     } else {
25791         //Just run an app
25793         //Load the bundled libraries for use in the app.
25794         if (commandOption === 'lib') {
25795             loadLib();
25796         }
25798         setBaseUrl(fileName);
25800         if (exists(fileName)) {
25801             exec(readFile(fileName), fileName);
25802         } else {
25803             showHelp();
25804         }
25805     }
25807 }((typeof console !== 'undefined' ? console : undefined),
25808     (typeof Packages !== 'undefined' || (typeof window === 'undefined' &&
25809         typeof Components !== 'undefined' && Components.interfaces) ?
25810         Array.prototype.slice.call(arguments, 0) : []),
25811     (typeof readFile !== 'undefined' ? readFile : undefined)));