Revert "Export"
[platform/framework/web/web-ui-fw.git] / libs / js / jquery-mobile-1.1.0 / external / r.js / dist / r.js
1 /**
2  * @license r.js 1.0.7+ Fri, 30 Mar 2012 00:24:35 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  */
6
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  */
13
14 /*jslint evil: true, nomen: true */
15 /*global readFile: true, process: false, Packages: false, print: false,
16 console: false, java: false, module: false, requirejsVars */
17
18 var requirejs, require, define;
19 (function (console, args, readFileFunc) {
20
21     var fileName, env, fs, vm, path, exec, rhinoContext, dir, nodeRequire,
22         nodeDefine, exists, reqMain, loadedOptimizedLib,
23         version = '1.0.7+ Fri, 30 Mar 2012 00:24:35 GMT',
24         jsSuffixRegExp = /\.js$/,
25         commandOption = '',
26         useLibLoaded = {},
27         //Used by jslib/rhino/args.js
28         rhinoArgs = args,
29         readFile = typeof readFileFunc !== 'undefined' ? readFileFunc : null;
30
31     function showHelp() {
32         console.log('See https://github.com/jrburke/r.js for usage.');
33     }
34
35     if (typeof Packages !== 'undefined') {
36         env = 'rhino';
37
38         fileName = args[0];
39
40         if (fileName && fileName.indexOf('-') === 0) {
41             commandOption = fileName.substring(1);
42             fileName = args[1];
43         }
44
45         //Set up execution context.
46         rhinoContext = Packages.org.mozilla.javascript.ContextFactory.getGlobal().enterContext();
47
48         exec = function (string, name) {
49             return rhinoContext.evaluateString(this, string, name, 0, null);
50         };
51
52         exists = function (fileName) {
53             return (new java.io.File(fileName)).exists();
54         };
55
56         //Define a console.log for easier logging. Don't
57         //get fancy though.
58         if (typeof console === 'undefined') {
59             console = {
60                 log: function () {
61                     print.apply(undefined, arguments);
62                 }
63             };
64         }
65     } else if (typeof process !== 'undefined') {
66         env = 'node';
67
68         //Get the fs module via Node's require before it
69         //gets replaced. Used in require/node.js
70         fs = require('fs');
71         vm = require('vm');
72         path = require('path');
73         nodeRequire = require;
74         nodeDefine = define;
75         reqMain = require.main;
76
77         //Temporarily hide require and define to allow require.js to define
78         //them.
79         require = undefined;
80         define = undefined;
81
82         readFile = function (path) {
83             return fs.readFileSync(path, 'utf8');
84         };
85
86         exec = function (string, name) {
87             return vm.runInThisContext(this.requirejsVars.require.makeNodeWrapper(string),
88                                        name ? fs.realpathSync(name) : '');
89         };
90
91         exists = function (fileName) {
92             return path.existsSync(fileName);
93         };
94
95
96         fileName = process.argv[2];
97
98         if (fileName && fileName.indexOf('-') === 0) {
99             commandOption = fileName.substring(1);
100             fileName = process.argv[3];
101         }
102     }
103
104     /** vim: et:ts=4:sw=4:sts=4
105  * @license RequireJS 1.0.7 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
106  * Available via the MIT or new BSD license.
107  * see: http://github.com/jrburke/requirejs for details
108  */
109 /*jslint strict: false, plusplus: false, sub: true */
110 /*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
111
112
113 (function () {
114     //Change this version number for each release.
115     var version = "1.0.7",
116         commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
117         cjsRequireRegExp = /require\(\s*["']([^'"\s]+)["']\s*\)/g,
118         currDirRegExp = /^\.\//,
119         jsSuffixRegExp = /\.js$/,
120         ostring = Object.prototype.toString,
121         ap = Array.prototype,
122         aps = ap.slice,
123         apsp = ap.splice,
124         isBrowser = !!(typeof window !== "undefined" && navigator && document),
125         isWebWorker = !isBrowser && typeof importScripts !== "undefined",
126         //PS3 indicates loaded and complete, but need to wait for complete
127         //specifically. Sequence is "loading", "loaded", execution,
128         // then "complete". The UA check is unfortunate, but not sure how
129         //to feature test w/o causing perf issues.
130         readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
131                       /^complete$/ : /^(complete|loaded)$/,
132         defContextName = "_",
133         //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
134         isOpera = typeof opera !== "undefined" && opera.toString() === "[object Opera]",
135         empty = {},
136         contexts = {},
137         globalDefQueue = [],
138         interactiveScript = null,
139         checkLoadedDepth = 0,
140         useInteractive = false,
141         reservedDependencies = {
142             require: true,
143             module: true,
144             exports: true
145         },
146         req, cfg = {}, currentlyAddingScript, s, head, baseElement, scripts, script,
147         src, subPath, mainScript, dataMain, globalI, ctx, jQueryCheck, checkLoadedTimeoutId;
148
149     function isFunction(it) {
150         return ostring.call(it) === "[object Function]";
151     }
152
153     function isArray(it) {
154         return ostring.call(it) === "[object Array]";
155     }
156
157     /**
158      * Simple function to mix in properties from source into target,
159      * but only if target does not already have a property of the same name.
160      * This is not robust in IE for transferring methods that match
161      * Object.prototype names, but the uses of mixin here seem unlikely to
162      * trigger a problem related to that.
163      */
164     function mixin(target, source, force) {
165         for (var prop in source) {
166             if (!(prop in empty) && (!(prop in target) || force)) {
167                 target[prop] = source[prop];
168             }
169         }
170         return req;
171     }
172
173     /**
174      * Constructs an error with a pointer to an URL with more information.
175      * @param {String} id the error ID that maps to an ID on a web page.
176      * @param {String} message human readable error.
177      * @param {Error} [err] the original error, if there is one.
178      *
179      * @returns {Error}
180      */
181     function makeError(id, msg, err) {
182         var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
183         if (err) {
184             e.originalError = err;
185         }
186         return e;
187     }
188
189     /**
190      * Used to set up package paths from a packagePaths or packages config object.
191      * @param {Object} pkgs the object to store the new package config
192      * @param {Array} currentPackages an array of packages to configure
193      * @param {String} [dir] a prefix dir to use.
194      */
195     function configurePackageDir(pkgs, currentPackages, dir) {
196         var i, location, pkgObj;
197
198         for (i = 0; (pkgObj = currentPackages[i]); i++) {
199             pkgObj = typeof pkgObj === "string" ? { name: pkgObj } : pkgObj;
200             location = pkgObj.location;
201
202             //Add dir to the path, but avoid paths that start with a slash
203             //or have a colon (indicates a protocol)
204             if (dir && (!location || (location.indexOf("/") !== 0 && location.indexOf(":") === -1))) {
205                 location = dir + "/" + (location || pkgObj.name);
206             }
207
208             //Create a brand new object on pkgs, since currentPackages can
209             //be passed in again, and config.pkgs is the internal transformed
210             //state for all package configs.
211             pkgs[pkgObj.name] = {
212                 name: pkgObj.name,
213                 location: location || pkgObj.name,
214                 //Remove leading dot in main, so main paths are normalized,
215                 //and remove any trailing .js, since different package
216                 //envs have different conventions: some use a module name,
217                 //some use a file name.
218                 main: (pkgObj.main || "main")
219                       .replace(currDirRegExp, '')
220                       .replace(jsSuffixRegExp, '')
221             };
222         }
223     }
224
225     /**
226      * jQuery 1.4.3-1.5.x use a readyWait/ready() pairing to hold DOM
227      * ready callbacks, but jQuery 1.6 supports a holdReady() API instead.
228      * At some point remove the readyWait/ready() support and just stick
229      * with using holdReady.
230      */
231     function jQueryHoldReady($, shouldHold) {
232         if ($.holdReady) {
233             $.holdReady(shouldHold);
234         } else if (shouldHold) {
235             $.readyWait += 1;
236         } else {
237             $.ready(true);
238         }
239     }
240
241     if (typeof define !== "undefined") {
242         //If a define is already in play via another AMD loader,
243         //do not overwrite.
244         return;
245     }
246
247     if (typeof requirejs !== "undefined") {
248         if (isFunction(requirejs)) {
249             //Do not overwrite and existing requirejs instance.
250             return;
251         } else {
252             cfg = requirejs;
253             requirejs = undefined;
254         }
255     }
256
257     //Allow for a require config object
258     if (typeof require !== "undefined" && !isFunction(require)) {
259         //assume it is a config object.
260         cfg = require;
261         require = undefined;
262     }
263
264     /**
265      * Creates a new context for use in require and define calls.
266      * Handle most of the heavy lifting. Do not want to use an object
267      * with prototype here to avoid using "this" in require, in case it
268      * needs to be used in more super secure envs that do not want this.
269      * Also there should not be that many contexts in the page. Usually just
270      * one for the default context, but could be extra for multiversion cases
271      * or if a package needs a special context for a dependency that conflicts
272      * with the standard context.
273      */
274     function newContext(contextName) {
275         var context, resume,
276             config = {
277                 waitSeconds: 7,
278                 baseUrl: "./",
279                 paths: {},
280                 pkgs: {},
281                 catchError: {}
282             },
283             defQueue = [],
284             specified = {
285                 "require": true,
286                 "exports": true,
287                 "module": true
288             },
289             urlMap = {},
290             defined = {},
291             loaded = {},
292             waiting = {},
293             waitAry = [],
294             urlFetched = {},
295             managerCounter = 0,
296             managerCallbacks = {},
297             plugins = {},
298             //Used to indicate which modules in a build scenario
299             //need to be full executed.
300             needFullExec = {},
301             fullExec = {},
302             resumeDepth = 0;
303
304         /**
305          * Trims the . and .. from an array of path segments.
306          * It will keep a leading path segment if a .. will become
307          * the first path segment, to help with module name lookups,
308          * which act like paths, but can be remapped. But the end result,
309          * all paths that use this function should look normalized.
310          * NOTE: this method MODIFIES the input array.
311          * @param {Array} ary the array of path segments.
312          */
313         function trimDots(ary) {
314             var i, part;
315             for (i = 0; (part = ary[i]); i++) {
316                 if (part === ".") {
317                     ary.splice(i, 1);
318                     i -= 1;
319                 } else if (part === "..") {
320                     if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
321                         //End of the line. Keep at least one non-dot
322                         //path segment at the front so it can be mapped
323                         //correctly to disk. Otherwise, there is likely
324                         //no path mapping for a path starting with '..'.
325                         //This can still fail, but catches the most reasonable
326                         //uses of ..
327                         break;
328                     } else if (i > 0) {
329                         ary.splice(i - 1, 2);
330                         i -= 2;
331                     }
332                 }
333             }
334         }
335
336         /**
337          * Given a relative module name, like ./something, normalize it to
338          * a real name that can be mapped to a path.
339          * @param {String} name the relative name
340          * @param {String} baseName a real name that the name arg is relative
341          * to.
342          * @returns {String} normalized name
343          */
344         function normalize(name, baseName) {
345             var pkgName, pkgConfig;
346
347             //Adjust any relative paths.
348             if (name && name.charAt(0) === ".") {
349                 //If have a base name, try to normalize against it,
350                 //otherwise, assume it is a top-level require that will
351                 //be relative to baseUrl in the end.
352                 if (baseName) {
353                     if (config.pkgs[baseName]) {
354                         //If the baseName is a package name, then just treat it as one
355                         //name to concat the name with.
356                         baseName = [baseName];
357                     } else {
358                         //Convert baseName to array, and lop off the last part,
359                         //so that . matches that "directory" and not name of the baseName's
360                         //module. For instance, baseName of "one/two/three", maps to
361                         //"one/two/three.js", but we want the directory, "one/two" for
362                         //this normalization.
363                         baseName = baseName.split("/");
364                         baseName = baseName.slice(0, baseName.length - 1);
365                     }
366
367                     name = baseName.concat(name.split("/"));
368                     trimDots(name);
369
370                     //Some use of packages may use a . path to reference the
371                     //"main" module name, so normalize for that.
372                     pkgConfig = config.pkgs[(pkgName = name[0])];
373                     name = name.join("/");
374                     if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {
375                         name = pkgName;
376                     }
377                 } else if (name.indexOf("./") === 0) {
378                     // No baseName, so this is ID is resolved relative
379                     // to baseUrl, pull off the leading dot.
380                     name = name.substring(2);
381                 }
382             }
383             return name;
384         }
385
386         /**
387          * Creates a module mapping that includes plugin prefix, module
388          * name, and path. If parentModuleMap is provided it will
389          * also normalize the name via require.normalize()
390          *
391          * @param {String} name the module name
392          * @param {String} [parentModuleMap] parent module map
393          * for the module name, used to resolve relative names.
394          *
395          * @returns {Object}
396          */
397         function makeModuleMap(name, parentModuleMap) {
398             var index = name ? name.indexOf("!") : -1,
399                 prefix = null,
400                 parentName = parentModuleMap ? parentModuleMap.name : null,
401                 originalName = name,
402                 normalizedName, url, pluginModule;
403
404             if (index !== -1) {
405                 prefix = name.substring(0, index);
406                 name = name.substring(index + 1, name.length);
407             }
408
409             if (prefix) {
410                 prefix = normalize(prefix, parentName);
411             }
412
413             //Account for relative paths if there is a base name.
414             if (name) {
415                 if (prefix) {
416                     pluginModule = defined[prefix];
417                     if (pluginModule && pluginModule.normalize) {
418                         //Plugin is loaded, use its normalize method.
419                         normalizedName = pluginModule.normalize(name, function (name) {
420                             return normalize(name, parentName);
421                         });
422                     } else {
423                         normalizedName = normalize(name, parentName);
424                     }
425                 } else {
426                     //A regular module.
427                     normalizedName = normalize(name, parentName);
428
429                     url = urlMap[normalizedName];
430                     if (!url) {
431                         //Calculate url for the module, if it has a name.
432                         //Use name here since nameToUrl also calls normalize,
433                         //and for relative names that are outside the baseUrl
434                         //this causes havoc. Was thinking of just removing
435                         //parentModuleMap to avoid extra normalization, but
436                         //normalize() still does a dot removal because of
437                         //issue #142, so just pass in name here and redo
438                         //the normalization. Paths outside baseUrl are just
439                         //messy to support.
440                         url = context.nameToUrl(name, null, parentModuleMap);
441
442                         //Store the URL mapping for later.
443                         urlMap[normalizedName] = url;
444                     }
445                 }
446             }
447
448             return {
449                 prefix: prefix,
450                 name: normalizedName,
451                 parentMap: parentModuleMap,
452                 url: url,
453                 originalName: originalName,
454                 fullName: prefix ? prefix + "!" + (normalizedName || '') : normalizedName
455             };
456         }
457
458         /**
459          * Determine if priority loading is done. If so clear the priorityWait
460          */
461         function isPriorityDone() {
462             var priorityDone = true,
463                 priorityWait = config.priorityWait,
464                 priorityName, i;
465             if (priorityWait) {
466                 for (i = 0; (priorityName = priorityWait[i]); i++) {
467                     if (!loaded[priorityName]) {
468                         priorityDone = false;
469                         break;
470                     }
471                 }
472                 if (priorityDone) {
473                     delete config.priorityWait;
474                 }
475             }
476             return priorityDone;
477         }
478
479         function makeContextModuleFunc(func, relModuleMap, enableBuildCallback) {
480             return function () {
481                 //A version of a require function that passes a moduleName
482                 //value for items that may need to
483                 //look up paths relative to the moduleName
484                 var args = aps.call(arguments, 0), lastArg;
485                 if (enableBuildCallback &&
486                     isFunction((lastArg = args[args.length - 1]))) {
487                     lastArg.__requireJsBuild = true;
488                 }
489                 args.push(relModuleMap);
490                 return func.apply(null, args);
491             };
492         }
493
494         /**
495          * Helper function that creates a require function object to give to
496          * modules that ask for it as a dependency. It needs to be specific
497          * per module because of the implication of path mappings that may
498          * need to be relative to the module name.
499          */
500         function makeRequire(relModuleMap, enableBuildCallback, altRequire) {
501             var modRequire = makeContextModuleFunc(altRequire || context.require, relModuleMap, enableBuildCallback);
502
503             mixin(modRequire, {
504                 nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap),
505                 toUrl: makeContextModuleFunc(context.toUrl, relModuleMap),
506                 defined: makeContextModuleFunc(context.requireDefined, relModuleMap),
507                 specified: makeContextModuleFunc(context.requireSpecified, relModuleMap),
508                 isBrowser: req.isBrowser
509             });
510             return modRequire;
511         }
512
513         /*
514          * Queues a dependency for checking after the loader is out of a
515          * "paused" state, for example while a script file is being loaded
516          * in the browser, where it may have many modules defined in it.
517          */
518         function queueDependency(manager) {
519             context.paused.push(manager);
520         }
521
522         function execManager(manager) {
523             var i, ret, err, errFile, errModuleTree,
524                 cb = manager.callback,
525                 map = manager.map,
526                 fullName = map.fullName,
527                 args = manager.deps,
528                 listeners = manager.listeners,
529                 execCb = config.requireExecCb || req.execCb,
530                 cjsModule;
531
532             //Call the callback to define the module, if necessary.
533             if (cb && isFunction(cb)) {
534                 if (config.catchError.define) {
535                     try {
536                         ret = execCb(fullName, manager.callback, args, defined[fullName]);
537                     } catch (e) {
538                         err = e;
539                     }
540                 } else {
541                     ret = execCb(fullName, manager.callback, args, defined[fullName]);
542                 }
543
544                 if (fullName) {
545                     //If setting exports via "module" is in play,
546                     //favor that over return value and exports. After that,
547                     //favor a non-undefined return value over exports use.
548                     cjsModule = manager.cjsModule;
549                     if (cjsModule &&
550                         cjsModule.exports !== undefined &&
551                         //Make sure it is not already the exports value
552                         cjsModule.exports !== defined[fullName]) {
553                         ret = defined[fullName] = manager.cjsModule.exports;
554                     } else if (ret === undefined && manager.usingExports) {
555                         //exports already set the defined value.
556                         ret = defined[fullName];
557                     } else {
558                         //Use the return value from the function.
559                         defined[fullName] = ret;
560                         //If this module needed full execution in a build
561                         //environment, mark that now.
562                         if (needFullExec[fullName]) {
563                             fullExec[fullName] = true;
564                         }
565                     }
566                 }
567             } else if (fullName) {
568                 //May just be an object definition for the module. Only
569                 //worry about defining if have a module name.
570                 ret = defined[fullName] = cb;
571
572                 //If this module needed full execution in a build
573                 //environment, mark that now.
574                 if (needFullExec[fullName]) {
575                     fullExec[fullName] = true;
576                 }
577             }
578
579             //Clean up waiting. Do this before error calls, and before
580             //calling back listeners, so that bookkeeping is correct
581             //in the event of an error and error is reported in correct order,
582             //since the listeners will likely have errors if the
583             //onError function does not throw.
584             if (waiting[manager.id]) {
585                 delete waiting[manager.id];
586                 manager.isDone = true;
587                 context.waitCount -= 1;
588                 if (context.waitCount === 0) {
589                     //Clear the wait array used for cycles.
590                     waitAry = [];
591                 }
592             }
593
594             //Do not need to track manager callback now that it is defined.
595             delete managerCallbacks[fullName];
596
597             //Allow instrumentation like the optimizer to know the order
598             //of modules executed and their dependencies.
599             if (req.onResourceLoad && !manager.placeholder) {
600                 req.onResourceLoad(context, map, manager.depArray);
601             }
602
603             if (err) {
604                 errFile = (fullName ? makeModuleMap(fullName).url : '') ||
605                            err.fileName || err.sourceURL;
606                 errModuleTree = err.moduleTree;
607                 err = makeError('defineerror', 'Error evaluating ' +
608                                 'module "' + fullName + '" at location "' +
609                                 errFile + '":\n' +
610                                 err + '\nfileName:' + errFile +
611                                 '\nlineNumber: ' + (err.lineNumber || err.line), err);
612                 err.moduleName = fullName;
613                 err.moduleTree = errModuleTree;
614                 return req.onError(err);
615             }
616
617             //Let listeners know of this manager's value.
618             for (i = 0; (cb = listeners[i]); i++) {
619                 cb(ret);
620             }
621
622             return undefined;
623         }
624
625         /**
626          * Helper that creates a callack function that is called when a dependency
627          * is ready, and sets the i-th dependency for the manager as the
628          * value passed to the callback generated by this function.
629          */
630         function makeArgCallback(manager, i) {
631             return function (value) {
632                 //Only do the work if it has not been done
633                 //already for a dependency. Cycle breaking
634                 //logic in forceExec could mean this function
635                 //is called more than once for a given dependency.
636                 if (!manager.depDone[i]) {
637                     manager.depDone[i] = true;
638                     manager.deps[i] = value;
639                     manager.depCount -= 1;
640                     if (!manager.depCount) {
641                         //All done, execute!
642                         execManager(manager);
643                     }
644                 }
645             };
646         }
647
648         function callPlugin(pluginName, depManager) {
649             var map = depManager.map,
650                 fullName = map.fullName,
651                 name = map.name,
652                 plugin = plugins[pluginName] ||
653                         (plugins[pluginName] = defined[pluginName]),
654                 load;
655
656             //No need to continue if the manager is already
657             //in the process of loading.
658             if (depManager.loading) {
659                 return;
660             }
661             depManager.loading = true;
662
663             load = function (ret) {
664                 depManager.callback = function () {
665                     return ret;
666                 };
667                 execManager(depManager);
668
669                 loaded[depManager.id] = true;
670
671                 //The loading of this plugin
672                 //might have placed other things
673                 //in the paused queue. In particular,
674                 //a loader plugin that depends on
675                 //a different plugin loaded resource.
676                 resume();
677             };
678
679             //Allow plugins to load other code without having to know the
680             //context or how to "complete" the load.
681             load.fromText = function (moduleName, text) {
682                 /*jslint evil: true */
683                 var hasInteractive = useInteractive;
684
685                 //Indicate a the module is in process of loading.
686                 loaded[moduleName] = false;
687                 context.scriptCount += 1;
688
689                 //Indicate this is not a "real" module, so do not track it
690                 //for builds, it does not map to a real file.
691                 context.fake[moduleName] = true;
692
693                 //Turn off interactive script matching for IE for any define
694                 //calls in the text, then turn it back on at the end.
695                 if (hasInteractive) {
696                     useInteractive = false;
697                 }
698
699                 req.exec(text);
700
701                 if (hasInteractive) {
702                     useInteractive = true;
703                 }
704
705                 //Support anonymous modules.
706                 context.completeLoad(moduleName);
707             };
708
709             //No need to continue if the plugin value has already been
710             //defined by a build.
711             if (fullName in defined) {
712                 load(defined[fullName]);
713             } else {
714                 //Use parentName here since the plugin's name is not reliable,
715                 //could be some weird string with no path that actually wants to
716                 //reference the parentName's path.
717                 plugin.load(name, makeRequire(map.parentMap, true, function (deps, cb) {
718                     var moduleDeps = [],
719                         i, dep, depMap;
720                     //Convert deps to full names and hold on to them
721                     //for reference later, when figuring out if they
722                     //are blocked by a circular dependency.
723                     for (i = 0; (dep = deps[i]); i++) {
724                         depMap = makeModuleMap(dep, map.parentMap);
725                         deps[i] = depMap.fullName;
726                         if (!depMap.prefix) {
727                             moduleDeps.push(deps[i]);
728                         }
729                     }
730                     depManager.moduleDeps = (depManager.moduleDeps || []).concat(moduleDeps);
731                     return context.require(deps, cb);
732                 }), load, config);
733             }
734         }
735
736         /**
737          * Adds the manager to the waiting queue. Only fully
738          * resolved items should be in the waiting queue.
739          */
740         function addWait(manager) {
741             if (!waiting[manager.id]) {
742                 waiting[manager.id] = manager;
743                 waitAry.push(manager);
744                 context.waitCount += 1;
745             }
746         }
747
748         /**
749          * Function added to every manager object. Created out here
750          * to avoid new function creation for each manager instance.
751          */
752         function managerAdd(cb) {
753             this.listeners.push(cb);
754         }
755
756         function getManager(map, shouldQueue) {
757             var fullName = map.fullName,
758                 prefix = map.prefix,
759                 plugin = prefix ? plugins[prefix] ||
760                                 (plugins[prefix] = defined[prefix]) : null,
761                 manager, created, pluginManager, prefixMap;
762
763             if (fullName) {
764                 manager = managerCallbacks[fullName];
765             }
766
767             if (!manager) {
768                 created = true;
769                 manager = {
770                     //ID is just the full name, but if it is a plugin resource
771                     //for a plugin that has not been loaded,
772                     //then add an ID counter to it.
773                     id: (prefix && !plugin ?
774                         (managerCounter++) + '__p@:' : '') +
775                         (fullName || '__r@' + (managerCounter++)),
776                     map: map,
777                     depCount: 0,
778                     depDone: [],
779                     depCallbacks: [],
780                     deps: [],
781                     listeners: [],
782                     add: managerAdd
783                 };
784
785                 specified[manager.id] = true;
786
787                 //Only track the manager/reuse it if this is a non-plugin
788                 //resource. Also only track plugin resources once
789                 //the plugin has been loaded, and so the fullName is the
790                 //true normalized value.
791                 if (fullName && (!prefix || plugins[prefix])) {
792                     managerCallbacks[fullName] = manager;
793                 }
794             }
795
796             //If there is a plugin needed, but it is not loaded,
797             //first load the plugin, then continue on.
798             if (prefix && !plugin) {
799                 prefixMap = makeModuleMap(prefix);
800
801                 //Clear out defined and urlFetched if the plugin was previously
802                 //loaded/defined, but not as full module (as in a build
803                 //situation). However, only do this work if the plugin is in
804                 //defined but does not have a module export value.
805                 if (prefix in defined && !defined[prefix]) {
806                     delete defined[prefix];
807                     delete urlFetched[prefixMap.url];
808                 }
809
810                 pluginManager = getManager(prefixMap, true);
811                 pluginManager.add(function (plugin) {
812                     //Create a new manager for the normalized
813                     //resource ID and have it call this manager when
814                     //done.
815                     var newMap = makeModuleMap(map.originalName, map.parentMap),
816                         normalizedManager = getManager(newMap, true);
817
818                     //Indicate this manager is a placeholder for the real,
819                     //normalized thing. Important for when trying to map
820                     //modules and dependencies, for instance, in a build.
821                     manager.placeholder = true;
822
823                     normalizedManager.add(function (resource) {
824                         manager.callback = function () {
825                             return resource;
826                         };
827                         execManager(manager);
828                     });
829                 });
830             } else if (created && shouldQueue) {
831                 //Indicate the resource is not loaded yet if it is to be
832                 //queued.
833                 loaded[manager.id] = false;
834                 queueDependency(manager);
835                 addWait(manager);
836             }
837
838             return manager;
839         }
840
841         function main(inName, depArray, callback, relModuleMap) {
842             var moduleMap = makeModuleMap(inName, relModuleMap),
843                 name = moduleMap.name,
844                 fullName = moduleMap.fullName,
845                 manager = getManager(moduleMap),
846                 id = manager.id,
847                 deps = manager.deps,
848                 i, depArg, depName, depPrefix, cjsMod;
849
850             if (fullName) {
851                 //If module already defined for context, or already loaded,
852                 //then leave. Also leave if jQuery is registering but it does
853                 //not match the desired version number in the config.
854                 if (fullName in defined || loaded[id] === true ||
855                     (fullName === "jquery" && config.jQuery &&
856                      config.jQuery !== callback().fn.jquery)) {
857                     return;
858                 }
859
860                 //Set specified/loaded here for modules that are also loaded
861                 //as part of a layer, where onScriptLoad is not fired
862                 //for those cases. Do this after the inline define and
863                 //dependency tracing is done.
864                 specified[id] = true;
865                 loaded[id] = true;
866
867                 //If module is jQuery set up delaying its dom ready listeners.
868                 if (fullName === "jquery" && callback) {
869                     jQueryCheck(callback());
870                 }
871             }
872
873             //Attach real depArray and callback to the manager. Do this
874             //only if the module has not been defined already, so do this after
875             //the fullName checks above. IE can call main() more than once
876             //for a module.
877             manager.depArray = depArray;
878             manager.callback = callback;
879
880             //Add the dependencies to the deps field, and register for callbacks
881             //on the dependencies.
882             for (i = 0; i < depArray.length; i++) {
883                 depArg = depArray[i];
884                 //There could be cases like in IE, where a trailing comma will
885                 //introduce a null dependency, so only treat a real dependency
886                 //value as a dependency.
887                 if (depArg) {
888                     //Split the dependency name into plugin and name parts
889                     depArg = makeModuleMap(depArg, (name ? moduleMap : relModuleMap));
890                     depName = depArg.fullName;
891                     depPrefix = depArg.prefix;
892
893                     //Fix the name in depArray to be just the name, since
894                     //that is how it will be called back later.
895                     depArray[i] = depName;
896
897                     //Fast path CommonJS standard dependencies.
898                     if (depName === "require") {
899                         deps[i] = makeRequire(moduleMap);
900                     } else if (depName === "exports") {
901                         //CommonJS module spec 1.1
902                         deps[i] = defined[fullName] = {};
903                         manager.usingExports = true;
904                     } else if (depName === "module") {
905                         //CommonJS module spec 1.1
906                         manager.cjsModule = cjsMod = deps[i] = {
907                             id: name,
908                             uri: name ? context.nameToUrl(name, null, relModuleMap) : undefined,
909                             exports: defined[fullName]
910                         };
911                     } else if (depName in defined && !(depName in waiting) &&
912                                (!(fullName in needFullExec) ||
913                                 (fullName in needFullExec && fullExec[depName]))) {
914                         //Module already defined, and not in a build situation
915                         //where the module is a something that needs full
916                         //execution and this dependency has not been fully
917                         //executed. See r.js's requirePatch.js for more info
918                         //on fullExec.
919                         deps[i] = defined[depName];
920                     } else {
921                         //Mark this dependency as needing full exec if
922                         //the current module needs full exec.
923                         if (fullName in needFullExec) {
924                             needFullExec[depName] = true;
925                             //Reset state so fully executed code will get
926                             //picked up correctly.
927                             delete defined[depName];
928                             urlFetched[depArg.url] = false;
929                         }
930
931                         //Either a resource that is not loaded yet, or a plugin
932                         //resource for either a plugin that has not
933                         //loaded yet.
934                         manager.depCount += 1;
935                         manager.depCallbacks[i] = makeArgCallback(manager, i);
936                         getManager(depArg, true).add(manager.depCallbacks[i]);
937                     }
938                 }
939             }
940
941             //Do not bother tracking the manager if it is all done.
942             if (!manager.depCount) {
943                 //All done, execute!
944                 execManager(manager);
945             } else {
946                 addWait(manager);
947             }
948         }
949
950         /**
951          * Convenience method to call main for a define call that was put on
952          * hold in the defQueue.
953          */
954         function callDefMain(args) {
955             main.apply(null, args);
956         }
957
958         /**
959          * jQuery 1.4.3+ supports ways to hold off calling
960          * calling jQuery ready callbacks until all scripts are loaded. Be sure
961          * to track it if the capability exists.. Also, since jQuery 1.4.3 does
962          * not register as a module, need to do some global inference checking.
963          * Even if it does register as a module, not guaranteed to be the precise
964          * name of the global. If a jQuery is tracked for this context, then go
965          * ahead and register it as a module too, if not already in process.
966          */
967         jQueryCheck = function (jqCandidate) {
968             if (!context.jQuery) {
969                 var $ = jqCandidate || (typeof jQuery !== "undefined" ? jQuery : null);
970
971                 if ($) {
972                     //If a specific version of jQuery is wanted, make sure to only
973                     //use this jQuery if it matches.
974                     if (config.jQuery && $.fn.jquery !== config.jQuery) {
975                         return;
976                     }
977
978                     if ("holdReady" in $ || "readyWait" in $) {
979                         context.jQuery = $;
980
981                         //Manually create a "jquery" module entry if not one already
982                         //or in process. Note this could trigger an attempt at
983                         //a second jQuery registration, but does no harm since
984                         //the first one wins, and it is the same value anyway.
985                         callDefMain(["jquery", [], function () {
986                             return jQuery;
987                         }]);
988
989                         //Ask jQuery to hold DOM ready callbacks.
990                         if (context.scriptCount) {
991                             jQueryHoldReady($, true);
992                             context.jQueryIncremented = true;
993                         }
994                     }
995                 }
996             }
997         };
998
999         function findCycle(manager, traced) {
1000             var fullName = manager.map.fullName,
1001                 depArray = manager.depArray,
1002                 fullyLoaded = true,
1003                 i, depName, depManager, result;
1004
1005             if (manager.isDone || !fullName || !loaded[fullName]) {
1006                 return result;
1007             }
1008
1009             //Found the cycle.
1010             if (traced[fullName]) {
1011                 return manager;
1012             }
1013
1014             traced[fullName] = true;
1015
1016             //Trace through the dependencies.
1017             if (depArray) {
1018                 for (i = 0; i < depArray.length; i++) {
1019                     //Some array members may be null, like if a trailing comma
1020                     //IE, so do the explicit [i] access and check if it has a value.
1021                     depName = depArray[i];
1022                     if (!loaded[depName] && !reservedDependencies[depName]) {
1023                         fullyLoaded = false;
1024                         break;
1025                     }
1026                     depManager = waiting[depName];
1027                     if (depManager && !depManager.isDone && loaded[depName]) {
1028                         result = findCycle(depManager, traced);
1029                         if (result) {
1030                             break;
1031                         }
1032                     }
1033                 }
1034                 if (!fullyLoaded) {
1035                     //Discard the cycle that was found, since it cannot
1036                     //be forced yet. Also clear this module from traced.
1037                     result = undefined;
1038                     delete traced[fullName];
1039                 }
1040             }
1041
1042             return result;
1043         }
1044
1045         function forceExec(manager, traced) {
1046             var fullName = manager.map.fullName,
1047                 depArray = manager.depArray,
1048                 i, depName, depManager, prefix, prefixManager, value;
1049
1050
1051             if (manager.isDone || !fullName || !loaded[fullName]) {
1052                 return undefined;
1053             }
1054
1055             if (fullName) {
1056                 if (traced[fullName]) {
1057                     return defined[fullName];
1058                 }
1059
1060                 traced[fullName] = true;
1061             }
1062
1063             //Trace through the dependencies.
1064             if (depArray) {
1065                 for (i = 0; i < depArray.length; i++) {
1066                     //Some array members may be null, like if a trailing comma
1067                     //IE, so do the explicit [i] access and check if it has a value.
1068                     depName = depArray[i];
1069                     if (depName) {
1070                         //First, make sure if it is a plugin resource that the
1071                         //plugin is not blocked.
1072                         prefix = makeModuleMap(depName).prefix;
1073                         if (prefix && (prefixManager = waiting[prefix])) {
1074                             forceExec(prefixManager, traced);
1075                         }
1076                         depManager = waiting[depName];
1077                         if (depManager && !depManager.isDone && loaded[depName]) {
1078                             value = forceExec(depManager, traced);
1079                             manager.depCallbacks[i](value);
1080                         }
1081                     }
1082                 }
1083             }
1084
1085             return defined[fullName];
1086         }
1087
1088         /**
1089          * Checks if all modules for a context are loaded, and if so, evaluates the
1090          * new ones in right dependency order.
1091          *
1092          * @private
1093          */
1094         function checkLoaded() {
1095             var waitInterval = config.waitSeconds * 1000,
1096                 //It is possible to disable the wait interval by using waitSeconds of 0.
1097                 expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
1098                 noLoads = "", hasLoadedProp = false, stillLoading = false,
1099                 cycleDeps = [],
1100                 i, prop, err, manager, cycleManager, moduleDeps;
1101
1102             //If there are items still in the paused queue processing wait.
1103             //This is particularly important in the sync case where each paused
1104             //item is processed right away but there may be more waiting.
1105             if (context.pausedCount > 0) {
1106                 return undefined;
1107             }
1108
1109             //Determine if priority loading is done. If so clear the priority. If
1110             //not, then do not check
1111             if (config.priorityWait) {
1112                 if (isPriorityDone()) {
1113                     //Call resume, since it could have
1114                     //some waiting dependencies to trace.
1115                     resume();
1116                 } else {
1117                     return undefined;
1118                 }
1119             }
1120
1121             //See if anything is still in flight.
1122             for (prop in loaded) {
1123                 if (!(prop in empty)) {
1124                     hasLoadedProp = true;
1125                     if (!loaded[prop]) {
1126                         if (expired) {
1127                             noLoads += prop + " ";
1128                         } else {
1129                             stillLoading = true;
1130                             if (prop.indexOf('!') === -1) {
1131                                 //No reason to keep looking for unfinished
1132                                 //loading. If the only stillLoading is a
1133                                 //plugin resource though, keep going,
1134                                 //because it may be that a plugin resource
1135                                 //is waiting on a non-plugin cycle.
1136                                 cycleDeps = [];
1137                                 break;
1138                             } else {
1139                                 moduleDeps = managerCallbacks[prop] && managerCallbacks[prop].moduleDeps;
1140                                 if (moduleDeps) {
1141                                     cycleDeps.push.apply(cycleDeps, moduleDeps);
1142                                 }
1143                             }
1144                         }
1145                     }
1146                 }
1147             }
1148
1149             //Check for exit conditions.
1150             if (!hasLoadedProp && !context.waitCount) {
1151                 //If the loaded object had no items, then the rest of
1152                 //the work below does not need to be done.
1153                 return undefined;
1154             }
1155             if (expired && noLoads) {
1156                 //If wait time expired, throw error of unloaded modules.
1157                 err = makeError("timeout", "Load timeout for modules: " + noLoads);
1158                 err.requireType = "timeout";
1159                 err.requireModules = noLoads;
1160                 err.contextName = context.contextName;
1161                 return req.onError(err);
1162             }
1163
1164             //If still loading but a plugin is waiting on a regular module cycle
1165             //break the cycle.
1166             if (stillLoading && cycleDeps.length) {
1167                 for (i = 0; (manager = waiting[cycleDeps[i]]); i++) {
1168                     if ((cycleManager = findCycle(manager, {}))) {
1169                         forceExec(cycleManager, {});
1170                         break;
1171                     }
1172                 }
1173
1174             }
1175
1176             //If still waiting on loads, and the waiting load is something
1177             //other than a plugin resource, or there are still outstanding
1178             //scripts, then just try back later.
1179             if (!expired && (stillLoading || context.scriptCount)) {
1180                 //Something is still waiting to load. Wait for it, but only
1181                 //if a timeout is not already in effect.
1182                 if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
1183                     checkLoadedTimeoutId = setTimeout(function () {
1184                         checkLoadedTimeoutId = 0;
1185                         checkLoaded();
1186                     }, 50);
1187                 }
1188                 return undefined;
1189             }
1190
1191             //If still have items in the waiting cue, but all modules have
1192             //been loaded, then it means there are some circular dependencies
1193             //that need to be broken.
1194             //However, as a waiting thing is fired, then it can add items to
1195             //the waiting cue, and those items should not be fired yet, so
1196             //make sure to redo the checkLoaded call after breaking a single
1197             //cycle, if nothing else loaded then this logic will pick it up
1198             //again.
1199             if (context.waitCount) {
1200                 //Cycle through the waitAry, and call items in sequence.
1201                 for (i = 0; (manager = waitAry[i]); i++) {
1202                     forceExec(manager, {});
1203                 }
1204
1205                 //If anything got placed in the paused queue, run it down.
1206                 if (context.paused.length) {
1207                     resume();
1208                 }
1209
1210                 //Only allow this recursion to a certain depth. Only
1211                 //triggered by errors in calling a module in which its
1212                 //modules waiting on it cannot finish loading, or some circular
1213                 //dependencies that then may add more dependencies.
1214                 //The value of 5 is a bit arbitrary. Hopefully just one extra
1215                 //pass, or two for the case of circular dependencies generating
1216                 //more work that gets resolved in the sync node case.
1217                 if (checkLoadedDepth < 5) {
1218                     checkLoadedDepth += 1;
1219                     checkLoaded();
1220                 }
1221             }
1222
1223             checkLoadedDepth = 0;
1224
1225             //Check for DOM ready, and nothing is waiting across contexts.
1226             req.checkReadyState();
1227
1228             return undefined;
1229         }
1230
1231         /**
1232          * Resumes tracing of dependencies and then checks if everything is loaded.
1233          */
1234         resume = function () {
1235             var manager, map, url, i, p, args, fullName;
1236
1237             //Any defined modules in the global queue, intake them now.
1238             context.takeGlobalQueue();
1239
1240             resumeDepth += 1;
1241
1242             if (context.scriptCount <= 0) {
1243                 //Synchronous envs will push the number below zero with the
1244                 //decrement above, be sure to set it back to zero for good measure.
1245                 //require() calls that also do not end up loading scripts could
1246                 //push the number negative too.
1247                 context.scriptCount = 0;
1248             }
1249
1250             //Make sure any remaining defQueue items get properly processed.
1251             while (defQueue.length) {
1252                 args = defQueue.shift();
1253                 if (args[0] === null) {
1254                     return req.onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
1255                 } else {
1256                     callDefMain(args);
1257                 }
1258             }
1259
1260             //Skip the resume of paused dependencies
1261             //if current context is in priority wait.
1262             if (!config.priorityWait || isPriorityDone()) {
1263                 while (context.paused.length) {
1264                     p = context.paused;
1265                     context.pausedCount += p.length;
1266                     //Reset paused list
1267                     context.paused = [];
1268
1269                     for (i = 0; (manager = p[i]); i++) {
1270                         map = manager.map;
1271                         url = map.url;
1272                         fullName = map.fullName;
1273
1274                         //If the manager is for a plugin managed resource,
1275                         //ask the plugin to load it now.
1276                         if (map.prefix) {
1277                             callPlugin(map.prefix, manager);
1278                         } else {
1279                             //Regular dependency.
1280                             if (!urlFetched[url] && !loaded[fullName]) {
1281                                 (config.requireLoad || req.load)(context, fullName, url);
1282
1283                                 //Mark the URL as fetched, but only if it is
1284                                 //not an empty: URL, used by the optimizer.
1285                                 //In that case we need to be sure to call
1286                                 //load() for each module that is mapped to
1287                                 //empty: so that dependencies are satisfied
1288                                 //correctly.
1289                                 if (url.indexOf('empty:') !== 0) {
1290                                     urlFetched[url] = true;
1291                                 }
1292                             }
1293                         }
1294                     }
1295
1296                     //Move the start time for timeout forward.
1297                     context.startTime = (new Date()).getTime();
1298                     context.pausedCount -= p.length;
1299                 }
1300             }
1301
1302             //Only check if loaded when resume depth is 1. It is likely that
1303             //it is only greater than 1 in sync environments where a factory
1304             //function also then calls the callback-style require. In those
1305             //cases, the checkLoaded should not occur until the resume
1306             //depth is back at the top level.
1307             if (resumeDepth === 1) {
1308                 checkLoaded();
1309             }
1310
1311             resumeDepth -= 1;
1312
1313             return undefined;
1314         };
1315
1316         //Define the context object. Many of these fields are on here
1317         //just to make debugging easier.
1318         context = {
1319             contextName: contextName,
1320             config: config,
1321             defQueue: defQueue,
1322             waiting: waiting,
1323             waitCount: 0,
1324             specified: specified,
1325             loaded: loaded,
1326             urlMap: urlMap,
1327             urlFetched: urlFetched,
1328             scriptCount: 0,
1329             defined: defined,
1330             paused: [],
1331             pausedCount: 0,
1332             plugins: plugins,
1333             needFullExec: needFullExec,
1334             fake: {},
1335             fullExec: fullExec,
1336             managerCallbacks: managerCallbacks,
1337             makeModuleMap: makeModuleMap,
1338             normalize: normalize,
1339             /**
1340              * Set a configuration for the context.
1341              * @param {Object} cfg config object to integrate.
1342              */
1343             configure: function (cfg) {
1344                 var paths, prop, packages, pkgs, packagePaths, requireWait;
1345
1346                 //Make sure the baseUrl ends in a slash.
1347                 if (cfg.baseUrl) {
1348                     if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== "/") {
1349                         cfg.baseUrl += "/";
1350                     }
1351                 }
1352
1353                 //Save off the paths and packages since they require special processing,
1354                 //they are additive.
1355                 paths = config.paths;
1356                 packages = config.packages;
1357                 pkgs = config.pkgs;
1358
1359                 //Mix in the config values, favoring the new values over
1360                 //existing ones in context.config.
1361                 mixin(config, cfg, true);
1362
1363                 //Adjust paths if necessary.
1364                 if (cfg.paths) {
1365                     for (prop in cfg.paths) {
1366                         if (!(prop in empty)) {
1367                             paths[prop] = cfg.paths[prop];
1368                         }
1369                     }
1370                     config.paths = paths;
1371                 }
1372
1373                 packagePaths = cfg.packagePaths;
1374                 if (packagePaths || cfg.packages) {
1375                     //Convert packagePaths into a packages config.
1376                     if (packagePaths) {
1377                         for (prop in packagePaths) {
1378                             if (!(prop in empty)) {
1379                                 configurePackageDir(pkgs, packagePaths[prop], prop);
1380                             }
1381                         }
1382                     }
1383
1384                     //Adjust packages if necessary.
1385                     if (cfg.packages) {
1386                         configurePackageDir(pkgs, cfg.packages);
1387                     }
1388
1389                     //Done with modifications, assing packages back to context config
1390                     config.pkgs = pkgs;
1391                 }
1392
1393                 //If priority loading is in effect, trigger the loads now
1394                 if (cfg.priority) {
1395                     //Hold on to requireWait value, and reset it after done
1396                     requireWait = context.requireWait;
1397
1398                     //Allow tracing some require calls to allow the fetching
1399                     //of the priority config.
1400                     context.requireWait = false;
1401                     //But first, call resume to register any defined modules that may
1402                     //be in a data-main built file before the priority config
1403                     //call.
1404                     resume();
1405
1406                     context.require(cfg.priority);
1407
1408                     //Trigger a resume right away, for the case when
1409                     //the script with the priority load is done as part
1410                     //of a data-main call. In that case the normal resume
1411                     //call will not happen because the scriptCount will be
1412                     //at 1, since the script for data-main is being processed.
1413                     resume();
1414
1415                     //Restore previous state.
1416                     context.requireWait = requireWait;
1417                     config.priorityWait = cfg.priority;
1418                 }
1419
1420                 //If a deps array or a config callback is specified, then call
1421                 //require with those args. This is useful when require is defined as a
1422                 //config object before require.js is loaded.
1423                 if (cfg.deps || cfg.callback) {
1424                     context.require(cfg.deps || [], cfg.callback);
1425                 }
1426             },
1427
1428             requireDefined: function (moduleName, relModuleMap) {
1429                 return makeModuleMap(moduleName, relModuleMap).fullName in defined;
1430             },
1431
1432             requireSpecified: function (moduleName, relModuleMap) {
1433                 return makeModuleMap(moduleName, relModuleMap).fullName in specified;
1434             },
1435
1436             require: function (deps, callback, relModuleMap) {
1437                 var moduleName, fullName, moduleMap;
1438                 if (typeof deps === "string") {
1439                     if (isFunction(callback)) {
1440                         //Invalid call
1441                         return req.onError(makeError("requireargs", "Invalid require call"));
1442                     }
1443
1444                     //Synchronous access to one module. If require.get is
1445                     //available (as in the Node adapter), prefer that.
1446                     //In this case deps is the moduleName and callback is
1447                     //the relModuleMap
1448                     if (req.get) {
1449                         return req.get(context, deps, callback);
1450                     }
1451
1452                     //Just return the module wanted. In this scenario, the
1453                     //second arg (if passed) is just the relModuleMap.
1454                     moduleName = deps;
1455                     relModuleMap = callback;
1456
1457                     //Normalize module name, if it contains . or ..
1458                     moduleMap = makeModuleMap(moduleName, relModuleMap);
1459                     fullName = moduleMap.fullName;
1460
1461                     if (!(fullName in defined)) {
1462                         return req.onError(makeError("notloaded", "Module name '" +
1463                                     moduleMap.fullName +
1464                                     "' has not been loaded yet for context: " +
1465                                     contextName));
1466                     }
1467                     return defined[fullName];
1468                 }
1469
1470                 //Call main but only if there are dependencies or
1471                 //a callback to call.
1472                 if (deps && deps.length || callback) {
1473                     main(null, deps, callback, relModuleMap);
1474                 }
1475
1476                 //If the require call does not trigger anything new to load,
1477                 //then resume the dependency processing.
1478                 if (!context.requireWait) {
1479                     while (!context.scriptCount && context.paused.length) {
1480                         resume();
1481                     }
1482                 }
1483                 return context.require;
1484             },
1485
1486             /**
1487              * Internal method to transfer globalQueue items to this context's
1488              * defQueue.
1489              */
1490             takeGlobalQueue: function () {
1491                 //Push all the globalDefQueue items into the context's defQueue
1492                 if (globalDefQueue.length) {
1493                     //Array splice in the values since the context code has a
1494                     //local var ref to defQueue, so cannot just reassign the one
1495                     //on context.
1496                     apsp.apply(context.defQueue,
1497                                [context.defQueue.length - 1, 0].concat(globalDefQueue));
1498                     globalDefQueue = [];
1499                 }
1500             },
1501
1502             /**
1503              * Internal method used by environment adapters to complete a load event.
1504              * A load event could be a script load or just a load pass from a synchronous
1505              * load call.
1506              * @param {String} moduleName the name of the module to potentially complete.
1507              */
1508             completeLoad: function (moduleName) {
1509                 var args;
1510
1511                 context.takeGlobalQueue();
1512
1513                 while (defQueue.length) {
1514                     args = defQueue.shift();
1515
1516                     if (args[0] === null) {
1517                         args[0] = moduleName;
1518                         break;
1519                     } else if (args[0] === moduleName) {
1520                         //Found matching define call for this script!
1521                         break;
1522                     } else {
1523                         //Some other named define call, most likely the result
1524                         //of a build layer that included many define calls.
1525                         callDefMain(args);
1526                         args = null;
1527                     }
1528                 }
1529                 if (args) {
1530                     callDefMain(args);
1531                 } else {
1532                     //A script that does not call define(), so just simulate
1533                     //the call for it. Special exception for jQuery dynamic load.
1534                     callDefMain([moduleName, [],
1535                                 moduleName === "jquery" && typeof jQuery !== "undefined" ?
1536                                 function () {
1537                                     return jQuery;
1538                                 } : null]);
1539                 }
1540
1541                 //Doing this scriptCount decrement branching because sync envs
1542                 //need to decrement after resume, otherwise it looks like
1543                 //loading is complete after the first dependency is fetched.
1544                 //For browsers, it works fine to decrement after, but it means
1545                 //the checkLoaded setTimeout 50 ms cost is taken. To avoid
1546                 //that cost, decrement beforehand.
1547                 if (req.isAsync) {
1548                     context.scriptCount -= 1;
1549                 }
1550                 resume();
1551                 if (!req.isAsync) {
1552                     context.scriptCount -= 1;
1553                 }
1554             },
1555
1556             /**
1557              * Converts a module name + .extension into an URL path.
1558              * *Requires* the use of a module name. It does not support using
1559              * plain URLs like nameToUrl.
1560              */
1561             toUrl: function (moduleNamePlusExt, relModuleMap) {
1562                 var index = moduleNamePlusExt.lastIndexOf("."),
1563                     ext = null;
1564
1565                 if (index !== -1) {
1566                     ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
1567                     moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
1568                 }
1569
1570                 return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap);
1571             },
1572
1573             /**
1574              * Converts a module name to a file path. Supports cases where
1575              * moduleName may actually be just an URL.
1576              */
1577             nameToUrl: function (moduleName, ext, relModuleMap) {
1578                 var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
1579                     config = context.config;
1580
1581                 //Normalize module name if have a base relative module name to work from.
1582                 moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName);
1583
1584                 //If a colon is in the URL, it indicates a protocol is used and it is just
1585                 //an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file.
1586                 //The slash is important for protocol-less URLs as well as full paths.
1587                 if (req.jsExtRegExp.test(moduleName)) {
1588                     //Just a plain path, not module name lookup, so just return it.
1589                     //Add extension if it is included. This is a bit wonky, only non-.js things pass
1590                     //an extension, this method probably needs to be reworked.
1591                     url = moduleName + (ext ? ext : "");
1592                 } else {
1593                     //A module that needs to be converted to a path.
1594                     paths = config.paths;
1595                     pkgs = config.pkgs;
1596
1597                     syms = moduleName.split("/");
1598                     //For each module name segment, see if there is a path
1599                     //registered for it. Start with most specific name
1600                     //and work up from it.
1601                     for (i = syms.length; i > 0; i--) {
1602                         parentModule = syms.slice(0, i).join("/");
1603                         if (paths[parentModule]) {
1604                             syms.splice(0, i, paths[parentModule]);
1605                             break;
1606                         } else if ((pkg = pkgs[parentModule])) {
1607                             //If module name is just the package name, then looking
1608                             //for the main module.
1609                             if (moduleName === pkg.name) {
1610                                 pkgPath = pkg.location + '/' + pkg.main;
1611                             } else {
1612                                 pkgPath = pkg.location;
1613                             }
1614                             syms.splice(0, i, pkgPath);
1615                             break;
1616                         }
1617                     }
1618
1619                     //Join the path parts together, then figure out if baseUrl is needed.
1620                     url = syms.join("/") + (ext || ".js");
1621                     url = (url.charAt(0) === '/' || url.match(/^\w+:/) ? "" : config.baseUrl) + url;
1622                 }
1623
1624                 return config.urlArgs ? url +
1625                                         ((url.indexOf('?') === -1 ? '?' : '&') +
1626                                          config.urlArgs) : url;
1627             }
1628         };
1629
1630         //Make these visible on the context so can be called at the very
1631         //end of the file to bootstrap
1632         context.jQueryCheck = jQueryCheck;
1633         context.resume = resume;
1634
1635         return context;
1636     }
1637
1638     /**
1639      * Main entry point.
1640      *
1641      * If the only argument to require is a string, then the module that
1642      * is represented by that string is fetched for the appropriate context.
1643      *
1644      * If the first argument is an array, then it will be treated as an array
1645      * of dependency string names to fetch. An optional function callback can
1646      * be specified to execute when all of those dependencies are available.
1647      *
1648      * Make a local req variable to help Caja compliance (it assumes things
1649      * on a require that are not standardized), and to give a short
1650      * name for minification/local scope use.
1651      */
1652     req = requirejs = function (deps, callback) {
1653
1654         //Find the right context, use default
1655         var contextName = defContextName,
1656             context, config;
1657
1658         // Determine if have config object in the call.
1659         if (!isArray(deps) && typeof deps !== "string") {
1660             // deps is a config object
1661             config = deps;
1662             if (isArray(callback)) {
1663                 // Adjust args if there are dependencies
1664                 deps = callback;
1665                 callback = arguments[2];
1666             } else {
1667                 deps = [];
1668             }
1669         }
1670
1671         if (config && config.context) {
1672             contextName = config.context;
1673         }
1674
1675         context = contexts[contextName] ||
1676                   (contexts[contextName] = newContext(contextName));
1677
1678         if (config) {
1679             context.configure(config);
1680         }
1681
1682         return context.require(deps, callback);
1683     };
1684
1685     /**
1686      * Support require.config() to make it easier to cooperate with other
1687      * AMD loaders on globally agreed names.
1688      */
1689     req.config = function (config) {
1690         return req(config);
1691     };
1692
1693     /**
1694      * Export require as a global, but only if it does not already exist.
1695      */
1696     if (!require) {
1697         require = req;
1698     }
1699
1700     /**
1701      * Global require.toUrl(), to match global require, mostly useful
1702      * for debugging/work in the global space.
1703      */
1704     req.toUrl = function (moduleNamePlusExt) {
1705         return contexts[defContextName].toUrl(moduleNamePlusExt);
1706     };
1707
1708     req.version = version;
1709
1710     //Used to filter out dependencies that are already paths.
1711     req.jsExtRegExp = /^\/|:|\?|\.js$/;
1712     s = req.s = {
1713         contexts: contexts,
1714         //Stores a list of URLs that should not get async script tag treatment.
1715         skipAsync: {}
1716     };
1717
1718     req.isAsync = req.isBrowser = isBrowser;
1719     if (isBrowser) {
1720         head = s.head = document.getElementsByTagName("head")[0];
1721         //If BASE tag is in play, using appendChild is a problem for IE6.
1722         //When that browser dies, this can be removed. Details in this jQuery bug:
1723         //http://dev.jquery.com/ticket/2709
1724         baseElement = document.getElementsByTagName("base")[0];
1725         if (baseElement) {
1726             head = s.head = baseElement.parentNode;
1727         }
1728     }
1729
1730     /**
1731      * Any errors that require explicitly generates will be passed to this
1732      * function. Intercept/override it if you want custom error handling.
1733      * @param {Error} err the error object.
1734      */
1735     req.onError = function (err) {
1736         throw err;
1737     };
1738
1739     /**
1740      * Does the request to load a module for the browser case.
1741      * Make this a separate function to allow other environments
1742      * to override it.
1743      *
1744      * @param {Object} context the require context to find state.
1745      * @param {String} moduleName the name of the module.
1746      * @param {Object} url the URL to the module.
1747      */
1748     req.load = function (context, moduleName, url) {
1749         req.resourcesReady(false);
1750
1751         context.scriptCount += 1;
1752         req.attach(url, context, moduleName);
1753
1754         //If tracking a jQuery, then make sure its ready callbacks
1755         //are put on hold to prevent its ready callbacks from
1756         //triggering too soon.
1757         if (context.jQuery && !context.jQueryIncremented) {
1758             jQueryHoldReady(context.jQuery, true);
1759             context.jQueryIncremented = true;
1760         }
1761     };
1762
1763     function getInteractiveScript() {
1764         var scripts, i, script;
1765         if (interactiveScript && interactiveScript.readyState === 'interactive') {
1766             return interactiveScript;
1767         }
1768
1769         scripts = document.getElementsByTagName('script');
1770         for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) {
1771             if (script.readyState === 'interactive') {
1772                 return (interactiveScript = script);
1773             }
1774         }
1775
1776         return null;
1777     }
1778
1779     /**
1780      * The function that handles definitions of modules. Differs from
1781      * require() in that a string for the module should be the first argument,
1782      * and the function to execute after dependencies are loaded should
1783      * return a value to define the module corresponding to the first argument's
1784      * name.
1785      */
1786     define = function (name, deps, callback) {
1787         var node, context;
1788
1789         //Allow for anonymous functions
1790         if (typeof name !== 'string') {
1791             //Adjust args appropriately
1792             callback = deps;
1793             deps = name;
1794             name = null;
1795         }
1796
1797         //This module may not have dependencies
1798         if (!isArray(deps)) {
1799             callback = deps;
1800             deps = [];
1801         }
1802
1803         //If no name, and callback is a function, then figure out if it a
1804         //CommonJS thing with dependencies.
1805         if (!deps.length && isFunction(callback)) {
1806             //Remove comments from the callback string,
1807             //look for require calls, and pull them into the dependencies,
1808             //but only if there are function args.
1809             if (callback.length) {
1810                 callback
1811                     .toString()
1812                     .replace(commentRegExp, "")
1813                     .replace(cjsRequireRegExp, function (match, dep) {
1814                         deps.push(dep);
1815                     });
1816
1817                 //May be a CommonJS thing even without require calls, but still
1818                 //could use exports, and module. Avoid doing exports and module
1819                 //work though if it just needs require.
1820                 //REQUIRES the function to expect the CommonJS variables in the
1821                 //order listed below.
1822                 deps = (callback.length === 1 ? ["require"] : ["require", "exports", "module"]).concat(deps);
1823             }
1824         }
1825
1826         //If in IE 6-8 and hit an anonymous define() call, do the interactive
1827         //work.
1828         if (useInteractive) {
1829             node = currentlyAddingScript || getInteractiveScript();
1830             if (node) {
1831                 if (!name) {
1832                     name = node.getAttribute("data-requiremodule");
1833                 }
1834                 context = contexts[node.getAttribute("data-requirecontext")];
1835             }
1836         }
1837
1838         //Always save off evaluating the def call until the script onload handler.
1839         //This allows multiple modules to be in a file without prematurely
1840         //tracing dependencies, and allows for anonymous module support,
1841         //where the module name is not known until the script onload event
1842         //occurs. If no context, use the global queue, and get it processed
1843         //in the onscript load callback.
1844         (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
1845
1846         return undefined;
1847     };
1848
1849     define.amd = {
1850         multiversion: true,
1851         plugins: true,
1852         jQuery: true
1853     };
1854
1855     /**
1856      * Executes the text. Normally just uses eval, but can be modified
1857      * to use a more environment specific call.
1858      * @param {String} text the text to execute/evaluate.
1859      */
1860     req.exec = function (text) {
1861         return eval(text);
1862     };
1863
1864     /**
1865      * Executes a module callack function. Broken out as a separate function
1866      * solely to allow the build system to sequence the files in the built
1867      * layer in the right sequence.
1868      *
1869      * @private
1870      */
1871     req.execCb = function (name, callback, args, exports) {
1872         return callback.apply(exports, args);
1873     };
1874
1875
1876     /**
1877      * Adds a node to the DOM. Public function since used by the order plugin.
1878      * This method should not normally be called by outside code.
1879      */
1880     req.addScriptToDom = function (node) {
1881         //For some cache cases in IE 6-8, the script executes before the end
1882         //of the appendChild execution, so to tie an anonymous define
1883         //call to the module name (which is stored on the node), hold on
1884         //to a reference to this node, but clear after the DOM insertion.
1885         currentlyAddingScript = node;
1886         if (baseElement) {
1887             head.insertBefore(node, baseElement);
1888         } else {
1889             head.appendChild(node);
1890         }
1891         currentlyAddingScript = null;
1892     };
1893
1894     /**
1895      * callback for script loads, used to check status of loading.
1896      *
1897      * @param {Event} evt the event from the browser for the script
1898      * that was loaded.
1899      *
1900      * @private
1901      */
1902     req.onScriptLoad = function (evt) {
1903         //Using currentTarget instead of target for Firefox 2.0's sake. Not
1904         //all old browsers will be supported, but this one was easy enough
1905         //to support and still makes sense.
1906         var node = evt.currentTarget || evt.srcElement, contextName, moduleName,
1907             context;
1908
1909         if (evt.type === "load" || (node && readyRegExp.test(node.readyState))) {
1910             //Reset interactive script so a script node is not held onto for
1911             //to long.
1912             interactiveScript = null;
1913
1914             //Pull out the name of the module and the context.
1915             contextName = node.getAttribute("data-requirecontext");
1916             moduleName = node.getAttribute("data-requiremodule");
1917             context = contexts[contextName];
1918
1919             contexts[contextName].completeLoad(moduleName);
1920
1921             //Clean up script binding. Favor detachEvent because of IE9
1922             //issue, see attachEvent/addEventListener comment elsewhere
1923             //in this file.
1924             if (node.detachEvent && !isOpera) {
1925                 //Probably IE. If not it will throw an error, which will be
1926                 //useful to know.
1927                 node.detachEvent("onreadystatechange", req.onScriptLoad);
1928             } else {
1929                 node.removeEventListener("load", req.onScriptLoad, false);
1930             }
1931         }
1932     };
1933
1934     /**
1935      * Attaches the script represented by the URL to the current
1936      * environment. Right now only supports browser loading,
1937      * but can be redefined in other environments to do the right thing.
1938      * @param {String} url the url of the script to attach.
1939      * @param {Object} context the context that wants the script.
1940      * @param {moduleName} the name of the module that is associated with the script.
1941      * @param {Function} [callback] optional callback, defaults to require.onScriptLoad
1942      * @param {String} [type] optional type, defaults to text/javascript
1943      * @param {Function} [fetchOnlyFunction] optional function to indicate the script node
1944      * should be set up to fetch the script but do not attach it to the DOM
1945      * so that it can later be attached to execute it. This is a way for the
1946      * order plugin to support ordered loading in IE. Once the script is fetched,
1947      * but not executed, the fetchOnlyFunction will be called.
1948      */
1949     req.attach = function (url, context, moduleName, callback, type, fetchOnlyFunction) {
1950         var node;
1951         if (isBrowser) {
1952             //In the browser so use a script tag
1953             callback = callback || req.onScriptLoad;
1954             node = context && context.config && context.config.xhtml ?
1955                     document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") :
1956                     document.createElement("script");
1957             node.type = type || (context && context.config.scriptType) ||
1958                         "text/javascript";
1959             node.charset = "utf-8";
1960             //Use async so Gecko does not block on executing the script if something
1961             //like a long-polling comet tag is being run first. Gecko likes
1962             //to evaluate scripts in DOM order, even for dynamic scripts.
1963             //It will fetch them async, but only evaluate the contents in DOM
1964             //order, so a long-polling script tag can delay execution of scripts
1965             //after it. But telling Gecko we expect async gets us the behavior
1966             //we want -- execute it whenever it is finished downloading. Only
1967             //Helps Firefox 3.6+
1968             //Allow some URLs to not be fetched async. Mostly helps the order!
1969             //plugin
1970             node.async = !s.skipAsync[url];
1971
1972             if (context) {
1973                 node.setAttribute("data-requirecontext", context.contextName);
1974             }
1975             node.setAttribute("data-requiremodule", moduleName);
1976
1977             //Set up load listener. Test attachEvent first because IE9 has
1978             //a subtle issue in its addEventListener and script onload firings
1979             //that do not match the behavior of all other browsers with
1980             //addEventListener support, which fire the onload event for a
1981             //script right after the script execution. See:
1982             //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
1983             //UNFORTUNATELY Opera implements attachEvent but does not follow the script
1984             //script execution mode.
1985             if (node.attachEvent && !isOpera) {
1986                 //Probably IE. IE (at least 6-8) do not fire
1987                 //script onload right after executing the script, so
1988                 //we cannot tie the anonymous define call to a name.
1989                 //However, IE reports the script as being in "interactive"
1990                 //readyState at the time of the define call.
1991                 useInteractive = true;
1992
1993
1994                 if (fetchOnlyFunction) {
1995                     //Need to use old school onreadystate here since
1996                     //when the event fires and the node is not attached
1997                     //to the DOM, the evt.srcElement is null, so use
1998                     //a closure to remember the node.
1999                     node.onreadystatechange = function (evt) {
2000                         //Script loaded but not executed.
2001                         //Clear loaded handler, set the real one that
2002                         //waits for script execution.
2003                         if (node.readyState === 'loaded') {
2004                             node.onreadystatechange = null;
2005                             node.attachEvent("onreadystatechange", callback);
2006                             fetchOnlyFunction(node);
2007                         }
2008                     };
2009                 } else {
2010                     node.attachEvent("onreadystatechange", callback);
2011                 }
2012             } else {
2013                 node.addEventListener("load", callback, false);
2014             }
2015             node.src = url;
2016
2017             //Fetch only means waiting to attach to DOM after loaded.
2018             if (!fetchOnlyFunction) {
2019                 req.addScriptToDom(node);
2020             }
2021
2022             return node;
2023         } else if (isWebWorker) {
2024             //In a web worker, use importScripts. This is not a very
2025             //efficient use of importScripts, importScripts will block until
2026             //its script is downloaded and evaluated. However, if web workers
2027             //are in play, the expectation that a build has been done so that
2028             //only one script needs to be loaded anyway. This may need to be
2029             //reevaluated if other use cases become common.
2030             importScripts(url);
2031
2032             //Account for anonymous modules
2033             context.completeLoad(moduleName);
2034         }
2035         return null;
2036     };
2037
2038     //Look for a data-main script attribute, which could also adjust the baseUrl.
2039     if (isBrowser) {
2040         //Figure out baseUrl. Get it from the script tag with require.js in it.
2041         scripts = document.getElementsByTagName("script");
2042
2043         for (globalI = scripts.length - 1; globalI > -1 && (script = scripts[globalI]); globalI--) {
2044             //Set the "head" where we can append children by
2045             //using the script's parent.
2046             if (!head) {
2047                 head = script.parentNode;
2048             }
2049
2050             //Look for a data-main attribute to set main script for the page
2051             //to load. If it is there, the path to data main becomes the
2052             //baseUrl, if it is not already set.
2053             if ((dataMain = script.getAttribute('data-main'))) {
2054                 if (!cfg.baseUrl) {
2055                     //Pull off the directory of data-main for use as the
2056                     //baseUrl.
2057                     src = dataMain.split('/');
2058                     mainScript = src.pop();
2059                     subPath = src.length ? src.join('/')  + '/' : './';
2060
2061                     //Set final config.
2062                     cfg.baseUrl = subPath;
2063                     //Strip off any trailing .js since dataMain is now
2064                     //like a module name.
2065                     dataMain = mainScript.replace(jsSuffixRegExp, '');
2066                 }
2067
2068                 //Put the data-main script in the files to load.
2069                 cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
2070
2071                 break;
2072             }
2073         }
2074     }
2075
2076     //See if there is nothing waiting across contexts, and if not, trigger
2077     //resourcesReady.
2078     req.checkReadyState = function () {
2079         var contexts = s.contexts, prop;
2080         for (prop in contexts) {
2081             if (!(prop in empty)) {
2082                 if (contexts[prop].waitCount) {
2083                     return;
2084                 }
2085             }
2086         }
2087         req.resourcesReady(true);
2088     };
2089
2090     /**
2091      * Internal function that is triggered whenever all scripts/resources
2092      * have been loaded by the loader. Can be overridden by other, for
2093      * instance the domReady plugin, which wants to know when all resources
2094      * are loaded.
2095      */
2096     req.resourcesReady = function (isReady) {
2097         var contexts, context, prop;
2098
2099         //First, set the public variable indicating that resources are loading.
2100         req.resourcesDone = isReady;
2101
2102         if (req.resourcesDone) {
2103             //If jQuery with DOM ready delayed, release it now.
2104             contexts = s.contexts;
2105             for (prop in contexts) {
2106                 if (!(prop in empty)) {
2107                     context = contexts[prop];
2108                     if (context.jQueryIncremented) {
2109                         jQueryHoldReady(context.jQuery, false);
2110                         context.jQueryIncremented = false;
2111                     }
2112                 }
2113             }
2114         }
2115     };
2116
2117     //FF < 3.6 readyState fix. Needed so that domReady plugin
2118     //works well in that environment, since require.js is normally
2119     //loaded via an HTML script tag so it will be there before window load,
2120     //where the domReady plugin is more likely to be loaded after window load.
2121     req.pageLoaded = function () {
2122         if (document.readyState !== "complete") {
2123             document.readyState = "complete";
2124         }
2125     };
2126     if (isBrowser) {
2127         if (document.addEventListener) {
2128             if (!document.readyState) {
2129                 document.readyState = "loading";
2130                 window.addEventListener("load", req.pageLoaded, false);
2131             }
2132         }
2133     }
2134
2135     //Set up default context. If require was a configuration object, use that as base config.
2136     req(cfg);
2137
2138     //If modules are built into require.js, then need to make sure dependencies are
2139     //traced. Use a setTimeout in the browser world, to allow all the modules to register
2140     //themselves. In a non-browser env, assume that modules are not built into require.js,
2141     //which seems odd to do on the server.
2142     if (req.isAsync && typeof setTimeout !== "undefined") {
2143         ctx = s.contexts[(cfg.context || defContextName)];
2144         //Indicate that the script that includes require() is still loading,
2145         //so that require()'d dependencies are not traced until the end of the
2146         //file is parsed (approximated via the setTimeout call).
2147         ctx.requireWait = true;
2148         setTimeout(function () {
2149             ctx.requireWait = false;
2150
2151             if (!ctx.scriptCount) {
2152                 ctx.resume();
2153             }
2154             req.checkReadyState();
2155         }, 0);
2156     }
2157 }());
2158
2159
2160     if (env === 'rhino') {
2161         /**
2162  * @license RequireJS rhino Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2163  * Available via the MIT or new BSD license.
2164  * see: http://github.com/jrburke/requirejs for details
2165  */
2166
2167 /*jslint strict: false */
2168 /*global require: false, java: false, load: false */
2169
2170 (function () {
2171
2172     require.load = function (context, moduleName, url) {
2173         //Indicate a the module is in process of loading.
2174         context.scriptCount += 1;
2175
2176         load(url);
2177
2178         //Support anonymous modules.
2179         context.completeLoad(moduleName);
2180     };
2181
2182 }());
2183     } else if (env === 'node') {
2184         this.requirejsVars = {
2185             require: require,
2186             requirejs: require,
2187             define: define,
2188             nodeRequire: nodeRequire
2189         };
2190         require.nodeRequire = nodeRequire;
2191
2192         /**
2193  * @license RequireJS node Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2194  * Available via the MIT or new BSD license.
2195  * see: http://github.com/jrburke/requirejs for details
2196  */
2197
2198 /*jslint regexp: false, strict: false */
2199 /*global require: false, define: false, requirejsVars: false, process: false */
2200
2201 /**
2202  * This adapter assumes that x.js has loaded it and set up
2203  * some variables. This adapter just allows limited RequireJS
2204  * usage from within the requirejs directory. The general
2205  * node adapater is r.js.
2206  */
2207
2208 (function () {
2209     var nodeReq = requirejsVars.nodeRequire,
2210         req = requirejsVars.require,
2211         def = requirejsVars.define,
2212         fs = nodeReq('fs'),
2213         path = nodeReq('path'),
2214         vm = nodeReq('vm');
2215
2216     //Supply an implementation that allows synchronous get of a module.
2217     req.get = function (context, moduleName, relModuleMap) {
2218         if (moduleName === "require" || moduleName === "exports" || moduleName === "module") {
2219             req.onError(new Error("Explicit require of " + moduleName + " is not allowed."));
2220         }
2221
2222         var ret,
2223             moduleMap = context.makeModuleMap(moduleName, relModuleMap);
2224
2225         //Normalize module name, if it contains . or ..
2226         moduleName = moduleMap.fullName;
2227
2228         if (moduleName in context.defined) {
2229             ret = context.defined[moduleName];
2230         } else {
2231             if (ret === undefined) {
2232                 //Try to dynamically fetch it.
2233                 req.load(context, moduleName, moduleMap.url);
2234                 //The above call is sync, so can do the next thing safely.
2235                 ret = context.defined[moduleName];
2236             }
2237         }
2238
2239         return ret;
2240     };
2241
2242     //Add wrapper around the code so that it gets the requirejs
2243     //API instead of the Node API, and it is done lexically so
2244     //that it survives later execution.
2245     req.makeNodeWrapper = function (contents) {
2246         return '(function (require, requirejs, define) { ' +
2247                 contents +
2248                 '\n}(requirejsVars.require, requirejsVars.requirejs, requirejsVars.define));';
2249     };
2250
2251     requirejsVars.nodeLoad = req.load = function (context, moduleName, url) {
2252         var contents, err;
2253
2254         //Indicate a the module is in process of loading.
2255         context.scriptCount += 1;
2256
2257         if (path.existsSync(url)) {
2258             contents = fs.readFileSync(url, 'utf8');
2259
2260             contents = req.makeNodeWrapper(contents);
2261             try {
2262                 vm.runInThisContext(contents, fs.realpathSync(url));
2263             } catch (e) {
2264                 err = new Error('Evaluating ' + url + ' as module "' +
2265                                 moduleName + '" failed with error: ' + e);
2266                 err.originalError = e;
2267                 err.moduleName = moduleName;
2268                 err.fileName = url;
2269                 return req.onError(err);
2270             }
2271         } else {
2272             def(moduleName, function () {
2273                 try {
2274                     return (context.config.nodeRequire || req.nodeRequire)(moduleName);
2275                 } catch (e) {
2276                     err = new Error('Calling node\'s require("' +
2277                                         moduleName + '") failed with error: ' + e);
2278                     err.originalError = e;
2279                     err.moduleName = moduleName;
2280                     return req.onError(err);
2281                 }
2282             });
2283         }
2284
2285         //Support anonymous modules.
2286         context.completeLoad(moduleName);
2287
2288         return undefined;
2289     };
2290
2291     //Override to provide the function wrapper for define/require.
2292     req.exec = function (text) {
2293         /*jslint evil: true */
2294         text = req.makeNodeWrapper(text);
2295         return eval(text);
2296     };
2297
2298     //Hold on to the original execCb to use in useLib calls.
2299     requirejsVars.nodeRequireExecCb = require.execCb;
2300 }());
2301
2302     }
2303
2304     //Support a default file name to execute. Useful for hosted envs
2305     //like Joyent where it defaults to a server.js as the only executed
2306     //script. But only do it if this is not an optimization run.
2307     if (commandOption !== 'o' && (!fileName || !jsSuffixRegExp.test(fileName))) {
2308         fileName = 'main.js';
2309     }
2310
2311     /**
2312      * Loads the library files that can be used for the optimizer, or for other
2313      * tasks.
2314      */
2315     function loadLib() {
2316         /**
2317  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2318  * Available via the MIT or new BSD license.
2319  * see: http://github.com/jrburke/requirejs for details
2320  */
2321
2322 /*jslint strict: false */
2323 /*global Packages: false, process: false, window: false, navigator: false,
2324   document: false, define: false */
2325
2326 /**
2327  * A plugin that modifies any /env/ path to be the right path based on
2328  * the host environment. Right now only works for Node, Rhino and browser.
2329  */
2330 (function () {
2331     var pathRegExp = /(\/|^)env\/|\{env\}/,
2332         env = 'unknown';
2333
2334     if (typeof Packages !== 'undefined') {
2335         env = 'rhino';
2336     } else if (typeof process !== 'undefined') {
2337         env = 'node';
2338     } else if (typeof window !== "undefined" && navigator && document) {
2339         env = 'browser';
2340     }
2341
2342     define('env', {
2343         load: function (name, req, load, config) {
2344             //Allow override in the config.
2345             if (config.env) {
2346                 env = config.env;
2347             }
2348
2349             name = name.replace(pathRegExp, function (match, prefix) {
2350                 if (match.indexOf('{') === -1) {
2351                     return prefix + env + '/';
2352                 } else {
2353                     return env;
2354                 }
2355             });
2356
2357             req([name], function (mod) {
2358                 load(mod);
2359             });
2360         }
2361     });
2362 }());
2363 if(env === 'node') {
2364 /**
2365  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2366  * Available via the MIT or new BSD license.
2367  * see: http://github.com/jrburke/requirejs for details
2368  */
2369
2370 /*jslint strict: false */
2371 /*global define: false, process: false */
2372
2373 define('node/args', function () {
2374     //Do not return the "node" or "r.js" arguments
2375     var args = process.argv.slice(2);
2376
2377     //Ignore any command option used for rq.js
2378     if (args[0] && args[0].indexOf('-' === 0)) {
2379         args = args.slice(1);
2380     }
2381
2382     return args;
2383 });
2384
2385 }
2386
2387 if(env === 'rhino') {
2388 /**
2389  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2390  * Available via the MIT or new BSD license.
2391  * see: http://github.com/jrburke/requirejs for details
2392  */
2393
2394 /*jslint strict: false */
2395 /*global define: false, process: false */
2396
2397 var jsLibRhinoArgs = (typeof rhinoArgs !== 'undefined' && rhinoArgs) || [].concat(Array.prototype.slice.call(arguments, 0));
2398
2399 define('rhino/args', function () {
2400     var args = jsLibRhinoArgs;
2401
2402     //Ignore any command option used for rq.js
2403     if (args[0] && args[0].indexOf('-' === 0)) {
2404         args = args.slice(1);
2405     }
2406
2407     return args;
2408 });
2409
2410 }
2411
2412 if(env === 'node') {
2413 /**
2414  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2415  * Available via the MIT or new BSD license.
2416  * see: http://github.com/jrburke/requirejs for details
2417  */
2418
2419 /*jslint strict: false */
2420 /*global define: false, console: false */
2421
2422 define('node/load', ['fs'], function (fs) {
2423     function load(fileName) {
2424         var contents = fs.readFileSync(fileName, 'utf8');
2425         process.compile(contents, fileName);
2426     }
2427
2428     return load;
2429 });
2430
2431 }
2432
2433 if(env === 'rhino') {
2434 /**
2435  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2436  * Available via the MIT or new BSD license.
2437  * see: http://github.com/jrburke/requirejs for details
2438  */
2439
2440 /*jslint strict: false */
2441 /*global define: false, load: false */
2442
2443 define('rhino/load', function () {
2444     return load;
2445 });
2446
2447 }
2448
2449 if(env === 'node') {
2450 /**
2451  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2452  * Available via the MIT or new BSD license.
2453  * see: http://github.com/jrburke/requirejs for details
2454  */
2455
2456 /*jslint plusplus: false, octal:false, strict: false */
2457 /*global define: false, process: false */
2458
2459 define('node/file', ['fs', 'path'], function (fs, path) {
2460
2461     var isWindows = process.platform === 'win32',
2462         windowsDriveRegExp = /^[a-zA-Z]\:\/$/,
2463         file;
2464
2465     function frontSlash(path) {
2466         return path.replace(/\\/g, '/');
2467     }
2468
2469     function exists(path) {
2470         if (isWindows && path.charAt(path.length - 1) === '/' &&
2471             path.charAt(path.length - 2) !== ':') {
2472             path = path.substring(0, path.length - 1);
2473         }
2474
2475         try {
2476             fs.statSync(path);
2477             return true;
2478         } catch (e) {
2479             return false;
2480         }
2481     }
2482
2483     function mkDir(dir) {
2484         if (!exists(dir) && (!isWindows || !windowsDriveRegExp.test(dir))) {
2485             fs.mkdirSync(dir, 511);
2486         }
2487     }
2488
2489     function mkFullDir(dir) {
2490         var parts = dir.split('/'),
2491             currDir = '',
2492             first = true;
2493
2494         parts.forEach(function (part) {
2495             //First part may be empty string if path starts with a slash.
2496             currDir += part + '/';
2497             first = false;
2498
2499             if (part) {
2500                 mkDir(currDir);
2501             }
2502         });
2503     }
2504
2505     file = {
2506         backSlashRegExp: /\\/g,
2507         exclusionRegExp: /^\./,
2508         getLineSeparator: function () {
2509             return '/';
2510         },
2511
2512         exists: function (fileName) {
2513             return exists(fileName);
2514         },
2515
2516         parent: function (fileName) {
2517             var parts = fileName.split('/');
2518             parts.pop();
2519             return parts.join('/');
2520         },
2521
2522         /**
2523          * Gets the absolute file path as a string, normalized
2524          * to using front slashes for path separators.
2525          * @param {String} fileName
2526          */
2527         absPath: function (fileName) {
2528             return frontSlash(path.normalize(frontSlash(fs.realpathSync(fileName))));
2529         },
2530
2531         normalize: function (fileName) {
2532             return frontSlash(path.normalize(fileName));
2533         },
2534
2535         isFile: function (path) {
2536             return fs.statSync(path).isFile();
2537         },
2538
2539         isDirectory: function (path) {
2540             return fs.statSync(path).isDirectory();
2541         },
2542
2543         getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths) {
2544             //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
2545             //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
2546             //and it will be treated as the "include" case.
2547             //Ignores files/directories that start with a period (.) unless exclusionRegExp
2548             //is set to another value.
2549             var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
2550                 i, stat, filePath, ok, dirFiles, fileName;
2551
2552             topDir = startDir;
2553
2554             regExpInclude = regExpFilters.include || regExpFilters;
2555             regExpExclude = regExpFilters.exclude || null;
2556
2557             if (file.exists(topDir)) {
2558                 dirFileArray = fs.readdirSync(topDir);
2559                 for (i = 0; i < dirFileArray.length; i++) {
2560                     fileName = dirFileArray[i];
2561                     filePath = path.join(topDir, fileName);
2562                     stat = fs.statSync(filePath);
2563                     if (stat.isFile()) {
2564                         if (makeUnixPaths) {
2565                             //Make sure we have a JS string.
2566                             if (filePath.indexOf("/") === -1) {
2567                                 filePath = frontSlash(filePath);
2568                             }
2569                         }
2570
2571                         ok = true;
2572                         if (regExpInclude) {
2573                             ok = filePath.match(regExpInclude);
2574                         }
2575                         if (ok && regExpExclude) {
2576                             ok = !filePath.match(regExpExclude);
2577                         }
2578
2579                         if (ok && (!file.exclusionRegExp ||
2580                             !file.exclusionRegExp.test(fileName))) {
2581                             files.push(filePath);
2582                         }
2583                     } else if (stat.isDirectory() &&
2584                               (!file.exclusionRegExp || !file.exclusionRegExp.test(fileName))) {
2585                         dirFiles = this.getFilteredFileList(filePath, regExpFilters, makeUnixPaths);
2586                         files.push.apply(files, dirFiles);
2587                     }
2588                 }
2589             }
2590
2591             return files; //Array
2592         },
2593
2594         copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
2595             //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
2596             //file should be copied. Returns a list file name strings of the destinations that were copied.
2597             regExpFilter = regExpFilter || /\w/;
2598
2599             //Normalize th directory names, but keep front slashes.
2600             //path module on windows now returns backslashed paths.
2601             srcDir = frontSlash(path.normalize(srcDir));
2602             destDir = frontSlash(path.normalize(destDir));
2603
2604             var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
2605             copiedFiles = [], i, srcFileName, destFileName;
2606
2607             for (i = 0; i < fileNames.length; i++) {
2608                 srcFileName = fileNames[i];
2609                 destFileName = srcFileName.replace(srcDir, destDir);
2610
2611                 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
2612                     copiedFiles.push(destFileName);
2613                 }
2614             }
2615
2616             return copiedFiles.length ? copiedFiles : null; //Array or null
2617         },
2618
2619         copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
2620             //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
2621             //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
2622             var parentDir;
2623
2624             //logger.trace("Src filename: " + srcFileName);
2625             //logger.trace("Dest filename: " + destFileName);
2626
2627             //If onlyCopyNew is true, then compare dates and only copy if the src is newer
2628             //than dest.
2629             if (onlyCopyNew) {
2630                 if (file.exists(destFileName) && fs.statSync(destFileName).mtime.getTime() >= fs.statSync(srcFileName).mtime.getTime()) {
2631                     return false; //Boolean
2632                 }
2633             }
2634
2635             //Make sure destination dir exists.
2636             parentDir = path.dirname(destFileName);
2637             if (!file.exists(parentDir)) {
2638                 mkFullDir(parentDir);
2639             }
2640
2641             fs.writeFileSync(destFileName, fs.readFileSync(srcFileName, 'binary'), 'binary');
2642
2643             return true; //Boolean
2644         },
2645
2646         /**
2647          * Renames a file. May fail if "to" already exists or is on another drive.
2648          */
2649         renameFile: function (from, to) {
2650             return fs.renameSync(from, to);
2651         },
2652
2653         /**
2654          * Reads a *text* file.
2655          */
2656         readFile: function (/*String*/path, /*String?*/encoding) {
2657             if (encoding === 'utf-8') {
2658                 encoding = 'utf8';
2659             }
2660             if (!encoding) {
2661                 encoding = 'utf8';
2662             }
2663
2664             var text = fs.readFileSync(path, encoding);
2665
2666             //Hmm, would not expect to get A BOM, but it seems to happen,
2667             //remove it just in case.
2668             if (text.indexOf('\uFEFF') === 0) {
2669                 text = text.substring(1, text.length);
2670             }
2671
2672             return text;
2673         },
2674
2675         saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
2676             //summary: saves a *text* file using UTF-8 encoding.
2677             file.saveFile(fileName, fileContents, "utf8");
2678         },
2679
2680         saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
2681             //summary: saves a *text* file.
2682             var parentDir;
2683
2684             if (encoding === 'utf-8') {
2685                 encoding = 'utf8';
2686             }
2687             if (!encoding) {
2688                 encoding = 'utf8';
2689             }
2690
2691             //Make sure destination directories exist.
2692             parentDir = path.dirname(fileName);
2693             if (!file.exists(parentDir)) {
2694                 mkFullDir(parentDir);
2695             }
2696
2697             fs.writeFileSync(fileName, fileContents, encoding);
2698         },
2699
2700         deleteFile: function (/*String*/fileName) {
2701             //summary: deletes a file or directory if it exists.
2702             var files, i, stat;
2703             if (file.exists(fileName)) {
2704                 stat = fs.statSync(fileName);
2705                 if (stat.isDirectory()) {
2706                     files = fs.readdirSync(fileName);
2707                     for (i = 0; i < files.length; i++) {
2708                         this.deleteFile(path.join(fileName, files[i]));
2709                     }
2710                     fs.rmdirSync(fileName);
2711                 } else {
2712                     fs.unlinkSync(fileName);
2713                 }
2714             }
2715         }
2716     };
2717
2718     return file;
2719
2720 });
2721
2722 }
2723
2724 if(env === 'rhino') {
2725 /**
2726  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2727  * Available via the MIT or new BSD license.
2728  * see: http://github.com/jrburke/requirejs for details
2729  */
2730 //Helper functions to deal with file I/O.
2731
2732 /*jslint plusplus: false, strict: false */
2733 /*global java: false, define: false */
2734
2735 define('rhino/file', function () {
2736     var file = {
2737         backSlashRegExp: /\\/g,
2738
2739         exclusionRegExp: /^\./,
2740
2741         getLineSeparator: function () {
2742             return file.lineSeparator;
2743         },
2744
2745         lineSeparator: java.lang.System.getProperty("line.separator"), //Java String
2746
2747         exists: function (fileName) {
2748             return (new java.io.File(fileName)).exists();
2749         },
2750
2751         parent: function (fileName) {
2752             return file.absPath((new java.io.File(fileName)).getParentFile());
2753         },
2754
2755         normalize: function (fileName) {
2756             return file.absPath(fileName);
2757         },
2758
2759         isFile: function (path) {
2760             return (new java.io.File(path)).isFile();
2761         },
2762
2763         isDirectory: function (path) {
2764             return (new java.io.File(path)).isDirectory();
2765         },
2766
2767         /**
2768          * Gets the absolute file path as a string, normalized
2769          * to using front slashes for path separators.
2770          * @param {java.io.File||String} file
2771          */
2772         absPath: function (fileObj) {
2773             if (typeof fileObj === "string") {
2774                 fileObj = new java.io.File(fileObj);
2775             }
2776             return (fileObj.getAbsolutePath() + "").replace(file.backSlashRegExp, "/");
2777         },
2778
2779         getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) {
2780             //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
2781             //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
2782             //and it will be treated as the "include" case.
2783             //Ignores files/directories that start with a period (.) unless exclusionRegExp
2784             //is set to another value.
2785             var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
2786                 i, fileObj, filePath, ok, dirFiles;
2787
2788             topDir = startDir;
2789             if (!startDirIsJavaObject) {
2790                 topDir = new java.io.File(startDir);
2791             }
2792
2793             regExpInclude = regExpFilters.include || regExpFilters;
2794             regExpExclude = regExpFilters.exclude || null;
2795
2796             if (topDir.exists()) {
2797                 dirFileArray = topDir.listFiles();
2798                 for (i = 0; i < dirFileArray.length; i++) {
2799                     fileObj = dirFileArray[i];
2800                     if (fileObj.isFile()) {
2801                         filePath = fileObj.getPath();
2802                         if (makeUnixPaths) {
2803                             //Make sure we have a JS string.
2804                             filePath = String(filePath);
2805                             if (filePath.indexOf("/") === -1) {
2806                                 filePath = filePath.replace(/\\/g, "/");
2807                             }
2808                         }
2809
2810                         ok = true;
2811                         if (regExpInclude) {
2812                             ok = filePath.match(regExpInclude);
2813                         }
2814                         if (ok && regExpExclude) {
2815                             ok = !filePath.match(regExpExclude);
2816                         }
2817
2818                         if (ok && (!file.exclusionRegExp ||
2819                             !file.exclusionRegExp.test(fileObj.getName()))) {
2820                             files.push(filePath);
2821                         }
2822                     } else if (fileObj.isDirectory() &&
2823                               (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.getName()))) {
2824                         dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true);
2825                         files.push.apply(files, dirFiles);
2826                     }
2827                 }
2828             }
2829
2830             return files; //Array
2831         },
2832
2833         copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
2834             //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
2835             //file should be copied. Returns a list file name strings of the destinations that were copied.
2836             regExpFilter = regExpFilter || /\w/;
2837
2838             var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
2839             copiedFiles = [], i, srcFileName, destFileName;
2840
2841             for (i = 0; i < fileNames.length; i++) {
2842                 srcFileName = fileNames[i];
2843                 destFileName = srcFileName.replace(srcDir, destDir);
2844
2845                 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
2846                     copiedFiles.push(destFileName);
2847                 }
2848             }
2849
2850             return copiedFiles.length ? copiedFiles : null; //Array or null
2851         },
2852
2853         copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
2854             //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
2855             //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
2856             var destFile = new java.io.File(destFileName), srcFile, parentDir,
2857             srcChannel, destChannel;
2858
2859             //logger.trace("Src filename: " + srcFileName);
2860             //logger.trace("Dest filename: " + destFileName);
2861
2862             //If onlyCopyNew is true, then compare dates and only copy if the src is newer
2863             //than dest.
2864             if (onlyCopyNew) {
2865                 srcFile = new java.io.File(srcFileName);
2866                 if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
2867                     return false; //Boolean
2868                 }
2869             }
2870
2871             //Make sure destination dir exists.
2872             parentDir = destFile.getParentFile();
2873             if (!parentDir.exists()) {
2874                 if (!parentDir.mkdirs()) {
2875                     throw "Could not create directory: " + parentDir.getAbsolutePath();
2876                 }
2877             }
2878
2879             //Java's version of copy file.
2880             srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
2881             destChannel = new java.io.FileOutputStream(destFileName).getChannel();
2882             destChannel.transferFrom(srcChannel, 0, srcChannel.size());
2883             srcChannel.close();
2884             destChannel.close();
2885
2886             return true; //Boolean
2887         },
2888
2889         /**
2890          * Renames a file. May fail if "to" already exists or is on another drive.
2891          */
2892         renameFile: function (from, to) {
2893             return (new java.io.File(from)).renameTo((new java.io.File(to)));
2894         },
2895
2896         readFile: function (/*String*/path, /*String?*/encoding) {
2897             //A file read function that can deal with BOMs
2898             encoding = encoding || "utf-8";
2899             var fileObj = new java.io.File(path),
2900                     input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(fileObj), encoding)),
2901                     stringBuffer, line;
2902             try {
2903                 stringBuffer = new java.lang.StringBuffer();
2904                 line = input.readLine();
2905
2906                 // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
2907                 // http://www.unicode.org/faq/utf_bom.html
2908
2909                 // 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:
2910                 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
2911                 if (line && line.length() && line.charAt(0) === 0xfeff) {
2912                     // Eat the BOM, since we've already found the encoding on this file,
2913                     // and we plan to concatenating this buffer with others; the BOM should
2914                     // only appear at the top of a file.
2915                     line = line.substring(1);
2916                 }
2917                 while (line !== null) {
2918                     stringBuffer.append(line);
2919                     stringBuffer.append(file.lineSeparator);
2920                     line = input.readLine();
2921                 }
2922                 //Make sure we return a JavaScript string and not a Java string.
2923                 return String(stringBuffer.toString()); //String
2924             } finally {
2925                 input.close();
2926             }
2927         },
2928
2929         saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
2930             //summary: saves a file using UTF-8 encoding.
2931             file.saveFile(fileName, fileContents, "utf-8");
2932         },
2933
2934         saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
2935             //summary: saves a file.
2936             var outFile = new java.io.File(fileName), outWriter, parentDir, os;
2937
2938             parentDir = outFile.getAbsoluteFile().getParentFile();
2939             if (!parentDir.exists()) {
2940                 if (!parentDir.mkdirs()) {
2941                     throw "Could not create directory: " + parentDir.getAbsolutePath();
2942                 }
2943             }
2944
2945             if (encoding) {
2946                 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
2947             } else {
2948                 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
2949             }
2950
2951             os = new java.io.BufferedWriter(outWriter);
2952             try {
2953                 os.write(fileContents);
2954             } finally {
2955                 os.close();
2956             }
2957         },
2958
2959         deleteFile: function (/*String*/fileName) {
2960             //summary: deletes a file or directory if it exists.
2961             var fileObj = new java.io.File(fileName), files, i;
2962             if (fileObj.exists()) {
2963                 if (fileObj.isDirectory()) {
2964                     files = fileObj.listFiles();
2965                     for (i = 0; i < files.length; i++) {
2966                         this.deleteFile(files[i]);
2967                     }
2968                 }
2969                 fileObj["delete"]();
2970             }
2971         }
2972     };
2973
2974     return file;
2975 });
2976
2977 }
2978 /**
2979  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2980  * Available via the MIT or new BSD license.
2981  * see: http://github.com/jrburke/requirejs for details
2982  */
2983
2984 /*jslint plusplus: true */
2985 /*global define */
2986
2987 define('lang', function () {
2988     'use strict';
2989
2990     var lang = {
2991         backSlashRegExp: /\\/g,
2992         ostring: Object.prototype.toString,
2993
2994         isArray: Array.isArray || function (it) {
2995             return lang.ostring.call(it) === "[object Array]";
2996         },
2997
2998         isFunction: function(it) {
2999             return lang.ostring.call(it) === "[object Function]";
3000         },
3001
3002         isRegExp: function(it) {
3003             return it && it instanceof RegExp;
3004         },
3005
3006         _mixin: function(dest, source, override){
3007             var name;
3008             for (name in source) {
3009                 if(source.hasOwnProperty(name)
3010                     && (override || !dest.hasOwnProperty(name))) {
3011                     dest[name] = source[name];
3012                 }
3013             }
3014
3015             return dest; // Object
3016         },
3017
3018         /**
3019          * mixin({}, obj1, obj2) is allowed. If the last argument is a boolean,
3020          * then the source objects properties are force copied over to dest.
3021          */
3022         mixin: function(dest){
3023             var parameters = Array.prototype.slice.call(arguments),
3024                 override, i, l;
3025
3026             if (!dest) { dest = {}; }
3027
3028             if (parameters.length > 2 && typeof arguments[parameters.length-1] === 'boolean') {
3029                 override = parameters.pop();
3030             }
3031
3032             for (i = 1, l = parameters.length; i < l; i++) {
3033                 lang._mixin(dest, parameters[i], override);
3034             }
3035             return dest; // Object
3036         },
3037
3038         delegate: (function () {
3039             // boodman/crockford delegation w/ cornford optimization
3040             function TMP() {}
3041             return function (obj, props) {
3042                 TMP.prototype = obj;
3043                 var tmp = new TMP();
3044                 TMP.prototype = null;
3045                 if (props) {
3046                     lang.mixin(tmp, props);
3047                 }
3048                 return tmp; // Object
3049             };
3050         }())
3051     };
3052     return lang;
3053 });
3054
3055 if(env === 'node') {
3056 /**
3057  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3058  * Available via the MIT or new BSD license.
3059  * see: http://github.com/jrburke/requirejs for details
3060  */
3061
3062 /*jslint strict: false */
3063 /*global define: false, console: false */
3064
3065 define('node/print', function () {
3066     function print(msg) {
3067         console.log(msg);
3068     }
3069
3070     return print;
3071 });
3072
3073 }
3074
3075 if(env === 'rhino') {
3076 /**
3077  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3078  * Available via the MIT or new BSD license.
3079  * see: http://github.com/jrburke/requirejs for details
3080  */
3081
3082 /*jslint strict: false */
3083 /*global define: false, print: false */
3084
3085 define('rhino/print', function () {
3086     return print;
3087 });
3088
3089 }
3090 /**
3091  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3092  * Available via the MIT or new BSD license.
3093  * see: http://github.com/jrburke/requirejs for details
3094  */
3095
3096 /*jslint nomen: false, strict: false */
3097 /*global define: false */
3098
3099 define('logger', ['env!env/print'], function (print) {
3100     var logger = {
3101         TRACE: 0,
3102         INFO: 1,
3103         WARN: 2,
3104         ERROR: 3,
3105         SILENT: 4,
3106         level: 0,
3107         logPrefix: "",
3108
3109         logLevel: function( level ) {
3110             this.level = level;
3111         },
3112
3113         trace: function (message) {
3114             if (this.level <= this.TRACE) {
3115                 this._print(message);
3116             }
3117         },
3118
3119         info: function (message) {
3120             if (this.level <= this.INFO) {
3121                 this._print(message);
3122             }
3123         },
3124
3125         warn: function (message) {
3126             if (this.level <= this.WARN) {
3127                 this._print(message);
3128             }
3129         },
3130
3131         error: function (message) {
3132             if (this.level <= this.ERROR) {
3133                 this._print(message);
3134             }
3135         },
3136
3137         _print: function (message) {
3138             this._sysPrint((this.logPrefix ? (this.logPrefix + " ") : "") + message);
3139         },
3140
3141         _sysPrint: function (message) {
3142             print(message);
3143         }
3144     };
3145
3146     return logger;
3147 });
3148 //Just a blank file to use when building the optimizer with the optimizer,
3149 //so that the build does not attempt to inline some env modules,
3150 //like Node's fs and path.
3151
3152 //Just a blank file to use when building the optimizer with the optimizer,
3153 //so that the build does not attempt to inline some env modules,
3154 //like Node's fs and path.
3155
3156 define('uglifyjs/parse-js', ["require", "exports", "module"], function(require, exports, module) {
3157 /***********************************************************************
3158
3159   A JavaScript tokenizer / parser / beautifier / compressor.
3160
3161   This version is suitable for Node.js.  With minimal changes (the
3162   exports stuff) it should work on any JS platform.
3163
3164   This file contains the tokenizer/parser.  It is a port to JavaScript
3165   of parse-js [1], a JavaScript parser library written in Common Lisp
3166   by Marijn Haverbeke.  Thank you Marijn!
3167
3168   [1] http://marijn.haverbeke.nl/parse-js/
3169
3170   Exported functions:
3171
3172     - tokenizer(code) -- returns a function.  Call the returned
3173       function to fetch the next token.
3174
3175     - parse(code) -- returns an AST of the given JavaScript code.
3176
3177   -------------------------------- (C) ---------------------------------
3178
3179                            Author: Mihai Bazon
3180                          <mihai.bazon@gmail.com>
3181                        http://mihai.bazon.net/blog
3182
3183   Distributed under the BSD license:
3184
3185     Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
3186     Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
3187
3188     Redistribution and use in source and binary forms, with or without
3189     modification, are permitted provided that the following conditions
3190     are met:
3191
3192         * Redistributions of source code must retain the above
3193           copyright notice, this list of conditions and the following
3194           disclaimer.
3195
3196         * Redistributions in binary form must reproduce the above
3197           copyright notice, this list of conditions and the following
3198           disclaimer in the documentation and/or other materials
3199           provided with the distribution.
3200
3201     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
3202     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3203     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3204     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
3205     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
3206     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3207     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3208     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3209     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
3210     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3211     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3212     SUCH DAMAGE.
3213
3214  ***********************************************************************/
3215
3216 /* -----[ Tokenizer (constants) ]----- */
3217
3218 var KEYWORDS = array_to_hash([
3219         "break",
3220         "case",
3221         "catch",
3222         "const",
3223         "continue",
3224         "default",
3225         "delete",
3226         "do",
3227         "else",
3228         "finally",
3229         "for",
3230         "function",
3231         "if",
3232         "in",
3233         "instanceof",
3234         "new",
3235         "return",
3236         "switch",
3237         "throw",
3238         "try",
3239         "typeof",
3240         "var",
3241         "void",
3242         "while",
3243         "with"
3244 ]);
3245
3246 var RESERVED_WORDS = array_to_hash([
3247         "abstract",
3248         "boolean",
3249         "byte",
3250         "char",
3251         "class",
3252         "debugger",
3253         "double",
3254         "enum",
3255         "export",
3256         "extends",
3257         "final",
3258         "float",
3259         "goto",
3260         "implements",
3261         "import",
3262         "int",
3263         "interface",
3264         "long",
3265         "native",
3266         "package",
3267         "private",
3268         "protected",
3269         "public",
3270         "short",
3271         "static",
3272         "super",
3273         "synchronized",
3274         "throws",
3275         "transient",
3276         "volatile"
3277 ]);
3278
3279 var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([
3280         "return",
3281         "new",
3282         "delete",
3283         "throw",
3284         "else",
3285         "case"
3286 ]);
3287
3288 var KEYWORDS_ATOM = array_to_hash([
3289         "false",
3290         "null",
3291         "true",
3292         "undefined"
3293 ]);
3294
3295 var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^"));
3296
3297 var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
3298 var RE_OCT_NUMBER = /^0[0-7]+$/;
3299 var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
3300
3301 var OPERATORS = array_to_hash([
3302         "in",
3303         "instanceof",
3304         "typeof",
3305         "new",
3306         "void",
3307         "delete",
3308         "++",
3309         "--",
3310         "+",
3311         "-",
3312         "!",
3313         "~",
3314         "&",
3315         "|",
3316         "^",
3317         "*",
3318         "/",
3319         "%",
3320         ">>",
3321         "<<",
3322         ">>>",
3323         "<",
3324         ">",
3325         "<=",
3326         ">=",
3327         "==",
3328         "===",
3329         "!=",
3330         "!==",
3331         "?",
3332         "=",
3333         "+=",
3334         "-=",
3335         "/=",
3336         "*=",
3337         "%=",
3338         ">>=",
3339         "<<=",
3340         ">>>=",
3341         "|=",
3342         "^=",
3343         "&=",
3344         "&&",
3345         "||"
3346 ]);
3347
3348 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"));
3349
3350 var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:"));
3351
3352 var PUNC_CHARS = array_to_hash(characters("[]{}(),;:"));
3353
3354 var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
3355
3356 /* -----[ Tokenizer ]----- */
3357
3358 // regexps adapted from http://xregexp.com/plugins/#unicode
3359 var UNICODE = {
3360         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]"),
3361         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]"),
3362         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]"),
3363         connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
3364 };
3365
3366 function is_letter(ch) {
3367         return UNICODE.letter.test(ch);
3368 };
3369
3370 function is_digit(ch) {
3371         ch = ch.charCodeAt(0);
3372         return ch >= 48 && ch <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9
3373 };
3374
3375 function is_alphanumeric_char(ch) {
3376         return is_digit(ch) || is_letter(ch);
3377 };
3378
3379 function is_unicode_combining_mark(ch) {
3380         return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
3381 };
3382
3383 function is_unicode_connector_punctuation(ch) {
3384         return UNICODE.connector_punctuation.test(ch);
3385 };
3386
3387 function is_identifier_start(ch) {
3388         return ch == "$" || ch == "_" || is_letter(ch);
3389 };
3390
3391 function is_identifier_char(ch) {
3392         return is_identifier_start(ch)
3393                 || is_unicode_combining_mark(ch)
3394                 || is_digit(ch)
3395                 || is_unicode_connector_punctuation(ch)
3396                 || ch == "\u200c" // zero-width non-joiner <ZWNJ>
3397                 || ch == "\u200d" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
3398         ;
3399 };
3400
3401 function parse_js_number(num) {
3402         if (RE_HEX_NUMBER.test(num)) {
3403                 return parseInt(num.substr(2), 16);
3404         } else if (RE_OCT_NUMBER.test(num)) {
3405                 return parseInt(num.substr(1), 8);
3406         } else if (RE_DEC_NUMBER.test(num)) {
3407                 return parseFloat(num);
3408         }
3409 };
3410
3411 function JS_Parse_Error(message, line, col, pos) {
3412         this.message = message;
3413         this.line = line + 1;
3414         this.col = col + 1;
3415         this.pos = pos + 1;
3416         this.stack = new Error().stack;
3417 };
3418
3419 JS_Parse_Error.prototype.toString = function() {
3420         return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
3421 };
3422
3423 function js_error(message, line, col, pos) {
3424         throw new JS_Parse_Error(message, line, col, pos);
3425 };
3426
3427 function is_token(token, type, val) {
3428         return token.type == type && (val == null || token.value == val);
3429 };
3430
3431 var EX_EOF = {};
3432
3433 function tokenizer($TEXT) {
3434
3435         var S = {
3436                 text            : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''),
3437                 pos             : 0,
3438                 tokpos          : 0,
3439                 line            : 0,
3440                 tokline         : 0,
3441                 col             : 0,
3442                 tokcol          : 0,
3443                 newline_before  : false,
3444                 regex_allowed   : false,
3445                 comments_before : []
3446         };
3447
3448         function peek() { return S.text.charAt(S.pos); };
3449
3450         function next(signal_eof, in_string) {
3451                 var ch = S.text.charAt(S.pos++);
3452                 if (signal_eof && !ch)
3453                         throw EX_EOF;
3454                 if (ch == "\n") {
3455                         S.newline_before = S.newline_before || !in_string;
3456                         ++S.line;
3457                         S.col = 0;
3458                 } else {
3459                         ++S.col;
3460                 }
3461                 return ch;
3462         };
3463
3464         function eof() {
3465                 return !S.peek();
3466         };
3467
3468         function find(what, signal_eof) {
3469                 var pos = S.text.indexOf(what, S.pos);
3470                 if (signal_eof && pos == -1) throw EX_EOF;
3471                 return pos;
3472         };
3473
3474         function start_token() {
3475                 S.tokline = S.line;
3476                 S.tokcol = S.col;
3477                 S.tokpos = S.pos;
3478         };
3479
3480         function token(type, value, is_comment) {
3481                 S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) ||
3482                                    (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||
3483                                    (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value)));
3484                 var ret = {
3485                         type   : type,
3486                         value  : value,
3487                         line   : S.tokline,
3488                         col    : S.tokcol,
3489                         pos    : S.tokpos,
3490                         endpos : S.pos,
3491                         nlb    : S.newline_before
3492                 };
3493                 if (!is_comment) {
3494                         ret.comments_before = S.comments_before;
3495                         S.comments_before = [];
3496                 }
3497                 S.newline_before = false;
3498                 return ret;
3499         };
3500
3501         function skip_whitespace() {
3502                 while (HOP(WHITESPACE_CHARS, peek()))
3503                         next();
3504         };
3505
3506         function read_while(pred) {
3507                 var ret = "", ch = peek(), i = 0;
3508                 while (ch && pred(ch, i++)) {
3509                         ret += next();
3510                         ch = peek();
3511                 }
3512                 return ret;
3513         };
3514
3515         function parse_error(err) {
3516                 js_error(err, S.tokline, S.tokcol, S.tokpos);
3517         };
3518
3519         function read_num(prefix) {
3520                 var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
3521                 var num = read_while(function(ch, i){
3522                         if (ch == "x" || ch == "X") {
3523                                 if (has_x) return false;
3524                                 return has_x = true;
3525                         }
3526                         if (!has_x && (ch == "E" || ch == "e")) {
3527                                 if (has_e) return false;
3528                                 return has_e = after_e = true;
3529                         }
3530                         if (ch == "-") {
3531                                 if (after_e || (i == 0 && !prefix)) return true;
3532                                 return false;
3533                         }
3534                         if (ch == "+") return after_e;
3535                         after_e = false;
3536                         if (ch == ".") {
3537                                 if (!has_dot && !has_x)
3538                                         return has_dot = true;
3539                                 return false;
3540                         }
3541                         return is_alphanumeric_char(ch);
3542                 });
3543                 if (prefix)
3544                         num = prefix + num;
3545                 var valid = parse_js_number(num);
3546                 if (!isNaN(valid)) {
3547                         return token("num", valid);
3548                 } else {
3549                         parse_error("Invalid syntax: " + num);
3550                 }
3551         };
3552
3553         function read_escaped_char(in_string) {
3554                 var ch = next(true, in_string);
3555                 switch (ch) {
3556                     case "n" : return "\n";
3557                     case "r" : return "\r";
3558                     case "t" : return "\t";
3559                     case "b" : return "\b";
3560                     case "v" : return "\u000b";
3561                     case "f" : return "\f";
3562                     case "0" : return "\0";
3563                     case "x" : return String.fromCharCode(hex_bytes(2));
3564                     case "u" : return String.fromCharCode(hex_bytes(4));
3565                     case "\n": return "";
3566                     default  : return ch;
3567                 }
3568         };
3569
3570         function hex_bytes(n) {
3571                 var num = 0;
3572                 for (; n > 0; --n) {
3573                         var digit = parseInt(next(true), 16);
3574                         if (isNaN(digit))
3575                                 parse_error("Invalid hex-character pattern in string");
3576                         num = (num << 4) | digit;
3577                 }
3578                 return num;
3579         };
3580
3581         function read_string() {
3582                 return with_eof_error("Unterminated string constant", function(){
3583                         var quote = next(), ret = "";
3584                         for (;;) {
3585                                 var ch = next(true);
3586                                 if (ch == "\\") {
3587                                         // read OctalEscapeSequence (XXX: deprecated if "strict mode")
3588                                         // https://github.com/mishoo/UglifyJS/issues/178
3589                                         var octal_len = 0, first = null;
3590                                         ch = read_while(function(ch){
3591                                                 if (ch >= "0" && ch <= "7") {
3592                                                         if (!first) {
3593                                                                 first = ch;
3594                                                                 return ++octal_len;
3595                                                         }
3596                                                         else if (first <= "3" && octal_len <= 2) return ++octal_len;
3597                                                         else if (first >= "4" && octal_len <= 1) return ++octal_len;
3598                                                 }
3599                                                 return false;
3600                                         });
3601                                         if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
3602                                         else ch = read_escaped_char(true);
3603                                 }
3604                                 else if (ch == quote) break;
3605                                 ret += ch;
3606                         }
3607                         return token("string", ret);
3608                 });
3609         };
3610
3611         function read_line_comment() {
3612                 next();
3613                 var i = find("\n"), ret;
3614                 if (i == -1) {
3615                         ret = S.text.substr(S.pos);
3616                         S.pos = S.text.length;
3617                 } else {
3618                         ret = S.text.substring(S.pos, i);
3619                         S.pos = i;
3620                 }
3621                 return token("comment1", ret, true);
3622         };
3623
3624         function read_multiline_comment() {
3625                 next();
3626                 return with_eof_error("Unterminated multiline comment", function(){
3627                         var i = find("*/", true),
3628                             text = S.text.substring(S.pos, i);
3629                         S.pos = i + 2;
3630                         S.line += text.split("\n").length - 1;
3631                         S.newline_before = text.indexOf("\n") >= 0;
3632
3633                         // https://github.com/mishoo/UglifyJS/issues/#issue/100
3634                         if (/^@cc_on/i.test(text)) {
3635                                 warn("WARNING: at line " + S.line);
3636                                 warn("*** Found \"conditional comment\": " + text);
3637                                 warn("*** UglifyJS DISCARDS ALL COMMENTS.  This means your code might no longer work properly in Internet Explorer.");
3638                         }
3639
3640                         return token("comment2", text, true);
3641                 });
3642         };
3643
3644         function read_name() {
3645                 var backslash = false, name = "", ch;
3646                 while ((ch = peek()) != null) {
3647                         if (!backslash) {
3648                                 if (ch == "\\") backslash = true, next();
3649                                 else if (is_identifier_char(ch)) name += next();
3650                                 else break;
3651                         }
3652                         else {
3653                                 if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
3654                                 ch = read_escaped_char();
3655                                 if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
3656                                 name += ch;
3657                                 backslash = false;
3658                         }
3659                 }
3660                 return name;
3661         };
3662
3663         function read_regexp(regexp) {
3664                 return with_eof_error("Unterminated regular expression", function(){
3665                         var prev_backslash = false, ch, in_class = false;
3666                         while ((ch = next(true))) if (prev_backslash) {
3667                                 regexp += "\\" + ch;
3668                                 prev_backslash = false;
3669                         } else if (ch == "[") {
3670                                 in_class = true;
3671                                 regexp += ch;
3672                         } else if (ch == "]" && in_class) {
3673                                 in_class = false;
3674                                 regexp += ch;
3675                         } else if (ch == "/" && !in_class) {
3676                                 break;
3677                         } else if (ch == "\\") {
3678                                 prev_backslash = true;
3679                         } else {
3680                                 regexp += ch;
3681                         }
3682                         var mods = read_name();
3683                         return token("regexp", [ regexp, mods ]);
3684                 });
3685         };
3686
3687         function read_operator(prefix) {
3688                 function grow(op) {
3689                         if (!peek()) return op;
3690                         var bigger = op + peek();
3691                         if (HOP(OPERATORS, bigger)) {
3692                                 next();
3693                                 return grow(bigger);
3694                         } else {
3695                                 return op;
3696                         }
3697                 };
3698                 return token("operator", grow(prefix || next()));
3699         };
3700
3701         function handle_slash() {
3702                 next();
3703                 var regex_allowed = S.regex_allowed;
3704                 switch (peek()) {
3705                     case "/":
3706                         S.comments_before.push(read_line_comment());
3707                         S.regex_allowed = regex_allowed;
3708                         return next_token();
3709                     case "*":
3710                         S.comments_before.push(read_multiline_comment());
3711                         S.regex_allowed = regex_allowed;
3712                         return next_token();
3713                 }
3714                 return S.regex_allowed ? read_regexp("") : read_operator("/");
3715         };
3716
3717         function handle_dot() {
3718                 next();
3719                 return is_digit(peek())
3720                         ? read_num(".")
3721                         : token("punc", ".");
3722         };
3723
3724         function read_word() {
3725                 var word = read_name();
3726                 return !HOP(KEYWORDS, word)
3727                         ? token("name", word)
3728                         : HOP(OPERATORS, word)
3729                         ? token("operator", word)
3730                         : HOP(KEYWORDS_ATOM, word)
3731                         ? token("atom", word)
3732                         : token("keyword", word);
3733         };
3734
3735         function with_eof_error(eof_error, cont) {
3736                 try {
3737                         return cont();
3738                 } catch(ex) {
3739                         if (ex === EX_EOF) parse_error(eof_error);
3740                         else throw ex;
3741                 }
3742         };
3743
3744         function next_token(force_regexp) {
3745                 if (force_regexp != null)
3746                         return read_regexp(force_regexp);
3747                 skip_whitespace();
3748                 start_token();
3749                 var ch = peek();
3750                 if (!ch) return token("eof");
3751                 if (is_digit(ch)) return read_num();
3752                 if (ch == '"' || ch == "'") return read_string();
3753                 if (HOP(PUNC_CHARS, ch)) return token("punc", next());
3754                 if (ch == ".") return handle_dot();
3755                 if (ch == "/") return handle_slash();
3756                 if (HOP(OPERATOR_CHARS, ch)) return read_operator();
3757                 if (ch == "\\" || is_identifier_start(ch)) return read_word();
3758                 parse_error("Unexpected character '" + ch + "'");
3759         };
3760
3761         next_token.context = function(nc) {
3762                 if (nc) S = nc;
3763                 return S;
3764         };
3765
3766         return next_token;
3767
3768 };
3769
3770 /* -----[ Parser (constants) ]----- */
3771
3772 var UNARY_PREFIX = array_to_hash([
3773         "typeof",
3774         "void",
3775         "delete",
3776         "--",
3777         "++",
3778         "!",
3779         "~",
3780         "-",
3781         "+"
3782 ]);
3783
3784 var UNARY_POSTFIX = array_to_hash([ "--", "++" ]);
3785
3786 var ASSIGNMENT = (function(a, ret, i){
3787         while (i < a.length) {
3788                 ret[a[i]] = a[i].substr(0, a[i].length - 1);
3789                 i++;
3790         }
3791         return ret;
3792 })(
3793         ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="],
3794         { "=": true },
3795         0
3796 );
3797
3798 var PRECEDENCE = (function(a, ret){
3799         for (var i = 0, n = 1; i < a.length; ++i, ++n) {
3800                 var b = a[i];
3801                 for (var j = 0; j < b.length; ++j) {
3802                         ret[b[j]] = n;
3803                 }
3804         }
3805         return ret;
3806 })(
3807         [
3808                 ["||"],
3809                 ["&&"],
3810                 ["|"],
3811                 ["^"],
3812                 ["&"],
3813                 ["==", "===", "!=", "!=="],
3814                 ["<", ">", "<=", ">=", "in", "instanceof"],
3815                 [">>", "<<", ">>>"],
3816                 ["+", "-"],
3817                 ["*", "/", "%"]
3818         ],
3819         {}
3820 );
3821
3822 var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
3823
3824 var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
3825
3826 /* -----[ Parser ]----- */
3827
3828 function NodeWithToken(str, start, end) {
3829         this.name = str;
3830         this.start = start;
3831         this.end = end;
3832 };
3833
3834 NodeWithToken.prototype.toString = function() { return this.name; };
3835
3836 function parse($TEXT, exigent_mode, embed_tokens) {
3837
3838         var S = {
3839                 input       : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT,
3840                 token       : null,
3841                 prev        : null,
3842                 peeked      : null,
3843                 in_function : 0,
3844                 in_loop     : 0,
3845                 labels      : []
3846         };
3847
3848         S.token = next();
3849
3850         function is(type, value) {
3851                 return is_token(S.token, type, value);
3852         };
3853
3854         function peek() { return S.peeked || (S.peeked = S.input()); };
3855
3856         function next() {
3857                 S.prev = S.token;
3858                 if (S.peeked) {
3859                         S.token = S.peeked;
3860                         S.peeked = null;
3861                 } else {
3862                         S.token = S.input();
3863                 }
3864                 return S.token;
3865         };
3866
3867         function prev() {
3868                 return S.prev;
3869         };
3870
3871         function croak(msg, line, col, pos) {
3872                 var ctx = S.input.context();
3873                 js_error(msg,
3874                          line != null ? line : ctx.tokline,
3875                          col != null ? col : ctx.tokcol,
3876                          pos != null ? pos : ctx.tokpos);
3877         };
3878
3879         function token_error(token, msg) {
3880                 croak(msg, token.line, token.col);
3881         };
3882
3883         function unexpected(token) {
3884                 if (token == null)
3885                         token = S.token;
3886                 token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
3887         };
3888
3889         function expect_token(type, val) {
3890                 if (is(type, val)) {
3891                         return next();
3892                 }
3893                 token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type);
3894         };
3895
3896         function expect(punc) { return expect_token("punc", punc); };
3897
3898         function can_insert_semicolon() {
3899                 return !exigent_mode && (
3900                         S.token.nlb || is("eof") || is("punc", "}")
3901                 );
3902         };
3903
3904         function semicolon() {
3905                 if (is("punc", ";")) next();
3906                 else if (!can_insert_semicolon()) unexpected();
3907         };
3908
3909         function as() {
3910                 return slice(arguments);
3911         };
3912
3913         function parenthesised() {
3914                 expect("(");
3915                 var ex = expression();
3916                 expect(")");
3917                 return ex;
3918         };
3919
3920         function add_tokens(str, start, end) {
3921                 return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);
3922         };
3923
3924         function maybe_embed_tokens(parser) {
3925                 if (embed_tokens) return function() {
3926                         var start = S.token;
3927                         var ast = parser.apply(this, arguments);
3928                         ast[0] = add_tokens(ast[0], start, prev());
3929                         return ast;
3930                 };
3931                 else return parser;
3932         };
3933
3934         var statement = maybe_embed_tokens(function() {
3935                 if (is("operator", "/") || is("operator", "/=")) {
3936                         S.peeked = null;
3937                         S.token = S.input(S.token.value.substr(1)); // force regexp
3938                 }
3939                 switch (S.token.type) {
3940                     case "num":
3941                     case "string":
3942                     case "regexp":
3943                     case "operator":
3944                     case "atom":
3945                         return simple_statement();
3946
3947                     case "name":
3948                         return is_token(peek(), "punc", ":")
3949                                 ? labeled_statement(prog1(S.token.value, next, next))
3950                                 : simple_statement();
3951
3952                     case "punc":
3953                         switch (S.token.value) {
3954                             case "{":
3955                                 return as("block", block_());
3956                             case "[":
3957                             case "(":
3958                                 return simple_statement();
3959                             case ";":
3960                                 next();
3961                                 return as("block");
3962                             default:
3963                                 unexpected();
3964                         }
3965
3966                     case "keyword":
3967                         switch (prog1(S.token.value, next)) {
3968                             case "break":
3969                                 return break_cont("break");
3970
3971                             case "continue":
3972                                 return break_cont("continue");
3973
3974                             case "debugger":
3975                                 semicolon();
3976                                 return as("debugger");
3977
3978                             case "do":
3979                                 return (function(body){
3980                                         expect_token("keyword", "while");
3981                                         return as("do", prog1(parenthesised, semicolon), body);
3982                                 })(in_loop(statement));
3983
3984                             case "for":
3985                                 return for_();
3986
3987                             case "function":
3988                                 return function_(true);
3989
3990                             case "if":
3991                                 return if_();
3992
3993                             case "return":
3994                                 if (S.in_function == 0)
3995                                         croak("'return' outside of function");
3996                                 return as("return",
3997                                           is("punc", ";")
3998                                           ? (next(), null)
3999                                           : can_insert_semicolon()
4000                                           ? null
4001                                           : prog1(expression, semicolon));
4002
4003                             case "switch":
4004                                 return as("switch", parenthesised(), switch_block_());
4005
4006                             case "throw":
4007                                 if (S.token.nlb)
4008                                         croak("Illegal newline after 'throw'");
4009                                 return as("throw", prog1(expression, semicolon));
4010
4011                             case "try":
4012                                 return try_();
4013
4014                             case "var":
4015                                 return prog1(var_, semicolon);
4016
4017                             case "const":
4018                                 return prog1(const_, semicolon);
4019
4020                             case "while":
4021                                 return as("while", parenthesised(), in_loop(statement));
4022
4023                             case "with":
4024                                 return as("with", parenthesised(), statement());
4025
4026                             default:
4027                                 unexpected();
4028                         }
4029                 }
4030         });
4031
4032         function labeled_statement(label) {
4033                 S.labels.push(label);
4034                 var start = S.token, stat = statement();
4035                 if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
4036                         unexpected(start);
4037                 S.labels.pop();
4038                 return as("label", label, stat);
4039         };
4040
4041         function simple_statement() {
4042                 return as("stat", prog1(expression, semicolon));
4043         };
4044
4045         function break_cont(type) {
4046                 var name;
4047                 if (!can_insert_semicolon()) {
4048                         name = is("name") ? S.token.value : null;
4049                 }
4050                 if (name != null) {
4051                         next();
4052                         if (!member(name, S.labels))
4053                                 croak("Label " + name + " without matching loop or statement");
4054                 }
4055                 else if (S.in_loop == 0)
4056                         croak(type + " not inside a loop or switch");
4057                 semicolon();
4058                 return as(type, name);
4059         };
4060
4061         function for_() {
4062                 expect("(");
4063                 var init = null;
4064                 if (!is("punc", ";")) {
4065                         init = is("keyword", "var")
4066                                 ? (next(), var_(true))
4067                                 : expression(true, true);
4068                         if (is("operator", "in"))
4069                                 return for_in(init);
4070                 }
4071                 return regular_for(init);
4072         };
4073
4074         function regular_for(init) {
4075                 expect(";");
4076                 var test = is("punc", ";") ? null : expression();
4077                 expect(";");
4078                 var step = is("punc", ")") ? null : expression();
4079                 expect(")");
4080                 return as("for", init, test, step, in_loop(statement));
4081         };
4082
4083         function for_in(init) {
4084                 var lhs = init[0] == "var" ? as("name", init[1][0]) : init;
4085                 next();
4086                 var obj = expression();
4087                 expect(")");
4088                 return as("for-in", init, lhs, obj, in_loop(statement));
4089         };
4090
4091         var function_ = function(in_statement) {
4092                 var name = is("name") ? prog1(S.token.value, next) : null;
4093                 if (in_statement && !name)
4094                         unexpected();
4095                 expect("(");
4096                 return as(in_statement ? "defun" : "function",
4097                           name,
4098                           // arguments
4099                           (function(first, a){
4100                                   while (!is("punc", ")")) {
4101                                           if (first) first = false; else expect(",");
4102                                           if (!is("name")) unexpected();
4103                                           a.push(S.token.value);
4104                                           next();
4105                                   }
4106                                   next();
4107                                   return a;
4108                           })(true, []),
4109                           // body
4110                           (function(){
4111                                   ++S.in_function;
4112                                   var loop = S.in_loop;
4113                                   S.in_loop = 0;
4114                                   var a = block_();
4115                                   --S.in_function;
4116                                   S.in_loop = loop;
4117                                   return a;
4118                           })());
4119         };
4120
4121         function if_() {
4122                 var cond = parenthesised(), body = statement(), belse;
4123                 if (is("keyword", "else")) {
4124                         next();
4125                         belse = statement();
4126                 }
4127                 return as("if", cond, body, belse);
4128         };
4129
4130         function block_() {
4131                 expect("{");
4132                 var a = [];
4133                 while (!is("punc", "}")) {
4134                         if (is("eof")) unexpected();
4135                         a.push(statement());
4136                 }
4137                 next();
4138                 return a;
4139         };
4140
4141         var switch_block_ = curry(in_loop, function(){
4142                 expect("{");
4143                 var a = [], cur = null;
4144                 while (!is("punc", "}")) {
4145                         if (is("eof")) unexpected();
4146                         if (is("keyword", "case")) {
4147                                 next();
4148                                 cur = [];
4149                                 a.push([ expression(), cur ]);
4150                                 expect(":");
4151                         }
4152                         else if (is("keyword", "default")) {
4153                                 next();
4154                                 expect(":");
4155                                 cur = [];
4156                                 a.push([ null, cur ]);
4157                         }
4158                         else {
4159                                 if (!cur) unexpected();
4160                                 cur.push(statement());
4161                         }
4162                 }
4163                 next();
4164                 return a;
4165         });
4166
4167         function try_() {
4168                 var body = block_(), bcatch, bfinally;
4169                 if (is("keyword", "catch")) {
4170                         next();
4171                         expect("(");
4172                         if (!is("name"))
4173                                 croak("Name expected");
4174                         var name = S.token.value;
4175                         next();
4176                         expect(")");
4177                         bcatch = [ name, block_() ];
4178                 }
4179                 if (is("keyword", "finally")) {
4180                         next();
4181                         bfinally = block_();
4182                 }
4183                 if (!bcatch && !bfinally)
4184                         croak("Missing catch/finally blocks");
4185                 return as("try", body, bcatch, bfinally);
4186         };
4187
4188         function vardefs(no_in) {
4189                 var a = [];
4190                 for (;;) {
4191                         if (!is("name"))
4192                                 unexpected();
4193                         var name = S.token.value;
4194                         next();
4195                         if (is("operator", "=")) {
4196                                 next();
4197                                 a.push([ name, expression(false, no_in) ]);
4198                         } else {
4199                                 a.push([ name ]);
4200                         }
4201                         if (!is("punc", ","))
4202                                 break;
4203                         next();
4204                 }
4205                 return a;
4206         };
4207
4208         function var_(no_in) {
4209                 return as("var", vardefs(no_in));
4210         };
4211
4212         function const_() {
4213                 return as("const", vardefs());
4214         };
4215
4216         function new_() {
4217                 var newexp = expr_atom(false), args;
4218                 if (is("punc", "(")) {
4219                         next();
4220                         args = expr_list(")");
4221                 } else {
4222                         args = [];
4223                 }
4224                 return subscripts(as("new", newexp, args), true);
4225         };
4226
4227         var expr_atom = maybe_embed_tokens(function(allow_calls) {
4228                 if (is("operator", "new")) {
4229                         next();
4230                         return new_();
4231                 }
4232                 if (is("punc")) {
4233                         switch (S.token.value) {
4234                             case "(":
4235                                 next();
4236                                 return subscripts(prog1(expression, curry(expect, ")")), allow_calls);
4237                             case "[":
4238                                 next();
4239                                 return subscripts(array_(), allow_calls);
4240                             case "{":
4241                                 next();
4242                                 return subscripts(object_(), allow_calls);
4243                         }
4244                         unexpected();
4245                 }
4246                 if (is("keyword", "function")) {
4247                         next();
4248                         return subscripts(function_(false), allow_calls);
4249                 }
4250                 if (HOP(ATOMIC_START_TOKEN, S.token.type)) {
4251                         var atom = S.token.type == "regexp"
4252                                 ? as("regexp", S.token.value[0], S.token.value[1])
4253                                 : as(S.token.type, S.token.value);
4254                         return subscripts(prog1(atom, next), allow_calls);
4255                 }
4256                 unexpected();
4257         });
4258
4259         function expr_list(closing, allow_trailing_comma, allow_empty) {
4260                 var first = true, a = [];
4261                 while (!is("punc", closing)) {
4262                         if (first) first = false; else expect(",");
4263                         if (allow_trailing_comma && is("punc", closing)) break;
4264                         if (is("punc", ",") && allow_empty) {
4265                                 a.push([ "atom", "undefined" ]);
4266                         } else {
4267                                 a.push(expression(false));
4268                         }
4269                 }
4270                 next();
4271                 return a;
4272         };
4273
4274         function array_() {
4275                 return as("array", expr_list("]", !exigent_mode, true));
4276         };
4277
4278         function object_() {
4279                 var first = true, a = [];
4280                 while (!is("punc", "}")) {
4281                         if (first) first = false; else expect(",");
4282                         if (!exigent_mode && is("punc", "}"))
4283                                 // allow trailing comma
4284                                 break;
4285                         var type = S.token.type;
4286                         var name = as_property_name();
4287                         if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) {
4288                                 a.push([ as_name(), function_(false), name ]);
4289                         } else {
4290                                 expect(":");
4291                                 a.push([ name, expression(false) ]);
4292                         }
4293                 }
4294                 next();
4295                 return as("object", a);
4296         };
4297
4298         function as_property_name() {
4299                 switch (S.token.type) {
4300                     case "num":
4301                     case "string":
4302                         return prog1(S.token.value, next);
4303                 }
4304                 return as_name();
4305         };
4306
4307         function as_name() {
4308                 switch (S.token.type) {
4309                     case "name":
4310                     case "operator":
4311                     case "keyword":
4312                     case "atom":
4313                         return prog1(S.token.value, next);
4314                     default:
4315                         unexpected();
4316                 }
4317         };
4318
4319         function subscripts(expr, allow_calls) {
4320                 if (is("punc", ".")) {
4321                         next();
4322                         return subscripts(as("dot", expr, as_name()), allow_calls);
4323                 }
4324                 if (is("punc", "[")) {
4325                         next();
4326                         return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls);
4327                 }
4328                 if (allow_calls && is("punc", "(")) {
4329                         next();
4330                         return subscripts(as("call", expr, expr_list(")")), true);
4331                 }
4332                 return expr;
4333         };
4334
4335         function maybe_unary(allow_calls) {
4336                 if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) {
4337                         return make_unary("unary-prefix",
4338                                           prog1(S.token.value, next),
4339                                           maybe_unary(allow_calls));
4340                 }
4341                 var val = expr_atom(allow_calls);
4342                 while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) {
4343                         val = make_unary("unary-postfix", S.token.value, val);
4344                         next();
4345                 }
4346                 return val;
4347         };
4348
4349         function make_unary(tag, op, expr) {
4350                 if ((op == "++" || op == "--") && !is_assignable(expr))
4351                         croak("Invalid use of " + op + " operator");
4352                 return as(tag, op, expr);
4353         };
4354
4355         function expr_op(left, min_prec, no_in) {
4356                 var op = is("operator") ? S.token.value : null;
4357                 if (op && op == "in" && no_in) op = null;
4358                 var prec = op != null ? PRECEDENCE[op] : null;
4359                 if (prec != null && prec > min_prec) {
4360                         next();
4361                         var right = expr_op(maybe_unary(true), prec, no_in);
4362                         return expr_op(as("binary", op, left, right), min_prec, no_in);
4363                 }
4364                 return left;
4365         };
4366
4367         function expr_ops(no_in) {
4368                 return expr_op(maybe_unary(true), 0, no_in);
4369         };
4370
4371         function maybe_conditional(no_in) {
4372                 var expr = expr_ops(no_in);
4373                 if (is("operator", "?")) {
4374                         next();
4375                         var yes = expression(false);
4376                         expect(":");
4377                         return as("conditional", expr, yes, expression(false, no_in));
4378                 }
4379                 return expr;
4380         };
4381
4382         function is_assignable(expr) {
4383                 if (!exigent_mode) return true;
4384                 switch (expr[0]+"") {
4385                     case "dot":
4386                     case "sub":
4387                     case "new":
4388                     case "call":
4389                         return true;
4390                     case "name":
4391                         return expr[1] != "this";
4392                 }
4393         };
4394
4395         function maybe_assign(no_in) {
4396                 var left = maybe_conditional(no_in), val = S.token.value;
4397                 if (is("operator") && HOP(ASSIGNMENT, val)) {
4398                         if (is_assignable(left)) {
4399                                 next();
4400                                 return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in));
4401                         }
4402                         croak("Invalid assignment");
4403                 }
4404                 return left;
4405         };
4406
4407         var expression = maybe_embed_tokens(function(commas, no_in) {
4408                 if (arguments.length == 0)
4409                         commas = true;
4410                 var expr = maybe_assign(no_in);
4411                 if (commas && is("punc", ",")) {
4412                         next();
4413                         return as("seq", expr, expression(true, no_in));
4414                 }
4415                 return expr;
4416         });
4417
4418         function in_loop(cont) {
4419                 try {
4420                         ++S.in_loop;
4421                         return cont();
4422                 } finally {
4423                         --S.in_loop;
4424                 }
4425         };
4426
4427         return as("toplevel", (function(a){
4428                 while (!is("eof"))
4429                         a.push(statement());
4430                 return a;
4431         })([]));
4432
4433 };
4434
4435 /* -----[ Utilities ]----- */
4436
4437 function curry(f) {
4438         var args = slice(arguments, 1);
4439         return function() { return f.apply(this, args.concat(slice(arguments))); };
4440 };
4441
4442 function prog1(ret) {
4443         if (ret instanceof Function)
4444                 ret = ret();
4445         for (var i = 1, n = arguments.length; --n > 0; ++i)
4446                 arguments[i]();
4447         return ret;
4448 };
4449
4450 function array_to_hash(a) {
4451         var ret = {};
4452         for (var i = 0; i < a.length; ++i)
4453                 ret[a[i]] = true;
4454         return ret;
4455 };
4456
4457 function slice(a, start) {
4458         return Array.prototype.slice.call(a, start || 0);
4459 };
4460
4461 function characters(str) {
4462         return str.split("");
4463 };
4464
4465 function member(name, array) {
4466         for (var i = array.length; --i >= 0;)
4467                 if (array[i] == name)
4468                         return true;
4469         return false;
4470 };
4471
4472 function HOP(obj, prop) {
4473         return Object.prototype.hasOwnProperty.call(obj, prop);
4474 };
4475
4476 var warn = function() {};
4477
4478 /* -----[ Exports ]----- */
4479
4480 exports.tokenizer = tokenizer;
4481 exports.parse = parse;
4482 exports.slice = slice;
4483 exports.curry = curry;
4484 exports.member = member;
4485 exports.array_to_hash = array_to_hash;
4486 exports.PRECEDENCE = PRECEDENCE;
4487 exports.KEYWORDS_ATOM = KEYWORDS_ATOM;
4488 exports.RESERVED_WORDS = RESERVED_WORDS;
4489 exports.KEYWORDS = KEYWORDS;
4490 exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;
4491 exports.OPERATORS = OPERATORS;
4492 exports.is_alphanumeric_char = is_alphanumeric_char;
4493 exports.set_logger = function(logger) {
4494         warn = logger;
4495 };
4496
4497 });
4498 define('uglifyjs/squeeze-more', ["require", "exports", "module", "./parse-js", "./process"], function(require, exports, module) {
4499
4500 var jsp = require("./parse-js"),
4501     pro = require("./process"),
4502     slice = jsp.slice,
4503     member = jsp.member,
4504     curry = jsp.curry,
4505     MAP = pro.MAP,
4506     PRECEDENCE = jsp.PRECEDENCE,
4507     OPERATORS = jsp.OPERATORS;
4508
4509 function ast_squeeze_more(ast) {
4510         var w = pro.ast_walker(), walk = w.walk, scope;
4511         function with_scope(s, cont) {
4512                 var save = scope, ret;
4513                 scope = s;
4514                 ret = cont();
4515                 scope = save;
4516                 return ret;
4517         };
4518         function _lambda(name, args, body) {
4519                 return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];
4520         };
4521         return w.with_walkers({
4522                 "toplevel": function(body) {
4523                         return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];
4524                 },
4525                 "function": _lambda,
4526                 "defun": _lambda,
4527                 "new": function(ctor, args) {
4528                         if (ctor[0] == "name") {
4529                                 if (ctor[1] == "Array" && !scope.has("Array")) {
4530                                         if (args.length != 1) {
4531                                                 return [ "array", args ];
4532                                         } else {
4533                                                 return walk([ "call", [ "name", "Array" ], args ]);
4534                                         }
4535                                 } else if (ctor[1] == "Object" && !scope.has("Object")) {
4536                                         if (!args.length) {
4537                                                 return [ "object", [] ];
4538                                         } else {
4539                                                 return walk([ "call", [ "name", "Object" ], args ]);
4540                                         }
4541                                 } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) {
4542                                         return walk([ "call", [ "name", ctor[1] ], args]);
4543                                 }
4544                         }
4545                 },
4546                 "call": function(expr, args) {
4547                         if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
4548                                 // foo.toString()  ==>  foo+""
4549                                 return [ "binary", "+", expr[1], [ "string", "" ]];
4550                         }
4551                         if (expr[0] == "name") {
4552                                 if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
4553                                         return [ "array", args ];
4554                                 }
4555                                 if (expr[1] == "Object" && !args.length && !scope.has("Object")) {
4556                                         return [ "object", [] ];
4557                                 }
4558                                 if (expr[1] == "String" && !scope.has("String")) {
4559                                         return [ "binary", "+", args[0], [ "string", "" ]];
4560                                 }
4561                         }
4562                 }
4563         }, function() {
4564                 return walk(pro.ast_add_scope(ast));
4565         });
4566 };
4567
4568 exports.ast_squeeze_more = ast_squeeze_more;
4569
4570 });define('uglifyjs/process', ["require", "exports", "module", "./parse-js", "./squeeze-more"], function(require, exports, module) {
4571
4572 /***********************************************************************
4573
4574   A JavaScript tokenizer / parser / beautifier / compressor.
4575
4576   This version is suitable for Node.js.  With minimal changes (the
4577   exports stuff) it should work on any JS platform.
4578
4579   This file implements some AST processors.  They work on data built
4580   by parse-js.
4581
4582   Exported functions:
4583
4584     - ast_mangle(ast, options) -- mangles the variable/function names
4585       in the AST.  Returns an AST.
4586
4587     - ast_squeeze(ast) -- employs various optimizations to make the
4588       final generated code even smaller.  Returns an AST.
4589
4590     - gen_code(ast, options) -- generates JS code from the AST.  Pass
4591       true (or an object, see the code for some options) as second
4592       argument to get "pretty" (indented) code.
4593
4594   -------------------------------- (C) ---------------------------------
4595
4596                            Author: Mihai Bazon
4597                          <mihai.bazon@gmail.com>
4598                        http://mihai.bazon.net/blog
4599
4600   Distributed under the BSD license:
4601
4602     Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
4603
4604     Redistribution and use in source and binary forms, with or without
4605     modification, are permitted provided that the following conditions
4606     are met:
4607
4608         * Redistributions of source code must retain the above
4609           copyright notice, this list of conditions and the following
4610           disclaimer.
4611
4612         * Redistributions in binary form must reproduce the above
4613           copyright notice, this list of conditions and the following
4614           disclaimer in the documentation and/or other materials
4615           provided with the distribution.
4616
4617     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
4618     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4619     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4620     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
4621     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
4622     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4623     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4624     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4625     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
4626     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
4627     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4628     SUCH DAMAGE.
4629
4630  ***********************************************************************/
4631
4632 var jsp = require("./parse-js"),
4633     slice = jsp.slice,
4634     member = jsp.member,
4635     PRECEDENCE = jsp.PRECEDENCE,
4636     OPERATORS = jsp.OPERATORS;
4637
4638 /* -----[ helper for AST traversal ]----- */
4639
4640 function ast_walker() {
4641         function _vardefs(defs) {
4642                 return [ this[0], MAP(defs, function(def){
4643                         var a = [ def[0] ];
4644                         if (def.length > 1)
4645                                 a[1] = walk(def[1]);
4646                         return a;
4647                 }) ];
4648         };
4649         function _block(statements) {
4650                 var out = [ this[0] ];
4651                 if (statements != null)
4652                         out.push(MAP(statements, walk));
4653                 return out;
4654         };
4655         var walkers = {
4656                 "string": function(str) {
4657                         return [ this[0], str ];
4658                 },
4659                 "num": function(num) {
4660                         return [ this[0], num ];
4661                 },
4662                 "name": function(name) {
4663                         return [ this[0], name ];
4664                 },
4665                 "toplevel": function(statements) {
4666                         return [ this[0], MAP(statements, walk) ];
4667                 },
4668                 "block": _block,
4669                 "splice": _block,
4670                 "var": _vardefs,
4671                 "const": _vardefs,
4672                 "try": function(t, c, f) {
4673                         return [
4674                                 this[0],
4675                                 MAP(t, walk),
4676                                 c != null ? [ c[0], MAP(c[1], walk) ] : null,
4677                                 f != null ? MAP(f, walk) : null
4678                         ];
4679                 },
4680                 "throw": function(expr) {
4681                         return [ this[0], walk(expr) ];
4682                 },
4683                 "new": function(ctor, args) {
4684                         return [ this[0], walk(ctor), MAP(args, walk) ];
4685                 },
4686                 "switch": function(expr, body) {
4687                         return [ this[0], walk(expr), MAP(body, function(branch){
4688                                 return [ branch[0] ? walk(branch[0]) : null,
4689                                          MAP(branch[1], walk) ];
4690                         }) ];
4691                 },
4692                 "break": function(label) {
4693                         return [ this[0], label ];
4694                 },
4695                 "continue": function(label) {
4696                         return [ this[0], label ];
4697                 },
4698                 "conditional": function(cond, t, e) {
4699                         return [ this[0], walk(cond), walk(t), walk(e) ];
4700                 },
4701                 "assign": function(op, lvalue, rvalue) {
4702                         return [ this[0], op, walk(lvalue), walk(rvalue) ];
4703                 },
4704                 "dot": function(expr) {
4705                         return [ this[0], walk(expr) ].concat(slice(arguments, 1));
4706                 },
4707                 "call": function(expr, args) {
4708                         return [ this[0], walk(expr), MAP(args, walk) ];
4709                 },
4710                 "function": function(name, args, body) {
4711                         return [ this[0], name, args.slice(), MAP(body, walk) ];
4712                 },
4713                 "defun": function(name, args, body) {
4714                         return [ this[0], name, args.slice(), MAP(body, walk) ];
4715                 },
4716                 "if": function(conditional, t, e) {
4717                         return [ this[0], walk(conditional), walk(t), walk(e) ];
4718                 },
4719                 "for": function(init, cond, step, block) {
4720                         return [ this[0], walk(init), walk(cond), walk(step), walk(block) ];
4721                 },
4722                 "for-in": function(vvar, key, hash, block) {
4723                         return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ];
4724                 },
4725                 "while": function(cond, block) {
4726                         return [ this[0], walk(cond), walk(block) ];
4727                 },
4728                 "do": function(cond, block) {
4729                         return [ this[0], walk(cond), walk(block) ];
4730                 },
4731                 "return": function(expr) {
4732                         return [ this[0], walk(expr) ];
4733                 },
4734                 "binary": function(op, left, right) {
4735                         return [ this[0], op, walk(left), walk(right) ];
4736                 },
4737                 "unary-prefix": function(op, expr) {
4738                         return [ this[0], op, walk(expr) ];
4739                 },
4740                 "unary-postfix": function(op, expr) {
4741                         return [ this[0], op, walk(expr) ];
4742                 },
4743                 "sub": function(expr, subscript) {
4744                         return [ this[0], walk(expr), walk(subscript) ];
4745                 },
4746                 "object": function(props) {
4747                         return [ this[0], MAP(props, function(p){
4748                                 return p.length == 2
4749                                         ? [ p[0], walk(p[1]) ]
4750                                         : [ p[0], walk(p[1]), p[2] ]; // get/set-ter
4751                         }) ];
4752                 },
4753                 "regexp": function(rx, mods) {
4754                         return [ this[0], rx, mods ];
4755                 },
4756                 "array": function(elements) {
4757                         return [ this[0], MAP(elements, walk) ];
4758                 },
4759                 "stat": function(stat) {
4760                         return [ this[0], walk(stat) ];
4761                 },
4762                 "seq": function() {
4763                         return [ this[0] ].concat(MAP(slice(arguments), walk));
4764                 },
4765                 "label": function(name, block) {
4766                         return [ this[0], name, walk(block) ];
4767                 },
4768                 "with": function(expr, block) {
4769                         return [ this[0], walk(expr), walk(block) ];
4770                 },
4771                 "atom": function(name) {
4772                         return [ this[0], name ];
4773                 }
4774         };
4775
4776         var user = {};
4777         var stack = [];
4778         function walk(ast) {
4779                 if (ast == null)
4780                         return null;
4781                 try {
4782                         stack.push(ast);
4783                         var type = ast[0];
4784                         var gen = user[type];
4785                         if (gen) {
4786                                 var ret = gen.apply(ast, ast.slice(1));
4787                                 if (ret != null)
4788                                         return ret;
4789                         }
4790                         gen = walkers[type];
4791                         return gen.apply(ast, ast.slice(1));
4792                 } finally {
4793                         stack.pop();
4794                 }
4795         };
4796
4797         function dive(ast) {
4798                 if (ast == null)
4799                         return null;
4800                 try {
4801                         stack.push(ast);
4802                         return walkers[ast[0]].apply(ast, ast.slice(1));
4803                 } finally {
4804                         stack.pop();
4805                 }
4806         };
4807
4808         function with_walkers(walkers, cont){
4809                 var save = {}, i;
4810                 for (i in walkers) if (HOP(walkers, i)) {
4811                         save[i] = user[i];
4812                         user[i] = walkers[i];
4813                 }
4814                 var ret = cont();
4815                 for (i in save) if (HOP(save, i)) {
4816                         if (!save[i]) delete user[i];
4817                         else user[i] = save[i];
4818                 }
4819                 return ret;
4820         };
4821
4822         return {
4823                 walk: walk,
4824                 dive: dive,
4825                 with_walkers: with_walkers,
4826                 parent: function() {
4827                         return stack[stack.length - 2]; // last one is current node
4828                 },
4829                 stack: function() {
4830                         return stack;
4831                 }
4832         };
4833 };
4834
4835 /* -----[ Scope and mangling ]----- */
4836
4837 function Scope(parent) {
4838         this.names = {};        // names defined in this scope
4839         this.mangled = {};      // mangled names (orig.name => mangled)
4840         this.rev_mangled = {};  // reverse lookup (mangled => orig.name)
4841         this.cname = -1;        // current mangled name
4842         this.refs = {};         // names referenced from this scope
4843         this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes
4844         this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes
4845         this.parent = parent;   // parent scope
4846         this.children = [];     // sub-scopes
4847         if (parent) {
4848                 this.level = parent.level + 1;
4849                 parent.children.push(this);
4850         } else {
4851                 this.level = 0;
4852         }
4853 };
4854
4855 var base54 = (function(){
4856         var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
4857         return function(num) {
4858                 var ret = "";
4859                 do {
4860                         ret = DIGITS.charAt(num % 54) + ret;
4861                         num = Math.floor(num / 54);
4862                 } while (num > 0);
4863                 return ret;
4864         };
4865 })();
4866
4867 Scope.prototype = {
4868         has: function(name) {
4869                 for (var s = this; s; s = s.parent)
4870                         if (HOP(s.names, name))
4871                                 return s;
4872         },
4873         has_mangled: function(mname) {
4874                 for (var s = this; s; s = s.parent)
4875                         if (HOP(s.rev_mangled, mname))
4876                                 return s;
4877         },
4878         toJSON: function() {
4879                 return {
4880                         names: this.names,
4881                         uses_eval: this.uses_eval,
4882                         uses_with: this.uses_with
4883                 };
4884         },
4885
4886         next_mangled: function() {
4887                 // we must be careful that the new mangled name:
4888                 //
4889                 // 1. doesn't shadow a mangled name from a parent
4890                 //    scope, unless we don't reference the original
4891                 //    name from this scope OR from any sub-scopes!
4892                 //    This will get slow.
4893                 //
4894                 // 2. doesn't shadow an original name from a parent
4895                 //    scope, in the event that the name is not mangled
4896                 //    in the parent scope and we reference that name
4897                 //    here OR IN ANY SUBSCOPES!
4898                 //
4899                 // 3. doesn't shadow a name that is referenced but not
4900                 //    defined (possibly global defined elsewhere).
4901                 for (;;) {
4902                         var m = base54(++this.cname), prior;
4903
4904                         // case 1.
4905                         prior = this.has_mangled(m);
4906                         if (prior && this.refs[prior.rev_mangled[m]] === prior)
4907                                 continue;
4908
4909                         // case 2.
4910                         prior = this.has(m);
4911                         if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m))
4912                                 continue;
4913
4914                         // case 3.
4915                         if (HOP(this.refs, m) && this.refs[m] == null)
4916                                 continue;
4917
4918                         // I got "do" once. :-/
4919                         if (!is_identifier(m))
4920                                 continue;
4921
4922                         return m;
4923                 }
4924         },
4925         set_mangle: function(name, m) {
4926                 this.rev_mangled[m] = name;
4927                 return this.mangled[name] = m;
4928         },
4929         get_mangled: function(name, newMangle) {
4930                 if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use
4931                 var s = this.has(name);
4932                 if (!s) return name; // not in visible scope, no mangle
4933                 if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope
4934                 if (!newMangle) return name;                      // not found and no mangling requested
4935                 return s.set_mangle(name, s.next_mangled());
4936         },
4937         references: function(name) {
4938                 return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name];
4939         },
4940         define: function(name, type) {
4941                 if (name != null) {
4942                         if (type == "var" || !HOP(this.names, name))
4943                                 this.names[name] = type || "var";
4944                         return name;
4945                 }
4946         }
4947 };
4948
4949 function ast_add_scope(ast) {
4950
4951         var current_scope = null;
4952         var w = ast_walker(), walk = w.walk;
4953         var having_eval = [];
4954
4955         function with_new_scope(cont) {
4956                 current_scope = new Scope(current_scope);
4957                 current_scope.labels = new Scope();
4958                 var ret = current_scope.body = cont();
4959                 ret.scope = current_scope;
4960                 current_scope = current_scope.parent;
4961                 return ret;
4962         };
4963
4964         function define(name, type) {
4965                 return current_scope.define(name, type);
4966         };
4967
4968         function reference(name) {
4969                 current_scope.refs[name] = true;
4970         };
4971
4972         function _lambda(name, args, body) {
4973                 var is_defun = this[0] == "defun";
4974                 return [ this[0], is_defun ? define(name, "defun") : name, args, with_new_scope(function(){
4975                         if (!is_defun) define(name, "lambda");
4976                         MAP(args, function(name){ define(name, "arg") });
4977                         return MAP(body, walk);
4978                 })];
4979         };
4980
4981         function _vardefs(type) {
4982                 return function(defs) {
4983                         MAP(defs, function(d){
4984                                 define(d[0], type);
4985                                 if (d[1]) reference(d[0]);
4986                         });
4987                 };
4988         };
4989
4990         function _breacont(label) {
4991                 if (label)
4992                         current_scope.labels.refs[label] = true;
4993         };
4994
4995         return with_new_scope(function(){
4996                 // process AST
4997                 var ret = w.with_walkers({
4998                         "function": _lambda,
4999                         "defun": _lambda,
5000                         "label": function(name, stat) { current_scope.labels.define(name) },
5001                         "break": _breacont,
5002                         "continue": _breacont,
5003                         "with": function(expr, block) {
5004                                 for (var s = current_scope; s; s = s.parent)
5005                                         s.uses_with = true;
5006                         },
5007                         "var": _vardefs("var"),
5008                         "const": _vardefs("const"),
5009                         "try": function(t, c, f) {
5010                                 if (c != null) return [
5011                                         this[0],
5012                                         MAP(t, walk),
5013                                         [ define(c[0], "catch"), MAP(c[1], walk) ],
5014                                         f != null ? MAP(f, walk) : null
5015                                 ];
5016                         },
5017                         "name": function(name) {
5018                                 if (name == "eval")
5019                                         having_eval.push(current_scope);
5020                                 reference(name);
5021                         }
5022                 }, function(){
5023                         return walk(ast);
5024                 });
5025
5026                 // the reason why we need an additional pass here is
5027                 // that names can be used prior to their definition.
5028
5029                 // scopes where eval was detected and their parents
5030                 // are marked with uses_eval, unless they define the
5031                 // "eval" name.
5032                 MAP(having_eval, function(scope){
5033                         if (!scope.has("eval")) while (scope) {
5034                                 scope.uses_eval = true;
5035                                 scope = scope.parent;
5036                         }
5037                 });
5038
5039                 // for referenced names it might be useful to know
5040                 // their origin scope.  current_scope here is the
5041                 // toplevel one.
5042                 function fixrefs(scope, i) {
5043                         // do children first; order shouldn't matter
5044                         for (i = scope.children.length; --i >= 0;)
5045                                 fixrefs(scope.children[i]);
5046                         for (i in scope.refs) if (HOP(scope.refs, i)) {
5047                                 // find origin scope and propagate the reference to origin
5048                                 for (var origin = scope.has(i), s = scope; s; s = s.parent) {
5049                                         s.refs[i] = origin;
5050                                         if (s === origin) break;
5051                                 }
5052                         }
5053                 };
5054                 fixrefs(current_scope);
5055
5056                 return ret;
5057         });
5058
5059 };
5060
5061 /* -----[ mangle names ]----- */
5062
5063 function ast_mangle(ast, options) {
5064         var w = ast_walker(), walk = w.walk, scope;
5065         options = options || {};
5066
5067         function get_mangled(name, newMangle) {
5068                 if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel
5069                 if (options.except && member(name, options.except))
5070                         return name;
5071                 return scope.get_mangled(name, newMangle);
5072         };
5073
5074         function get_define(name) {
5075                 if (options.defines) {
5076                         // we always lookup a defined symbol for the current scope FIRST, so declared
5077                         // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value
5078                         if (!scope.has(name)) {
5079                                 if (HOP(options.defines, name)) {
5080                                         return options.defines[name];
5081                                 }
5082                         }
5083                         return null;
5084                 }
5085         };
5086
5087         function _lambda(name, args, body) {
5088                 if (!options.no_functions) {
5089                         var is_defun = this[0] == "defun", extra;
5090                         if (name) {
5091                                 if (is_defun) name = get_mangled(name);
5092                                 else if (body.scope.references(name)) {
5093                                         extra = {};
5094                                         if (!(scope.uses_eval || scope.uses_with))
5095                                                 name = extra[name] = scope.next_mangled();
5096                                         else
5097                                                 extra[name] = name;
5098                                 }
5099                                 else name = null;
5100                         }
5101                 }
5102                 body = with_scope(body.scope, function(){
5103                         args = MAP(args, function(name){ return get_mangled(name) });
5104                         return MAP(body, walk);
5105                 }, extra);
5106                 return [ this[0], name, args, body ];
5107         };
5108
5109         function with_scope(s, cont, extra) {
5110                 var _scope = scope;
5111                 scope = s;
5112                 if (extra) for (var i in extra) if (HOP(extra, i)) {
5113                         s.set_mangle(i, extra[i]);
5114                 }
5115                 for (var i in s.names) if (HOP(s.names, i)) {
5116                         get_mangled(i, true);
5117                 }
5118                 var ret = cont();
5119                 ret.scope = s;
5120                 scope = _scope;
5121                 return ret;
5122         };
5123
5124         function _vardefs(defs) {
5125                 return [ this[0], MAP(defs, function(d){
5126                         return [ get_mangled(d[0]), walk(d[1]) ];
5127                 }) ];
5128         };
5129
5130         function _breacont(label) {
5131                 if (label) return [ this[0], scope.labels.get_mangled(label) ];
5132         };
5133
5134         return w.with_walkers({
5135                 "function": _lambda,
5136                 "defun": function() {
5137                         // move function declarations to the top when
5138                         // they are not in some block.
5139                         var ast = _lambda.apply(this, arguments);
5140                         switch (w.parent()[0]) {
5141                             case "toplevel":
5142                             case "function":
5143                             case "defun":
5144                                 return MAP.at_top(ast);
5145                         }
5146                         return ast;
5147                 },
5148                 "label": function(label, stat) {
5149                         if (scope.labels.refs[label]) return [
5150                                 this[0],
5151                                 scope.labels.get_mangled(label, true),
5152                                 walk(stat)
5153                         ];
5154                         return walk(stat);
5155                 },
5156                 "break": _breacont,
5157                 "continue": _breacont,
5158                 "var": _vardefs,
5159                 "const": _vardefs,
5160                 "name": function(name) {
5161                         return get_define(name) || [ this[0], get_mangled(name) ];
5162                 },
5163                 "try": function(t, c, f) {
5164                         return [ this[0],
5165                                  MAP(t, walk),
5166                                  c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,
5167                                  f != null ? MAP(f, walk) : null ];
5168                 },
5169                 "toplevel": function(body) {
5170                         var self = this;
5171                         return with_scope(self.scope, function(){
5172                                 return [ self[0], MAP(body, walk) ];
5173                         });
5174                 }
5175         }, function() {
5176                 return walk(ast_add_scope(ast));
5177         });
5178 };
5179
5180 /* -----[
5181    - compress foo["bar"] into foo.bar,
5182    - remove block brackets {} where possible
5183    - join consecutive var declarations
5184    - various optimizations for IFs:
5185      - if (cond) foo(); else bar();  ==>  cond?foo():bar();
5186      - if (cond) foo();  ==>  cond&&foo();
5187      - if (foo) return bar(); else return baz();  ==> return foo?bar():baz(); // also for throw
5188      - if (foo) return bar(); else something();  ==> {if(foo)return bar();something()}
5189    ]----- */
5190
5191 var warn = function(){};
5192
5193 function best_of(ast1, ast2) {
5194         return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1;
5195 };
5196
5197 function last_stat(b) {
5198         if (b[0] == "block" && b[1] && b[1].length > 0)
5199                 return b[1][b[1].length - 1];
5200         return b;
5201 }
5202
5203 function aborts(t) {
5204         if (t) switch (last_stat(t)[0]) {
5205             case "return":
5206             case "break":
5207             case "continue":
5208             case "throw":
5209                 return true;
5210         }
5211 };
5212
5213 function boolean_expr(expr) {
5214         return ( (expr[0] == "unary-prefix"
5215                   && member(expr[1], [ "!", "delete" ])) ||
5216
5217                  (expr[0] == "binary"
5218                   && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) ||
5219
5220                  (expr[0] == "binary"
5221                   && member(expr[1], [ "&&", "||" ])
5222                   && boolean_expr(expr[2])
5223                   && boolean_expr(expr[3])) ||
5224
5225                  (expr[0] == "conditional"
5226                   && boolean_expr(expr[2])
5227                   && boolean_expr(expr[3])) ||
5228
5229                  (expr[0] == "assign"
5230                   && expr[1] === true
5231                   && boolean_expr(expr[3])) ||
5232
5233                  (expr[0] == "seq"
5234                   && boolean_expr(expr[expr.length - 1]))
5235                );
5236 };
5237
5238 function empty(b) {
5239         return !b || (b[0] == "block" && (!b[1] || b[1].length == 0));
5240 };
5241
5242 function is_string(node) {
5243         return (node[0] == "string" ||
5244                 node[0] == "unary-prefix" && node[1] == "typeof" ||
5245                 node[0] == "binary" && node[1] == "+" &&
5246                 (is_string(node[2]) || is_string(node[3])));
5247 };
5248
5249 var when_constant = (function(){
5250
5251         var $NOT_CONSTANT = {};
5252
5253         // this can only evaluate constant expressions.  If it finds anything
5254         // not constant, it throws $NOT_CONSTANT.
5255         function evaluate(expr) {
5256                 switch (expr[0]) {
5257                     case "string":
5258                     case "num":
5259                         return expr[1];
5260                     case "name":
5261                     case "atom":
5262                         switch (expr[1]) {
5263                             case "true": return true;
5264                             case "false": return false;
5265                             case "null": return null;
5266                         }
5267                         break;
5268                     case "unary-prefix":
5269                         switch (expr[1]) {
5270                             case "!": return !evaluate(expr[2]);
5271                             case "typeof": return typeof evaluate(expr[2]);
5272                             case "~": return ~evaluate(expr[2]);
5273                             case "-": return -evaluate(expr[2]);
5274                             case "+": return +evaluate(expr[2]);
5275                         }
5276                         break;
5277                     case "binary":
5278                         var left = expr[2], right = expr[3];
5279                         switch (expr[1]) {
5280                             case "&&"         : return evaluate(left) &&         evaluate(right);
5281                             case "||"         : return evaluate(left) ||         evaluate(right);
5282                             case "|"          : return evaluate(left) |          evaluate(right);
5283                             case "&"          : return evaluate(left) &          evaluate(right);
5284                             case "^"          : return evaluate(left) ^          evaluate(right);
5285                             case "+"          : return evaluate(left) +          evaluate(right);
5286                             case "*"          : return evaluate(left) *          evaluate(right);
5287                             case "/"          : return evaluate(left) /          evaluate(right);
5288                             case "%"          : return evaluate(left) %          evaluate(right);
5289                             case "-"          : return evaluate(left) -          evaluate(right);
5290                             case "<<"         : return evaluate(left) <<         evaluate(right);
5291                             case ">>"         : return evaluate(left) >>         evaluate(right);
5292                             case ">>>"        : return evaluate(left) >>>        evaluate(right);
5293                             case "=="         : return evaluate(left) ==         evaluate(right);
5294                             case "==="        : return evaluate(left) ===        evaluate(right);
5295                             case "!="         : return evaluate(left) !=         evaluate(right);
5296                             case "!=="        : return evaluate(left) !==        evaluate(right);
5297                             case "<"          : return evaluate(left) <          evaluate(right);
5298                             case "<="         : return evaluate(left) <=         evaluate(right);
5299                             case ">"          : return evaluate(left) >          evaluate(right);
5300                             case ">="         : return evaluate(left) >=         evaluate(right);
5301                             case "in"         : return evaluate(left) in         evaluate(right);
5302                             case "instanceof" : return evaluate(left) instanceof evaluate(right);
5303                         }
5304                 }
5305                 throw $NOT_CONSTANT;
5306         };
5307
5308         return function(expr, yes, no) {
5309                 try {
5310                         var val = evaluate(expr), ast;
5311                         switch (typeof val) {
5312                             case "string": ast =  [ "string", val ]; break;
5313                             case "number": ast =  [ "num", val ]; break;
5314                             case "boolean": ast =  [ "name", String(val) ]; break;
5315                             default: throw new Error("Can't handle constant of type: " + (typeof val));
5316                         }
5317                         return yes.call(expr, ast, val);
5318                 } catch(ex) {
5319                         if (ex === $NOT_CONSTANT) {
5320                                 if (expr[0] == "binary"
5321                                     && (expr[1] == "===" || expr[1] == "!==")
5322                                     && ((is_string(expr[2]) && is_string(expr[3]))
5323                                         || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {
5324                                         expr[1] = expr[1].substr(0, 2);
5325                                 }
5326                                 else if (no && expr[0] == "binary"
5327                                          && (expr[1] == "||" || expr[1] == "&&")) {
5328                                     // the whole expression is not constant but the lval may be...
5329                                     try {
5330                                         var lval = evaluate(expr[2]);
5331                                         expr = ((expr[1] == "&&" && (lval ? expr[3] : lval))    ||
5332                                                 (expr[1] == "||" && (lval ? lval    : expr[3])) ||
5333                                                 expr);
5334                                     } catch(ex2) {
5335                                         // IGNORE... lval is not constant
5336                                     }
5337                                 }
5338                                 return no ? no.call(expr, expr) : null;
5339                         }
5340                         else throw ex;
5341                 }
5342         };
5343
5344 })();
5345
5346 function warn_unreachable(ast) {
5347         if (!empty(ast))
5348                 warn("Dropping unreachable code: " + gen_code(ast, true));
5349 };
5350
5351 function prepare_ifs(ast) {
5352         var w = ast_walker(), walk = w.walk;
5353         // In this first pass, we rewrite ifs which abort with no else with an
5354         // if-else.  For example:
5355         //
5356         // if (x) {
5357         //     blah();
5358         //     return y;
5359         // }
5360         // foobar();
5361         //
5362         // is rewritten into:
5363         //
5364         // if (x) {
5365         //     blah();
5366         //     return y;
5367         // } else {
5368         //     foobar();
5369         // }
5370         function redo_if(statements) {
5371                 statements = MAP(statements, walk);
5372
5373                 for (var i = 0; i < statements.length; ++i) {
5374                         var fi = statements[i];
5375                         if (fi[0] != "if") continue;
5376
5377                         if (fi[3] && walk(fi[3])) continue;
5378
5379                         var t = walk(fi[2]);
5380                         if (!aborts(t)) continue;
5381
5382                         var conditional = walk(fi[1]);
5383
5384                         var e_body = statements.slice(i + 1);
5385                         var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ];
5386
5387                         var ret = statements.slice(0, i).concat([ [
5388                                 fi[0],          // "if"
5389                                 conditional,    // conditional
5390                                 t,              // then
5391                                 e               // else
5392                         ] ]);
5393
5394                         return redo_if(ret);
5395                 }
5396
5397                 return statements;
5398         };
5399
5400         function redo_if_lambda(name, args, body) {
5401                 body = redo_if(body);
5402                 return [ this[0], name, args, body ];
5403         };
5404
5405         function redo_if_block(statements) {
5406                 return [ this[0], statements != null ? redo_if(statements) : null ];
5407         };
5408
5409         return w.with_walkers({
5410                 "defun": redo_if_lambda,
5411                 "function": redo_if_lambda,
5412                 "block": redo_if_block,
5413                 "splice": redo_if_block,
5414                 "toplevel": function(statements) {
5415                         return [ this[0], redo_if(statements) ];
5416                 },
5417                 "try": function(t, c, f) {
5418                         return [
5419                                 this[0],
5420                                 redo_if(t),
5421                                 c != null ? [ c[0], redo_if(c[1]) ] : null,
5422                                 f != null ? redo_if(f) : null
5423                         ];
5424                 }
5425         }, function() {
5426                 return walk(ast);
5427         });
5428 };
5429
5430 function for_side_effects(ast, handler) {
5431         var w = ast_walker(), walk = w.walk;
5432         var $stop = {}, $restart = {};
5433         function stop() { throw $stop };
5434         function restart() { throw $restart };
5435         function found(){ return handler.call(this, this, w, stop, restart) };
5436         function unary(op) {
5437                 if (op == "++" || op == "--")
5438                         return found.apply(this, arguments);
5439         };
5440         return w.with_walkers({
5441                 "try": found,
5442                 "throw": found,
5443                 "return": found,
5444                 "new": found,
5445                 "switch": found,
5446                 "break": found,
5447                 "continue": found,
5448                 "assign": found,
5449                 "call": found,
5450                 "if": found,
5451                 "for": found,
5452                 "for-in": found,
5453                 "while": found,
5454                 "do": found,
5455                 "return": found,
5456                 "unary-prefix": unary,
5457                 "unary-postfix": unary,
5458                 "defun": found
5459         }, function(){
5460                 while (true) try {
5461                         walk(ast);
5462                         break;
5463                 } catch(ex) {
5464                         if (ex === $stop) break;
5465                         if (ex === $restart) continue;
5466                         throw ex;
5467                 }
5468         });
5469 };
5470
5471 function ast_lift_variables(ast) {
5472         var w = ast_walker(), walk = w.walk, scope;
5473         function do_body(body, env) {
5474                 var _scope = scope;
5475                 scope = env;
5476                 body = MAP(body, walk);
5477                 var hash = {}, names = MAP(env.names, function(type, name){
5478                         if (type != "var") return MAP.skip;
5479                         if (!env.references(name)) return MAP.skip;
5480                         hash[name] = true;
5481                         return [ name ];
5482                 });
5483                 if (names.length > 0) {
5484                         // looking for assignments to any of these variables.
5485                         // we can save considerable space by moving the definitions
5486                         // in the var declaration.
5487                         for_side_effects([ "block", body ], function(ast, walker, stop, restart) {
5488                                 if (ast[0] == "assign"
5489                                     && ast[1] === true
5490                                     && ast[2][0] == "name"
5491                                     && HOP(hash, ast[2][1])) {
5492                                         // insert the definition into the var declaration
5493                                         for (var i = names.length; --i >= 0;) {
5494                                                 if (names[i][0] == ast[2][1]) {
5495                                                         if (names[i][1]) // this name already defined, we must stop
5496                                                                 stop();
5497                                                         names[i][1] = ast[3]; // definition
5498                                                         names.push(names.splice(i, 1)[0]);
5499                                                         break;
5500                                                 }
5501                                         }
5502                                         // remove this assignment from the AST.
5503                                         var p = walker.parent();
5504                                         if (p[0] == "seq") {
5505                                                 var a = p[2];
5506                                                 a.unshift(0, p.length);
5507                                                 p.splice.apply(p, a);
5508                                         }
5509                                         else if (p[0] == "stat") {
5510                                                 p.splice(0, p.length, "block"); // empty statement
5511                                         }
5512                                         else {
5513                                                 stop();
5514                                         }
5515                                         restart();
5516                                 }
5517                                 stop();
5518                         });
5519                         body.unshift([ "var", names ]);
5520                 }
5521                 scope = _scope;
5522                 return body;
5523         };
5524         function _vardefs(defs) {
5525                 var ret = null;
5526                 for (var i = defs.length; --i >= 0;) {
5527                         var d = defs[i];
5528                         if (!d[1]) continue;
5529                         d = [ "assign", true, [ "name", d[0] ], d[1] ];
5530                         if (ret == null) ret = d;
5531                         else ret = [ "seq", d, ret ];
5532                 }
5533                 if (ret == null) {
5534                         if (w.parent()[0] == "for-in")
5535                                 return [ "name", defs[0][0] ];
5536                         return MAP.skip;
5537                 }
5538                 return [ "stat", ret ];
5539         };
5540         function _toplevel(body) {
5541                 return [ this[0], do_body(body, this.scope) ];
5542         };
5543         return w.with_walkers({
5544                 "function": function(name, args, body){
5545                         for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)
5546                                 args.pop();
5547                         if (!body.scope.references(name)) name = null;
5548                         return [ this[0], name, args, do_body(body, body.scope) ];
5549                 },
5550                 "defun": function(name, args, body){
5551                         if (!scope.references(name)) return MAP.skip;
5552                         for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)
5553                                 args.pop();
5554                         return [ this[0], name, args, do_body(body, body.scope) ];
5555                 },
5556                 "var": _vardefs,
5557                 "toplevel": _toplevel
5558         }, function(){
5559                 return walk(ast_add_scope(ast));
5560         });
5561 };
5562
5563 function ast_squeeze(ast, options) {
5564         options = defaults(options, {
5565                 make_seqs   : true,
5566                 dead_code   : true,
5567                 no_warnings : false,
5568                 keep_comps  : true
5569         });
5570
5571         var w = ast_walker(), walk = w.walk;
5572
5573         function negate(c) {
5574                 var not_c = [ "unary-prefix", "!", c ];
5575                 switch (c[0]) {
5576                     case "unary-prefix":
5577                         return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c;
5578                     case "seq":
5579                         c = slice(c);
5580                         c[c.length - 1] = negate(c[c.length - 1]);
5581                         return c;
5582                     case "conditional":
5583                         return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]);
5584                     case "binary":
5585                         var op = c[1], left = c[2], right = c[3];
5586                         if (!options.keep_comps) switch (op) {
5587                             case "<="  : return [ "binary", ">", left, right ];
5588                             case "<"   : return [ "binary", ">=", left, right ];
5589                             case ">="  : return [ "binary", "<", left, right ];
5590                             case ">"   : return [ "binary", "<=", left, right ];
5591                         }
5592                         switch (op) {
5593                             case "=="  : return [ "binary", "!=", left, right ];
5594                             case "!="  : return [ "binary", "==", left, right ];
5595                             case "===" : return [ "binary", "!==", left, right ];
5596                             case "!==" : return [ "binary", "===", left, right ];
5597                             case "&&"  : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]);
5598                             case "||"  : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]);
5599                         }
5600                         break;
5601                 }
5602                 return not_c;
5603         };
5604
5605         function make_conditional(c, t, e) {
5606                 var make_real_conditional = function() {
5607                         if (c[0] == "unary-prefix" && c[1] == "!") {
5608                                 return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
5609                         } else {
5610                                 return e ? best_of(
5611                                         [ "conditional", c, t, e ],
5612                                         [ "conditional", negate(c), e, t ]
5613                                 ) : [ "binary", "&&", c, t ];
5614                         }
5615                 };
5616                 // shortcut the conditional if the expression has a constant value
5617                 return when_constant(c, function(ast, val){
5618                         warn_unreachable(val ? e : t);
5619                         return          (val ? t : e);
5620                 }, make_real_conditional);
5621         };
5622
5623         function rmblock(block) {
5624                 if (block != null && block[0] == "block" && block[1]) {
5625                         if (block[1].length == 1)
5626                                 block = block[1][0];
5627                         else if (block[1].length == 0)
5628                                 block = [ "block" ];
5629                 }
5630                 return block;
5631         };
5632
5633         function _lambda(name, args, body) {
5634                 return [ this[0], name, args, tighten(body, "lambda") ];
5635         };
5636
5637         // this function does a few things:
5638         // 1. discard useless blocks
5639         // 2. join consecutive var declarations
5640         // 3. remove obviously dead code
5641         // 4. transform consecutive statements using the comma operator
5642         // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... }
5643         function tighten(statements, block_type) {
5644                 statements = MAP(statements, walk);
5645
5646                 statements = statements.reduce(function(a, stat){
5647                         if (stat[0] == "block") {
5648                                 if (stat[1]) {
5649                                         a.push.apply(a, stat[1]);
5650                                 }
5651                         } else {
5652                                 a.push(stat);
5653                         }
5654                         return a;
5655                 }, []);
5656
5657                 statements = (function(a, prev){
5658                         statements.forEach(function(cur){
5659                                 if (prev && ((cur[0] == "var" && prev[0] == "var") ||
5660                                              (cur[0] == "const" && prev[0] == "const"))) {
5661                                         prev[1] = prev[1].concat(cur[1]);
5662                                 } else {
5663                                         a.push(cur);
5664                                         prev = cur;
5665                                 }
5666                         });
5667                         return a;
5668                 })([]);
5669
5670                 if (options.dead_code) statements = (function(a, has_quit){
5671                         statements.forEach(function(st){
5672                                 if (has_quit) {
5673                                         if (st[0] == "function" || st[0] == "defun") {
5674                                                 a.push(st);
5675                                         }
5676                                         else if (st[0] == "var" || st[0] == "const") {
5677                                                 if (!options.no_warnings)
5678                                                         warn("Variables declared in unreachable code");
5679                                                 st[1] = MAP(st[1], function(def){
5680                                                         if (def[1] && !options.no_warnings)
5681                                                                 warn_unreachable([ "assign", true, [ "name", def[0] ], def[1] ]);
5682                                                         return [ def[0] ];
5683                                                 });
5684                                                 a.push(st);
5685                                         }
5686                                         else if (!options.no_warnings)
5687                                                 warn_unreachable(st);
5688                                 }
5689                                 else {
5690                                         a.push(st);
5691                                         if (member(st[0], [ "return", "throw", "break", "continue" ]))
5692                                                 has_quit = true;
5693                                 }
5694                         });
5695                         return a;
5696                 })([]);
5697
5698                 if (options.make_seqs) statements = (function(a, prev) {
5699                         statements.forEach(function(cur){
5700                                 if (prev && prev[0] == "stat" && cur[0] == "stat") {
5701                                         prev[1] = [ "seq", prev[1], cur[1] ];
5702                                 } else {
5703                                         a.push(cur);
5704                                         prev = cur;
5705                                 }
5706                         });
5707                         if (a.length >= 2
5708                             && a[a.length-2][0] == "stat"
5709                             && (a[a.length-1][0] == "return" || a[a.length-1][0] == "throw")
5710                             && a[a.length-1][1])
5711                         {
5712                                 a.splice(a.length - 2, 2,
5713                                          [ a[a.length-1][0],
5714                                            [ "seq", a[a.length-2][1], a[a.length-1][1] ]]);
5715                         }
5716                         return a;
5717                 })([]);
5718
5719                 // this increases jQuery by 1K.  Probably not such a good idea after all..
5720                 // part of this is done in prepare_ifs anyway.
5721                 // if (block_type == "lambda") statements = (function(i, a, stat){
5722                 //         while (i < statements.length) {
5723                 //                 stat = statements[i++];
5724                 //                 if (stat[0] == "if" && !stat[3]) {
5725                 //                         if (stat[2][0] == "return" && stat[2][1] == null) {
5726                 //                                 a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ]));
5727                 //                                 break;
5728                 //                         }
5729                 //                         var last = last_stat(stat[2]);
5730                 //                         if (last[0] == "return" && last[1] == null) {
5731                 //                                 a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ]));
5732                 //                                 break;
5733                 //                         }
5734                 //                 }
5735                 //                 a.push(stat);
5736                 //         }
5737                 //         return a;
5738                 // })(0, []);
5739
5740                 return statements;
5741         };
5742
5743         function make_if(c, t, e) {
5744                 return when_constant(c, function(ast, val){
5745                         if (val) {
5746                                 t = walk(t);
5747                                 warn_unreachable(e);
5748                                 return t || [ "block" ];
5749                         } else {
5750                                 e = walk(e);
5751                                 warn_unreachable(t);
5752                                 return e || [ "block" ];
5753                         }
5754                 }, function() {
5755                         return make_real_if(c, t, e);
5756                 });
5757         };
5758
5759         function make_real_if(c, t, e) {
5760                 c = walk(c);
5761                 t = walk(t);
5762                 e = walk(e);
5763
5764                 if (empty(t)) {
5765                         c = negate(c);
5766                         t = e;
5767                         e = null;
5768                 } else if (empty(e)) {
5769                         e = null;
5770                 } else {
5771                         // if we have both else and then, maybe it makes sense to switch them?
5772                         (function(){
5773                                 var a = gen_code(c);
5774                                 var n = negate(c);
5775                                 var b = gen_code(n);
5776                                 if (b.length < a.length) {
5777                                         var tmp = t;
5778                                         t = e;
5779                                         e = tmp;
5780                                         c = n;
5781                                 }
5782                         })();
5783                 }
5784                 if (empty(e) && empty(t))
5785                         return [ "stat", c ];
5786                 var ret = [ "if", c, t, e ];
5787                 if (t[0] == "if" && empty(t[3]) && empty(e)) {
5788                         ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ]));
5789                 }
5790                 else if (t[0] == "stat") {
5791                         if (e) {
5792                                 if (e[0] == "stat") {
5793                                         ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]);
5794                                 }
5795                         }
5796                         else {
5797                                 ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]);
5798                         }
5799                 }
5800                 else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) {
5801                         ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]);
5802                 }
5803                 else if (e && aborts(t)) {
5804                         ret = [ [ "if", c, t ] ];
5805                         if (e[0] == "block") {
5806                                 if (e[1]) ret = ret.concat(e[1]);
5807                         }
5808                         else {
5809                                 ret.push(e);
5810                         }
5811                         ret = walk([ "block", ret ]);
5812                 }
5813                 else if (t && aborts(e)) {
5814                         ret = [ [ "if", negate(c), e ] ];
5815                         if (t[0] == "block") {
5816                                 if (t[1]) ret = ret.concat(t[1]);
5817                         } else {
5818                                 ret.push(t);
5819                         }
5820                         ret = walk([ "block", ret ]);
5821                 }
5822                 return ret;
5823         };
5824
5825         function _do_while(cond, body) {
5826                 return when_constant(cond, function(cond, val){
5827                         if (!val) {
5828                                 warn_unreachable(body);
5829                                 return [ "block" ];
5830                         } else {
5831                                 return [ "for", null, null, null, walk(body) ];
5832                         }
5833                 });
5834         };
5835
5836         return w.with_walkers({
5837                 "sub": function(expr, subscript) {
5838                         if (subscript[0] == "string") {
5839                                 var name = subscript[1];
5840                                 if (is_identifier(name))
5841                                         return [ "dot", walk(expr), name ];
5842                                 else if (/^[1-9][0-9]*$/.test(name) || name === "0")
5843                                         return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ];
5844                         }
5845                 },
5846                 "if": make_if,
5847                 "toplevel": function(body) {
5848                         return [ "toplevel", tighten(body) ];
5849                 },
5850                 "switch": function(expr, body) {
5851                         var last = body.length - 1;
5852                         return [ "switch", walk(expr), MAP(body, function(branch, i){
5853                                 var block = tighten(branch[1]);
5854                                 if (i == last && block.length > 0) {
5855                                         var node = block[block.length - 1];
5856                                         if (node[0] == "break" && !node[1])
5857                                                 block.pop();
5858                                 }
5859                                 return [ branch[0] ? walk(branch[0]) : null, block ];
5860                         }) ];
5861                 },
5862                 "function": _lambda,
5863                 "defun": _lambda,
5864                 "block": function(body) {
5865                         if (body) return rmblock([ "block", tighten(body) ]);
5866                 },
5867                 "binary": function(op, left, right) {
5868                         return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){
5869                                 return best_of(walk(c), this);
5870                         }, function no() {
5871                                 return function(){
5872                                         if(op != "==" && op != "!=") return;
5873                                         var l = walk(left), r = walk(right);
5874                                         if(l && l[0] == "unary-prefix" && l[1] == "!" && l[2][0] == "num")
5875                                                 left = ['num', +!l[2][1]];
5876                                         else if (r && r[0] == "unary-prefix" && r[1] == "!" && r[2][0] == "num")
5877                                                 right = ['num', +!r[2][1]];
5878                                         return ["binary", op, left, right];
5879                                 }() || this;
5880                         });
5881                 },
5882                 "conditional": function(c, t, e) {
5883                         return make_conditional(walk(c), walk(t), walk(e));
5884                 },
5885                 "try": function(t, c, f) {
5886                         return [
5887                                 "try",
5888                                 tighten(t),
5889                                 c != null ? [ c[0], tighten(c[1]) ] : null,
5890                                 f != null ? tighten(f) : null
5891                         ];
5892                 },
5893                 "unary-prefix": function(op, expr) {
5894                         expr = walk(expr);
5895                         var ret = [ "unary-prefix", op, expr ];
5896                         if (op == "!")
5897                                 ret = best_of(ret, negate(expr));
5898                         return when_constant(ret, function(ast, val){
5899                                 return walk(ast); // it's either true or false, so minifies to !0 or !1
5900                         }, function() { return ret });
5901                 },
5902                 "name": function(name) {
5903                         switch (name) {
5904                             case "true": return [ "unary-prefix", "!", [ "num", 0 ]];
5905                             case "false": return [ "unary-prefix", "!", [ "num", 1 ]];
5906                         }
5907                 },
5908                 "while": _do_while,
5909                 "assign": function(op, lvalue, rvalue) {
5910                         lvalue = walk(lvalue);
5911                         rvalue = walk(rvalue);
5912                         var okOps = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
5913                         if (op === true && lvalue[0] === "name" && rvalue[0] === "binary" &&
5914                             ~okOps.indexOf(rvalue[1]) && rvalue[2][0] === "name" &&
5915                             rvalue[2][1] === lvalue[1]) {
5916                                 return [ this[0], rvalue[1], lvalue, rvalue[3] ]
5917                         }
5918                         return [ this[0], op, lvalue, rvalue ];
5919                 }
5920         }, function() {
5921                 for (var i = 0; i < 2; ++i) {
5922                         ast = prepare_ifs(ast);
5923                         ast = walk(ast);
5924                 }
5925                 return ast;
5926         });
5927 };
5928
5929 /* -----[ re-generate code from the AST ]----- */
5930
5931 var DOT_CALL_NO_PARENS = jsp.array_to_hash([
5932         "name",
5933         "array",
5934         "object",
5935         "string",
5936         "dot",
5937         "sub",
5938         "call",
5939         "regexp",
5940         "defun"
5941 ]);
5942
5943 function make_string(str, ascii_only) {
5944         var dq = 0, sq = 0;
5945         str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){
5946                 switch (s) {
5947                     case "\\": return "\\\\";
5948                     case "\b": return "\\b";
5949                     case "\f": return "\\f";
5950                     case "\n": return "\\n";
5951                     case "\r": return "\\r";
5952                     case "\t": return "\\t";
5953                     case "\u2028": return "\\u2028";
5954                     case "\u2029": return "\\u2029";
5955                     case '"': ++dq; return '"';
5956                     case "'": ++sq; return "'";
5957                     case "\0": return "\\0";
5958                 }
5959                 return s;
5960         });
5961         if (ascii_only) str = to_ascii(str);
5962         if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'";
5963         else return '"' + str.replace(/\x22/g, '\\"') + '"';
5964 };
5965
5966 function to_ascii(str) {
5967         return str.replace(/[\u0080-\uffff]/g, function(ch) {
5968                 var code = ch.charCodeAt(0).toString(16);
5969                 while (code.length < 4) code = "0" + code;
5970                 return "\\u" + code;
5971         });
5972 };
5973
5974 var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]);
5975
5976 function gen_code(ast, options) {
5977         options = defaults(options, {
5978                 indent_start : 0,
5979                 indent_level : 4,
5980                 quote_keys   : false,
5981                 space_colon  : false,
5982                 beautify     : false,
5983                 ascii_only   : false,
5984                 inline_script: false
5985         });
5986         var beautify = !!options.beautify;
5987         var indentation = 0,
5988             newline = beautify ? "\n" : "",
5989             space = beautify ? " " : "";
5990
5991         function encode_string(str) {
5992                 var ret = make_string(str, options.ascii_only);
5993                 if (options.inline_script)
5994                         ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
5995                 return ret;
5996         };
5997
5998         function make_name(name) {
5999                 name = name.toString();
6000                 if (options.ascii_only)
6001                         name = to_ascii(name);
6002                 return name;
6003         };
6004
6005         function indent(line) {
6006                 if (line == null)
6007                         line = "";
6008                 if (beautify)
6009                         line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line;
6010                 return line;
6011         };
6012
6013         function with_indent(cont, incr) {
6014                 if (incr == null) incr = 1;
6015                 indentation += incr;
6016                 try { return cont.apply(null, slice(arguments, 1)); }
6017                 finally { indentation -= incr; }
6018         };
6019
6020         function add_spaces(a) {
6021                 if (beautify)
6022                         return a.join(" ");
6023                 var b = [];
6024                 for (var i = 0; i < a.length; ++i) {
6025                         var next = a[i + 1];
6026                         b.push(a[i]);
6027                         if (next &&
6028                             ((/[a-z0-9_\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\x24]/i.test(next.toString())) ||
6029                              (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString())))) {
6030                                 b.push(" ");
6031                         }
6032                 }
6033                 return b.join("");
6034         };
6035
6036         function add_commas(a) {
6037                 return a.join("," + space);
6038         };
6039
6040         function parenthesize(expr) {
6041                 var gen = make(expr);
6042                 for (var i = 1; i < arguments.length; ++i) {
6043                         var el = arguments[i];
6044                         if ((el instanceof Function && el(expr)) || expr[0] == el)
6045                                 return "(" + gen + ")";
6046                 }
6047                 return gen;
6048         };
6049
6050         function best_of(a) {
6051                 if (a.length == 1) {
6052                         return a[0];
6053                 }
6054                 if (a.length == 2) {
6055                         var b = a[1];
6056                         a = a[0];
6057                         return a.length <= b.length ? a : b;
6058                 }
6059                 return best_of([ a[0], best_of(a.slice(1)) ]);
6060         };
6061
6062         function needs_parens(expr) {
6063                 if (expr[0] == "function" || expr[0] == "object") {
6064                         // dot/call on a literal function requires the
6065                         // function literal itself to be parenthesized
6066                         // only if it's the first "thing" in a
6067                         // statement.  This means that the parent is
6068                         // "stat", but it could also be a "seq" and
6069                         // we're the first in this "seq" and the
6070                         // parent is "stat", and so on.  Messy stuff,
6071                         // but it worths the trouble.
6072                         var a = slice(w.stack()), self = a.pop(), p = a.pop();
6073                         while (p) {
6074                                 if (p[0] == "stat") return true;
6075                                 if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) ||
6076                                     ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) {
6077                                         self = p;
6078                                         p = a.pop();
6079                                 } else {
6080                                         return false;
6081                                 }
6082                         }
6083                 }
6084                 return !HOP(DOT_CALL_NO_PARENS, expr[0]);
6085         };
6086
6087         function make_num(num) {
6088                 var str = num.toString(10), a = [ str.replace(/^0\./, ".") ], m;
6089                 if (Math.floor(num) === num) {
6090                         if (num >= 0) {
6091                                 a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
6092                                        "0" + num.toString(8)); // same.
6093                         } else {
6094                                 a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
6095                                        "-0" + (-num).toString(8)); // same.
6096                         }
6097                         if ((m = /^(.*?)(0+)$/.exec(num))) {
6098                                 a.push(m[1] + "e" + m[2].length);
6099                         }
6100                 } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
6101                         a.push(m[2] + "e-" + (m[1].length + m[2].length),
6102                                str.substr(str.indexOf(".")));
6103                 }
6104                 return best_of(a);
6105         };
6106
6107         var w = ast_walker();
6108         var make = w.walk;
6109         return w.with_walkers({
6110                 "string": encode_string,
6111                 "num": make_num,
6112                 "name": make_name,
6113                 "toplevel": function(statements) {
6114                         return make_block_statements(statements)
6115                                 .join(newline + newline);
6116                 },
6117                 "splice": function(statements) {
6118                         var parent = w.parent();
6119                         if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {
6120                                 // we need block brackets in this case
6121                                 return make_block.apply(this, arguments);
6122                         } else {
6123                                 return MAP(make_block_statements(statements, true),
6124                                            function(line, i) {
6125                                                    // the first line is already indented
6126                                                    return i > 0 ? indent(line) : line;
6127                                            }).join(newline);
6128                         }
6129                 },
6130                 "block": make_block,
6131                 "var": function(defs) {
6132                         return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
6133                 },
6134                 "const": function(defs) {
6135                         return "const " + add_commas(MAP(defs, make_1vardef)) + ";";
6136                 },
6137                 "try": function(tr, ca, fi) {
6138                         var out = [ "try", make_block(tr) ];
6139                         if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1]));
6140                         if (fi) out.push("finally", make_block(fi));
6141                         return add_spaces(out);
6142                 },
6143                 "throw": function(expr) {
6144                         return add_spaces([ "throw", make(expr) ]) + ";";
6145                 },
6146                 "new": function(ctor, args) {
6147                         args = args.length > 0 ? "(" + add_commas(MAP(args, function(expr){
6148                                 return parenthesize(expr, "seq");
6149                         })) + ")" : "";
6150                         return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){
6151                                 var w = ast_walker(), has_call = {};
6152                                 try {
6153                                         w.with_walkers({
6154                                                 "call": function() { throw has_call },
6155                                                 "function": function() { return this }
6156                                         }, function(){
6157                                                 w.walk(expr);
6158                                         });
6159                                 } catch(ex) {
6160                                         if (ex === has_call)
6161                                                 return true;
6162                                         throw ex;
6163                                 }
6164                         }) + args ]);
6165                 },
6166                 "switch": function(expr, body) {
6167                         return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]);
6168                 },
6169                 "break": function(label) {
6170                         var out = "break";
6171                         if (label != null)
6172                                 out += " " + make_name(label);
6173                         return out + ";";
6174                 },
6175                 "continue": function(label) {
6176                         var out = "continue";
6177                         if (label != null)
6178                                 out += " " + make_name(label);
6179                         return out + ";";
6180                 },
6181                 "conditional": function(co, th, el) {
6182                         return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?",
6183                                             parenthesize(th, "seq"), ":",
6184                                             parenthesize(el, "seq") ]);
6185                 },
6186                 "assign": function(op, lvalue, rvalue) {
6187                         if (op && op !== true) op += "=";
6188                         else op = "=";
6189                         return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]);
6190                 },
6191                 "dot": function(expr) {
6192                         var out = make(expr), i = 1;
6193                         if (expr[0] == "num") {
6194                                 if (!/\./.test(expr[1]))
6195                                         out += ".";
6196                         } else if (needs_parens(expr))
6197                                 out = "(" + out + ")";
6198                         while (i < arguments.length)
6199                                 out += "." + make_name(arguments[i++]);
6200                         return out;
6201                 },
6202                 "call": function(func, args) {
6203                         var f = make(func);
6204                         if (f.charAt(0) != "(" && needs_parens(func))
6205                                 f = "(" + f + ")";
6206                         return f + "(" + add_commas(MAP(args, function(expr){
6207                                 return parenthesize(expr, "seq");
6208                         })) + ")";
6209                 },
6210                 "function": make_function,
6211                 "defun": make_function,
6212                 "if": function(co, th, el) {
6213                         var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ];
6214                         if (el) {
6215                                 out.push("else", make(el));
6216                         }
6217                         return add_spaces(out);
6218                 },
6219                 "for": function(init, cond, step, block) {
6220                         var out = [ "for" ];
6221                         init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space);
6222                         cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space);
6223                         step = (step != null ? make(step) : "").replace(/;*\s*$/, "");
6224                         var args = init + cond + step;
6225                         if (args == "; ; ") args = ";;";
6226                         out.push("(" + args + ")", make(block));
6227                         return add_spaces(out);
6228                 },
6229                 "for-in": function(vvar, key, hash, block) {
6230                         return add_spaces([ "for", "(" +
6231                                             (vvar ? make(vvar).replace(/;+$/, "") : make(key)),
6232                                             "in",
6233                                             make(hash) + ")", make(block) ]);
6234                 },
6235                 "while": function(condition, block) {
6236                         return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]);
6237                 },
6238                 "do": function(condition, block) {
6239                         return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";";
6240                 },
6241                 "return": function(expr) {
6242                         var out = [ "return" ];
6243                         if (expr != null) out.push(make(expr));
6244                         return add_spaces(out) + ";";
6245                 },
6246                 "binary": function(operator, lvalue, rvalue) {
6247                         var left = make(lvalue), right = make(rvalue);
6248                         // XXX: I'm pretty sure other cases will bite here.
6249                         //      we need to be smarter.
6250                         //      adding parens all the time is the safest bet.
6251                         if (member(lvalue[0], [ "assign", "conditional", "seq" ]) ||
6252                             lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] ||
6253                             lvalue[0] == "function" && needs_parens(this)) {
6254                                 left = "(" + left + ")";
6255                         }
6256                         if (member(rvalue[0], [ "assign", "conditional", "seq" ]) ||
6257                             rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] &&
6258                             !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) {
6259                                 right = "(" + right + ")";
6260                         }
6261                         else if (!beautify && options.inline_script && (operator == "<" || operator == "<<")
6262                                  && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) {
6263                                 right = " " + right;
6264                         }
6265                         return add_spaces([ left, operator, right ]);
6266                 },
6267                 "unary-prefix": function(operator, expr) {
6268                         var val = make(expr);
6269                         if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
6270                                 val = "(" + val + ")";
6271                         return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val;
6272                 },
6273                 "unary-postfix": function(operator, expr) {
6274                         var val = make(expr);
6275                         if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
6276                                 val = "(" + val + ")";
6277                         return val + operator;
6278                 },
6279                 "sub": function(expr, subscript) {
6280                         var hash = make(expr);
6281                         if (needs_parens(expr))
6282                                 hash = "(" + hash + ")";
6283                         return hash + "[" + make(subscript) + "]";
6284                 },
6285                 "object": function(props) {
6286                         var obj_needs_parens = needs_parens(this);
6287                         if (props.length == 0)
6288                                 return obj_needs_parens ? "({})" : "{}";
6289                         var out = "{" + newline + with_indent(function(){
6290                                 return MAP(props, function(p){
6291                                         if (p.length == 3) {
6292                                                 // getter/setter.  The name is in p[0], the arg.list in p[1][2], the
6293                                                 // body in p[1][3] and type ("get" / "set") in p[2].
6294                                                 return indent(make_function(p[0], p[1][2], p[1][3], p[2]));
6295                                         }
6296                                         var key = p[0], val = parenthesize(p[1], "seq");
6297                                         if (options.quote_keys) {
6298                                                 key = encode_string(key);
6299                                         } else if ((typeof key == "number" || !beautify && +key + "" == key)
6300                                                    && parseFloat(key) >= 0) {
6301                                                 key = make_num(+key);
6302                                         } else if (!is_identifier(key)) {
6303                                                 key = encode_string(key);
6304                                         }
6305                                         return indent(add_spaces(beautify && options.space_colon
6306                                                                  ? [ key, ":", val ]
6307                                                                  : [ key + ":", val ]));
6308                                 }).join("," + newline);
6309                         }) + newline + indent("}");
6310                         return obj_needs_parens ? "(" + out + ")" : out;
6311                 },
6312                 "regexp": function(rx, mods) {
6313                         return "/" + rx + "/" + mods;
6314                 },
6315                 "array": function(elements) {
6316                         if (elements.length == 0) return "[]";
6317                         return add_spaces([ "[", add_commas(MAP(elements, function(el, i){
6318                                 if (!beautify && el[0] == "atom" && el[1] == "undefined") return i === elements.length - 1 ? "," : "";
6319                                 return parenthesize(el, "seq");
6320                         })), "]" ]);
6321                 },
6322                 "stat": function(stmt) {
6323                         return make(stmt).replace(/;*\s*$/, ";");
6324                 },
6325                 "seq": function() {
6326                         return add_commas(MAP(slice(arguments), make));
6327                 },
6328                 "label": function(name, block) {
6329                         return add_spaces([ make_name(name), ":", make(block) ]);
6330                 },
6331                 "with": function(expr, block) {
6332                         return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]);
6333                 },
6334                 "atom": function(name) {
6335                         return make_name(name);
6336                 }
6337         }, function(){ return make(ast) });
6338
6339         // The squeezer replaces "block"-s that contain only a single
6340         // statement with the statement itself; technically, the AST
6341         // is correct, but this can create problems when we output an
6342         // IF having an ELSE clause where the THEN clause ends in an
6343         // IF *without* an ELSE block (then the outer ELSE would refer
6344         // to the inner IF).  This function checks for this case and
6345         // adds the block brackets if needed.
6346         function make_then(th) {
6347                 if (th == null) return ";";
6348                 if (th[0] == "do") {
6349                         // https://github.com/mishoo/UglifyJS/issues/#issue/57
6350                         // IE croaks with "syntax error" on code like this:
6351                         //     if (foo) do ... while(cond); else ...
6352                         // we need block brackets around do/while
6353                         return make_block([ th ]);
6354                 }
6355                 var b = th;
6356                 while (true) {
6357                         var type = b[0];
6358                         if (type == "if") {
6359                                 if (!b[3])
6360                                         // no else, we must add the block
6361                                         return make([ "block", [ th ]]);
6362                                 b = b[3];
6363                         }
6364                         else if (type == "while" || type == "do") b = b[2];
6365                         else if (type == "for" || type == "for-in") b = b[4];
6366                         else break;
6367                 }
6368                 return make(th);
6369         };
6370
6371         function make_function(name, args, body, keyword) {
6372                 var out = keyword || "function";
6373                 if (name) {
6374                         out += " " + make_name(name);
6375                 }
6376                 out += "(" + add_commas(MAP(args, make_name)) + ")";
6377                 out = add_spaces([ out, make_block(body) ]);
6378                 return needs_parens(this) ? "(" + out + ")" : out;
6379         };
6380
6381         function must_has_semicolon(node) {
6382                 switch (node[0]) {
6383                     case "with":
6384                     case "while":
6385                         return empty(node[2]); // `with' or `while' with empty body?
6386                     case "for":
6387                     case "for-in":
6388                         return empty(node[4]); // `for' with empty body?
6389                     case "if":
6390                         if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else'
6391                         if (node[3]) {
6392                                 if (empty(node[3])) return true; // `else' present but empty
6393                                 return must_has_semicolon(node[3]); // dive into the `else' branch
6394                         }
6395                         return must_has_semicolon(node[2]); // dive into the `then' branch
6396                 }
6397         };
6398
6399         function make_block_statements(statements, noindent) {
6400                 for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {
6401                         var stat = statements[i];
6402                         var code = make(stat);
6403                         if (code != ";") {
6404                                 if (!beautify && i == last && !must_has_semicolon(stat)) {
6405                                         code = code.replace(/;+\s*$/, "");
6406                                 }
6407                                 a.push(code);
6408                         }
6409                 }
6410                 return noindent ? a : MAP(a, indent);
6411         };
6412
6413         function make_switch_block(body) {
6414                 var n = body.length;
6415                 if (n == 0) return "{}";
6416                 return "{" + newline + MAP(body, function(branch, i){
6417                         var has_body = branch[1].length > 0, code = with_indent(function(){
6418                                 return indent(branch[0]
6419                                               ? add_spaces([ "case", make(branch[0]) + ":" ])
6420                                               : "default:");
6421                         }, 0.5) + (has_body ? newline + with_indent(function(){
6422                                 return make_block_statements(branch[1]).join(newline);
6423                         }) : "");
6424                         if (!beautify && has_body && i < n - 1)
6425                                 code += ";";
6426                         return code;
6427                 }).join(newline) + newline + indent("}");
6428         };
6429
6430         function make_block(statements) {
6431                 if (!statements) return ";";
6432                 if (statements.length == 0) return "{}";
6433                 return "{" + newline + with_indent(function(){
6434                         return make_block_statements(statements).join(newline);
6435                 }) + newline + indent("}");
6436         };
6437
6438         function make_1vardef(def) {
6439                 var name = def[0], val = def[1];
6440                 if (val != null)
6441                         name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]);
6442                 return name;
6443         };
6444
6445 };
6446
6447 function split_lines(code, max_line_length) {
6448         var splits = [ 0 ];
6449         jsp.parse(function(){
6450                 var next_token = jsp.tokenizer(code);
6451                 var last_split = 0;
6452                 var prev_token;
6453                 function current_length(tok) {
6454                         return tok.pos - last_split;
6455                 };
6456                 function split_here(tok) {
6457                         last_split = tok.pos;
6458                         splits.push(last_split);
6459                 };
6460                 function custom(){
6461                         var tok = next_token.apply(this, arguments);
6462                         out: {
6463                                 if (prev_token) {
6464                                         if (prev_token.type == "keyword") break out;
6465                                 }
6466                                 if (current_length(tok) > max_line_length) {
6467                                         switch (tok.type) {
6468                                             case "keyword":
6469                                             case "atom":
6470                                             case "name":
6471                                             case "punc":
6472                                                 split_here(tok);
6473                                                 break out;
6474                                         }
6475                                 }
6476                         }
6477                         prev_token = tok;
6478                         return tok;
6479                 };
6480                 custom.context = function() {
6481                         return next_token.context.apply(this, arguments);
6482                 };
6483                 return custom;
6484         }());
6485         return splits.map(function(pos, i){
6486                 return code.substring(pos, splits[i + 1] || code.length);
6487         }).join("\n");
6488 };
6489
6490 /* -----[ Utilities ]----- */
6491
6492 function repeat_string(str, i) {
6493         if (i <= 0) return "";
6494         if (i == 1) return str;
6495         var d = repeat_string(str, i >> 1);
6496         d += d;
6497         if (i & 1) d += str;
6498         return d;
6499 };
6500
6501 function defaults(args, defs) {
6502         var ret = {};
6503         if (args === true)
6504                 args = {};
6505         for (var i in defs) if (HOP(defs, i)) {
6506                 ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
6507         }
6508         return ret;
6509 };
6510
6511 function is_identifier(name) {
6512         return /^[a-z_$][a-z0-9_$]*$/i.test(name)
6513                 && name != "this"
6514                 && !HOP(jsp.KEYWORDS_ATOM, name)
6515                 && !HOP(jsp.RESERVED_WORDS, name)
6516                 && !HOP(jsp.KEYWORDS, name);
6517 };
6518
6519 function HOP(obj, prop) {
6520         return Object.prototype.hasOwnProperty.call(obj, prop);
6521 };
6522
6523 // some utilities
6524
6525 var MAP;
6526
6527 (function(){
6528         MAP = function(a, f, o) {
6529                 var ret = [], top = [], i;
6530                 function doit() {
6531                         var val = f.call(o, a[i], i);
6532                         if (val instanceof AtTop) {
6533                                 val = val.v;
6534                                 if (val instanceof Splice) {
6535                                         top.push.apply(top, val.v);
6536                                 } else {
6537                                         top.push(val);
6538                                 }
6539                         }
6540                         else if (val != skip) {
6541                                 if (val instanceof Splice) {
6542                                         ret.push.apply(ret, val.v);
6543                                 } else {
6544                                         ret.push(val);
6545                                 }
6546                         }
6547                 };
6548                 if (a instanceof Array) for (i = 0; i < a.length; ++i) doit();
6549                 else for (i in a) if (HOP(a, i)) doit();
6550                 return top.concat(ret);
6551         };
6552         MAP.at_top = function(val) { return new AtTop(val) };
6553         MAP.splice = function(val) { return new Splice(val) };
6554         var skip = MAP.skip = {};
6555         function AtTop(val) { this.v = val };
6556         function Splice(val) { this.v = val };
6557 })();
6558
6559 /* -----[ Exports ]----- */
6560
6561 exports.ast_walker = ast_walker;
6562 exports.ast_mangle = ast_mangle;
6563 exports.ast_squeeze = ast_squeeze;
6564 exports.ast_lift_variables = ast_lift_variables;
6565 exports.gen_code = gen_code;
6566 exports.ast_add_scope = ast_add_scope;
6567 exports.set_logger = function(logger) { warn = logger };
6568 exports.make_string = make_string;
6569 exports.split_lines = split_lines;
6570 exports.MAP = MAP;
6571
6572 // keep this last!
6573 exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more;
6574
6575 });define('uglifyjs/index', ["require", "exports", "module", "./parse-js", "./process"], function(require, exports, module) {
6576
6577 //convienence function(src, [options]);
6578 function uglify(orig_code, options){
6579   options || (options = {});
6580   var jsp = uglify.parser;
6581   var pro = uglify.uglify;
6582
6583   var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST
6584   ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names
6585   ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations
6586   var final_code = pro.gen_code(ast, options.gen_options); // compressed code here
6587   return final_code;
6588 };
6589
6590 uglify.parser = require("./parse-js");
6591 uglify.uglify = require("./process");
6592
6593 module.exports = uglify
6594
6595 });/**
6596  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
6597  * Available via the MIT or new BSD license.
6598  * see: http://github.com/jrburke/requirejs for details
6599  */
6600
6601 /*jslint plusplus: false, strict: false */
6602 /*global define: false */
6603
6604 define('parse', ['./uglifyjs/index'], function (uglify) {
6605     var parser = uglify.parser,
6606         processor = uglify.uglify,
6607         ostring = Object.prototype.toString,
6608         isArray;
6609
6610     if (Array.isArray) {
6611         isArray = Array.isArray;
6612     } else {
6613         isArray = function (it) {
6614             return ostring.call(it) === "[object Array]";
6615         };
6616     }
6617
6618     /**
6619      * Determines if the AST node is an array literal
6620      */
6621     function isArrayLiteral(node) {
6622         return node[0] === 'array';
6623     }
6624
6625     /**
6626      * Determines if the AST node is an object literal
6627      */
6628     function isObjectLiteral(node) {
6629         return node[0] === 'object';
6630     }
6631
6632     /**
6633      * Converts a regular JS array of strings to an AST node that
6634      * represents that array.
6635      * @param {Array} ary
6636      * @param {Node} an AST node that represents an array of strings.
6637      */
6638     function toAstArray(ary) {
6639         var output = [
6640             'array',
6641             []
6642         ],
6643         i, item;
6644
6645         for (i = 0; (item = ary[i]); i++) {
6646             output[1].push([
6647                 'string',
6648                 item
6649             ]);
6650         }
6651
6652         return output;
6653     }
6654
6655     /**
6656      * Validates a node as being an object literal (like for i18n bundles)
6657      * or an array literal with just string members. If an array literal,
6658      * only return array members that are full strings. So the caller of
6659      * this function should use the return value as the new value for the
6660      * node.
6661      *
6662      * This function does not need to worry about comments, they are not
6663      * present in this AST.
6664      *
6665      * @param {Node} node an AST node.
6666      *
6667      * @returns {Node} an AST node to use for the valid dependencies.
6668      * If null is returned, then it means the input node was not a valid
6669      * dependency.
6670      */
6671     function validateDeps(node) {
6672         var newDeps = ['array', []],
6673             arrayArgs, i, dep;
6674
6675         if (!node) {
6676             return null;
6677         }
6678
6679         if (isObjectLiteral(node) || node[0] === 'function') {
6680             return node;
6681         }
6682
6683         //Dependencies can be an object literal or an array.
6684         if (!isArrayLiteral(node)) {
6685             return null;
6686         }
6687
6688         arrayArgs = node[1];
6689
6690         for (i = 0; i < arrayArgs.length; i++) {
6691             dep = arrayArgs[i];
6692             if (dep[0] === 'string') {
6693                 newDeps[1].push(dep);
6694             }
6695         }
6696         return newDeps[1].length ? newDeps : null;
6697     }
6698
6699     /**
6700      * Gets dependencies from a node, but only if it is an array literal,
6701      * and only if the dependency is a string literal.
6702      *
6703      * This function does not need to worry about comments, they are not
6704      * present in this AST.
6705      *
6706      * @param {Node} node an AST node.
6707      *
6708      * @returns {Array} of valid dependencies.
6709      * If null is returned, then it means the input node was not a valid
6710      * array literal, or did not have any string literals..
6711      */
6712     function getValidDeps(node) {
6713         var newDeps = [],
6714             arrayArgs, i, dep;
6715
6716         if (!node) {
6717             return null;
6718         }
6719
6720         if (isObjectLiteral(node) || node[0] === 'function') {
6721             return null;
6722         }
6723
6724         //Dependencies can be an object literal or an array.
6725         if (!isArrayLiteral(node)) {
6726             return null;
6727         }
6728
6729         arrayArgs = node[1];
6730
6731         for (i = 0; i < arrayArgs.length; i++) {
6732             dep = arrayArgs[i];
6733             if (dep[0] === 'string') {
6734                 newDeps.push(dep[1]);
6735             }
6736         }
6737         return newDeps.length ? newDeps : null;
6738     }
6739
6740     /**
6741      * Main parse function. Returns a string of any valid require or define/require.def
6742      * calls as part of one JavaScript source string.
6743      * @param {String} moduleName the module name that represents this file.
6744      * It is used to create a default define if there is not one already for the file.
6745      * This allows properly tracing dependencies for builds. Otherwise, if
6746      * the file just has a require() call, the file dependencies will not be
6747      * properly reflected: the file will come before its dependencies.
6748      * @param {String} moduleName
6749      * @param {String} fileName
6750      * @param {String} fileContents
6751      * @param {Object} options optional options. insertNeedsDefine: true will
6752      * add calls to require.needsDefine() if appropriate.
6753      * @returns {String} JS source string or null, if no require or define/require.def
6754      * calls are found.
6755      */
6756     function parse(moduleName, fileName, fileContents, options) {
6757         options = options || {};
6758
6759         //Set up source input
6760         var moduleDeps = [],
6761             result = '',
6762             moduleList = [],
6763             needsDefine = true,
6764             astRoot = parser.parse(fileContents),
6765             i, moduleCall, depString;
6766
6767         parse.recurse(astRoot, function (callName, config, name, deps) {
6768             //If name is an array, it means it is an anonymous module,
6769             //so adjust args appropriately. An anonymous module could
6770             //have a FUNCTION as the name type, but just ignore those
6771             //since we just want to find dependencies.
6772             if (name && isArrayLiteral(name)) {
6773                 deps = name;
6774                 name = null;
6775             }
6776
6777             if (!(deps = getValidDeps(deps))) {
6778                 deps = [];
6779             }
6780
6781             //Get the name as a string literal, if it is available.
6782             if (name && name[0] === 'string') {
6783                 name = name[1];
6784             } else {
6785                 name = null;
6786             }
6787
6788             if (callName === 'define' && (!name || name === moduleName)) {
6789                 needsDefine = false;
6790             }
6791
6792             if (!name) {
6793                 //If there is no module name, the dependencies are for
6794                 //this file/default module name.
6795                 moduleDeps = moduleDeps.concat(deps);
6796             } else {
6797                 moduleList.push({
6798                     name: name,
6799                     deps: deps
6800                 });
6801             }
6802
6803             //If define was found, no need to dive deeper, unless
6804             //the config explicitly wants to dig deeper.
6805             return !options.findNestedDependencies;
6806         }, options);
6807
6808         if (options.insertNeedsDefine && needsDefine) {
6809             result += 'require.needsDefine("' + moduleName + '");';
6810         }
6811
6812         if (moduleDeps.length || moduleList.length) {
6813             for (i = 0; (moduleCall = moduleList[i]); i++) {
6814                 if (result) {
6815                     result += '\n';
6816                 }
6817
6818                 //If this is the main module for this file, combine any
6819                 //"anonymous" dependencies (could come from a nested require
6820                 //call) with this module.
6821                 if (moduleCall.name === moduleName) {
6822                     moduleCall.deps = moduleCall.deps.concat(moduleDeps);
6823                     moduleDeps = [];
6824                 }
6825
6826                 depString = moduleCall.deps.length ? '["' + moduleCall.deps.join('","') + '"]' : '[]';
6827                 result += 'define("' + moduleCall.name + '",' + depString + ');';
6828             }
6829             if (moduleDeps.length) {
6830                 if (result) {
6831                     result += '\n';
6832                 }
6833                 depString = moduleDeps.length ? '["' + moduleDeps.join('","') + '"]' : '[]';
6834                 result += 'define("' + moduleName + '",' + depString + ');';
6835             }
6836         }
6837
6838         return result ? result : null;
6839     }
6840
6841     //Add some private methods to object for use in derived objects.
6842     parse.isArray = isArray;
6843     parse.isObjectLiteral = isObjectLiteral;
6844     parse.isArrayLiteral = isArrayLiteral;
6845
6846     /**
6847      * Handles parsing a file recursively for require calls.
6848      * @param {Array} parentNode the AST node to start with.
6849      * @param {Function} onMatch function to call on a parse match.
6850      * @param {Object} [options] This is normally the build config options if
6851      * it is passed.
6852      * @param {Function} [recurseCallback] function to call on each valid
6853      * node, defaults to parse.parseNode.
6854      */
6855     parse.recurse = function (parentNode, onMatch, options, recurseCallback) {
6856         var hasHas = options && options.has,
6857             i, node;
6858
6859         recurseCallback = recurseCallback || this.parseNode;
6860
6861         if (isArray(parentNode)) {
6862             for (i = 0; i < parentNode.length; i++) {
6863                 node = parentNode[i];
6864                 if (isArray(node)) {
6865                     //If has config is in play, if calls have been converted
6866                     //by this point to be true/false values. So, if
6867                     //options has a 'has' value, skip if branches that have
6868                     //literal false values.
6869
6870                     //uglify returns if constructs in an array:
6871                     //[0]: 'if'
6872                     //[1]: the condition, ['name', true | false] for the has replaced case.
6873                     //[2]: the block to process if true
6874                     //[3]: the block to process if false
6875                     //For if/else if/else, the else if is in the [3],
6876                     //so only ever have to deal with this structure.
6877                     if (hasHas && node[0] === 'if' && node[1] && node[1][0] === 'name' &&
6878                         (node[1][1] === 'true' || node[1][1] === 'false')) {
6879                         if (node[1][1] === 'true') {
6880                             this.recurse([node[2]], onMatch, options, recurseCallback);
6881                         } else {
6882                             this.recurse([node[3]], onMatch, options, recurseCallback);
6883                         }
6884                     } else {
6885                         if (recurseCallback(node, onMatch)) {
6886                             //The onMatch indicated parsing should
6887                             //stop for children of this node.
6888                             continue;
6889                         }
6890                         this.recurse(node, onMatch, options, recurseCallback);
6891                     }
6892                 }
6893             }
6894         }
6895     };
6896
6897     /**
6898      * Determines if the file defines require().
6899      * @param {String} fileName
6900      * @param {String} fileContents
6901      * @returns {Boolean}
6902      */
6903     parse.definesRequire = function (fileName, fileContents) {
6904         var astRoot = parser.parse(fileContents);
6905         return this.nodeHasRequire(astRoot);
6906     };
6907
6908     /**
6909      * Finds require("") calls inside a CommonJS anonymous module wrapped in a
6910      * define(function(require, exports, module){}) wrapper. These dependencies
6911      * will be added to a modified define() call that lists the dependencies
6912      * on the outside of the function.
6913      * @param {String} fileName
6914      * @param {String} fileContents
6915      * @returns {Array} an array of module names that are dependencies. Always
6916      * returns an array, but could be of length zero.
6917      */
6918     parse.getAnonDeps = function (fileName, fileContents) {
6919         var astRoot = parser.parse(fileContents),
6920             defFunc = this.findAnonDefineFactory(astRoot);
6921
6922         return parse.getAnonDepsFromNode(defFunc);
6923     };
6924
6925     /**
6926      * Finds require("") calls inside a CommonJS anonymous module wrapped
6927      * in a define function, given an AST node for the definition function.
6928      * @param {Node} node the AST node for the definition function.
6929      * @returns {Array} and array of dependency names. Can be of zero length.
6930      */
6931     parse.getAnonDepsFromNode = function (node) {
6932         var deps = [],
6933             funcArgLength;
6934
6935         if (node) {
6936             this.findRequireDepNames(node, deps);
6937
6938             //If no deps, still add the standard CommonJS require, exports, module,
6939             //in that order, to the deps, but only if specified as function args.
6940             //In particular, if exports is used, it is favored over the return
6941             //value of the function, so only add it if asked.
6942             funcArgLength = node[2] && node[2].length;
6943             if (funcArgLength) {
6944                 deps = (funcArgLength > 1 ? ["require", "exports", "module"] :
6945                         ["require"]).concat(deps);
6946             }
6947         }
6948         return deps;
6949     };
6950
6951     /**
6952      * Finds the function in define(function (require, exports, module){});
6953      * @param {Array} node
6954      * @returns {Boolean}
6955      */
6956     parse.findAnonDefineFactory = function (node) {
6957         var callback, i, n, call, args;
6958
6959         if (isArray(node)) {
6960             if (node[0] === 'call') {
6961                 call = node[1];
6962                 args = node[2];
6963                 if ((call[0] === 'name' && call[1] === 'define') ||
6964                            (call[0] === 'dot' && call[1][1] === 'require' && call[2] === 'def')) {
6965
6966                     //There should only be one argument and it should be a function,
6967                     //or a named module with function as second arg
6968                     if (args.length === 1 && args[0][0] === 'function') {
6969                         return args[0];
6970                     } else if (args.length === 2 && args[0][0] === 'string' &&
6971                                args[1][0] === 'function') {
6972                         return args[1];
6973                     }
6974                 }
6975             }
6976
6977             //Check child nodes
6978             for (i = 0; i < node.length; i++) {
6979                 n = node[i];
6980                 if ((callback = this.findAnonDefineFactory(n))) {
6981                     return callback;
6982                 }
6983             }
6984         }
6985
6986         return null;
6987     };
6988
6989     /**
6990      * Finds any config that is passed to requirejs.
6991      * @param {String} fileName
6992      * @param {String} fileContents
6993      *
6994      * @returns {Object} a config object. Will be null if no config.
6995      * Can throw an error if the config in the file cannot be evaluated in
6996      * a build context to valid JavaScript.
6997      */
6998     parse.findConfig = function (fileName, fileContents) {
6999         /*jslint evil: true */
7000         //This is a litle bit inefficient, it ends up with two uglifyjs parser
7001         //calls. Can revisit later, but trying to build out larger functional
7002         //pieces first.
7003         var foundConfig = null,
7004             astRoot = parser.parse(fileContents);
7005
7006         parse.recurse(astRoot, function (configNode) {
7007             var jsConfig;
7008
7009             if (!foundConfig && configNode) {
7010                 jsConfig = parse.nodeToString(configNode);
7011                 foundConfig = eval('(' + jsConfig + ')');
7012                 return foundConfig;
7013             }
7014             return undefined;
7015         }, null, parse.parseConfigNode);
7016
7017         return foundConfig;
7018     };
7019
7020     /**
7021      * Finds all dependencies specified in dependency arrays and inside
7022      * simplified commonjs wrappers.
7023      * @param {String} fileName
7024      * @param {String} fileContents
7025      *
7026      * @returns {Array} an array of dependency strings. The dependencies
7027      * have not been normalized, they may be relative IDs.
7028      */
7029     parse.findDependencies = function (fileName, fileContents, options) {
7030         //This is a litle bit inefficient, it ends up with two uglifyjs parser
7031         //calls. Can revisit later, but trying to build out larger functional
7032         //pieces first.
7033         var dependencies = [],
7034             astRoot = parser.parse(fileContents);
7035
7036         parse.recurse(astRoot, function (callName, config, name, deps) {
7037             //Normalize the input args.
7038             if (name && isArrayLiteral(name)) {
7039                 deps = name;
7040                 name = null;
7041             }
7042
7043             if ((deps = getValidDeps(deps))) {
7044                 dependencies = dependencies.concat(deps);
7045             }
7046         }, options);
7047
7048         return dependencies;
7049     };
7050
7051     /**
7052      * Finds only CJS dependencies, ones that are the form require('stringLiteral')
7053      */
7054     parse.findCjsDependencies = function (fileName, fileContents, options) {
7055         //This is a litle bit inefficient, it ends up with two uglifyjs parser
7056         //calls. Can revisit later, but trying to build out larger functional
7057         //pieces first.
7058         var dependencies = [],
7059             astRoot = parser.parse(fileContents);
7060
7061         parse.recurse(astRoot, function (dep) {
7062             dependencies.push(dep);
7063         }, options, function (node, onMatch) {
7064
7065             var call, args;
7066
7067             if (!isArray(node)) {
7068                 return false;
7069             }
7070
7071             if (node[0] === 'call') {
7072                 call = node[1];
7073                 args = node[2];
7074
7075                 if (call) {
7076                     //A require('') use.
7077                     if (call[0] === 'name' && call[1] === 'require' &&
7078                         args[0][0] === 'string') {
7079                         return onMatch(args[0][1]);
7080                     }
7081                 }
7082             }
7083
7084             return false;
7085
7086         });
7087
7088         return dependencies;
7089     };
7090
7091     /**
7092      * Determines if define(), require({}|[]) or requirejs was called in the
7093      * file. Also finds out if define() is declared and if define.amd is called.
7094      */
7095     parse.usesAmdOrRequireJs = function (fileName, fileContents, options) {
7096         var astRoot = parser.parse(fileContents),
7097             uses;
7098
7099         parse.recurse(astRoot, function (prop) {
7100             if (!uses) {
7101                 uses = {};
7102             }
7103             uses[prop] = true;
7104         }, options, parse.findAmdOrRequireJsNode);
7105
7106         return uses;
7107     };
7108
7109     /**
7110      * Determines if require(''), exports.x =, module.exports =,
7111      * __dirname, __filename are used. So, not strictly traditional CommonJS,
7112      * also checks for Node variants.
7113      */
7114     parse.usesCommonJs = function (fileName, fileContents, options) {
7115         var uses = null,
7116             assignsExports = false,
7117             astRoot = parser.parse(fileContents);
7118
7119         parse.recurse(astRoot, function (prop) {
7120             if (prop === 'varExports') {
7121                 assignsExports = true;
7122             } else if (prop !== 'exports' || !assignsExports) {
7123                 if (!uses) {
7124                     uses = {};
7125                 }
7126                 uses[prop] = true;
7127             }
7128         }, options, function (node, onMatch) {
7129
7130             var call, args;
7131
7132             if (!isArray(node)) {
7133                 return false;
7134             }
7135
7136             if (node[0] === 'name' && (node[1] === '__dirname' || node[1] === '__filename')) {
7137                 return onMatch(node[1].substring(2));
7138             } else if (node[0] === 'var' && node[1] && node[1][0] && node[1][0][0] === 'exports') {
7139                 //Hmm, a variable assignment for exports, so does not use cjs exports.
7140                 return onMatch('varExports');
7141             } else if (node[0] === 'assign' && node[2] && node[2][0] === 'dot') {
7142                 args = node[2][1];
7143
7144                 if (args) {
7145                     //An exports or module.exports assignment.
7146                     if (args[0] === 'name' && args[1] === 'module' &&
7147                         node[2][2] === 'exports') {
7148                         return onMatch('moduleExports');
7149                     } else if (args[0] === 'name' && args[1] === 'exports') {
7150                         return onMatch('exports');
7151                     }
7152                 }
7153             } else if (node[0] === 'call') {
7154                 call = node[1];
7155                 args = node[2];
7156
7157                 if (call) {
7158                     //A require('') use.
7159                     if (call[0] === 'name' && call[1] === 'require' &&
7160                         args[0][0] === 'string') {
7161                         return onMatch('require');
7162                     }
7163                 }
7164             }
7165
7166             return false;
7167
7168         });
7169
7170         return uses;
7171     };
7172
7173
7174     parse.findRequireDepNames = function (node, deps) {
7175         var moduleName, i, n, call, args;
7176
7177         if (isArray(node)) {
7178             if (node[0] === 'call') {
7179                 call = node[1];
7180                 args = node[2];
7181
7182                 if (call && call[0] === 'name' && call[1] === 'require') {
7183                     moduleName = args[0];
7184                     if (moduleName[0] === 'string') {
7185                         deps.push(moduleName[1]);
7186                     }
7187                 }
7188
7189
7190             }
7191
7192             //Check child nodes
7193             for (i = 0; i < node.length; i++) {
7194                 n = node[i];
7195                 this.findRequireDepNames(n, deps);
7196             }
7197         }
7198     };
7199
7200     /**
7201      * Determines if a given node contains a require() definition.
7202      * @param {Array} node
7203      * @returns {Boolean}
7204      */
7205     parse.nodeHasRequire = function (node) {
7206         if (this.isDefineNode(node)) {
7207             return true;
7208         }
7209
7210         if (isArray(node)) {
7211             for (var i = 0, n; i < node.length; i++) {
7212                 n = node[i];
7213                 if (this.nodeHasRequire(n)) {
7214                     return true;
7215                 }
7216             }
7217         }
7218
7219         return false;
7220     };
7221
7222     /**
7223      * Is the given node the actual definition of define(). Actually uses
7224      * the definition of define.amd to find require.
7225      * @param {Array} node
7226      * @returns {Boolean}
7227      */
7228     parse.isDefineNode = function (node) {
7229         //Actually look for the define.amd = assignment, since
7230         //that is more indicative of RequireJS vs a plain require definition.
7231         var assign;
7232         if (!node) {
7233             return null;
7234         }
7235
7236         if (node[0] === 'assign' && node[1] === true) {
7237             assign = node[2];
7238             if (assign[0] === 'dot' && assign[1][0] === 'name' &&
7239                 assign[1][1] === 'define' && assign[2] === 'amd') {
7240                 return true;
7241             }
7242         }
7243         return false;
7244     };
7245
7246     /**
7247      * Determines if a specific node is a valid require or define/require.def call.
7248      * @param {Array} node
7249      * @param {Function} onMatch a function to call when a match is found.
7250      * It is passed the match name, and the config, name, deps possible args.
7251      * The config, name and deps args are not normalized.
7252      *
7253      * @returns {String} a JS source string with the valid require/define call.
7254      * Otherwise null.
7255      */
7256     parse.parseNode = function (node, onMatch) {
7257         var call, name, config, deps, args, cjsDeps;
7258
7259         if (!isArray(node)) {
7260             return false;
7261         }
7262
7263         if (node[0] === 'call') {
7264             call = node[1];
7265             args = node[2];
7266
7267             if (call) {
7268                 if (call[0] === 'name' &&
7269                    (call[1] === 'require' || call[1] === 'requirejs')) {
7270
7271                     //It is a plain require() call.
7272                     config = args[0];
7273                     deps = args[1];
7274                     if (isArrayLiteral(config)) {
7275                         deps = config;
7276                         config = null;
7277                     }
7278
7279                     if (!(deps = validateDeps(deps))) {
7280                         return null;
7281                     }
7282
7283                     return onMatch("require", null, null, deps);
7284
7285                 } else if (call[0] === 'name' && call[1] === 'define') {
7286
7287                     //A define call
7288                     name = args[0];
7289                     deps = args[1];
7290                     //Only allow define calls that match what is expected
7291                     //in an AMD call:
7292                     //* first arg should be string, array, function or object
7293                     //* second arg optional, or array, function or object.
7294                     //This helps weed out calls to a non-AMD define, but it is
7295                     //not completely robust. Someone could create a define
7296                     //function that still matches this shape, but this is the
7297                     //best that is possible, and at least allows UglifyJS,
7298                     //which does create its own internal define in one file,
7299                     //to be inlined.
7300                     if (((name[0] === 'string' || isArrayLiteral(name) ||
7301                           name[0] === 'function' || isObjectLiteral(name))) &&
7302                         (!deps || isArrayLiteral(deps) ||
7303                          deps[0] === 'function' || isObjectLiteral(deps) ||
7304                          // allow define(['dep'], factory) pattern
7305                          (isArrayLiteral(name) && deps[0] === 'name' && args.length === 2))) {
7306
7307                         //If first arg is a function, could be a commonjs wrapper,
7308                         //look inside for commonjs dependencies.
7309                         //Also, if deps is a function look for commonjs deps.
7310                         if (name && name[0] === 'function') {
7311                             cjsDeps = parse.getAnonDepsFromNode(name);
7312                             if (cjsDeps.length) {
7313                                 name = toAstArray(cjsDeps);
7314                             }
7315                         } else if (deps && deps[0] === 'function') {
7316                             cjsDeps = parse.getAnonDepsFromNode(deps);
7317                             if (cjsDeps.length) {
7318                                 deps = toAstArray(cjsDeps);
7319                             }
7320                         }
7321
7322                         return onMatch("define", null, name, deps);
7323                     }
7324                 }
7325             }
7326         }
7327
7328         return false;
7329     };
7330
7331     /**
7332      * Looks for define(), require({} || []), requirejs({} || []) calls.
7333      */
7334     parse.findAmdOrRequireJsNode = function (node, onMatch) {
7335         var call, args, configNode, type;
7336
7337         if (!isArray(node)) {
7338             return false;
7339         }
7340
7341         if (node[0] === 'defun' && node[1] === 'define') {
7342             type = 'declaresDefine';
7343         } else if (node[0] === 'assign' && node[2] && node[2][2] === 'amd' &&
7344             node[2][1] && node[2][1][0] === 'name' &&
7345             node[2][1][1] === 'define') {
7346             type = 'defineAmd';
7347         } else if (node[0] === 'call') {
7348             call = node[1];
7349             args = node[2];
7350
7351             if (call) {
7352                 if ((call[0] === 'dot' &&
7353                    (call[1] && call[1][0] === 'name' &&
7354                     (call[1][1] === 'require' || call[1][1] === 'requirejs')) &&
7355                    call[2] === 'config')) {
7356                     //A require.config() or requirejs.config() call.
7357                     type = call[1][1] + 'Config';
7358                 } else if (call[0] === 'name' &&
7359                    (call[1] === 'require' || call[1] === 'requirejs')) {
7360                     //A require() or requirejs() config call.
7361                     //Only want ones that start with an object or an array.
7362                     configNode = args[0];
7363                     if (configNode[0] === 'object' || configNode[0] === 'array') {
7364                         type = call[1];
7365                     }
7366                 } else if (call[0] === 'name' && call[1] === 'define') {
7367                     //A define call.
7368                     type = 'define';
7369                 }
7370             }
7371         }
7372
7373         if (type) {
7374             return onMatch(type);
7375         }
7376
7377         return false;
7378     };
7379
7380     /**
7381      * Determines if a specific node is a valid require/requirejs config
7382      * call. That includes calls to require/requirejs.config().
7383      * @param {Array} node
7384      * @param {Function} onMatch a function to call when a match is found.
7385      * It is passed the match name, and the config, name, deps possible args.
7386      * The config, name and deps args are not normalized.
7387      *
7388      * @returns {String} a JS source string with the valid require/define call.
7389      * Otherwise null.
7390      */
7391     parse.parseConfigNode = function (node, onMatch) {
7392         var call, configNode, args;
7393
7394         if (!isArray(node)) {
7395             return false;
7396         }
7397
7398         if (node[0] === 'call') {
7399             call = node[1];
7400             args = node[2];
7401
7402             if (call) {
7403                 //A require.config() or requirejs.config() call.
7404                 if ((call[0] === 'dot' &&
7405                    (call[1] && call[1][0] === 'name' &&
7406                     (call[1][1] === 'require' || call[1][1] === 'requirejs')) &&
7407                    call[2] === 'config') ||
7408                    //A require() or requirejs() config call.
7409
7410                    (call[0] === 'name' &&
7411                    (call[1] === 'require' || call[1] === 'requirejs'))
7412                 ) {
7413                     //It is a plain require() call.
7414                     configNode = args[0];
7415
7416                     if (configNode[0] !== 'object') {
7417                         return null;
7418                     }
7419
7420                     return onMatch(configNode);
7421
7422                 }
7423             }
7424         }
7425
7426         return false;
7427     };
7428
7429     /**
7430      * Converts an AST node into a JS source string. Does not maintain formatting
7431      * or even comments from original source, just returns valid JS source.
7432      * @param {Array} node
7433      * @returns {String} a JS source string.
7434      */
7435     parse.nodeToString = function (node) {
7436         return processor.gen_code(node, true);
7437     };
7438
7439     return parse;
7440 });
7441 /**
7442  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
7443  * Available via the MIT or new BSD license.
7444  * see: http://github.com/jrburke/requirejs for details
7445  */
7446
7447 /*jslint regexp: false, strict: false, plusplus: false  */
7448 /*global define: false */
7449
7450 define('pragma', ['parse', 'logger'], function (parse, logger) {
7451
7452     function Temp() {}
7453
7454     function create(obj, mixin) {
7455         Temp.prototype = obj;
7456         var temp = new Temp(), prop;
7457
7458         //Avoid any extra memory hanging around
7459         Temp.prototype = null;
7460
7461         if (mixin) {
7462             for (prop in mixin) {
7463                 if (mixin.hasOwnProperty(prop) && !(prop in temp)) {
7464                     temp[prop] = mixin[prop];
7465                 }
7466             }
7467         }
7468
7469         return temp; // Object
7470     }
7471
7472     var pragma = {
7473         conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
7474         useStrictRegExp: /['"]use strict['"];/g,
7475         hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
7476         nsRegExp: /(^|[^\.])(requirejs|require|define)\s*\(/,
7477         nsWrapRegExp: /\/\*requirejs namespace: true \*\//,
7478         apiDefRegExp: /var requirejs, require, define;/,
7479         defineCheckRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd/g,
7480         defineJQueryRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd\s*&&\s*define\s*\.\s*amd\s*\.\s*jQuery/g,
7481         defineHasRegExp: /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g,
7482         defineTernaryRegExp: /typeof\s+define\s*===\s*['"]function["']\s*&&\s*define\s*\.\s*amd\s*\?\s*define/,
7483         amdefineRegExp: /if\s*\(\s*typeof define\s*\!==\s*'function'\s*\)\s*\{\s*[^\{\}]+amdefine[^\{\}]+\}/g,
7484
7485         removeStrict: function (contents, config) {
7486             return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '');
7487         },
7488
7489         namespace: function (fileContents, ns, onLifecycleName) {
7490             if (ns) {
7491                 //Namespace require/define calls
7492                 fileContents = fileContents.replace(pragma.nsRegExp, '$1' + ns + '.$2(');
7493
7494                 //Namespace define ternary use:
7495                 fileContents = fileContents.replace(pragma.defineTernaryRegExp,
7496                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd ? " + ns + ".define");
7497
7498                 //Namespace define jquery use:
7499                 fileContents = fileContents.replace(pragma.defineJQueryRegExp,
7500                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd && " + ns + ".define.amd.jQuery");
7501
7502                 //Namespace has.js define use:
7503                 fileContents = fileContents.replace(pragma.defineHasRegExp,
7504                                                     "typeof " + ns + ".define === 'function' && typeof " + ns + ".define.amd === 'object' && " + ns + ".define.amd");
7505
7506                 //Namespace define checks.
7507                 //Do this one last, since it is a subset of the more specific
7508                 //checks above.
7509                 fileContents = fileContents.replace(pragma.defineCheckRegExp,
7510                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd");
7511
7512                 //Check for require.js with the require/define definitions
7513                 if (pragma.apiDefRegExp.test(fileContents) &&
7514                     fileContents.indexOf("if (typeof " + ns + " === 'undefined')") === -1) {
7515                     //Wrap the file contents in a typeof check, and a function
7516                     //to contain the API globals.
7517                     fileContents = "var " + ns + ";(function () { if (typeof " +
7518                                     ns + " === 'undefined') {\n" +
7519                                     ns + ' = {};\n' +
7520                                     fileContents +
7521                                     "\n" +
7522                                     ns + ".requirejs = requirejs;" +
7523                                     ns + ".require = require;" +
7524                                     ns + ".define = define;\n" +
7525                                     "}\n}());";
7526                 }
7527
7528                 //Finally, if the file wants a special wrapper because it ties
7529                 //in to the requirejs internals in a way that would not fit
7530                 //the above matches, do that. Look for /*requirejs namespace: true*/
7531                 if (pragma.nsWrapRegExp.test(fileContents)) {
7532                     //Remove the pragma.
7533                     fileContents = fileContents.replace(pragma.nsWrapRegExp, '');
7534
7535                     //Alter the contents.
7536                     fileContents = '(function () {\n' +
7537                                    'var require = ' + ns + '.require,' +
7538                                    'requirejs = ' + ns + '.requirejs,' +
7539                                    'define = ' + ns + '.define;\n' +
7540                                    fileContents +
7541                                    '\n}());'
7542                 }
7543             }
7544
7545             return fileContents;
7546         },
7547
7548         /**
7549          * processes the fileContents for some //>> conditional statements
7550          */
7551         process: function (fileName, fileContents, config, onLifecycleName, pluginCollector) {
7552             /*jslint evil: true */
7553             var foundIndex = -1, startIndex = 0, lineEndIndex, conditionLine,
7554                 matches, type, marker, condition, isTrue, endRegExp, endMatches,
7555                 endMarkerIndex, shouldInclude, startLength, lifecycleHas, deps,
7556                 i, dep, moduleName,
7557                 lifecyclePragmas, pragmas = config.pragmas, hasConfig = config.has,
7558                 //Legacy arg defined to help in dojo conversion script. Remove later
7559                 //when dojo no longer needs conversion:
7560                 kwArgs = pragmas;
7561
7562             //Mix in a specific lifecycle scoped object, to allow targeting
7563             //some pragmas/has tests to only when files are saved, or at different
7564             //lifecycle events. Do not bother with kwArgs in this section, since
7565             //the old dojo kwArgs were for all points in the build lifecycle.
7566             if (onLifecycleName) {
7567                 lifecyclePragmas = config['pragmas' + onLifecycleName];
7568                 lifecycleHas = config['has' + onLifecycleName];
7569
7570                 if (lifecyclePragmas) {
7571                     pragmas = create(pragmas || {}, lifecyclePragmas);
7572                 }
7573
7574                 if (lifecycleHas) {
7575                     hasConfig = create(hasConfig || {}, lifecycleHas);
7576                 }
7577             }
7578
7579             //Replace has references if desired
7580             if (hasConfig) {
7581                 fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) {
7582                     if (test in hasConfig) {
7583                         return !!hasConfig[test];
7584                     }
7585                     return match;
7586                 });
7587             }
7588
7589             if (!config.skipPragmas) {
7590
7591                 while ((foundIndex = fileContents.indexOf("//>>", startIndex)) !== -1) {
7592                     //Found a conditional. Get the conditional line.
7593                     lineEndIndex = fileContents.indexOf("\n", foundIndex);
7594                     if (lineEndIndex === -1) {
7595                         lineEndIndex = fileContents.length - 1;
7596                     }
7597
7598                     //Increment startIndex past the line so the next conditional search can be done.
7599                     startIndex = lineEndIndex + 1;
7600
7601                     //Break apart the conditional.
7602                     conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
7603                     matches = conditionLine.match(pragma.conditionalRegExp);
7604                     if (matches) {
7605                         type = matches[1];
7606                         marker = matches[2];
7607                         condition = matches[3];
7608                         isTrue = false;
7609                         //See if the condition is true.
7610                         try {
7611                             isTrue = !!eval("(" + condition + ")");
7612                         } catch (e) {
7613                             throw "Error in file: " +
7614                                    fileName +
7615                                    ". Conditional comment: " +
7616                                    conditionLine +
7617                                    " failed with this error: " + e;
7618                         }
7619
7620                         //Find the endpoint marker.
7621                         endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
7622                         endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
7623                         if (endMatches) {
7624                             endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
7625
7626                             //Find the next line return based on the match position.
7627                             lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
7628                             if (lineEndIndex === -1) {
7629                                 lineEndIndex = fileContents.length - 1;
7630                             }
7631
7632                             //Should we include the segment?
7633                             shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue));
7634
7635                             //Remove the conditional comments, and optionally remove the content inside
7636                             //the conditional comments.
7637                             startLength = startIndex - foundIndex;
7638                             fileContents = fileContents.substring(0, foundIndex) +
7639                                 (shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") +
7640                                 fileContents.substring(lineEndIndex + 1, fileContents.length);
7641
7642                             //Move startIndex to foundIndex, since that is the new position in the file
7643                             //where we need to look for more conditionals in the next while loop pass.
7644                             startIndex = foundIndex;
7645                         } else {
7646                             throw "Error in file: " +
7647                                   fileName +
7648                                   ". Cannot find end marker for conditional comment: " +
7649                                   conditionLine;
7650
7651                         }
7652                     }
7653                 }
7654             }
7655
7656             //If need to find all plugin resources to optimize, do that now,
7657             //before namespacing, since the namespacing will change the API
7658             //names.
7659             //If there is a plugin collector, scan the file for plugin resources.
7660             if (config.optimizeAllPluginResources && pluginCollector) {
7661                 try {
7662                     deps = parse.findDependencies(fileName, fileContents);
7663                     if (deps.length) {
7664                         for (i = 0; (dep = deps[i]); i++) {
7665                             if (dep.indexOf('!') !== -1) {
7666                                 (pluginCollector[moduleName] ||
7667                                  (pluginCollector[moduleName] = [])).push(dep);
7668                             }
7669                         }
7670                     }
7671                 } catch (eDep) {
7672                     logger.error('Parse error looking for plugin resources in ' +
7673                                  fileName + ', skipping.');
7674                 }
7675             }
7676
7677             //Strip amdefine use for node-shared modules.
7678             fileContents = fileContents.replace(pragma.amdefineRegExp, '');
7679
7680             //Do namespacing
7681             if (onLifecycleName === 'OnSave' && config.namespace) {
7682                 fileContents = pragma.namespace(fileContents, config.namespace, onLifecycleName);
7683             }
7684
7685
7686             return pragma.removeStrict(fileContents, config);
7687         }
7688     };
7689
7690     return pragma;
7691 });
7692 if(env === 'node') {
7693 /**
7694  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
7695  * Available via the MIT or new BSD license.
7696  * see: http://github.com/jrburke/requirejs for details
7697  */
7698
7699 /*jslint strict: false */
7700 /*global define: false */
7701
7702 define('node/optimize', {});
7703
7704 }
7705
7706 if(env === 'rhino') {
7707 /**
7708  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
7709  * Available via the MIT or new BSD license.
7710  * see: http://github.com/jrburke/requirejs for details
7711  */
7712
7713 /*jslint strict: false, plusplus: false */
7714 /*global define: false, java: false, Packages: false */
7715
7716 define('rhino/optimize', ['logger'], function (logger) {
7717
7718     //Add .reduce to Rhino so UglifyJS can run in Rhino,
7719     //inspired by https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
7720     //but rewritten for brevity, and to be good enough for use by UglifyJS.
7721     if (!Array.prototype.reduce) {
7722         Array.prototype.reduce = function (fn /*, initialValue */) {
7723             var i = 0,
7724                 length = this.length,
7725                 accumulator;
7726
7727             if (arguments.length >= 2) {
7728                 accumulator = arguments[1];
7729             } else {
7730                 do {
7731                     if (i in this) {
7732                         accumulator = this[i++];
7733                         break;
7734                     }
7735                 }
7736                 while (true);
7737             }
7738
7739             for (; i < length; i++) {
7740                 if (i in this) {
7741                     accumulator = fn.call(undefined, accumulator, this[i], i, this);
7742                 }
7743             }
7744
7745             return accumulator;
7746         };
7747     }
7748
7749     var JSSourceFilefromCode, optimize;
7750
7751     //Bind to Closure compiler, but if it is not available, do not sweat it.
7752     try {
7753         JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]);
7754     } catch (e) {}
7755
7756     //Helper for closure compiler, because of weird Java-JavaScript interactions.
7757     function closurefromCode(filename, content) {
7758         return JSSourceFilefromCode.invoke(null, [filename, content]);
7759     }
7760
7761     optimize = {
7762         closure: function (fileName, fileContents, keepLines, config) {
7763             config = config || {};
7764             var jscomp = Packages.com.google.javascript.jscomp,
7765                 flags = Packages.com.google.common.flags,
7766                 //Fake extern
7767                 externSourceFile = closurefromCode("fakeextern.js", " "),
7768                 //Set up source input
7769                 jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
7770                 options, option, FLAG_compilation_level, compiler,
7771                 Compiler = Packages.com.google.javascript.jscomp.Compiler,
7772                 result;
7773
7774             logger.trace("Minifying file: " + fileName);
7775
7776             //Set up options
7777             options = new jscomp.CompilerOptions();
7778             for (option in config.CompilerOptions) {
7779                 // options are false by default and jslint wanted an if statement in this for loop
7780                 if (config.CompilerOptions[option]) {
7781                     options[option] = config.CompilerOptions[option];
7782                 }
7783
7784             }
7785             options.prettyPrint = keepLines || options.prettyPrint;
7786
7787             FLAG_compilation_level = jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS'];
7788             FLAG_compilation_level.setOptionsForCompilationLevel(options);
7789
7790             //Trigger the compiler
7791             Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']);
7792             compiler = new Compiler();
7793
7794             result = compiler.compile(externSourceFile, jsSourceFile, options);
7795             if (!result.success) {
7796                 logger.error('Cannot closure compile file: ' + fileName + '. Skipping it.');
7797             } else {
7798                 fileContents = compiler.toSource();
7799             }
7800
7801             return fileContents;
7802         }
7803     };
7804
7805     return optimize;
7806 });
7807 }
7808 /**
7809  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
7810  * Available via the MIT or new BSD license.
7811  * see: http://github.com/jrburke/requirejs for details
7812  */
7813
7814 /*jslint plusplus: false, nomen: false, regexp: false */
7815 /*global define: false */
7816
7817 define('optimize', [ 'lang', 'logger', 'env!env/optimize', 'env!env/file', 'parse',
7818          'pragma', 'uglifyjs/index'],
7819 function (lang,   logger,   envOptimize,        file,           parse,
7820           pragma, uglify) {
7821
7822     var optimize,
7823         cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g,
7824         cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g;
7825
7826     /**
7827      * If an URL from a CSS url value contains start/end quotes, remove them.
7828      * This is not done in the regexp, since my regexp fu is not that strong,
7829      * and the CSS spec allows for ' and " in the URL if they are backslash escaped.
7830      * @param {String} url
7831      */
7832     function cleanCssUrlQuotes(url) {
7833         //Make sure we are not ending in whitespace.
7834         //Not very confident of the css regexps above that there will not be ending
7835         //whitespace.
7836         url = url.replace(/\s+$/, "");
7837
7838         if (url.charAt(0) === "'" || url.charAt(0) === "\"") {
7839             url = url.substring(1, url.length - 1);
7840         }
7841
7842         return url;
7843     }
7844
7845     /**
7846      * Inlines nested stylesheets that have @import calls in them.
7847      * @param {String} fileName the file name
7848      * @param {String} fileContents the file contents
7849      * @param {String} cssImportIgnore comma delimited string of files to ignore
7850      * @param {Object} included an object used to track the files already imported
7851      */
7852     function flattenCss(fileName, fileContents, cssImportIgnore, included) {
7853         //Find the last slash in the name.
7854         fileName = fileName.replace(lang.backSlashRegExp, "/");
7855         var endIndex = fileName.lastIndexOf("/"),
7856             //Make a file path based on the last slash.
7857             //If no slash, so must be just a file name. Use empty string then.
7858             filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "",
7859             //store a list of merged files
7860             importList = [];
7861
7862         //Make sure we have a delimited ignore list to make matching faster
7863         if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") {
7864             cssImportIgnore += ",";
7865         }
7866
7867         fileContents = fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) {
7868             //Only process media type "all" or empty media type rules.
7869             if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) {
7870                 return fullMatch;
7871             }
7872
7873             importFileName = cleanCssUrlQuotes(importFileName);
7874
7875             //Ignore the file import if it is part of an ignore list.
7876             if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) {
7877                 return fullMatch;
7878             }
7879
7880             //Make sure we have a unix path for the rest of the operation.
7881             importFileName = importFileName.replace(lang.backSlashRegExp, "/");
7882
7883             try {
7884                 //if a relative path, then tack on the filePath.
7885                 //If it is not a relative path, then the readFile below will fail,
7886                 //and we will just skip that import.
7887                 var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName,
7888                     importContents = file.readFile(fullImportFileName), i,
7889                     importEndIndex, importPath, fixedUrlMatch, colonIndex, parts, flat;
7890
7891                 //Skip the file if it has already been included.
7892                 if (included[fullImportFileName]) {
7893                     return '';
7894                 }
7895                 included[fullImportFileName] = true;
7896
7897                 //Make sure to flatten any nested imports.
7898                 flat = flattenCss(fullImportFileName, importContents, cssImportIgnore, included);
7899                 importContents = flat.fileContents;
7900
7901                 if (flat.importList.length) {
7902                     importList.push.apply(importList, flat.importList);
7903                 }
7904
7905                 //Make the full import path
7906                 importEndIndex = importFileName.lastIndexOf("/");
7907
7908                 //Make a file path based on the last slash.
7909                 //If no slash, so must be just a file name. Use empty string then.
7910                 importPath = (importEndIndex !== -1) ? importFileName.substring(0, importEndIndex + 1) : "";
7911
7912                 //fix url() on relative import (#5)
7913                 importPath = importPath.replace(/^\.\//, '');
7914
7915                 //Modify URL paths to match the path represented by this file.
7916                 importContents = importContents.replace(cssUrlRegExp, function (fullMatch, urlMatch) {
7917                     fixedUrlMatch = cleanCssUrlQuotes(urlMatch);
7918                     fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/");
7919
7920                     //Only do the work for relative URLs. Skip things that start with / or have
7921                     //a protocol.
7922                     colonIndex = fixedUrlMatch.indexOf(":");
7923                     if (fixedUrlMatch.charAt(0) !== "/" && (colonIndex === -1 || colonIndex > fixedUrlMatch.indexOf("/"))) {
7924                         //It is a relative URL, tack on the path prefix
7925                         urlMatch = importPath + fixedUrlMatch;
7926                     } else {
7927                         logger.trace(importFileName + "\n  URL not a relative URL, skipping: " + urlMatch);
7928                     }
7929
7930                     //Collapse .. and .
7931                     parts = urlMatch.split("/");
7932                     for (i = parts.length - 1; i > 0; i--) {
7933                         if (parts[i] === ".") {
7934                             parts.splice(i, 1);
7935                         } else if (parts[i] === "..") {
7936                             if (i !== 0 && parts[i - 1] !== "..") {
7937                                 parts.splice(i - 1, 2);
7938                                 i -= 1;
7939                             }
7940                         }
7941                     }
7942
7943                     return "url(" + parts.join("/") + ")";
7944                 });
7945
7946                 importList.push(fullImportFileName);
7947                 return importContents;
7948             } catch (e) {
7949                 logger.warn(fileName + "\n  Cannot inline css import, skipping: " + importFileName);
7950                 return fullMatch;
7951             }
7952         });
7953
7954         return {
7955             importList : importList,
7956             fileContents : fileContents
7957         };
7958     }
7959
7960     optimize = {
7961         licenseCommentRegExp: /\/\*[\s\S]*?\*\//g,
7962
7963         /**
7964          * Optimizes a file that contains JavaScript content. Optionally collects
7965          * plugin resources mentioned in a file, and then passes the content
7966          * through an minifier if one is specified via config.optimize.
7967          *
7968          * @param {String} fileName the name of the file to optimize
7969          * @param {String} outFileName the name of the file to use for the
7970          * saved optimized content.
7971          * @param {Object} config the build config object.
7972          * @param {String} [moduleName] the module name to use for the file.
7973          * Used for plugin resource collection.
7974          * @param {Array} [pluginCollector] storage for any plugin resources
7975          * found.
7976          */
7977         jsFile: function (fileName, outFileName, config, moduleName, pluginCollector) {
7978             var parts = (config.optimize + "").split('.'),
7979                 optimizerName = parts[0],
7980                 keepLines = parts[1] === 'keepLines',
7981                 fileContents;
7982
7983             fileContents = file.readFile(fileName);
7984
7985             fileContents = optimize.js(fileName, fileContents, optimizerName,
7986                                        keepLines, config, pluginCollector);
7987
7988             file.saveUtf8File(outFileName, fileContents);
7989         },
7990
7991         /**
7992          * Optimizes a file that contains JavaScript content. Optionally collects
7993          * plugin resources mentioned in a file, and then passes the content
7994          * through an minifier if one is specified via config.optimize.
7995          *
7996          * @param {String} fileName the name of the file that matches the
7997          * fileContents.
7998          * @param {String} fileContents the string of JS to optimize.
7999          * @param {String} [optimizerName] optional name of the optimizer to
8000          * use. 'uglify' is default.
8001          * @param {Boolean} [keepLines] whether to keep line returns in the optimization.
8002          * @param {Object} [config] the build config object.
8003          * @param {Array} [pluginCollector] storage for any plugin resources
8004          * found.
8005          */
8006         js: function (fileName, fileContents, optimizerName, keepLines, config, pluginCollector) {
8007             var licenseContents = '',
8008                 optFunc, match, comment;
8009
8010             config = config || {};
8011
8012             //Apply pragmas/namespace renaming
8013             fileContents = pragma.process(fileName, fileContents, config, 'OnSave', pluginCollector);
8014
8015             //Optimize the JS files if asked.
8016             if (optimizerName && optimizerName !== 'none') {
8017                 optFunc = envOptimize[optimizerName] || optimize.optimizers[optimizerName];
8018                 if (!optFunc) {
8019                     throw new Error('optimizer with name of "' +
8020                                     optimizerName +
8021                                     '" not found for this environment');
8022                 }
8023
8024                 if (config.preserveLicenseComments) {
8025                     //Pull out any license comments for prepending after optimization.
8026                     optimize.licenseCommentRegExp.lastIndex = 0;
8027                     while ((match = optimize.licenseCommentRegExp.exec(fileContents))) {
8028                         comment = match[0];
8029                         //Only keep the comments if they are license comments.
8030                         if (comment.indexOf('@license') !== -1 ||
8031                             comment.indexOf('/*!') === 0) {
8032                             licenseContents += comment + '\n';
8033                         }
8034                     }
8035                 }
8036
8037                 fileContents = licenseContents + optFunc(fileName, fileContents, keepLines,
8038                                         config[optimizerName]);
8039             }
8040
8041             return fileContents;
8042         },
8043
8044         /**
8045          * Optimizes one CSS file, inlining @import calls, stripping comments, and
8046          * optionally removes line returns.
8047          * @param {String} fileName the path to the CSS file to optimize
8048          * @param {String} outFileName the path to save the optimized file.
8049          * @param {Object} config the config object with the optimizeCss and
8050          * cssImportIgnore options.
8051          */
8052         cssFile: function (fileName, outFileName, config) {
8053
8054             //Read in the file. Make sure we have a JS string.
8055             var originalFileContents = file.readFile(fileName),
8056                 flat = flattenCss(fileName, originalFileContents, config.cssImportIgnore, {}),
8057                 fileContents = flat.fileContents,
8058                 startIndex, endIndex, buildText;
8059
8060             //Do comment removal.
8061             try {
8062                 if (config.optimizeCss.indexOf(".keepComments") === -1) {
8063                     startIndex = -1;
8064                     //Get rid of comments.
8065                     while ((startIndex = fileContents.indexOf("/*")) !== -1) {
8066                         endIndex = fileContents.indexOf("*/", startIndex + 2);
8067                         if (endIndex === -1) {
8068                             throw "Improper comment in CSS file: " + fileName;
8069                         }
8070                         fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length);
8071                     }
8072                 }
8073                 //Get rid of newlines.
8074                 if (config.optimizeCss.indexOf(".keepLines") === -1) {
8075                     fileContents = fileContents.replace(/[\r\n]/g, "");
8076                     fileContents = fileContents.replace(/\s+/g, " ");
8077                     fileContents = fileContents.replace(/\{\s/g, "{");
8078                     fileContents = fileContents.replace(/\s\}/g, "}");
8079                 } else {
8080                     //Remove multiple empty lines.
8081                     fileContents = fileContents.replace(/(\r\n)+/g, "\r\n");
8082                     fileContents = fileContents.replace(/(\n)+/g, "\n");
8083                 }
8084             } catch (e) {
8085                 fileContents = originalFileContents;
8086                 logger.error("Could not optimized CSS file: " + fileName + ", error: " + e);
8087             }
8088
8089             file.saveUtf8File(outFileName, fileContents);
8090
8091             //text output to stdout and/or written to build.txt file
8092             buildText = "\n"+ outFileName.replace(config.dir, "") +"\n----------------\n";
8093             flat.importList.push(fileName);
8094             buildText += flat.importList.map(function(path){
8095                 return path.replace(config.dir, "");
8096             }).join("\n");
8097             return buildText +"\n";
8098         },
8099
8100         /**
8101          * Optimizes CSS files, inlining @import calls, stripping comments, and
8102          * optionally removes line returns.
8103          * @param {String} startDir the path to the top level directory
8104          * @param {Object} config the config object with the optimizeCss and
8105          * cssImportIgnore options.
8106          */
8107         css: function (startDir, config) {
8108             var buildText = "",
8109                 i, fileName, fileList;
8110             if (config.optimizeCss.indexOf("standard") !== -1) {
8111                 fileList = file.getFilteredFileList(startDir, /\.css$/, true);
8112                 if (fileList) {
8113                     for (i = 0; i < fileList.length; i++) {
8114                         fileName = fileList[i];
8115                         logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName);
8116                         buildText += optimize.cssFile(fileName, fileName, config);
8117                     }
8118                 }
8119             }
8120             return buildText;
8121         },
8122
8123         optimizers: {
8124             uglify: function (fileName, fileContents, keepLines, config) {
8125                 var parser = uglify.parser,
8126                     processor = uglify.uglify,
8127                     ast;
8128
8129                 config = config || {};
8130
8131                 logger.trace("Uglifying file: " + fileName);
8132
8133                 try {
8134                     ast = parser.parse(fileContents, config.strict_semicolons);
8135                     ast = processor.ast_mangle(ast, config);
8136                     ast = processor.ast_squeeze(ast, config);
8137
8138                     fileContents = processor.gen_code(ast, config);
8139                 } catch (e) {
8140                     logger.error('Cannot uglify file: ' + fileName + '. Skipping it. Error is:\n' + e.toString());
8141                 }
8142                 return fileContents;
8143             }
8144         }
8145     };
8146
8147     return optimize;
8148 });
8149 /**
8150  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
8151  * Available via the MIT or new BSD license.
8152  * see: http://github.com/jrburke/requirejs for details
8153  */
8154 /*
8155  * This file patches require.js to communicate with the build system.
8156  */
8157
8158 /*jslint nomen: false, plusplus: false, regexp: false, strict: false */
8159 /*global require: false, define: true */
8160
8161 //NOT asking for require as a dependency since the goal is to modify the
8162 //global require below
8163 define('requirePatch', [ 'env!env/file', 'pragma', 'parse'],
8164 function (file,           pragma,   parse) {
8165
8166     var allowRun = true;
8167
8168     //This method should be called when the patches to require should take hold.
8169     return function () {
8170         if (!allowRun) {
8171             return;
8172         }
8173         allowRun = false;
8174
8175         var layer,
8176             pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/,
8177             oldDef;
8178
8179
8180         /** Print out some extrs info about the module tree that caused the error. **/
8181         require.onError = function (err) {
8182
8183             var msg = '\nIn module tree:\n',
8184                 standardIndent = '  ',
8185                 tree = err.moduleTree,
8186                 i, j, mod;
8187
8188             if (tree && tree.length > 0) {
8189                 for (i = tree.length - 1; i > -1 && (mod = tree[i]); i--) {
8190                     for (j = tree.length - i; j > -1; j--) {
8191                         msg += standardIndent;
8192                     }
8193                     msg += mod + '\n';
8194                 }
8195
8196                 err = new Error(err.toString() + msg);
8197             }
8198
8199             throw err;
8200         };
8201
8202         //Stored cached file contents for reuse in other layers.
8203         require._cachedFileContents = {};
8204
8205         /** Reset state for each build layer pass. */
8206         require._buildReset = function () {
8207             var oldContext = require.s.contexts._;
8208
8209             //Clear up the existing context.
8210             delete require.s.contexts._;
8211
8212             //Set up new context, so the layer object can hold onto it.
8213             require({});
8214
8215             layer = require._layer = {
8216                 buildPathMap: {},
8217                 buildFileToModule: {},
8218                 buildFilePaths: [],
8219                 pathAdded: {},
8220                 modulesWithNames: {},
8221                 needsDefine: {},
8222                 existingRequireUrl: "",
8223                 context: require.s.contexts._
8224             };
8225
8226             //Return the previous context in case it is needed, like for
8227             //the basic config object.
8228             return oldContext;
8229         };
8230
8231         require._buildReset();
8232
8233         /**
8234          * Makes sure the URL is something that can be supported by the
8235          * optimization tool.
8236          * @param {String} url
8237          * @returns {Boolean}
8238          */
8239         require._isSupportedBuildUrl = function (url) {
8240             //Ignore URLs with protocols, hosts or question marks, means either network
8241             //access is needed to fetch it or it is too dynamic. Note that
8242             //on Windows, full paths are used for some urls, which include
8243             //the drive, like c:/something, so need to test for something other
8244             //than just a colon.
8245             return url.indexOf("://") === -1 && url.indexOf("?") === -1 &&
8246                    url.indexOf('empty:') !== 0 && url.indexOf('//') !== 0;
8247         };
8248
8249         //Override define() to catch modules that just define an object, so that
8250         //a dummy define call is not put in the build file for them. They do
8251         //not end up getting defined via require.execCb, so we need to catch them
8252         //at the define call.
8253         oldDef = define;
8254
8255         //This function signature does not have to be exact, just match what we
8256         //are looking for.
8257         define = function (name, obj) {
8258             if (typeof name === "string" && !layer.needsDefine[name]) {
8259                 layer.modulesWithNames[name] = true;
8260             }
8261             return oldDef.apply(require, arguments);
8262         };
8263
8264         define.amd = oldDef.amd;
8265
8266         //Add some utilities for plugins
8267         require._readFile = file.readFile;
8268         require._fileExists = function (path) {
8269             return file.exists(path);
8270         };
8271
8272         function normalizeUrlWithBase(context, moduleName, url) {
8273             //Adjust the URL if it was not transformed to use baseUrl.
8274             if (require.jsExtRegExp.test(moduleName)) {
8275                 url = (context.config.dir || context.config.dirBaseUrl) + url;
8276             }
8277             return url;
8278         }
8279
8280         //Override load so that the file paths can be collected.
8281         require.load = function (context, moduleName, url) {
8282             /*jslint evil: true */
8283             var contents, pluginBuilderMatch, builderName;
8284
8285             context.scriptCount += 1;
8286
8287             //Only handle urls that can be inlined, so that means avoiding some
8288             //URLs like ones that require network access or may be too dynamic,
8289             //like JSONP
8290             if (require._isSupportedBuildUrl(url)) {
8291                 //Adjust the URL if it was not transformed to use baseUrl.
8292                 url = normalizeUrlWithBase(context, moduleName, url);
8293                 
8294                 //Save the module name to path  and path to module name mappings.
8295                 layer.buildPathMap[moduleName] = url;
8296                 layer.buildFileToModule[url] = moduleName;
8297
8298                 if (moduleName in context.plugins) {
8299                     //plugins need to have their source evaled as-is.
8300                     context.needFullExec[moduleName] = true;
8301                 }
8302
8303                 try {
8304                     if (url in require._cachedFileContents &&
8305                         (!context.needFullExec[moduleName] || context.fullExec[moduleName])) {
8306                         contents = require._cachedFileContents[url];
8307                     } else {
8308                         //Load the file contents, process for conditionals, then
8309                         //evaluate it.
8310                         contents = file.readFile(url);
8311
8312                         //If there is a read filter, run it now.
8313                         if (context.config.onBuildRead) {
8314                             contents = context.config.onBuildRead(moduleName, url, contents);
8315                         }
8316
8317                         contents = pragma.process(url, contents, context.config, 'OnExecute');
8318
8319                         //Find out if the file contains a require() definition. Need to know
8320                         //this so we can inject plugins right after it, but before they are needed,
8321                         //and to make sure this file is first, so that define calls work.
8322                         //This situation mainly occurs when the build is done on top of the output
8323                         //of another build, where the first build may include require somewhere in it.
8324                         try {
8325                             if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) {
8326                                 layer.existingRequireUrl = url;
8327                             }
8328                         } catch (e1) {
8329                             throw new Error('Parse error using UglifyJS ' +
8330                                             'for file: ' + url + '\n' + e1);
8331                         }
8332
8333                         if (moduleName in context.plugins) {
8334                             //This is a loader plugin, check to see if it has a build extension,
8335                             //otherwise the plugin will act as the plugin builder too.
8336                             pluginBuilderMatch = pluginBuilderRegExp.exec(contents);
8337                             if (pluginBuilderMatch) {
8338                                 //Load the plugin builder for the plugin contents.
8339                                 builderName = context.normalize(pluginBuilderMatch[3], moduleName);
8340                                 contents = file.readFile(context.nameToUrl(builderName));
8341                             }
8342                         }
8343
8344                         //Parse out the require and define calls.
8345                         //Do this even for plugins in case they have their own
8346                         //dependencies that may be separate to how the pluginBuilder works.
8347                         try {
8348                             if (!context.needFullExec[moduleName]) {
8349                                 contents = parse(moduleName, url, contents, {
8350                                     insertNeedsDefine: true,
8351                                     has: context.config.has,
8352                                     findNestedDependencies: context.config.findNestedDependencies
8353                                 });
8354                             }
8355                         } catch (e2) {
8356                             throw new Error('Parse error using UglifyJS ' +
8357                                             'for file: ' + url + '\n' + e2);
8358                         }
8359
8360                         require._cachedFileContents[url] = contents;
8361                     }
8362
8363                     if (contents) {
8364                         eval(contents);
8365                     }
8366
8367                     //Need to close out completion of this module
8368                     //so that listeners will get notified that it is available.
8369                     try {
8370                         context.completeLoad(moduleName);
8371                     } catch (e) {
8372                         //Track which module could not complete loading.
8373                         (e.moduleTree || (e.moduleTree = [])).push(moduleName);
8374                         throw e;
8375                     }
8376
8377                 } catch (eOuter) {
8378                     if (!eOuter.fileName) {
8379                         eOuter.fileName = url;
8380                     }
8381                     throw eOuter;
8382                 }
8383             } else {
8384                 //With unsupported URLs still need to call completeLoad to
8385                 //finish loading.
8386                 context.completeLoad(moduleName);
8387             }
8388
8389             //Mark the module loaded.
8390             context.loaded[moduleName] = true;
8391         };
8392
8393
8394         //Called when execManager runs for a dependency. Used to figure out
8395         //what order of execution.
8396         require.onResourceLoad = function (context, map) {
8397             var fullName = map.fullName,
8398                 url;
8399
8400             //Ignore "fake" modules, usually generated by plugin code, since
8401             //they do not map back to a real file to include in the optimizer,
8402             //or it will be included, but in a different form.
8403             if (context.fake[fullName]) {
8404                 return;
8405             }
8406
8407             //A plugin.
8408             if (map.prefix) {
8409                 if (!layer.pathAdded[fullName]) {
8410                     layer.buildFilePaths.push(fullName);
8411                     //For plugins the real path is not knowable, use the name
8412                     //for both module to file and file to module mappings.
8413                     layer.buildPathMap[fullName] = fullName;
8414                     layer.buildFileToModule[fullName] = fullName;
8415                     layer.modulesWithNames[fullName] = true;
8416                     layer.pathAdded[fullName] = true;
8417                 }
8418             } else if (map.url && require._isSupportedBuildUrl(map.url)) {
8419                 //If the url has not been added to the layer yet, and it
8420                 //is from an actual file that was loaded, add it now.
8421                 url = normalizeUrlWithBase(context, map.fullName, map.url);
8422                 if (!layer.pathAdded[url] && layer.buildPathMap[fullName]) {
8423                     //Remember the list of dependencies for this layer.
8424                     layer.buildFilePaths.push(url);
8425                     layer.pathAdded[url] = true;
8426                 }
8427             }
8428         };
8429
8430         //Called by output of the parse() function, when a file does not
8431         //explicitly call define, probably just require, but the parse()
8432         //function normalizes on define() for dependency mapping and file
8433         //ordering works correctly.
8434         require.needsDefine = function (moduleName) {
8435             layer.needsDefine[moduleName] = true;
8436         };
8437
8438         //Marks module has having a name, and optionally executes the
8439         //callback, but only if it meets certain criteria.
8440         require.execCb = function (name, cb, args, exports) {
8441             if (!layer.needsDefine[name]) {
8442                 layer.modulesWithNames[name] = true;
8443             }
8444             if (cb.__requireJsBuild || layer.context.needFullExec[name]) {
8445                 return cb.apply(exports, args);
8446             }
8447             return undefined;
8448         };
8449     };
8450 });
8451 /**
8452  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
8453  * Available via the MIT or new BSD license.
8454  * see: http://github.com/jrburke/requirejs for details
8455  */
8456
8457 /*jslint plusplus: false, regexp: false, strict: false */
8458 /*global define: false, console: false */
8459
8460 define('commonJs', ['env!env/file', 'uglifyjs/index'], function (file, uglify) {
8461     var commonJs = {
8462         depRegExp: /require\s*\(\s*["']([\w-_\.\/]+)["']\s*\)/g,
8463
8464         //Set this to false in non-rhino environments. If rhino, then it uses
8465         //rhino's decompiler to remove comments before looking for require() calls,
8466         //otherwise, it will use a crude regexp approach to remove comments. The
8467         //rhino way is more robust, but he regexp is more portable across environments.
8468         useRhino: true,
8469
8470         //Set to false if you do not want this file to log. Useful in environments
8471         //like node where you want the work to happen without noise.
8472         useLog: true,
8473
8474         convertDir: function (commonJsPath, savePath) {
8475             var fileList, i,
8476                 jsFileRegExp = /\.js$/,
8477                 fileName, convertedFileName, fileContents;
8478
8479             //Get list of files to convert.
8480             fileList = file.getFilteredFileList(commonJsPath, /\w/, true);
8481
8482             //Normalize on front slashes and make sure the paths do not end in a slash.
8483             commonJsPath = commonJsPath.replace(/\\/g, "/");
8484             savePath = savePath.replace(/\\/g, "/");
8485             if (commonJsPath.charAt(commonJsPath.length - 1) === "/") {
8486                 commonJsPath = commonJsPath.substring(0, commonJsPath.length - 1);
8487             }
8488             if (savePath.charAt(savePath.length - 1) === "/") {
8489                 savePath = savePath.substring(0, savePath.length - 1);
8490             }
8491
8492             //Cycle through all the JS files and convert them.
8493             if (!fileList || !fileList.length) {
8494                 if (commonJs.useLog) {
8495                     if (commonJsPath === "convert") {
8496                         //A request just to convert one file.
8497                         console.log('\n\n' + commonJs.convert(savePath, file.readFile(savePath)));
8498                     } else {
8499                         console.log("No files to convert in directory: " + commonJsPath);
8500                     }
8501                 }
8502             } else {
8503                 for (i = 0; (fileName = fileList[i]); i++) {
8504                     convertedFileName = fileName.replace(commonJsPath, savePath);
8505
8506                     //Handle JS files.
8507                     if (jsFileRegExp.test(fileName)) {
8508                         fileContents = file.readFile(fileName);
8509                         fileContents = commonJs.convert(fileName, fileContents);
8510                         file.saveUtf8File(convertedFileName, fileContents);
8511                     } else {
8512                         //Just copy the file over.
8513                         file.copyFile(fileName, convertedFileName, true);
8514                     }
8515                 }
8516             }
8517         },
8518
8519         /**
8520          * Removes the comments from a string.
8521          *
8522          * @param {String} fileContents
8523          * @param {String} fileName mostly used for informative reasons if an error.
8524          *
8525          * @returns {String} a string of JS with comments removed.
8526          */
8527         removeComments: function (fileContents, fileName) {
8528             //Uglify's ast generation removes comments, so just convert to ast,
8529             //then back to source code to get rid of comments.
8530             return uglify.uglify.gen_code(uglify.parser.parse(fileContents), true);
8531         },
8532
8533         /**
8534          * Regexp for testing if there is already a require.def call in the file,
8535          * in which case do not try to convert it.
8536          */
8537         defRegExp: /define\s*\(\s*("|'|\[|function)/,
8538
8539         /**
8540          * Regexp for testing if there is a require([]) or require(function(){})
8541          * call, indicating the file is already in requirejs syntax.
8542          */
8543         rjsRegExp: /require\s*\(\s*(\[|function)/,
8544
8545         /**
8546          * Does the actual file conversion.
8547          *
8548          * @param {String} fileName the name of the file.
8549          *
8550          * @param {String} fileContents the contents of a file :)
8551          *
8552          * @param {Boolean} skipDeps if true, require("") dependencies
8553          * will not be searched, but the contents will just be wrapped in the
8554          * standard require, exports, module dependencies. Only usable in sync
8555          * environments like Node where the require("") calls can be resolved on
8556          * the fly.
8557          *
8558          * @returns {String} the converted contents
8559          */
8560         convert: function (fileName, fileContents, skipDeps) {
8561             //Strip out comments.
8562             try {
8563                 var deps = [], depName, match,
8564                     //Remove comments
8565                     tempContents = commonJs.removeComments(fileContents, fileName);
8566
8567                 //First see if the module is not already RequireJS-formatted.
8568                 if (commonJs.defRegExp.test(tempContents) || commonJs.rjsRegExp.test(tempContents)) {
8569                     return fileContents;
8570                 }
8571
8572                 //Reset the regexp to start at beginning of file. Do this
8573                 //since the regexp is reused across files.
8574                 commonJs.depRegExp.lastIndex = 0;
8575
8576                 if (!skipDeps) {
8577                     //Find dependencies in the code that was not in comments.
8578                     while ((match = commonJs.depRegExp.exec(tempContents))) {
8579                         depName = match[1];
8580                         if (depName) {
8581                             deps.push('"' + depName + '"');
8582                         }
8583                     }
8584                 }
8585
8586                 //Construct the wrapper boilerplate.
8587                 fileContents = 'define(["require", "exports", "module"' +
8588                        (deps.length ? ', ' + deps.join(",") : '') + '], ' +
8589                        'function(require, exports, module) {\n' +
8590                        fileContents +
8591                        '\n});\n';
8592             } catch (e) {
8593                 console.log("COULD NOT CONVERT: " + fileName + ", so skipping it. Error was: " + e);
8594                 return fileContents;
8595             }
8596
8597             return fileContents;
8598         }
8599     };
8600
8601     return commonJs;
8602 });
8603 /**
8604  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
8605  * Available via the MIT or new BSD license.
8606  * see: http://github.com/jrburke/requirejs for details
8607  */
8608
8609 /*jslint plusplus: true, nomen: true  */
8610 /*global define, require */
8611
8612
8613 define('build', [ 'lang', 'logger', 'env!env/file', 'parse', 'optimize', 'pragma',
8614          'env!env/load', 'requirePatch'],
8615 function (lang,   logger,   file,          parse,    optimize,   pragma,
8616           load,           requirePatch) {
8617     'use strict';
8618
8619     var build, buildBaseConfig,
8620         endsWithSemiColonRegExp = /;\s*$/;
8621
8622     buildBaseConfig = {
8623             appDir: "",
8624             pragmas: {},
8625             paths: {},
8626             optimize: "uglify",
8627             optimizeCss: "standard.keepLines",
8628             inlineText: true,
8629             isBuild: true,
8630             optimizeAllPluginResources: false,
8631             findNestedDependencies: false,
8632             preserveLicenseComments: true,
8633             //By default, all files/directories are copied, unless
8634             //they match this regexp, by default just excludes .folders
8635             dirExclusionRegExp: file.dirExclusionRegExp
8636         };
8637
8638     /**
8639      * Some JS may not be valid if concatenated with other JS, in particular
8640      * the style of omitting semicolons and rely on ASI. Add a semicolon in
8641      * those cases.
8642      */
8643     function addSemiColon(text) {
8644         if (endsWithSemiColonRegExp.test(text)) {
8645             return text;
8646         } else {
8647             return text + ";";
8648         }
8649     }
8650
8651     /**
8652      * If the path looks like an URL, throw an error. This is to prevent
8653      * people from using URLs with protocols in the build config, since
8654      * the optimizer is not set up to do network access. However, be
8655      * sure to allow absolute paths on Windows, like C:\directory.
8656      */
8657     function disallowUrls(path) {
8658         if ((path.indexOf('://') !== -1 || path.indexOf('//') === 0) && path !== 'empty:') {
8659             throw new Error('Path is not supported: ' + path +
8660                             '\nOptimizer can only handle' +
8661                             ' local paths. Download the locally if necessary' +
8662                             ' and update the config to use a local path.\n' +
8663                             'http://requirejs.org/docs/errors.html#pathnotsupported');
8664         }
8665     }
8666
8667     function endsWithSlash(dirName) {
8668         if (dirName.charAt(dirName.length - 1) !== "/") {
8669             dirName += "/";
8670         }
8671         disallowUrls(dirName);
8672         return dirName;
8673     }
8674
8675     //Method used by plugin writeFile calls, defined up here to avoid
8676     //jslint warning about "making a function in a loop".
8677     function makeWriteFile(anonDefRegExp, namespaceWithDot, layer) {
8678         function writeFile(name, contents) {
8679             logger.trace('Saving plugin-optimized file: ' + name);
8680             file.saveUtf8File(name, contents);
8681         }
8682
8683         writeFile.asModule = function (moduleName, fileName, contents) {
8684             writeFile(fileName,
8685                 build.toTransport(anonDefRegExp, namespaceWithDot, moduleName, fileName, contents, layer));
8686         };
8687
8688         return writeFile;
8689     }
8690
8691     /**
8692      * Main API entry point into the build. The args argument can either be
8693      * an array of arguments (like the onese passed on a command-line),
8694      * or it can be a JavaScript object that has the format of a build profile
8695      * file.
8696      *
8697      * If it is an object, then in addition to the normal properties allowed in
8698      * a build profile file, the object should contain one other property:
8699      *
8700      * The object could also contain a "buildFile" property, which is a string
8701      * that is the file path to a build profile that contains the rest
8702      * of the build profile directives.
8703      *
8704      * This function does not return a status, it should throw an error if
8705      * there is a problem completing the build.
8706      */
8707     build = function (args) {
8708         var buildFile, cmdConfig;
8709
8710         if (!args || lang.isArray(args)) {
8711             if (!args || args.length < 1) {
8712                 logger.error("build.js buildProfile.js\n" +
8713                       "where buildProfile.js is the name of the build file (see example.build.js for hints on how to make a build file).");
8714                 return undefined;
8715             }
8716
8717             //Next args can include a build file path as well as other build args.
8718             //build file path comes first. If it does not contain an = then it is
8719             //a build file path. Otherwise, just all build args.
8720             if (args[0].indexOf("=") === -1) {
8721                 buildFile = args[0];
8722                 args.splice(0, 1);
8723             }
8724
8725             //Remaining args are options to the build
8726             cmdConfig = build.convertArrayToObject(args);
8727             cmdConfig.buildFile = buildFile;
8728         } else {
8729             cmdConfig = args;
8730         }
8731
8732         return build._run(cmdConfig);
8733     };
8734
8735     build._run = function (cmdConfig) {
8736         var buildFileContents = "",
8737             pluginCollector = {},
8738             buildPaths, fileName, fileNames,
8739             prop, paths, i,
8740             baseConfig, config,
8741             modules, builtModule, srcPath, buildContext,
8742             destPath, moduleName, moduleMap, parentModuleMap, context,
8743             resources, resource, pluginProcessed = {}, plugin;
8744
8745         //Can now run the patches to require.js to allow it to be used for
8746         //build generation. Do it here instead of at the top of the module
8747         //because we want normal require behavior to load the build tool
8748         //then want to switch to build mode.
8749         requirePatch();
8750
8751         config = build.createConfig(cmdConfig);
8752         paths = config.paths;
8753
8754         if (config.logLevel) {
8755             logger.logLevel(config.logLevel);
8756         }
8757
8758         if (!config.out && !config.cssIn) {
8759             //This is not just a one-off file build but a full build profile, with
8760             //lots of files to process.
8761
8762             //First copy all the baseUrl content
8763             file.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true);
8764
8765             //Adjust baseUrl if config.appDir is in play, and set up build output paths.
8766             buildPaths = {};
8767             if (config.appDir) {
8768                 //All the paths should be inside the appDir, so just adjust
8769                 //the paths to use the dirBaseUrl
8770                 for (prop in paths) {
8771                     if (paths.hasOwnProperty(prop)) {
8772                         buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl);
8773                     }
8774                 }
8775             } else {
8776                 //If no appDir, then make sure to copy the other paths to this directory.
8777                 for (prop in paths) {
8778                     if (paths.hasOwnProperty(prop)) {
8779                         //Set up build path for each path prefix.
8780                         buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop.replace(/\./g, "/");
8781
8782                         //Make sure source path is fully formed with baseUrl,
8783                         //if it is a relative URL.
8784                         srcPath = paths[prop];
8785                         if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) {
8786                             srcPath = config.baseUrl + srcPath;
8787                         }
8788
8789                         destPath = config.dirBaseUrl + buildPaths[prop];
8790
8791                         //Skip empty: paths
8792                         if (srcPath !== 'empty:') {
8793                             //If the srcPath is a directory, copy the whole directory.
8794                             if (file.exists(srcPath) && file.isDirectory(srcPath)) {
8795                                 //Copy files to build area. Copy all files (the /\w/ regexp)
8796                                 file.copyDir(srcPath, destPath, /\w/, true);
8797                             } else {
8798                                 //Try a .js extension
8799                                 srcPath += '.js';
8800                                 destPath += '.js';
8801                                 file.copyFile(srcPath, destPath);
8802                             }
8803                         }
8804                     }
8805                 }
8806             }
8807         }
8808
8809         //Figure out source file location for each module layer. Do this by seeding require
8810         //with source area configuration. This is needed so that later the module layers
8811         //can be manually copied over to the source area, since the build may be
8812         //require multiple times and the above copyDir call only copies newer files.
8813         require({
8814             baseUrl: config.baseUrl,
8815             paths: paths,
8816             packagePaths: config.packagePaths,
8817             packages: config.packages
8818         });
8819         buildContext = require.s.contexts._;
8820         modules = config.modules;
8821
8822         if (modules) {
8823             modules.forEach(function (module) {
8824                 if (module.name) {
8825                     module._sourcePath = buildContext.nameToUrl(module.name);
8826                     //If the module does not exist, and this is not a "new" module layer,
8827                     //as indicated by a true "create" property on the module, and
8828                     //it is not a plugin-loaded resource, then throw an error.
8829                     if (!file.exists(module._sourcePath) && !module.create &&
8830                         module.name.indexOf('!') === -1) {
8831                         throw new Error("ERROR: module path does not exist: " +
8832                                         module._sourcePath + " for module named: " + module.name +
8833                                         ". Path is relative to: " + file.absPath('.'));
8834                     }
8835                 }
8836             });
8837         }
8838
8839         if (config.out) {
8840             //Just set up the _buildPath for the module layer.
8841             require(config);
8842             if (!config.cssIn) {
8843                 config.modules[0]._buildPath = config.out;
8844             }
8845         } else if (!config.cssIn) {
8846             //Now set up the config for require to use the build area, and calculate the
8847             //build file locations. Pass along any config info too.
8848             baseConfig = {
8849                 baseUrl: config.dirBaseUrl,
8850                 paths: buildPaths
8851             };
8852
8853             lang.mixin(baseConfig, config);
8854             require(baseConfig);
8855
8856             if (modules) {
8857                 modules.forEach(function (module) {
8858                     if (module.name) {
8859                         module._buildPath = buildContext.nameToUrl(module.name, null);
8860                         if (!module.create) {
8861                             file.copyFile(module._sourcePath, module._buildPath);
8862                         }
8863                     }
8864                 });
8865             }
8866         }
8867
8868         //Run CSS optimizations before doing JS module tracing, to allow
8869         //things like text loader plugins loading CSS to get the optimized
8870         //CSS.
8871         if (config.optimizeCss && config.optimizeCss !== "none" && config.dir) {
8872             buildFileContents += optimize.css(config.dir, config);
8873         }
8874
8875         if (modules) {
8876             //For each module layer, call require to calculate dependencies.
8877             modules.forEach(function (module) {
8878                 module.layer = build.traceDependencies(module, config);
8879             });
8880
8881             //Now build up shadow layers for anything that should be excluded.
8882             //Do this after tracing dependencies for each module, in case one
8883             //of those modules end up being one of the excluded values.
8884             modules.forEach(function (module) {
8885                 if (module.exclude) {
8886                     module.excludeLayers = [];
8887                     module.exclude.forEach(function (exclude, i) {
8888                         //See if it is already in the list of modules.
8889                         //If not trace dependencies for it.
8890                         module.excludeLayers[i] = build.findBuildModule(exclude, modules) ||
8891                                                  {layer: build.traceDependencies({name: exclude}, config)};
8892                     });
8893                 }
8894             });
8895
8896             modules.forEach(function (module) {
8897                 if (module.exclude) {
8898                     //module.exclude is an array of module names. For each one,
8899                     //get the nested dependencies for it via a matching entry
8900                     //in the module.excludeLayers array.
8901                     module.exclude.forEach(function (excludeModule, i) {
8902                         var excludeLayer = module.excludeLayers[i].layer, map = excludeLayer.buildPathMap, prop;
8903                         for (prop in map) {
8904                             if (map.hasOwnProperty(prop)) {
8905                                 build.removeModulePath(prop, map[prop], module.layer);
8906                             }
8907                         }
8908                     });
8909                 }
8910                 if (module.excludeShallow) {
8911                     //module.excludeShallow is an array of module names.
8912                     //shallow exclusions are just that module itself, and not
8913                     //its nested dependencies.
8914                     module.excludeShallow.forEach(function (excludeShallowModule) {
8915                         var path = module.layer.buildPathMap[excludeShallowModule];
8916                         if (path) {
8917                             build.removeModulePath(excludeShallowModule, path, module.layer);
8918                         }
8919                     });
8920                 }
8921
8922                 //Flatten them and collect the build output for each module.
8923                 builtModule = build.flattenModule(module, module.layer, config);
8924
8925                 //Save it to a temp file for now, in case there are other layers that
8926                 //contain optimized content that should not be included in later
8927                 //layer optimizations. See issue #56.
8928                 file.saveUtf8File(module._buildPath + '-temp', builtModule.text);
8929                 buildFileContents += builtModule.buildText;
8930             });
8931
8932             //Now move the build layers to their final position.
8933             modules.forEach(function (module) {
8934                 var finalPath = module._buildPath;
8935                 if (file.exists(finalPath)) {
8936                     file.deleteFile(finalPath);
8937                 }
8938                 file.renameFile(finalPath + '-temp', finalPath);
8939             });
8940         }
8941
8942         //Do other optimizations.
8943         if (config.out && !config.cssIn) {
8944             //Just need to worry about one JS file.
8945             fileName = config.modules[0]._buildPath;
8946             optimize.jsFile(fileName, fileName, config);
8947         } else if (!config.cssIn) {
8948             //Normal optimizations across modules.
8949
8950             //JS optimizations.
8951             fileNames = file.getFilteredFileList(config.dir, /\.js$/, true);
8952             for (i = 0; (fileName = fileNames[i]); i++) {
8953                 //Generate the module name from the config.dir root.
8954                 moduleName = fileName.replace(config.dir, '');
8955                 //Get rid of the extension
8956                 moduleName = moduleName.substring(0, moduleName.length - 3);
8957                 optimize.jsFile(fileName, fileName, config, moduleName, pluginCollector);
8958             }
8959
8960             //Normalize all the plugin resources.
8961             context = require.s.contexts._;
8962
8963             for (moduleName in pluginCollector) {
8964                 if (pluginCollector.hasOwnProperty(moduleName)) {
8965                     parentModuleMap = context.makeModuleMap(moduleName);
8966                     resources = pluginCollector[moduleName];
8967                     for (i = 0; (resource = resources[i]); i++) {
8968                         moduleMap = context.makeModuleMap(resource, parentModuleMap);
8969                         if (!context.plugins[moduleMap.prefix]) {
8970                             //Set the value in context.plugins so it
8971                             //will be evaluated as a full plugin.
8972                             context.plugins[moduleMap.prefix] = true;
8973
8974                             //Do not bother if the plugin is not available.
8975                             if (!file.exists(require.toUrl(moduleMap.prefix + '.js'))) {
8976                                 continue;
8977                             }
8978
8979                             //Rely on the require in the build environment
8980                             //to be synchronous
8981                             context.require([moduleMap.prefix]);
8982
8983                             //Now that the plugin is loaded, redo the moduleMap
8984                             //since the plugin will need to normalize part of the path.
8985                             moduleMap = context.makeModuleMap(resource, parentModuleMap);
8986                         }
8987
8988                         //Only bother with plugin resources that can be handled
8989                         //processed by the plugin, via support of the writeFile
8990                         //method.
8991                         if (!pluginProcessed[moduleMap.fullName]) {
8992                             //Only do the work if the plugin was really loaded.
8993                             //Using an internal access because the file may
8994                             //not really be loaded.
8995                             plugin = context.defined[moduleMap.prefix];
8996                             if (plugin && plugin.writeFile) {
8997                                 plugin.writeFile(
8998                                     moduleMap.prefix,
8999                                     moduleMap.name,
9000                                     require,
9001                                     makeWriteFile(
9002                                         config.anonDefRegExp,
9003                                         config.namespaceWithDot
9004                                     ),
9005                                     context.config
9006                                 );
9007                             }
9008
9009                             pluginProcessed[moduleMap.fullName] = true;
9010                         }
9011                     }
9012
9013                 }
9014             }
9015
9016             //console.log('PLUGIN COLLECTOR: ' + JSON.stringify(pluginCollector, null, "  "));
9017
9018
9019             //All module layers are done, write out the build.txt file.
9020             file.saveUtf8File(config.dir + "build.txt", buildFileContents);
9021         }
9022
9023         //If just have one CSS file to optimize, do that here.
9024         if (config.cssIn) {
9025             buildFileContents += optimize.cssFile(config.cssIn, config.out, config);
9026         }
9027
9028         //Print out what was built into which layers.
9029         if (buildFileContents) {
9030             logger.info(buildFileContents);
9031             return buildFileContents;
9032         }
9033
9034         return '';
9035     };
9036
9037     /**
9038      * Converts command line args like "paths.foo=../some/path"
9039      * result.paths = { foo: '../some/path' } where prop = paths,
9040      * name = paths.foo and value = ../some/path, so it assumes the
9041      * name=value splitting has already happened.
9042      */
9043     function stringDotToObj(result, prop, name, value) {
9044         if (!result[prop]) {
9045             result[prop] = {};
9046         }
9047         name = name.substring((prop + '.').length, name.length);
9048         result[prop][name] = value;
9049     }
9050
9051     //Used by convertArrayToObject to convert some things from prop.name=value
9052     //to a prop: { name: value}
9053     build.dotProps = [
9054         'paths.',
9055         'wrap.',
9056         'pragmas.',
9057         'pragmasOnSave.',
9058         'has.',
9059         'hasOnSave.',
9060         'wrap.',
9061         'uglify.',
9062         'closure.'
9063     ];
9064
9065     build.hasDotPropMatch = function (prop) {
9066         return build.dotProps.some(function (dotProp) {
9067             return prop.indexOf(dotProp) === 0;
9068         });
9069     };
9070
9071     /**
9072      * Converts an array that has String members of "name=value"
9073      * into an object, where the properties on the object are the names in the array.
9074      * Also converts the strings "true" and "false" to booleans for the values.
9075      * member name/value pairs, and converts some comma-separated lists into
9076      * arrays.
9077      * @param {Array} ary
9078      */
9079     build.convertArrayToObject = function (ary) {
9080         var result = {}, i, separatorIndex, prop, value,
9081             needArray = {
9082                 "include": true,
9083                 "exclude": true,
9084                 "excludeShallow": true
9085             };
9086
9087         for (i = 0; i < ary.length; i++) {
9088             separatorIndex = ary[i].indexOf("=");
9089             if (separatorIndex === -1) {
9090                 throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value";
9091             }
9092
9093             value = ary[i].substring(separatorIndex + 1, ary[i].length);
9094             if (value === "true") {
9095                 value = true;
9096             } else if (value === "false") {
9097                 value = false;
9098             }
9099
9100             prop = ary[i].substring(0, separatorIndex);
9101
9102             //Convert to array if necessary
9103             if (needArray[prop]) {
9104                 value = value.split(",");
9105             }
9106
9107             if (build.hasDotPropMatch(prop)) {
9108                 stringDotToObj(result, prop.split('.')[0], prop, value);
9109             } else {
9110                 result[prop] = value;
9111             }
9112         }
9113         return result; //Object
9114     };
9115
9116     build.makeAbsPath = function (path, absFilePath) {
9117         //Add abspath if necessary. If path starts with a slash or has a colon,
9118         //then already is an abolute path.
9119         if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) {
9120             path = absFilePath +
9121                    (absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') +
9122                    path;
9123             path = file.normalize(path);
9124         }
9125         return path.replace(lang.backSlashRegExp, '/');
9126     };
9127
9128     build.makeAbsObject = function (props, obj, absFilePath) {
9129         var i, prop;
9130         if (obj) {
9131             for (i = 0; (prop = props[i]); i++) {
9132                 if (obj.hasOwnProperty(prop)) {
9133                     obj[prop] = build.makeAbsPath(obj[prop], absFilePath);
9134                 }
9135             }
9136         }
9137     };
9138
9139     /**
9140      * For any path in a possible config, make it absolute relative
9141      * to the absFilePath passed in.
9142      */
9143     build.makeAbsConfig = function (config, absFilePath) {
9144         var props, prop, i;
9145
9146         props = ["appDir", "dir", "baseUrl"];
9147         for (i = 0; (prop = props[i]); i++) {
9148             if (config[prop]) {
9149                 //Add abspath if necessary, make sure these paths end in
9150                 //slashes
9151                 if (prop === "baseUrl") {
9152                     config.originalBaseUrl = config.baseUrl;
9153                     if (config.appDir) {
9154                         //If baseUrl with an appDir, the baseUrl is relative to
9155                         //the appDir, *not* the absFilePath. appDir and dir are
9156                         //made absolute before baseUrl, so this will work.
9157                         config.baseUrl = build.makeAbsPath(config.originalBaseUrl, config.appDir);
9158                     } else {
9159                         //The dir output baseUrl is same as regular baseUrl, both
9160                         //relative to the absFilePath.
9161                         config.baseUrl = build.makeAbsPath(config[prop], absFilePath);
9162                     }
9163                 } else {
9164                     config[prop] = build.makeAbsPath(config[prop], absFilePath);
9165                 }
9166
9167                 config[prop] = endsWithSlash(config[prop]);
9168             }
9169         }
9170
9171         //Do not allow URLs for paths resources.
9172         if (config.paths) {
9173             for (prop in config.paths) {
9174                 if (config.paths.hasOwnProperty(prop)) {
9175                     config.paths[prop] = build.makeAbsPath(config.paths[prop],
9176                                               (config.baseUrl || absFilePath));
9177                 }
9178             }
9179         }
9180
9181         build.makeAbsObject(["out", "cssIn"], config, absFilePath);
9182         build.makeAbsObject(["startFile", "endFile"], config.wrap, absFilePath);
9183     };
9184
9185     build.nestedMix = {
9186         paths: true,
9187         has: true,
9188         hasOnSave: true,
9189         pragmas: true,
9190         pragmasOnSave: true
9191     };
9192
9193     /**
9194      * Mixes additional source config into target config, and merges some
9195      * nested config, like paths, correctly.
9196      */
9197     function mixConfig(target, source) {
9198         var prop, value;
9199
9200         for (prop in source) {
9201             if (source.hasOwnProperty(prop)) {
9202                 //If the value of the property is a plain object, then
9203                 //allow a one-level-deep mixing of it.
9204                 value = source[prop];
9205                 if (typeof value === 'object' && value &&
9206                     !lang.isArray(value) && !lang.isFunction(value) &&
9207                     !lang.isRegExp(value)) {
9208                     target[prop] = lang.mixin({}, target[prop], value, true);
9209                 } else {
9210                     target[prop] = value;
9211                 }
9212             }
9213         }
9214     }
9215
9216     /**
9217      * Creates a config object for an optimization build.
9218      * It will also read the build profile if it is available, to create
9219      * the configuration.
9220      *
9221      * @param {Object} cfg config options that take priority
9222      * over defaults and ones in the build file. These options could
9223      * be from a command line, for instance.
9224      *
9225      * @param {Object} the created config object.
9226      */
9227     build.createConfig = function (cfg) {
9228         /*jslint evil: true */
9229         var config = {}, buildFileContents, buildFileConfig, mainConfig,
9230             mainConfigFile, prop, buildFile, absFilePath;
9231
9232         //Make sure all paths are relative to current directory.
9233         absFilePath = file.absPath('.');
9234         build.makeAbsConfig(cfg, absFilePath);
9235         build.makeAbsConfig(buildBaseConfig, absFilePath);
9236
9237         lang.mixin(config, buildBaseConfig);
9238         lang.mixin(config, cfg, true);
9239
9240         if (config.buildFile) {
9241             //A build file exists, load it to get more config.
9242             buildFile = file.absPath(config.buildFile);
9243
9244             //Find the build file, and make sure it exists, if this is a build
9245             //that has a build profile, and not just command line args with an in=path
9246             if (!file.exists(buildFile)) {
9247                 throw new Error("ERROR: build file does not exist: " + buildFile);
9248             }
9249
9250             absFilePath = config.baseUrl = file.absPath(file.parent(buildFile));
9251
9252             //Load build file options.
9253             buildFileContents = file.readFile(buildFile);
9254             try {
9255                 buildFileConfig = eval("(" + buildFileContents + ")");
9256                 build.makeAbsConfig(buildFileConfig, absFilePath);
9257
9258                 if (!buildFileConfig.out && !buildFileConfig.dir) {
9259                     buildFileConfig.dir = (buildFileConfig.baseUrl || config.baseUrl) + "/build/";
9260                 }
9261
9262             } catch (e) {
9263                 throw new Error("Build file " + buildFile + " is malformed: " + e);
9264             }
9265         }
9266
9267         mainConfigFile = config.mainConfigFile || (buildFileConfig && buildFileConfig.mainConfigFile);
9268         if (mainConfigFile) {
9269             mainConfigFile = build.makeAbsPath(mainConfigFile, absFilePath);
9270             try {
9271                 mainConfig = parse.findConfig(mainConfigFile, file.readFile(mainConfigFile));
9272             } catch (configError) {
9273                 throw new Error('The config in mainConfigFile ' +
9274                         mainConfigFile +
9275                         ' cannot be used because it cannot be evaluated' +
9276                         ' correctly while running in the optimizer. Try only' +
9277                         ' using a config that is also valid JSON, or do not use' +
9278                         ' mainConfigFile and instead copy the config values needed' +
9279                         ' into a build file or command line arguments given to the optimizer.');
9280             }
9281             if (mainConfig) {
9282                 //If no baseUrl, then use the directory holding the main config.
9283                 if (!mainConfig.baseUrl) {
9284                     mainConfig.baseUrl = mainConfigFile.substring(0, mainConfigFile.lastIndexOf('/'));
9285                 }
9286                 build.makeAbsConfig(mainConfig, mainConfigFile);
9287                 mixConfig(config, mainConfig);
9288             }
9289         }
9290
9291         //Mix in build file config, but only after mainConfig has been mixed in.
9292         if (buildFileConfig) {
9293             mixConfig(config, buildFileConfig);
9294         }
9295
9296         //Re-apply the override config values. Command line
9297         //args should take precedence over build file values.
9298         mixConfig(config, cfg);
9299
9300
9301         //Set final output dir
9302         if (config.hasOwnProperty("baseUrl")) {
9303             if (config.appDir) {
9304                 config.dirBaseUrl = build.makeAbsPath(config.originalBaseUrl, config.dir);
9305             } else {
9306                 config.dirBaseUrl = config.dir || config.baseUrl;
9307             }
9308             //Make sure dirBaseUrl ends in a slash, since it is
9309             //concatenated with other strings.
9310             config.dirBaseUrl = endsWithSlash(config.dirBaseUrl);
9311         }
9312
9313         //Check for errors in config
9314         if (config.cssIn && !config.out) {
9315             throw new Error("ERROR: 'out' option missing.");
9316         }
9317         if (!config.cssIn && !config.baseUrl) {
9318             throw new Error("ERROR: 'baseUrl' option missing.");
9319         }
9320         if (!config.out && !config.dir) {
9321             throw new Error('Missing either an "out" or "dir" config value. ' +
9322                             'If using "appDir" for a full project optimization, ' +
9323                             'use "dir". If you want to optimize to one file, ' +
9324                             'use "out".');
9325         }
9326         if (config.appDir && config.out) {
9327             throw new Error('"appDir" is not compatible with "out". Use "dir" ' +
9328                             'instead. appDir is used to copy whole projects, ' +
9329                             'where "out" is used to just optimize to one file.');
9330         }
9331         if (config.out && config.dir) {
9332             throw new Error('The "out" and "dir" options are incompatible.' +
9333                             ' Use "out" if you are targeting a single file for' +
9334                             ' for optimization, and "dir" if you want the appDir' +
9335                             ' or baseUrl directories optimized.');
9336         }
9337
9338         if ((config.name || config.include) && !config.modules) {
9339             //Just need to build one file, but may be part of a whole appDir/
9340             //baseUrl copy, but specified on the command line, so cannot do
9341             //the modules array setup. So create a modules section in that
9342             //case.
9343             config.modules = [
9344                 {
9345                     name: config.name,
9346                     out: config.out,
9347                     include: config.include,
9348                     exclude: config.exclude,
9349                     excludeShallow: config.excludeShallow
9350                 }
9351             ];
9352         }
9353
9354         if (config.out && !config.cssIn) {
9355             //Just one file to optimize.
9356
9357             //Does not have a build file, so set up some defaults.
9358             //Optimizing CSS should not be allowed, unless explicitly
9359             //asked for on command line. In that case the only task is
9360             //to optimize a CSS file.
9361             if (!cfg.optimizeCss) {
9362                 config.optimizeCss = "none";
9363             }
9364         }
9365
9366         //Do not allow URLs for paths resources.
9367         if (config.paths) {
9368             for (prop in config.paths) {
9369                 if (config.paths.hasOwnProperty(prop)) {
9370                     disallowUrls(config.paths[prop]);
9371                 }
9372             }
9373         }
9374
9375         //Get any wrap text.
9376         try {
9377             if (config.wrap) {
9378                 if (config.wrap === true) {
9379                     //Use default values.
9380                     config.wrap = {
9381                         start: '(function () {',
9382                         end: '}());'
9383                     };
9384                 } else {
9385                     config.wrap.start = config.wrap.start ||
9386                             file.readFile(build.makeAbsPath(config.wrap.startFile, absFilePath));
9387                     config.wrap.end = config.wrap.end ||
9388                             file.readFile(build.makeAbsPath(config.wrap.endFile, absFilePath));
9389                 }
9390             }
9391         } catch (wrapError) {
9392             throw new Error('Malformed wrap config: need both start/end or ' +
9393                             'startFile/endFile: ' + wrapError.toString());
9394         }
9395
9396
9397         //Set up proper info for namespaces and using namespaces in transport
9398         //wrappings.
9399         config.namespaceWithDot = config.namespace ? config.namespace + '.' : '';
9400         config.anonDefRegExp = build.makeAnonDefRegExp(config.namespaceWithDot);
9401
9402         //Do final input verification
9403         if (config.context) {
9404             throw new Error('The build argument "context" is not supported' +
9405                             ' in a build. It should only be used in web' +
9406                             ' pages.');
9407         }
9408
9409         //Set file.fileExclusionRegExp if desired
9410         if ('fileExclusionRegExp' in config) {
9411             if (typeof config.fileExclusionRegExp === "string") {
9412                 file.exclusionRegExp = new RegExp(config.fileExclusionRegExp);
9413             } else {
9414                 file.exclusionRegExp = config.fileExclusionRegExp;
9415             }
9416         } else if ('dirExclusionRegExp' in config) {
9417             //Set file.dirExclusionRegExp if desired, this is the old
9418             //name for fileExclusionRegExp before 1.0.2. Support for backwards
9419             //compatibility
9420             file.exclusionRegExp = config.dirExclusionRegExp;
9421         }
9422
9423         return config;
9424     };
9425
9426     /**
9427      * finds the module being built/optimized with the given moduleName,
9428      * or returns null.
9429      * @param {String} moduleName
9430      * @param {Array} modules
9431      * @returns {Object} the module object from the build profile, or null.
9432      */
9433     build.findBuildModule = function (moduleName, modules) {
9434         var i, module;
9435         for (i = 0; (module = modules[i]); i++) {
9436             if (module.name === moduleName) {
9437                 return module;
9438             }
9439         }
9440         return null;
9441     };
9442
9443     /**
9444      * Removes a module name and path from a layer, if it is supposed to be
9445      * excluded from the layer.
9446      * @param {String} moduleName the name of the module
9447      * @param {String} path the file path for the module
9448      * @param {Object} layer the layer to remove the module/path from
9449      */
9450     build.removeModulePath = function (module, path, layer) {
9451         var index = layer.buildFilePaths.indexOf(path);
9452         if (index !== -1) {
9453             layer.buildFilePaths.splice(index, 1);
9454         }
9455
9456         //Take it out of the specified modules. Specified modules are mostly
9457         //used to find require modifiers.
9458         delete layer.specified[module];
9459     };
9460
9461     /**
9462      * Uses the module build config object to trace the dependencies for the
9463      * given module.
9464      *
9465      * @param {Object} module the module object from the build config info.
9466      * @param {Object} the build config object.
9467      *
9468      * @returns {Object} layer information about what paths and modules should
9469      * be in the flattened module.
9470      */
9471     build.traceDependencies = function (module, config) {
9472         var include, override, layer, context, baseConfig, oldContext;
9473
9474         //Reset some state set up in requirePatch.js, and clean up require's
9475         //current context.
9476         oldContext = require._buildReset();
9477
9478         //Grab the reset layer and context after the reset, but keep the
9479         //old config to reuse in the new context.
9480         baseConfig = oldContext.config;
9481         layer = require._layer;
9482         context = layer.context;
9483
9484         //Put back basic config, use a fresh object for it.
9485         //WARNING: probably not robust for paths and packages/packagePaths,
9486         //since those property's objects can be modified. But for basic
9487         //config clone it works out.
9488         require(lang.delegate(baseConfig));
9489
9490         logger.trace("\nTracing dependencies for: " + (module.name || module.out));
9491         include = module.name && !module.create ? [module.name] : [];
9492         if (module.include) {
9493             include = include.concat(module.include);
9494         }
9495
9496         //If there are overrides to basic config, set that up now.;
9497         if (module.override) {
9498             override = lang.delegate(baseConfig);
9499             lang.mixin(override, module.override, true);
9500             require(override);
9501         }
9502
9503         //Figure out module layer dependencies by calling require to do the work.
9504         require(include);
9505
9506         //Pull out the layer dependencies.
9507         layer.specified = context.specified;
9508
9509         //Reset config
9510         if (module.override) {
9511             require(baseConfig);
9512         }
9513
9514         return layer;
9515     };
9516
9517     /**
9518      * Uses the module build config object to create an flattened version
9519      * of the module, with deep dependencies included.
9520      *
9521      * @param {Object} module the module object from the build config info.
9522      *
9523      * @param {Object} layer the layer object returned from build.traceDependencies.
9524      *
9525      * @param {Object} the build config object.
9526      *
9527      * @returns {Object} with two properties: "text", the text of the flattened
9528      * module, and "buildText", a string of text representing which files were
9529      * included in the flattened module text.
9530      */
9531     build.flattenModule = function (module, layer, config) {
9532         var buildFileContents = "",
9533             namespace = config.namespace ? config.namespace + '.' : '',
9534             context = layer.context,
9535             anonDefRegExp = config.anonDefRegExp,
9536             path, reqIndex, fileContents, currContents,
9537             i, moduleName,
9538             parts, builder, writeApi;
9539
9540         //Use override settings, particularly for pragmas
9541         if (module.override) {
9542             config = lang.delegate(config);
9543             lang.mixin(config, module.override, true);
9544         }
9545
9546         //Start build output for the module.
9547         buildFileContents += "\n" +
9548                              (config.dir ? module._buildPath.replace(config.dir, "") : module._buildPath) +
9549                              "\n----------------\n";
9550
9551         //If there was an existing file with require in it, hoist to the top.
9552         if (layer.existingRequireUrl) {
9553             reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl);
9554             if (reqIndex !== -1) {
9555                 layer.buildFilePaths.splice(reqIndex, 1);
9556                 layer.buildFilePaths.unshift(layer.existingRequireUrl);
9557             }
9558         }
9559
9560         //Write the built module to disk, and build up the build output.
9561         fileContents = "";
9562         for (i = 0; (path = layer.buildFilePaths[i]); i++) {
9563             moduleName = layer.buildFileToModule[path];
9564
9565             //Figure out if the module is a result of a build plugin, and if so,
9566             //then delegate to that plugin.
9567             parts = context.makeModuleMap(moduleName);
9568             builder = parts.prefix && context.defined[parts.prefix];
9569             if (builder) {
9570                 if (builder.write) {
9571                     writeApi = function (input) {
9572                         fileContents += "\n" + addSemiColon(input);
9573                         if (config.onBuildWrite) {
9574                             fileContents = config.onBuildWrite(moduleName, path, fileContents);
9575                         }
9576                     };
9577                     writeApi.asModule = function (moduleName, input) {
9578                         fileContents += "\n" +
9579                                         addSemiColon(
9580                                             build.toTransport(anonDefRegExp, namespace, moduleName, path, input, layer));
9581                         if (config.onBuildWrite) {
9582                             fileContents = config.onBuildWrite(moduleName, path, fileContents);
9583                         }
9584                     };
9585                     builder.write(parts.prefix, parts.name, writeApi);
9586                 }
9587             } else {
9588                 currContents = file.readFile(path);
9589
9590                 if (config.onBuildRead) {
9591                     currContents = config.onBuildRead(moduleName, path, currContents);
9592                 }
9593
9594                 if (config.namespace) {
9595                     currContents = pragma.namespace(currContents, config.namespace);
9596                 }
9597
9598                 currContents = build.toTransport(anonDefRegExp, namespace, moduleName, path, currContents, layer);
9599
9600                 if (config.onBuildWrite) {
9601                     currContents = config.onBuildWrite(moduleName, path, currContents);
9602                 }
9603
9604                 //Semicolon is for files that are not well formed when
9605                 //concatenated with other content.
9606                 fileContents += "\n" + addSemiColon(currContents);
9607             }
9608
9609             buildFileContents += path.replace(config.dir, "") + "\n";
9610             //Some files may not have declared a require module, and if so,
9611             //put in a placeholder call so the require does not try to load them
9612             //after the module is processed.
9613             //If we have a name, but no defined module, then add in the placeholder.
9614             if (moduleName && !layer.modulesWithNames[moduleName] && !config.skipModuleInsertion) {
9615                 //If including jquery, register the module correctly, otherwise
9616                 //register an empty function. For jquery, make sure jQuery is
9617                 //a real object, and perhaps not some other file mapping, like
9618                 //to zepto.
9619                 if (moduleName === 'jquery') {
9620                     fileContents += '\n(function () {\n' +
9621                                    'var jq = typeof jQuery !== "undefined" && jQuery;\n' +
9622                                    namespace +
9623                                    'define("jquery", [], function () { return jq; });\n' +
9624                                    '}());\n';
9625                 } else {
9626                     fileContents += '\n' + namespace + 'define("' + moduleName + '", function(){});\n';
9627                 }
9628             }
9629         }
9630
9631         return {
9632             text: config.wrap ?
9633                     config.wrap.start + fileContents + config.wrap.end :
9634                     fileContents,
9635             buildText: buildFileContents
9636         };
9637     };
9638
9639     /**
9640      * Creates the regexp to find anonymous defines.
9641      * @param {String} namespace an optional namespace to use. The namespace
9642      * should *include* a trailing dot. So a valid value would be 'foo.'
9643      * @returns {RegExp}
9644      */
9645     build.makeAnonDefRegExp = function (namespace) {
9646         //This regexp is not bullet-proof, and it has one optional part to
9647         //avoid issues with some Dojo transition modules that use a
9648         //define(\n//begin v1.x content
9649         //for a comment.
9650         return new RegExp('(^|[^\\.])(' + (namespace || '').replace(/\./g, '\\.') +
9651                           'define|define)\\s*\\(\\s*(\\/\\/[^\\n\\r]*[\\r\\n])?(\\[|function|[\\w\\d_\\-\\$]+\\s*\\)|\\{|["\']([^"\']+)["\'])(\\s*,\\s*f)?');
9652     };
9653
9654     build.leadingCommaRegExp = /^\s*,/;
9655
9656     build.toTransport = function (anonDefRegExp, namespace, moduleName, path, contents, layer) {
9657
9658         //If anonymous module, insert the module name.
9659         return contents.replace(anonDefRegExp, function (match, start, callName, possibleComment, suffix, namedModule, namedFuncStart) {
9660             //A named module with either listed dependencies or an object
9661             //literal for a value. Skip it. If named module, only want ones
9662             //whose next argument is a function literal to scan for
9663             //require('') dependecies.
9664             if (namedModule && !namedFuncStart) {
9665                 return match;
9666             }
9667
9668             //Only mark this module as having a name if not a named module,
9669             //or if a named module and the name matches expectations.
9670             if (layer && (!namedModule || namedModule === moduleName)) {
9671                 layer.modulesWithNames[moduleName] = true;
9672             }
9673
9674             var deps = null;
9675
9676             //Look for CommonJS require calls inside the function if this is
9677             //an anonymous define call that just has a function registered.
9678             //Also look if a named define function but has a factory function
9679             //as the second arg that should be scanned for dependencies.
9680             if (suffix.indexOf('f') !== -1 || (namedModule)) {
9681                 deps = parse.getAnonDeps(path, contents);
9682
9683                 if (deps.length) {
9684                     deps = deps.map(function (dep) {
9685                         return "'" + dep + "'";
9686                     });
9687                 } else {
9688                     deps = [];
9689                 }
9690             }
9691
9692             return start + namespace + "define('" + (namedModule || moduleName) + "'," +
9693                    (deps ? ('[' + deps.toString() + '],') : '') +
9694                    (namedModule ? namedFuncStart.replace(build.leadingCommaRegExp, '') : suffix);
9695         });
9696
9697     };
9698
9699     return build;
9700 });
9701
9702     }
9703
9704
9705     /**
9706      * Sets the default baseUrl for requirejs to be directory of top level
9707      * script.
9708      */
9709     function setBaseUrl(fileName) {
9710         //Use the file name's directory as the baseUrl if available.
9711         dir = fileName.replace(/\\/g, '/');
9712         if (dir.indexOf('/') !== -1) {
9713             dir = dir.split('/');
9714             dir.pop();
9715             dir = dir.join('/');
9716             exec("require({baseUrl: '" + dir + "'});");
9717         }
9718     }
9719
9720     //If in Node, and included via a require('requirejs'), just export and
9721     //THROW IT ON THE GROUND!
9722     if (env === 'node' && reqMain !== module) {
9723         setBaseUrl(path.resolve(reqMain ? reqMain.filename : '.'));
9724
9725         //Create a method that will run the optimzer given an object
9726         //config.
9727         requirejs.optimize = function (config, callback) {
9728             if (!loadedOptimizedLib) {
9729                 loadLib();
9730                 loadedOptimizedLib = true;
9731             }
9732
9733             //Create the function that will be called once build modules
9734             //have been loaded.
9735             var runBuild = function (build, logger) {
9736                 //Make sure config has a log level, and if not,
9737                 //make it "silent" by default.
9738                 config.logLevel = config.hasOwnProperty('logLevel') ?
9739                                   config.logLevel : logger.SILENT;
9740
9741                 var result = build(config);
9742
9743                 //Reset build internals on each run.
9744                 requirejs._buildReset();
9745
9746                 if (callback) {
9747                     callback(result);
9748                 }
9749             };
9750
9751             //Enable execution of this callback in a build setting.
9752             //Normally, once requirePatch is run, by default it will
9753             //not execute callbacks, unless this property is set on
9754             //the callback.
9755             runBuild.__requireJsBuild = true;
9756
9757             requirejs({
9758                 context: 'build'
9759             }, ['build', 'logger'], runBuild);
9760         };
9761
9762         requirejs.tools = {
9763             useLib: function (contextName, callback) {
9764                 if (!callback) {
9765                     callback = contextName;
9766                     contextName = 'uselib';
9767                 }
9768
9769                 if (!useLibLoaded[contextName]) {
9770                     loadLib();
9771                     useLibLoaded[contextName] = true;
9772                 }
9773
9774                 var req = requirejs({
9775                     context: contextName,
9776                     requireLoad: requirejsVars.nodeLoad,
9777                     requireExecCb: requirejsVars.nodeRequireExecCb
9778                 });
9779
9780                 req(['build'], function () {
9781                     callback(req);
9782                 });
9783             }
9784         };
9785
9786         requirejs.define = define;
9787
9788         module.exports = requirejs;
9789         return;
9790     }
9791
9792     if (commandOption === 'o') {
9793         //Do the optimizer work.
9794         loadLib();
9795
9796         /**
9797  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
9798  * Available via the MIT or new BSD license.
9799  * see: http://github.com/jrburke/requirejs for details
9800  */
9801
9802 /*
9803  * Create a build.js file that has the build options you want and pass that
9804  * build file to this file to do the build. See example.build.js for more information.
9805  */
9806
9807 /*jslint strict: false, nomen: false */
9808 /*global require: false */
9809
9810 require({
9811     baseUrl: require.s.contexts._.config.baseUrl,
9812     //Use a separate context than the default context so that the
9813     //build can use the default context.
9814     context: 'build',
9815     catchError: {
9816         define: true
9817     }
9818 },       ['env!env/args', 'build'],
9819 function (args,            build) {
9820     build(args);
9821 });
9822
9823
9824     } else if (commandOption === 'v') {
9825         console.log('r.js: ' + version + ', RequireJS: ' + this.requirejsVars.require.version);
9826     } else if (commandOption === 'convert') {
9827         loadLib();
9828
9829         this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'],
9830         function (args,           commonJs,   print) {
9831
9832             var srcDir, outDir;
9833             srcDir = args[0];
9834             outDir = args[1];
9835
9836             if (!srcDir || !outDir) {
9837                 print('Usage: path/to/commonjs/modules output/dir');
9838                 return;
9839             }
9840
9841             commonJs.convertDir(args[0], args[1]);
9842         });
9843     } else {
9844         //Just run an app
9845
9846         //Load the bundled libraries for use in the app.
9847         if (commandOption === 'lib') {
9848             loadLib();
9849         }
9850
9851         setBaseUrl(fileName);
9852
9853         if (exists(fileName)) {
9854             exec(readFile(fileName), fileName);
9855         } else {
9856             showHelp();
9857         }
9858     }
9859
9860 }((typeof console !== 'undefined' ? console : undefined),
9861   (typeof Packages !== 'undefined' ? Array.prototype.slice.call(arguments, 0) : []),
9862   (typeof readFile !== 'undefined' ? readFile : undefined)));