UNPKG

1.2 MBJavaScriptView Raw
1#!/usr/bin/env node
2/**
3 * @license r.js 2.3.5 Copyright jQuery Foundation and other contributors.
4 * Released under MIT license, http://github.com/requirejs/r.js/LICENSE
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, sloppy: true */
15/*global readFile: true, process: false, Packages: false, print: false,
16console: false, java: false, module: false, requirejsVars, navigator,
17document, importScripts, self, location, Components, FileUtils */
18
19var requirejs, require, define, xpcUtil;
20(function (console, args, readFileFunc) {
21 var fileName, env, fs, vm, path, exec, rhinoContext, dir, nodeRequire,
22 nodeDefine, exists, reqMain, loadedOptimizedLib, existsForNode, Cc, Ci,
23 version = '2.3.5',
24 jsSuffixRegExp = /\.js$/,
25 commandOption = '',
26 useLibLoaded = {},
27 //Used by jslib/rhino/args.js
28 rhinoArgs = args,
29 //Used by jslib/xpconnect/args.js
30 xpconnectArgs = args,
31 readFile = typeof readFileFunc !== 'undefined' ? readFileFunc : null;
32
33 function showHelp() {
34 console.log('See https://github.com/requirejs/r.js for usage.');
35 }
36
37 if (typeof process !== 'undefined' && process.versions && !!process.versions.node) {
38 env = 'node';
39
40 //Get the fs module via Node's require before it
41 //gets replaced. Used in require/node.js
42 fs = require('fs');
43 vm = require('vm');
44 path = require('path');
45 //In Node 0.7+ existsSync is on fs.
46 existsForNode = fs.existsSync || path.existsSync;
47
48 nodeRequire = require;
49 nodeDefine = define;
50 reqMain = require.main;
51
52 //Temporarily hide require and define to allow require.js to define
53 //them.
54 require = undefined;
55 define = undefined;
56
57 readFile = function (path) {
58 return fs.readFileSync(path, 'utf8');
59 };
60
61 exec = function (string, name) {
62 return vm.runInThisContext(this.requirejsVars.require.makeNodeWrapper(string),
63 name ? fs.realpathSync(name) : '');
64 };
65
66 exists = function (fileName) {
67 return existsForNode(fileName);
68 };
69
70
71 fileName = process.argv[2];
72
73 if (fileName && fileName.indexOf('-') === 0) {
74 commandOption = fileName.substring(1);
75 fileName = process.argv[3];
76 }
77 } else if (typeof Packages !== 'undefined') {
78 env = 'rhino';
79
80 fileName = args[0];
81
82 if (fileName && fileName.indexOf('-') === 0) {
83 commandOption = fileName.substring(1);
84 fileName = args[1];
85 }
86
87 //Exec/readFile differs between Rhino and Nashorn. Rhino has an
88 //importPackage where Nashorn does not, so branch on that. This is a
89 //coarser check -- detecting readFile existence might also be enough for
90 //this spot. However, sticking with importPackage to keep it the same
91 //as other Rhino/Nashorn detection branches.
92 if (typeof importPackage !== 'undefined') {
93 rhinoContext = Packages.org.mozilla.javascript.ContextFactory.getGlobal().enterContext();
94
95 exec = function (string, name) {
96 return rhinoContext.evaluateString(this, string, name, 0, null);
97 };
98 } else {
99 exec = function (string, name) {
100 load({ script: string, name: name});
101 };
102 readFile = readFully;
103 }
104
105 exists = function (fileName) {
106 return (new java.io.File(fileName)).exists();
107 };
108
109 //Define a console.log for easier logging. Don't
110 //get fancy though.
111 if (typeof console === 'undefined') {
112 console = {
113 log: function () {
114 print.apply(undefined, arguments);
115 }
116 };
117 }
118 } else if ((typeof navigator !== 'undefined' && typeof document !== 'undefined') ||
119 (typeof importScripts !== 'undefined' && typeof self !== 'undefined')) {
120 env = 'browser';
121
122 readFile = function (path) {
123 return fs.readFileSync(path, 'utf8');
124 };
125
126 exec = function (string) {
127 return eval(string);
128 };
129
130 exists = function () {
131 console.log('x.js exists not applicable in browser env');
132 return false;
133 };
134
135 } else if (typeof Components !== 'undefined' && Components.classes && Components.interfaces) {
136 env = 'xpconnect';
137
138 Components.utils['import']('resource://gre/modules/FileUtils.jsm');
139 Cc = Components.classes;
140 Ci = Components.interfaces;
141
142 fileName = args[0];
143
144 if (fileName && fileName.indexOf('-') === 0) {
145 commandOption = fileName.substring(1);
146 fileName = args[1];
147 }
148
149 xpcUtil = {
150 isWindows: ('@mozilla.org/windows-registry-key;1' in Cc),
151 cwd: function () {
152 return FileUtils.getFile("CurWorkD", []).path;
153 },
154
155 //Remove . and .. from paths, normalize on front slashes
156 normalize: function (path) {
157 //There has to be an easier way to do this.
158 var i, part, ary,
159 firstChar = path.charAt(0);
160
161 if (firstChar !== '/' &&
162 firstChar !== '\\' &&
163 path.indexOf(':') === -1) {
164 //A relative path. Use the current working directory.
165 path = xpcUtil.cwd() + '/' + path;
166 }
167
168 ary = path.replace(/\\/g, '/').split('/');
169
170 for (i = 0; i < ary.length; i += 1) {
171 part = ary[i];
172 if (part === '.') {
173 ary.splice(i, 1);
174 i -= 1;
175 } else if (part === '..') {
176 ary.splice(i - 1, 2);
177 i -= 2;
178 }
179 }
180 return ary.join('/');
181 },
182
183 xpfile: function (path) {
184 var fullPath;
185 try {
186 fullPath = xpcUtil.normalize(path);
187 if (xpcUtil.isWindows) {
188 fullPath = fullPath.replace(/\//g, '\\');
189 }
190 return new FileUtils.File(fullPath);
191 } catch (e) {
192 throw new Error((fullPath || path) + ' failed: ' + e);
193 }
194 },
195
196 readFile: function (/*String*/path, /*String?*/encoding) {
197 //A file read function that can deal with BOMs
198 encoding = encoding || "utf-8";
199
200 var inStream, convertStream,
201 readData = {},
202 fileObj = xpcUtil.xpfile(path);
203
204 //XPCOM, you so crazy
205 try {
206 inStream = Cc['@mozilla.org/network/file-input-stream;1']
207 .createInstance(Ci.nsIFileInputStream);
208 inStream.init(fileObj, 1, 0, false);
209
210 convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']
211 .createInstance(Ci.nsIConverterInputStream);
212 convertStream.init(inStream, encoding, inStream.available(),
213 Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
214
215 convertStream.readString(inStream.available(), readData);
216 return readData.value;
217 } catch (e) {
218 throw new Error((fileObj && fileObj.path || '') + ': ' + e);
219 } finally {
220 if (convertStream) {
221 convertStream.close();
222 }
223 if (inStream) {
224 inStream.close();
225 }
226 }
227 }
228 };
229
230 readFile = xpcUtil.readFile;
231
232 exec = function (string) {
233 return eval(string);
234 };
235
236 exists = function (fileName) {
237 return xpcUtil.xpfile(fileName).exists();
238 };
239
240 //Define a console.log for easier logging. Don't
241 //get fancy though.
242 if (typeof console === 'undefined') {
243 console = {
244 log: function () {
245 print.apply(undefined, arguments);
246 }
247 };
248 }
249 }
250
251 /** vim: et:ts=4:sw=4:sts=4
252 * @license RequireJS 2.3.5 Copyright jQuery Foundation and other contributors.
253 * Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE
254 */
255//Not using strict: uneven strict support in browsers, #392, and causes
256//problems with requirejs.exec()/transpiler plugins that may not be strict.
257/*jslint regexp: true, nomen: true, sloppy: true */
258/*global window, navigator, document, importScripts, setTimeout, opera */
259
260
261(function (global, setTimeout) {
262 var req, s, head, baseElement, dataMain, src,
263 interactiveScript, currentlyAddingScript, mainScript, subPath,
264 version = '2.3.5',
265 commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/mg,
266 cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
267 jsSuffixRegExp = /\.js$/,
268 currDirRegExp = /^\.\//,
269 op = Object.prototype,
270 ostring = op.toString,
271 hasOwn = op.hasOwnProperty,
272 isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document),
273 isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
274 //PS3 indicates loaded and complete, but need to wait for complete
275 //specifically. Sequence is 'loading', 'loaded', execution,
276 // then 'complete'. The UA check is unfortunate, but not sure how
277 //to feature test w/o causing perf issues.
278 readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
279 /^complete$/ : /^(complete|loaded)$/,
280 defContextName = '_',
281 //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
282 isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
283 contexts = {},
284 cfg = {},
285 globalDefQueue = [],
286 useInteractive = false;
287
288 //Could match something like ')//comment', do not lose the prefix to comment.
289 function commentReplace(match, singlePrefix) {
290 return singlePrefix || '';
291 }
292
293 function isFunction(it) {
294 return ostring.call(it) === '[object Function]';
295 }
296
297 function isArray(it) {
298 return ostring.call(it) === '[object Array]';
299 }
300
301 /**
302 * Helper function for iterating over an array. If the func returns
303 * a true value, it will break out of the loop.
304 */
305 function each(ary, func) {
306 if (ary) {
307 var i;
308 for (i = 0; i < ary.length; i += 1) {
309 if (ary[i] && func(ary[i], i, ary)) {
310 break;
311 }
312 }
313 }
314 }
315
316 /**
317 * Helper function for iterating over an array backwards. If the func
318 * returns a true value, it will break out of the loop.
319 */
320 function eachReverse(ary, func) {
321 if (ary) {
322 var i;
323 for (i = ary.length - 1; i > -1; i -= 1) {
324 if (ary[i] && func(ary[i], i, ary)) {
325 break;
326 }
327 }
328 }
329 }
330
331 function hasProp(obj, prop) {
332 return hasOwn.call(obj, prop);
333 }
334
335 function getOwn(obj, prop) {
336 return hasProp(obj, prop) && obj[prop];
337 }
338
339 /**
340 * Cycles over properties in an object and calls a function for each
341 * property value. If the function returns a truthy value, then the
342 * iteration is stopped.
343 */
344 function eachProp(obj, func) {
345 var prop;
346 for (prop in obj) {
347 if (hasProp(obj, prop)) {
348 if (func(obj[prop], prop)) {
349 break;
350 }
351 }
352 }
353 }
354
355 /**
356 * Simple function to mix in properties from source into target,
357 * but only if target does not already have a property of the same name.
358 */
359 function mixin(target, source, force, deepStringMixin) {
360 if (source) {
361 eachProp(source, function (value, prop) {
362 if (force || !hasProp(target, prop)) {
363 if (deepStringMixin && typeof value === 'object' && value &&
364 !isArray(value) && !isFunction(value) &&
365 !(value instanceof RegExp)) {
366
367 if (!target[prop]) {
368 target[prop] = {};
369 }
370 mixin(target[prop], value, force, deepStringMixin);
371 } else {
372 target[prop] = value;
373 }
374 }
375 });
376 }
377 return target;
378 }
379
380 //Similar to Function.prototype.bind, but the 'this' object is specified
381 //first, since it is easier to read/figure out what 'this' will be.
382 function bind(obj, fn) {
383 return function () {
384 return fn.apply(obj, arguments);
385 };
386 }
387
388 function scripts() {
389 return document.getElementsByTagName('script');
390 }
391
392 function defaultOnError(err) {
393 throw err;
394 }
395
396 //Allow getting a global that is expressed in
397 //dot notation, like 'a.b.c'.
398 function getGlobal(value) {
399 if (!value) {
400 return value;
401 }
402 var g = global;
403 each(value.split('.'), function (part) {
404 g = g[part];
405 });
406 return g;
407 }
408
409 /**
410 * Constructs an error with a pointer to an URL with more information.
411 * @param {String} id the error ID that maps to an ID on a web page.
412 * @param {String} message human readable error.
413 * @param {Error} [err] the original error, if there is one.
414 *
415 * @returns {Error}
416 */
417 function makeError(id, msg, err, requireModules) {
418 var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
419 e.requireType = id;
420 e.requireModules = requireModules;
421 if (err) {
422 e.originalError = err;
423 }
424 return e;
425 }
426
427 if (typeof define !== 'undefined') {
428 //If a define is already in play via another AMD loader,
429 //do not overwrite.
430 return;
431 }
432
433 if (typeof requirejs !== 'undefined') {
434 if (isFunction(requirejs)) {
435 //Do not overwrite an existing requirejs instance.
436 return;
437 }
438 cfg = requirejs;
439 requirejs = undefined;
440 }
441
442 //Allow for a require config object
443 if (typeof require !== 'undefined' && !isFunction(require)) {
444 //assume it is a config object.
445 cfg = require;
446 require = undefined;
447 }
448
449 function newContext(contextName) {
450 var inCheckLoaded, Module, context, handlers,
451 checkLoadedTimeoutId,
452 config = {
453 //Defaults. Do not set a default for map
454 //config to speed up normalize(), which
455 //will run faster if there is no default.
456 waitSeconds: 7,
457 baseUrl: './',
458 paths: {},
459 bundles: {},
460 pkgs: {},
461 shim: {},
462 config: {}
463 },
464 registry = {},
465 //registry of just enabled modules, to speed
466 //cycle breaking code when lots of modules
467 //are registered, but not activated.
468 enabledRegistry = {},
469 undefEvents = {},
470 defQueue = [],
471 defined = {},
472 urlFetched = {},
473 bundlesMap = {},
474 requireCounter = 1,
475 unnormalizedCounter = 1;
476
477 /**
478 * Trims the . and .. from an array of path segments.
479 * It will keep a leading path segment if a .. will become
480 * the first path segment, to help with module name lookups,
481 * which act like paths, but can be remapped. But the end result,
482 * all paths that use this function should look normalized.
483 * NOTE: this method MODIFIES the input array.
484 * @param {Array} ary the array of path segments.
485 */
486 function trimDots(ary) {
487 var i, part;
488 for (i = 0; i < ary.length; i++) {
489 part = ary[i];
490 if (part === '.') {
491 ary.splice(i, 1);
492 i -= 1;
493 } else if (part === '..') {
494 // If at the start, or previous value is still ..,
495 // keep them so that when converted to a path it may
496 // still work when converted to a path, even though
497 // as an ID it is less than ideal. In larger point
498 // releases, may be better to just kick out an error.
499 if (i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1] === '..') {
500 continue;
501 } else if (i > 0) {
502 ary.splice(i - 1, 2);
503 i -= 2;
504 }
505 }
506 }
507 }
508
509 /**
510 * Given a relative module name, like ./something, normalize it to
511 * a real name that can be mapped to a path.
512 * @param {String} name the relative name
513 * @param {String} baseName a real name that the name arg is relative
514 * to.
515 * @param {Boolean} applyMap apply the map config to the value. Should
516 * only be done if this normalization is for a dependency ID.
517 * @returns {String} normalized name
518 */
519 function normalize(name, baseName, applyMap) {
520 var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex,
521 foundMap, foundI, foundStarMap, starI, normalizedBaseParts,
522 baseParts = (baseName && baseName.split('/')),
523 map = config.map,
524 starMap = map && map['*'];
525
526 //Adjust any relative paths.
527 if (name) {
528 name = name.split('/');
529 lastIndex = name.length - 1;
530
531 // If wanting node ID compatibility, strip .js from end
532 // of IDs. Have to do this here, and not in nameToUrl
533 // because node allows either .js or non .js to map
534 // to same file.
535 if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
536 name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
537 }
538
539 // Starts with a '.' so need the baseName
540 if (name[0].charAt(0) === '.' && baseParts) {
541 //Convert baseName to array, and lop off the last part,
542 //so that . matches that 'directory' and not name of the baseName's
543 //module. For instance, baseName of 'one/two/three', maps to
544 //'one/two/three.js', but we want the directory, 'one/two' for
545 //this normalization.
546 normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
547 name = normalizedBaseParts.concat(name);
548 }
549
550 trimDots(name);
551 name = name.join('/');
552 }
553
554 //Apply map config if available.
555 if (applyMap && map && (baseParts || starMap)) {
556 nameParts = name.split('/');
557
558 outerLoop: for (i = nameParts.length; i > 0; i -= 1) {
559 nameSegment = nameParts.slice(0, i).join('/');
560
561 if (baseParts) {
562 //Find the longest baseName segment match in the config.
563 //So, do joins on the biggest to smallest lengths of baseParts.
564 for (j = baseParts.length; j > 0; j -= 1) {
565 mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
566
567 //baseName segment has config, find if it has one for
568 //this name.
569 if (mapValue) {
570 mapValue = getOwn(mapValue, nameSegment);
571 if (mapValue) {
572 //Match, update name to the new value.
573 foundMap = mapValue;
574 foundI = i;
575 break outerLoop;
576 }
577 }
578 }
579 }
580
581 //Check for a star map match, but just hold on to it,
582 //if there is a shorter segment match later in a matching
583 //config, then favor over this star map.
584 if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
585 foundStarMap = getOwn(starMap, nameSegment);
586 starI = i;
587 }
588 }
589
590 if (!foundMap && foundStarMap) {
591 foundMap = foundStarMap;
592 foundI = starI;
593 }
594
595 if (foundMap) {
596 nameParts.splice(0, foundI, foundMap);
597 name = nameParts.join('/');
598 }
599 }
600
601 // If the name points to a package's name, use
602 // the package main instead.
603 pkgMain = getOwn(config.pkgs, name);
604
605 return pkgMain ? pkgMain : name;
606 }
607
608 function removeScript(name) {
609 if (isBrowser) {
610 each(scripts(), function (scriptNode) {
611 if (scriptNode.getAttribute('data-requiremodule') === name &&
612 scriptNode.getAttribute('data-requirecontext') === context.contextName) {
613 scriptNode.parentNode.removeChild(scriptNode);
614 return true;
615 }
616 });
617 }
618 }
619
620 function hasPathFallback(id) {
621 var pathConfig = getOwn(config.paths, id);
622 if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
623 //Pop off the first array value, since it failed, and
624 //retry
625 pathConfig.shift();
626 context.require.undef(id);
627
628 //Custom require that does not do map translation, since
629 //ID is "absolute", already mapped/resolved.
630 context.makeRequire(null, {
631 skipMap: true
632 })([id]);
633
634 return true;
635 }
636 }
637
638 //Turns a plugin!resource to [plugin, resource]
639 //with the plugin being undefined if the name
640 //did not have a plugin prefix.
641 function splitPrefix(name) {
642 var prefix,
643 index = name ? name.indexOf('!') : -1;
644 if (index > -1) {
645 prefix = name.substring(0, index);
646 name = name.substring(index + 1, name.length);
647 }
648 return [prefix, name];
649 }
650
651 /**
652 * Creates a module mapping that includes plugin prefix, module
653 * name, and path. If parentModuleMap is provided it will
654 * also normalize the name via require.normalize()
655 *
656 * @param {String} name the module name
657 * @param {String} [parentModuleMap] parent module map
658 * for the module name, used to resolve relative names.
659 * @param {Boolean} isNormalized: is the ID already normalized.
660 * This is true if this call is done for a define() module ID.
661 * @param {Boolean} applyMap: apply the map config to the ID.
662 * Should only be true if this map is for a dependency.
663 *
664 * @returns {Object}
665 */
666 function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
667 var url, pluginModule, suffix, nameParts,
668 prefix = null,
669 parentName = parentModuleMap ? parentModuleMap.name : null,
670 originalName = name,
671 isDefine = true,
672 normalizedName = '';
673
674 //If no name, then it means it is a require call, generate an
675 //internal name.
676 if (!name) {
677 isDefine = false;
678 name = '_@r' + (requireCounter += 1);
679 }
680
681 nameParts = splitPrefix(name);
682 prefix = nameParts[0];
683 name = nameParts[1];
684
685 if (prefix) {
686 prefix = normalize(prefix, parentName, applyMap);
687 pluginModule = getOwn(defined, prefix);
688 }
689
690 //Account for relative paths if there is a base name.
691 if (name) {
692 if (prefix) {
693 if (isNormalized) {
694 normalizedName = name;
695 } else if (pluginModule && pluginModule.normalize) {
696 //Plugin is loaded, use its normalize method.
697 normalizedName = pluginModule.normalize(name, function (name) {
698 return normalize(name, parentName, applyMap);
699 });
700 } else {
701 // If nested plugin references, then do not try to
702 // normalize, as it will not normalize correctly. This
703 // places a restriction on resourceIds, and the longer
704 // term solution is not to normalize until plugins are
705 // loaded and all normalizations to allow for async
706 // loading of a loader plugin. But for now, fixes the
707 // common uses. Details in #1131
708 normalizedName = name.indexOf('!') === -1 ?
709 normalize(name, parentName, applyMap) :
710 name;
711 }
712 } else {
713 //A regular module.
714 normalizedName = normalize(name, parentName, applyMap);
715
716 //Normalized name may be a plugin ID due to map config
717 //application in normalize. The map config values must
718 //already be normalized, so do not need to redo that part.
719 nameParts = splitPrefix(normalizedName);
720 prefix = nameParts[0];
721 normalizedName = nameParts[1];
722 isNormalized = true;
723
724 url = context.nameToUrl(normalizedName);
725 }
726 }
727
728 //If the id is a plugin id that cannot be determined if it needs
729 //normalization, stamp it with a unique ID so two matching relative
730 //ids that may conflict can be separate.
731 suffix = prefix && !pluginModule && !isNormalized ?
732 '_unnormalized' + (unnormalizedCounter += 1) :
733 '';
734
735 return {
736 prefix: prefix,
737 name: normalizedName,
738 parentMap: parentModuleMap,
739 unnormalized: !!suffix,
740 url: url,
741 originalName: originalName,
742 isDefine: isDefine,
743 id: (prefix ?
744 prefix + '!' + normalizedName :
745 normalizedName) + suffix
746 };
747 }
748
749 function getModule(depMap) {
750 var id = depMap.id,
751 mod = getOwn(registry, id);
752
753 if (!mod) {
754 mod = registry[id] = new context.Module(depMap);
755 }
756
757 return mod;
758 }
759
760 function on(depMap, name, fn) {
761 var id = depMap.id,
762 mod = getOwn(registry, id);
763
764 if (hasProp(defined, id) &&
765 (!mod || mod.defineEmitComplete)) {
766 if (name === 'defined') {
767 fn(defined[id]);
768 }
769 } else {
770 mod = getModule(depMap);
771 if (mod.error && name === 'error') {
772 fn(mod.error);
773 } else {
774 mod.on(name, fn);
775 }
776 }
777 }
778
779 function onError(err, errback) {
780 var ids = err.requireModules,
781 notified = false;
782
783 if (errback) {
784 errback(err);
785 } else {
786 each(ids, function (id) {
787 var mod = getOwn(registry, id);
788 if (mod) {
789 //Set error on module, so it skips timeout checks.
790 mod.error = err;
791 if (mod.events.error) {
792 notified = true;
793 mod.emit('error', err);
794 }
795 }
796 });
797
798 if (!notified) {
799 req.onError(err);
800 }
801 }
802 }
803
804 /**
805 * Internal method to transfer globalQueue items to this context's
806 * defQueue.
807 */
808 function takeGlobalQueue() {
809 //Push all the globalDefQueue items into the context's defQueue
810 if (globalDefQueue.length) {
811 each(globalDefQueue, function(queueItem) {
812 var id = queueItem[0];
813 if (typeof id === 'string') {
814 context.defQueueMap[id] = true;
815 }
816 defQueue.push(queueItem);
817 });
818 globalDefQueue = [];
819 }
820 }
821
822 handlers = {
823 'require': function (mod) {
824 if (mod.require) {
825 return mod.require;
826 } else {
827 return (mod.require = context.makeRequire(mod.map));
828 }
829 },
830 'exports': function (mod) {
831 mod.usingExports = true;
832 if (mod.map.isDefine) {
833 if (mod.exports) {
834 return (defined[mod.map.id] = mod.exports);
835 } else {
836 return (mod.exports = defined[mod.map.id] = {});
837 }
838 }
839 },
840 'module': function (mod) {
841 if (mod.module) {
842 return mod.module;
843 } else {
844 return (mod.module = {
845 id: mod.map.id,
846 uri: mod.map.url,
847 config: function () {
848 return getOwn(config.config, mod.map.id) || {};
849 },
850 exports: mod.exports || (mod.exports = {})
851 });
852 }
853 }
854 };
855
856 function cleanRegistry(id) {
857 //Clean up machinery used for waiting modules.
858 delete registry[id];
859 delete enabledRegistry[id];
860 }
861
862 function breakCycle(mod, traced, processed) {
863 var id = mod.map.id;
864
865 if (mod.error) {
866 mod.emit('error', mod.error);
867 } else {
868 traced[id] = true;
869 each(mod.depMaps, function (depMap, i) {
870 var depId = depMap.id,
871 dep = getOwn(registry, depId);
872
873 //Only force things that have not completed
874 //being defined, so still in the registry,
875 //and only if it has not been matched up
876 //in the module already.
877 if (dep && !mod.depMatched[i] && !processed[depId]) {
878 if (getOwn(traced, depId)) {
879 mod.defineDep(i, defined[depId]);
880 mod.check(); //pass false?
881 } else {
882 breakCycle(dep, traced, processed);
883 }
884 }
885 });
886 processed[id] = true;
887 }
888 }
889
890 function checkLoaded() {
891 var err, usingPathFallback,
892 waitInterval = config.waitSeconds * 1000,
893 //It is possible to disable the wait interval by using waitSeconds of 0.
894 expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
895 noLoads = [],
896 reqCalls = [],
897 stillLoading = false,
898 needCycleCheck = true;
899
900 //Do not bother if this call was a result of a cycle break.
901 if (inCheckLoaded) {
902 return;
903 }
904
905 inCheckLoaded = true;
906
907 //Figure out the state of all the modules.
908 eachProp(enabledRegistry, function (mod) {
909 var map = mod.map,
910 modId = map.id;
911
912 //Skip things that are not enabled or in error state.
913 if (!mod.enabled) {
914 return;
915 }
916
917 if (!map.isDefine) {
918 reqCalls.push(mod);
919 }
920
921 if (!mod.error) {
922 //If the module should be executed, and it has not
923 //been inited and time is up, remember it.
924 if (!mod.inited && expired) {
925 if (hasPathFallback(modId)) {
926 usingPathFallback = true;
927 stillLoading = true;
928 } else {
929 noLoads.push(modId);
930 removeScript(modId);
931 }
932 } else if (!mod.inited && mod.fetched && map.isDefine) {
933 stillLoading = true;
934 if (!map.prefix) {
935 //No reason to keep looking for unfinished
936 //loading. If the only stillLoading is a
937 //plugin resource though, keep going,
938 //because it may be that a plugin resource
939 //is waiting on a non-plugin cycle.
940 return (needCycleCheck = false);
941 }
942 }
943 }
944 });
945
946 if (expired && noLoads.length) {
947 //If wait time expired, throw error of unloaded modules.
948 err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
949 err.contextName = context.contextName;
950 return onError(err);
951 }
952
953 //Not expired, check for a cycle.
954 if (needCycleCheck) {
955 each(reqCalls, function (mod) {
956 breakCycle(mod, {}, {});
957 });
958 }
959
960 //If still waiting on loads, and the waiting load is something
961 //other than a plugin resource, or there are still outstanding
962 //scripts, then just try back later.
963 if ((!expired || usingPathFallback) && stillLoading) {
964 //Something is still waiting to load. Wait for it, but only
965 //if a timeout is not already in effect.
966 if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
967 checkLoadedTimeoutId = setTimeout(function () {
968 checkLoadedTimeoutId = 0;
969 checkLoaded();
970 }, 50);
971 }
972 }
973
974 inCheckLoaded = false;
975 }
976
977 Module = function (map) {
978 this.events = getOwn(undefEvents, map.id) || {};
979 this.map = map;
980 this.shim = getOwn(config.shim, map.id);
981 this.depExports = [];
982 this.depMaps = [];
983 this.depMatched = [];
984 this.pluginMaps = {};
985 this.depCount = 0;
986
987 /* this.exports this.factory
988 this.depMaps = [],
989 this.enabled, this.fetched
990 */
991 };
992
993 Module.prototype = {
994 init: function (depMaps, factory, errback, options) {
995 options = options || {};
996
997 //Do not do more inits if already done. Can happen if there
998 //are multiple define calls for the same module. That is not
999 //a normal, common case, but it is also not unexpected.
1000 if (this.inited) {
1001 return;
1002 }
1003
1004 this.factory = factory;
1005
1006 if (errback) {
1007 //Register for errors on this module.
1008 this.on('error', errback);
1009 } else if (this.events.error) {
1010 //If no errback already, but there are error listeners
1011 //on this module, set up an errback to pass to the deps.
1012 errback = bind(this, function (err) {
1013 this.emit('error', err);
1014 });
1015 }
1016
1017 //Do a copy of the dependency array, so that
1018 //source inputs are not modified. For example
1019 //"shim" deps are passed in here directly, and
1020 //doing a direct modification of the depMaps array
1021 //would affect that config.
1022 this.depMaps = depMaps && depMaps.slice(0);
1023
1024 this.errback = errback;
1025
1026 //Indicate this module has be initialized
1027 this.inited = true;
1028
1029 this.ignore = options.ignore;
1030
1031 //Could have option to init this module in enabled mode,
1032 //or could have been previously marked as enabled. However,
1033 //the dependencies are not known until init is called. So
1034 //if enabled previously, now trigger dependencies as enabled.
1035 if (options.enabled || this.enabled) {
1036 //Enable this module and dependencies.
1037 //Will call this.check()
1038 this.enable();
1039 } else {
1040 this.check();
1041 }
1042 },
1043
1044 defineDep: function (i, depExports) {
1045 //Because of cycles, defined callback for a given
1046 //export can be called more than once.
1047 if (!this.depMatched[i]) {
1048 this.depMatched[i] = true;
1049 this.depCount -= 1;
1050 this.depExports[i] = depExports;
1051 }
1052 },
1053
1054 fetch: function () {
1055 if (this.fetched) {
1056 return;
1057 }
1058 this.fetched = true;
1059
1060 context.startTime = (new Date()).getTime();
1061
1062 var map = this.map;
1063
1064 //If the manager is for a plugin managed resource,
1065 //ask the plugin to load it now.
1066 if (this.shim) {
1067 context.makeRequire(this.map, {
1068 enableBuildCallback: true
1069 })(this.shim.deps || [], bind(this, function () {
1070 return map.prefix ? this.callPlugin() : this.load();
1071 }));
1072 } else {
1073 //Regular dependency.
1074 return map.prefix ? this.callPlugin() : this.load();
1075 }
1076 },
1077
1078 load: function () {
1079 var url = this.map.url;
1080
1081 //Regular dependency.
1082 if (!urlFetched[url]) {
1083 urlFetched[url] = true;
1084 context.load(this.map.id, url);
1085 }
1086 },
1087
1088 /**
1089 * Checks if the module is ready to define itself, and if so,
1090 * define it.
1091 */
1092 check: function () {
1093 if (!this.enabled || this.enabling) {
1094 return;
1095 }
1096
1097 var err, cjsModule,
1098 id = this.map.id,
1099 depExports = this.depExports,
1100 exports = this.exports,
1101 factory = this.factory;
1102
1103 if (!this.inited) {
1104 // Only fetch if not already in the defQueue.
1105 if (!hasProp(context.defQueueMap, id)) {
1106 this.fetch();
1107 }
1108 } else if (this.error) {
1109 this.emit('error', this.error);
1110 } else if (!this.defining) {
1111 //The factory could trigger another require call
1112 //that would result in checking this module to
1113 //define itself again. If already in the process
1114 //of doing that, skip this work.
1115 this.defining = true;
1116
1117 if (this.depCount < 1 && !this.defined) {
1118 if (isFunction(factory)) {
1119 //If there is an error listener, favor passing
1120 //to that instead of throwing an error. However,
1121 //only do it for define()'d modules. require
1122 //errbacks should not be called for failures in
1123 //their callbacks (#699). However if a global
1124 //onError is set, use that.
1125 if ((this.events.error && this.map.isDefine) ||
1126 req.onError !== defaultOnError) {
1127 try {
1128 exports = context.execCb(id, factory, depExports, exports);
1129 } catch (e) {
1130 err = e;
1131 }
1132 } else {
1133 exports = context.execCb(id, factory, depExports, exports);
1134 }
1135
1136 // Favor return value over exports. If node/cjs in play,
1137 // then will not have a return value anyway. Favor
1138 // module.exports assignment over exports object.
1139 if (this.map.isDefine && exports === undefined) {
1140 cjsModule = this.module;
1141 if (cjsModule) {
1142 exports = cjsModule.exports;
1143 } else if (this.usingExports) {
1144 //exports already set the defined value.
1145 exports = this.exports;
1146 }
1147 }
1148
1149 if (err) {
1150 err.requireMap = this.map;
1151 err.requireModules = this.map.isDefine ? [this.map.id] : null;
1152 err.requireType = this.map.isDefine ? 'define' : 'require';
1153 return onError((this.error = err));
1154 }
1155
1156 } else {
1157 //Just a literal value
1158 exports = factory;
1159 }
1160
1161 this.exports = exports;
1162
1163 if (this.map.isDefine && !this.ignore) {
1164 defined[id] = exports;
1165
1166 if (req.onResourceLoad) {
1167 var resLoadMaps = [];
1168 each(this.depMaps, function (depMap) {
1169 resLoadMaps.push(depMap.normalizedMap || depMap);
1170 });
1171 req.onResourceLoad(context, this.map, resLoadMaps);
1172 }
1173 }
1174
1175 //Clean up
1176 cleanRegistry(id);
1177
1178 this.defined = true;
1179 }
1180
1181 //Finished the define stage. Allow calling check again
1182 //to allow define notifications below in the case of a
1183 //cycle.
1184 this.defining = false;
1185
1186 if (this.defined && !this.defineEmitted) {
1187 this.defineEmitted = true;
1188 this.emit('defined', this.exports);
1189 this.defineEmitComplete = true;
1190 }
1191
1192 }
1193 },
1194
1195 callPlugin: function () {
1196 var map = this.map,
1197 id = map.id,
1198 //Map already normalized the prefix.
1199 pluginMap = makeModuleMap(map.prefix);
1200
1201 //Mark this as a dependency for this plugin, so it
1202 //can be traced for cycles.
1203 this.depMaps.push(pluginMap);
1204
1205 on(pluginMap, 'defined', bind(this, function (plugin) {
1206 var load, normalizedMap, normalizedMod,
1207 bundleId = getOwn(bundlesMap, this.map.id),
1208 name = this.map.name,
1209 parentName = this.map.parentMap ? this.map.parentMap.name : null,
1210 localRequire = context.makeRequire(map.parentMap, {
1211 enableBuildCallback: true
1212 });
1213
1214 //If current map is not normalized, wait for that
1215 //normalized name to load instead of continuing.
1216 if (this.map.unnormalized) {
1217 //Normalize the ID if the plugin allows it.
1218 if (plugin.normalize) {
1219 name = plugin.normalize(name, function (name) {
1220 return normalize(name, parentName, true);
1221 }) || '';
1222 }
1223
1224 //prefix and name should already be normalized, no need
1225 //for applying map config again either.
1226 normalizedMap = makeModuleMap(map.prefix + '!' + name,
1227 this.map.parentMap,
1228 true);
1229 on(normalizedMap,
1230 'defined', bind(this, function (value) {
1231 this.map.normalizedMap = normalizedMap;
1232 this.init([], function () { return value; }, null, {
1233 enabled: true,
1234 ignore: true
1235 });
1236 }));
1237
1238 normalizedMod = getOwn(registry, normalizedMap.id);
1239 if (normalizedMod) {
1240 //Mark this as a dependency for this plugin, so it
1241 //can be traced for cycles.
1242 this.depMaps.push(normalizedMap);
1243
1244 if (this.events.error) {
1245 normalizedMod.on('error', bind(this, function (err) {
1246 this.emit('error', err);
1247 }));
1248 }
1249 normalizedMod.enable();
1250 }
1251
1252 return;
1253 }
1254
1255 //If a paths config, then just load that file instead to
1256 //resolve the plugin, as it is built into that paths layer.
1257 if (bundleId) {
1258 this.map.url = context.nameToUrl(bundleId);
1259 this.load();
1260 return;
1261 }
1262
1263 load = bind(this, function (value) {
1264 this.init([], function () { return value; }, null, {
1265 enabled: true
1266 });
1267 });
1268
1269 load.error = bind(this, function (err) {
1270 this.inited = true;
1271 this.error = err;
1272 err.requireModules = [id];
1273
1274 //Remove temp unnormalized modules for this module,
1275 //since they will never be resolved otherwise now.
1276 eachProp(registry, function (mod) {
1277 if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
1278 cleanRegistry(mod.map.id);
1279 }
1280 });
1281
1282 onError(err);
1283 });
1284
1285 //Allow plugins to load other code without having to know the
1286 //context or how to 'complete' the load.
1287 load.fromText = bind(this, function (text, textAlt) {
1288 /*jslint evil: true */
1289 var moduleName = map.name,
1290 moduleMap = makeModuleMap(moduleName),
1291 hasInteractive = useInteractive;
1292
1293 //As of 2.1.0, support just passing the text, to reinforce
1294 //fromText only being called once per resource. Still
1295 //support old style of passing moduleName but discard
1296 //that moduleName in favor of the internal ref.
1297 if (textAlt) {
1298 text = textAlt;
1299 }
1300
1301 //Turn off interactive script matching for IE for any define
1302 //calls in the text, then turn it back on at the end.
1303 if (hasInteractive) {
1304 useInteractive = false;
1305 }
1306
1307 //Prime the system by creating a module instance for
1308 //it.
1309 getModule(moduleMap);
1310
1311 //Transfer any config to this other module.
1312 if (hasProp(config.config, id)) {
1313 config.config[moduleName] = config.config[id];
1314 }
1315
1316 try {
1317 req.exec(text);
1318 } catch (e) {
1319 return onError(makeError('fromtexteval',
1320 'fromText eval for ' + id +
1321 ' failed: ' + e,
1322 e,
1323 [id]));
1324 }
1325
1326 if (hasInteractive) {
1327 useInteractive = true;
1328 }
1329
1330 //Mark this as a dependency for the plugin
1331 //resource
1332 this.depMaps.push(moduleMap);
1333
1334 //Support anonymous modules.
1335 context.completeLoad(moduleName);
1336
1337 //Bind the value of that module to the value for this
1338 //resource ID.
1339 localRequire([moduleName], load);
1340 });
1341
1342 //Use parentName here since the plugin's name is not reliable,
1343 //could be some weird string with no path that actually wants to
1344 //reference the parentName's path.
1345 plugin.load(map.name, localRequire, load, config);
1346 }));
1347
1348 context.enable(pluginMap, this);
1349 this.pluginMaps[pluginMap.id] = pluginMap;
1350 },
1351
1352 enable: function () {
1353 enabledRegistry[this.map.id] = this;
1354 this.enabled = true;
1355
1356 //Set flag mentioning that the module is enabling,
1357 //so that immediate calls to the defined callbacks
1358 //for dependencies do not trigger inadvertent load
1359 //with the depCount still being zero.
1360 this.enabling = true;
1361
1362 //Enable each dependency
1363 each(this.depMaps, bind(this, function (depMap, i) {
1364 var id, mod, handler;
1365
1366 if (typeof depMap === 'string') {
1367 //Dependency needs to be converted to a depMap
1368 //and wired up to this module.
1369 depMap = makeModuleMap(depMap,
1370 (this.map.isDefine ? this.map : this.map.parentMap),
1371 false,
1372 !this.skipMap);
1373 this.depMaps[i] = depMap;
1374
1375 handler = getOwn(handlers, depMap.id);
1376
1377 if (handler) {
1378 this.depExports[i] = handler(this);
1379 return;
1380 }
1381
1382 this.depCount += 1;
1383
1384 on(depMap, 'defined', bind(this, function (depExports) {
1385 if (this.undefed) {
1386 return;
1387 }
1388 this.defineDep(i, depExports);
1389 this.check();
1390 }));
1391
1392 if (this.errback) {
1393 on(depMap, 'error', bind(this, this.errback));
1394 } else if (this.events.error) {
1395 // No direct errback on this module, but something
1396 // else is listening for errors, so be sure to
1397 // propagate the error correctly.
1398 on(depMap, 'error', bind(this, function(err) {
1399 this.emit('error', err);
1400 }));
1401 }
1402 }
1403
1404 id = depMap.id;
1405 mod = registry[id];
1406
1407 //Skip special modules like 'require', 'exports', 'module'
1408 //Also, don't call enable if it is already enabled,
1409 //important in circular dependency cases.
1410 if (!hasProp(handlers, id) && mod && !mod.enabled) {
1411 context.enable(depMap, this);
1412 }
1413 }));
1414
1415 //Enable each plugin that is used in
1416 //a dependency
1417 eachProp(this.pluginMaps, bind(this, function (pluginMap) {
1418 var mod = getOwn(registry, pluginMap.id);
1419 if (mod && !mod.enabled) {
1420 context.enable(pluginMap, this);
1421 }
1422 }));
1423
1424 this.enabling = false;
1425
1426 this.check();
1427 },
1428
1429 on: function (name, cb) {
1430 var cbs = this.events[name];
1431 if (!cbs) {
1432 cbs = this.events[name] = [];
1433 }
1434 cbs.push(cb);
1435 },
1436
1437 emit: function (name, evt) {
1438 each(this.events[name], function (cb) {
1439 cb(evt);
1440 });
1441 if (name === 'error') {
1442 //Now that the error handler was triggered, remove
1443 //the listeners, since this broken Module instance
1444 //can stay around for a while in the registry.
1445 delete this.events[name];
1446 }
1447 }
1448 };
1449
1450 function callGetModule(args) {
1451 //Skip modules already defined.
1452 if (!hasProp(defined, args[0])) {
1453 getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
1454 }
1455 }
1456
1457 function removeListener(node, func, name, ieName) {
1458 //Favor detachEvent because of IE9
1459 //issue, see attachEvent/addEventListener comment elsewhere
1460 //in this file.
1461 if (node.detachEvent && !isOpera) {
1462 //Probably IE. If not it will throw an error, which will be
1463 //useful to know.
1464 if (ieName) {
1465 node.detachEvent(ieName, func);
1466 }
1467 } else {
1468 node.removeEventListener(name, func, false);
1469 }
1470 }
1471
1472 /**
1473 * Given an event from a script node, get the requirejs info from it,
1474 * and then removes the event listeners on the node.
1475 * @param {Event} evt
1476 * @returns {Object}
1477 */
1478 function getScriptData(evt) {
1479 //Using currentTarget instead of target for Firefox 2.0's sake. Not
1480 //all old browsers will be supported, but this one was easy enough
1481 //to support and still makes sense.
1482 var node = evt.currentTarget || evt.srcElement;
1483
1484 //Remove the listeners once here.
1485 removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
1486 removeListener(node, context.onScriptError, 'error');
1487
1488 return {
1489 node: node,
1490 id: node && node.getAttribute('data-requiremodule')
1491 };
1492 }
1493
1494 function intakeDefines() {
1495 var args;
1496
1497 //Any defined modules in the global queue, intake them now.
1498 takeGlobalQueue();
1499
1500 //Make sure any remaining defQueue items get properly processed.
1501 while (defQueue.length) {
1502 args = defQueue.shift();
1503 if (args[0] === null) {
1504 return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' +
1505 args[args.length - 1]));
1506 } else {
1507 //args are id, deps, factory. Should be normalized by the
1508 //define() function.
1509 callGetModule(args);
1510 }
1511 }
1512 context.defQueueMap = {};
1513 }
1514
1515 context = {
1516 config: config,
1517 contextName: contextName,
1518 registry: registry,
1519 defined: defined,
1520 urlFetched: urlFetched,
1521 defQueue: defQueue,
1522 defQueueMap: {},
1523 Module: Module,
1524 makeModuleMap: makeModuleMap,
1525 nextTick: req.nextTick,
1526 onError: onError,
1527
1528 /**
1529 * Set a configuration for the context.
1530 * @param {Object} cfg config object to integrate.
1531 */
1532 configure: function (cfg) {
1533 //Make sure the baseUrl ends in a slash.
1534 if (cfg.baseUrl) {
1535 if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
1536 cfg.baseUrl += '/';
1537 }
1538 }
1539
1540 // Convert old style urlArgs string to a function.
1541 if (typeof cfg.urlArgs === 'string') {
1542 var urlArgs = cfg.urlArgs;
1543 cfg.urlArgs = function(id, url) {
1544 return (url.indexOf('?') === -1 ? '?' : '&') + urlArgs;
1545 };
1546 }
1547
1548 //Save off the paths since they require special processing,
1549 //they are additive.
1550 var shim = config.shim,
1551 objs = {
1552 paths: true,
1553 bundles: true,
1554 config: true,
1555 map: true
1556 };
1557
1558 eachProp(cfg, function (value, prop) {
1559 if (objs[prop]) {
1560 if (!config[prop]) {
1561 config[prop] = {};
1562 }
1563 mixin(config[prop], value, true, true);
1564 } else {
1565 config[prop] = value;
1566 }
1567 });
1568
1569 //Reverse map the bundles
1570 if (cfg.bundles) {
1571 eachProp(cfg.bundles, function (value, prop) {
1572 each(value, function (v) {
1573 if (v !== prop) {
1574 bundlesMap[v] = prop;
1575 }
1576 });
1577 });
1578 }
1579
1580 //Merge shim
1581 if (cfg.shim) {
1582 eachProp(cfg.shim, function (value, id) {
1583 //Normalize the structure
1584 if (isArray(value)) {
1585 value = {
1586 deps: value
1587 };
1588 }
1589 if ((value.exports || value.init) && !value.exportsFn) {
1590 value.exportsFn = context.makeShimExports(value);
1591 }
1592 shim[id] = value;
1593 });
1594 config.shim = shim;
1595 }
1596
1597 //Adjust packages if necessary.
1598 if (cfg.packages) {
1599 each(cfg.packages, function (pkgObj) {
1600 var location, name;
1601
1602 pkgObj = typeof pkgObj === 'string' ? {name: pkgObj} : pkgObj;
1603
1604 name = pkgObj.name;
1605 location = pkgObj.location;
1606 if (location) {
1607 config.paths[name] = pkgObj.location;
1608 }
1609
1610 //Save pointer to main module ID for pkg name.
1611 //Remove leading dot in main, so main paths are normalized,
1612 //and remove any trailing .js, since different package
1613 //envs have different conventions: some use a module name,
1614 //some use a file name.
1615 config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main')
1616 .replace(currDirRegExp, '')
1617 .replace(jsSuffixRegExp, '');
1618 });
1619 }
1620
1621 //If there are any "waiting to execute" modules in the registry,
1622 //update the maps for them, since their info, like URLs to load,
1623 //may have changed.
1624 eachProp(registry, function (mod, id) {
1625 //If module already has init called, since it is too
1626 //late to modify them, and ignore unnormalized ones
1627 //since they are transient.
1628 if (!mod.inited && !mod.map.unnormalized) {
1629 mod.map = makeModuleMap(id, null, true);
1630 }
1631 });
1632
1633 //If a deps array or a config callback is specified, then call
1634 //require with those args. This is useful when require is defined as a
1635 //config object before require.js is loaded.
1636 if (cfg.deps || cfg.callback) {
1637 context.require(cfg.deps || [], cfg.callback);
1638 }
1639 },
1640
1641 makeShimExports: function (value) {
1642 function fn() {
1643 var ret;
1644 if (value.init) {
1645 ret = value.init.apply(global, arguments);
1646 }
1647 return ret || (value.exports && getGlobal(value.exports));
1648 }
1649 return fn;
1650 },
1651
1652 makeRequire: function (relMap, options) {
1653 options = options || {};
1654
1655 function localRequire(deps, callback, errback) {
1656 var id, map, requireMod;
1657
1658 if (options.enableBuildCallback && callback && isFunction(callback)) {
1659 callback.__requireJsBuild = true;
1660 }
1661
1662 if (typeof deps === 'string') {
1663 if (isFunction(callback)) {
1664 //Invalid call
1665 return onError(makeError('requireargs', 'Invalid require call'), errback);
1666 }
1667
1668 //If require|exports|module are requested, get the
1669 //value for them from the special handlers. Caveat:
1670 //this only works while module is being defined.
1671 if (relMap && hasProp(handlers, deps)) {
1672 return handlers[deps](registry[relMap.id]);
1673 }
1674
1675 //Synchronous access to one module. If require.get is
1676 //available (as in the Node adapter), prefer that.
1677 if (req.get) {
1678 return req.get(context, deps, relMap, localRequire);
1679 }
1680
1681 //Normalize module name, if it contains . or ..
1682 map = makeModuleMap(deps, relMap, false, true);
1683 id = map.id;
1684
1685 if (!hasProp(defined, id)) {
1686 return onError(makeError('notloaded', 'Module name "' +
1687 id +
1688 '" has not been loaded yet for context: ' +
1689 contextName +
1690 (relMap ? '' : '. Use require([])')));
1691 }
1692 return defined[id];
1693 }
1694
1695 //Grab defines waiting in the global queue.
1696 intakeDefines();
1697
1698 //Mark all the dependencies as needing to be loaded.
1699 context.nextTick(function () {
1700 //Some defines could have been added since the
1701 //require call, collect them.
1702 intakeDefines();
1703
1704 requireMod = getModule(makeModuleMap(null, relMap));
1705
1706 //Store if map config should be applied to this require
1707 //call for dependencies.
1708 requireMod.skipMap = options.skipMap;
1709
1710 requireMod.init(deps, callback, errback, {
1711 enabled: true
1712 });
1713
1714 checkLoaded();
1715 });
1716
1717 return localRequire;
1718 }
1719
1720 mixin(localRequire, {
1721 isBrowser: isBrowser,
1722
1723 /**
1724 * Converts a module name + .extension into an URL path.
1725 * *Requires* the use of a module name. It does not support using
1726 * plain URLs like nameToUrl.
1727 */
1728 toUrl: function (moduleNamePlusExt) {
1729 var ext,
1730 index = moduleNamePlusExt.lastIndexOf('.'),
1731 segment = moduleNamePlusExt.split('/')[0],
1732 isRelative = segment === '.' || segment === '..';
1733
1734 //Have a file extension alias, and it is not the
1735 //dots from a relative path.
1736 if (index !== -1 && (!isRelative || index > 1)) {
1737 ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
1738 moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
1739 }
1740
1741 return context.nameToUrl(normalize(moduleNamePlusExt,
1742 relMap && relMap.id, true), ext, true);
1743 },
1744
1745 defined: function (id) {
1746 return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
1747 },
1748
1749 specified: function (id) {
1750 id = makeModuleMap(id, relMap, false, true).id;
1751 return hasProp(defined, id) || hasProp(registry, id);
1752 }
1753 });
1754
1755 //Only allow undef on top level require calls
1756 if (!relMap) {
1757 localRequire.undef = function (id) {
1758 //Bind any waiting define() calls to this context,
1759 //fix for #408
1760 takeGlobalQueue();
1761
1762 var map = makeModuleMap(id, relMap, true),
1763 mod = getOwn(registry, id);
1764
1765 mod.undefed = true;
1766 removeScript(id);
1767
1768 delete defined[id];
1769 delete urlFetched[map.url];
1770 delete undefEvents[id];
1771
1772 //Clean queued defines too. Go backwards
1773 //in array so that the splices do not
1774 //mess up the iteration.
1775 eachReverse(defQueue, function(args, i) {
1776 if (args[0] === id) {
1777 defQueue.splice(i, 1);
1778 }
1779 });
1780 delete context.defQueueMap[id];
1781
1782 if (mod) {
1783 //Hold on to listeners in case the
1784 //module will be attempted to be reloaded
1785 //using a different config.
1786 if (mod.events.defined) {
1787 undefEvents[id] = mod.events;
1788 }
1789
1790 cleanRegistry(id);
1791 }
1792 };
1793 }
1794
1795 return localRequire;
1796 },
1797
1798 /**
1799 * Called to enable a module if it is still in the registry
1800 * awaiting enablement. A second arg, parent, the parent module,
1801 * is passed in for context, when this method is overridden by
1802 * the optimizer. Not shown here to keep code compact.
1803 */
1804 enable: function (depMap) {
1805 var mod = getOwn(registry, depMap.id);
1806 if (mod) {
1807 getModule(depMap).enable();
1808 }
1809 },
1810
1811 /**
1812 * Internal method used by environment adapters to complete a load event.
1813 * A load event could be a script load or just a load pass from a synchronous
1814 * load call.
1815 * @param {String} moduleName the name of the module to potentially complete.
1816 */
1817 completeLoad: function (moduleName) {
1818 var found, args, mod,
1819 shim = getOwn(config.shim, moduleName) || {},
1820 shExports = shim.exports;
1821
1822 takeGlobalQueue();
1823
1824 while (defQueue.length) {
1825 args = defQueue.shift();
1826 if (args[0] === null) {
1827 args[0] = moduleName;
1828 //If already found an anonymous module and bound it
1829 //to this name, then this is some other anon module
1830 //waiting for its completeLoad to fire.
1831 if (found) {
1832 break;
1833 }
1834 found = true;
1835 } else if (args[0] === moduleName) {
1836 //Found matching define call for this script!
1837 found = true;
1838 }
1839
1840 callGetModule(args);
1841 }
1842 context.defQueueMap = {};
1843
1844 //Do this after the cycle of callGetModule in case the result
1845 //of those calls/init calls changes the registry.
1846 mod = getOwn(registry, moduleName);
1847
1848 if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
1849 if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
1850 if (hasPathFallback(moduleName)) {
1851 return;
1852 } else {
1853 return onError(makeError('nodefine',
1854 'No define call for ' + moduleName,
1855 null,
1856 [moduleName]));
1857 }
1858 } else {
1859 //A script that does not call define(), so just simulate
1860 //the call for it.
1861 callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
1862 }
1863 }
1864
1865 checkLoaded();
1866 },
1867
1868 /**
1869 * Converts a module name to a file path. Supports cases where
1870 * moduleName may actually be just an URL.
1871 * Note that it **does not** call normalize on the moduleName,
1872 * it is assumed to have already been normalized. This is an
1873 * internal API, not a public one. Use toUrl for the public API.
1874 */
1875 nameToUrl: function (moduleName, ext, skipExt) {
1876 var paths, syms, i, parentModule, url,
1877 parentPath, bundleId,
1878 pkgMain = getOwn(config.pkgs, moduleName);
1879
1880 if (pkgMain) {
1881 moduleName = pkgMain;
1882 }
1883
1884 bundleId = getOwn(bundlesMap, moduleName);
1885
1886 if (bundleId) {
1887 return context.nameToUrl(bundleId, ext, skipExt);
1888 }
1889
1890 //If a colon is in the URL, it indicates a protocol is used and it is just
1891 //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
1892 //or ends with .js, then assume the user meant to use an url and not a module id.
1893 //The slash is important for protocol-less URLs as well as full paths.
1894 if (req.jsExtRegExp.test(moduleName)) {
1895 //Just a plain path, not module name lookup, so just return it.
1896 //Add extension if it is included. This is a bit wonky, only non-.js things pass
1897 //an extension, this method probably needs to be reworked.
1898 url = moduleName + (ext || '');
1899 } else {
1900 //A module that needs to be converted to a path.
1901 paths = config.paths;
1902
1903 syms = moduleName.split('/');
1904 //For each module name segment, see if there is a path
1905 //registered for it. Start with most specific name
1906 //and work up from it.
1907 for (i = syms.length; i > 0; i -= 1) {
1908 parentModule = syms.slice(0, i).join('/');
1909
1910 parentPath = getOwn(paths, parentModule);
1911 if (parentPath) {
1912 //If an array, it means there are a few choices,
1913 //Choose the one that is desired
1914 if (isArray(parentPath)) {
1915 parentPath = parentPath[0];
1916 }
1917 syms.splice(0, i, parentPath);
1918 break;
1919 }
1920 }
1921
1922 //Join the path parts together, then figure out if baseUrl is needed.
1923 url = syms.join('/');
1924 url += (ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? '' : '.js'));
1925 url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
1926 }
1927
1928 return config.urlArgs && !/^blob\:/.test(url) ?
1929 url + config.urlArgs(moduleName, url) : url;
1930 },
1931
1932 //Delegates to req.load. Broken out as a separate function to
1933 //allow overriding in the optimizer.
1934 load: function (id, url) {
1935 req.load(context, id, url);
1936 },
1937
1938 /**
1939 * Executes a module callback function. Broken out as a separate function
1940 * solely to allow the build system to sequence the files in the built
1941 * layer in the right sequence.
1942 *
1943 * @private
1944 */
1945 execCb: function (name, callback, args, exports) {
1946 return callback.apply(exports, args);
1947 },
1948
1949 /**
1950 * callback for script loads, used to check status of loading.
1951 *
1952 * @param {Event} evt the event from the browser for the script
1953 * that was loaded.
1954 */
1955 onScriptLoad: function (evt) {
1956 //Using currentTarget instead of target for Firefox 2.0's sake. Not
1957 //all old browsers will be supported, but this one was easy enough
1958 //to support and still makes sense.
1959 if (evt.type === 'load' ||
1960 (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
1961 //Reset interactive script so a script node is not held onto for
1962 //to long.
1963 interactiveScript = null;
1964
1965 //Pull out the name of the module and the context.
1966 var data = getScriptData(evt);
1967 context.completeLoad(data.id);
1968 }
1969 },
1970
1971 /**
1972 * Callback for script errors.
1973 */
1974 onScriptError: function (evt) {
1975 var data = getScriptData(evt);
1976 if (!hasPathFallback(data.id)) {
1977 var parents = [];
1978 eachProp(registry, function(value, key) {
1979 if (key.indexOf('_@r') !== 0) {
1980 each(value.depMaps, function(depMap) {
1981 if (depMap.id === data.id) {
1982 parents.push(key);
1983 return true;
1984 }
1985 });
1986 }
1987 });
1988 return onError(makeError('scripterror', 'Script error for "' + data.id +
1989 (parents.length ?
1990 '", needed by: ' + parents.join(', ') :
1991 '"'), evt, [data.id]));
1992 }
1993 }
1994 };
1995
1996 context.require = context.makeRequire();
1997 return context;
1998 }
1999
2000 /**
2001 * Main entry point.
2002 *
2003 * If the only argument to require is a string, then the module that
2004 * is represented by that string is fetched for the appropriate context.
2005 *
2006 * If the first argument is an array, then it will be treated as an array
2007 * of dependency string names to fetch. An optional function callback can
2008 * be specified to execute when all of those dependencies are available.
2009 *
2010 * Make a local req variable to help Caja compliance (it assumes things
2011 * on a require that are not standardized), and to give a short
2012 * name for minification/local scope use.
2013 */
2014 req = requirejs = function (deps, callback, errback, optional) {
2015
2016 //Find the right context, use default
2017 var context, config,
2018 contextName = defContextName;
2019
2020 // Determine if have config object in the call.
2021 if (!isArray(deps) && typeof deps !== 'string') {
2022 // deps is a config object
2023 config = deps;
2024 if (isArray(callback)) {
2025 // Adjust args if there are dependencies
2026 deps = callback;
2027 callback = errback;
2028 errback = optional;
2029 } else {
2030 deps = [];
2031 }
2032 }
2033
2034 if (config && config.context) {
2035 contextName = config.context;
2036 }
2037
2038 context = getOwn(contexts, contextName);
2039 if (!context) {
2040 context = contexts[contextName] = req.s.newContext(contextName);
2041 }
2042
2043 if (config) {
2044 context.configure(config);
2045 }
2046
2047 return context.require(deps, callback, errback);
2048 };
2049
2050 /**
2051 * Support require.config() to make it easier to cooperate with other
2052 * AMD loaders on globally agreed names.
2053 */
2054 req.config = function (config) {
2055 return req(config);
2056 };
2057
2058 /**
2059 * Execute something after the current tick
2060 * of the event loop. Override for other envs
2061 * that have a better solution than setTimeout.
2062 * @param {Function} fn function to execute later.
2063 */
2064 req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
2065 setTimeout(fn, 4);
2066 } : function (fn) { fn(); };
2067
2068 /**
2069 * Export require as a global, but only if it does not already exist.
2070 */
2071 if (!require) {
2072 require = req;
2073 }
2074
2075 req.version = version;
2076
2077 //Used to filter out dependencies that are already paths.
2078 req.jsExtRegExp = /^\/|:|\?|\.js$/;
2079 req.isBrowser = isBrowser;
2080 s = req.s = {
2081 contexts: contexts,
2082 newContext: newContext
2083 };
2084
2085 //Create default context.
2086 req({});
2087
2088 //Exports some context-sensitive methods on global require.
2089 each([
2090 'toUrl',
2091 'undef',
2092 'defined',
2093 'specified'
2094 ], function (prop) {
2095 //Reference from contexts instead of early binding to default context,
2096 //so that during builds, the latest instance of the default context
2097 //with its config gets used.
2098 req[prop] = function () {
2099 var ctx = contexts[defContextName];
2100 return ctx.require[prop].apply(ctx, arguments);
2101 };
2102 });
2103
2104 if (isBrowser) {
2105 head = s.head = document.getElementsByTagName('head')[0];
2106 //If BASE tag is in play, using appendChild is a problem for IE6.
2107 //When that browser dies, this can be removed. Details in this jQuery bug:
2108 //http://dev.jquery.com/ticket/2709
2109 baseElement = document.getElementsByTagName('base')[0];
2110 if (baseElement) {
2111 head = s.head = baseElement.parentNode;
2112 }
2113 }
2114
2115 /**
2116 * Any errors that require explicitly generates will be passed to this
2117 * function. Intercept/override it if you want custom error handling.
2118 * @param {Error} err the error object.
2119 */
2120 req.onError = defaultOnError;
2121
2122 /**
2123 * Creates the node for the load command. Only used in browser envs.
2124 */
2125 req.createNode = function (config, moduleName, url) {
2126 var node = config.xhtml ?
2127 document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
2128 document.createElement('script');
2129 node.type = config.scriptType || 'text/javascript';
2130 node.charset = 'utf-8';
2131 node.async = true;
2132 return node;
2133 };
2134
2135 /**
2136 * Does the request to load a module for the browser case.
2137 * Make this a separate function to allow other environments
2138 * to override it.
2139 *
2140 * @param {Object} context the require context to find state.
2141 * @param {String} moduleName the name of the module.
2142 * @param {Object} url the URL to the module.
2143 */
2144 req.load = function (context, moduleName, url) {
2145 var config = (context && context.config) || {},
2146 node;
2147 if (isBrowser) {
2148 //In the browser so use a script tag
2149 node = req.createNode(config, moduleName, url);
2150
2151 node.setAttribute('data-requirecontext', context.contextName);
2152 node.setAttribute('data-requiremodule', moduleName);
2153
2154 //Set up load listener. Test attachEvent first because IE9 has
2155 //a subtle issue in its addEventListener and script onload firings
2156 //that do not match the behavior of all other browsers with
2157 //addEventListener support, which fire the onload event for a
2158 //script right after the script execution. See:
2159 //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
2160 //UNFORTUNATELY Opera implements attachEvent but does not follow the script
2161 //script execution mode.
2162 if (node.attachEvent &&
2163 //Check if node.attachEvent is artificially added by custom script or
2164 //natively supported by browser
2165 //read https://github.com/requirejs/requirejs/issues/187
2166 //if we can NOT find [native code] then it must NOT natively supported.
2167 //in IE8, node.attachEvent does not have toString()
2168 //Note the test for "[native code" with no closing brace, see:
2169 //https://github.com/requirejs/requirejs/issues/273
2170 !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
2171 !isOpera) {
2172 //Probably IE. IE (at least 6-8) do not fire
2173 //script onload right after executing the script, so
2174 //we cannot tie the anonymous define call to a name.
2175 //However, IE reports the script as being in 'interactive'
2176 //readyState at the time of the define call.
2177 useInteractive = true;
2178
2179 node.attachEvent('onreadystatechange', context.onScriptLoad);
2180 //It would be great to add an error handler here to catch
2181 //404s in IE9+. However, onreadystatechange will fire before
2182 //the error handler, so that does not help. If addEventListener
2183 //is used, then IE will fire error before load, but we cannot
2184 //use that pathway given the connect.microsoft.com issue
2185 //mentioned above about not doing the 'script execute,
2186 //then fire the script load event listener before execute
2187 //next script' that other browsers do.
2188 //Best hope: IE10 fixes the issues,
2189 //and then destroys all installs of IE 6-9.
2190 //node.attachEvent('onerror', context.onScriptError);
2191 } else {
2192 node.addEventListener('load', context.onScriptLoad, false);
2193 node.addEventListener('error', context.onScriptError, false);
2194 }
2195 node.src = url;
2196
2197 //Calling onNodeCreated after all properties on the node have been
2198 //set, but before it is placed in the DOM.
2199 if (config.onNodeCreated) {
2200 config.onNodeCreated(node, config, moduleName, url);
2201 }
2202
2203 //For some cache cases in IE 6-8, the script executes before the end
2204 //of the appendChild execution, so to tie an anonymous define
2205 //call to the module name (which is stored on the node), hold on
2206 //to a reference to this node, but clear after the DOM insertion.
2207 currentlyAddingScript = node;
2208 if (baseElement) {
2209 head.insertBefore(node, baseElement);
2210 } else {
2211 head.appendChild(node);
2212 }
2213 currentlyAddingScript = null;
2214
2215 return node;
2216 } else if (isWebWorker) {
2217 try {
2218 //In a web worker, use importScripts. This is not a very
2219 //efficient use of importScripts, importScripts will block until
2220 //its script is downloaded and evaluated. However, if web workers
2221 //are in play, the expectation is that a build has been done so
2222 //that only one script needs to be loaded anyway. This may need
2223 //to be reevaluated if other use cases become common.
2224
2225 // Post a task to the event loop to work around a bug in WebKit
2226 // where the worker gets garbage-collected after calling
2227 // importScripts(): https://webkit.org/b/153317
2228 setTimeout(function() {}, 0);
2229 importScripts(url);
2230
2231 //Account for anonymous modules
2232 context.completeLoad(moduleName);
2233 } catch (e) {
2234 context.onError(makeError('importscripts',
2235 'importScripts failed for ' +
2236 moduleName + ' at ' + url,
2237 e,
2238 [moduleName]));
2239 }
2240 }
2241 };
2242
2243 function getInteractiveScript() {
2244 if (interactiveScript && interactiveScript.readyState === 'interactive') {
2245 return interactiveScript;
2246 }
2247
2248 eachReverse(scripts(), function (script) {
2249 if (script.readyState === 'interactive') {
2250 return (interactiveScript = script);
2251 }
2252 });
2253 return interactiveScript;
2254 }
2255
2256 //Look for a data-main script attribute, which could also adjust the baseUrl.
2257 if (isBrowser && !cfg.skipDataMain) {
2258 //Figure out baseUrl. Get it from the script tag with require.js in it.
2259 eachReverse(scripts(), function (script) {
2260 //Set the 'head' where we can append children by
2261 //using the script's parent.
2262 if (!head) {
2263 head = script.parentNode;
2264 }
2265
2266 //Look for a data-main attribute to set main script for the page
2267 //to load. If it is there, the path to data main becomes the
2268 //baseUrl, if it is not already set.
2269 dataMain = script.getAttribute('data-main');
2270 if (dataMain) {
2271 //Preserve dataMain in case it is a path (i.e. contains '?')
2272 mainScript = dataMain;
2273
2274 //Set final baseUrl if there is not already an explicit one,
2275 //but only do so if the data-main value is not a loader plugin
2276 //module ID.
2277 if (!cfg.baseUrl && mainScript.indexOf('!') === -1) {
2278 //Pull off the directory of data-main for use as the
2279 //baseUrl.
2280 src = mainScript.split('/');
2281 mainScript = src.pop();
2282 subPath = src.length ? src.join('/') + '/' : './';
2283
2284 cfg.baseUrl = subPath;
2285 }
2286
2287 //Strip off any trailing .js since mainScript is now
2288 //like a module name.
2289 mainScript = mainScript.replace(jsSuffixRegExp, '');
2290
2291 //If mainScript is still a path, fall back to dataMain
2292 if (req.jsExtRegExp.test(mainScript)) {
2293 mainScript = dataMain;
2294 }
2295
2296 //Put the data-main script in the files to load.
2297 cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
2298
2299 return true;
2300 }
2301 });
2302 }
2303
2304 /**
2305 * The function that handles definitions of modules. Differs from
2306 * require() in that a string for the module should be the first argument,
2307 * and the function to execute after dependencies are loaded should
2308 * return a value to define the module corresponding to the first argument's
2309 * name.
2310 */
2311 define = function (name, deps, callback) {
2312 var node, context;
2313
2314 //Allow for anonymous modules
2315 if (typeof name !== 'string') {
2316 //Adjust args appropriately
2317 callback = deps;
2318 deps = name;
2319 name = null;
2320 }
2321
2322 //This module may not have dependencies
2323 if (!isArray(deps)) {
2324 callback = deps;
2325 deps = null;
2326 }
2327
2328 //If no name, and callback is a function, then figure out if it a
2329 //CommonJS thing with dependencies.
2330 if (!deps && isFunction(callback)) {
2331 deps = [];
2332 //Remove comments from the callback string,
2333 //look for require calls, and pull them into the dependencies,
2334 //but only if there are function args.
2335 if (callback.length) {
2336 callback
2337 .toString()
2338 .replace(commentRegExp, commentReplace)
2339 .replace(cjsRequireRegExp, function (match, dep) {
2340 deps.push(dep);
2341 });
2342
2343 //May be a CommonJS thing even without require calls, but still
2344 //could use exports, and module. Avoid doing exports and module
2345 //work though if it just needs require.
2346 //REQUIRES the function to expect the CommonJS variables in the
2347 //order listed below.
2348 deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
2349 }
2350 }
2351
2352 //If in IE 6-8 and hit an anonymous define() call, do the interactive
2353 //work.
2354 if (useInteractive) {
2355 node = currentlyAddingScript || getInteractiveScript();
2356 if (node) {
2357 if (!name) {
2358 name = node.getAttribute('data-requiremodule');
2359 }
2360 context = contexts[node.getAttribute('data-requirecontext')];
2361 }
2362 }
2363
2364 //Always save off evaluating the def call until the script onload handler.
2365 //This allows multiple modules to be in a file without prematurely
2366 //tracing dependencies, and allows for anonymous module support,
2367 //where the module name is not known until the script onload event
2368 //occurs. If no context, use the global queue, and get it processed
2369 //in the onscript load callback.
2370 if (context) {
2371 context.defQueue.push([name, deps, callback]);
2372 context.defQueueMap[name] = true;
2373 } else {
2374 globalDefQueue.push([name, deps, callback]);
2375 }
2376 };
2377
2378 define.amd = {
2379 jQuery: true
2380 };
2381
2382 /**
2383 * Executes the text. Normally just uses eval, but can be modified
2384 * to use a better, environment-specific call. Only used for transpiling
2385 * loader plugins, not for plain JS modules.
2386 * @param {String} text the text to execute/evaluate.
2387 */
2388 req.exec = function (text) {
2389 /*jslint evil: true */
2390 return eval(text);
2391 };
2392
2393 //Set up with config info.
2394 req(cfg);
2395}(this, (typeof setTimeout === 'undefined' ? undefined : setTimeout)));
2396
2397
2398
2399 this.requirejsVars = {
2400 require: require,
2401 requirejs: require,
2402 define: define
2403 };
2404
2405 if (env === 'browser') {
2406 //sloppy since eval enclosed with use strict causes problems if the source
2407//text is not strict-compliant.
2408/*jslint sloppy: true, evil: true */
2409/*global require, XMLHttpRequest */
2410
2411(function () {
2412 // Separate function to avoid eval pollution, same with arguments use.
2413 function exec() {
2414 eval(arguments[0]);
2415 }
2416
2417 require.load = function (context, moduleName, url) {
2418 var xhr = new XMLHttpRequest();
2419
2420 xhr.open('GET', url, true);
2421 xhr.send();
2422
2423 xhr.onreadystatechange = function () {
2424 if (xhr.readyState === 4) {
2425 exec(xhr.responseText);
2426
2427 //Support anonymous modules.
2428 context.completeLoad(moduleName);
2429 }
2430 };
2431 };
2432}());
2433 } else if (env === 'rhino') {
2434 /*global require: false, java: false, load: false */
2435
2436(function () {
2437 'use strict';
2438 require.load = function (context, moduleName, url) {
2439
2440 load(url);
2441
2442 //Support anonymous modules.
2443 context.completeLoad(moduleName);
2444 };
2445
2446}());
2447 } else if (env === 'node') {
2448 this.requirejsVars.nodeRequire = nodeRequire;
2449 require.nodeRequire = nodeRequire;
2450
2451 //Explicity not strict since this file contains an eval call, and do not want
2452//to enforce strict on code evaluated that way. See
2453//https://github.com/requirejs/r.js/issues/774
2454/*jslint regexp: false, sloppy: true*/
2455/*global require: false, define: false, requirejsVars: false, process: false */
2456
2457/**
2458 * This adapter assumes that x.js has loaded it and set up
2459 * some variables. This adapter just allows limited RequireJS
2460 * usage from within the requirejs directory. The general
2461 * node adapater is r.js.
2462 */
2463
2464(function () {
2465 var nodeReq = requirejsVars.nodeRequire,
2466 req = requirejsVars.require,
2467 def = requirejsVars.define,
2468 fs = nodeReq('fs'),
2469 path = nodeReq('path'),
2470 vm = nodeReq('vm'),
2471 //In Node 0.7+ existsSync is on fs.
2472 exists = fs.existsSync || path.existsSync,
2473 hasOwn = Object.prototype.hasOwnProperty;
2474
2475 function hasProp(obj, prop) {
2476 return hasOwn.call(obj, prop);
2477 }
2478
2479 function syncTick(fn) {
2480 fn();
2481 }
2482
2483 function makeError(message, moduleName) {
2484 var err = new Error(message);
2485 err.requireModules = [moduleName];
2486 return err;
2487 }
2488
2489 //Supply an implementation that allows synchronous get of a module.
2490 req.get = function (context, moduleName, relModuleMap, localRequire) {
2491 if (moduleName === "require" || moduleName === "exports" || moduleName === "module") {
2492 context.onError(makeError("Explicit require of " + moduleName + " is not allowed.", moduleName));
2493 }
2494
2495 var ret, oldTick,
2496 moduleMap = context.makeModuleMap(moduleName, relModuleMap, false, true);
2497
2498 //Normalize module name, if it contains . or ..
2499 moduleName = moduleMap.id;
2500
2501 if (hasProp(context.defined, moduleName)) {
2502 ret = context.defined[moduleName];
2503 } else {
2504 if (ret === undefined) {
2505 //Make sure nextTick for this type of call is sync-based.
2506 oldTick = context.nextTick;
2507 context.nextTick = syncTick;
2508 try {
2509 if (moduleMap.prefix) {
2510 //A plugin, call requirejs to handle it. Now that
2511 //nextTick is syncTick, the require will complete
2512 //synchronously.
2513 localRequire([moduleMap.originalName]);
2514
2515 //Now that plugin is loaded, can regenerate the moduleMap
2516 //to get the final, normalized ID.
2517 moduleMap = context.makeModuleMap(moduleMap.originalName, relModuleMap, false, true);
2518 moduleName = moduleMap.id;
2519 } else {
2520 //Try to dynamically fetch it.
2521 req.load(context, moduleName, moduleMap.url);
2522
2523 //Enable the module
2524 context.enable(moduleMap, relModuleMap);
2525 }
2526
2527 //Break any cycles by requiring it normally, but this will
2528 //finish synchronously
2529 context.require([moduleName]);
2530
2531 //The above calls are sync, so can do the next thing safely.
2532 ret = context.defined[moduleName];
2533 } finally {
2534 context.nextTick = oldTick;
2535 }
2536 }
2537 }
2538
2539 return ret;
2540 };
2541
2542 req.nextTick = function (fn) {
2543 process.nextTick(fn);
2544 };
2545
2546 //Add wrapper around the code so that it gets the requirejs
2547 //API instead of the Node API, and it is done lexically so
2548 //that it survives later execution.
2549 req.makeNodeWrapper = function (contents) {
2550 return '(function (require, requirejs, define) { ' +
2551 contents +
2552 '\n}(requirejsVars.require, requirejsVars.requirejs, requirejsVars.define));';
2553 };
2554
2555 req.load = function (context, moduleName, url) {
2556 var contents, err,
2557 config = context.config;
2558
2559 if (config.shim[moduleName] && (!config.suppress || !config.suppress.nodeShim)) {
2560 console.warn('Shim config not supported in Node, may or may not work. Detected ' +
2561 'for module: ' + moduleName);
2562 }
2563
2564 if (exists(url)) {
2565 contents = fs.readFileSync(url, 'utf8');
2566
2567 contents = req.makeNodeWrapper(contents);
2568 try {
2569 vm.runInThisContext(contents, fs.realpathSync(url));
2570 } catch (e) {
2571 err = new Error('Evaluating ' + url + ' as module "' +
2572 moduleName + '" failed with error: ' + e);
2573 err.originalError = e;
2574 err.moduleName = moduleName;
2575 err.requireModules = [moduleName];
2576 err.fileName = url;
2577 return context.onError(err);
2578 }
2579 } else {
2580 def(moduleName, function () {
2581 //Get the original name, since relative requires may be
2582 //resolved differently in node (issue #202). Also, if relative,
2583 //make it relative to the URL of the item requesting it
2584 //(issue #393)
2585 var dirName,
2586 map = hasProp(context.registry, moduleName) &&
2587 context.registry[moduleName].map,
2588 parentMap = map && map.parentMap,
2589 originalName = map && map.originalName;
2590
2591 if (originalName.charAt(0) === '.' && parentMap) {
2592 dirName = parentMap.url.split('/');
2593 dirName.pop();
2594 originalName = dirName.join('/') + '/' + originalName;
2595 }
2596
2597 try {
2598 return (context.config.nodeRequire || req.nodeRequire)(originalName);
2599 } catch (e) {
2600 err = new Error('Tried loading "' + moduleName + '" at ' +
2601 url + ' then tried node\'s require("' +
2602 originalName + '") and it failed ' +
2603 'with error: ' + e);
2604 err.originalError = e;
2605 err.moduleName = originalName;
2606 err.requireModules = [moduleName];
2607 throw err;
2608 }
2609 });
2610 }
2611
2612 //Support anonymous modules.
2613 context.completeLoad(moduleName);
2614 };
2615
2616 //Override to provide the function wrapper for define/require.
2617 req.exec = function (text) {
2618 /*jslint evil: true */
2619 text = req.makeNodeWrapper(text);
2620 return eval(text);
2621 };
2622}());
2623
2624 } else if (env === 'xpconnect') {
2625 /*jslint */
2626/*global require, load */
2627
2628(function () {
2629 'use strict';
2630 require.load = function (context, moduleName, url) {
2631
2632 load(url);
2633
2634 //Support anonymous modules.
2635 context.completeLoad(moduleName);
2636 };
2637
2638}());
2639
2640 }
2641
2642 //Support a default file name to execute. Useful for hosted envs
2643 //like Joyent where it defaults to a server.js as the only executed
2644 //script. But only do it if this is not an optimization run.
2645 if (commandOption !== 'o' && (!fileName || !jsSuffixRegExp.test(fileName))) {
2646 fileName = 'main.js';
2647 }
2648
2649 /**
2650 * Loads the library files that can be used for the optimizer, or for other
2651 * tasks.
2652 */
2653 function loadLib() {
2654 /*jslint strict: false */
2655/*global Packages: false, process: false, window: false, navigator: false,
2656 document: false, define: false */
2657
2658/**
2659 * A plugin that modifies any /env/ path to be the right path based on
2660 * the host environment. Right now only works for Node, Rhino and browser.
2661 */
2662(function () {
2663 var pathRegExp = /(\/|^)env\/|\{env\}/,
2664 env = 'unknown';
2665
2666 if (typeof process !== 'undefined' && process.versions && !!process.versions.node) {
2667 env = 'node';
2668 } else if (typeof Packages !== 'undefined') {
2669 env = 'rhino';
2670 } else if ((typeof navigator !== 'undefined' && typeof document !== 'undefined') ||
2671 (typeof importScripts !== 'undefined' && typeof self !== 'undefined')) {
2672 env = 'browser';
2673 } else if (typeof Components !== 'undefined' && Components.classes && Components.interfaces) {
2674 env = 'xpconnect';
2675 }
2676
2677 define('env', {
2678 get: function () {
2679 return env;
2680 },
2681
2682 load: function (name, req, load, config) {
2683 //Allow override in the config.
2684 if (config.env) {
2685 env = config.env;
2686 }
2687
2688 name = name.replace(pathRegExp, function (match, prefix) {
2689 if (match.indexOf('{') === -1) {
2690 return prefix + env + '/';
2691 } else {
2692 return env;
2693 }
2694 });
2695
2696 req([name], function (mod) {
2697 load(mod);
2698 });
2699 }
2700 });
2701}());
2702/*jslint plusplus: true */
2703/*global define, java */
2704
2705define('lang', function () {
2706 'use strict';
2707
2708 var lang, isJavaObj,
2709 hasOwn = Object.prototype.hasOwnProperty;
2710
2711 function hasProp(obj, prop) {
2712 return hasOwn.call(obj, prop);
2713 }
2714
2715 isJavaObj = function () {
2716 return false;
2717 };
2718
2719 //Rhino, but not Nashorn (detected by importPackage not existing)
2720 //Can have some strange foreign objects.
2721 if (typeof java !== 'undefined' && java.lang && java.lang.Object && typeof importPackage !== 'undefined') {
2722 isJavaObj = function (obj) {
2723 return obj instanceof java.lang.Object;
2724 };
2725 }
2726
2727 lang = {
2728 backSlashRegExp: /\\/g,
2729 ostring: Object.prototype.toString,
2730
2731 isArray: Array.isArray || function (it) {
2732 return lang.ostring.call(it) === "[object Array]";
2733 },
2734
2735 isFunction: function(it) {
2736 return lang.ostring.call(it) === "[object Function]";
2737 },
2738
2739 isRegExp: function(it) {
2740 return it && it instanceof RegExp;
2741 },
2742
2743 hasProp: hasProp,
2744
2745 //returns true if the object does not have an own property prop,
2746 //or if it does, it is a falsy value.
2747 falseProp: function (obj, prop) {
2748 return !hasProp(obj, prop) || !obj[prop];
2749 },
2750
2751 //gets own property value for given prop on object
2752 getOwn: function (obj, prop) {
2753 return hasProp(obj, prop) && obj[prop];
2754 },
2755
2756 _mixin: function(dest, source, override){
2757 var name;
2758 for (name in source) {
2759 if(source.hasOwnProperty(name) &&
2760 (override || !dest.hasOwnProperty(name))) {
2761 dest[name] = source[name];
2762 }
2763 }
2764
2765 return dest; // Object
2766 },
2767
2768 /**
2769 * mixin({}, obj1, obj2) is allowed. If the last argument is a boolean,
2770 * then the source objects properties are force copied over to dest.
2771 */
2772 mixin: function(dest){
2773 var parameters = Array.prototype.slice.call(arguments),
2774 override, i, l;
2775
2776 if (!dest) { dest = {}; }
2777
2778 if (parameters.length > 2 && typeof arguments[parameters.length-1] === 'boolean') {
2779 override = parameters.pop();
2780 }
2781
2782 for (i = 1, l = parameters.length; i < l; i++) {
2783 lang._mixin(dest, parameters[i], override);
2784 }
2785 return dest; // Object
2786 },
2787
2788 /**
2789 * Does a deep mix of source into dest, where source values override
2790 * dest values if a winner is needed.
2791 * @param {Object} dest destination object that receives the mixed
2792 * values.
2793 * @param {Object} source source object contributing properties to mix
2794 * in.
2795 * @return {[Object]} returns dest object with the modification.
2796 */
2797 deepMix: function(dest, source) {
2798 lang.eachProp(source, function (value, prop) {
2799 if (typeof value === 'object' && value &&
2800 !lang.isArray(value) && !lang.isFunction(value) &&
2801 !(value instanceof RegExp)) {
2802
2803 if (!dest[prop]) {
2804 dest[prop] = {};
2805 }
2806 lang.deepMix(dest[prop], value);
2807 } else {
2808 dest[prop] = value;
2809 }
2810 });
2811 return dest;
2812 },
2813
2814 /**
2815 * Does a type of deep copy. Do not give it anything fancy, best
2816 * for basic object copies of objects that also work well as
2817 * JSON-serialized things, or has properties pointing to functions.
2818 * For non-array/object values, just returns the same object.
2819 * @param {Object} obj copy properties from this object
2820 * @param {Object} [ignoredProps] optional object whose own properties
2821 * are keys that should be ignored.
2822 * @return {Object}
2823 */
2824 deeplikeCopy: function (obj, ignoredProps) {
2825 var type, result;
2826
2827 if (lang.isArray(obj)) {
2828 result = [];
2829 obj.forEach(function(value) {
2830 result.push(lang.deeplikeCopy(value, ignoredProps));
2831 });
2832 return result;
2833 }
2834
2835 type = typeof obj;
2836 if (obj === null || obj === undefined || type === 'boolean' ||
2837 type === 'string' || type === 'number' || lang.isFunction(obj) ||
2838 lang.isRegExp(obj)|| isJavaObj(obj)) {
2839 return obj;
2840 }
2841
2842 //Anything else is an object, hopefully.
2843 result = {};
2844 lang.eachProp(obj, function(value, key) {
2845 if (!ignoredProps || !hasProp(ignoredProps, key)) {
2846 result[key] = lang.deeplikeCopy(value, ignoredProps);
2847 }
2848 });
2849 return result;
2850 },
2851
2852 delegate: (function () {
2853 // boodman/crockford delegation w/ cornford optimization
2854 function TMP() {}
2855 return function (obj, props) {
2856 TMP.prototype = obj;
2857 var tmp = new TMP();
2858 TMP.prototype = null;
2859 if (props) {
2860 lang.mixin(tmp, props);
2861 }
2862 return tmp; // Object
2863 };
2864 }()),
2865
2866 /**
2867 * Helper function for iterating over an array. If the func returns
2868 * a true value, it will break out of the loop.
2869 */
2870 each: function each(ary, func) {
2871 if (ary) {
2872 var i;
2873 for (i = 0; i < ary.length; i += 1) {
2874 if (func(ary[i], i, ary)) {
2875 break;
2876 }
2877 }
2878 }
2879 },
2880
2881 /**
2882 * Cycles over properties in an object and calls a function for each
2883 * property value. If the function returns a truthy value, then the
2884 * iteration is stopped.
2885 */
2886 eachProp: function eachProp(obj, func) {
2887 var prop;
2888 for (prop in obj) {
2889 if (hasProp(obj, prop)) {
2890 if (func(obj[prop], prop)) {
2891 break;
2892 }
2893 }
2894 }
2895 },
2896
2897 //Similar to Function.prototype.bind, but the "this" object is specified
2898 //first, since it is easier to read/figure out what "this" will be.
2899 bind: function bind(obj, fn) {
2900 return function () {
2901 return fn.apply(obj, arguments);
2902 };
2903 },
2904
2905 //Escapes a content string to be be a string that has characters escaped
2906 //for inclusion as part of a JS string.
2907 jsEscape: function (content) {
2908 return content.replace(/(["'\\])/g, '\\$1')
2909 .replace(/[\f]/g, "\\f")
2910 .replace(/[\b]/g, "\\b")
2911 .replace(/[\n]/g, "\\n")
2912 .replace(/[\t]/g, "\\t")
2913 .replace(/[\r]/g, "\\r");
2914 }
2915 };
2916 return lang;
2917});
2918/**
2919 * prim 0.0.1 Copyright (c) 2012-2014, The Dojo Foundation All Rights Reserved.
2920 * Available via the MIT or new BSD license.
2921 * see: http://github.com/requirejs/prim for details
2922 */
2923
2924/*global setImmediate, process, setTimeout, define, module */
2925
2926//Set prime.hideResolutionConflict = true to allow "resolution-races"
2927//in promise-tests to pass.
2928//Since the goal of prim is to be a small impl for trusted code, it is
2929//more important to normally throw in this case so that we can find
2930//logic errors quicker.
2931
2932var prim;
2933(function () {
2934 'use strict';
2935 var op = Object.prototype,
2936 hasOwn = op.hasOwnProperty;
2937
2938 function hasProp(obj, prop) {
2939 return hasOwn.call(obj, prop);
2940 }
2941
2942 /**
2943 * Helper function for iterating over an array. If the func returns
2944 * a true value, it will break out of the loop.
2945 */
2946 function each(ary, func) {
2947 if (ary) {
2948 var i;
2949 for (i = 0; i < ary.length; i += 1) {
2950 if (ary[i]) {
2951 func(ary[i], i, ary);
2952 }
2953 }
2954 }
2955 }
2956
2957 function check(p) {
2958 if (hasProp(p, 'e') || hasProp(p, 'v')) {
2959 if (!prim.hideResolutionConflict) {
2960 throw new Error('Prim promise already resolved: ' +
2961 JSON.stringify(p));
2962 }
2963 return false;
2964 }
2965 return true;
2966 }
2967
2968 function notify(ary, value) {
2969 prim.nextTick(function () {
2970 each(ary, function (item) {
2971 item(value);
2972 });
2973 });
2974 }
2975
2976 prim = function prim() {
2977 var p,
2978 ok = [],
2979 fail = [];
2980
2981 return (p = {
2982 callback: function (yes, no) {
2983 if (no) {
2984 p.errback(no);
2985 }
2986
2987 if (hasProp(p, 'v')) {
2988 prim.nextTick(function () {
2989 yes(p.v);
2990 });
2991 } else {
2992 ok.push(yes);
2993 }
2994 },
2995
2996 errback: function (no) {
2997 if (hasProp(p, 'e')) {
2998 prim.nextTick(function () {
2999 no(p.e);
3000 });
3001 } else {
3002 fail.push(no);
3003 }
3004 },
3005
3006 finished: function () {
3007 return hasProp(p, 'e') || hasProp(p, 'v');
3008 },
3009
3010 rejected: function () {
3011 return hasProp(p, 'e');
3012 },
3013
3014 resolve: function (v) {
3015 if (check(p)) {
3016 p.v = v;
3017 notify(ok, v);
3018 }
3019 return p;
3020 },
3021 reject: function (e) {
3022 if (check(p)) {
3023 p.e = e;
3024 notify(fail, e);
3025 }
3026 return p;
3027 },
3028
3029 start: function (fn) {
3030 p.resolve();
3031 return p.promise.then(fn);
3032 },
3033
3034 promise: {
3035 then: function (yes, no) {
3036 var next = prim();
3037
3038 p.callback(function (v) {
3039 try {
3040 if (yes && typeof yes === 'function') {
3041 v = yes(v);
3042 }
3043
3044 if (v && v.then) {
3045 v.then(next.resolve, next.reject);
3046 } else {
3047 next.resolve(v);
3048 }
3049 } catch (e) {
3050 next.reject(e);
3051 }
3052 }, function (e) {
3053 var err;
3054
3055 try {
3056 if (!no || typeof no !== 'function') {
3057 next.reject(e);
3058 } else {
3059 err = no(e);
3060
3061 if (err && err.then) {
3062 err.then(next.resolve, next.reject);
3063 } else {
3064 next.resolve(err);
3065 }
3066 }
3067 } catch (e2) {
3068 next.reject(e2);
3069 }
3070 });
3071
3072 return next.promise;
3073 },
3074
3075 fail: function (no) {
3076 return p.promise.then(null, no);
3077 },
3078
3079 end: function () {
3080 p.errback(function (e) {
3081 throw e;
3082 });
3083 }
3084 }
3085 });
3086 };
3087
3088 prim.serial = function (ary) {
3089 var result = prim().resolve().promise;
3090 each(ary, function (item) {
3091 result = result.then(function () {
3092 return item();
3093 });
3094 });
3095 return result;
3096 };
3097
3098 prim.nextTick = typeof setImmediate === 'function' ? setImmediate :
3099 (typeof process !== 'undefined' && process.nextTick ?
3100 process.nextTick : (typeof setTimeout !== 'undefined' ?
3101 function (fn) {
3102 setTimeout(fn, 0);
3103 } : function (fn) {
3104 fn();
3105 }));
3106
3107 if (typeof define === 'function' && define.amd) {
3108 define('prim', function () { return prim; });
3109 } else if (typeof module !== 'undefined' && module.exports) {
3110 module.exports = prim;
3111 }
3112}());
3113if(env === 'browser') {
3114/*jslint strict: false */
3115/*global define: false, load: false */
3116
3117//Just a stub for use with uglify's consolidator.js
3118define('browser/assert', function () {
3119 return {};
3120});
3121
3122}
3123
3124if(env === 'node') {
3125/*jslint strict: false */
3126/*global define: false, load: false */
3127
3128//Needed so that rhino/assert can return a stub for uglify's consolidator.js
3129define('node/assert', ['assert'], function (assert) {
3130 return assert;
3131});
3132
3133}
3134
3135if(env === 'rhino') {
3136/*jslint strict: false */
3137/*global define: false, load: false */
3138
3139//Just a stub for use with uglify's consolidator.js
3140define('rhino/assert', function () {
3141 return {};
3142});
3143
3144}
3145
3146if(env === 'xpconnect') {
3147/*jslint strict: false */
3148/*global define: false, load: false */
3149
3150//Just a stub for use with uglify's consolidator.js
3151define('xpconnect/assert', function () {
3152 return {};
3153});
3154
3155}
3156
3157if(env === 'browser') {
3158/*jslint strict: false */
3159/*global define: false, process: false */
3160
3161define('browser/args', function () {
3162 //Always expect config via an API call
3163 return [];
3164});
3165
3166}
3167
3168if(env === 'node') {
3169/*jslint strict: false */
3170/*global define: false, process: false */
3171
3172define('node/args', function () {
3173 //Do not return the "node" or "r.js" arguments
3174 var args = process.argv.slice(2);
3175
3176 //Ignore any command option used for main x.js branching
3177 if (args[0] && args[0].indexOf('-') === 0) {
3178 args = args.slice(1);
3179 }
3180
3181 return args;
3182});
3183
3184}
3185
3186if(env === 'rhino') {
3187/*jslint strict: false */
3188/*global define: false, process: false */
3189
3190var jsLibRhinoArgs = (typeof rhinoArgs !== 'undefined' && rhinoArgs) || [].concat(Array.prototype.slice.call(arguments, 0));
3191
3192define('rhino/args', function () {
3193 var args = jsLibRhinoArgs;
3194
3195 //Ignore any command option used for main x.js branching
3196 if (args[0] && args[0].indexOf('-') === 0) {
3197 args = args.slice(1);
3198 }
3199
3200 return args;
3201});
3202
3203}
3204
3205if(env === 'xpconnect') {
3206/*jslint strict: false */
3207/*global define, xpconnectArgs */
3208
3209var jsLibXpConnectArgs = (typeof xpconnectArgs !== 'undefined' && xpconnectArgs) || [].concat(Array.prototype.slice.call(arguments, 0));
3210
3211define('xpconnect/args', function () {
3212 var args = jsLibXpConnectArgs;
3213
3214 //Ignore any command option used for main x.js branching
3215 if (args[0] && args[0].indexOf('-') === 0) {
3216 args = args.slice(1);
3217 }
3218
3219 return args;
3220});
3221
3222}
3223
3224if(env === 'browser') {
3225/*jslint strict: false */
3226/*global define: false, console: false */
3227
3228define('browser/load', ['./file'], function (file) {
3229 function load(fileName) {
3230 eval(file.readFile(fileName));
3231 }
3232
3233 return load;
3234});
3235
3236}
3237
3238if(env === 'node') {
3239/*jslint strict: false */
3240/*global define: false, console: false */
3241
3242define('node/load', ['fs'], function (fs) {
3243 function load(fileName) {
3244 var contents = fs.readFileSync(fileName, 'utf8');
3245 process.compile(contents, fileName);
3246 }
3247
3248 return load;
3249});
3250
3251}
3252
3253if(env === 'rhino') {
3254/*jslint strict: false */
3255/*global define: false, load: false */
3256
3257define('rhino/load', function () {
3258 return load;
3259});
3260
3261}
3262
3263if(env === 'xpconnect') {
3264/*jslint strict: false */
3265/*global define: false, load: false */
3266
3267define('xpconnect/load', function () {
3268 return load;
3269});
3270
3271}
3272
3273if(env === 'browser') {
3274/*jslint sloppy: true, nomen: true */
3275/*global require, define, console, XMLHttpRequest, requirejs, location */
3276
3277define('browser/file', ['prim'], function (prim) {
3278
3279 var file,
3280 currDirRegExp = /^\.(\/|$)/;
3281
3282 function frontSlash(path) {
3283 return path.replace(/\\/g, '/');
3284 }
3285
3286 function exists(path) {
3287 var status, xhr = new XMLHttpRequest();
3288
3289 //Oh yeah, that is right SYNC IO. Behold its glory
3290 //and horrible blocking behavior.
3291 xhr.open('HEAD', path, false);
3292 xhr.send();
3293 status = xhr.status;
3294
3295 return status === 200 || status === 304;
3296 }
3297
3298 function mkDir(dir) {
3299 console.log('mkDir is no-op in browser');
3300 }
3301
3302 function mkFullDir(dir) {
3303 console.log('mkFullDir is no-op in browser');
3304 }
3305
3306 file = {
3307 backSlashRegExp: /\\/g,
3308 exclusionRegExp: /^\./,
3309 getLineSeparator: function () {
3310 return '/';
3311 },
3312
3313 exists: function (fileName) {
3314 return exists(fileName);
3315 },
3316
3317 parent: function (fileName) {
3318 var parts = fileName.split('/');
3319 parts.pop();
3320 return parts.join('/');
3321 },
3322
3323 /**
3324 * Gets the absolute file path as a string, normalized
3325 * to using front slashes for path separators.
3326 * @param {String} fileName
3327 */
3328 absPath: function (fileName) {
3329 var dir;
3330 if (currDirRegExp.test(fileName)) {
3331 dir = frontSlash(location.href);
3332 if (dir.indexOf('/') !== -1) {
3333 dir = dir.split('/');
3334
3335 //Pull off protocol and host, just want
3336 //to allow paths (other build parts, like
3337 //require._isSupportedBuildUrl do not support
3338 //full URLs), but a full path from
3339 //the root.
3340 dir.splice(0, 3);
3341
3342 dir.pop();
3343 dir = '/' + dir.join('/');
3344 }
3345
3346 fileName = dir + fileName.substring(1);
3347 }
3348
3349 return fileName;
3350 },
3351
3352 normalize: function (fileName) {
3353 return fileName;
3354 },
3355
3356 isFile: function (path) {
3357 return true;
3358 },
3359
3360 isDirectory: function (path) {
3361 return false;
3362 },
3363
3364 getFilteredFileList: function (startDir, regExpFilters, makeUnixPaths) {
3365 console.log('file.getFilteredFileList is no-op in browser');
3366 },
3367
3368 copyDir: function (srcDir, destDir, regExpFilter, onlyCopyNew) {
3369 console.log('file.copyDir is no-op in browser');
3370
3371 },
3372
3373 copyFile: function (srcFileName, destFileName, onlyCopyNew) {
3374 console.log('file.copyFile is no-op in browser');
3375 },
3376
3377 /**
3378 * Renames a file. May fail if "to" already exists or is on another drive.
3379 */
3380 renameFile: function (from, to) {
3381 console.log('file.renameFile is no-op in browser');
3382 },
3383
3384 /**
3385 * Reads a *text* file.
3386 */
3387 readFile: function (path, encoding) {
3388 var xhr = new XMLHttpRequest();
3389
3390 //Oh yeah, that is right SYNC IO. Behold its glory
3391 //and horrible blocking behavior.
3392 xhr.open('GET', path, false);
3393 xhr.send();
3394
3395 return xhr.responseText;
3396 },
3397
3398 readFileAsync: function (path, encoding) {
3399 var xhr = new XMLHttpRequest(),
3400 d = prim();
3401
3402 xhr.open('GET', path, true);
3403 xhr.send();
3404
3405 xhr.onreadystatechange = function () {
3406 if (xhr.readyState === 4) {
3407 if (xhr.status > 400) {
3408 d.reject(new Error('Status: ' + xhr.status + ': ' + xhr.statusText));
3409 } else {
3410 d.resolve(xhr.responseText);
3411 }
3412 }
3413 };
3414
3415 return d.promise;
3416 },
3417
3418 saveUtf8File: function (fileName, fileContents) {
3419 //summary: saves a *text* file using UTF-8 encoding.
3420 file.saveFile(fileName, fileContents, "utf8");
3421 },
3422
3423 saveFile: function (fileName, fileContents, encoding) {
3424 requirejs.browser.saveFile(fileName, fileContents, encoding);
3425 },
3426
3427 deleteFile: function (fileName) {
3428 console.log('file.deleteFile is no-op in browser');
3429 },
3430
3431 /**
3432 * Deletes any empty directories under the given directory.
3433 */
3434 deleteEmptyDirs: function (startDir) {
3435 console.log('file.deleteEmptyDirs is no-op in browser');
3436 }
3437 };
3438
3439 return file;
3440
3441});
3442
3443}
3444
3445if(env === 'node') {
3446/*jslint plusplus: false, octal:false, strict: false */
3447/*global define: false, process: false */
3448
3449define('node/file', ['fs', 'path', 'prim'], function (fs, path, prim) {
3450
3451 var isWindows = process.platform === 'win32',
3452 windowsDriveRegExp = /^[a-zA-Z]\:\/$/,
3453 file;
3454
3455 function frontSlash(path) {
3456 return path.replace(/\\/g, '/');
3457 }
3458
3459 function exists(path) {
3460 if (isWindows && path.charAt(path.length - 1) === '/' &&
3461 path.charAt(path.length - 2) !== ':') {
3462 path = path.substring(0, path.length - 1);
3463 }
3464
3465 try {
3466 fs.statSync(path);
3467 return true;
3468 } catch (e) {
3469 return false;
3470 }
3471 }
3472
3473 function mkDir(dir) {
3474 if (!exists(dir) && (!isWindows || !windowsDriveRegExp.test(dir))) {
3475 fs.mkdirSync(dir, 511);
3476 }
3477 }
3478
3479 function mkFullDir(dir) {
3480 var parts = dir.split('/'),
3481 currDir = '',
3482 first = true;
3483
3484 parts.forEach(function (part) {
3485 //First part may be empty string if path starts with a slash.
3486 currDir += part + '/';
3487 first = false;
3488
3489 if (part) {
3490 mkDir(currDir);
3491 }
3492 });
3493 }
3494
3495 file = {
3496 backSlashRegExp: /\\/g,
3497 exclusionRegExp: /^\./,
3498 getLineSeparator: function () {
3499 return '/';
3500 },
3501
3502 exists: function (fileName) {
3503 return exists(fileName);
3504 },
3505
3506 parent: function (fileName) {
3507 var parts = fileName.split('/');
3508 parts.pop();
3509 return parts.join('/');
3510 },
3511
3512 /**
3513 * Gets the absolute file path as a string, normalized
3514 * to using front slashes for path separators.
3515 * @param {String} fileName
3516 */
3517 absPath: function (fileName) {
3518 return frontSlash(path.normalize(frontSlash(fs.realpathSync(fileName))));
3519 },
3520
3521 normalize: function (fileName) {
3522 return frontSlash(path.normalize(fileName));
3523 },
3524
3525 isFile: function (path) {
3526 return fs.statSync(path).isFile();
3527 },
3528
3529 isDirectory: function (path) {
3530 return fs.statSync(path).isDirectory();
3531 },
3532
3533 getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths) {
3534 //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
3535 //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
3536 //and it will be treated as the "include" case.
3537 //Ignores files/directories that start with a period (.) unless exclusionRegExp
3538 //is set to another value.
3539 var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
3540 i, stat, filePath, ok, dirFiles, fileName;
3541
3542 topDir = startDir;
3543
3544 regExpInclude = regExpFilters.include || regExpFilters;
3545 regExpExclude = regExpFilters.exclude || null;
3546
3547 if (file.exists(topDir)) {
3548 dirFileArray = fs.readdirSync(topDir);
3549 for (i = 0; i < dirFileArray.length; i++) {
3550 fileName = dirFileArray[i];
3551 filePath = path.join(topDir, fileName);
3552 stat = fs.statSync(filePath);
3553 if (stat.isFile()) {
3554 if (makeUnixPaths) {
3555 //Make sure we have a JS string.
3556 if (filePath.indexOf("/") === -1) {
3557 filePath = frontSlash(filePath);
3558 }
3559 }
3560
3561 ok = true;
3562 if (regExpInclude) {
3563 ok = filePath.match(regExpInclude);
3564 }
3565 if (ok && regExpExclude) {
3566 ok = !filePath.match(regExpExclude);
3567 }
3568
3569 if (ok && (!file.exclusionRegExp ||
3570 !file.exclusionRegExp.test(fileName))) {
3571 files.push(filePath);
3572 }
3573 } else if (stat.isDirectory() &&
3574 (!file.exclusionRegExp || !file.exclusionRegExp.test(fileName))) {
3575 dirFiles = this.getFilteredFileList(filePath, regExpFilters, makeUnixPaths);
3576 //Do not use push.apply for dir listings, can hit limit of max number
3577 //of arguments to a function call, #921.
3578 dirFiles.forEach(function (dirFile) {
3579 files.push(dirFile);
3580 });
3581 }
3582 }
3583 }
3584
3585 return files; //Array
3586 },
3587
3588 copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
3589 //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
3590 //file should be copied. Returns a list file name strings of the destinations that were copied.
3591 regExpFilter = regExpFilter || /\w/;
3592
3593 //Normalize th directory names, but keep front slashes.
3594 //path module on windows now returns backslashed paths.
3595 srcDir = frontSlash(path.normalize(srcDir));
3596 destDir = frontSlash(path.normalize(destDir));
3597
3598 var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
3599 copiedFiles = [], i, srcFileName, destFileName;
3600
3601 for (i = 0; i < fileNames.length; i++) {
3602 srcFileName = fileNames[i];
3603 destFileName = srcFileName.replace(srcDir, destDir);
3604
3605 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
3606 copiedFiles.push(destFileName);
3607 }
3608 }
3609
3610 return copiedFiles.length ? copiedFiles : null; //Array or null
3611 },
3612
3613 copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
3614 //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
3615 //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
3616 var parentDir;
3617
3618 //logger.trace("Src filename: " + srcFileName);
3619 //logger.trace("Dest filename: " + destFileName);
3620
3621 //If onlyCopyNew is true, then compare dates and only copy if the src is newer
3622 //than dest.
3623 if (onlyCopyNew) {
3624 if (file.exists(destFileName) && fs.statSync(destFileName).mtime.getTime() >= fs.statSync(srcFileName).mtime.getTime()) {
3625 return false; //Boolean
3626 }
3627 }
3628
3629 //Make sure destination dir exists.
3630 parentDir = path.dirname(destFileName);
3631 if (!file.exists(parentDir)) {
3632 mkFullDir(parentDir);
3633 }
3634
3635 fs.writeFileSync(destFileName, fs.readFileSync(srcFileName, 'binary'), 'binary');
3636
3637 return true; //Boolean
3638 },
3639
3640 /**
3641 * Renames a file. May fail if "to" already exists or is on another drive.
3642 */
3643 renameFile: function (from, to) {
3644 return fs.renameSync(from, to);
3645 },
3646
3647 /**
3648 * Reads a *text* file.
3649 */
3650 readFile: function (/*String*/path, /*String?*/encoding) {
3651 if (encoding === 'utf-8') {
3652 encoding = 'utf8';
3653 }
3654 if (!encoding) {
3655 encoding = 'utf8';
3656 }
3657
3658 var text = fs.readFileSync(path, encoding);
3659
3660 //Hmm, would not expect to get A BOM, but it seems to happen,
3661 //remove it just in case.
3662 if (text.indexOf('\uFEFF') === 0) {
3663 text = text.substring(1, text.length);
3664 }
3665
3666 return text;
3667 },
3668
3669 readFileAsync: function (path, encoding) {
3670 var d = prim();
3671 try {
3672 d.resolve(file.readFile(path, encoding));
3673 } catch (e) {
3674 d.reject(e);
3675 }
3676 return d.promise;
3677 },
3678
3679 saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
3680 //summary: saves a *text* file using UTF-8 encoding.
3681 file.saveFile(fileName, fileContents, "utf8");
3682 },
3683
3684 saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
3685 //summary: saves a *text* file.
3686 var parentDir;
3687
3688 if (encoding === 'utf-8') {
3689 encoding = 'utf8';
3690 }
3691 if (!encoding) {
3692 encoding = 'utf8';
3693 }
3694
3695 //Make sure destination directories exist.
3696 parentDir = path.dirname(fileName);
3697 if (!file.exists(parentDir)) {
3698 mkFullDir(parentDir);
3699 }
3700
3701 fs.writeFileSync(fileName, fileContents, encoding);
3702 },
3703
3704 deleteFile: function (/*String*/fileName) {
3705 //summary: deletes a file or directory if it exists.
3706 var files, i, stat;
3707 if (file.exists(fileName)) {
3708 stat = fs.lstatSync(fileName);
3709 if (stat.isDirectory()) {
3710 files = fs.readdirSync(fileName);
3711 for (i = 0; i < files.length; i++) {
3712 this.deleteFile(path.join(fileName, files[i]));
3713 }
3714 fs.rmdirSync(fileName);
3715 } else {
3716 fs.unlinkSync(fileName);
3717 }
3718 }
3719 },
3720
3721
3722 /**
3723 * Deletes any empty directories under the given directory.
3724 */
3725 deleteEmptyDirs: function (startDir) {
3726 var dirFileArray, i, fileName, filePath, stat;
3727
3728 if (file.exists(startDir)) {
3729 dirFileArray = fs.readdirSync(startDir);
3730 for (i = 0; i < dirFileArray.length; i++) {
3731 fileName = dirFileArray[i];
3732 filePath = path.join(startDir, fileName);
3733 stat = fs.lstatSync(filePath);
3734 if (stat.isDirectory()) {
3735 file.deleteEmptyDirs(filePath);
3736 }
3737 }
3738
3739 //If directory is now empty, remove it.
3740 if (fs.readdirSync(startDir).length === 0) {
3741 file.deleteFile(startDir);
3742 }
3743 }
3744 }
3745 };
3746
3747 return file;
3748
3749});
3750
3751}
3752
3753if(env === 'rhino') {
3754//Helper functions to deal with file I/O.
3755
3756/*jslint plusplus: false */
3757/*global java: false, define: false */
3758
3759define('rhino/file', ['prim'], function (prim) {
3760 var file = {
3761 backSlashRegExp: /\\/g,
3762
3763 exclusionRegExp: /^\./,
3764
3765 getLineSeparator: function () {
3766 return file.lineSeparator;
3767 },
3768
3769 lineSeparator: java.lang.System.getProperty("line.separator"), //Java String
3770
3771 exists: function (fileName) {
3772 return (new java.io.File(fileName)).exists();
3773 },
3774
3775 parent: function (fileName) {
3776 return file.absPath((new java.io.File(fileName)).getParentFile());
3777 },
3778
3779 normalize: function (fileName) {
3780 return file.absPath(fileName);
3781 },
3782
3783 isFile: function (path) {
3784 return (new java.io.File(path)).isFile();
3785 },
3786
3787 isDirectory: function (path) {
3788 return (new java.io.File(path)).isDirectory();
3789 },
3790
3791 /**
3792 * Gets the absolute file path as a string, normalized
3793 * to using front slashes for path separators.
3794 * @param {java.io.File||String} file
3795 */
3796 absPath: function (fileObj) {
3797 if (typeof fileObj === "string") {
3798 fileObj = new java.io.File(fileObj);
3799 }
3800 return (fileObj.getCanonicalPath() + "").replace(file.backSlashRegExp, "/");
3801 },
3802
3803 getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) {
3804 //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
3805 //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
3806 //and it will be treated as the "include" case.
3807 //Ignores files/directories that start with a period (.) unless exclusionRegExp
3808 //is set to another value.
3809 var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
3810 i, fileObj, filePath, ok, dirFiles;
3811
3812 topDir = startDir;
3813 if (!startDirIsJavaObject) {
3814 topDir = new java.io.File(startDir);
3815 }
3816
3817 regExpInclude = regExpFilters.include || regExpFilters;
3818 regExpExclude = regExpFilters.exclude || null;
3819
3820 if (topDir.exists()) {
3821 dirFileArray = topDir.listFiles();
3822 for (i = 0; i < dirFileArray.length; i++) {
3823 fileObj = dirFileArray[i];
3824 if (fileObj.isFile()) {
3825 filePath = fileObj.getPath();
3826 if (makeUnixPaths) {
3827 //Make sure we have a JS string.
3828 filePath = String(filePath);
3829 if (filePath.indexOf("/") === -1) {
3830 filePath = filePath.replace(/\\/g, "/");
3831 }
3832 }
3833
3834 ok = true;
3835 if (regExpInclude) {
3836 ok = filePath.match(regExpInclude);
3837 }
3838 if (ok && regExpExclude) {
3839 ok = !filePath.match(regExpExclude);
3840 }
3841
3842 if (ok && (!file.exclusionRegExp ||
3843 !file.exclusionRegExp.test(fileObj.getName()))) {
3844 files.push(filePath);
3845 }
3846 } else if (fileObj.isDirectory() &&
3847 (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.getName()))) {
3848 dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true);
3849 //Do not use push.apply for dir listings, can hit limit of max number
3850 //of arguments to a function call, #921.
3851 dirFiles.forEach(function (dirFile) {
3852 files.push(dirFile);
3853 });
3854 }
3855 }
3856 }
3857
3858 return files; //Array
3859 },
3860
3861 copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
3862 //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
3863 //file should be copied. Returns a list file name strings of the destinations that were copied.
3864 regExpFilter = regExpFilter || /\w/;
3865
3866 var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
3867 copiedFiles = [], i, srcFileName, destFileName;
3868
3869 for (i = 0; i < fileNames.length; i++) {
3870 srcFileName = fileNames[i];
3871 destFileName = srcFileName.replace(srcDir, destDir);
3872
3873 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
3874 copiedFiles.push(destFileName);
3875 }
3876 }
3877
3878 return copiedFiles.length ? copiedFiles : null; //Array or null
3879 },
3880
3881 copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
3882 //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
3883 //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
3884 var destFile = new java.io.File(destFileName), srcFile, parentDir,
3885 srcChannel, destChannel;
3886
3887 //logger.trace("Src filename: " + srcFileName);
3888 //logger.trace("Dest filename: " + destFileName);
3889
3890 //If onlyCopyNew is true, then compare dates and only copy if the src is newer
3891 //than dest.
3892 if (onlyCopyNew) {
3893 srcFile = new java.io.File(srcFileName);
3894 if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
3895 return false; //Boolean
3896 }
3897 }
3898
3899 //Make sure destination dir exists.
3900 parentDir = destFile.getParentFile();
3901 if (!parentDir.exists()) {
3902 if (!parentDir.mkdirs()) {
3903 throw "Could not create directory: " + parentDir.getCanonicalPath();
3904 }
3905 }
3906
3907 //Java's version of copy file.
3908 srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
3909 destChannel = new java.io.FileOutputStream(destFileName).getChannel();
3910 destChannel.transferFrom(srcChannel, 0, srcChannel.size());
3911 srcChannel.close();
3912 destChannel.close();
3913
3914 return true; //Boolean
3915 },
3916
3917 /**
3918 * Renames a file. May fail if "to" already exists or is on another drive.
3919 */
3920 renameFile: function (from, to) {
3921 return (new java.io.File(from)).renameTo((new java.io.File(to)));
3922 },
3923
3924 readFile: function (/*String*/path, /*String?*/encoding) {
3925 //A file read function that can deal with BOMs
3926 encoding = encoding || "utf-8";
3927 var fileObj = new java.io.File(path),
3928 input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(fileObj), encoding)),
3929 stringBuffer, line;
3930 try {
3931 stringBuffer = new java.lang.StringBuffer();
3932 line = input.readLine();
3933
3934 // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
3935 // http://www.unicode.org/faq/utf_bom.html
3936
3937 // 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:
3938 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
3939 if (line && line.length() && line.charAt(0) === 0xfeff) {
3940 // Eat the BOM, since we've already found the encoding on this file,
3941 // and we plan to concatenating this buffer with others; the BOM should
3942 // only appear at the top of a file.
3943 line = line.substring(1);
3944 }
3945 while (line !== null) {
3946 stringBuffer.append(line);
3947 stringBuffer.append(file.lineSeparator);
3948 line = input.readLine();
3949 }
3950 //Make sure we return a JavaScript string and not a Java string.
3951 return String(stringBuffer.toString()); //String
3952 } finally {
3953 input.close();
3954 }
3955 },
3956
3957 readFileAsync: function (path, encoding) {
3958 var d = prim();
3959 try {
3960 d.resolve(file.readFile(path, encoding));
3961 } catch (e) {
3962 d.reject(e);
3963 }
3964 return d.promise;
3965 },
3966
3967 saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
3968 //summary: saves a file using UTF-8 encoding.
3969 file.saveFile(fileName, fileContents, "utf-8");
3970 },
3971
3972 saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
3973 //summary: saves a file.
3974 var outFile = new java.io.File(fileName), outWriter, parentDir, os;
3975
3976 parentDir = outFile.getAbsoluteFile().getParentFile();
3977 if (!parentDir.exists()) {
3978 if (!parentDir.mkdirs()) {
3979 throw "Could not create directory: " + parentDir.getAbsolutePath();
3980 }
3981 }
3982
3983 if (encoding) {
3984 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
3985 } else {
3986 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
3987 }
3988
3989 os = new java.io.BufferedWriter(outWriter);
3990 try {
3991 //If in Nashorn, need to coerce the JS string to a Java string so that
3992 //writer.write method dispatch correctly detects the type.
3993 if (typeof importPackage !== 'undefined') {
3994 os.write(fileContents);
3995 } else {
3996 os.write(new java.lang.String(fileContents));
3997 }
3998 } finally {
3999 os.close();
4000 }
4001 },
4002
4003 deleteFile: function (/*String*/fileName) {
4004 //summary: deletes a file or directory if it exists.
4005 var fileObj = new java.io.File(fileName), files, i;
4006 if (fileObj.exists()) {
4007 if (fileObj.isDirectory()) {
4008 files = fileObj.listFiles();
4009 for (i = 0; i < files.length; i++) {
4010 this.deleteFile(files[i]);
4011 }
4012 }
4013 fileObj["delete"]();
4014 }
4015 },
4016
4017 /**
4018 * Deletes any empty directories under the given directory.
4019 * The startDirIsJavaObject is private to this implementation's
4020 * recursion needs.
4021 */
4022 deleteEmptyDirs: function (startDir, startDirIsJavaObject) {
4023 var topDir = startDir,
4024 dirFileArray, i, fileObj;
4025
4026 if (!startDirIsJavaObject) {
4027 topDir = new java.io.File(startDir);
4028 }
4029
4030 if (topDir.exists()) {
4031 dirFileArray = topDir.listFiles();
4032 for (i = 0; i < dirFileArray.length; i++) {
4033 fileObj = dirFileArray[i];
4034 if (fileObj.isDirectory()) {
4035 file.deleteEmptyDirs(fileObj, true);
4036 }
4037 }
4038
4039 //If the directory is empty now, delete it.
4040 if (topDir.listFiles().length === 0) {
4041 file.deleteFile(String(topDir.getPath()));
4042 }
4043 }
4044 }
4045 };
4046
4047 return file;
4048});
4049
4050}
4051
4052if(env === 'xpconnect') {
4053//Helper functions to deal with file I/O.
4054
4055/*jslint plusplus: false */
4056/*global define, Components, xpcUtil */
4057
4058define('xpconnect/file', ['prim'], function (prim) {
4059 var file,
4060 Cc = Components.classes,
4061 Ci = Components.interfaces,
4062 //Depends on xpcUtil which is set up in x.js
4063 xpfile = xpcUtil.xpfile;
4064
4065 function mkFullDir(dirObj) {
4066 //1 is DIRECTORY_TYPE, 511 is 0777 permissions
4067 if (!dirObj.exists()) {
4068 dirObj.create(1, 511);
4069 }
4070 }
4071
4072 file = {
4073 backSlashRegExp: /\\/g,
4074
4075 exclusionRegExp: /^\./,
4076
4077 getLineSeparator: function () {
4078 return file.lineSeparator;
4079 },
4080
4081 lineSeparator: ('@mozilla.org/windows-registry-key;1' in Cc) ?
4082 '\r\n' : '\n',
4083
4084 exists: function (fileName) {
4085 return xpfile(fileName).exists();
4086 },
4087
4088 parent: function (fileName) {
4089 return xpfile(fileName).parent;
4090 },
4091
4092 normalize: function (fileName) {
4093 return file.absPath(fileName);
4094 },
4095
4096 isFile: function (path) {
4097 return xpfile(path).isFile();
4098 },
4099
4100 isDirectory: function (path) {
4101 return xpfile(path).isDirectory();
4102 },
4103
4104 /**
4105 * Gets the absolute file path as a string, normalized
4106 * to using front slashes for path separators.
4107 * @param {java.io.File||String} file
4108 */
4109 absPath: function (fileObj) {
4110 if (typeof fileObj === "string") {
4111 fileObj = xpfile(fileObj);
4112 }
4113 return fileObj.path;
4114 },
4115
4116 getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsObject) {
4117 //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
4118 //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
4119 //and it will be treated as the "include" case.
4120 //Ignores files/directories that start with a period (.) unless exclusionRegExp
4121 //is set to another value.
4122 var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
4123 fileObj, filePath, ok, dirFiles;
4124
4125 topDir = startDir;
4126 if (!startDirIsObject) {
4127 topDir = xpfile(startDir);
4128 }
4129
4130 regExpInclude = regExpFilters.include || regExpFilters;
4131 regExpExclude = regExpFilters.exclude || null;
4132
4133 if (topDir.exists()) {
4134 dirFileArray = topDir.directoryEntries;
4135 while (dirFileArray.hasMoreElements()) {
4136 fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile);
4137 if (fileObj.isFile()) {
4138 filePath = fileObj.path;
4139 if (makeUnixPaths) {
4140 if (filePath.indexOf("/") === -1) {
4141 filePath = filePath.replace(/\\/g, "/");
4142 }
4143 }
4144
4145 ok = true;
4146 if (regExpInclude) {
4147 ok = filePath.match(regExpInclude);
4148 }
4149 if (ok && regExpExclude) {
4150 ok = !filePath.match(regExpExclude);
4151 }
4152
4153 if (ok && (!file.exclusionRegExp ||
4154 !file.exclusionRegExp.test(fileObj.leafName))) {
4155 files.push(filePath);
4156 }
4157 } else if (fileObj.isDirectory() &&
4158 (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.leafName))) {
4159 dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true);
4160 //Do not use push.apply for dir listings, can hit limit of max number
4161 //of arguments to a function call, #921.
4162 dirFiles.forEach(function (dirFile) {
4163 files.push(dirFile);
4164 });
4165 }
4166 }
4167 }
4168
4169 return files; //Array
4170 },
4171
4172 copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
4173 //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
4174 //file should be copied. Returns a list file name strings of the destinations that were copied.
4175 regExpFilter = regExpFilter || /\w/;
4176
4177 var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
4178 copiedFiles = [], i, srcFileName, destFileName;
4179
4180 for (i = 0; i < fileNames.length; i += 1) {
4181 srcFileName = fileNames[i];
4182 destFileName = srcFileName.replace(srcDir, destDir);
4183
4184 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
4185 copiedFiles.push(destFileName);
4186 }
4187 }
4188
4189 return copiedFiles.length ? copiedFiles : null; //Array or null
4190 },
4191
4192 copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
4193 //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
4194 //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
4195 var destFile = xpfile(destFileName),
4196 srcFile = xpfile(srcFileName);
4197
4198 //logger.trace("Src filename: " + srcFileName);
4199 //logger.trace("Dest filename: " + destFileName);
4200
4201 //If onlyCopyNew is true, then compare dates and only copy if the src is newer
4202 //than dest.
4203 if (onlyCopyNew) {
4204 if (destFile.exists() && destFile.lastModifiedTime >= srcFile.lastModifiedTime) {
4205 return false; //Boolean
4206 }
4207 }
4208
4209 srcFile.copyTo(destFile.parent, destFile.leafName);
4210
4211 return true; //Boolean
4212 },
4213
4214 /**
4215 * Renames a file. May fail if "to" already exists or is on another drive.
4216 */
4217 renameFile: function (from, to) {
4218 var toFile = xpfile(to);
4219 return xpfile(from).moveTo(toFile.parent, toFile.leafName);
4220 },
4221
4222 readFile: xpcUtil.readFile,
4223
4224 readFileAsync: function (path, encoding) {
4225 var d = prim();
4226 try {
4227 d.resolve(file.readFile(path, encoding));
4228 } catch (e) {
4229 d.reject(e);
4230 }
4231 return d.promise;
4232 },
4233
4234 saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
4235 //summary: saves a file using UTF-8 encoding.
4236 file.saveFile(fileName, fileContents, "utf-8");
4237 },
4238
4239 saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
4240 var outStream, convertStream,
4241 fileObj = xpfile(fileName);
4242
4243 mkFullDir(fileObj.parent);
4244
4245 try {
4246 outStream = Cc['@mozilla.org/network/file-output-stream;1']
4247 .createInstance(Ci.nsIFileOutputStream);
4248 //438 is decimal for 0777
4249 outStream.init(fileObj, 0x02 | 0x08 | 0x20, 511, 0);
4250
4251 convertStream = Cc['@mozilla.org/intl/converter-output-stream;1']
4252 .createInstance(Ci.nsIConverterOutputStream);
4253
4254 convertStream.init(outStream, encoding, 0, 0);
4255 convertStream.writeString(fileContents);
4256 } catch (e) {
4257 throw new Error((fileObj && fileObj.path || '') + ': ' + e);
4258 } finally {
4259 if (convertStream) {
4260 convertStream.close();
4261 }
4262 if (outStream) {
4263 outStream.close();
4264 }
4265 }
4266 },
4267
4268 deleteFile: function (/*String*/fileName) {
4269 //summary: deletes a file or directory if it exists.
4270 var fileObj = xpfile(fileName);
4271 if (fileObj.exists()) {
4272 fileObj.remove(true);
4273 }
4274 },
4275
4276 /**
4277 * Deletes any empty directories under the given directory.
4278 * The startDirIsJavaObject is private to this implementation's
4279 * recursion needs.
4280 */
4281 deleteEmptyDirs: function (startDir, startDirIsObject) {
4282 var topDir = startDir,
4283 dirFileArray, fileObj;
4284
4285 if (!startDirIsObject) {
4286 topDir = xpfile(startDir);
4287 }
4288
4289 if (topDir.exists()) {
4290 dirFileArray = topDir.directoryEntries;
4291 while (dirFileArray.hasMoreElements()) {
4292 fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile);
4293
4294 if (fileObj.isDirectory()) {
4295 file.deleteEmptyDirs(fileObj, true);
4296 }
4297 }
4298
4299 //If the directory is empty now, delete it.
4300 dirFileArray = topDir.directoryEntries;
4301 if (!dirFileArray.hasMoreElements()) {
4302 file.deleteFile(topDir.path);
4303 }
4304 }
4305 }
4306 };
4307
4308 return file;
4309});
4310
4311}
4312
4313if(env === 'browser') {
4314/*global process */
4315define('browser/quit', function () {
4316 'use strict';
4317 return function (code) {
4318 };
4319});
4320}
4321
4322if(env === 'node') {
4323/*global process */
4324define('node/quit', function () {
4325 'use strict';
4326 return function (code) {
4327 var draining = 0;
4328 var exit = function () {
4329 if (draining === 0) {
4330 process.exit(code);
4331 } else {
4332 draining -= 1;
4333 }
4334 };
4335 if (process.stdout.bufferSize) {
4336 draining += 1;
4337 process.stdout.once('drain', exit);
4338 }
4339 if (process.stderr.bufferSize) {
4340 draining += 1;
4341 process.stderr.once('drain', exit);
4342 }
4343 exit();
4344 };
4345});
4346
4347}
4348
4349if(env === 'rhino') {
4350/*global quit */
4351define('rhino/quit', function () {
4352 'use strict';
4353 return function (code) {
4354 return quit(code);
4355 };
4356});
4357
4358}
4359
4360if(env === 'xpconnect') {
4361/*global quit */
4362define('xpconnect/quit', function () {
4363 'use strict';
4364 return function (code) {
4365 return quit(code);
4366 };
4367});
4368
4369}
4370
4371if(env === 'browser') {
4372/*jslint strict: false */
4373/*global define: false, console: false */
4374
4375define('browser/print', function () {
4376 function print(msg) {
4377 console.log(msg);
4378 }
4379
4380 return print;
4381});
4382
4383}
4384
4385if(env === 'node') {
4386/*jslint strict: false */
4387/*global define: false, console: false */
4388
4389define('node/print', function () {
4390 function print(msg) {
4391 console.log(msg);
4392 }
4393
4394 return print;
4395});
4396
4397}
4398
4399if(env === 'rhino') {
4400/*jslint strict: false */
4401/*global define: false, print: false */
4402
4403define('rhino/print', function () {
4404 return print;
4405});
4406
4407}
4408
4409if(env === 'xpconnect') {
4410/*jslint strict: false */
4411/*global define: false, print: false */
4412
4413define('xpconnect/print', function () {
4414 return print;
4415});
4416
4417}
4418/*jslint nomen: false, strict: false */
4419/*global define: false */
4420
4421define('logger', ['env!env/print'], function (print) {
4422 var logger = {
4423 TRACE: 0,
4424 INFO: 1,
4425 WARN: 2,
4426 ERROR: 3,
4427 SILENT: 4,
4428 level: 0,
4429 logPrefix: "",
4430
4431 logLevel: function( level ) {
4432 this.level = level;
4433 },
4434
4435 trace: function (message) {
4436 if (this.level <= this.TRACE) {
4437 this._print(message);
4438 }
4439 },
4440
4441 info: function (message) {
4442 if (this.level <= this.INFO) {
4443 this._print(message);
4444 }
4445 },
4446
4447 warn: function (message) {
4448 if (this.level <= this.WARN) {
4449 this._print(message);
4450 }
4451 },
4452
4453 error: function (message) {
4454 if (this.level <= this.ERROR) {
4455 this._print(message);
4456 }
4457 },
4458
4459 _print: function (message) {
4460 this._sysPrint((this.logPrefix ? (this.logPrefix + " ") : "") + message);
4461 },
4462
4463 _sysPrint: function (message) {
4464 print(message);
4465 }
4466 };
4467
4468 return logger;
4469});
4470//Just a blank file to use when building the optimizer with the optimizer,
4471//so that the build does not attempt to inline some env modules,
4472//like Node's fs and path.
4473
4474(function webpackUniversalModuleDefinition(root, factory) {
4475/* istanbul ignore next */
4476 if(typeof define === 'function' && define.amd)
4477 define('esprima', [], factory);
4478/* istanbul ignore next */
4479 else if(typeof exports === 'object')
4480 exports["esprima"] = factory();
4481 else
4482 root["esprima"] = factory();
4483})(this, function() {
4484return /******/ (function(modules) { // webpackBootstrap
4485/******/ // The module cache
4486/******/ var installedModules = {};
4487
4488/******/ // The require function
4489/******/ function __webpack_require__(moduleId) {
4490
4491/******/ // Check if module is in cache
4492/* istanbul ignore if */
4493/******/ if(installedModules[moduleId])
4494/******/ return installedModules[moduleId].exports;
4495
4496/******/ // Create a new module (and put it into the cache)
4497/******/ var module = installedModules[moduleId] = {
4498/******/ exports: {},
4499/******/ id: moduleId,
4500/******/ loaded: false
4501/******/ };
4502
4503/******/ // Execute the module function
4504/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
4505
4506/******/ // Flag the module as loaded
4507/******/ module.loaded = true;
4508
4509/******/ // Return the exports of the module
4510/******/ return module.exports;
4511/******/ }
4512
4513
4514/******/ // expose the modules object (__webpack_modules__)
4515/******/ __webpack_require__.m = modules;
4516
4517/******/ // expose the module cache
4518/******/ __webpack_require__.c = installedModules;
4519
4520/******/ // __webpack_public_path__
4521/******/ __webpack_require__.p = "";
4522
4523/******/ // Load entry module and return exports
4524/******/ return __webpack_require__(0);
4525/******/ })
4526/************************************************************************/
4527/******/ ([
4528/* 0 */
4529/***/ function(module, exports, __webpack_require__) {
4530
4531 "use strict";
4532 /*
4533 Copyright JS Foundation and other contributors, https://js.foundation/
4534
4535 Redistribution and use in source and binary forms, with or without
4536 modification, are permitted provided that the following conditions are met:
4537
4538 * Redistributions of source code must retain the above copyright
4539 notice, this list of conditions and the following disclaimer.
4540 * Redistributions in binary form must reproduce the above copyright
4541 notice, this list of conditions and the following disclaimer in the
4542 documentation and/or other materials provided with the distribution.
4543
4544 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4545 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4546 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4547 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
4548 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4549 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4550 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
4551 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4552 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
4553 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4554 */
4555 Object.defineProperty(exports, "__esModule", { value: true });
4556 var comment_handler_1 = __webpack_require__(1);
4557 var jsx_parser_1 = __webpack_require__(3);
4558 var parser_1 = __webpack_require__(8);
4559 var tokenizer_1 = __webpack_require__(15);
4560 function parse(code, options, delegate) {
4561 var commentHandler = null;
4562 var proxyDelegate = function (node, metadata) {
4563 if (delegate) {
4564 delegate(node, metadata);
4565 }
4566 if (commentHandler) {
4567 commentHandler.visit(node, metadata);
4568 }
4569 };
4570 var parserDelegate = (typeof delegate === 'function') ? proxyDelegate : null;
4571 var collectComment = false;
4572 if (options) {
4573 collectComment = (typeof options.comment === 'boolean' && options.comment);
4574 var attachComment = (typeof options.attachComment === 'boolean' && options.attachComment);
4575 if (collectComment || attachComment) {
4576 commentHandler = new comment_handler_1.CommentHandler();
4577 commentHandler.attach = attachComment;
4578 options.comment = true;
4579 parserDelegate = proxyDelegate;
4580 }
4581 }
4582 var isModule = false;
4583 if (options && typeof options.sourceType === 'string') {
4584 isModule = (options.sourceType === 'module');
4585 }
4586 var parser;
4587 if (options && typeof options.jsx === 'boolean' && options.jsx) {
4588 parser = new jsx_parser_1.JSXParser(code, options, parserDelegate);
4589 }
4590 else {
4591 parser = new parser_1.Parser(code, options, parserDelegate);
4592 }
4593 var program = isModule ? parser.parseModule() : parser.parseScript();
4594 var ast = program;
4595 if (collectComment && commentHandler) {
4596 ast.comments = commentHandler.comments;
4597 }
4598 if (parser.config.tokens) {
4599 ast.tokens = parser.tokens;
4600 }
4601 if (parser.config.tolerant) {
4602 ast.errors = parser.errorHandler.errors;
4603 }
4604 return ast;
4605 }
4606 exports.parse = parse;
4607 function parseModule(code, options, delegate) {
4608 var parsingOptions = options || {};
4609 parsingOptions.sourceType = 'module';
4610 return parse(code, parsingOptions, delegate);
4611 }
4612 exports.parseModule = parseModule;
4613 function parseScript(code, options, delegate) {
4614 var parsingOptions = options || {};
4615 parsingOptions.sourceType = 'script';
4616 return parse(code, parsingOptions, delegate);
4617 }
4618 exports.parseScript = parseScript;
4619 function tokenize(code, options, delegate) {
4620 var tokenizer = new tokenizer_1.Tokenizer(code, options);
4621 var tokens;
4622 tokens = [];
4623 try {
4624 while (true) {
4625 var token = tokenizer.getNextToken();
4626 if (!token) {
4627 break;
4628 }
4629 if (delegate) {
4630 token = delegate(token);
4631 }
4632 tokens.push(token);
4633 }
4634 }
4635 catch (e) {
4636 tokenizer.errorHandler.tolerate(e);
4637 }
4638 if (tokenizer.errorHandler.tolerant) {
4639 tokens.errors = tokenizer.errors();
4640 }
4641 return tokens;
4642 }
4643 exports.tokenize = tokenize;
4644 var syntax_1 = __webpack_require__(2);
4645 exports.Syntax = syntax_1.Syntax;
4646 // Sync with *.json manifests.
4647 exports.version = '4.0.0';
4648
4649
4650/***/ },
4651/* 1 */
4652/***/ function(module, exports, __webpack_require__) {
4653
4654 "use strict";
4655 Object.defineProperty(exports, "__esModule", { value: true });
4656 var syntax_1 = __webpack_require__(2);
4657 var CommentHandler = (function () {
4658 function CommentHandler() {
4659 this.attach = false;
4660 this.comments = [];
4661 this.stack = [];
4662 this.leading = [];
4663 this.trailing = [];
4664 }
4665 CommentHandler.prototype.insertInnerComments = function (node, metadata) {
4666 // innnerComments for properties empty block
4667 // `function a() {/** comments **\/}`
4668 if (node.type === syntax_1.Syntax.BlockStatement && node.body.length === 0) {
4669 var innerComments = [];
4670 for (var i = this.leading.length - 1; i >= 0; --i) {
4671 var entry = this.leading[i];
4672 if (metadata.end.offset >= entry.start) {
4673 innerComments.unshift(entry.comment);
4674 this.leading.splice(i, 1);
4675 this.trailing.splice(i, 1);
4676 }
4677 }
4678 if (innerComments.length) {
4679 node.innerComments = innerComments;
4680 }
4681 }
4682 };
4683 CommentHandler.prototype.findTrailingComments = function (metadata) {
4684 var trailingComments = [];
4685 if (this.trailing.length > 0) {
4686 for (var i = this.trailing.length - 1; i >= 0; --i) {
4687 var entry_1 = this.trailing[i];
4688 if (entry_1.start >= metadata.end.offset) {
4689 trailingComments.unshift(entry_1.comment);
4690 }
4691 }
4692 this.trailing.length = 0;
4693 return trailingComments;
4694 }
4695 var entry = this.stack[this.stack.length - 1];
4696 if (entry && entry.node.trailingComments) {
4697 var firstComment = entry.node.trailingComments[0];
4698 if (firstComment && firstComment.range[0] >= metadata.end.offset) {
4699 trailingComments = entry.node.trailingComments;
4700 delete entry.node.trailingComments;
4701 }
4702 }
4703 return trailingComments;
4704 };
4705 CommentHandler.prototype.findLeadingComments = function (metadata) {
4706 var leadingComments = [];
4707 var target;
4708 while (this.stack.length > 0) {
4709 var entry = this.stack[this.stack.length - 1];
4710 if (entry && entry.start >= metadata.start.offset) {
4711 target = entry.node;
4712 this.stack.pop();
4713 }
4714 else {
4715 break;
4716 }
4717 }
4718 if (target) {
4719 var count = target.leadingComments ? target.leadingComments.length : 0;
4720 for (var i = count - 1; i >= 0; --i) {
4721 var comment = target.leadingComments[i];
4722 if (comment.range[1] <= metadata.start.offset) {
4723 leadingComments.unshift(comment);
4724 target.leadingComments.splice(i, 1);
4725 }
4726 }
4727 if (target.leadingComments && target.leadingComments.length === 0) {
4728 delete target.leadingComments;
4729 }
4730 return leadingComments;
4731 }
4732 for (var i = this.leading.length - 1; i >= 0; --i) {
4733 var entry = this.leading[i];
4734 if (entry.start <= metadata.start.offset) {
4735 leadingComments.unshift(entry.comment);
4736 this.leading.splice(i, 1);
4737 }
4738 }
4739 return leadingComments;
4740 };
4741 CommentHandler.prototype.visitNode = function (node, metadata) {
4742 if (node.type === syntax_1.Syntax.Program && node.body.length > 0) {
4743 return;
4744 }
4745 this.insertInnerComments(node, metadata);
4746 var trailingComments = this.findTrailingComments(metadata);
4747 var leadingComments = this.findLeadingComments(metadata);
4748 if (leadingComments.length > 0) {
4749 node.leadingComments = leadingComments;
4750 }
4751 if (trailingComments.length > 0) {
4752 node.trailingComments = trailingComments;
4753 }
4754 this.stack.push({
4755 node: node,
4756 start: metadata.start.offset
4757 });
4758 };
4759 CommentHandler.prototype.visitComment = function (node, metadata) {
4760 var type = (node.type[0] === 'L') ? 'Line' : 'Block';
4761 var comment = {
4762 type: type,
4763 value: node.value
4764 };
4765 if (node.range) {
4766 comment.range = node.range;
4767 }
4768 if (node.loc) {
4769 comment.loc = node.loc;
4770 }
4771 this.comments.push(comment);
4772 if (this.attach) {
4773 var entry = {
4774 comment: {
4775 type: type,
4776 value: node.value,
4777 range: [metadata.start.offset, metadata.end.offset]
4778 },
4779 start: metadata.start.offset
4780 };
4781 if (node.loc) {
4782 entry.comment.loc = node.loc;
4783 }
4784 node.type = type;
4785 this.leading.push(entry);
4786 this.trailing.push(entry);
4787 }
4788 };
4789 CommentHandler.prototype.visit = function (node, metadata) {
4790 if (node.type === 'LineComment') {
4791 this.visitComment(node, metadata);
4792 }
4793 else if (node.type === 'BlockComment') {
4794 this.visitComment(node, metadata);
4795 }
4796 else if (this.attach) {
4797 this.visitNode(node, metadata);
4798 }
4799 };
4800 return CommentHandler;
4801 }());
4802 exports.CommentHandler = CommentHandler;
4803
4804
4805/***/ },
4806/* 2 */
4807/***/ function(module, exports) {
4808
4809 "use strict";
4810 Object.defineProperty(exports, "__esModule", { value: true });
4811 exports.Syntax = {
4812 AssignmentExpression: 'AssignmentExpression',
4813 AssignmentPattern: 'AssignmentPattern',
4814 ArrayExpression: 'ArrayExpression',
4815 ArrayPattern: 'ArrayPattern',
4816 ArrowFunctionExpression: 'ArrowFunctionExpression',
4817 AwaitExpression: 'AwaitExpression',
4818 BlockStatement: 'BlockStatement',
4819 BinaryExpression: 'BinaryExpression',
4820 BreakStatement: 'BreakStatement',
4821 CallExpression: 'CallExpression',
4822 CatchClause: 'CatchClause',
4823 ClassBody: 'ClassBody',
4824 ClassDeclaration: 'ClassDeclaration',
4825 ClassExpression: 'ClassExpression',
4826 ConditionalExpression: 'ConditionalExpression',
4827 ContinueStatement: 'ContinueStatement',
4828 DoWhileStatement: 'DoWhileStatement',
4829 DebuggerStatement: 'DebuggerStatement',
4830 EmptyStatement: 'EmptyStatement',
4831 ExportAllDeclaration: 'ExportAllDeclaration',
4832 ExportDefaultDeclaration: 'ExportDefaultDeclaration',
4833 ExportNamedDeclaration: 'ExportNamedDeclaration',
4834 ExportSpecifier: 'ExportSpecifier',
4835 ExpressionStatement: 'ExpressionStatement',
4836 ForStatement: 'ForStatement',
4837 ForOfStatement: 'ForOfStatement',
4838 ForInStatement: 'ForInStatement',
4839 FunctionDeclaration: 'FunctionDeclaration',
4840 FunctionExpression: 'FunctionExpression',
4841 Identifier: 'Identifier',
4842 IfStatement: 'IfStatement',
4843 ImportDeclaration: 'ImportDeclaration',
4844 ImportDefaultSpecifier: 'ImportDefaultSpecifier',
4845 ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
4846 ImportSpecifier: 'ImportSpecifier',
4847 Literal: 'Literal',
4848 LabeledStatement: 'LabeledStatement',
4849 LogicalExpression: 'LogicalExpression',
4850 MemberExpression: 'MemberExpression',
4851 MetaProperty: 'MetaProperty',
4852 MethodDefinition: 'MethodDefinition',
4853 NewExpression: 'NewExpression',
4854 ObjectExpression: 'ObjectExpression',
4855 ObjectPattern: 'ObjectPattern',
4856 Program: 'Program',
4857 Property: 'Property',
4858 RestElement: 'RestElement',
4859 ReturnStatement: 'ReturnStatement',
4860 SequenceExpression: 'SequenceExpression',
4861 SpreadElement: 'SpreadElement',
4862 Super: 'Super',
4863 SwitchCase: 'SwitchCase',
4864 SwitchStatement: 'SwitchStatement',
4865 TaggedTemplateExpression: 'TaggedTemplateExpression',
4866 TemplateElement: 'TemplateElement',
4867 TemplateLiteral: 'TemplateLiteral',
4868 ThisExpression: 'ThisExpression',
4869 ThrowStatement: 'ThrowStatement',
4870 TryStatement: 'TryStatement',
4871 UnaryExpression: 'UnaryExpression',
4872 UpdateExpression: 'UpdateExpression',
4873 VariableDeclaration: 'VariableDeclaration',
4874 VariableDeclarator: 'VariableDeclarator',
4875 WhileStatement: 'WhileStatement',
4876 WithStatement: 'WithStatement',
4877 YieldExpression: 'YieldExpression'
4878 };
4879
4880
4881/***/ },
4882/* 3 */
4883/***/ function(module, exports, __webpack_require__) {
4884
4885 "use strict";
4886/* istanbul ignore next */
4887 var __extends = (this && this.__extends) || (function () {
4888 var extendStatics = Object.setPrototypeOf ||
4889 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4890 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4891 return function (d, b) {
4892 extendStatics(d, b);
4893 function __() { this.constructor = d; }
4894 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4895 };
4896 })();
4897 Object.defineProperty(exports, "__esModule", { value: true });
4898 var character_1 = __webpack_require__(4);
4899 var JSXNode = __webpack_require__(5);
4900 var jsx_syntax_1 = __webpack_require__(6);
4901 var Node = __webpack_require__(7);
4902 var parser_1 = __webpack_require__(8);
4903 var token_1 = __webpack_require__(13);
4904 var xhtml_entities_1 = __webpack_require__(14);
4905 token_1.TokenName[100 /* Identifier */] = 'JSXIdentifier';
4906 token_1.TokenName[101 /* Text */] = 'JSXText';
4907 // Fully qualified element name, e.g. <svg:path> returns "svg:path"
4908 function getQualifiedElementName(elementName) {
4909 var qualifiedName;
4910 switch (elementName.type) {
4911 case jsx_syntax_1.JSXSyntax.JSXIdentifier:
4912 var id = elementName;
4913 qualifiedName = id.name;
4914 break;
4915 case jsx_syntax_1.JSXSyntax.JSXNamespacedName:
4916 var ns = elementName;
4917 qualifiedName = getQualifiedElementName(ns.namespace) + ':' +
4918 getQualifiedElementName(ns.name);
4919 break;
4920 case jsx_syntax_1.JSXSyntax.JSXMemberExpression:
4921 var expr = elementName;
4922 qualifiedName = getQualifiedElementName(expr.object) + '.' +
4923 getQualifiedElementName(expr.property);
4924 break;
4925 /* istanbul ignore next */
4926 default:
4927 break;
4928 }
4929 return qualifiedName;
4930 }
4931 var JSXParser = (function (_super) {
4932 __extends(JSXParser, _super);
4933 function JSXParser(code, options, delegate) {
4934 return _super.call(this, code, options, delegate) || this;
4935 }
4936 JSXParser.prototype.parsePrimaryExpression = function () {
4937 return this.match('<') ? this.parseJSXRoot() : _super.prototype.parsePrimaryExpression.call(this);
4938 };
4939 JSXParser.prototype.startJSX = function () {
4940 // Unwind the scanner before the lookahead token.
4941 this.scanner.index = this.startMarker.index;
4942 this.scanner.lineNumber = this.startMarker.line;
4943 this.scanner.lineStart = this.startMarker.index - this.startMarker.column;
4944 };
4945 JSXParser.prototype.finishJSX = function () {
4946 // Prime the next lookahead.
4947 this.nextToken();
4948 };
4949 JSXParser.prototype.reenterJSX = function () {
4950 this.startJSX();
4951 this.expectJSX('}');
4952 // Pop the closing '}' added from the lookahead.
4953 if (this.config.tokens) {
4954 this.tokens.pop();
4955 }
4956 };
4957 JSXParser.prototype.createJSXNode = function () {
4958 this.collectComments();
4959 return {
4960 index: this.scanner.index,
4961 line: this.scanner.lineNumber,
4962 column: this.scanner.index - this.scanner.lineStart
4963 };
4964 };
4965 JSXParser.prototype.createJSXChildNode = function () {
4966 return {
4967 index: this.scanner.index,
4968 line: this.scanner.lineNumber,
4969 column: this.scanner.index - this.scanner.lineStart
4970 };
4971 };
4972 JSXParser.prototype.scanXHTMLEntity = function (quote) {
4973 var result = '&';
4974 var valid = true;
4975 var terminated = false;
4976 var numeric = false;
4977 var hex = false;
4978 while (!this.scanner.eof() && valid && !terminated) {
4979 var ch = this.scanner.source[this.scanner.index];
4980 if (ch === quote) {
4981 break;
4982 }
4983 terminated = (ch === ';');
4984 result += ch;
4985 ++this.scanner.index;
4986 if (!terminated) {
4987 switch (result.length) {
4988 case 2:
4989 // e.g. '&#123;'
4990 numeric = (ch === '#');
4991 break;
4992 case 3:
4993 if (numeric) {
4994 // e.g. '&#x41;'
4995 hex = (ch === 'x');
4996 valid = hex || character_1.Character.isDecimalDigit(ch.charCodeAt(0));
4997 numeric = numeric && !hex;
4998 }
4999 break;
5000 default:
5001 valid = valid && !(numeric && !character_1.Character.isDecimalDigit(ch.charCodeAt(0)));
5002 valid = valid && !(hex && !character_1.Character.isHexDigit(ch.charCodeAt(0)));
5003 break;
5004 }
5005 }
5006 }
5007 if (valid && terminated && result.length > 2) {
5008 // e.g. '&#x41;' becomes just '#x41'
5009 var str = result.substr(1, result.length - 2);
5010 if (numeric && str.length > 1) {
5011 result = String.fromCharCode(parseInt(str.substr(1), 10));
5012 }
5013 else if (hex && str.length > 2) {
5014 result = String.fromCharCode(parseInt('0' + str.substr(1), 16));
5015 }
5016 else if (!numeric && !hex && xhtml_entities_1.XHTMLEntities[str]) {
5017 result = xhtml_entities_1.XHTMLEntities[str];
5018 }
5019 }
5020 return result;
5021 };
5022 // Scan the next JSX token. This replaces Scanner#lex when in JSX mode.
5023 JSXParser.prototype.lexJSX = function () {
5024 var cp = this.scanner.source.charCodeAt(this.scanner.index);
5025 // < > / : = { }
5026 if (cp === 60 || cp === 62 || cp === 47 || cp === 58 || cp === 61 || cp === 123 || cp === 125) {
5027 var value = this.scanner.source[this.scanner.index++];
5028 return {
5029 type: 7 /* Punctuator */,
5030 value: value,
5031 lineNumber: this.scanner.lineNumber,
5032 lineStart: this.scanner.lineStart,
5033 start: this.scanner.index - 1,
5034 end: this.scanner.index
5035 };
5036 }
5037 // " '
5038 if (cp === 34 || cp === 39) {
5039 var start = this.scanner.index;
5040 var quote = this.scanner.source[this.scanner.index++];
5041 var str = '';
5042 while (!this.scanner.eof()) {
5043 var ch = this.scanner.source[this.scanner.index++];
5044 if (ch === quote) {
5045 break;
5046 }
5047 else if (ch === '&') {
5048 str += this.scanXHTMLEntity(quote);
5049 }
5050 else {
5051 str += ch;
5052 }
5053 }
5054 return {
5055 type: 8 /* StringLiteral */,
5056 value: str,
5057 lineNumber: this.scanner.lineNumber,
5058 lineStart: this.scanner.lineStart,
5059 start: start,
5060 end: this.scanner.index
5061 };
5062 }
5063 // ... or .
5064 if (cp === 46) {
5065 var n1 = this.scanner.source.charCodeAt(this.scanner.index + 1);
5066 var n2 = this.scanner.source.charCodeAt(this.scanner.index + 2);
5067 var value = (n1 === 46 && n2 === 46) ? '...' : '.';
5068 var start = this.scanner.index;
5069 this.scanner.index += value.length;
5070 return {
5071 type: 7 /* Punctuator */,
5072 value: value,
5073 lineNumber: this.scanner.lineNumber,
5074 lineStart: this.scanner.lineStart,
5075 start: start,
5076 end: this.scanner.index
5077 };
5078 }
5079 // `
5080 if (cp === 96) {
5081 // Only placeholder, since it will be rescanned as a real assignment expression.
5082 return {
5083 type: 10 /* Template */,
5084 value: '',
5085 lineNumber: this.scanner.lineNumber,
5086 lineStart: this.scanner.lineStart,
5087 start: this.scanner.index,
5088 end: this.scanner.index
5089 };
5090 }
5091 // Identifer can not contain backslash (char code 92).
5092 if (character_1.Character.isIdentifierStart(cp) && (cp !== 92)) {
5093 var start = this.scanner.index;
5094 ++this.scanner.index;
5095 while (!this.scanner.eof()) {
5096 var ch = this.scanner.source.charCodeAt(this.scanner.index);
5097 if (character_1.Character.isIdentifierPart(ch) && (ch !== 92)) {
5098 ++this.scanner.index;
5099 }
5100 else if (ch === 45) {
5101 // Hyphen (char code 45) can be part of an identifier.
5102 ++this.scanner.index;
5103 }
5104 else {
5105 break;
5106 }
5107 }
5108 var id = this.scanner.source.slice(start, this.scanner.index);
5109 return {
5110 type: 100 /* Identifier */,
5111 value: id,
5112 lineNumber: this.scanner.lineNumber,
5113 lineStart: this.scanner.lineStart,
5114 start: start,
5115 end: this.scanner.index
5116 };
5117 }
5118 return this.scanner.lex();
5119 };
5120 JSXParser.prototype.nextJSXToken = function () {
5121 this.collectComments();
5122 this.startMarker.index = this.scanner.index;
5123 this.startMarker.line = this.scanner.lineNumber;
5124 this.startMarker.column = this.scanner.index - this.scanner.lineStart;
5125 var token = this.lexJSX();
5126 this.lastMarker.index = this.scanner.index;
5127 this.lastMarker.line = this.scanner.lineNumber;
5128 this.lastMarker.column = this.scanner.index - this.scanner.lineStart;
5129 if (this.config.tokens) {
5130 this.tokens.push(this.convertToken(token));
5131 }
5132 return token;
5133 };
5134 JSXParser.prototype.nextJSXText = function () {
5135 this.startMarker.index = this.scanner.index;
5136 this.startMarker.line = this.scanner.lineNumber;
5137 this.startMarker.column = this.scanner.index - this.scanner.lineStart;
5138 var start = this.scanner.index;
5139 var text = '';
5140 while (!this.scanner.eof()) {
5141 var ch = this.scanner.source[this.scanner.index];
5142 if (ch === '{' || ch === '<') {
5143 break;
5144 }
5145 ++this.scanner.index;
5146 text += ch;
5147 if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) {
5148 ++this.scanner.lineNumber;
5149 if (ch === '\r' && this.scanner.source[this.scanner.index] === '\n') {
5150 ++this.scanner.index;
5151 }
5152 this.scanner.lineStart = this.scanner.index;
5153 }
5154 }
5155 this.lastMarker.index = this.scanner.index;
5156 this.lastMarker.line = this.scanner.lineNumber;
5157 this.lastMarker.column = this.scanner.index - this.scanner.lineStart;
5158 var token = {
5159 type: 101 /* Text */,
5160 value: text,
5161 lineNumber: this.scanner.lineNumber,
5162 lineStart: this.scanner.lineStart,
5163 start: start,
5164 end: this.scanner.index
5165 };
5166 if ((text.length > 0) && this.config.tokens) {
5167 this.tokens.push(this.convertToken(token));
5168 }
5169 return token;
5170 };
5171 JSXParser.prototype.peekJSXToken = function () {
5172 var state = this.scanner.saveState();
5173 this.scanner.scanComments();
5174 var next = this.lexJSX();
5175 this.scanner.restoreState(state);
5176 return next;
5177 };
5178 // Expect the next JSX token to match the specified punctuator.
5179 // If not, an exception will be thrown.
5180 JSXParser.prototype.expectJSX = function (value) {
5181 var token = this.nextJSXToken();
5182 if (token.type !== 7 /* Punctuator */ || token.value !== value) {
5183 this.throwUnexpectedToken(token);
5184 }
5185 };
5186 // Return true if the next JSX token matches the specified punctuator.
5187 JSXParser.prototype.matchJSX = function (value) {
5188 var next = this.peekJSXToken();
5189 return next.type === 7 /* Punctuator */ && next.value === value;
5190 };
5191 JSXParser.prototype.parseJSXIdentifier = function () {
5192 var node = this.createJSXNode();
5193 var token = this.nextJSXToken();
5194 if (token.type !== 100 /* Identifier */) {
5195 this.throwUnexpectedToken(token);
5196 }
5197 return this.finalize(node, new JSXNode.JSXIdentifier(token.value));
5198 };
5199 JSXParser.prototype.parseJSXElementName = function () {
5200 var node = this.createJSXNode();
5201 var elementName = this.parseJSXIdentifier();
5202 if (this.matchJSX(':')) {
5203 var namespace = elementName;
5204 this.expectJSX(':');
5205 var name_1 = this.parseJSXIdentifier();
5206 elementName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_1));
5207 }
5208 else if (this.matchJSX('.')) {
5209 while (this.matchJSX('.')) {
5210 var object = elementName;
5211 this.expectJSX('.');
5212 var property = this.parseJSXIdentifier();
5213 elementName = this.finalize(node, new JSXNode.JSXMemberExpression(object, property));
5214 }
5215 }
5216 return elementName;
5217 };
5218 JSXParser.prototype.parseJSXAttributeName = function () {
5219 var node = this.createJSXNode();
5220 var attributeName;
5221 var identifier = this.parseJSXIdentifier();
5222 if (this.matchJSX(':')) {
5223 var namespace = identifier;
5224 this.expectJSX(':');
5225 var name_2 = this.parseJSXIdentifier();
5226 attributeName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_2));
5227 }
5228 else {
5229 attributeName = identifier;
5230 }
5231 return attributeName;
5232 };
5233 JSXParser.prototype.parseJSXStringLiteralAttribute = function () {
5234 var node = this.createJSXNode();
5235 var token = this.nextJSXToken();
5236 if (token.type !== 8 /* StringLiteral */) {
5237 this.throwUnexpectedToken(token);
5238 }
5239 var raw = this.getTokenRaw(token);
5240 return this.finalize(node, new Node.Literal(token.value, raw));
5241 };
5242 JSXParser.prototype.parseJSXExpressionAttribute = function () {
5243 var node = this.createJSXNode();
5244 this.expectJSX('{');
5245 this.finishJSX();
5246 if (this.match('}')) {
5247 this.tolerateError('JSX attributes must only be assigned a non-empty expression');
5248 }
5249 var expression = this.parseAssignmentExpression();
5250 this.reenterJSX();
5251 return this.finalize(node, new JSXNode.JSXExpressionContainer(expression));
5252 };
5253 JSXParser.prototype.parseJSXAttributeValue = function () {
5254 return this.matchJSX('{') ? this.parseJSXExpressionAttribute() :
5255 this.matchJSX('<') ? this.parseJSXElement() : this.parseJSXStringLiteralAttribute();
5256 };
5257 JSXParser.prototype.parseJSXNameValueAttribute = function () {
5258 var node = this.createJSXNode();
5259 var name = this.parseJSXAttributeName();
5260 var value = null;
5261 if (this.matchJSX('=')) {
5262 this.expectJSX('=');
5263 value = this.parseJSXAttributeValue();
5264 }
5265 return this.finalize(node, new JSXNode.JSXAttribute(name, value));
5266 };
5267 JSXParser.prototype.parseJSXSpreadAttribute = function () {
5268 var node = this.createJSXNode();
5269 this.expectJSX('{');
5270 this.expectJSX('...');
5271 this.finishJSX();
5272 var argument = this.parseAssignmentExpression();
5273 this.reenterJSX();
5274 return this.finalize(node, new JSXNode.JSXSpreadAttribute(argument));
5275 };
5276 JSXParser.prototype.parseJSXAttributes = function () {
5277 var attributes = [];
5278 while (!this.matchJSX('/') && !this.matchJSX('>')) {
5279 var attribute = this.matchJSX('{') ? this.parseJSXSpreadAttribute() :
5280 this.parseJSXNameValueAttribute();
5281 attributes.push(attribute);
5282 }
5283 return attributes;
5284 };
5285 JSXParser.prototype.parseJSXOpeningElement = function () {
5286 var node = this.createJSXNode();
5287 this.expectJSX('<');
5288 var name = this.parseJSXElementName();
5289 var attributes = this.parseJSXAttributes();
5290 var selfClosing = this.matchJSX('/');
5291 if (selfClosing) {
5292 this.expectJSX('/');
5293 }
5294 this.expectJSX('>');
5295 return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes));
5296 };
5297 JSXParser.prototype.parseJSXBoundaryElement = function () {
5298 var node = this.createJSXNode();
5299 this.expectJSX('<');
5300 if (this.matchJSX('/')) {
5301 this.expectJSX('/');
5302 var name_3 = this.parseJSXElementName();
5303 this.expectJSX('>');
5304 return this.finalize(node, new JSXNode.JSXClosingElement(name_3));
5305 }
5306 var name = this.parseJSXElementName();
5307 var attributes = this.parseJSXAttributes();
5308 var selfClosing = this.matchJSX('/');
5309 if (selfClosing) {
5310 this.expectJSX('/');
5311 }
5312 this.expectJSX('>');
5313 return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes));
5314 };
5315 JSXParser.prototype.parseJSXEmptyExpression = function () {
5316 var node = this.createJSXChildNode();
5317 this.collectComments();
5318 this.lastMarker.index = this.scanner.index;
5319 this.lastMarker.line = this.scanner.lineNumber;
5320 this.lastMarker.column = this.scanner.index - this.scanner.lineStart;
5321 return this.finalize(node, new JSXNode.JSXEmptyExpression());
5322 };
5323 JSXParser.prototype.parseJSXExpressionContainer = function () {
5324 var node = this.createJSXNode();
5325 this.expectJSX('{');
5326 var expression;
5327 if (this.matchJSX('}')) {
5328 expression = this.parseJSXEmptyExpression();
5329 this.expectJSX('}');
5330 }
5331 else {
5332 this.finishJSX();
5333 expression = this.parseAssignmentExpression();
5334 this.reenterJSX();
5335 }
5336 return this.finalize(node, new JSXNode.JSXExpressionContainer(expression));
5337 };
5338 JSXParser.prototype.parseJSXChildren = function () {
5339 var children = [];
5340 while (!this.scanner.eof()) {
5341 var node = this.createJSXChildNode();
5342 var token = this.nextJSXText();
5343 if (token.start < token.end) {
5344 var raw = this.getTokenRaw(token);
5345 var child = this.finalize(node, new JSXNode.JSXText(token.value, raw));
5346 children.push(child);
5347 }
5348 if (this.scanner.source[this.scanner.index] === '{') {
5349 var container = this.parseJSXExpressionContainer();
5350 children.push(container);
5351 }
5352 else {
5353 break;
5354 }
5355 }
5356 return children;
5357 };
5358 JSXParser.prototype.parseComplexJSXElement = function (el) {
5359 var stack = [];
5360 while (!this.scanner.eof()) {
5361 el.children = el.children.concat(this.parseJSXChildren());
5362 var node = this.createJSXChildNode();
5363 var element = this.parseJSXBoundaryElement();
5364 if (element.type === jsx_syntax_1.JSXSyntax.JSXOpeningElement) {
5365 var opening = element;
5366 if (opening.selfClosing) {
5367 var child = this.finalize(node, new JSXNode.JSXElement(opening, [], null));
5368 el.children.push(child);
5369 }
5370 else {
5371 stack.push(el);
5372 el = { node: node, opening: opening, closing: null, children: [] };
5373 }
5374 }
5375 if (element.type === jsx_syntax_1.JSXSyntax.JSXClosingElement) {
5376 el.closing = element;
5377 var open_1 = getQualifiedElementName(el.opening.name);
5378 var close_1 = getQualifiedElementName(el.closing.name);
5379 if (open_1 !== close_1) {
5380 this.tolerateError('Expected corresponding JSX closing tag for %0', open_1);
5381 }
5382 if (stack.length > 0) {
5383 var child = this.finalize(el.node, new JSXNode.JSXElement(el.opening, el.children, el.closing));
5384 el = stack[stack.length - 1];
5385 el.children.push(child);
5386 stack.pop();
5387 }
5388 else {
5389 break;
5390 }
5391 }
5392 }
5393 return el;
5394 };
5395 JSXParser.prototype.parseJSXElement = function () {
5396 var node = this.createJSXNode();
5397 var opening = this.parseJSXOpeningElement();
5398 var children = [];
5399 var closing = null;
5400 if (!opening.selfClosing) {
5401 var el = this.parseComplexJSXElement({ node: node, opening: opening, closing: closing, children: children });
5402 children = el.children;
5403 closing = el.closing;
5404 }
5405 return this.finalize(node, new JSXNode.JSXElement(opening, children, closing));
5406 };
5407 JSXParser.prototype.parseJSXRoot = function () {
5408 // Pop the opening '<' added from the lookahead.
5409 if (this.config.tokens) {
5410 this.tokens.pop();
5411 }
5412 this.startJSX();
5413 var element = this.parseJSXElement();
5414 this.finishJSX();
5415 return element;
5416 };
5417 JSXParser.prototype.isStartOfExpression = function () {
5418 return _super.prototype.isStartOfExpression.call(this) || this.match('<');
5419 };
5420 return JSXParser;
5421 }(parser_1.Parser));
5422 exports.JSXParser = JSXParser;
5423
5424
5425/***/ },
5426/* 4 */
5427/***/ function(module, exports) {
5428
5429 "use strict";
5430 Object.defineProperty(exports, "__esModule", { value: true });
5431 // See also tools/generate-unicode-regex.js.
5432 var Regex = {
5433 // Unicode v8.0.0 NonAsciiIdentifierStart:
5434 NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\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\u0AF9\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-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/,
5435 // Unicode v8.0.0 NonAsciiIdentifierPart:
5436 NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
5437 };
5438 exports.Character = {
5439 /* tslint:disable:no-bitwise */
5440 fromCodePoint: function (cp) {
5441 return (cp < 0x10000) ? String.fromCharCode(cp) :
5442 String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
5443 String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
5444 },
5445 // https://tc39.github.io/ecma262/#sec-white-space
5446 isWhiteSpace: function (cp) {
5447 return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) ||
5448 (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0);
5449 },
5450 // https://tc39.github.io/ecma262/#sec-line-terminators
5451 isLineTerminator: function (cp) {
5452 return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029);
5453 },
5454 // https://tc39.github.io/ecma262/#sec-names-and-keywords
5455 isIdentifierStart: function (cp) {
5456 return (cp === 0x24) || (cp === 0x5F) ||
5457 (cp >= 0x41 && cp <= 0x5A) ||
5458 (cp >= 0x61 && cp <= 0x7A) ||
5459 (cp === 0x5C) ||
5460 ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(exports.Character.fromCodePoint(cp)));
5461 },
5462 isIdentifierPart: function (cp) {
5463 return (cp === 0x24) || (cp === 0x5F) ||
5464 (cp >= 0x41 && cp <= 0x5A) ||
5465 (cp >= 0x61 && cp <= 0x7A) ||
5466 (cp >= 0x30 && cp <= 0x39) ||
5467 (cp === 0x5C) ||
5468 ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(exports.Character.fromCodePoint(cp)));
5469 },
5470 // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
5471 isDecimalDigit: function (cp) {
5472 return (cp >= 0x30 && cp <= 0x39); // 0..9
5473 },
5474 isHexDigit: function (cp) {
5475 return (cp >= 0x30 && cp <= 0x39) ||
5476 (cp >= 0x41 && cp <= 0x46) ||
5477 (cp >= 0x61 && cp <= 0x66); // a..f
5478 },
5479 isOctalDigit: function (cp) {
5480 return (cp >= 0x30 && cp <= 0x37); // 0..7
5481 }
5482 };
5483
5484
5485/***/ },
5486/* 5 */
5487/***/ function(module, exports, __webpack_require__) {
5488
5489 "use strict";
5490 Object.defineProperty(exports, "__esModule", { value: true });
5491 var jsx_syntax_1 = __webpack_require__(6);
5492 /* tslint:disable:max-classes-per-file */
5493 var JSXClosingElement = (function () {
5494 function JSXClosingElement(name) {
5495 this.type = jsx_syntax_1.JSXSyntax.JSXClosingElement;
5496 this.name = name;
5497 }
5498 return JSXClosingElement;
5499 }());
5500 exports.JSXClosingElement = JSXClosingElement;
5501 var JSXElement = (function () {
5502 function JSXElement(openingElement, children, closingElement) {
5503 this.type = jsx_syntax_1.JSXSyntax.JSXElement;
5504 this.openingElement = openingElement;
5505 this.children = children;
5506 this.closingElement = closingElement;
5507 }
5508 return JSXElement;
5509 }());
5510 exports.JSXElement = JSXElement;
5511 var JSXEmptyExpression = (function () {
5512 function JSXEmptyExpression() {
5513 this.type = jsx_syntax_1.JSXSyntax.JSXEmptyExpression;
5514 }
5515 return JSXEmptyExpression;
5516 }());
5517 exports.JSXEmptyExpression = JSXEmptyExpression;
5518 var JSXExpressionContainer = (function () {
5519 function JSXExpressionContainer(expression) {
5520 this.type = jsx_syntax_1.JSXSyntax.JSXExpressionContainer;
5521 this.expression = expression;
5522 }
5523 return JSXExpressionContainer;
5524 }());
5525 exports.JSXExpressionContainer = JSXExpressionContainer;
5526 var JSXIdentifier = (function () {
5527 function JSXIdentifier(name) {
5528 this.type = jsx_syntax_1.JSXSyntax.JSXIdentifier;
5529 this.name = name;
5530 }
5531 return JSXIdentifier;
5532 }());
5533 exports.JSXIdentifier = JSXIdentifier;
5534 var JSXMemberExpression = (function () {
5535 function JSXMemberExpression(object, property) {
5536 this.type = jsx_syntax_1.JSXSyntax.JSXMemberExpression;
5537 this.object = object;
5538 this.property = property;
5539 }
5540 return JSXMemberExpression;
5541 }());
5542 exports.JSXMemberExpression = JSXMemberExpression;
5543 var JSXAttribute = (function () {
5544 function JSXAttribute(name, value) {
5545 this.type = jsx_syntax_1.JSXSyntax.JSXAttribute;
5546 this.name = name;
5547 this.value = value;
5548 }
5549 return JSXAttribute;
5550 }());
5551 exports.JSXAttribute = JSXAttribute;
5552 var JSXNamespacedName = (function () {
5553 function JSXNamespacedName(namespace, name) {
5554 this.type = jsx_syntax_1.JSXSyntax.JSXNamespacedName;
5555 this.namespace = namespace;
5556 this.name = name;
5557 }
5558 return JSXNamespacedName;
5559 }());
5560 exports.JSXNamespacedName = JSXNamespacedName;
5561 var JSXOpeningElement = (function () {
5562 function JSXOpeningElement(name, selfClosing, attributes) {
5563 this.type = jsx_syntax_1.JSXSyntax.JSXOpeningElement;
5564 this.name = name;
5565 this.selfClosing = selfClosing;
5566 this.attributes = attributes;
5567 }
5568 return JSXOpeningElement;
5569 }());
5570 exports.JSXOpeningElement = JSXOpeningElement;
5571 var JSXSpreadAttribute = (function () {
5572 function JSXSpreadAttribute(argument) {
5573 this.type = jsx_syntax_1.JSXSyntax.JSXSpreadAttribute;
5574 this.argument = argument;
5575 }
5576 return JSXSpreadAttribute;
5577 }());
5578 exports.JSXSpreadAttribute = JSXSpreadAttribute;
5579 var JSXText = (function () {
5580 function JSXText(value, raw) {
5581 this.type = jsx_syntax_1.JSXSyntax.JSXText;
5582 this.value = value;
5583 this.raw = raw;
5584 }
5585 return JSXText;
5586 }());
5587 exports.JSXText = JSXText;
5588
5589
5590/***/ },
5591/* 6 */
5592/***/ function(module, exports) {
5593
5594 "use strict";
5595 Object.defineProperty(exports, "__esModule", { value: true });
5596 exports.JSXSyntax = {
5597 JSXAttribute: 'JSXAttribute',
5598 JSXClosingElement: 'JSXClosingElement',
5599 JSXElement: 'JSXElement',
5600 JSXEmptyExpression: 'JSXEmptyExpression',
5601 JSXExpressionContainer: 'JSXExpressionContainer',
5602 JSXIdentifier: 'JSXIdentifier',
5603 JSXMemberExpression: 'JSXMemberExpression',
5604 JSXNamespacedName: 'JSXNamespacedName',
5605 JSXOpeningElement: 'JSXOpeningElement',
5606 JSXSpreadAttribute: 'JSXSpreadAttribute',
5607 JSXText: 'JSXText'
5608 };
5609
5610
5611/***/ },
5612/* 7 */
5613/***/ function(module, exports, __webpack_require__) {
5614
5615 "use strict";
5616 Object.defineProperty(exports, "__esModule", { value: true });
5617 var syntax_1 = __webpack_require__(2);
5618 /* tslint:disable:max-classes-per-file */
5619 var ArrayExpression = (function () {
5620 function ArrayExpression(elements) {
5621 this.type = syntax_1.Syntax.ArrayExpression;
5622 this.elements = elements;
5623 }
5624 return ArrayExpression;
5625 }());
5626 exports.ArrayExpression = ArrayExpression;
5627 var ArrayPattern = (function () {
5628 function ArrayPattern(elements) {
5629 this.type = syntax_1.Syntax.ArrayPattern;
5630 this.elements = elements;
5631 }
5632 return ArrayPattern;
5633 }());
5634 exports.ArrayPattern = ArrayPattern;
5635 var ArrowFunctionExpression = (function () {
5636 function ArrowFunctionExpression(params, body, expression) {
5637 this.type = syntax_1.Syntax.ArrowFunctionExpression;
5638 this.id = null;
5639 this.params = params;
5640 this.body = body;
5641 this.generator = false;
5642 this.expression = expression;
5643 this.async = false;
5644 }
5645 return ArrowFunctionExpression;
5646 }());
5647 exports.ArrowFunctionExpression = ArrowFunctionExpression;
5648 var AssignmentExpression = (function () {
5649 function AssignmentExpression(operator, left, right) {
5650 this.type = syntax_1.Syntax.AssignmentExpression;
5651 this.operator = operator;
5652 this.left = left;
5653 this.right = right;
5654 }
5655 return AssignmentExpression;
5656 }());
5657 exports.AssignmentExpression = AssignmentExpression;
5658 var AssignmentPattern = (function () {
5659 function AssignmentPattern(left, right) {
5660 this.type = syntax_1.Syntax.AssignmentPattern;
5661 this.left = left;
5662 this.right = right;
5663 }
5664 return AssignmentPattern;
5665 }());
5666 exports.AssignmentPattern = AssignmentPattern;
5667 var AsyncArrowFunctionExpression = (function () {
5668 function AsyncArrowFunctionExpression(params, body, expression) {
5669 this.type = syntax_1.Syntax.ArrowFunctionExpression;
5670 this.id = null;
5671 this.params = params;
5672 this.body = body;
5673 this.generator = false;
5674 this.expression = expression;
5675 this.async = true;
5676 }
5677 return AsyncArrowFunctionExpression;
5678 }());
5679 exports.AsyncArrowFunctionExpression = AsyncArrowFunctionExpression;
5680 var AsyncFunctionDeclaration = (function () {
5681 function AsyncFunctionDeclaration(id, params, body) {
5682 this.type = syntax_1.Syntax.FunctionDeclaration;
5683 this.id = id;
5684 this.params = params;
5685 this.body = body;
5686 this.generator = false;
5687 this.expression = false;
5688 this.async = true;
5689 }
5690 return AsyncFunctionDeclaration;
5691 }());
5692 exports.AsyncFunctionDeclaration = AsyncFunctionDeclaration;
5693 var AsyncFunctionExpression = (function () {
5694 function AsyncFunctionExpression(id, params, body) {
5695 this.type = syntax_1.Syntax.FunctionExpression;
5696 this.id = id;
5697 this.params = params;
5698 this.body = body;
5699 this.generator = false;
5700 this.expression = false;
5701 this.async = true;
5702 }
5703 return AsyncFunctionExpression;
5704 }());
5705 exports.AsyncFunctionExpression = AsyncFunctionExpression;
5706 var AwaitExpression = (function () {
5707 function AwaitExpression(argument) {
5708 this.type = syntax_1.Syntax.AwaitExpression;
5709 this.argument = argument;
5710 }
5711 return AwaitExpression;
5712 }());
5713 exports.AwaitExpression = AwaitExpression;
5714 var BinaryExpression = (function () {
5715 function BinaryExpression(operator, left, right) {
5716 var logical = (operator === '||' || operator === '&&');
5717 this.type = logical ? syntax_1.Syntax.LogicalExpression : syntax_1.Syntax.BinaryExpression;
5718 this.operator = operator;
5719 this.left = left;
5720 this.right = right;
5721 }
5722 return BinaryExpression;
5723 }());
5724 exports.BinaryExpression = BinaryExpression;
5725 var BlockStatement = (function () {
5726 function BlockStatement(body) {
5727 this.type = syntax_1.Syntax.BlockStatement;
5728 this.body = body;
5729 }
5730 return BlockStatement;
5731 }());
5732 exports.BlockStatement = BlockStatement;
5733 var BreakStatement = (function () {
5734 function BreakStatement(label) {
5735 this.type = syntax_1.Syntax.BreakStatement;
5736 this.label = label;
5737 }
5738 return BreakStatement;
5739 }());
5740 exports.BreakStatement = BreakStatement;
5741 var CallExpression = (function () {
5742 function CallExpression(callee, args) {
5743 this.type = syntax_1.Syntax.CallExpression;
5744 this.callee = callee;
5745 this.arguments = args;
5746 }
5747 return CallExpression;
5748 }());
5749 exports.CallExpression = CallExpression;
5750 var CatchClause = (function () {
5751 function CatchClause(param, body) {
5752 this.type = syntax_1.Syntax.CatchClause;
5753 this.param = param;
5754 this.body = body;
5755 }
5756 return CatchClause;
5757 }());
5758 exports.CatchClause = CatchClause;
5759 var ClassBody = (function () {
5760 function ClassBody(body) {
5761 this.type = syntax_1.Syntax.ClassBody;
5762 this.body = body;
5763 }
5764 return ClassBody;
5765 }());
5766 exports.ClassBody = ClassBody;
5767 var ClassDeclaration = (function () {
5768 function ClassDeclaration(id, superClass, body) {
5769 this.type = syntax_1.Syntax.ClassDeclaration;
5770 this.id = id;
5771 this.superClass = superClass;
5772 this.body = body;
5773 }
5774 return ClassDeclaration;
5775 }());
5776 exports.ClassDeclaration = ClassDeclaration;
5777 var ClassExpression = (function () {
5778 function ClassExpression(id, superClass, body) {
5779 this.type = syntax_1.Syntax.ClassExpression;
5780 this.id = id;
5781 this.superClass = superClass;
5782 this.body = body;
5783 }
5784 return ClassExpression;
5785 }());
5786 exports.ClassExpression = ClassExpression;
5787 var ComputedMemberExpression = (function () {
5788 function ComputedMemberExpression(object, property) {
5789 this.type = syntax_1.Syntax.MemberExpression;
5790 this.computed = true;
5791 this.object = object;
5792 this.property = property;
5793 }
5794 return ComputedMemberExpression;
5795 }());
5796 exports.ComputedMemberExpression = ComputedMemberExpression;
5797 var ConditionalExpression = (function () {
5798 function ConditionalExpression(test, consequent, alternate) {
5799 this.type = syntax_1.Syntax.ConditionalExpression;
5800 this.test = test;
5801 this.consequent = consequent;
5802 this.alternate = alternate;
5803 }
5804 return ConditionalExpression;
5805 }());
5806 exports.ConditionalExpression = ConditionalExpression;
5807 var ContinueStatement = (function () {
5808 function ContinueStatement(label) {
5809 this.type = syntax_1.Syntax.ContinueStatement;
5810 this.label = label;
5811 }
5812 return ContinueStatement;
5813 }());
5814 exports.ContinueStatement = ContinueStatement;
5815 var DebuggerStatement = (function () {
5816 function DebuggerStatement() {
5817 this.type = syntax_1.Syntax.DebuggerStatement;
5818 }
5819 return DebuggerStatement;
5820 }());
5821 exports.DebuggerStatement = DebuggerStatement;
5822 var Directive = (function () {
5823 function Directive(expression, directive) {
5824 this.type = syntax_1.Syntax.ExpressionStatement;
5825 this.expression = expression;
5826 this.directive = directive;
5827 }
5828 return Directive;
5829 }());
5830 exports.Directive = Directive;
5831 var DoWhileStatement = (function () {
5832 function DoWhileStatement(body, test) {
5833 this.type = syntax_1.Syntax.DoWhileStatement;
5834 this.body = body;
5835 this.test = test;
5836 }
5837 return DoWhileStatement;
5838 }());
5839 exports.DoWhileStatement = DoWhileStatement;
5840 var EmptyStatement = (function () {
5841 function EmptyStatement() {
5842 this.type = syntax_1.Syntax.EmptyStatement;
5843 }
5844 return EmptyStatement;
5845 }());
5846 exports.EmptyStatement = EmptyStatement;
5847 var ExportAllDeclaration = (function () {
5848 function ExportAllDeclaration(source) {
5849 this.type = syntax_1.Syntax.ExportAllDeclaration;
5850 this.source = source;
5851 }
5852 return ExportAllDeclaration;
5853 }());
5854 exports.ExportAllDeclaration = ExportAllDeclaration;
5855 var ExportDefaultDeclaration = (function () {
5856 function ExportDefaultDeclaration(declaration) {
5857 this.type = syntax_1.Syntax.ExportDefaultDeclaration;
5858 this.declaration = declaration;
5859 }
5860 return ExportDefaultDeclaration;
5861 }());
5862 exports.ExportDefaultDeclaration = ExportDefaultDeclaration;
5863 var ExportNamedDeclaration = (function () {
5864 function ExportNamedDeclaration(declaration, specifiers, source) {
5865 this.type = syntax_1.Syntax.ExportNamedDeclaration;
5866 this.declaration = declaration;
5867 this.specifiers = specifiers;
5868 this.source = source;
5869 }
5870 return ExportNamedDeclaration;
5871 }());
5872 exports.ExportNamedDeclaration = ExportNamedDeclaration;
5873 var ExportSpecifier = (function () {
5874 function ExportSpecifier(local, exported) {
5875 this.type = syntax_1.Syntax.ExportSpecifier;
5876 this.exported = exported;
5877 this.local = local;
5878 }
5879 return ExportSpecifier;
5880 }());
5881 exports.ExportSpecifier = ExportSpecifier;
5882 var ExpressionStatement = (function () {
5883 function ExpressionStatement(expression) {
5884 this.type = syntax_1.Syntax.ExpressionStatement;
5885 this.expression = expression;
5886 }
5887 return ExpressionStatement;
5888 }());
5889 exports.ExpressionStatement = ExpressionStatement;
5890 var ForInStatement = (function () {
5891 function ForInStatement(left, right, body) {
5892 this.type = syntax_1.Syntax.ForInStatement;
5893 this.left = left;
5894 this.right = right;
5895 this.body = body;
5896 this.each = false;
5897 }
5898 return ForInStatement;
5899 }());
5900 exports.ForInStatement = ForInStatement;
5901 var ForOfStatement = (function () {
5902 function ForOfStatement(left, right, body) {
5903 this.type = syntax_1.Syntax.ForOfStatement;
5904 this.left = left;
5905 this.right = right;
5906 this.body = body;
5907 }
5908 return ForOfStatement;
5909 }());
5910 exports.ForOfStatement = ForOfStatement;
5911 var ForStatement = (function () {
5912 function ForStatement(init, test, update, body) {
5913 this.type = syntax_1.Syntax.ForStatement;
5914 this.init = init;
5915 this.test = test;
5916 this.update = update;
5917 this.body = body;
5918 }
5919 return ForStatement;
5920 }());
5921 exports.ForStatement = ForStatement;
5922 var FunctionDeclaration = (function () {
5923 function FunctionDeclaration(id, params, body, generator) {
5924 this.type = syntax_1.Syntax.FunctionDeclaration;
5925 this.id = id;
5926 this.params = params;
5927 this.body = body;
5928 this.generator = generator;
5929 this.expression = false;
5930 this.async = false;
5931 }
5932 return FunctionDeclaration;
5933 }());
5934 exports.FunctionDeclaration = FunctionDeclaration;
5935 var FunctionExpression = (function () {
5936 function FunctionExpression(id, params, body, generator) {
5937 this.type = syntax_1.Syntax.FunctionExpression;
5938 this.id = id;
5939 this.params = params;
5940 this.body = body;
5941 this.generator = generator;
5942 this.expression = false;
5943 this.async = false;
5944 }
5945 return FunctionExpression;
5946 }());
5947 exports.FunctionExpression = FunctionExpression;
5948 var Identifier = (function () {
5949 function Identifier(name) {
5950 this.type = syntax_1.Syntax.Identifier;
5951 this.name = name;
5952 }
5953 return Identifier;
5954 }());
5955 exports.Identifier = Identifier;
5956 var IfStatement = (function () {
5957 function IfStatement(test, consequent, alternate) {
5958 this.type = syntax_1.Syntax.IfStatement;
5959 this.test = test;
5960 this.consequent = consequent;
5961 this.alternate = alternate;
5962 }
5963 return IfStatement;
5964 }());
5965 exports.IfStatement = IfStatement;
5966 var ImportDeclaration = (function () {
5967 function ImportDeclaration(specifiers, source) {
5968 this.type = syntax_1.Syntax.ImportDeclaration;
5969 this.specifiers = specifiers;
5970 this.source = source;
5971 }
5972 return ImportDeclaration;
5973 }());
5974 exports.ImportDeclaration = ImportDeclaration;
5975 var ImportDefaultSpecifier = (function () {
5976 function ImportDefaultSpecifier(local) {
5977 this.type = syntax_1.Syntax.ImportDefaultSpecifier;
5978 this.local = local;
5979 }
5980 return ImportDefaultSpecifier;
5981 }());
5982 exports.ImportDefaultSpecifier = ImportDefaultSpecifier;
5983 var ImportNamespaceSpecifier = (function () {
5984 function ImportNamespaceSpecifier(local) {
5985 this.type = syntax_1.Syntax.ImportNamespaceSpecifier;
5986 this.local = local;
5987 }
5988 return ImportNamespaceSpecifier;
5989 }());
5990 exports.ImportNamespaceSpecifier = ImportNamespaceSpecifier;
5991 var ImportSpecifier = (function () {
5992 function ImportSpecifier(local, imported) {
5993 this.type = syntax_1.Syntax.ImportSpecifier;
5994 this.local = local;
5995 this.imported = imported;
5996 }
5997 return ImportSpecifier;
5998 }());
5999 exports.ImportSpecifier = ImportSpecifier;
6000 var LabeledStatement = (function () {
6001 function LabeledStatement(label, body) {
6002 this.type = syntax_1.Syntax.LabeledStatement;
6003 this.label = label;
6004 this.body = body;
6005 }
6006 return LabeledStatement;
6007 }());
6008 exports.LabeledStatement = LabeledStatement;
6009 var Literal = (function () {
6010 function Literal(value, raw) {
6011 this.type = syntax_1.Syntax.Literal;
6012 this.value = value;
6013 this.raw = raw;
6014 }
6015 return Literal;
6016 }());
6017 exports.Literal = Literal;
6018 var MetaProperty = (function () {
6019 function MetaProperty(meta, property) {
6020 this.type = syntax_1.Syntax.MetaProperty;
6021 this.meta = meta;
6022 this.property = property;
6023 }
6024 return MetaProperty;
6025 }());
6026 exports.MetaProperty = MetaProperty;
6027 var MethodDefinition = (function () {
6028 function MethodDefinition(key, computed, value, kind, isStatic) {
6029 this.type = syntax_1.Syntax.MethodDefinition;
6030 this.key = key;
6031 this.computed = computed;
6032 this.value = value;
6033 this.kind = kind;
6034 this.static = isStatic;
6035 }
6036 return MethodDefinition;
6037 }());
6038 exports.MethodDefinition = MethodDefinition;
6039 var Module = (function () {
6040 function Module(body) {
6041 this.type = syntax_1.Syntax.Program;
6042 this.body = body;
6043 this.sourceType = 'module';
6044 }
6045 return Module;
6046 }());
6047 exports.Module = Module;
6048 var NewExpression = (function () {
6049 function NewExpression(callee, args) {
6050 this.type = syntax_1.Syntax.NewExpression;
6051 this.callee = callee;
6052 this.arguments = args;
6053 }
6054 return NewExpression;
6055 }());
6056 exports.NewExpression = NewExpression;
6057 var ObjectExpression = (function () {
6058 function ObjectExpression(properties) {
6059 this.type = syntax_1.Syntax.ObjectExpression;
6060 this.properties = properties;
6061 }
6062 return ObjectExpression;
6063 }());
6064 exports.ObjectExpression = ObjectExpression;
6065 var ObjectPattern = (function () {
6066 function ObjectPattern(properties) {
6067 this.type = syntax_1.Syntax.ObjectPattern;
6068 this.properties = properties;
6069 }
6070 return ObjectPattern;
6071 }());
6072 exports.ObjectPattern = ObjectPattern;
6073 var Property = (function () {
6074 function Property(kind, key, computed, value, method, shorthand) {
6075 this.type = syntax_1.Syntax.Property;
6076 this.key = key;
6077 this.computed = computed;
6078 this.value = value;
6079 this.kind = kind;
6080 this.method = method;
6081 this.shorthand = shorthand;
6082 }
6083 return Property;
6084 }());
6085 exports.Property = Property;
6086 var RegexLiteral = (function () {
6087 function RegexLiteral(value, raw, pattern, flags) {
6088 this.type = syntax_1.Syntax.Literal;
6089 this.value = value;
6090 this.raw = raw;
6091 this.regex = { pattern: pattern, flags: flags };
6092 }
6093 return RegexLiteral;
6094 }());
6095 exports.RegexLiteral = RegexLiteral;
6096 var RestElement = (function () {
6097 function RestElement(argument) {
6098 this.type = syntax_1.Syntax.RestElement;
6099 this.argument = argument;
6100 }
6101 return RestElement;
6102 }());
6103 exports.RestElement = RestElement;
6104 var ReturnStatement = (function () {
6105 function ReturnStatement(argument) {
6106 this.type = syntax_1.Syntax.ReturnStatement;
6107 this.argument = argument;
6108 }
6109 return ReturnStatement;
6110 }());
6111 exports.ReturnStatement = ReturnStatement;
6112 var Script = (function () {
6113 function Script(body) {
6114 this.type = syntax_1.Syntax.Program;
6115 this.body = body;
6116 this.sourceType = 'script';
6117 }
6118 return Script;
6119 }());
6120 exports.Script = Script;
6121 var SequenceExpression = (function () {
6122 function SequenceExpression(expressions) {
6123 this.type = syntax_1.Syntax.SequenceExpression;
6124 this.expressions = expressions;
6125 }
6126 return SequenceExpression;
6127 }());
6128 exports.SequenceExpression = SequenceExpression;
6129 var SpreadElement = (function () {
6130 function SpreadElement(argument) {
6131 this.type = syntax_1.Syntax.SpreadElement;
6132 this.argument = argument;
6133 }
6134 return SpreadElement;
6135 }());
6136 exports.SpreadElement = SpreadElement;
6137 var StaticMemberExpression = (function () {
6138 function StaticMemberExpression(object, property) {
6139 this.type = syntax_1.Syntax.MemberExpression;
6140 this.computed = false;
6141 this.object = object;
6142 this.property = property;
6143 }
6144 return StaticMemberExpression;
6145 }());
6146 exports.StaticMemberExpression = StaticMemberExpression;
6147 var Super = (function () {
6148 function Super() {
6149 this.type = syntax_1.Syntax.Super;
6150 }
6151 return Super;
6152 }());
6153 exports.Super = Super;
6154 var SwitchCase = (function () {
6155 function SwitchCase(test, consequent) {
6156 this.type = syntax_1.Syntax.SwitchCase;
6157 this.test = test;
6158 this.consequent = consequent;
6159 }
6160 return SwitchCase;
6161 }());
6162 exports.SwitchCase = SwitchCase;
6163 var SwitchStatement = (function () {
6164 function SwitchStatement(discriminant, cases) {
6165 this.type = syntax_1.Syntax.SwitchStatement;
6166 this.discriminant = discriminant;
6167 this.cases = cases;
6168 }
6169 return SwitchStatement;
6170 }());
6171 exports.SwitchStatement = SwitchStatement;
6172 var TaggedTemplateExpression = (function () {
6173 function TaggedTemplateExpression(tag, quasi) {
6174 this.type = syntax_1.Syntax.TaggedTemplateExpression;
6175 this.tag = tag;
6176 this.quasi = quasi;
6177 }
6178 return TaggedTemplateExpression;
6179 }());
6180 exports.TaggedTemplateExpression = TaggedTemplateExpression;
6181 var TemplateElement = (function () {
6182 function TemplateElement(value, tail) {
6183 this.type = syntax_1.Syntax.TemplateElement;
6184 this.value = value;
6185 this.tail = tail;
6186 }
6187 return TemplateElement;
6188 }());
6189 exports.TemplateElement = TemplateElement;
6190 var TemplateLiteral = (function () {
6191 function TemplateLiteral(quasis, expressions) {
6192 this.type = syntax_1.Syntax.TemplateLiteral;
6193 this.quasis = quasis;
6194 this.expressions = expressions;
6195 }
6196 return TemplateLiteral;
6197 }());
6198 exports.TemplateLiteral = TemplateLiteral;
6199 var ThisExpression = (function () {
6200 function ThisExpression() {
6201 this.type = syntax_1.Syntax.ThisExpression;
6202 }
6203 return ThisExpression;
6204 }());
6205 exports.ThisExpression = ThisExpression;
6206 var ThrowStatement = (function () {
6207 function ThrowStatement(argument) {
6208 this.type = syntax_1.Syntax.ThrowStatement;
6209 this.argument = argument;
6210 }
6211 return ThrowStatement;
6212 }());
6213 exports.ThrowStatement = ThrowStatement;
6214 var TryStatement = (function () {
6215 function TryStatement(block, handler, finalizer) {
6216 this.type = syntax_1.Syntax.TryStatement;
6217 this.block = block;
6218 this.handler = handler;
6219 this.finalizer = finalizer;
6220 }
6221 return TryStatement;
6222 }());
6223 exports.TryStatement = TryStatement;
6224 var UnaryExpression = (function () {
6225 function UnaryExpression(operator, argument) {
6226 this.type = syntax_1.Syntax.UnaryExpression;
6227 this.operator = operator;
6228 this.argument = argument;
6229 this.prefix = true;
6230 }
6231 return UnaryExpression;
6232 }());
6233 exports.UnaryExpression = UnaryExpression;
6234 var UpdateExpression = (function () {
6235 function UpdateExpression(operator, argument, prefix) {
6236 this.type = syntax_1.Syntax.UpdateExpression;
6237 this.operator = operator;
6238 this.argument = argument;
6239 this.prefix = prefix;
6240 }
6241 return UpdateExpression;
6242 }());
6243 exports.UpdateExpression = UpdateExpression;
6244 var VariableDeclaration = (function () {
6245 function VariableDeclaration(declarations, kind) {
6246 this.type = syntax_1.Syntax.VariableDeclaration;
6247 this.declarations = declarations;
6248 this.kind = kind;
6249 }
6250 return VariableDeclaration;
6251 }());
6252 exports.VariableDeclaration = VariableDeclaration;
6253 var VariableDeclarator = (function () {
6254 function VariableDeclarator(id, init) {
6255 this.type = syntax_1.Syntax.VariableDeclarator;
6256 this.id = id;
6257 this.init = init;
6258 }
6259 return VariableDeclarator;
6260 }());
6261 exports.VariableDeclarator = VariableDeclarator;
6262 var WhileStatement = (function () {
6263 function WhileStatement(test, body) {
6264 this.type = syntax_1.Syntax.WhileStatement;
6265 this.test = test;
6266 this.body = body;
6267 }
6268 return WhileStatement;
6269 }());
6270 exports.WhileStatement = WhileStatement;
6271 var WithStatement = (function () {
6272 function WithStatement(object, body) {
6273 this.type = syntax_1.Syntax.WithStatement;
6274 this.object = object;
6275 this.body = body;
6276 }
6277 return WithStatement;
6278 }());
6279 exports.WithStatement = WithStatement;
6280 var YieldExpression = (function () {
6281 function YieldExpression(argument, delegate) {
6282 this.type = syntax_1.Syntax.YieldExpression;
6283 this.argument = argument;
6284 this.delegate = delegate;
6285 }
6286 return YieldExpression;
6287 }());
6288 exports.YieldExpression = YieldExpression;
6289
6290
6291/***/ },
6292/* 8 */
6293/***/ function(module, exports, __webpack_require__) {
6294
6295 "use strict";
6296 Object.defineProperty(exports, "__esModule", { value: true });
6297 var assert_1 = __webpack_require__(9);
6298 var error_handler_1 = __webpack_require__(10);
6299 var messages_1 = __webpack_require__(11);
6300 var Node = __webpack_require__(7);
6301 var scanner_1 = __webpack_require__(12);
6302 var syntax_1 = __webpack_require__(2);
6303 var token_1 = __webpack_require__(13);
6304 var ArrowParameterPlaceHolder = 'ArrowParameterPlaceHolder';
6305 var Parser = (function () {
6306 function Parser(code, options, delegate) {
6307 if (options === void 0) { options = {}; }
6308 this.config = {
6309 range: (typeof options.range === 'boolean') && options.range,
6310 loc: (typeof options.loc === 'boolean') && options.loc,
6311 source: null,
6312 tokens: (typeof options.tokens === 'boolean') && options.tokens,
6313 comment: (typeof options.comment === 'boolean') && options.comment,
6314 tolerant: (typeof options.tolerant === 'boolean') && options.tolerant
6315 };
6316 if (this.config.loc && options.source && options.source !== null) {
6317 this.config.source = String(options.source);
6318 }
6319 this.delegate = delegate;
6320 this.errorHandler = new error_handler_1.ErrorHandler();
6321 this.errorHandler.tolerant = this.config.tolerant;
6322 this.scanner = new scanner_1.Scanner(code, this.errorHandler);
6323 this.scanner.trackComment = this.config.comment;
6324 this.operatorPrecedence = {
6325 ')': 0,
6326 ';': 0,
6327 ',': 0,
6328 '=': 0,
6329 ']': 0,
6330 '||': 1,
6331 '&&': 2,
6332 '|': 3,
6333 '^': 4,
6334 '&': 5,
6335 '==': 6,
6336 '!=': 6,
6337 '===': 6,
6338 '!==': 6,
6339 '<': 7,
6340 '>': 7,
6341 '<=': 7,
6342 '>=': 7,
6343 '<<': 8,
6344 '>>': 8,
6345 '>>>': 8,
6346 '+': 9,
6347 '-': 9,
6348 '*': 11,
6349 '/': 11,
6350 '%': 11
6351 };
6352 this.lookahead = {
6353 type: 2 /* EOF */,
6354 value: '',
6355 lineNumber: this.scanner.lineNumber,
6356 lineStart: 0,
6357 start: 0,
6358 end: 0
6359 };
6360 this.hasLineTerminator = false;
6361 this.context = {
6362 isModule: false,
6363 await: false,
6364 allowIn: true,
6365 allowStrictDirective: true,
6366 allowYield: true,
6367 firstCoverInitializedNameError: null,
6368 isAssignmentTarget: false,
6369 isBindingElement: false,
6370 inFunctionBody: false,
6371 inIteration: false,
6372 inSwitch: false,
6373 labelSet: {},
6374 strict: false
6375 };
6376 this.tokens = [];
6377 this.startMarker = {
6378 index: 0,
6379 line: this.scanner.lineNumber,
6380 column: 0
6381 };
6382 this.lastMarker = {
6383 index: 0,
6384 line: this.scanner.lineNumber,
6385 column: 0
6386 };
6387 this.nextToken();
6388 this.lastMarker = {
6389 index: this.scanner.index,
6390 line: this.scanner.lineNumber,
6391 column: this.scanner.index - this.scanner.lineStart
6392 };
6393 }
6394 Parser.prototype.throwError = function (messageFormat) {
6395 var values = [];
6396 for (var _i = 1; _i < arguments.length; _i++) {
6397 values[_i - 1] = arguments[_i];
6398 }
6399 var args = Array.prototype.slice.call(arguments, 1);
6400 var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) {
6401 assert_1.assert(idx < args.length, 'Message reference must be in range');
6402 return args[idx];
6403 });
6404 var index = this.lastMarker.index;
6405 var line = this.lastMarker.line;
6406 var column = this.lastMarker.column + 1;
6407 throw this.errorHandler.createError(index, line, column, msg);
6408 };
6409 Parser.prototype.tolerateError = function (messageFormat) {
6410 var values = [];
6411 for (var _i = 1; _i < arguments.length; _i++) {
6412 values[_i - 1] = arguments[_i];
6413 }
6414 var args = Array.prototype.slice.call(arguments, 1);
6415 var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) {
6416 assert_1.assert(idx < args.length, 'Message reference must be in range');
6417 return args[idx];
6418 });
6419 var index = this.lastMarker.index;
6420 var line = this.scanner.lineNumber;
6421 var column = this.lastMarker.column + 1;
6422 this.errorHandler.tolerateError(index, line, column, msg);
6423 };
6424 // Throw an exception because of the token.
6425 Parser.prototype.unexpectedTokenError = function (token, message) {
6426 var msg = message || messages_1.Messages.UnexpectedToken;
6427 var value;
6428 if (token) {
6429 if (!message) {
6430 msg = (token.type === 2 /* EOF */) ? messages_1.Messages.UnexpectedEOS :
6431 (token.type === 3 /* Identifier */) ? messages_1.Messages.UnexpectedIdentifier :
6432 (token.type === 6 /* NumericLiteral */) ? messages_1.Messages.UnexpectedNumber :
6433 (token.type === 8 /* StringLiteral */) ? messages_1.Messages.UnexpectedString :
6434 (token.type === 10 /* Template */) ? messages_1.Messages.UnexpectedTemplate :
6435 messages_1.Messages.UnexpectedToken;
6436 if (token.type === 4 /* Keyword */) {
6437 if (this.scanner.isFutureReservedWord(token.value)) {
6438 msg = messages_1.Messages.UnexpectedReserved;
6439 }
6440 else if (this.context.strict && this.scanner.isStrictModeReservedWord(token.value)) {
6441 msg = messages_1.Messages.StrictReservedWord;
6442 }
6443 }
6444 }
6445 value = token.value;
6446 }
6447 else {
6448 value = 'ILLEGAL';
6449 }
6450 msg = msg.replace('%0', value);
6451 if (token && typeof token.lineNumber === 'number') {
6452 var index = token.start;
6453 var line = token.lineNumber;
6454 var lastMarkerLineStart = this.lastMarker.index - this.lastMarker.column;
6455 var column = token.start - lastMarkerLineStart + 1;
6456 return this.errorHandler.createError(index, line, column, msg);
6457 }
6458 else {
6459 var index = this.lastMarker.index;
6460 var line = this.lastMarker.line;
6461 var column = this.lastMarker.column + 1;
6462 return this.errorHandler.createError(index, line, column, msg);
6463 }
6464 };
6465 Parser.prototype.throwUnexpectedToken = function (token, message) {
6466 throw this.unexpectedTokenError(token, message);
6467 };
6468 Parser.prototype.tolerateUnexpectedToken = function (token, message) {
6469 this.errorHandler.tolerate(this.unexpectedTokenError(token, message));
6470 };
6471 Parser.prototype.collectComments = function () {
6472 if (!this.config.comment) {
6473 this.scanner.scanComments();
6474 }
6475 else {
6476 var comments = this.scanner.scanComments();
6477 if (comments.length > 0 && this.delegate) {
6478 for (var i = 0; i < comments.length; ++i) {
6479 var e = comments[i];
6480 var node = void 0;
6481 node = {
6482 type: e.multiLine ? 'BlockComment' : 'LineComment',
6483 value: this.scanner.source.slice(e.slice[0], e.slice[1])
6484 };
6485 if (this.config.range) {
6486 node.range = e.range;
6487 }
6488 if (this.config.loc) {
6489 node.loc = e.loc;
6490 }
6491 var metadata = {
6492 start: {
6493 line: e.loc.start.line,
6494 column: e.loc.start.column,
6495 offset: e.range[0]
6496 },
6497 end: {
6498 line: e.loc.end.line,
6499 column: e.loc.end.column,
6500 offset: e.range[1]
6501 }
6502 };
6503 this.delegate(node, metadata);
6504 }
6505 }
6506 }
6507 };
6508 // From internal representation to an external structure
6509 Parser.prototype.getTokenRaw = function (token) {
6510 return this.scanner.source.slice(token.start, token.end);
6511 };
6512 Parser.prototype.convertToken = function (token) {
6513 var t = {
6514 type: token_1.TokenName[token.type],
6515 value: this.getTokenRaw(token)
6516 };
6517 if (this.config.range) {
6518 t.range = [token.start, token.end];
6519 }
6520 if (this.config.loc) {
6521 t.loc = {
6522 start: {
6523 line: this.startMarker.line,
6524 column: this.startMarker.column
6525 },
6526 end: {
6527 line: this.scanner.lineNumber,
6528 column: this.scanner.index - this.scanner.lineStart
6529 }
6530 };
6531 }
6532 if (token.type === 9 /* RegularExpression */) {
6533 var pattern = token.pattern;
6534 var flags = token.flags;
6535 t.regex = { pattern: pattern, flags: flags };
6536 }
6537 return t;
6538 };
6539 Parser.prototype.nextToken = function () {
6540 var token = this.lookahead;
6541 this.lastMarker.index = this.scanner.index;
6542 this.lastMarker.line = this.scanner.lineNumber;
6543 this.lastMarker.column = this.scanner.index - this.scanner.lineStart;
6544 this.collectComments();
6545 if (this.scanner.index !== this.startMarker.index) {
6546 this.startMarker.index = this.scanner.index;
6547 this.startMarker.line = this.scanner.lineNumber;
6548 this.startMarker.column = this.scanner.index - this.scanner.lineStart;
6549 }
6550 var next = this.scanner.lex();
6551 this.hasLineTerminator = (token.lineNumber !== next.lineNumber);
6552 if (next && this.context.strict && next.type === 3 /* Identifier */) {
6553 if (this.scanner.isStrictModeReservedWord(next.value)) {
6554 next.type = 4 /* Keyword */;
6555 }
6556 }
6557 this.lookahead = next;
6558 if (this.config.tokens && next.type !== 2 /* EOF */) {
6559 this.tokens.push(this.convertToken(next));
6560 }
6561 return token;
6562 };
6563 Parser.prototype.nextRegexToken = function () {
6564 this.collectComments();
6565 var token = this.scanner.scanRegExp();
6566 if (this.config.tokens) {
6567 // Pop the previous token, '/' or '/='
6568 // This is added from the lookahead token.
6569 this.tokens.pop();
6570 this.tokens.push(this.convertToken(token));
6571 }
6572 // Prime the next lookahead.
6573 this.lookahead = token;
6574 this.nextToken();
6575 return token;
6576 };
6577 Parser.prototype.createNode = function () {
6578 return {
6579 index: this.startMarker.index,
6580 line: this.startMarker.line,
6581 column: this.startMarker.column
6582 };
6583 };
6584 Parser.prototype.startNode = function (token) {
6585 return {
6586 index: token.start,
6587 line: token.lineNumber,
6588 column: token.start - token.lineStart
6589 };
6590 };
6591 Parser.prototype.finalize = function (marker, node) {
6592 if (this.config.range) {
6593 node.range = [marker.index, this.lastMarker.index];
6594 }
6595 if (this.config.loc) {
6596 node.loc = {
6597 start: {
6598 line: marker.line,
6599 column: marker.column,
6600 },
6601 end: {
6602 line: this.lastMarker.line,
6603 column: this.lastMarker.column
6604 }
6605 };
6606 if (this.config.source) {
6607 node.loc.source = this.config.source;
6608 }
6609 }
6610 if (this.delegate) {
6611 var metadata = {
6612 start: {
6613 line: marker.line,
6614 column: marker.column,
6615 offset: marker.index
6616 },
6617 end: {
6618 line: this.lastMarker.line,
6619 column: this.lastMarker.column,
6620 offset: this.lastMarker.index
6621 }
6622 };
6623 this.delegate(node, metadata);
6624 }
6625 return node;
6626 };
6627 // Expect the next token to match the specified punctuator.
6628 // If not, an exception will be thrown.
6629 Parser.prototype.expect = function (value) {
6630 var token = this.nextToken();
6631 if (token.type !== 7 /* Punctuator */ || token.value !== value) {
6632 this.throwUnexpectedToken(token);
6633 }
6634 };
6635 // Quietly expect a comma when in tolerant mode, otherwise delegates to expect().
6636 Parser.prototype.expectCommaSeparator = function () {
6637 if (this.config.tolerant) {
6638 var token = this.lookahead;
6639 if (token.type === 7 /* Punctuator */ && token.value === ',') {
6640 this.nextToken();
6641 }
6642 else if (token.type === 7 /* Punctuator */ && token.value === ';') {
6643 this.nextToken();
6644 this.tolerateUnexpectedToken(token);
6645 }
6646 else {
6647 this.tolerateUnexpectedToken(token, messages_1.Messages.UnexpectedToken);
6648 }
6649 }
6650 else {
6651 this.expect(',');
6652 }
6653 };
6654 // Expect the next token to match the specified keyword.
6655 // If not, an exception will be thrown.
6656 Parser.prototype.expectKeyword = function (keyword) {
6657 var token = this.nextToken();
6658 if (token.type !== 4 /* Keyword */ || token.value !== keyword) {
6659 this.throwUnexpectedToken(token);
6660 }
6661 };
6662 // Return true if the next token matches the specified punctuator.
6663 Parser.prototype.match = function (value) {
6664 return this.lookahead.type === 7 /* Punctuator */ && this.lookahead.value === value;
6665 };
6666 // Return true if the next token matches the specified keyword
6667 Parser.prototype.matchKeyword = function (keyword) {
6668 return this.lookahead.type === 4 /* Keyword */ && this.lookahead.value === keyword;
6669 };
6670 // Return true if the next token matches the specified contextual keyword
6671 // (where an identifier is sometimes a keyword depending on the context)
6672 Parser.prototype.matchContextualKeyword = function (keyword) {
6673 return this.lookahead.type === 3 /* Identifier */ && this.lookahead.value === keyword;
6674 };
6675 // Return true if the next token is an assignment operator
6676 Parser.prototype.matchAssign = function () {
6677 if (this.lookahead.type !== 7 /* Punctuator */) {
6678 return false;
6679 }
6680 var op = this.lookahead.value;
6681 return op === '=' ||
6682 op === '*=' ||
6683 op === '**=' ||
6684 op === '/=' ||
6685 op === '%=' ||
6686 op === '+=' ||
6687 op === '-=' ||
6688 op === '<<=' ||
6689 op === '>>=' ||
6690 op === '>>>=' ||
6691 op === '&=' ||
6692 op === '^=' ||
6693 op === '|=';
6694 };
6695 // Cover grammar support.
6696 //
6697 // When an assignment expression position starts with an left parenthesis, the determination of the type
6698 // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
6699 // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
6700 //
6701 // There are three productions that can be parsed in a parentheses pair that needs to be determined
6702 // after the outermost pair is closed. They are:
6703 //
6704 // 1. AssignmentExpression
6705 // 2. BindingElements
6706 // 3. AssignmentTargets
6707 //
6708 // In order to avoid exponential backtracking, we use two flags to denote if the production can be
6709 // binding element or assignment target.
6710 //
6711 // The three productions have the relationship:
6712 //
6713 // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression
6714 //
6715 // with a single exception that CoverInitializedName when used directly in an Expression, generates
6716 // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
6717 // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
6718 //
6719 // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
6720 // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
6721 // the CoverInitializedName check is conducted.
6722 //
6723 // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
6724 // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
6725 // pattern. The CoverInitializedName check is deferred.
6726 Parser.prototype.isolateCoverGrammar = function (parseFunction) {
6727 var previousIsBindingElement = this.context.isBindingElement;
6728 var previousIsAssignmentTarget = this.context.isAssignmentTarget;
6729 var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError;
6730 this.context.isBindingElement = true;
6731 this.context.isAssignmentTarget = true;
6732 this.context.firstCoverInitializedNameError = null;
6733 var result = parseFunction.call(this);
6734 if (this.context.firstCoverInitializedNameError !== null) {
6735 this.throwUnexpectedToken(this.context.firstCoverInitializedNameError);
6736 }
6737 this.context.isBindingElement = previousIsBindingElement;
6738 this.context.isAssignmentTarget = previousIsAssignmentTarget;
6739 this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError;
6740 return result;
6741 };
6742 Parser.prototype.inheritCoverGrammar = function (parseFunction) {
6743 var previousIsBindingElement = this.context.isBindingElement;
6744 var previousIsAssignmentTarget = this.context.isAssignmentTarget;
6745 var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError;
6746 this.context.isBindingElement = true;
6747 this.context.isAssignmentTarget = true;
6748 this.context.firstCoverInitializedNameError = null;
6749 var result = parseFunction.call(this);
6750 this.context.isBindingElement = this.context.isBindingElement && previousIsBindingElement;
6751 this.context.isAssignmentTarget = this.context.isAssignmentTarget && previousIsAssignmentTarget;
6752 this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.context.firstCoverInitializedNameError;
6753 return result;
6754 };
6755 Parser.prototype.consumeSemicolon = function () {
6756 if (this.match(';')) {
6757 this.nextToken();
6758 }
6759 else if (!this.hasLineTerminator) {
6760 if (this.lookahead.type !== 2 /* EOF */ && !this.match('}')) {
6761 this.throwUnexpectedToken(this.lookahead);
6762 }
6763 this.lastMarker.index = this.startMarker.index;
6764 this.lastMarker.line = this.startMarker.line;
6765 this.lastMarker.column = this.startMarker.column;
6766 }
6767 };
6768 // https://tc39.github.io/ecma262/#sec-primary-expression
6769 Parser.prototype.parsePrimaryExpression = function () {
6770 var node = this.createNode();
6771 var expr;
6772 var token, raw;
6773 switch (this.lookahead.type) {
6774 case 3 /* Identifier */:
6775 if ((this.context.isModule || this.context.await) && this.lookahead.value === 'await') {
6776 this.tolerateUnexpectedToken(this.lookahead);
6777 }
6778 expr = this.matchAsyncFunction() ? this.parseFunctionExpression() : this.finalize(node, new Node.Identifier(this.nextToken().value));
6779 break;
6780 case 6 /* NumericLiteral */:
6781 case 8 /* StringLiteral */:
6782 if (this.context.strict && this.lookahead.octal) {
6783 this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.StrictOctalLiteral);
6784 }
6785 this.context.isAssignmentTarget = false;
6786 this.context.isBindingElement = false;
6787 token = this.nextToken();
6788 raw = this.getTokenRaw(token);
6789 expr = this.finalize(node, new Node.Literal(token.value, raw));
6790 break;
6791 case 1 /* BooleanLiteral */:
6792 this.context.isAssignmentTarget = false;
6793 this.context.isBindingElement = false;
6794 token = this.nextToken();
6795 raw = this.getTokenRaw(token);
6796 expr = this.finalize(node, new Node.Literal(token.value === 'true', raw));
6797 break;
6798 case 5 /* NullLiteral */:
6799 this.context.isAssignmentTarget = false;
6800 this.context.isBindingElement = false;
6801 token = this.nextToken();
6802 raw = this.getTokenRaw(token);
6803 expr = this.finalize(node, new Node.Literal(null, raw));
6804 break;
6805 case 10 /* Template */:
6806 expr = this.parseTemplateLiteral();
6807 break;
6808 case 7 /* Punctuator */:
6809 switch (this.lookahead.value) {
6810 case '(':
6811 this.context.isBindingElement = false;
6812 expr = this.inheritCoverGrammar(this.parseGroupExpression);
6813 break;
6814 case '[':
6815 expr = this.inheritCoverGrammar(this.parseArrayInitializer);
6816 break;
6817 case '{':
6818 expr = this.inheritCoverGrammar(this.parseObjectInitializer);
6819 break;
6820 case '/':
6821 case '/=':
6822 this.context.isAssignmentTarget = false;
6823 this.context.isBindingElement = false;
6824 this.scanner.index = this.startMarker.index;
6825 token = this.nextRegexToken();
6826 raw = this.getTokenRaw(token);
6827 expr = this.finalize(node, new Node.RegexLiteral(token.regex, raw, token.pattern, token.flags));
6828 break;
6829 default:
6830 expr = this.throwUnexpectedToken(this.nextToken());
6831 }
6832 break;
6833 case 4 /* Keyword */:
6834 if (!this.context.strict && this.context.allowYield && this.matchKeyword('yield')) {
6835 expr = this.parseIdentifierName();
6836 }
6837 else if (!this.context.strict && this.matchKeyword('let')) {
6838 expr = this.finalize(node, new Node.Identifier(this.nextToken().value));
6839 }
6840 else {
6841 this.context.isAssignmentTarget = false;
6842 this.context.isBindingElement = false;
6843 if (this.matchKeyword('function')) {
6844 expr = this.parseFunctionExpression();
6845 }
6846 else if (this.matchKeyword('this')) {
6847 this.nextToken();
6848 expr = this.finalize(node, new Node.ThisExpression());
6849 }
6850 else if (this.matchKeyword('class')) {
6851 expr = this.parseClassExpression();
6852 }
6853 else {
6854 expr = this.throwUnexpectedToken(this.nextToken());
6855 }
6856 }
6857 break;
6858 default:
6859 expr = this.throwUnexpectedToken(this.nextToken());
6860 }
6861 return expr;
6862 };
6863 // https://tc39.github.io/ecma262/#sec-array-initializer
6864 Parser.prototype.parseSpreadElement = function () {
6865 var node = this.createNode();
6866 this.expect('...');
6867 var arg = this.inheritCoverGrammar(this.parseAssignmentExpression);
6868 return this.finalize(node, new Node.SpreadElement(arg));
6869 };
6870 Parser.prototype.parseArrayInitializer = function () {
6871 var node = this.createNode();
6872 var elements = [];
6873 this.expect('[');
6874 while (!this.match(']')) {
6875 if (this.match(',')) {
6876 this.nextToken();
6877 elements.push(null);
6878 }
6879 else if (this.match('...')) {
6880 var element = this.parseSpreadElement();
6881 if (!this.match(']')) {
6882 this.context.isAssignmentTarget = false;
6883 this.context.isBindingElement = false;
6884 this.expect(',');
6885 }
6886 elements.push(element);
6887 }
6888 else {
6889 elements.push(this.inheritCoverGrammar(this.parseAssignmentExpression));
6890 if (!this.match(']')) {
6891 this.expect(',');
6892 }
6893 }
6894 }
6895 this.expect(']');
6896 return this.finalize(node, new Node.ArrayExpression(elements));
6897 };
6898 // https://tc39.github.io/ecma262/#sec-object-initializer
6899 Parser.prototype.parsePropertyMethod = function (params) {
6900 this.context.isAssignmentTarget = false;
6901 this.context.isBindingElement = false;
6902 var previousStrict = this.context.strict;
6903 var previousAllowStrictDirective = this.context.allowStrictDirective;
6904 this.context.allowStrictDirective = params.simple;
6905 var body = this.isolateCoverGrammar(this.parseFunctionSourceElements);
6906 if (this.context.strict && params.firstRestricted) {
6907 this.tolerateUnexpectedToken(params.firstRestricted, params.message);
6908 }
6909 if (this.context.strict && params.stricted) {
6910 this.tolerateUnexpectedToken(params.stricted, params.message);
6911 }
6912 this.context.strict = previousStrict;
6913 this.context.allowStrictDirective = previousAllowStrictDirective;
6914 return body;
6915 };
6916 Parser.prototype.parsePropertyMethodFunction = function () {
6917 var isGenerator = false;
6918 var node = this.createNode();
6919 var previousAllowYield = this.context.allowYield;
6920 this.context.allowYield = false;
6921 var params = this.parseFormalParameters();
6922 var method = this.parsePropertyMethod(params);
6923 this.context.allowYield = previousAllowYield;
6924 return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator));
6925 };
6926 Parser.prototype.parsePropertyMethodAsyncFunction = function () {
6927 var node = this.createNode();
6928 var previousAllowYield = this.context.allowYield;
6929 var previousAwait = this.context.await;
6930 this.context.allowYield = false;
6931 this.context.await = true;
6932 var params = this.parseFormalParameters();
6933 var method = this.parsePropertyMethod(params);
6934 this.context.allowYield = previousAllowYield;
6935 this.context.await = previousAwait;
6936 return this.finalize(node, new Node.AsyncFunctionExpression(null, params.params, method));
6937 };
6938 Parser.prototype.parseObjectPropertyKey = function () {
6939 var node = this.createNode();
6940 var token = this.nextToken();
6941 var key;
6942 switch (token.type) {
6943 case 8 /* StringLiteral */:
6944 case 6 /* NumericLiteral */:
6945 if (this.context.strict && token.octal) {
6946 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictOctalLiteral);
6947 }
6948 var raw = this.getTokenRaw(token);
6949 key = this.finalize(node, new Node.Literal(token.value, raw));
6950 break;
6951 case 3 /* Identifier */:
6952 case 1 /* BooleanLiteral */:
6953 case 5 /* NullLiteral */:
6954 case 4 /* Keyword */:
6955 key = this.finalize(node, new Node.Identifier(token.value));
6956 break;
6957 case 7 /* Punctuator */:
6958 if (token.value === '[') {
6959 key = this.isolateCoverGrammar(this.parseAssignmentExpression);
6960 this.expect(']');
6961 }
6962 else {
6963 key = this.throwUnexpectedToken(token);
6964 }
6965 break;
6966 default:
6967 key = this.throwUnexpectedToken(token);
6968 }
6969 return key;
6970 };
6971 Parser.prototype.isPropertyKey = function (key, value) {
6972 return (key.type === syntax_1.Syntax.Identifier && key.name === value) ||
6973 (key.type === syntax_1.Syntax.Literal && key.value === value);
6974 };
6975 Parser.prototype.parseObjectProperty = function (hasProto) {
6976 var node = this.createNode();
6977 var token = this.lookahead;
6978 var kind;
6979 var key = null;
6980 var value = null;
6981 var computed = false;
6982 var method = false;
6983 var shorthand = false;
6984 var isAsync = false;
6985 if (token.type === 3 /* Identifier */) {
6986 var id = token.value;
6987 this.nextToken();
6988 computed = this.match('[');
6989 isAsync = !this.hasLineTerminator && (id === 'async') &&
6990 !this.match(':') && !this.match('(') && !this.match('*');
6991 key = isAsync ? this.parseObjectPropertyKey() : this.finalize(node, new Node.Identifier(id));
6992 }
6993 else if (this.match('*')) {
6994 this.nextToken();
6995 }
6996 else {
6997 computed = this.match('[');
6998 key = this.parseObjectPropertyKey();
6999 }
7000 var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead);
7001 if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'get' && lookaheadPropertyKey) {
7002 kind = 'get';
7003 computed = this.match('[');
7004 key = this.parseObjectPropertyKey();
7005 this.context.allowYield = false;
7006 value = this.parseGetterMethod();
7007 }
7008 else if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'set' && lookaheadPropertyKey) {
7009 kind = 'set';
7010 computed = this.match('[');
7011 key = this.parseObjectPropertyKey();
7012 value = this.parseSetterMethod();
7013 }
7014 else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) {
7015 kind = 'init';
7016 computed = this.match('[');
7017 key = this.parseObjectPropertyKey();
7018 value = this.parseGeneratorMethod();
7019 method = true;
7020 }
7021 else {
7022 if (!key) {
7023 this.throwUnexpectedToken(this.lookahead);
7024 }
7025 kind = 'init';
7026 if (this.match(':') && !isAsync) {
7027 if (!computed && this.isPropertyKey(key, '__proto__')) {
7028 if (hasProto.value) {
7029 this.tolerateError(messages_1.Messages.DuplicateProtoProperty);
7030 }
7031 hasProto.value = true;
7032 }
7033 this.nextToken();
7034 value = this.inheritCoverGrammar(this.parseAssignmentExpression);
7035 }
7036 else if (this.match('(')) {
7037 value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction();
7038 method = true;
7039 }
7040 else if (token.type === 3 /* Identifier */) {
7041 var id = this.finalize(node, new Node.Identifier(token.value));
7042 if (this.match('=')) {
7043 this.context.firstCoverInitializedNameError = this.lookahead;
7044 this.nextToken();
7045 shorthand = true;
7046 var init = this.isolateCoverGrammar(this.parseAssignmentExpression);
7047 value = this.finalize(node, new Node.AssignmentPattern(id, init));
7048 }
7049 else {
7050 shorthand = true;
7051 value = id;
7052 }
7053 }
7054 else {
7055 this.throwUnexpectedToken(this.nextToken());
7056 }
7057 }
7058 return this.finalize(node, new Node.Property(kind, key, computed, value, method, shorthand));
7059 };
7060 Parser.prototype.parseObjectInitializer = function () {
7061 var node = this.createNode();
7062 this.expect('{');
7063 var properties = [];
7064 var hasProto = { value: false };
7065 while (!this.match('}')) {
7066 properties.push(this.parseObjectProperty(hasProto));
7067 if (!this.match('}')) {
7068 this.expectCommaSeparator();
7069 }
7070 }
7071 this.expect('}');
7072 return this.finalize(node, new Node.ObjectExpression(properties));
7073 };
7074 // https://tc39.github.io/ecma262/#sec-template-literals
7075 Parser.prototype.parseTemplateHead = function () {
7076 assert_1.assert(this.lookahead.head, 'Template literal must start with a template head');
7077 var node = this.createNode();
7078 var token = this.nextToken();
7079 var raw = token.value;
7080 var cooked = token.cooked;
7081 return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail));
7082 };
7083 Parser.prototype.parseTemplateElement = function () {
7084 if (this.lookahead.type !== 10 /* Template */) {
7085 this.throwUnexpectedToken();
7086 }
7087 var node = this.createNode();
7088 var token = this.nextToken();
7089 var raw = token.value;
7090 var cooked = token.cooked;
7091 return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail));
7092 };
7093 Parser.prototype.parseTemplateLiteral = function () {
7094 var node = this.createNode();
7095 var expressions = [];
7096 var quasis = [];
7097 var quasi = this.parseTemplateHead();
7098 quasis.push(quasi);
7099 while (!quasi.tail) {
7100 expressions.push(this.parseExpression());
7101 quasi = this.parseTemplateElement();
7102 quasis.push(quasi);
7103 }
7104 return this.finalize(node, new Node.TemplateLiteral(quasis, expressions));
7105 };
7106 // https://tc39.github.io/ecma262/#sec-grouping-operator
7107 Parser.prototype.reinterpretExpressionAsPattern = function (expr) {
7108 switch (expr.type) {
7109 case syntax_1.Syntax.Identifier:
7110 case syntax_1.Syntax.MemberExpression:
7111 case syntax_1.Syntax.RestElement:
7112 case syntax_1.Syntax.AssignmentPattern:
7113 break;
7114 case syntax_1.Syntax.SpreadElement:
7115 expr.type = syntax_1.Syntax.RestElement;
7116 this.reinterpretExpressionAsPattern(expr.argument);
7117 break;
7118 case syntax_1.Syntax.ArrayExpression:
7119 expr.type = syntax_1.Syntax.ArrayPattern;
7120 for (var i = 0; i < expr.elements.length; i++) {
7121 if (expr.elements[i] !== null) {
7122 this.reinterpretExpressionAsPattern(expr.elements[i]);
7123 }
7124 }
7125 break;
7126 case syntax_1.Syntax.ObjectExpression:
7127 expr.type = syntax_1.Syntax.ObjectPattern;
7128 for (var i = 0; i < expr.properties.length; i++) {
7129 this.reinterpretExpressionAsPattern(expr.properties[i].value);
7130 }
7131 break;
7132 case syntax_1.Syntax.AssignmentExpression:
7133 expr.type = syntax_1.Syntax.AssignmentPattern;
7134 delete expr.operator;
7135 this.reinterpretExpressionAsPattern(expr.left);
7136 break;
7137 default:
7138 // Allow other node type for tolerant parsing.
7139 break;
7140 }
7141 };
7142 Parser.prototype.parseGroupExpression = function () {
7143 var expr;
7144 this.expect('(');
7145 if (this.match(')')) {
7146 this.nextToken();
7147 if (!this.match('=>')) {
7148 this.expect('=>');
7149 }
7150 expr = {
7151 type: ArrowParameterPlaceHolder,
7152 params: [],
7153 async: false
7154 };
7155 }
7156 else {
7157 var startToken = this.lookahead;
7158 var params = [];
7159 if (this.match('...')) {
7160 expr = this.parseRestElement(params);
7161 this.expect(')');
7162 if (!this.match('=>')) {
7163 this.expect('=>');
7164 }
7165 expr = {
7166 type: ArrowParameterPlaceHolder,
7167 params: [expr],
7168 async: false
7169 };
7170 }
7171 else {
7172 var arrow = false;
7173 this.context.isBindingElement = true;
7174 expr = this.inheritCoverGrammar(this.parseAssignmentExpression);
7175 if (this.match(',')) {
7176 var expressions = [];
7177 this.context.isAssignmentTarget = false;
7178 expressions.push(expr);
7179 while (this.lookahead.type !== 2 /* EOF */) {
7180 if (!this.match(',')) {
7181 break;
7182 }
7183 this.nextToken();
7184 if (this.match(')')) {
7185 this.nextToken();
7186 for (var i = 0; i < expressions.length; i++) {
7187 this.reinterpretExpressionAsPattern(expressions[i]);
7188 }
7189 arrow = true;
7190 expr = {
7191 type: ArrowParameterPlaceHolder,
7192 params: expressions,
7193 async: false
7194 };
7195 }
7196 else if (this.match('...')) {
7197 if (!this.context.isBindingElement) {
7198 this.throwUnexpectedToken(this.lookahead);
7199 }
7200 expressions.push(this.parseRestElement(params));
7201 this.expect(')');
7202 if (!this.match('=>')) {
7203 this.expect('=>');
7204 }
7205 this.context.isBindingElement = false;
7206 for (var i = 0; i < expressions.length; i++) {
7207 this.reinterpretExpressionAsPattern(expressions[i]);
7208 }
7209 arrow = true;
7210 expr = {
7211 type: ArrowParameterPlaceHolder,
7212 params: expressions,
7213 async: false
7214 };
7215 }
7216 else {
7217 expressions.push(this.inheritCoverGrammar(this.parseAssignmentExpression));
7218 }
7219 if (arrow) {
7220 break;
7221 }
7222 }
7223 if (!arrow) {
7224 expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions));
7225 }
7226 }
7227 if (!arrow) {
7228 this.expect(')');
7229 if (this.match('=>')) {
7230 if (expr.type === syntax_1.Syntax.Identifier && expr.name === 'yield') {
7231 arrow = true;
7232 expr = {
7233 type: ArrowParameterPlaceHolder,
7234 params: [expr],
7235 async: false
7236 };
7237 }
7238 if (!arrow) {
7239 if (!this.context.isBindingElement) {
7240 this.throwUnexpectedToken(this.lookahead);
7241 }
7242 if (expr.type === syntax_1.Syntax.SequenceExpression) {
7243 for (var i = 0; i < expr.expressions.length; i++) {
7244 this.reinterpretExpressionAsPattern(expr.expressions[i]);
7245 }
7246 }
7247 else {
7248 this.reinterpretExpressionAsPattern(expr);
7249 }
7250 var parameters = (expr.type === syntax_1.Syntax.SequenceExpression ? expr.expressions : [expr]);
7251 expr = {
7252 type: ArrowParameterPlaceHolder,
7253 params: parameters,
7254 async: false
7255 };
7256 }
7257 }
7258 this.context.isBindingElement = false;
7259 }
7260 }
7261 }
7262 return expr;
7263 };
7264 // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions
7265 Parser.prototype.parseArguments = function () {
7266 this.expect('(');
7267 var args = [];
7268 if (!this.match(')')) {
7269 while (true) {
7270 var expr = this.match('...') ? this.parseSpreadElement() :
7271 this.isolateCoverGrammar(this.parseAssignmentExpression);
7272 args.push(expr);
7273 if (this.match(')')) {
7274 break;
7275 }
7276 this.expectCommaSeparator();
7277 if (this.match(')')) {
7278 break;
7279 }
7280 }
7281 }
7282 this.expect(')');
7283 return args;
7284 };
7285 Parser.prototype.isIdentifierName = function (token) {
7286 return token.type === 3 /* Identifier */ ||
7287 token.type === 4 /* Keyword */ ||
7288 token.type === 1 /* BooleanLiteral */ ||
7289 token.type === 5 /* NullLiteral */;
7290 };
7291 Parser.prototype.parseIdentifierName = function () {
7292 var node = this.createNode();
7293 var token = this.nextToken();
7294 if (!this.isIdentifierName(token)) {
7295 this.throwUnexpectedToken(token);
7296 }
7297 return this.finalize(node, new Node.Identifier(token.value));
7298 };
7299 Parser.prototype.parseNewExpression = function () {
7300 var node = this.createNode();
7301 var id = this.parseIdentifierName();
7302 assert_1.assert(id.name === 'new', 'New expression must start with `new`');
7303 var expr;
7304 if (this.match('.')) {
7305 this.nextToken();
7306 if (this.lookahead.type === 3 /* Identifier */ && this.context.inFunctionBody && this.lookahead.value === 'target') {
7307 var property = this.parseIdentifierName();
7308 expr = new Node.MetaProperty(id, property);
7309 }
7310 else {
7311 this.throwUnexpectedToken(this.lookahead);
7312 }
7313 }
7314 else {
7315 var callee = this.isolateCoverGrammar(this.parseLeftHandSideExpression);
7316 var args = this.match('(') ? this.parseArguments() : [];
7317 expr = new Node.NewExpression(callee, args);
7318 this.context.isAssignmentTarget = false;
7319 this.context.isBindingElement = false;
7320 }
7321 return this.finalize(node, expr);
7322 };
7323 Parser.prototype.parseAsyncArgument = function () {
7324 var arg = this.parseAssignmentExpression();
7325 this.context.firstCoverInitializedNameError = null;
7326 return arg;
7327 };
7328 Parser.prototype.parseAsyncArguments = function () {
7329 this.expect('(');
7330 var args = [];
7331 if (!this.match(')')) {
7332 while (true) {
7333 var expr = this.match('...') ? this.parseSpreadElement() :
7334 this.isolateCoverGrammar(this.parseAsyncArgument);
7335 args.push(expr);
7336 if (this.match(')')) {
7337 break;
7338 }
7339 this.expectCommaSeparator();
7340 if (this.match(')')) {
7341 break;
7342 }
7343 }
7344 }
7345 this.expect(')');
7346 return args;
7347 };
7348 Parser.prototype.parseLeftHandSideExpressionAllowCall = function () {
7349 var startToken = this.lookahead;
7350 var maybeAsync = this.matchContextualKeyword('async');
7351 var previousAllowIn = this.context.allowIn;
7352 this.context.allowIn = true;
7353 var expr;
7354 if (this.matchKeyword('super') && this.context.inFunctionBody) {
7355 expr = this.createNode();
7356 this.nextToken();
7357 expr = this.finalize(expr, new Node.Super());
7358 if (!this.match('(') && !this.match('.') && !this.match('[')) {
7359 this.throwUnexpectedToken(this.lookahead);
7360 }
7361 }
7362 else {
7363 expr = this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression);
7364 }
7365 while (true) {
7366 if (this.match('.')) {
7367 this.context.isBindingElement = false;
7368 this.context.isAssignmentTarget = true;
7369 this.expect('.');
7370 var property = this.parseIdentifierName();
7371 expr = this.finalize(this.startNode(startToken), new Node.StaticMemberExpression(expr, property));
7372 }
7373 else if (this.match('(')) {
7374 var asyncArrow = maybeAsync && (startToken.lineNumber === this.lookahead.lineNumber);
7375 this.context.isBindingElement = false;
7376 this.context.isAssignmentTarget = false;
7377 var args = asyncArrow ? this.parseAsyncArguments() : this.parseArguments();
7378 expr = this.finalize(this.startNode(startToken), new Node.CallExpression(expr, args));
7379 if (asyncArrow && this.match('=>')) {
7380 for (var i = 0; i < args.length; ++i) {
7381 this.reinterpretExpressionAsPattern(args[i]);
7382 }
7383 expr = {
7384 type: ArrowParameterPlaceHolder,
7385 params: args,
7386 async: true
7387 };
7388 }
7389 }
7390 else if (this.match('[')) {
7391 this.context.isBindingElement = false;
7392 this.context.isAssignmentTarget = true;
7393 this.expect('[');
7394 var property = this.isolateCoverGrammar(this.parseExpression);
7395 this.expect(']');
7396 expr = this.finalize(this.startNode(startToken), new Node.ComputedMemberExpression(expr, property));
7397 }
7398 else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) {
7399 var quasi = this.parseTemplateLiteral();
7400 expr = this.finalize(this.startNode(startToken), new Node.TaggedTemplateExpression(expr, quasi));
7401 }
7402 else {
7403 break;
7404 }
7405 }
7406 this.context.allowIn = previousAllowIn;
7407 return expr;
7408 };
7409 Parser.prototype.parseSuper = function () {
7410 var node = this.createNode();
7411 this.expectKeyword('super');
7412 if (!this.match('[') && !this.match('.')) {
7413 this.throwUnexpectedToken(this.lookahead);
7414 }
7415 return this.finalize(node, new Node.Super());
7416 };
7417 Parser.prototype.parseLeftHandSideExpression = function () {
7418 assert_1.assert(this.context.allowIn, 'callee of new expression always allow in keyword.');
7419 var node = this.startNode(this.lookahead);
7420 var expr = (this.matchKeyword('super') && this.context.inFunctionBody) ? this.parseSuper() :
7421 this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression);
7422 while (true) {
7423 if (this.match('[')) {
7424 this.context.isBindingElement = false;
7425 this.context.isAssignmentTarget = true;
7426 this.expect('[');
7427 var property = this.isolateCoverGrammar(this.parseExpression);
7428 this.expect(']');
7429 expr = this.finalize(node, new Node.ComputedMemberExpression(expr, property));
7430 }
7431 else if (this.match('.')) {
7432 this.context.isBindingElement = false;
7433 this.context.isAssignmentTarget = true;
7434 this.expect('.');
7435 var property = this.parseIdentifierName();
7436 expr = this.finalize(node, new Node.StaticMemberExpression(expr, property));
7437 }
7438 else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) {
7439 var quasi = this.parseTemplateLiteral();
7440 expr = this.finalize(node, new Node.TaggedTemplateExpression(expr, quasi));
7441 }
7442 else {
7443 break;
7444 }
7445 }
7446 return expr;
7447 };
7448 // https://tc39.github.io/ecma262/#sec-update-expressions
7449 Parser.prototype.parseUpdateExpression = function () {
7450 var expr;
7451 var startToken = this.lookahead;
7452 if (this.match('++') || this.match('--')) {
7453 var node = this.startNode(startToken);
7454 var token = this.nextToken();
7455 expr = this.inheritCoverGrammar(this.parseUnaryExpression);
7456 if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) {
7457 this.tolerateError(messages_1.Messages.StrictLHSPrefix);
7458 }
7459 if (!this.context.isAssignmentTarget) {
7460 this.tolerateError(messages_1.Messages.InvalidLHSInAssignment);
7461 }
7462 var prefix = true;
7463 expr = this.finalize(node, new Node.UpdateExpression(token.value, expr, prefix));
7464 this.context.isAssignmentTarget = false;
7465 this.context.isBindingElement = false;
7466 }
7467 else {
7468 expr = this.inheritCoverGrammar(this.parseLeftHandSideExpressionAllowCall);
7469 if (!this.hasLineTerminator && this.lookahead.type === 7 /* Punctuator */) {
7470 if (this.match('++') || this.match('--')) {
7471 if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) {
7472 this.tolerateError(messages_1.Messages.StrictLHSPostfix);
7473 }
7474 if (!this.context.isAssignmentTarget) {
7475 this.tolerateError(messages_1.Messages.InvalidLHSInAssignment);
7476 }
7477 this.context.isAssignmentTarget = false;
7478 this.context.isBindingElement = false;
7479 var operator = this.nextToken().value;
7480 var prefix = false;
7481 expr = this.finalize(this.startNode(startToken), new Node.UpdateExpression(operator, expr, prefix));
7482 }
7483 }
7484 }
7485 return expr;
7486 };
7487 // https://tc39.github.io/ecma262/#sec-unary-operators
7488 Parser.prototype.parseAwaitExpression = function () {
7489 var node = this.createNode();
7490 this.nextToken();
7491 var argument = this.parseUnaryExpression();
7492 return this.finalize(node, new Node.AwaitExpression(argument));
7493 };
7494 Parser.prototype.parseUnaryExpression = function () {
7495 var expr;
7496 if (this.match('+') || this.match('-') || this.match('~') || this.match('!') ||
7497 this.matchKeyword('delete') || this.matchKeyword('void') || this.matchKeyword('typeof')) {
7498 var node = this.startNode(this.lookahead);
7499 var token = this.nextToken();
7500 expr = this.inheritCoverGrammar(this.parseUnaryExpression);
7501 expr = this.finalize(node, new Node.UnaryExpression(token.value, expr));
7502 if (this.context.strict && expr.operator === 'delete' && expr.argument.type === syntax_1.Syntax.Identifier) {
7503 this.tolerateError(messages_1.Messages.StrictDelete);
7504 }
7505 this.context.isAssignmentTarget = false;
7506 this.context.isBindingElement = false;
7507 }
7508 else if (this.context.await && this.matchContextualKeyword('await')) {
7509 expr = this.parseAwaitExpression();
7510 }
7511 else {
7512 expr = this.parseUpdateExpression();
7513 }
7514 return expr;
7515 };
7516 Parser.prototype.parseExponentiationExpression = function () {
7517 var startToken = this.lookahead;
7518 var expr = this.inheritCoverGrammar(this.parseUnaryExpression);
7519 if (expr.type !== syntax_1.Syntax.UnaryExpression && this.match('**')) {
7520 this.nextToken();
7521 this.context.isAssignmentTarget = false;
7522 this.context.isBindingElement = false;
7523 var left = expr;
7524 var right = this.isolateCoverGrammar(this.parseExponentiationExpression);
7525 expr = this.finalize(this.startNode(startToken), new Node.BinaryExpression('**', left, right));
7526 }
7527 return expr;
7528 };
7529 // https://tc39.github.io/ecma262/#sec-exp-operator
7530 // https://tc39.github.io/ecma262/#sec-multiplicative-operators
7531 // https://tc39.github.io/ecma262/#sec-additive-operators
7532 // https://tc39.github.io/ecma262/#sec-bitwise-shift-operators
7533 // https://tc39.github.io/ecma262/#sec-relational-operators
7534 // https://tc39.github.io/ecma262/#sec-equality-operators
7535 // https://tc39.github.io/ecma262/#sec-binary-bitwise-operators
7536 // https://tc39.github.io/ecma262/#sec-binary-logical-operators
7537 Parser.prototype.binaryPrecedence = function (token) {
7538 var op = token.value;
7539 var precedence;
7540 if (token.type === 7 /* Punctuator */) {
7541 precedence = this.operatorPrecedence[op] || 0;
7542 }
7543 else if (token.type === 4 /* Keyword */) {
7544 precedence = (op === 'instanceof' || (this.context.allowIn && op === 'in')) ? 7 : 0;
7545 }
7546 else {
7547 precedence = 0;
7548 }
7549 return precedence;
7550 };
7551 Parser.prototype.parseBinaryExpression = function () {
7552 var startToken = this.lookahead;
7553 var expr = this.inheritCoverGrammar(this.parseExponentiationExpression);
7554 var token = this.lookahead;
7555 var prec = this.binaryPrecedence(token);
7556 if (prec > 0) {
7557 this.nextToken();
7558 this.context.isAssignmentTarget = false;
7559 this.context.isBindingElement = false;
7560 var markers = [startToken, this.lookahead];
7561 var left = expr;
7562 var right = this.isolateCoverGrammar(this.parseExponentiationExpression);
7563 var stack = [left, token.value, right];
7564 var precedences = [prec];
7565 while (true) {
7566 prec = this.binaryPrecedence(this.lookahead);
7567 if (prec <= 0) {
7568 break;
7569 }
7570 // Reduce: make a binary expression from the three topmost entries.
7571 while ((stack.length > 2) && (prec <= precedences[precedences.length - 1])) {
7572 right = stack.pop();
7573 var operator = stack.pop();
7574 precedences.pop();
7575 left = stack.pop();
7576 markers.pop();
7577 var node = this.startNode(markers[markers.length - 1]);
7578 stack.push(this.finalize(node, new Node.BinaryExpression(operator, left, right)));
7579 }
7580 // Shift.
7581 stack.push(this.nextToken().value);
7582 precedences.push(prec);
7583 markers.push(this.lookahead);
7584 stack.push(this.isolateCoverGrammar(this.parseExponentiationExpression));
7585 }
7586 // Final reduce to clean-up the stack.
7587 var i = stack.length - 1;
7588 expr = stack[i];
7589 markers.pop();
7590 while (i > 1) {
7591 var node = this.startNode(markers.pop());
7592 var operator = stack[i - 1];
7593 expr = this.finalize(node, new Node.BinaryExpression(operator, stack[i - 2], expr));
7594 i -= 2;
7595 }
7596 }
7597 return expr;
7598 };
7599 // https://tc39.github.io/ecma262/#sec-conditional-operator
7600 Parser.prototype.parseConditionalExpression = function () {
7601 var startToken = this.lookahead;
7602 var expr = this.inheritCoverGrammar(this.parseBinaryExpression);
7603 if (this.match('?')) {
7604 this.nextToken();
7605 var previousAllowIn = this.context.allowIn;
7606 this.context.allowIn = true;
7607 var consequent = this.isolateCoverGrammar(this.parseAssignmentExpression);
7608 this.context.allowIn = previousAllowIn;
7609 this.expect(':');
7610 var alternate = this.isolateCoverGrammar(this.parseAssignmentExpression);
7611 expr = this.finalize(this.startNode(startToken), new Node.ConditionalExpression(expr, consequent, alternate));
7612 this.context.isAssignmentTarget = false;
7613 this.context.isBindingElement = false;
7614 }
7615 return expr;
7616 };
7617 // https://tc39.github.io/ecma262/#sec-assignment-operators
7618 Parser.prototype.checkPatternParam = function (options, param) {
7619 switch (param.type) {
7620 case syntax_1.Syntax.Identifier:
7621 this.validateParam(options, param, param.name);
7622 break;
7623 case syntax_1.Syntax.RestElement:
7624 this.checkPatternParam(options, param.argument);
7625 break;
7626 case syntax_1.Syntax.AssignmentPattern:
7627 this.checkPatternParam(options, param.left);
7628 break;
7629 case syntax_1.Syntax.ArrayPattern:
7630 for (var i = 0; i < param.elements.length; i++) {
7631 if (param.elements[i] !== null) {
7632 this.checkPatternParam(options, param.elements[i]);
7633 }
7634 }
7635 break;
7636 case syntax_1.Syntax.ObjectPattern:
7637 for (var i = 0; i < param.properties.length; i++) {
7638 this.checkPatternParam(options, param.properties[i].value);
7639 }
7640 break;
7641 default:
7642 break;
7643 }
7644 options.simple = options.simple && (param instanceof Node.Identifier);
7645 };
7646 Parser.prototype.reinterpretAsCoverFormalsList = function (expr) {
7647 var params = [expr];
7648 var options;
7649 var asyncArrow = false;
7650 switch (expr.type) {
7651 case syntax_1.Syntax.Identifier:
7652 break;
7653 case ArrowParameterPlaceHolder:
7654 params = expr.params;
7655 asyncArrow = expr.async;
7656 break;
7657 default:
7658 return null;
7659 }
7660 options = {
7661 simple: true,
7662 paramSet: {}
7663 };
7664 for (var i = 0; i < params.length; ++i) {
7665 var param = params[i];
7666 if (param.type === syntax_1.Syntax.AssignmentPattern) {
7667 if (param.right.type === syntax_1.Syntax.YieldExpression) {
7668 if (param.right.argument) {
7669 this.throwUnexpectedToken(this.lookahead);
7670 }
7671 param.right.type = syntax_1.Syntax.Identifier;
7672 param.right.name = 'yield';
7673 delete param.right.argument;
7674 delete param.right.delegate;
7675 }
7676 }
7677 else if (asyncArrow && param.type === syntax_1.Syntax.Identifier && param.name === 'await') {
7678 this.throwUnexpectedToken(this.lookahead);
7679 }
7680 this.checkPatternParam(options, param);
7681 params[i] = param;
7682 }
7683 if (this.context.strict || !this.context.allowYield) {
7684 for (var i = 0; i < params.length; ++i) {
7685 var param = params[i];
7686 if (param.type === syntax_1.Syntax.YieldExpression) {
7687 this.throwUnexpectedToken(this.lookahead);
7688 }
7689 }
7690 }
7691 if (options.message === messages_1.Messages.StrictParamDupe) {
7692 var token = this.context.strict ? options.stricted : options.firstRestricted;
7693 this.throwUnexpectedToken(token, options.message);
7694 }
7695 return {
7696 simple: options.simple,
7697 params: params,
7698 stricted: options.stricted,
7699 firstRestricted: options.firstRestricted,
7700 message: options.message
7701 };
7702 };
7703 Parser.prototype.parseAssignmentExpression = function () {
7704 var expr;
7705 if (!this.context.allowYield && this.matchKeyword('yield')) {
7706 expr = this.parseYieldExpression();
7707 }
7708 else {
7709 var startToken = this.lookahead;
7710 var token = startToken;
7711 expr = this.parseConditionalExpression();
7712 if (token.type === 3 /* Identifier */ && (token.lineNumber === this.lookahead.lineNumber) && token.value === 'async') {
7713 if (this.lookahead.type === 3 /* Identifier */ || this.matchKeyword('yield')) {
7714 var arg = this.parsePrimaryExpression();
7715 this.reinterpretExpressionAsPattern(arg);
7716 expr = {
7717 type: ArrowParameterPlaceHolder,
7718 params: [arg],
7719 async: true
7720 };
7721 }
7722 }
7723 if (expr.type === ArrowParameterPlaceHolder || this.match('=>')) {
7724 // https://tc39.github.io/ecma262/#sec-arrow-function-definitions
7725 this.context.isAssignmentTarget = false;
7726 this.context.isBindingElement = false;
7727 var isAsync = expr.async;
7728 var list = this.reinterpretAsCoverFormalsList(expr);
7729 if (list) {
7730 if (this.hasLineTerminator) {
7731 this.tolerateUnexpectedToken(this.lookahead);
7732 }
7733 this.context.firstCoverInitializedNameError = null;
7734 var previousStrict = this.context.strict;
7735 var previousAllowStrictDirective = this.context.allowStrictDirective;
7736 this.context.allowStrictDirective = list.simple;
7737 var previousAllowYield = this.context.allowYield;
7738 var previousAwait = this.context.await;
7739 this.context.allowYield = true;
7740 this.context.await = isAsync;
7741 var node = this.startNode(startToken);
7742 this.expect('=>');
7743 var body = void 0;
7744 if (this.match('{')) {
7745 var previousAllowIn = this.context.allowIn;
7746 this.context.allowIn = true;
7747 body = this.parseFunctionSourceElements();
7748 this.context.allowIn = previousAllowIn;
7749 }
7750 else {
7751 body = this.isolateCoverGrammar(this.parseAssignmentExpression);
7752 }
7753 var expression = body.type !== syntax_1.Syntax.BlockStatement;
7754 if (this.context.strict && list.firstRestricted) {
7755 this.throwUnexpectedToken(list.firstRestricted, list.message);
7756 }
7757 if (this.context.strict && list.stricted) {
7758 this.tolerateUnexpectedToken(list.stricted, list.message);
7759 }
7760 expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression)) :
7761 this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression));
7762 this.context.strict = previousStrict;
7763 this.context.allowStrictDirective = previousAllowStrictDirective;
7764 this.context.allowYield = previousAllowYield;
7765 this.context.await = previousAwait;
7766 }
7767 }
7768 else {
7769 if (this.matchAssign()) {
7770 if (!this.context.isAssignmentTarget) {
7771 this.tolerateError(messages_1.Messages.InvalidLHSInAssignment);
7772 }
7773 if (this.context.strict && expr.type === syntax_1.Syntax.Identifier) {
7774 var id = expr;
7775 if (this.scanner.isRestrictedWord(id.name)) {
7776 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictLHSAssignment);
7777 }
7778 if (this.scanner.isStrictModeReservedWord(id.name)) {
7779 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord);
7780 }
7781 }
7782 if (!this.match('=')) {
7783 this.context.isAssignmentTarget = false;
7784 this.context.isBindingElement = false;
7785 }
7786 else {
7787 this.reinterpretExpressionAsPattern(expr);
7788 }
7789 token = this.nextToken();
7790 var operator = token.value;
7791 var right = this.isolateCoverGrammar(this.parseAssignmentExpression);
7792 expr = this.finalize(this.startNode(startToken), new Node.AssignmentExpression(operator, expr, right));
7793 this.context.firstCoverInitializedNameError = null;
7794 }
7795 }
7796 }
7797 return expr;
7798 };
7799 // https://tc39.github.io/ecma262/#sec-comma-operator
7800 Parser.prototype.parseExpression = function () {
7801 var startToken = this.lookahead;
7802 var expr = this.isolateCoverGrammar(this.parseAssignmentExpression);
7803 if (this.match(',')) {
7804 var expressions = [];
7805 expressions.push(expr);
7806 while (this.lookahead.type !== 2 /* EOF */) {
7807 if (!this.match(',')) {
7808 break;
7809 }
7810 this.nextToken();
7811 expressions.push(this.isolateCoverGrammar(this.parseAssignmentExpression));
7812 }
7813 expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions));
7814 }
7815 return expr;
7816 };
7817 // https://tc39.github.io/ecma262/#sec-block
7818 Parser.prototype.parseStatementListItem = function () {
7819 var statement;
7820 this.context.isAssignmentTarget = true;
7821 this.context.isBindingElement = true;
7822 if (this.lookahead.type === 4 /* Keyword */) {
7823 switch (this.lookahead.value) {
7824 case 'export':
7825 if (!this.context.isModule) {
7826 this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalExportDeclaration);
7827 }
7828 statement = this.parseExportDeclaration();
7829 break;
7830 case 'import':
7831 if (!this.context.isModule) {
7832 this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalImportDeclaration);
7833 }
7834 statement = this.parseImportDeclaration();
7835 break;
7836 case 'const':
7837 statement = this.parseLexicalDeclaration({ inFor: false });
7838 break;
7839 case 'function':
7840 statement = this.parseFunctionDeclaration();
7841 break;
7842 case 'class':
7843 statement = this.parseClassDeclaration();
7844 break;
7845 case 'let':
7846 statement = this.isLexicalDeclaration() ? this.parseLexicalDeclaration({ inFor: false }) : this.parseStatement();
7847 break;
7848 default:
7849 statement = this.parseStatement();
7850 break;
7851 }
7852 }
7853 else {
7854 statement = this.parseStatement();
7855 }
7856 return statement;
7857 };
7858 Parser.prototype.parseBlock = function () {
7859 var node = this.createNode();
7860 this.expect('{');
7861 var block = [];
7862 while (true) {
7863 if (this.match('}')) {
7864 break;
7865 }
7866 block.push(this.parseStatementListItem());
7867 }
7868 this.expect('}');
7869 return this.finalize(node, new Node.BlockStatement(block));
7870 };
7871 // https://tc39.github.io/ecma262/#sec-let-and-const-declarations
7872 Parser.prototype.parseLexicalBinding = function (kind, options) {
7873 var node = this.createNode();
7874 var params = [];
7875 var id = this.parsePattern(params, kind);
7876 if (this.context.strict && id.type === syntax_1.Syntax.Identifier) {
7877 if (this.scanner.isRestrictedWord(id.name)) {
7878 this.tolerateError(messages_1.Messages.StrictVarName);
7879 }
7880 }
7881 var init = null;
7882 if (kind === 'const') {
7883 if (!this.matchKeyword('in') && !this.matchContextualKeyword('of')) {
7884 if (this.match('=')) {
7885 this.nextToken();
7886 init = this.isolateCoverGrammar(this.parseAssignmentExpression);
7887 }
7888 else {
7889 this.throwError(messages_1.Messages.DeclarationMissingInitializer, 'const');
7890 }
7891 }
7892 }
7893 else if ((!options.inFor && id.type !== syntax_1.Syntax.Identifier) || this.match('=')) {
7894 this.expect('=');
7895 init = this.isolateCoverGrammar(this.parseAssignmentExpression);
7896 }
7897 return this.finalize(node, new Node.VariableDeclarator(id, init));
7898 };
7899 Parser.prototype.parseBindingList = function (kind, options) {
7900 var list = [this.parseLexicalBinding(kind, options)];
7901 while (this.match(',')) {
7902 this.nextToken();
7903 list.push(this.parseLexicalBinding(kind, options));
7904 }
7905 return list;
7906 };
7907 Parser.prototype.isLexicalDeclaration = function () {
7908 var state = this.scanner.saveState();
7909 this.scanner.scanComments();
7910 var next = this.scanner.lex();
7911 this.scanner.restoreState(state);
7912 return (next.type === 3 /* Identifier */) ||
7913 (next.type === 7 /* Punctuator */ && next.value === '[') ||
7914 (next.type === 7 /* Punctuator */ && next.value === '{') ||
7915 (next.type === 4 /* Keyword */ && next.value === 'let') ||
7916 (next.type === 4 /* Keyword */ && next.value === 'yield');
7917 };
7918 Parser.prototype.parseLexicalDeclaration = function (options) {
7919 var node = this.createNode();
7920 var kind = this.nextToken().value;
7921 assert_1.assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const');
7922 var declarations = this.parseBindingList(kind, options);
7923 this.consumeSemicolon();
7924 return this.finalize(node, new Node.VariableDeclaration(declarations, kind));
7925 };
7926 // https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns
7927 Parser.prototype.parseBindingRestElement = function (params, kind) {
7928 var node = this.createNode();
7929 this.expect('...');
7930 var arg = this.parsePattern(params, kind);
7931 return this.finalize(node, new Node.RestElement(arg));
7932 };
7933 Parser.prototype.parseArrayPattern = function (params, kind) {
7934 var node = this.createNode();
7935 this.expect('[');
7936 var elements = [];
7937 while (!this.match(']')) {
7938 if (this.match(',')) {
7939 this.nextToken();
7940 elements.push(null);
7941 }
7942 else {
7943 if (this.match('...')) {
7944 elements.push(this.parseBindingRestElement(params, kind));
7945 break;
7946 }
7947 else {
7948 elements.push(this.parsePatternWithDefault(params, kind));
7949 }
7950 if (!this.match(']')) {
7951 this.expect(',');
7952 }
7953 }
7954 }
7955 this.expect(']');
7956 return this.finalize(node, new Node.ArrayPattern(elements));
7957 };
7958 Parser.prototype.parsePropertyPattern = function (params, kind) {
7959 var node = this.createNode();
7960 var computed = false;
7961 var shorthand = false;
7962 var method = false;
7963 var key;
7964 var value;
7965 if (this.lookahead.type === 3 /* Identifier */) {
7966 var keyToken = this.lookahead;
7967 key = this.parseVariableIdentifier();
7968 var init = this.finalize(node, new Node.Identifier(keyToken.value));
7969 if (this.match('=')) {
7970 params.push(keyToken);
7971 shorthand = true;
7972 this.nextToken();
7973 var expr = this.parseAssignmentExpression();
7974 value = this.finalize(this.startNode(keyToken), new Node.AssignmentPattern(init, expr));
7975 }
7976 else if (!this.match(':')) {
7977 params.push(keyToken);
7978 shorthand = true;
7979 value = init;
7980 }
7981 else {
7982 this.expect(':');
7983 value = this.parsePatternWithDefault(params, kind);
7984 }
7985 }
7986 else {
7987 computed = this.match('[');
7988 key = this.parseObjectPropertyKey();
7989 this.expect(':');
7990 value = this.parsePatternWithDefault(params, kind);
7991 }
7992 return this.finalize(node, new Node.Property('init', key, computed, value, method, shorthand));
7993 };
7994 Parser.prototype.parseObjectPattern = function (params, kind) {
7995 var node = this.createNode();
7996 var properties = [];
7997 this.expect('{');
7998 while (!this.match('}')) {
7999 properties.push(this.parsePropertyPattern(params, kind));
8000 if (!this.match('}')) {
8001 this.expect(',');
8002 }
8003 }
8004 this.expect('}');
8005 return this.finalize(node, new Node.ObjectPattern(properties));
8006 };
8007 Parser.prototype.parsePattern = function (params, kind) {
8008 var pattern;
8009 if (this.match('[')) {
8010 pattern = this.parseArrayPattern(params, kind);
8011 }
8012 else if (this.match('{')) {
8013 pattern = this.parseObjectPattern(params, kind);
8014 }
8015 else {
8016 if (this.matchKeyword('let') && (kind === 'const' || kind === 'let')) {
8017 this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.LetInLexicalBinding);
8018 }
8019 params.push(this.lookahead);
8020 pattern = this.parseVariableIdentifier(kind);
8021 }
8022 return pattern;
8023 };
8024 Parser.prototype.parsePatternWithDefault = function (params, kind) {
8025 var startToken = this.lookahead;
8026 var pattern = this.parsePattern(params, kind);
8027 if (this.match('=')) {
8028 this.nextToken();
8029 var previousAllowYield = this.context.allowYield;
8030 this.context.allowYield = true;
8031 var right = this.isolateCoverGrammar(this.parseAssignmentExpression);
8032 this.context.allowYield = previousAllowYield;
8033 pattern = this.finalize(this.startNode(startToken), new Node.AssignmentPattern(pattern, right));
8034 }
8035 return pattern;
8036 };
8037 // https://tc39.github.io/ecma262/#sec-variable-statement
8038 Parser.prototype.parseVariableIdentifier = function (kind) {
8039 var node = this.createNode();
8040 var token = this.nextToken();
8041 if (token.type === 4 /* Keyword */ && token.value === 'yield') {
8042 if (this.context.strict) {
8043 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord);
8044 }
8045 else if (!this.context.allowYield) {
8046 this.throwUnexpectedToken(token);
8047 }
8048 }
8049 else if (token.type !== 3 /* Identifier */) {
8050 if (this.context.strict && token.type === 4 /* Keyword */ && this.scanner.isStrictModeReservedWord(token.value)) {
8051 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord);
8052 }
8053 else {
8054 if (this.context.strict || token.value !== 'let' || kind !== 'var') {
8055 this.throwUnexpectedToken(token);
8056 }
8057 }
8058 }
8059 else if ((this.context.isModule || this.context.await) && token.type === 3 /* Identifier */ && token.value === 'await') {
8060 this.tolerateUnexpectedToken(token);
8061 }
8062 return this.finalize(node, new Node.Identifier(token.value));
8063 };
8064 Parser.prototype.parseVariableDeclaration = function (options) {
8065 var node = this.createNode();
8066 var params = [];
8067 var id = this.parsePattern(params, 'var');
8068 if (this.context.strict && id.type === syntax_1.Syntax.Identifier) {
8069 if (this.scanner.isRestrictedWord(id.name)) {
8070 this.tolerateError(messages_1.Messages.StrictVarName);
8071 }
8072 }
8073 var init = null;
8074 if (this.match('=')) {
8075 this.nextToken();
8076 init = this.isolateCoverGrammar(this.parseAssignmentExpression);
8077 }
8078 else if (id.type !== syntax_1.Syntax.Identifier && !options.inFor) {
8079 this.expect('=');
8080 }
8081 return this.finalize(node, new Node.VariableDeclarator(id, init));
8082 };
8083 Parser.prototype.parseVariableDeclarationList = function (options) {
8084 var opt = { inFor: options.inFor };
8085 var list = [];
8086 list.push(this.parseVariableDeclaration(opt));
8087 while (this.match(',')) {
8088 this.nextToken();
8089 list.push(this.parseVariableDeclaration(opt));
8090 }
8091 return list;
8092 };
8093 Parser.prototype.parseVariableStatement = function () {
8094 var node = this.createNode();
8095 this.expectKeyword('var');
8096 var declarations = this.parseVariableDeclarationList({ inFor: false });
8097 this.consumeSemicolon();
8098 return this.finalize(node, new Node.VariableDeclaration(declarations, 'var'));
8099 };
8100 // https://tc39.github.io/ecma262/#sec-empty-statement
8101 Parser.prototype.parseEmptyStatement = function () {
8102 var node = this.createNode();
8103 this.expect(';');
8104 return this.finalize(node, new Node.EmptyStatement());
8105 };
8106 // https://tc39.github.io/ecma262/#sec-expression-statement
8107 Parser.prototype.parseExpressionStatement = function () {
8108 var node = this.createNode();
8109 var expr = this.parseExpression();
8110 this.consumeSemicolon();
8111 return this.finalize(node, new Node.ExpressionStatement(expr));
8112 };
8113 // https://tc39.github.io/ecma262/#sec-if-statement
8114 Parser.prototype.parseIfClause = function () {
8115 if (this.context.strict && this.matchKeyword('function')) {
8116 this.tolerateError(messages_1.Messages.StrictFunction);
8117 }
8118 return this.parseStatement();
8119 };
8120 Parser.prototype.parseIfStatement = function () {
8121 var node = this.createNode();
8122 var consequent;
8123 var alternate = null;
8124 this.expectKeyword('if');
8125 this.expect('(');
8126 var test = this.parseExpression();
8127 if (!this.match(')') && this.config.tolerant) {
8128 this.tolerateUnexpectedToken(this.nextToken());
8129 consequent = this.finalize(this.createNode(), new Node.EmptyStatement());
8130 }
8131 else {
8132 this.expect(')');
8133 consequent = this.parseIfClause();
8134 if (this.matchKeyword('else')) {
8135 this.nextToken();
8136 alternate = this.parseIfClause();
8137 }
8138 }
8139 return this.finalize(node, new Node.IfStatement(test, consequent, alternate));
8140 };
8141 // https://tc39.github.io/ecma262/#sec-do-while-statement
8142 Parser.prototype.parseDoWhileStatement = function () {
8143 var node = this.createNode();
8144 this.expectKeyword('do');
8145 var previousInIteration = this.context.inIteration;
8146 this.context.inIteration = true;
8147 var body = this.parseStatement();
8148 this.context.inIteration = previousInIteration;
8149 this.expectKeyword('while');
8150 this.expect('(');
8151 var test = this.parseExpression();
8152 if (!this.match(')') && this.config.tolerant) {
8153 this.tolerateUnexpectedToken(this.nextToken());
8154 }
8155 else {
8156 this.expect(')');
8157 if (this.match(';')) {
8158 this.nextToken();
8159 }
8160 }
8161 return this.finalize(node, new Node.DoWhileStatement(body, test));
8162 };
8163 // https://tc39.github.io/ecma262/#sec-while-statement
8164 Parser.prototype.parseWhileStatement = function () {
8165 var node = this.createNode();
8166 var body;
8167 this.expectKeyword('while');
8168 this.expect('(');
8169 var test = this.parseExpression();
8170 if (!this.match(')') && this.config.tolerant) {
8171 this.tolerateUnexpectedToken(this.nextToken());
8172 body = this.finalize(this.createNode(), new Node.EmptyStatement());
8173 }
8174 else {
8175 this.expect(')');
8176 var previousInIteration = this.context.inIteration;
8177 this.context.inIteration = true;
8178 body = this.parseStatement();
8179 this.context.inIteration = previousInIteration;
8180 }
8181 return this.finalize(node, new Node.WhileStatement(test, body));
8182 };
8183 // https://tc39.github.io/ecma262/#sec-for-statement
8184 // https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements
8185 Parser.prototype.parseForStatement = function () {
8186 var init = null;
8187 var test = null;
8188 var update = null;
8189 var forIn = true;
8190 var left, right;
8191 var node = this.createNode();
8192 this.expectKeyword('for');
8193 this.expect('(');
8194 if (this.match(';')) {
8195 this.nextToken();
8196 }
8197 else {
8198 if (this.matchKeyword('var')) {
8199 init = this.createNode();
8200 this.nextToken();
8201 var previousAllowIn = this.context.allowIn;
8202 this.context.allowIn = false;
8203 var declarations = this.parseVariableDeclarationList({ inFor: true });
8204 this.context.allowIn = previousAllowIn;
8205 if (declarations.length === 1 && this.matchKeyword('in')) {
8206 var decl = declarations[0];
8207 if (decl.init && (decl.id.type === syntax_1.Syntax.ArrayPattern || decl.id.type === syntax_1.Syntax.ObjectPattern || this.context.strict)) {
8208 this.tolerateError(messages_1.Messages.ForInOfLoopInitializer, 'for-in');
8209 }
8210 init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var'));
8211 this.nextToken();
8212 left = init;
8213 right = this.parseExpression();
8214 init = null;
8215 }
8216 else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) {
8217 init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var'));
8218 this.nextToken();
8219 left = init;
8220 right = this.parseAssignmentExpression();
8221 init = null;
8222 forIn = false;
8223 }
8224 else {
8225 init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var'));
8226 this.expect(';');
8227 }
8228 }
8229 else if (this.matchKeyword('const') || this.matchKeyword('let')) {
8230 init = this.createNode();
8231 var kind = this.nextToken().value;
8232 if (!this.context.strict && this.lookahead.value === 'in') {
8233 init = this.finalize(init, new Node.Identifier(kind));
8234 this.nextToken();
8235 left = init;
8236 right = this.parseExpression();
8237 init = null;
8238 }
8239 else {
8240 var previousAllowIn = this.context.allowIn;
8241 this.context.allowIn = false;
8242 var declarations = this.parseBindingList(kind, { inFor: true });
8243 this.context.allowIn = previousAllowIn;
8244 if (declarations.length === 1 && declarations[0].init === null && this.matchKeyword('in')) {
8245 init = this.finalize(init, new Node.VariableDeclaration(declarations, kind));
8246 this.nextToken();
8247 left = init;
8248 right = this.parseExpression();
8249 init = null;
8250 }
8251 else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) {
8252 init = this.finalize(init, new Node.VariableDeclaration(declarations, kind));
8253 this.nextToken();
8254 left = init;
8255 right = this.parseAssignmentExpression();
8256 init = null;
8257 forIn = false;
8258 }
8259 else {
8260 this.consumeSemicolon();
8261 init = this.finalize(init, new Node.VariableDeclaration(declarations, kind));
8262 }
8263 }
8264 }
8265 else {
8266 var initStartToken = this.lookahead;
8267 var previousAllowIn = this.context.allowIn;
8268 this.context.allowIn = false;
8269 init = this.inheritCoverGrammar(this.parseAssignmentExpression);
8270 this.context.allowIn = previousAllowIn;
8271 if (this.matchKeyword('in')) {
8272 if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) {
8273 this.tolerateError(messages_1.Messages.InvalidLHSInForIn);
8274 }
8275 this.nextToken();
8276 this.reinterpretExpressionAsPattern(init);
8277 left = init;
8278 right = this.parseExpression();
8279 init = null;
8280 }
8281 else if (this.matchContextualKeyword('of')) {
8282 if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) {
8283 this.tolerateError(messages_1.Messages.InvalidLHSInForLoop);
8284 }
8285 this.nextToken();
8286 this.reinterpretExpressionAsPattern(init);
8287 left = init;
8288 right = this.parseAssignmentExpression();
8289 init = null;
8290 forIn = false;
8291 }
8292 else {
8293 if (this.match(',')) {
8294 var initSeq = [init];
8295 while (this.match(',')) {
8296 this.nextToken();
8297 initSeq.push(this.isolateCoverGrammar(this.parseAssignmentExpression));
8298 }
8299 init = this.finalize(this.startNode(initStartToken), new Node.SequenceExpression(initSeq));
8300 }
8301 this.expect(';');
8302 }
8303 }
8304 }
8305 if (typeof left === 'undefined') {
8306 if (!this.match(';')) {
8307 test = this.parseExpression();
8308 }
8309 this.expect(';');
8310 if (!this.match(')')) {
8311 update = this.parseExpression();
8312 }
8313 }
8314 var body;
8315 if (!this.match(')') && this.config.tolerant) {
8316 this.tolerateUnexpectedToken(this.nextToken());
8317 body = this.finalize(this.createNode(), new Node.EmptyStatement());
8318 }
8319 else {
8320 this.expect(')');
8321 var previousInIteration = this.context.inIteration;
8322 this.context.inIteration = true;
8323 body = this.isolateCoverGrammar(this.parseStatement);
8324 this.context.inIteration = previousInIteration;
8325 }
8326 return (typeof left === 'undefined') ?
8327 this.finalize(node, new Node.ForStatement(init, test, update, body)) :
8328 forIn ? this.finalize(node, new Node.ForInStatement(left, right, body)) :
8329 this.finalize(node, new Node.ForOfStatement(left, right, body));
8330 };
8331 // https://tc39.github.io/ecma262/#sec-continue-statement
8332 Parser.prototype.parseContinueStatement = function () {
8333 var node = this.createNode();
8334 this.expectKeyword('continue');
8335 var label = null;
8336 if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) {
8337 var id = this.parseVariableIdentifier();
8338 label = id;
8339 var key = '$' + id.name;
8340 if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) {
8341 this.throwError(messages_1.Messages.UnknownLabel, id.name);
8342 }
8343 }
8344 this.consumeSemicolon();
8345 if (label === null && !this.context.inIteration) {
8346 this.throwError(messages_1.Messages.IllegalContinue);
8347 }
8348 return this.finalize(node, new Node.ContinueStatement(label));
8349 };
8350 // https://tc39.github.io/ecma262/#sec-break-statement
8351 Parser.prototype.parseBreakStatement = function () {
8352 var node = this.createNode();
8353 this.expectKeyword('break');
8354 var label = null;
8355 if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) {
8356 var id = this.parseVariableIdentifier();
8357 var key = '$' + id.name;
8358 if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) {
8359 this.throwError(messages_1.Messages.UnknownLabel, id.name);
8360 }
8361 label = id;
8362 }
8363 this.consumeSemicolon();
8364 if (label === null && !this.context.inIteration && !this.context.inSwitch) {
8365 this.throwError(messages_1.Messages.IllegalBreak);
8366 }
8367 return this.finalize(node, new Node.BreakStatement(label));
8368 };
8369 // https://tc39.github.io/ecma262/#sec-return-statement
8370 Parser.prototype.parseReturnStatement = function () {
8371 if (!this.context.inFunctionBody) {
8372 this.tolerateError(messages_1.Messages.IllegalReturn);
8373 }
8374 var node = this.createNode();
8375 this.expectKeyword('return');
8376 var hasArgument = !this.match(';') && !this.match('}') &&
8377 !this.hasLineTerminator && this.lookahead.type !== 2 /* EOF */;
8378 var argument = hasArgument ? this.parseExpression() : null;
8379 this.consumeSemicolon();
8380 return this.finalize(node, new Node.ReturnStatement(argument));
8381 };
8382 // https://tc39.github.io/ecma262/#sec-with-statement
8383 Parser.prototype.parseWithStatement = function () {
8384 if (this.context.strict) {
8385 this.tolerateError(messages_1.Messages.StrictModeWith);
8386 }
8387 var node = this.createNode();
8388 var body;
8389 this.expectKeyword('with');
8390 this.expect('(');
8391 var object = this.parseExpression();
8392 if (!this.match(')') && this.config.tolerant) {
8393 this.tolerateUnexpectedToken(this.nextToken());
8394 body = this.finalize(this.createNode(), new Node.EmptyStatement());
8395 }
8396 else {
8397 this.expect(')');
8398 body = this.parseStatement();
8399 }
8400 return this.finalize(node, new Node.WithStatement(object, body));
8401 };
8402 // https://tc39.github.io/ecma262/#sec-switch-statement
8403 Parser.prototype.parseSwitchCase = function () {
8404 var node = this.createNode();
8405 var test;
8406 if (this.matchKeyword('default')) {
8407 this.nextToken();
8408 test = null;
8409 }
8410 else {
8411 this.expectKeyword('case');
8412 test = this.parseExpression();
8413 }
8414 this.expect(':');
8415 var consequent = [];
8416 while (true) {
8417 if (this.match('}') || this.matchKeyword('default') || this.matchKeyword('case')) {
8418 break;
8419 }
8420 consequent.push(this.parseStatementListItem());
8421 }
8422 return this.finalize(node, new Node.SwitchCase(test, consequent));
8423 };
8424 Parser.prototype.parseSwitchStatement = function () {
8425 var node = this.createNode();
8426 this.expectKeyword('switch');
8427 this.expect('(');
8428 var discriminant = this.parseExpression();
8429 this.expect(')');
8430 var previousInSwitch = this.context.inSwitch;
8431 this.context.inSwitch = true;
8432 var cases = [];
8433 var defaultFound = false;
8434 this.expect('{');
8435 while (true) {
8436 if (this.match('}')) {
8437 break;
8438 }
8439 var clause = this.parseSwitchCase();
8440 if (clause.test === null) {
8441 if (defaultFound) {
8442 this.throwError(messages_1.Messages.MultipleDefaultsInSwitch);
8443 }
8444 defaultFound = true;
8445 }
8446 cases.push(clause);
8447 }
8448 this.expect('}');
8449 this.context.inSwitch = previousInSwitch;
8450 return this.finalize(node, new Node.SwitchStatement(discriminant, cases));
8451 };
8452 // https://tc39.github.io/ecma262/#sec-labelled-statements
8453 Parser.prototype.parseLabelledStatement = function () {
8454 var node = this.createNode();
8455 var expr = this.parseExpression();
8456 var statement;
8457 if ((expr.type === syntax_1.Syntax.Identifier) && this.match(':')) {
8458 this.nextToken();
8459 var id = expr;
8460 var key = '$' + id.name;
8461 if (Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) {
8462 this.throwError(messages_1.Messages.Redeclaration, 'Label', id.name);
8463 }
8464 this.context.labelSet[key] = true;
8465 var body = void 0;
8466 if (this.matchKeyword('class')) {
8467 this.tolerateUnexpectedToken(this.lookahead);
8468 body = this.parseClassDeclaration();
8469 }
8470 else if (this.matchKeyword('function')) {
8471 var token = this.lookahead;
8472 var declaration = this.parseFunctionDeclaration();
8473 if (this.context.strict) {
8474 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunction);
8475 }
8476 else if (declaration.generator) {
8477 this.tolerateUnexpectedToken(token, messages_1.Messages.GeneratorInLegacyContext);
8478 }
8479 body = declaration;
8480 }
8481 else {
8482 body = this.parseStatement();
8483 }
8484 delete this.context.labelSet[key];
8485 statement = new Node.LabeledStatement(id, body);
8486 }
8487 else {
8488 this.consumeSemicolon();
8489 statement = new Node.ExpressionStatement(expr);
8490 }
8491 return this.finalize(node, statement);
8492 };
8493 // https://tc39.github.io/ecma262/#sec-throw-statement
8494 Parser.prototype.parseThrowStatement = function () {
8495 var node = this.createNode();
8496 this.expectKeyword('throw');
8497 if (this.hasLineTerminator) {
8498 this.throwError(messages_1.Messages.NewlineAfterThrow);
8499 }
8500 var argument = this.parseExpression();
8501 this.consumeSemicolon();
8502 return this.finalize(node, new Node.ThrowStatement(argument));
8503 };
8504 // https://tc39.github.io/ecma262/#sec-try-statement
8505 Parser.prototype.parseCatchClause = function () {
8506 var node = this.createNode();
8507 this.expectKeyword('catch');
8508 this.expect('(');
8509 if (this.match(')')) {
8510 this.throwUnexpectedToken(this.lookahead);
8511 }
8512 var params = [];
8513 var param = this.parsePattern(params);
8514 var paramMap = {};
8515 for (var i = 0; i < params.length; i++) {
8516 var key = '$' + params[i].value;
8517 if (Object.prototype.hasOwnProperty.call(paramMap, key)) {
8518 this.tolerateError(messages_1.Messages.DuplicateBinding, params[i].value);
8519 }
8520 paramMap[key] = true;
8521 }
8522 if (this.context.strict && param.type === syntax_1.Syntax.Identifier) {
8523 if (this.scanner.isRestrictedWord(param.name)) {
8524 this.tolerateError(messages_1.Messages.StrictCatchVariable);
8525 }
8526 }
8527 this.expect(')');
8528 var body = this.parseBlock();
8529 return this.finalize(node, new Node.CatchClause(param, body));
8530 };
8531 Parser.prototype.parseFinallyClause = function () {
8532 this.expectKeyword('finally');
8533 return this.parseBlock();
8534 };
8535 Parser.prototype.parseTryStatement = function () {
8536 var node = this.createNode();
8537 this.expectKeyword('try');
8538 var block = this.parseBlock();
8539 var handler = this.matchKeyword('catch') ? this.parseCatchClause() : null;
8540 var finalizer = this.matchKeyword('finally') ? this.parseFinallyClause() : null;
8541 if (!handler && !finalizer) {
8542 this.throwError(messages_1.Messages.NoCatchOrFinally);
8543 }
8544 return this.finalize(node, new Node.TryStatement(block, handler, finalizer));
8545 };
8546 // https://tc39.github.io/ecma262/#sec-debugger-statement
8547 Parser.prototype.parseDebuggerStatement = function () {
8548 var node = this.createNode();
8549 this.expectKeyword('debugger');
8550 this.consumeSemicolon();
8551 return this.finalize(node, new Node.DebuggerStatement());
8552 };
8553 // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations
8554 Parser.prototype.parseStatement = function () {
8555 var statement;
8556 switch (this.lookahead.type) {
8557 case 1 /* BooleanLiteral */:
8558 case 5 /* NullLiteral */:
8559 case 6 /* NumericLiteral */:
8560 case 8 /* StringLiteral */:
8561 case 10 /* Template */:
8562 case 9 /* RegularExpression */:
8563 statement = this.parseExpressionStatement();
8564 break;
8565 case 7 /* Punctuator */:
8566 var value = this.lookahead.value;
8567 if (value === '{') {
8568 statement = this.parseBlock();
8569 }
8570 else if (value === '(') {
8571 statement = this.parseExpressionStatement();
8572 }
8573 else if (value === ';') {
8574 statement = this.parseEmptyStatement();
8575 }
8576 else {
8577 statement = this.parseExpressionStatement();
8578 }
8579 break;
8580 case 3 /* Identifier */:
8581 statement = this.matchAsyncFunction() ? this.parseFunctionDeclaration() : this.parseLabelledStatement();
8582 break;
8583 case 4 /* Keyword */:
8584 switch (this.lookahead.value) {
8585 case 'break':
8586 statement = this.parseBreakStatement();
8587 break;
8588 case 'continue':
8589 statement = this.parseContinueStatement();
8590 break;
8591 case 'debugger':
8592 statement = this.parseDebuggerStatement();
8593 break;
8594 case 'do':
8595 statement = this.parseDoWhileStatement();
8596 break;
8597 case 'for':
8598 statement = this.parseForStatement();
8599 break;
8600 case 'function':
8601 statement = this.parseFunctionDeclaration();
8602 break;
8603 case 'if':
8604 statement = this.parseIfStatement();
8605 break;
8606 case 'return':
8607 statement = this.parseReturnStatement();
8608 break;
8609 case 'switch':
8610 statement = this.parseSwitchStatement();
8611 break;
8612 case 'throw':
8613 statement = this.parseThrowStatement();
8614 break;
8615 case 'try':
8616 statement = this.parseTryStatement();
8617 break;
8618 case 'var':
8619 statement = this.parseVariableStatement();
8620 break;
8621 case 'while':
8622 statement = this.parseWhileStatement();
8623 break;
8624 case 'with':
8625 statement = this.parseWithStatement();
8626 break;
8627 default:
8628 statement = this.parseExpressionStatement();
8629 break;
8630 }
8631 break;
8632 default:
8633 statement = this.throwUnexpectedToken(this.lookahead);
8634 }
8635 return statement;
8636 };
8637 // https://tc39.github.io/ecma262/#sec-function-definitions
8638 Parser.prototype.parseFunctionSourceElements = function () {
8639 var node = this.createNode();
8640 this.expect('{');
8641 var body = this.parseDirectivePrologues();
8642 var previousLabelSet = this.context.labelSet;
8643 var previousInIteration = this.context.inIteration;
8644 var previousInSwitch = this.context.inSwitch;
8645 var previousInFunctionBody = this.context.inFunctionBody;
8646 this.context.labelSet = {};
8647 this.context.inIteration = false;
8648 this.context.inSwitch = false;
8649 this.context.inFunctionBody = true;
8650 while (this.lookahead.type !== 2 /* EOF */) {
8651 if (this.match('}')) {
8652 break;
8653 }
8654 body.push(this.parseStatementListItem());
8655 }
8656 this.expect('}');
8657 this.context.labelSet = previousLabelSet;
8658 this.context.inIteration = previousInIteration;
8659 this.context.inSwitch = previousInSwitch;
8660 this.context.inFunctionBody = previousInFunctionBody;
8661 return this.finalize(node, new Node.BlockStatement(body));
8662 };
8663 Parser.prototype.validateParam = function (options, param, name) {
8664 var key = '$' + name;
8665 if (this.context.strict) {
8666 if (this.scanner.isRestrictedWord(name)) {
8667 options.stricted = param;
8668 options.message = messages_1.Messages.StrictParamName;
8669 }
8670 if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
8671 options.stricted = param;
8672 options.message = messages_1.Messages.StrictParamDupe;
8673 }
8674 }
8675 else if (!options.firstRestricted) {
8676 if (this.scanner.isRestrictedWord(name)) {
8677 options.firstRestricted = param;
8678 options.message = messages_1.Messages.StrictParamName;
8679 }
8680 else if (this.scanner.isStrictModeReservedWord(name)) {
8681 options.firstRestricted = param;
8682 options.message = messages_1.Messages.StrictReservedWord;
8683 }
8684 else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
8685 options.stricted = param;
8686 options.message = messages_1.Messages.StrictParamDupe;
8687 }
8688 }
8689 /* istanbul ignore next */
8690 if (typeof Object.defineProperty === 'function') {
8691 Object.defineProperty(options.paramSet, key, { value: true, enumerable: true, writable: true, configurable: true });
8692 }
8693 else {
8694 options.paramSet[key] = true;
8695 }
8696 };
8697 Parser.prototype.parseRestElement = function (params) {
8698 var node = this.createNode();
8699 this.expect('...');
8700 var arg = this.parsePattern(params);
8701 if (this.match('=')) {
8702 this.throwError(messages_1.Messages.DefaultRestParameter);
8703 }
8704 if (!this.match(')')) {
8705 this.throwError(messages_1.Messages.ParameterAfterRestParameter);
8706 }
8707 return this.finalize(node, new Node.RestElement(arg));
8708 };
8709 Parser.prototype.parseFormalParameter = function (options) {
8710 var params = [];
8711 var param = this.match('...') ? this.parseRestElement(params) : this.parsePatternWithDefault(params);
8712 for (var i = 0; i < params.length; i++) {
8713 this.validateParam(options, params[i], params[i].value);
8714 }
8715 options.simple = options.simple && (param instanceof Node.Identifier);
8716 options.params.push(param);
8717 };
8718 Parser.prototype.parseFormalParameters = function (firstRestricted) {
8719 var options;
8720 options = {
8721 simple: true,
8722 params: [],
8723 firstRestricted: firstRestricted
8724 };
8725 this.expect('(');
8726 if (!this.match(')')) {
8727 options.paramSet = {};
8728 while (this.lookahead.type !== 2 /* EOF */) {
8729 this.parseFormalParameter(options);
8730 if (this.match(')')) {
8731 break;
8732 }
8733 this.expect(',');
8734 if (this.match(')')) {
8735 break;
8736 }
8737 }
8738 }
8739 this.expect(')');
8740 return {
8741 simple: options.simple,
8742 params: options.params,
8743 stricted: options.stricted,
8744 firstRestricted: options.firstRestricted,
8745 message: options.message
8746 };
8747 };
8748 Parser.prototype.matchAsyncFunction = function () {
8749 var match = this.matchContextualKeyword('async');
8750 if (match) {
8751 var state = this.scanner.saveState();
8752 this.scanner.scanComments();
8753 var next = this.scanner.lex();
8754 this.scanner.restoreState(state);
8755 match = (state.lineNumber === next.lineNumber) && (next.type === 4 /* Keyword */) && (next.value === 'function');
8756 }
8757 return match;
8758 };
8759 Parser.prototype.parseFunctionDeclaration = function (identifierIsOptional) {
8760 var node = this.createNode();
8761 var isAsync = this.matchContextualKeyword('async');
8762 if (isAsync) {
8763 this.nextToken();
8764 }
8765 this.expectKeyword('function');
8766 var isGenerator = isAsync ? false : this.match('*');
8767 if (isGenerator) {
8768 this.nextToken();
8769 }
8770 var message;
8771 var id = null;
8772 var firstRestricted = null;
8773 if (!identifierIsOptional || !this.match('(')) {
8774 var token = this.lookahead;
8775 id = this.parseVariableIdentifier();
8776 if (this.context.strict) {
8777 if (this.scanner.isRestrictedWord(token.value)) {
8778 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName);
8779 }
8780 }
8781 else {
8782 if (this.scanner.isRestrictedWord(token.value)) {
8783 firstRestricted = token;
8784 message = messages_1.Messages.StrictFunctionName;
8785 }
8786 else if (this.scanner.isStrictModeReservedWord(token.value)) {
8787 firstRestricted = token;
8788 message = messages_1.Messages.StrictReservedWord;
8789 }
8790 }
8791 }
8792 var previousAllowAwait = this.context.await;
8793 var previousAllowYield = this.context.allowYield;
8794 this.context.await = isAsync;
8795 this.context.allowYield = !isGenerator;
8796 var formalParameters = this.parseFormalParameters(firstRestricted);
8797 var params = formalParameters.params;
8798 var stricted = formalParameters.stricted;
8799 firstRestricted = formalParameters.firstRestricted;
8800 if (formalParameters.message) {
8801 message = formalParameters.message;
8802 }
8803 var previousStrict = this.context.strict;
8804 var previousAllowStrictDirective = this.context.allowStrictDirective;
8805 this.context.allowStrictDirective = formalParameters.simple;
8806 var body = this.parseFunctionSourceElements();
8807 if (this.context.strict && firstRestricted) {
8808 this.throwUnexpectedToken(firstRestricted, message);
8809 }
8810 if (this.context.strict && stricted) {
8811 this.tolerateUnexpectedToken(stricted, message);
8812 }
8813 this.context.strict = previousStrict;
8814 this.context.allowStrictDirective = previousAllowStrictDirective;
8815 this.context.await = previousAllowAwait;
8816 this.context.allowYield = previousAllowYield;
8817 return isAsync ? this.finalize(node, new Node.AsyncFunctionDeclaration(id, params, body)) :
8818 this.finalize(node, new Node.FunctionDeclaration(id, params, body, isGenerator));
8819 };
8820 Parser.prototype.parseFunctionExpression = function () {
8821 var node = this.createNode();
8822 var isAsync = this.matchContextualKeyword('async');
8823 if (isAsync) {
8824 this.nextToken();
8825 }
8826 this.expectKeyword('function');
8827 var isGenerator = isAsync ? false : this.match('*');
8828 if (isGenerator) {
8829 this.nextToken();
8830 }
8831 var message;
8832 var id = null;
8833 var firstRestricted;
8834 var previousAllowAwait = this.context.await;
8835 var previousAllowYield = this.context.allowYield;
8836 this.context.await = isAsync;
8837 this.context.allowYield = !isGenerator;
8838 if (!this.match('(')) {
8839 var token = this.lookahead;
8840 id = (!this.context.strict && !isGenerator && this.matchKeyword('yield')) ? this.parseIdentifierName() : this.parseVariableIdentifier();
8841 if (this.context.strict) {
8842 if (this.scanner.isRestrictedWord(token.value)) {
8843 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName);
8844 }
8845 }
8846 else {
8847 if (this.scanner.isRestrictedWord(token.value)) {
8848 firstRestricted = token;
8849 message = messages_1.Messages.StrictFunctionName;
8850 }
8851 else if (this.scanner.isStrictModeReservedWord(token.value)) {
8852 firstRestricted = token;
8853 message = messages_1.Messages.StrictReservedWord;
8854 }
8855 }
8856 }
8857 var formalParameters = this.parseFormalParameters(firstRestricted);
8858 var params = formalParameters.params;
8859 var stricted = formalParameters.stricted;
8860 firstRestricted = formalParameters.firstRestricted;
8861 if (formalParameters.message) {
8862 message = formalParameters.message;
8863 }
8864 var previousStrict = this.context.strict;
8865 var previousAllowStrictDirective = this.context.allowStrictDirective;
8866 this.context.allowStrictDirective = formalParameters.simple;
8867 var body = this.parseFunctionSourceElements();
8868 if (this.context.strict && firstRestricted) {
8869 this.throwUnexpectedToken(firstRestricted, message);
8870 }
8871 if (this.context.strict && stricted) {
8872 this.tolerateUnexpectedToken(stricted, message);
8873 }
8874 this.context.strict = previousStrict;
8875 this.context.allowStrictDirective = previousAllowStrictDirective;
8876 this.context.await = previousAllowAwait;
8877 this.context.allowYield = previousAllowYield;
8878 return isAsync ? this.finalize(node, new Node.AsyncFunctionExpression(id, params, body)) :
8879 this.finalize(node, new Node.FunctionExpression(id, params, body, isGenerator));
8880 };
8881 // https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive
8882 Parser.prototype.parseDirective = function () {
8883 var token = this.lookahead;
8884 var node = this.createNode();
8885 var expr = this.parseExpression();
8886 var directive = (expr.type === syntax_1.Syntax.Literal) ? this.getTokenRaw(token).slice(1, -1) : null;
8887 this.consumeSemicolon();
8888 return this.finalize(node, directive ? new Node.Directive(expr, directive) : new Node.ExpressionStatement(expr));
8889 };
8890 Parser.prototype.parseDirectivePrologues = function () {
8891 var firstRestricted = null;
8892 var body = [];
8893 while (true) {
8894 var token = this.lookahead;
8895 if (token.type !== 8 /* StringLiteral */) {
8896 break;
8897 }
8898 var statement = this.parseDirective();
8899 body.push(statement);
8900 var directive = statement.directive;
8901 if (typeof directive !== 'string') {
8902 break;
8903 }
8904 if (directive === 'use strict') {
8905 this.context.strict = true;
8906 if (firstRestricted) {
8907 this.tolerateUnexpectedToken(firstRestricted, messages_1.Messages.StrictOctalLiteral);
8908 }
8909 if (!this.context.allowStrictDirective) {
8910 this.tolerateUnexpectedToken(token, messages_1.Messages.IllegalLanguageModeDirective);
8911 }
8912 }
8913 else {
8914 if (!firstRestricted && token.octal) {
8915 firstRestricted = token;
8916 }
8917 }
8918 }
8919 return body;
8920 };
8921 // https://tc39.github.io/ecma262/#sec-method-definitions
8922 Parser.prototype.qualifiedPropertyName = function (token) {
8923 switch (token.type) {
8924 case 3 /* Identifier */:
8925 case 8 /* StringLiteral */:
8926 case 1 /* BooleanLiteral */:
8927 case 5 /* NullLiteral */:
8928 case 6 /* NumericLiteral */:
8929 case 4 /* Keyword */:
8930 return true;
8931 case 7 /* Punctuator */:
8932 return token.value === '[';
8933 default:
8934 break;
8935 }
8936 return false;
8937 };
8938 Parser.prototype.parseGetterMethod = function () {
8939 var node = this.createNode();
8940 var isGenerator = false;
8941 var previousAllowYield = this.context.allowYield;
8942 this.context.allowYield = false;
8943 var formalParameters = this.parseFormalParameters();
8944 if (formalParameters.params.length > 0) {
8945 this.tolerateError(messages_1.Messages.BadGetterArity);
8946 }
8947 var method = this.parsePropertyMethod(formalParameters);
8948 this.context.allowYield = previousAllowYield;
8949 return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator));
8950 };
8951 Parser.prototype.parseSetterMethod = function () {
8952 var node = this.createNode();
8953 var isGenerator = false;
8954 var previousAllowYield = this.context.allowYield;
8955 this.context.allowYield = false;
8956 var formalParameters = this.parseFormalParameters();
8957 if (formalParameters.params.length !== 1) {
8958 this.tolerateError(messages_1.Messages.BadSetterArity);
8959 }
8960 else if (formalParameters.params[0] instanceof Node.RestElement) {
8961 this.tolerateError(messages_1.Messages.BadSetterRestParameter);
8962 }
8963 var method = this.parsePropertyMethod(formalParameters);
8964 this.context.allowYield = previousAllowYield;
8965 return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator));
8966 };
8967 Parser.prototype.parseGeneratorMethod = function () {
8968 var node = this.createNode();
8969 var isGenerator = true;
8970 var previousAllowYield = this.context.allowYield;
8971 this.context.allowYield = true;
8972 var params = this.parseFormalParameters();
8973 this.context.allowYield = false;
8974 var method = this.parsePropertyMethod(params);
8975 this.context.allowYield = previousAllowYield;
8976 return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator));
8977 };
8978 // https://tc39.github.io/ecma262/#sec-generator-function-definitions
8979 Parser.prototype.isStartOfExpression = function () {
8980 var start = true;
8981 var value = this.lookahead.value;
8982 switch (this.lookahead.type) {
8983 case 7 /* Punctuator */:
8984 start = (value === '[') || (value === '(') || (value === '{') ||
8985 (value === '+') || (value === '-') ||
8986 (value === '!') || (value === '~') ||
8987 (value === '++') || (value === '--') ||
8988 (value === '/') || (value === '/='); // regular expression literal
8989 break;
8990 case 4 /* Keyword */:
8991 start = (value === 'class') || (value === 'delete') ||
8992 (value === 'function') || (value === 'let') || (value === 'new') ||
8993 (value === 'super') || (value === 'this') || (value === 'typeof') ||
8994 (value === 'void') || (value === 'yield');
8995 break;
8996 default:
8997 break;
8998 }
8999 return start;
9000 };
9001 Parser.prototype.parseYieldExpression = function () {
9002 var node = this.createNode();
9003 this.expectKeyword('yield');
9004 var argument = null;
9005 var delegate = false;
9006 if (!this.hasLineTerminator) {
9007 var previousAllowYield = this.context.allowYield;
9008 this.context.allowYield = false;
9009 delegate = this.match('*');
9010 if (delegate) {
9011 this.nextToken();
9012 argument = this.parseAssignmentExpression();
9013 }
9014 else if (this.isStartOfExpression()) {
9015 argument = this.parseAssignmentExpression();
9016 }
9017 this.context.allowYield = previousAllowYield;
9018 }
9019 return this.finalize(node, new Node.YieldExpression(argument, delegate));
9020 };
9021 // https://tc39.github.io/ecma262/#sec-class-definitions
9022 Parser.prototype.parseClassElement = function (hasConstructor) {
9023 var token = this.lookahead;
9024 var node = this.createNode();
9025 var kind = '';
9026 var key = null;
9027 var value = null;
9028 var computed = false;
9029 var method = false;
9030 var isStatic = false;
9031 var isAsync = false;
9032 if (this.match('*')) {
9033 this.nextToken();
9034 }
9035 else {
9036 computed = this.match('[');
9037 key = this.parseObjectPropertyKey();
9038 var id = key;
9039 if (id.name === 'static' && (this.qualifiedPropertyName(this.lookahead) || this.match('*'))) {
9040 token = this.lookahead;
9041 isStatic = true;
9042 computed = this.match('[');
9043 if (this.match('*')) {
9044 this.nextToken();
9045 }
9046 else {
9047 key = this.parseObjectPropertyKey();
9048 }
9049 }
9050 if ((token.type === 3 /* Identifier */) && !this.hasLineTerminator && (token.value === 'async')) {
9051 var punctuator = this.lookahead.value;
9052 if (punctuator !== ':' && punctuator !== '(' && punctuator !== '*') {
9053 isAsync = true;
9054 token = this.lookahead;
9055 key = this.parseObjectPropertyKey();
9056 if (token.type === 3 /* Identifier */) {
9057 if (token.value === 'get' || token.value === 'set') {
9058 this.tolerateUnexpectedToken(token);
9059 }
9060 else if (token.value === 'constructor') {
9061 this.tolerateUnexpectedToken(token, messages_1.Messages.ConstructorIsAsync);
9062 }
9063 }
9064 }
9065 }
9066 }
9067 var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead);
9068 if (token.type === 3 /* Identifier */) {
9069 if (token.value === 'get' && lookaheadPropertyKey) {
9070 kind = 'get';
9071 computed = this.match('[');
9072 key = this.parseObjectPropertyKey();
9073 this.context.allowYield = false;
9074 value = this.parseGetterMethod();
9075 }
9076 else if (token.value === 'set' && lookaheadPropertyKey) {
9077 kind = 'set';
9078 computed = this.match('[');
9079 key = this.parseObjectPropertyKey();
9080 value = this.parseSetterMethod();
9081 }
9082 }
9083 else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) {
9084 kind = 'init';
9085 computed = this.match('[');
9086 key = this.parseObjectPropertyKey();
9087 value = this.parseGeneratorMethod();
9088 method = true;
9089 }
9090 if (!kind && key && this.match('(')) {
9091 kind = 'init';
9092 value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction();
9093 method = true;
9094 }
9095 if (!kind) {
9096 this.throwUnexpectedToken(this.lookahead);
9097 }
9098 if (kind === 'init') {
9099 kind = 'method';
9100 }
9101 if (!computed) {
9102 if (isStatic && this.isPropertyKey(key, 'prototype')) {
9103 this.throwUnexpectedToken(token, messages_1.Messages.StaticPrototype);
9104 }
9105 if (!isStatic && this.isPropertyKey(key, 'constructor')) {
9106 if (kind !== 'method' || !method || (value && value.generator)) {
9107 this.throwUnexpectedToken(token, messages_1.Messages.ConstructorSpecialMethod);
9108 }
9109 if (hasConstructor.value) {
9110 this.throwUnexpectedToken(token, messages_1.Messages.DuplicateConstructor);
9111 }
9112 else {
9113 hasConstructor.value = true;
9114 }
9115 kind = 'constructor';
9116 }
9117 }
9118 return this.finalize(node, new Node.MethodDefinition(key, computed, value, kind, isStatic));
9119 };
9120 Parser.prototype.parseClassElementList = function () {
9121 var body = [];
9122 var hasConstructor = { value: false };
9123 this.expect('{');
9124 while (!this.match('}')) {
9125 if (this.match(';')) {
9126 this.nextToken();
9127 }
9128 else {
9129 body.push(this.parseClassElement(hasConstructor));
9130 }
9131 }
9132 this.expect('}');
9133 return body;
9134 };
9135 Parser.prototype.parseClassBody = function () {
9136 var node = this.createNode();
9137 var elementList = this.parseClassElementList();
9138 return this.finalize(node, new Node.ClassBody(elementList));
9139 };
9140 Parser.prototype.parseClassDeclaration = function (identifierIsOptional) {
9141 var node = this.createNode();
9142 var previousStrict = this.context.strict;
9143 this.context.strict = true;
9144 this.expectKeyword('class');
9145 var id = (identifierIsOptional && (this.lookahead.type !== 3 /* Identifier */)) ? null : this.parseVariableIdentifier();
9146 var superClass = null;
9147 if (this.matchKeyword('extends')) {
9148 this.nextToken();
9149 superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall);
9150 }
9151 var classBody = this.parseClassBody();
9152 this.context.strict = previousStrict;
9153 return this.finalize(node, new Node.ClassDeclaration(id, superClass, classBody));
9154 };
9155 Parser.prototype.parseClassExpression = function () {
9156 var node = this.createNode();
9157 var previousStrict = this.context.strict;
9158 this.context.strict = true;
9159 this.expectKeyword('class');
9160 var id = (this.lookahead.type === 3 /* Identifier */) ? this.parseVariableIdentifier() : null;
9161 var superClass = null;
9162 if (this.matchKeyword('extends')) {
9163 this.nextToken();
9164 superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall);
9165 }
9166 var classBody = this.parseClassBody();
9167 this.context.strict = previousStrict;
9168 return this.finalize(node, new Node.ClassExpression(id, superClass, classBody));
9169 };
9170 // https://tc39.github.io/ecma262/#sec-scripts
9171 // https://tc39.github.io/ecma262/#sec-modules
9172 Parser.prototype.parseModule = function () {
9173 this.context.strict = true;
9174 this.context.isModule = true;
9175 var node = this.createNode();
9176 var body = this.parseDirectivePrologues();
9177 while (this.lookahead.type !== 2 /* EOF */) {
9178 body.push(this.parseStatementListItem());
9179 }
9180 return this.finalize(node, new Node.Module(body));
9181 };
9182 Parser.prototype.parseScript = function () {
9183 var node = this.createNode();
9184 var body = this.parseDirectivePrologues();
9185 while (this.lookahead.type !== 2 /* EOF */) {
9186 body.push(this.parseStatementListItem());
9187 }
9188 return this.finalize(node, new Node.Script(body));
9189 };
9190 // https://tc39.github.io/ecma262/#sec-imports
9191 Parser.prototype.parseModuleSpecifier = function () {
9192 var node = this.createNode();
9193 if (this.lookahead.type !== 8 /* StringLiteral */) {
9194 this.throwError(messages_1.Messages.InvalidModuleSpecifier);
9195 }
9196 var token = this.nextToken();
9197 var raw = this.getTokenRaw(token);
9198 return this.finalize(node, new Node.Literal(token.value, raw));
9199 };
9200 // import {<foo as bar>} ...;
9201 Parser.prototype.parseImportSpecifier = function () {
9202 var node = this.createNode();
9203 var imported;
9204 var local;
9205 if (this.lookahead.type === 3 /* Identifier */) {
9206 imported = this.parseVariableIdentifier();
9207 local = imported;
9208 if (this.matchContextualKeyword('as')) {
9209 this.nextToken();
9210 local = this.parseVariableIdentifier();
9211 }
9212 }
9213 else {
9214 imported = this.parseIdentifierName();
9215 local = imported;
9216 if (this.matchContextualKeyword('as')) {
9217 this.nextToken();
9218 local = this.parseVariableIdentifier();
9219 }
9220 else {
9221 this.throwUnexpectedToken(this.nextToken());
9222 }
9223 }
9224 return this.finalize(node, new Node.ImportSpecifier(local, imported));
9225 };
9226 // {foo, bar as bas}
9227 Parser.prototype.parseNamedImports = function () {
9228 this.expect('{');
9229 var specifiers = [];
9230 while (!this.match('}')) {
9231 specifiers.push(this.parseImportSpecifier());
9232 if (!this.match('}')) {
9233 this.expect(',');
9234 }
9235 }
9236 this.expect('}');
9237 return specifiers;
9238 };
9239 // import <foo> ...;
9240 Parser.prototype.parseImportDefaultSpecifier = function () {
9241 var node = this.createNode();
9242 var local = this.parseIdentifierName();
9243 return this.finalize(node, new Node.ImportDefaultSpecifier(local));
9244 };
9245 // import <* as foo> ...;
9246 Parser.prototype.parseImportNamespaceSpecifier = function () {
9247 var node = this.createNode();
9248 this.expect('*');
9249 if (!this.matchContextualKeyword('as')) {
9250 this.throwError(messages_1.Messages.NoAsAfterImportNamespace);
9251 }
9252 this.nextToken();
9253 var local = this.parseIdentifierName();
9254 return this.finalize(node, new Node.ImportNamespaceSpecifier(local));
9255 };
9256 Parser.prototype.parseImportDeclaration = function () {
9257 if (this.context.inFunctionBody) {
9258 this.throwError(messages_1.Messages.IllegalImportDeclaration);
9259 }
9260 var node = this.createNode();
9261 this.expectKeyword('import');
9262 var src;
9263 var specifiers = [];
9264 if (this.lookahead.type === 8 /* StringLiteral */) {
9265 // import 'foo';
9266 src = this.parseModuleSpecifier();
9267 }
9268 else {
9269 if (this.match('{')) {
9270 // import {bar}
9271 specifiers = specifiers.concat(this.parseNamedImports());
9272 }
9273 else if (this.match('*')) {
9274 // import * as foo
9275 specifiers.push(this.parseImportNamespaceSpecifier());
9276 }
9277 else if (this.isIdentifierName(this.lookahead) && !this.matchKeyword('default')) {
9278 // import foo
9279 specifiers.push(this.parseImportDefaultSpecifier());
9280 if (this.match(',')) {
9281 this.nextToken();
9282 if (this.match('*')) {
9283 // import foo, * as foo
9284 specifiers.push(this.parseImportNamespaceSpecifier());
9285 }
9286 else if (this.match('{')) {
9287 // import foo, {bar}
9288 specifiers = specifiers.concat(this.parseNamedImports());
9289 }
9290 else {
9291 this.throwUnexpectedToken(this.lookahead);
9292 }
9293 }
9294 }
9295 else {
9296 this.throwUnexpectedToken(this.nextToken());
9297 }
9298 if (!this.matchContextualKeyword('from')) {
9299 var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause;
9300 this.throwError(message, this.lookahead.value);
9301 }
9302 this.nextToken();
9303 src = this.parseModuleSpecifier();
9304 }
9305 this.consumeSemicolon();
9306 return this.finalize(node, new Node.ImportDeclaration(specifiers, src));
9307 };
9308 // https://tc39.github.io/ecma262/#sec-exports
9309 Parser.prototype.parseExportSpecifier = function () {
9310 var node = this.createNode();
9311 var local = this.parseIdentifierName();
9312 var exported = local;
9313 if (this.matchContextualKeyword('as')) {
9314 this.nextToken();
9315 exported = this.parseIdentifierName();
9316 }
9317 return this.finalize(node, new Node.ExportSpecifier(local, exported));
9318 };
9319 Parser.prototype.parseExportDeclaration = function () {
9320 if (this.context.inFunctionBody) {
9321 this.throwError(messages_1.Messages.IllegalExportDeclaration);
9322 }
9323 var node = this.createNode();
9324 this.expectKeyword('export');
9325 var exportDeclaration;
9326 if (this.matchKeyword('default')) {
9327 // export default ...
9328 this.nextToken();
9329 if (this.matchKeyword('function')) {
9330 // export default function foo () {}
9331 // export default function () {}
9332 var declaration = this.parseFunctionDeclaration(true);
9333 exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration));
9334 }
9335 else if (this.matchKeyword('class')) {
9336 // export default class foo {}
9337 var declaration = this.parseClassDeclaration(true);
9338 exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration));
9339 }
9340 else if (this.matchContextualKeyword('async')) {
9341 // export default async function f () {}
9342 // export default async function () {}
9343 // export default async x => x
9344 var declaration = this.matchAsyncFunction() ? this.parseFunctionDeclaration(true) : this.parseAssignmentExpression();
9345 exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration));
9346 }
9347 else {
9348 if (this.matchContextualKeyword('from')) {
9349 this.throwError(messages_1.Messages.UnexpectedToken, this.lookahead.value);
9350 }
9351 // export default {};
9352 // export default [];
9353 // export default (1 + 2);
9354 var declaration = this.match('{') ? this.parseObjectInitializer() :
9355 this.match('[') ? this.parseArrayInitializer() : this.parseAssignmentExpression();
9356 this.consumeSemicolon();
9357 exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration));
9358 }
9359 }
9360 else if (this.match('*')) {
9361 // export * from 'foo';
9362 this.nextToken();
9363 if (!this.matchContextualKeyword('from')) {
9364 var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause;
9365 this.throwError(message, this.lookahead.value);
9366 }
9367 this.nextToken();
9368 var src = this.parseModuleSpecifier();
9369 this.consumeSemicolon();
9370 exportDeclaration = this.finalize(node, new Node.ExportAllDeclaration(src));
9371 }
9372 else if (this.lookahead.type === 4 /* Keyword */) {
9373 // export var f = 1;
9374 var declaration = void 0;
9375 switch (this.lookahead.value) {
9376 case 'let':
9377 case 'const':
9378 declaration = this.parseLexicalDeclaration({ inFor: false });
9379 break;
9380 case 'var':
9381 case 'class':
9382 case 'function':
9383 declaration = this.parseStatementListItem();
9384 break;
9385 default:
9386 this.throwUnexpectedToken(this.lookahead);
9387 }
9388 exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null));
9389 }
9390 else if (this.matchAsyncFunction()) {
9391 var declaration = this.parseFunctionDeclaration();
9392 exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null));
9393 }
9394 else {
9395 var specifiers = [];
9396 var source = null;
9397 var isExportFromIdentifier = false;
9398 this.expect('{');
9399 while (!this.match('}')) {
9400 isExportFromIdentifier = isExportFromIdentifier || this.matchKeyword('default');
9401 specifiers.push(this.parseExportSpecifier());
9402 if (!this.match('}')) {
9403 this.expect(',');
9404 }
9405 }
9406 this.expect('}');
9407 if (this.matchContextualKeyword('from')) {
9408 // export {default} from 'foo';
9409 // export {foo} from 'foo';
9410 this.nextToken();
9411 source = this.parseModuleSpecifier();
9412 this.consumeSemicolon();
9413 }
9414 else if (isExportFromIdentifier) {
9415 // export {default}; // missing fromClause
9416 var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause;
9417 this.throwError(message, this.lookahead.value);
9418 }
9419 else {
9420 // export {foo};
9421 this.consumeSemicolon();
9422 }
9423 exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(null, specifiers, source));
9424 }
9425 return exportDeclaration;
9426 };
9427 return Parser;
9428 }());
9429 exports.Parser = Parser;
9430
9431
9432/***/ },
9433/* 9 */
9434/***/ function(module, exports) {
9435
9436 "use strict";
9437 // Ensure the condition is true, otherwise throw an error.
9438 // This is only to have a better contract semantic, i.e. another safety net
9439 // to catch a logic error. The condition shall be fulfilled in normal case.
9440 // Do NOT use this to enforce a certain condition on any user input.
9441 Object.defineProperty(exports, "__esModule", { value: true });
9442 function assert(condition, message) {
9443 /* istanbul ignore if */
9444 if (!condition) {
9445 throw new Error('ASSERT: ' + message);
9446 }
9447 }
9448 exports.assert = assert;
9449
9450
9451/***/ },
9452/* 10 */
9453/***/ function(module, exports) {
9454
9455 "use strict";
9456 /* tslint:disable:max-classes-per-file */
9457 Object.defineProperty(exports, "__esModule", { value: true });
9458 var ErrorHandler = (function () {
9459 function ErrorHandler() {
9460 this.errors = [];
9461 this.tolerant = false;
9462 }
9463 ErrorHandler.prototype.recordError = function (error) {
9464 this.errors.push(error);
9465 };
9466 ErrorHandler.prototype.tolerate = function (error) {
9467 if (this.tolerant) {
9468 this.recordError(error);
9469 }
9470 else {
9471 throw error;
9472 }
9473 };
9474 ErrorHandler.prototype.constructError = function (msg, column) {
9475 var error = new Error(msg);
9476 try {
9477 throw error;
9478 }
9479 catch (base) {
9480 /* istanbul ignore else */
9481 if (Object.create && Object.defineProperty) {
9482 error = Object.create(base);
9483 Object.defineProperty(error, 'column', { value: column });
9484 }
9485 }
9486 /* istanbul ignore next */
9487 return error;
9488 };
9489 ErrorHandler.prototype.createError = function (index, line, col, description) {
9490 var msg = 'Line ' + line + ': ' + description;
9491 var error = this.constructError(msg, col);
9492 error.index = index;
9493 error.lineNumber = line;
9494 error.description = description;
9495 return error;
9496 };
9497 ErrorHandler.prototype.throwError = function (index, line, col, description) {
9498 throw this.createError(index, line, col, description);
9499 };
9500 ErrorHandler.prototype.tolerateError = function (index, line, col, description) {
9501 var error = this.createError(index, line, col, description);
9502 if (this.tolerant) {
9503 this.recordError(error);
9504 }
9505 else {
9506 throw error;
9507 }
9508 };
9509 return ErrorHandler;
9510 }());
9511 exports.ErrorHandler = ErrorHandler;
9512
9513
9514/***/ },
9515/* 11 */
9516/***/ function(module, exports) {
9517
9518 "use strict";
9519 Object.defineProperty(exports, "__esModule", { value: true });
9520 // Error messages should be identical to V8.
9521 exports.Messages = {
9522 BadGetterArity: 'Getter must not have any formal parameters',
9523 BadSetterArity: 'Setter must have exactly one formal parameter',
9524 BadSetterRestParameter: 'Setter function argument must not be a rest parameter',
9525 ConstructorIsAsync: 'Class constructor may not be an async method',
9526 ConstructorSpecialMethod: 'Class constructor may not be an accessor',
9527 DeclarationMissingInitializer: 'Missing initializer in %0 declaration',
9528 DefaultRestParameter: 'Unexpected token =',
9529 DuplicateBinding: 'Duplicate binding %0',
9530 DuplicateConstructor: 'A class may only have one constructor',
9531 DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
9532 ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer',
9533 GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts',
9534 IllegalBreak: 'Illegal break statement',
9535 IllegalContinue: 'Illegal continue statement',
9536 IllegalExportDeclaration: 'Unexpected token',
9537 IllegalImportDeclaration: 'Unexpected token',
9538 IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list',
9539 IllegalReturn: 'Illegal return statement',
9540 InvalidEscapedReservedWord: 'Keyword must not contain escaped characters',
9541 InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence',
9542 InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
9543 InvalidLHSInForIn: 'Invalid left-hand side in for-in',
9544 InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
9545 InvalidModuleSpecifier: 'Unexpected token',
9546 InvalidRegExp: 'Invalid regular expression',
9547 LetInLexicalBinding: 'let is disallowed as a lexically bound name',
9548 MissingFromClause: 'Unexpected token',
9549 MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
9550 NewlineAfterThrow: 'Illegal newline after throw',
9551 NoAsAfterImportNamespace: 'Unexpected token',
9552 NoCatchOrFinally: 'Missing catch or finally after try',
9553 ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
9554 Redeclaration: '%0 \'%1\' has already been declared',
9555 StaticPrototype: 'Classes may not have static property named prototype',
9556 StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
9557 StrictDelete: 'Delete of an unqualified identifier in strict mode.',
9558 StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block',
9559 StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
9560 StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
9561 StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
9562 StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
9563 StrictModeWith: 'Strict mode code may not include a with statement',
9564 StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
9565 StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
9566 StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
9567 StrictReservedWord: 'Use of future reserved word in strict mode',
9568 StrictVarName: 'Variable name may not be eval or arguments in strict mode',
9569 TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
9570 UnexpectedEOS: 'Unexpected end of input',
9571 UnexpectedIdentifier: 'Unexpected identifier',
9572 UnexpectedNumber: 'Unexpected number',
9573 UnexpectedReserved: 'Unexpected reserved word',
9574 UnexpectedString: 'Unexpected string',
9575 UnexpectedTemplate: 'Unexpected quasi %0',
9576 UnexpectedToken: 'Unexpected token %0',
9577 UnexpectedTokenIllegal: 'Unexpected token ILLEGAL',
9578 UnknownLabel: 'Undefined label \'%0\'',
9579 UnterminatedRegExp: 'Invalid regular expression: missing /'
9580 };
9581
9582
9583/***/ },
9584/* 12 */
9585/***/ function(module, exports, __webpack_require__) {
9586
9587 "use strict";
9588 Object.defineProperty(exports, "__esModule", { value: true });
9589 var assert_1 = __webpack_require__(9);
9590 var character_1 = __webpack_require__(4);
9591 var messages_1 = __webpack_require__(11);
9592 function hexValue(ch) {
9593 return '0123456789abcdef'.indexOf(ch.toLowerCase());
9594 }
9595 function octalValue(ch) {
9596 return '01234567'.indexOf(ch);
9597 }
9598 var Scanner = (function () {
9599 function Scanner(code, handler) {
9600 this.source = code;
9601 this.errorHandler = handler;
9602 this.trackComment = false;
9603 this.length = code.length;
9604 this.index = 0;
9605 this.lineNumber = (code.length > 0) ? 1 : 0;
9606 this.lineStart = 0;
9607 this.curlyStack = [];
9608 }
9609 Scanner.prototype.saveState = function () {
9610 return {
9611 index: this.index,
9612 lineNumber: this.lineNumber,
9613 lineStart: this.lineStart
9614 };
9615 };
9616 Scanner.prototype.restoreState = function (state) {
9617 this.index = state.index;
9618 this.lineNumber = state.lineNumber;
9619 this.lineStart = state.lineStart;
9620 };
9621 Scanner.prototype.eof = function () {
9622 return this.index >= this.length;
9623 };
9624 Scanner.prototype.throwUnexpectedToken = function (message) {
9625 if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; }
9626 return this.errorHandler.throwError(this.index, this.lineNumber, this.index - this.lineStart + 1, message);
9627 };
9628 Scanner.prototype.tolerateUnexpectedToken = function (message) {
9629 if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; }
9630 this.errorHandler.tolerateError(this.index, this.lineNumber, this.index - this.lineStart + 1, message);
9631 };
9632 // https://tc39.github.io/ecma262/#sec-comments
9633 Scanner.prototype.skipSingleLineComment = function (offset) {
9634 var comments = [];
9635 var start, loc;
9636 if (this.trackComment) {
9637 comments = [];
9638 start = this.index - offset;
9639 loc = {
9640 start: {
9641 line: this.lineNumber,
9642 column: this.index - this.lineStart - offset
9643 },
9644 end: {}
9645 };
9646 }
9647 while (!this.eof()) {
9648 var ch = this.source.charCodeAt(this.index);
9649 ++this.index;
9650 if (character_1.Character.isLineTerminator(ch)) {
9651 if (this.trackComment) {
9652 loc.end = {
9653 line: this.lineNumber,
9654 column: this.index - this.lineStart - 1
9655 };
9656 var entry = {
9657 multiLine: false,
9658 slice: [start + offset, this.index - 1],
9659 range: [start, this.index - 1],
9660 loc: loc
9661 };
9662 comments.push(entry);
9663 }
9664 if (ch === 13 && this.source.charCodeAt(this.index) === 10) {
9665 ++this.index;
9666 }
9667 ++this.lineNumber;
9668 this.lineStart = this.index;
9669 return comments;
9670 }
9671 }
9672 if (this.trackComment) {
9673 loc.end = {
9674 line: this.lineNumber,
9675 column: this.index - this.lineStart
9676 };
9677 var entry = {
9678 multiLine: false,
9679 slice: [start + offset, this.index],
9680 range: [start, this.index],
9681 loc: loc
9682 };
9683 comments.push(entry);
9684 }
9685 return comments;
9686 };
9687 Scanner.prototype.skipMultiLineComment = function () {
9688 var comments = [];
9689 var start, loc;
9690 if (this.trackComment) {
9691 comments = [];
9692 start = this.index - 2;
9693 loc = {
9694 start: {
9695 line: this.lineNumber,
9696 column: this.index - this.lineStart - 2
9697 },
9698 end: {}
9699 };
9700 }
9701 while (!this.eof()) {
9702 var ch = this.source.charCodeAt(this.index);
9703 if (character_1.Character.isLineTerminator(ch)) {
9704 if (ch === 0x0D && this.source.charCodeAt(this.index + 1) === 0x0A) {
9705 ++this.index;
9706 }
9707 ++this.lineNumber;
9708 ++this.index;
9709 this.lineStart = this.index;
9710 }
9711 else if (ch === 0x2A) {
9712 // Block comment ends with '*/'.
9713 if (this.source.charCodeAt(this.index + 1) === 0x2F) {
9714 this.index += 2;
9715 if (this.trackComment) {
9716 loc.end = {
9717 line: this.lineNumber,
9718 column: this.index - this.lineStart
9719 };
9720 var entry = {
9721 multiLine: true,
9722 slice: [start + 2, this.index - 2],
9723 range: [start, this.index],
9724 loc: loc
9725 };
9726 comments.push(entry);
9727 }
9728 return comments;
9729 }
9730 ++this.index;
9731 }
9732 else {
9733 ++this.index;
9734 }
9735 }
9736 // Ran off the end of the file - the whole thing is a comment
9737 if (this.trackComment) {
9738 loc.end = {
9739 line: this.lineNumber,
9740 column: this.index - this.lineStart
9741 };
9742 var entry = {
9743 multiLine: true,
9744 slice: [start + 2, this.index],
9745 range: [start, this.index],
9746 loc: loc
9747 };
9748 comments.push(entry);
9749 }
9750 this.tolerateUnexpectedToken();
9751 return comments;
9752 };
9753 Scanner.prototype.scanComments = function () {
9754 var comments;
9755 if (this.trackComment) {
9756 comments = [];
9757 }
9758 var start = (this.index === 0);
9759 while (!this.eof()) {
9760 var ch = this.source.charCodeAt(this.index);
9761 if (character_1.Character.isWhiteSpace(ch)) {
9762 ++this.index;
9763 }
9764 else if (character_1.Character.isLineTerminator(ch)) {
9765 ++this.index;
9766 if (ch === 0x0D && this.source.charCodeAt(this.index) === 0x0A) {
9767 ++this.index;
9768 }
9769 ++this.lineNumber;
9770 this.lineStart = this.index;
9771 start = true;
9772 }
9773 else if (ch === 0x2F) {
9774 ch = this.source.charCodeAt(this.index + 1);
9775 if (ch === 0x2F) {
9776 this.index += 2;
9777 var comment = this.skipSingleLineComment(2);
9778 if (this.trackComment) {
9779 comments = comments.concat(comment);
9780 }
9781 start = true;
9782 }
9783 else if (ch === 0x2A) {
9784 this.index += 2;
9785 var comment = this.skipMultiLineComment();
9786 if (this.trackComment) {
9787 comments = comments.concat(comment);
9788 }
9789 }
9790 else {
9791 break;
9792 }
9793 }
9794 else if (start && ch === 0x2D) {
9795 // U+003E is '>'
9796 if ((this.source.charCodeAt(this.index + 1) === 0x2D) && (this.source.charCodeAt(this.index + 2) === 0x3E)) {
9797 // '-->' is a single-line comment
9798 this.index += 3;
9799 var comment = this.skipSingleLineComment(3);
9800 if (this.trackComment) {
9801 comments = comments.concat(comment);
9802 }
9803 }
9804 else {
9805 break;
9806 }
9807 }
9808 else if (ch === 0x3C) {
9809 if (this.source.slice(this.index + 1, this.index + 4) === '!--') {
9810 this.index += 4; // `<!--`
9811 var comment = this.skipSingleLineComment(4);
9812 if (this.trackComment) {
9813 comments = comments.concat(comment);
9814 }
9815 }
9816 else {
9817 break;
9818 }
9819 }
9820 else {
9821 break;
9822 }
9823 }
9824 return comments;
9825 };
9826 // https://tc39.github.io/ecma262/#sec-future-reserved-words
9827 Scanner.prototype.isFutureReservedWord = function (id) {
9828 switch (id) {
9829 case 'enum':
9830 case 'export':
9831 case 'import':
9832 case 'super':
9833 return true;
9834 default:
9835 return false;
9836 }
9837 };
9838 Scanner.prototype.isStrictModeReservedWord = function (id) {
9839 switch (id) {
9840 case 'implements':
9841 case 'interface':
9842 case 'package':
9843 case 'private':
9844 case 'protected':
9845 case 'public':
9846 case 'static':
9847 case 'yield':
9848 case 'let':
9849 return true;
9850 default:
9851 return false;
9852 }
9853 };
9854 Scanner.prototype.isRestrictedWord = function (id) {
9855 return id === 'eval' || id === 'arguments';
9856 };
9857 // https://tc39.github.io/ecma262/#sec-keywords
9858 Scanner.prototype.isKeyword = function (id) {
9859 switch (id.length) {
9860 case 2:
9861 return (id === 'if') || (id === 'in') || (id === 'do');
9862 case 3:
9863 return (id === 'var') || (id === 'for') || (id === 'new') ||
9864 (id === 'try') || (id === 'let');
9865 case 4:
9866 return (id === 'this') || (id === 'else') || (id === 'case') ||
9867 (id === 'void') || (id === 'with') || (id === 'enum');
9868 case 5:
9869 return (id === 'while') || (id === 'break') || (id === 'catch') ||
9870 (id === 'throw') || (id === 'const') || (id === 'yield') ||
9871 (id === 'class') || (id === 'super');
9872 case 6:
9873 return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
9874 (id === 'switch') || (id === 'export') || (id === 'import');
9875 case 7:
9876 return (id === 'default') || (id === 'finally') || (id === 'extends');
9877 case 8:
9878 return (id === 'function') || (id === 'continue') || (id === 'debugger');
9879 case 10:
9880 return (id === 'instanceof');
9881 default:
9882 return false;
9883 }
9884 };
9885 Scanner.prototype.codePointAt = function (i) {
9886 var cp = this.source.charCodeAt(i);
9887 if (cp >= 0xD800 && cp <= 0xDBFF) {
9888 var second = this.source.charCodeAt(i + 1);
9889 if (second >= 0xDC00 && second <= 0xDFFF) {
9890 var first = cp;
9891 cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
9892 }
9893 }
9894 return cp;
9895 };
9896 Scanner.prototype.scanHexEscape = function (prefix) {
9897 var len = (prefix === 'u') ? 4 : 2;
9898 var code = 0;
9899 for (var i = 0; i < len; ++i) {
9900 if (!this.eof() && character_1.Character.isHexDigit(this.source.charCodeAt(this.index))) {
9901 code = code * 16 + hexValue(this.source[this.index++]);
9902 }
9903 else {
9904 return null;
9905 }
9906 }
9907 return String.fromCharCode(code);
9908 };
9909 Scanner.prototype.scanUnicodeCodePointEscape = function () {
9910 var ch = this.source[this.index];
9911 var code = 0;
9912 // At least, one hex digit is required.
9913 if (ch === '}') {
9914 this.throwUnexpectedToken();
9915 }
9916 while (!this.eof()) {
9917 ch = this.source[this.index++];
9918 if (!character_1.Character.isHexDigit(ch.charCodeAt(0))) {
9919 break;
9920 }
9921 code = code * 16 + hexValue(ch);
9922 }
9923 if (code > 0x10FFFF || ch !== '}') {
9924 this.throwUnexpectedToken();
9925 }
9926 return character_1.Character.fromCodePoint(code);
9927 };
9928 Scanner.prototype.getIdentifier = function () {
9929 var start = this.index++;
9930 while (!this.eof()) {
9931 var ch = this.source.charCodeAt(this.index);
9932 if (ch === 0x5C) {
9933 // Blackslash (U+005C) marks Unicode escape sequence.
9934 this.index = start;
9935 return this.getComplexIdentifier();
9936 }
9937 else if (ch >= 0xD800 && ch < 0xDFFF) {
9938 // Need to handle surrogate pairs.
9939 this.index = start;
9940 return this.getComplexIdentifier();
9941 }
9942 if (character_1.Character.isIdentifierPart(ch)) {
9943 ++this.index;
9944 }
9945 else {
9946 break;
9947 }
9948 }
9949 return this.source.slice(start, this.index);
9950 };
9951 Scanner.prototype.getComplexIdentifier = function () {
9952 var cp = this.codePointAt(this.index);
9953 var id = character_1.Character.fromCodePoint(cp);
9954 this.index += id.length;
9955 // '\u' (U+005C, U+0075) denotes an escaped character.
9956 var ch;
9957 if (cp === 0x5C) {
9958 if (this.source.charCodeAt(this.index) !== 0x75) {
9959 this.throwUnexpectedToken();
9960 }
9961 ++this.index;
9962 if (this.source[this.index] === '{') {
9963 ++this.index;
9964 ch = this.scanUnicodeCodePointEscape();
9965 }
9966 else {
9967 ch = this.scanHexEscape('u');
9968 if (ch === null || ch === '\\' || !character_1.Character.isIdentifierStart(ch.charCodeAt(0))) {
9969 this.throwUnexpectedToken();
9970 }
9971 }
9972 id = ch;
9973 }
9974 while (!this.eof()) {
9975 cp = this.codePointAt(this.index);
9976 if (!character_1.Character.isIdentifierPart(cp)) {
9977 break;
9978 }
9979 ch = character_1.Character.fromCodePoint(cp);
9980 id += ch;
9981 this.index += ch.length;
9982 // '\u' (U+005C, U+0075) denotes an escaped character.
9983 if (cp === 0x5C) {
9984 id = id.substr(0, id.length - 1);
9985 if (this.source.charCodeAt(this.index) !== 0x75) {
9986 this.throwUnexpectedToken();
9987 }
9988 ++this.index;
9989 if (this.source[this.index] === '{') {
9990 ++this.index;
9991 ch = this.scanUnicodeCodePointEscape();
9992 }
9993 else {
9994 ch = this.scanHexEscape('u');
9995 if (ch === null || ch === '\\' || !character_1.Character.isIdentifierPart(ch.charCodeAt(0))) {
9996 this.throwUnexpectedToken();
9997 }
9998 }
9999 id += ch;
10000 }
10001 }
10002 return id;
10003 };
10004 Scanner.prototype.octalToDecimal = function (ch) {
10005 // \0 is not octal escape sequence
10006 var octal = (ch !== '0');
10007 var code = octalValue(ch);
10008 if (!this.eof() && character_1.Character.isOctalDigit(this.source.charCodeAt(this.index))) {
10009 octal = true;
10010 code = code * 8 + octalValue(this.source[this.index++]);
10011 // 3 digits are only allowed when string starts
10012 // with 0, 1, 2, 3
10013 if ('0123'.indexOf(ch) >= 0 && !this.eof() && character_1.Character.isOctalDigit(this.source.charCodeAt(this.index))) {
10014 code = code * 8 + octalValue(this.source[this.index++]);
10015 }
10016 }
10017 return {
10018 code: code,
10019 octal: octal
10020 };
10021 };
10022 // https://tc39.github.io/ecma262/#sec-names-and-keywords
10023 Scanner.prototype.scanIdentifier = function () {
10024 var type;
10025 var start = this.index;
10026 // Backslash (U+005C) starts an escaped character.
10027 var id = (this.source.charCodeAt(start) === 0x5C) ? this.getComplexIdentifier() : this.getIdentifier();
10028 // There is no keyword or literal with only one character.
10029 // Thus, it must be an identifier.
10030 if (id.length === 1) {
10031 type = 3 /* Identifier */;
10032 }
10033 else if (this.isKeyword(id)) {
10034 type = 4 /* Keyword */;
10035 }
10036 else if (id === 'null') {
10037 type = 5 /* NullLiteral */;
10038 }
10039 else if (id === 'true' || id === 'false') {
10040 type = 1 /* BooleanLiteral */;
10041 }
10042 else {
10043 type = 3 /* Identifier */;
10044 }
10045 if (type !== 3 /* Identifier */ && (start + id.length !== this.index)) {
10046 var restore = this.index;
10047 this.index = start;
10048 this.tolerateUnexpectedToken(messages_1.Messages.InvalidEscapedReservedWord);
10049 this.index = restore;
10050 }
10051 return {
10052 type: type,
10053 value: id,
10054 lineNumber: this.lineNumber,
10055 lineStart: this.lineStart,
10056 start: start,
10057 end: this.index
10058 };
10059 };
10060 // https://tc39.github.io/ecma262/#sec-punctuators
10061 Scanner.prototype.scanPunctuator = function () {
10062 var start = this.index;
10063 // Check for most common single-character punctuators.
10064 var str = this.source[this.index];
10065 switch (str) {
10066 case '(':
10067 case '{':
10068 if (str === '{') {
10069 this.curlyStack.push('{');
10070 }
10071 ++this.index;
10072 break;
10073 case '.':
10074 ++this.index;
10075 if (this.source[this.index] === '.' && this.source[this.index + 1] === '.') {
10076 // Spread operator: ...
10077 this.index += 2;
10078 str = '...';
10079 }
10080 break;
10081 case '}':
10082 ++this.index;
10083 this.curlyStack.pop();
10084 break;
10085 case ')':
10086 case ';':
10087 case ',':
10088 case '[':
10089 case ']':
10090 case ':':
10091 case '?':
10092 case '~':
10093 ++this.index;
10094 break;
10095 default:
10096 // 4-character punctuator.
10097 str = this.source.substr(this.index, 4);
10098 if (str === '>>>=') {
10099 this.index += 4;
10100 }
10101 else {
10102 // 3-character punctuators.
10103 str = str.substr(0, 3);
10104 if (str === '===' || str === '!==' || str === '>>>' ||
10105 str === '<<=' || str === '>>=' || str === '**=') {
10106 this.index += 3;
10107 }
10108 else {
10109 // 2-character punctuators.
10110 str = str.substr(0, 2);
10111 if (str === '&&' || str === '||' || str === '==' || str === '!=' ||
10112 str === '+=' || str === '-=' || str === '*=' || str === '/=' ||
10113 str === '++' || str === '--' || str === '<<' || str === '>>' ||
10114 str === '&=' || str === '|=' || str === '^=' || str === '%=' ||
10115 str === '<=' || str === '>=' || str === '=>' || str === '**') {
10116 this.index += 2;
10117 }
10118 else {
10119 // 1-character punctuators.
10120 str = this.source[this.index];
10121 if ('<>=!+-*%&|^/'.indexOf(str) >= 0) {
10122 ++this.index;
10123 }
10124 }
10125 }
10126 }
10127 }
10128 if (this.index === start) {
10129 this.throwUnexpectedToken();
10130 }
10131 return {
10132 type: 7 /* Punctuator */,
10133 value: str,
10134 lineNumber: this.lineNumber,
10135 lineStart: this.lineStart,
10136 start: start,
10137 end: this.index
10138 };
10139 };
10140 // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
10141 Scanner.prototype.scanHexLiteral = function (start) {
10142 var num = '';
10143 while (!this.eof()) {
10144 if (!character_1.Character.isHexDigit(this.source.charCodeAt(this.index))) {
10145 break;
10146 }
10147 num += this.source[this.index++];
10148 }
10149 if (num.length === 0) {
10150 this.throwUnexpectedToken();
10151 }
10152 if (character_1.Character.isIdentifierStart(this.source.charCodeAt(this.index))) {
10153 this.throwUnexpectedToken();
10154 }
10155 return {
10156 type: 6 /* NumericLiteral */,
10157 value: parseInt('0x' + num, 16),
10158 lineNumber: this.lineNumber,
10159 lineStart: this.lineStart,
10160 start: start,
10161 end: this.index
10162 };
10163 };
10164 Scanner.prototype.scanBinaryLiteral = function (start) {
10165 var num = '';
10166 var ch;
10167 while (!this.eof()) {
10168 ch = this.source[this.index];
10169 if (ch !== '0' && ch !== '1') {
10170 break;
10171 }
10172 num += this.source[this.index++];
10173 }
10174 if (num.length === 0) {
10175 // only 0b or 0B
10176 this.throwUnexpectedToken();
10177 }
10178 if (!this.eof()) {
10179 ch = this.source.charCodeAt(this.index);
10180 /* istanbul ignore else */
10181 if (character_1.Character.isIdentifierStart(ch) || character_1.Character.isDecimalDigit(ch)) {
10182 this.throwUnexpectedToken();
10183 }
10184 }
10185 return {
10186 type: 6 /* NumericLiteral */,
10187 value: parseInt(num, 2),
10188 lineNumber: this.lineNumber,
10189 lineStart: this.lineStart,
10190 start: start,
10191 end: this.index
10192 };
10193 };
10194 Scanner.prototype.scanOctalLiteral = function (prefix, start) {
10195 var num = '';
10196 var octal = false;
10197 if (character_1.Character.isOctalDigit(prefix.charCodeAt(0))) {
10198 octal = true;
10199 num = '0' + this.source[this.index++];
10200 }
10201 else {
10202 ++this.index;
10203 }
10204 while (!this.eof()) {
10205 if (!character_1.Character.isOctalDigit(this.source.charCodeAt(this.index))) {
10206 break;
10207 }
10208 num += this.source[this.index++];
10209 }
10210 if (!octal && num.length === 0) {
10211 // only 0o or 0O
10212 this.throwUnexpectedToken();
10213 }
10214 if (character_1.Character.isIdentifierStart(this.source.charCodeAt(this.index)) || character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
10215 this.throwUnexpectedToken();
10216 }
10217 return {
10218 type: 6 /* NumericLiteral */,
10219 value: parseInt(num, 8),
10220 octal: octal,
10221 lineNumber: this.lineNumber,
10222 lineStart: this.lineStart,
10223 start: start,
10224 end: this.index
10225 };
10226 };
10227 Scanner.prototype.isImplicitOctalLiteral = function () {
10228 // Implicit octal, unless there is a non-octal digit.
10229 // (Annex B.1.1 on Numeric Literals)
10230 for (var i = this.index + 1; i < this.length; ++i) {
10231 var ch = this.source[i];
10232 if (ch === '8' || ch === '9') {
10233 return false;
10234 }
10235 if (!character_1.Character.isOctalDigit(ch.charCodeAt(0))) {
10236 return true;
10237 }
10238 }
10239 return true;
10240 };
10241 Scanner.prototype.scanNumericLiteral = function () {
10242 var start = this.index;
10243 var ch = this.source[start];
10244 assert_1.assert(character_1.Character.isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), 'Numeric literal must start with a decimal digit or a decimal point');
10245 var num = '';
10246 if (ch !== '.') {
10247 num = this.source[this.index++];
10248 ch = this.source[this.index];
10249 // Hex number starts with '0x'.
10250 // Octal number starts with '0'.
10251 // Octal number in ES6 starts with '0o'.
10252 // Binary number in ES6 starts with '0b'.
10253 if (num === '0') {
10254 if (ch === 'x' || ch === 'X') {
10255 ++this.index;
10256 return this.scanHexLiteral(start);
10257 }
10258 if (ch === 'b' || ch === 'B') {
10259 ++this.index;
10260 return this.scanBinaryLiteral(start);
10261 }
10262 if (ch === 'o' || ch === 'O') {
10263 return this.scanOctalLiteral(ch, start);
10264 }
10265 if (ch && character_1.Character.isOctalDigit(ch.charCodeAt(0))) {
10266 if (this.isImplicitOctalLiteral()) {
10267 return this.scanOctalLiteral(ch, start);
10268 }
10269 }
10270 }
10271 while (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
10272 num += this.source[this.index++];
10273 }
10274 ch = this.source[this.index];
10275 }
10276 if (ch === '.') {
10277 num += this.source[this.index++];
10278 while (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
10279 num += this.source[this.index++];
10280 }
10281 ch = this.source[this.index];
10282 }
10283 if (ch === 'e' || ch === 'E') {
10284 num += this.source[this.index++];
10285 ch = this.source[this.index];
10286 if (ch === '+' || ch === '-') {
10287 num += this.source[this.index++];
10288 }
10289 if (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
10290 while (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
10291 num += this.source[this.index++];
10292 }
10293 }
10294 else {
10295 this.throwUnexpectedToken();
10296 }
10297 }
10298 if (character_1.Character.isIdentifierStart(this.source.charCodeAt(this.index))) {
10299 this.throwUnexpectedToken();
10300 }
10301 return {
10302 type: 6 /* NumericLiteral */,
10303 value: parseFloat(num),
10304 lineNumber: this.lineNumber,
10305 lineStart: this.lineStart,
10306 start: start,
10307 end: this.index
10308 };
10309 };
10310 // https://tc39.github.io/ecma262/#sec-literals-string-literals
10311 Scanner.prototype.scanStringLiteral = function () {
10312 var start = this.index;
10313 var quote = this.source[start];
10314 assert_1.assert((quote === '\'' || quote === '"'), 'String literal must starts with a quote');
10315 ++this.index;
10316 var octal = false;
10317 var str = '';
10318 while (!this.eof()) {
10319 var ch = this.source[this.index++];
10320 if (ch === quote) {
10321 quote = '';
10322 break;
10323 }
10324 else if (ch === '\\') {
10325 ch = this.source[this.index++];
10326 if (!ch || !character_1.Character.isLineTerminator(ch.charCodeAt(0))) {
10327 switch (ch) {
10328 case 'u':
10329 if (this.source[this.index] === '{') {
10330 ++this.index;
10331 str += this.scanUnicodeCodePointEscape();
10332 }
10333 else {
10334 var unescaped_1 = this.scanHexEscape(ch);
10335 if (unescaped_1 === null) {
10336 this.throwUnexpectedToken();
10337 }
10338 str += unescaped_1;
10339 }
10340 break;
10341 case 'x':
10342 var unescaped = this.scanHexEscape(ch);
10343 if (unescaped === null) {
10344 this.throwUnexpectedToken(messages_1.Messages.InvalidHexEscapeSequence);
10345 }
10346 str += unescaped;
10347 break;
10348 case 'n':
10349 str += '\n';
10350 break;
10351 case 'r':
10352 str += '\r';
10353 break;
10354 case 't':
10355 str += '\t';
10356 break;
10357 case 'b':
10358 str += '\b';
10359 break;
10360 case 'f':
10361 str += '\f';
10362 break;
10363 case 'v':
10364 str += '\x0B';
10365 break;
10366 case '8':
10367 case '9':
10368 str += ch;
10369 this.tolerateUnexpectedToken();
10370 break;
10371 default:
10372 if (ch && character_1.Character.isOctalDigit(ch.charCodeAt(0))) {
10373 var octToDec = this.octalToDecimal(ch);
10374 octal = octToDec.octal || octal;
10375 str += String.fromCharCode(octToDec.code);
10376 }
10377 else {
10378 str += ch;
10379 }
10380 break;
10381 }
10382 }
10383 else {
10384 ++this.lineNumber;
10385 if (ch === '\r' && this.source[this.index] === '\n') {
10386 ++this.index;
10387 }
10388 this.lineStart = this.index;
10389 }
10390 }
10391 else if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) {
10392 break;
10393 }
10394 else {
10395 str += ch;
10396 }
10397 }
10398 if (quote !== '') {
10399 this.index = start;
10400 this.throwUnexpectedToken();
10401 }
10402 return {
10403 type: 8 /* StringLiteral */,
10404 value: str,
10405 octal: octal,
10406 lineNumber: this.lineNumber,
10407 lineStart: this.lineStart,
10408 start: start,
10409 end: this.index
10410 };
10411 };
10412 // https://tc39.github.io/ecma262/#sec-template-literal-lexical-components
10413 Scanner.prototype.scanTemplate = function () {
10414 var cooked = '';
10415 var terminated = false;
10416 var start = this.index;
10417 var head = (this.source[start] === '`');
10418 var tail = false;
10419 var rawOffset = 2;
10420 ++this.index;
10421 while (!this.eof()) {
10422 var ch = this.source[this.index++];
10423 if (ch === '`') {
10424 rawOffset = 1;
10425 tail = true;
10426 terminated = true;
10427 break;
10428 }
10429 else if (ch === '$') {
10430 if (this.source[this.index] === '{') {
10431 this.curlyStack.push('${');
10432 ++this.index;
10433 terminated = true;
10434 break;
10435 }
10436 cooked += ch;
10437 }
10438 else if (ch === '\\') {
10439 ch = this.source[this.index++];
10440 if (!character_1.Character.isLineTerminator(ch.charCodeAt(0))) {
10441 switch (ch) {
10442 case 'n':
10443 cooked += '\n';
10444 break;
10445 case 'r':
10446 cooked += '\r';
10447 break;
10448 case 't':
10449 cooked += '\t';
10450 break;
10451 case 'u':
10452 if (this.source[this.index] === '{') {
10453 ++this.index;
10454 cooked += this.scanUnicodeCodePointEscape();
10455 }
10456 else {
10457 var restore = this.index;
10458 var unescaped_2 = this.scanHexEscape(ch);
10459 if (unescaped_2 !== null) {
10460 cooked += unescaped_2;
10461 }
10462 else {
10463 this.index = restore;
10464 cooked += ch;
10465 }
10466 }
10467 break;
10468 case 'x':
10469 var unescaped = this.scanHexEscape(ch);
10470 if (unescaped === null) {
10471 this.throwUnexpectedToken(messages_1.Messages.InvalidHexEscapeSequence);
10472 }
10473 cooked += unescaped;
10474 break;
10475 case 'b':
10476 cooked += '\b';
10477 break;
10478 case 'f':
10479 cooked += '\f';
10480 break;
10481 case 'v':
10482 cooked += '\v';
10483 break;
10484 default:
10485 if (ch === '0') {
10486 if (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
10487 // Illegal: \01 \02 and so on
10488 this.throwUnexpectedToken(messages_1.Messages.TemplateOctalLiteral);
10489 }
10490 cooked += '\0';
10491 }
10492 else if (character_1.Character.isOctalDigit(ch.charCodeAt(0))) {
10493 // Illegal: \1 \2
10494 this.throwUnexpectedToken(messages_1.Messages.TemplateOctalLiteral);
10495 }
10496 else {
10497 cooked += ch;
10498 }
10499 break;
10500 }
10501 }
10502 else {
10503 ++this.lineNumber;
10504 if (ch === '\r' && this.source[this.index] === '\n') {
10505 ++this.index;
10506 }
10507 this.lineStart = this.index;
10508 }
10509 }
10510 else if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) {
10511 ++this.lineNumber;
10512 if (ch === '\r' && this.source[this.index] === '\n') {
10513 ++this.index;
10514 }
10515 this.lineStart = this.index;
10516 cooked += '\n';
10517 }
10518 else {
10519 cooked += ch;
10520 }
10521 }
10522 if (!terminated) {
10523 this.throwUnexpectedToken();
10524 }
10525 if (!head) {
10526 this.curlyStack.pop();
10527 }
10528 return {
10529 type: 10 /* Template */,
10530 value: this.source.slice(start + 1, this.index - rawOffset),
10531 cooked: cooked,
10532 head: head,
10533 tail: tail,
10534 lineNumber: this.lineNumber,
10535 lineStart: this.lineStart,
10536 start: start,
10537 end: this.index
10538 };
10539 };
10540 // https://tc39.github.io/ecma262/#sec-literals-regular-expression-literals
10541 Scanner.prototype.testRegExp = function (pattern, flags) {
10542 // The BMP character to use as a replacement for astral symbols when
10543 // translating an ES6 "u"-flagged pattern to an ES5-compatible
10544 // approximation.
10545 // Note: replacing with '\uFFFF' enables false positives in unlikely
10546 // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid
10547 // pattern that would not be detected by this substitution.
10548 var astralSubstitute = '\uFFFF';
10549 var tmp = pattern;
10550 var self = this;
10551 if (flags.indexOf('u') >= 0) {
10552 tmp = tmp
10553 .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) {
10554 var codePoint = parseInt($1 || $2, 16);
10555 if (codePoint > 0x10FFFF) {
10556 self.throwUnexpectedToken(messages_1.Messages.InvalidRegExp);
10557 }
10558 if (codePoint <= 0xFFFF) {
10559 return String.fromCharCode(codePoint);
10560 }
10561 return astralSubstitute;
10562 })
10563 .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, astralSubstitute);
10564 }
10565 // First, detect invalid regular expressions.
10566 try {
10567 RegExp(tmp);
10568 }
10569 catch (e) {
10570 this.throwUnexpectedToken(messages_1.Messages.InvalidRegExp);
10571 }
10572 // Return a regular expression object for this pattern-flag pair, or
10573 // `null` in case the current environment doesn't support the flags it
10574 // uses.
10575 try {
10576 return new RegExp(pattern, flags);
10577 }
10578 catch (exception) {
10579 /* istanbul ignore next */
10580 return null;
10581 }
10582 };
10583 Scanner.prototype.scanRegExpBody = function () {
10584 var ch = this.source[this.index];
10585 assert_1.assert(ch === '/', 'Regular expression literal must start with a slash');
10586 var str = this.source[this.index++];
10587 var classMarker = false;
10588 var terminated = false;
10589 while (!this.eof()) {
10590 ch = this.source[this.index++];
10591 str += ch;
10592 if (ch === '\\') {
10593 ch = this.source[this.index++];
10594 // https://tc39.github.io/ecma262/#sec-literals-regular-expression-literals
10595 if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) {
10596 this.throwUnexpectedToken(messages_1.Messages.UnterminatedRegExp);
10597 }
10598 str += ch;
10599 }
10600 else if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) {
10601 this.throwUnexpectedToken(messages_1.Messages.UnterminatedRegExp);
10602 }
10603 else if (classMarker) {
10604 if (ch === ']') {
10605 classMarker = false;
10606 }
10607 }
10608 else {
10609 if (ch === '/') {
10610 terminated = true;
10611 break;
10612 }
10613 else if (ch === '[') {
10614 classMarker = true;
10615 }
10616 }
10617 }
10618 if (!terminated) {
10619 this.throwUnexpectedToken(messages_1.Messages.UnterminatedRegExp);
10620 }
10621 // Exclude leading and trailing slash.
10622 return str.substr(1, str.length - 2);
10623 };
10624 Scanner.prototype.scanRegExpFlags = function () {
10625 var str = '';
10626 var flags = '';
10627 while (!this.eof()) {
10628 var ch = this.source[this.index];
10629 if (!character_1.Character.isIdentifierPart(ch.charCodeAt(0))) {
10630 break;
10631 }
10632 ++this.index;
10633 if (ch === '\\' && !this.eof()) {
10634 ch = this.source[this.index];
10635 if (ch === 'u') {
10636 ++this.index;
10637 var restore = this.index;
10638 var char = this.scanHexEscape('u');
10639 if (char !== null) {
10640 flags += char;
10641 for (str += '\\u'; restore < this.index; ++restore) {
10642 str += this.source[restore];
10643 }
10644 }
10645 else {
10646 this.index = restore;
10647 flags += 'u';
10648 str += '\\u';
10649 }
10650 this.tolerateUnexpectedToken();
10651 }
10652 else {
10653 str += '\\';
10654 this.tolerateUnexpectedToken();
10655 }
10656 }
10657 else {
10658 flags += ch;
10659 str += ch;
10660 }
10661 }
10662 return flags;
10663 };
10664 Scanner.prototype.scanRegExp = function () {
10665 var start = this.index;
10666 var pattern = this.scanRegExpBody();
10667 var flags = this.scanRegExpFlags();
10668 var value = this.testRegExp(pattern, flags);
10669 return {
10670 type: 9 /* RegularExpression */,
10671 value: '',
10672 pattern: pattern,
10673 flags: flags,
10674 regex: value,
10675 lineNumber: this.lineNumber,
10676 lineStart: this.lineStart,
10677 start: start,
10678 end: this.index
10679 };
10680 };
10681 Scanner.prototype.lex = function () {
10682 if (this.eof()) {
10683 return {
10684 type: 2 /* EOF */,
10685 value: '',
10686 lineNumber: this.lineNumber,
10687 lineStart: this.lineStart,
10688 start: this.index,
10689 end: this.index
10690 };
10691 }
10692 var cp = this.source.charCodeAt(this.index);
10693 if (character_1.Character.isIdentifierStart(cp)) {
10694 return this.scanIdentifier();
10695 }
10696 // Very common: ( and ) and ;
10697 if (cp === 0x28 || cp === 0x29 || cp === 0x3B) {
10698 return this.scanPunctuator();
10699 }
10700 // String literal starts with single quote (U+0027) or double quote (U+0022).
10701 if (cp === 0x27 || cp === 0x22) {
10702 return this.scanStringLiteral();
10703 }
10704 // Dot (.) U+002E can also start a floating-point number, hence the need
10705 // to check the next character.
10706 if (cp === 0x2E) {
10707 if (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index + 1))) {
10708 return this.scanNumericLiteral();
10709 }
10710 return this.scanPunctuator();
10711 }
10712 if (character_1.Character.isDecimalDigit(cp)) {
10713 return this.scanNumericLiteral();
10714 }
10715 // Template literals start with ` (U+0060) for template head
10716 // or } (U+007D) for template middle or template tail.
10717 if (cp === 0x60 || (cp === 0x7D && this.curlyStack[this.curlyStack.length - 1] === '${')) {
10718 return this.scanTemplate();
10719 }
10720 // Possible identifier start in a surrogate pair.
10721 if (cp >= 0xD800 && cp < 0xDFFF) {
10722 if (character_1.Character.isIdentifierStart(this.codePointAt(this.index))) {
10723 return this.scanIdentifier();
10724 }
10725 }
10726 return this.scanPunctuator();
10727 };
10728 return Scanner;
10729 }());
10730 exports.Scanner = Scanner;
10731
10732
10733/***/ },
10734/* 13 */
10735/***/ function(module, exports) {
10736
10737 "use strict";
10738 Object.defineProperty(exports, "__esModule", { value: true });
10739 exports.TokenName = {};
10740 exports.TokenName[1 /* BooleanLiteral */] = 'Boolean';
10741 exports.TokenName[2 /* EOF */] = '<end>';
10742 exports.TokenName[3 /* Identifier */] = 'Identifier';
10743 exports.TokenName[4 /* Keyword */] = 'Keyword';
10744 exports.TokenName[5 /* NullLiteral */] = 'Null';
10745 exports.TokenName[6 /* NumericLiteral */] = 'Numeric';
10746 exports.TokenName[7 /* Punctuator */] = 'Punctuator';
10747 exports.TokenName[8 /* StringLiteral */] = 'String';
10748 exports.TokenName[9 /* RegularExpression */] = 'RegularExpression';
10749 exports.TokenName[10 /* Template */] = 'Template';
10750
10751
10752/***/ },
10753/* 14 */
10754/***/ function(module, exports) {
10755
10756 "use strict";
10757 // Generated by generate-xhtml-entities.js. DO NOT MODIFY!
10758 Object.defineProperty(exports, "__esModule", { value: true });
10759 exports.XHTMLEntities = {
10760 quot: '\u0022',
10761 amp: '\u0026',
10762 apos: '\u0027',
10763 gt: '\u003E',
10764 nbsp: '\u00A0',
10765 iexcl: '\u00A1',
10766 cent: '\u00A2',
10767 pound: '\u00A3',
10768 curren: '\u00A4',
10769 yen: '\u00A5',
10770 brvbar: '\u00A6',
10771 sect: '\u00A7',
10772 uml: '\u00A8',
10773 copy: '\u00A9',
10774 ordf: '\u00AA',
10775 laquo: '\u00AB',
10776 not: '\u00AC',
10777 shy: '\u00AD',
10778 reg: '\u00AE',
10779 macr: '\u00AF',
10780 deg: '\u00B0',
10781 plusmn: '\u00B1',
10782 sup2: '\u00B2',
10783 sup3: '\u00B3',
10784 acute: '\u00B4',
10785 micro: '\u00B5',
10786 para: '\u00B6',
10787 middot: '\u00B7',
10788 cedil: '\u00B8',
10789 sup1: '\u00B9',
10790 ordm: '\u00BA',
10791 raquo: '\u00BB',
10792 frac14: '\u00BC',
10793 frac12: '\u00BD',
10794 frac34: '\u00BE',
10795 iquest: '\u00BF',
10796 Agrave: '\u00C0',
10797 Aacute: '\u00C1',
10798 Acirc: '\u00C2',
10799 Atilde: '\u00C3',
10800 Auml: '\u00C4',
10801 Aring: '\u00C5',
10802 AElig: '\u00C6',
10803 Ccedil: '\u00C7',
10804 Egrave: '\u00C8',
10805 Eacute: '\u00C9',
10806 Ecirc: '\u00CA',
10807 Euml: '\u00CB',
10808 Igrave: '\u00CC',
10809 Iacute: '\u00CD',
10810 Icirc: '\u00CE',
10811 Iuml: '\u00CF',
10812 ETH: '\u00D0',
10813 Ntilde: '\u00D1',
10814 Ograve: '\u00D2',
10815 Oacute: '\u00D3',
10816 Ocirc: '\u00D4',
10817 Otilde: '\u00D5',
10818 Ouml: '\u00D6',
10819 times: '\u00D7',
10820 Oslash: '\u00D8',
10821 Ugrave: '\u00D9',
10822 Uacute: '\u00DA',
10823 Ucirc: '\u00DB',
10824 Uuml: '\u00DC',
10825 Yacute: '\u00DD',
10826 THORN: '\u00DE',
10827 szlig: '\u00DF',
10828 agrave: '\u00E0',
10829 aacute: '\u00E1',
10830 acirc: '\u00E2',
10831 atilde: '\u00E3',
10832 auml: '\u00E4',
10833 aring: '\u00E5',
10834 aelig: '\u00E6',
10835 ccedil: '\u00E7',
10836 egrave: '\u00E8',
10837 eacute: '\u00E9',
10838 ecirc: '\u00EA',
10839 euml: '\u00EB',
10840 igrave: '\u00EC',
10841 iacute: '\u00ED',
10842 icirc: '\u00EE',
10843 iuml: '\u00EF',
10844 eth: '\u00F0',
10845 ntilde: '\u00F1',
10846 ograve: '\u00F2',
10847 oacute: '\u00F3',
10848 ocirc: '\u00F4',
10849 otilde: '\u00F5',
10850 ouml: '\u00F6',
10851 divide: '\u00F7',
10852 oslash: '\u00F8',
10853 ugrave: '\u00F9',
10854 uacute: '\u00FA',
10855 ucirc: '\u00FB',
10856 uuml: '\u00FC',
10857 yacute: '\u00FD',
10858 thorn: '\u00FE',
10859 yuml: '\u00FF',
10860 OElig: '\u0152',
10861 oelig: '\u0153',
10862 Scaron: '\u0160',
10863 scaron: '\u0161',
10864 Yuml: '\u0178',
10865 fnof: '\u0192',
10866 circ: '\u02C6',
10867 tilde: '\u02DC',
10868 Alpha: '\u0391',
10869 Beta: '\u0392',
10870 Gamma: '\u0393',
10871 Delta: '\u0394',
10872 Epsilon: '\u0395',
10873 Zeta: '\u0396',
10874 Eta: '\u0397',
10875 Theta: '\u0398',
10876 Iota: '\u0399',
10877 Kappa: '\u039A',
10878 Lambda: '\u039B',
10879 Mu: '\u039C',
10880 Nu: '\u039D',
10881 Xi: '\u039E',
10882 Omicron: '\u039F',
10883 Pi: '\u03A0',
10884 Rho: '\u03A1',
10885 Sigma: '\u03A3',
10886 Tau: '\u03A4',
10887 Upsilon: '\u03A5',
10888 Phi: '\u03A6',
10889 Chi: '\u03A7',
10890 Psi: '\u03A8',
10891 Omega: '\u03A9',
10892 alpha: '\u03B1',
10893 beta: '\u03B2',
10894 gamma: '\u03B3',
10895 delta: '\u03B4',
10896 epsilon: '\u03B5',
10897 zeta: '\u03B6',
10898 eta: '\u03B7',
10899 theta: '\u03B8',
10900 iota: '\u03B9',
10901 kappa: '\u03BA',
10902 lambda: '\u03BB',
10903 mu: '\u03BC',
10904 nu: '\u03BD',
10905 xi: '\u03BE',
10906 omicron: '\u03BF',
10907 pi: '\u03C0',
10908 rho: '\u03C1',
10909 sigmaf: '\u03C2',
10910 sigma: '\u03C3',
10911 tau: '\u03C4',
10912 upsilon: '\u03C5',
10913 phi: '\u03C6',
10914 chi: '\u03C7',
10915 psi: '\u03C8',
10916 omega: '\u03C9',
10917 thetasym: '\u03D1',
10918 upsih: '\u03D2',
10919 piv: '\u03D6',
10920 ensp: '\u2002',
10921 emsp: '\u2003',
10922 thinsp: '\u2009',
10923 zwnj: '\u200C',
10924 zwj: '\u200D',
10925 lrm: '\u200E',
10926 rlm: '\u200F',
10927 ndash: '\u2013',
10928 mdash: '\u2014',
10929 lsquo: '\u2018',
10930 rsquo: '\u2019',
10931 sbquo: '\u201A',
10932 ldquo: '\u201C',
10933 rdquo: '\u201D',
10934 bdquo: '\u201E',
10935 dagger: '\u2020',
10936 Dagger: '\u2021',
10937 bull: '\u2022',
10938 hellip: '\u2026',
10939 permil: '\u2030',
10940 prime: '\u2032',
10941 Prime: '\u2033',
10942 lsaquo: '\u2039',
10943 rsaquo: '\u203A',
10944 oline: '\u203E',
10945 frasl: '\u2044',
10946 euro: '\u20AC',
10947 image: '\u2111',
10948 weierp: '\u2118',
10949 real: '\u211C',
10950 trade: '\u2122',
10951 alefsym: '\u2135',
10952 larr: '\u2190',
10953 uarr: '\u2191',
10954 rarr: '\u2192',
10955 darr: '\u2193',
10956 harr: '\u2194',
10957 crarr: '\u21B5',
10958 lArr: '\u21D0',
10959 uArr: '\u21D1',
10960 rArr: '\u21D2',
10961 dArr: '\u21D3',
10962 hArr: '\u21D4',
10963 forall: '\u2200',
10964 part: '\u2202',
10965 exist: '\u2203',
10966 empty: '\u2205',
10967 nabla: '\u2207',
10968 isin: '\u2208',
10969 notin: '\u2209',
10970 ni: '\u220B',
10971 prod: '\u220F',
10972 sum: '\u2211',
10973 minus: '\u2212',
10974 lowast: '\u2217',
10975 radic: '\u221A',
10976 prop: '\u221D',
10977 infin: '\u221E',
10978 ang: '\u2220',
10979 and: '\u2227',
10980 or: '\u2228',
10981 cap: '\u2229',
10982 cup: '\u222A',
10983 int: '\u222B',
10984 there4: '\u2234',
10985 sim: '\u223C',
10986 cong: '\u2245',
10987 asymp: '\u2248',
10988 ne: '\u2260',
10989 equiv: '\u2261',
10990 le: '\u2264',
10991 ge: '\u2265',
10992 sub: '\u2282',
10993 sup: '\u2283',
10994 nsub: '\u2284',
10995 sube: '\u2286',
10996 supe: '\u2287',
10997 oplus: '\u2295',
10998 otimes: '\u2297',
10999 perp: '\u22A5',
11000 sdot: '\u22C5',
11001 lceil: '\u2308',
11002 rceil: '\u2309',
11003 lfloor: '\u230A',
11004 rfloor: '\u230B',
11005 loz: '\u25CA',
11006 spades: '\u2660',
11007 clubs: '\u2663',
11008 hearts: '\u2665',
11009 diams: '\u2666',
11010 lang: '\u27E8',
11011 rang: '\u27E9'
11012 };
11013
11014
11015/***/ },
11016/* 15 */
11017/***/ function(module, exports, __webpack_require__) {
11018
11019 "use strict";
11020 Object.defineProperty(exports, "__esModule", { value: true });
11021 var error_handler_1 = __webpack_require__(10);
11022 var scanner_1 = __webpack_require__(12);
11023 var token_1 = __webpack_require__(13);
11024 var Reader = (function () {
11025 function Reader() {
11026 this.values = [];
11027 this.curly = this.paren = -1;
11028 }
11029 // A function following one of those tokens is an expression.
11030 Reader.prototype.beforeFunctionExpression = function (t) {
11031 return ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
11032 'return', 'case', 'delete', 'throw', 'void',
11033 // assignment operators
11034 '=', '+=', '-=', '*=', '**=', '/=', '%=', '<<=', '>>=', '>>>=',
11035 '&=', '|=', '^=', ',',
11036 // binary/unary operators
11037 '+', '-', '*', '**', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
11038 '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
11039 '<=', '<', '>', '!=', '!=='].indexOf(t) >= 0;
11040 };
11041 // Determine if forward slash (/) is an operator or part of a regular expression
11042 // https://github.com/mozilla/sweet.js/wiki/design
11043 Reader.prototype.isRegexStart = function () {
11044 var previous = this.values[this.values.length - 1];
11045 var regex = (previous !== null);
11046 switch (previous) {
11047 case 'this':
11048 case ']':
11049 regex = false;
11050 break;
11051 case ')':
11052 var keyword = this.values[this.paren - 1];
11053 regex = (keyword === 'if' || keyword === 'while' || keyword === 'for' || keyword === 'with');
11054 break;
11055 case '}':
11056 // Dividing a function by anything makes little sense,
11057 // but we have to check for that.
11058 regex = false;
11059 if (this.values[this.curly - 3] === 'function') {
11060 // Anonymous function, e.g. function(){} /42
11061 var check = this.values[this.curly - 4];
11062 regex = check ? !this.beforeFunctionExpression(check) : false;
11063 }
11064 else if (this.values[this.curly - 4] === 'function') {
11065 // Named function, e.g. function f(){} /42/
11066 var check = this.values[this.curly - 5];
11067 regex = check ? !this.beforeFunctionExpression(check) : true;
11068 }
11069 break;
11070 default:
11071 break;
11072 }
11073 return regex;
11074 };
11075 Reader.prototype.push = function (token) {
11076 if (token.type === 7 /* Punctuator */ || token.type === 4 /* Keyword */) {
11077 if (token.value === '{') {
11078 this.curly = this.values.length;
11079 }
11080 else if (token.value === '(') {
11081 this.paren = this.values.length;
11082 }
11083 this.values.push(token.value);
11084 }
11085 else {
11086 this.values.push(null);
11087 }
11088 };
11089 return Reader;
11090 }());
11091 var Tokenizer = (function () {
11092 function Tokenizer(code, config) {
11093 this.errorHandler = new error_handler_1.ErrorHandler();
11094 this.errorHandler.tolerant = config ? (typeof config.tolerant === 'boolean' && config.tolerant) : false;
11095 this.scanner = new scanner_1.Scanner(code, this.errorHandler);
11096 this.scanner.trackComment = config ? (typeof config.comment === 'boolean' && config.comment) : false;
11097 this.trackRange = config ? (typeof config.range === 'boolean' && config.range) : false;
11098 this.trackLoc = config ? (typeof config.loc === 'boolean' && config.loc) : false;
11099 this.buffer = [];
11100 this.reader = new Reader();
11101 }
11102 Tokenizer.prototype.errors = function () {
11103 return this.errorHandler.errors;
11104 };
11105 Tokenizer.prototype.getNextToken = function () {
11106 if (this.buffer.length === 0) {
11107 var comments = this.scanner.scanComments();
11108 if (this.scanner.trackComment) {
11109 for (var i = 0; i < comments.length; ++i) {
11110 var e = comments[i];
11111 var value = this.scanner.source.slice(e.slice[0], e.slice[1]);
11112 var comment = {
11113 type: e.multiLine ? 'BlockComment' : 'LineComment',
11114 value: value
11115 };
11116 if (this.trackRange) {
11117 comment.range = e.range;
11118 }
11119 if (this.trackLoc) {
11120 comment.loc = e.loc;
11121 }
11122 this.buffer.push(comment);
11123 }
11124 }
11125 if (!this.scanner.eof()) {
11126 var loc = void 0;
11127 if (this.trackLoc) {
11128 loc = {
11129 start: {
11130 line: this.scanner.lineNumber,
11131 column: this.scanner.index - this.scanner.lineStart
11132 },
11133 end: {}
11134 };
11135 }
11136 var startRegex = (this.scanner.source[this.scanner.index] === '/') && this.reader.isRegexStart();
11137 var token = startRegex ? this.scanner.scanRegExp() : this.scanner.lex();
11138 this.reader.push(token);
11139 var entry = {
11140 type: token_1.TokenName[token.type],
11141 value: this.scanner.source.slice(token.start, token.end)
11142 };
11143 if (this.trackRange) {
11144 entry.range = [token.start, token.end];
11145 }
11146 if (this.trackLoc) {
11147 loc.end = {
11148 line: this.scanner.lineNumber,
11149 column: this.scanner.index - this.scanner.lineStart
11150 };
11151 entry.loc = loc;
11152 }
11153 if (token.type === 9 /* RegularExpression */) {
11154 var pattern = token.pattern;
11155 var flags = token.flags;
11156 entry.regex = { pattern: pattern, flags: flags };
11157 }
11158 this.buffer.push(entry);
11159 }
11160 }
11161 return this.buffer.shift();
11162 };
11163 return Tokenizer;
11164 }());
11165 exports.Tokenizer = Tokenizer;
11166
11167
11168/***/ }
11169/******/ ])
11170});
11171;
11172/*global define, Reflect */
11173
11174/*
11175 * xpcshell has a smaller stack on linux and windows (1MB vs 9MB on mac),
11176 * and the recursive nature of esprima can cause it to overflow pretty
11177 * quickly. So favor it built in Reflect parser:
11178 * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
11179 */
11180define('esprimaAdapter', ['./esprima', 'env'], function (esprima, env) {
11181 if (env.get() === 'xpconnect' && typeof Reflect !== 'undefined') {
11182 return Reflect;
11183 } else {
11184 return esprima;
11185 }
11186});
11187(function webpackUniversalModuleDefinition(root, factory) {
11188var exports, module;
11189 if(typeof exports === 'object' && typeof module === 'object')
11190 module.exports = factory();
11191 else if(typeof define === 'function' && define.amd)
11192 define('source-map', [], factory);
11193 else if(typeof exports === 'object')
11194 exports["sourceMap"] = factory();
11195 else
11196 root["sourceMap"] = factory();
11197})(this, function() {
11198return /******/ (function(modules) { // webpackBootstrap
11199/******/ // The module cache
11200/******/ var installedModules = {};
11201
11202/******/ // The require function
11203/******/ function __webpack_require__(moduleId) {
11204
11205/******/ // Check if module is in cache
11206/******/ if(installedModules[moduleId])
11207/******/ return installedModules[moduleId].exports;
11208
11209/******/ // Create a new module (and put it into the cache)
11210/******/ var module = installedModules[moduleId] = {
11211/******/ exports: {},
11212/******/ id: moduleId,
11213/******/ loaded: false
11214/******/ };
11215
11216/******/ // Execute the module function
11217/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
11218
11219/******/ // Flag the module as loaded
11220/******/ module.loaded = true;
11221
11222/******/ // Return the exports of the module
11223/******/ return module.exports;
11224/******/ }
11225
11226
11227/******/ // expose the modules object (__webpack_modules__)
11228/******/ __webpack_require__.m = modules;
11229
11230/******/ // expose the module cache
11231/******/ __webpack_require__.c = installedModules;
11232
11233/******/ // __webpack_public_path__
11234/******/ __webpack_require__.p = "";
11235
11236/******/ // Load entry module and return exports
11237/******/ return __webpack_require__(0);
11238/******/ })
11239/************************************************************************/
11240/******/ ([
11241/* 0 */
11242/***/ function(module, exports, __webpack_require__) {
11243
11244 /*
11245 * Copyright 2009-2011 Mozilla Foundation and contributors
11246 * Licensed under the New BSD license. See LICENSE.txt or:
11247 * http://opensource.org/licenses/BSD-3-Clause
11248 */
11249 exports.SourceMapGenerator = __webpack_require__(1).SourceMapGenerator;
11250 exports.SourceMapConsumer = __webpack_require__(7).SourceMapConsumer;
11251 exports.SourceNode = __webpack_require__(10).SourceNode;
11252
11253
11254/***/ },
11255/* 1 */
11256/***/ function(module, exports, __webpack_require__) {
11257
11258 /* -*- Mode: js; js-indent-level: 2; -*- */
11259 /*
11260 * Copyright 2011 Mozilla Foundation and contributors
11261 * Licensed under the New BSD license. See LICENSE or:
11262 * http://opensource.org/licenses/BSD-3-Clause
11263 */
11264
11265 var base64VLQ = __webpack_require__(2);
11266 var util = __webpack_require__(4);
11267 var ArraySet = __webpack_require__(5).ArraySet;
11268 var MappingList = __webpack_require__(6).MappingList;
11269
11270 /**
11271 * An instance of the SourceMapGenerator represents a source map which is
11272 * being built incrementally. You may pass an object with the following
11273 * properties:
11274 *
11275 * - file: The filename of the generated source.
11276 * - sourceRoot: A root for all relative URLs in this source map.
11277 */
11278 function SourceMapGenerator(aArgs) {
11279 if (!aArgs) {
11280 aArgs = {};
11281 }
11282 this._file = util.getArg(aArgs, 'file', null);
11283 this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
11284 this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
11285 this._sources = new ArraySet();
11286 this._names = new ArraySet();
11287 this._mappings = new MappingList();
11288 this._sourcesContents = null;
11289 }
11290
11291 SourceMapGenerator.prototype._version = 3;
11292
11293 /**
11294 * Creates a new SourceMapGenerator based on a SourceMapConsumer
11295 *
11296 * @param aSourceMapConsumer The SourceMap.
11297 */
11298 SourceMapGenerator.fromSourceMap =
11299 function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
11300 var sourceRoot = aSourceMapConsumer.sourceRoot;
11301 var generator = new SourceMapGenerator({
11302 file: aSourceMapConsumer.file,
11303 sourceRoot: sourceRoot
11304 });
11305 aSourceMapConsumer.eachMapping(function (mapping) {
11306 var newMapping = {
11307 generated: {
11308 line: mapping.generatedLine,
11309 column: mapping.generatedColumn
11310 }
11311 };
11312
11313 if (mapping.source != null) {
11314 newMapping.source = mapping.source;
11315 if (sourceRoot != null) {
11316 newMapping.source = util.relative(sourceRoot, newMapping.source);
11317 }
11318
11319 newMapping.original = {
11320 line: mapping.originalLine,
11321 column: mapping.originalColumn
11322 };
11323
11324 if (mapping.name != null) {
11325 newMapping.name = mapping.name;
11326 }
11327 }
11328
11329 generator.addMapping(newMapping);
11330 });
11331 aSourceMapConsumer.sources.forEach(function (sourceFile) {
11332 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
11333 if (content != null) {
11334 generator.setSourceContent(sourceFile, content);
11335 }
11336 });
11337 return generator;
11338 };
11339
11340 /**
11341 * Add a single mapping from original source line and column to the generated
11342 * source's line and column for this source map being created. The mapping
11343 * object should have the following properties:
11344 *
11345 * - generated: An object with the generated line and column positions.
11346 * - original: An object with the original line and column positions.
11347 * - source: The original source file (relative to the sourceRoot).
11348 * - name: An optional original token name for this mapping.
11349 */
11350 SourceMapGenerator.prototype.addMapping =
11351 function SourceMapGenerator_addMapping(aArgs) {
11352 var generated = util.getArg(aArgs, 'generated');
11353 var original = util.getArg(aArgs, 'original', null);
11354 var source = util.getArg(aArgs, 'source', null);
11355 var name = util.getArg(aArgs, 'name', null);
11356
11357 if (!this._skipValidation) {
11358 this._validateMapping(generated, original, source, name);
11359 }
11360
11361 if (source != null) {
11362 source = String(source);
11363 if (!this._sources.has(source)) {
11364 this._sources.add(source);
11365 }
11366 }
11367
11368 if (name != null) {
11369 name = String(name);
11370 if (!this._names.has(name)) {
11371 this._names.add(name);
11372 }
11373 }
11374
11375 this._mappings.add({
11376 generatedLine: generated.line,
11377 generatedColumn: generated.column,
11378 originalLine: original != null && original.line,
11379 originalColumn: original != null && original.column,
11380 source: source,
11381 name: name
11382 });
11383 };
11384
11385 /**
11386 * Set the source content for a source file.
11387 */
11388 SourceMapGenerator.prototype.setSourceContent =
11389 function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
11390 var source = aSourceFile;
11391 if (this._sourceRoot != null) {
11392 source = util.relative(this._sourceRoot, source);
11393 }
11394
11395 if (aSourceContent != null) {
11396 // Add the source content to the _sourcesContents map.
11397 // Create a new _sourcesContents map if the property is null.
11398 if (!this._sourcesContents) {
11399 this._sourcesContents = Object.create(null);
11400 }
11401 this._sourcesContents[util.toSetString(source)] = aSourceContent;
11402 } else if (this._sourcesContents) {
11403 // Remove the source file from the _sourcesContents map.
11404 // If the _sourcesContents map is empty, set the property to null.
11405 delete this._sourcesContents[util.toSetString(source)];
11406 if (Object.keys(this._sourcesContents).length === 0) {
11407 this._sourcesContents = null;
11408 }
11409 }
11410 };
11411
11412 /**
11413 * Applies the mappings of a sub-source-map for a specific source file to the
11414 * source map being generated. Each mapping to the supplied source file is
11415 * rewritten using the supplied source map. Note: The resolution for the
11416 * resulting mappings is the minimium of this map and the supplied map.
11417 *
11418 * @param aSourceMapConsumer The source map to be applied.
11419 * @param aSourceFile Optional. The filename of the source file.
11420 * If omitted, SourceMapConsumer's file property will be used.
11421 * @param aSourceMapPath Optional. The dirname of the path to the source map
11422 * to be applied. If relative, it is relative to the SourceMapConsumer.
11423 * This parameter is needed when the two source maps aren't in the same
11424 * directory, and the source map to be applied contains relative source
11425 * paths. If so, those relative source paths need to be rewritten
11426 * relative to the SourceMapGenerator.
11427 */
11428 SourceMapGenerator.prototype.applySourceMap =
11429 function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
11430 var sourceFile = aSourceFile;
11431 // If aSourceFile is omitted, we will use the file property of the SourceMap
11432 if (aSourceFile == null) {
11433 if (aSourceMapConsumer.file == null) {
11434 throw new Error(
11435 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +
11436 'or the source map\'s "file" property. Both were omitted.'
11437 );
11438 }
11439 sourceFile = aSourceMapConsumer.file;
11440 }
11441 var sourceRoot = this._sourceRoot;
11442 // Make "sourceFile" relative if an absolute Url is passed.
11443 if (sourceRoot != null) {
11444 sourceFile = util.relative(sourceRoot, sourceFile);
11445 }
11446 // Applying the SourceMap can add and remove items from the sources and
11447 // the names array.
11448 var newSources = new ArraySet();
11449 var newNames = new ArraySet();
11450
11451 // Find mappings for the "sourceFile"
11452 this._mappings.unsortedForEach(function (mapping) {
11453 if (mapping.source === sourceFile && mapping.originalLine != null) {
11454 // Check if it can be mapped by the source map, then update the mapping.
11455 var original = aSourceMapConsumer.originalPositionFor({
11456 line: mapping.originalLine,
11457 column: mapping.originalColumn
11458 });
11459 if (original.source != null) {
11460 // Copy mapping
11461 mapping.source = original.source;
11462 if (aSourceMapPath != null) {
11463 mapping.source = util.join(aSourceMapPath, mapping.source)
11464 }
11465 if (sourceRoot != null) {
11466 mapping.source = util.relative(sourceRoot, mapping.source);
11467 }
11468 mapping.originalLine = original.line;
11469 mapping.originalColumn = original.column;
11470 if (original.name != null) {
11471 mapping.name = original.name;
11472 }
11473 }
11474 }
11475
11476 var source = mapping.source;
11477 if (source != null && !newSources.has(source)) {
11478 newSources.add(source);
11479 }
11480
11481 var name = mapping.name;
11482 if (name != null && !newNames.has(name)) {
11483 newNames.add(name);
11484 }
11485
11486 }, this);
11487 this._sources = newSources;
11488 this._names = newNames;
11489
11490 // Copy sourcesContents of applied map.
11491 aSourceMapConsumer.sources.forEach(function (sourceFile) {
11492 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
11493 if (content != null) {
11494 if (aSourceMapPath != null) {
11495 sourceFile = util.join(aSourceMapPath, sourceFile);
11496 }
11497 if (sourceRoot != null) {
11498 sourceFile = util.relative(sourceRoot, sourceFile);
11499 }
11500 this.setSourceContent(sourceFile, content);
11501 }
11502 }, this);
11503 };
11504
11505 /**
11506 * A mapping can have one of the three levels of data:
11507 *
11508 * 1. Just the generated position.
11509 * 2. The Generated position, original position, and original source.
11510 * 3. Generated and original position, original source, as well as a name
11511 * token.
11512 *
11513 * To maintain consistency, we validate that any new mapping being added falls
11514 * in to one of these categories.
11515 */
11516 SourceMapGenerator.prototype._validateMapping =
11517 function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
11518 aName) {
11519 if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
11520 && aGenerated.line > 0 && aGenerated.column >= 0
11521 && !aOriginal && !aSource && !aName) {
11522 // Case 1.
11523 return;
11524 }
11525 else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
11526 && aOriginal && 'line' in aOriginal && 'column' in aOriginal
11527 && aGenerated.line > 0 && aGenerated.column >= 0
11528 && aOriginal.line > 0 && aOriginal.column >= 0
11529 && aSource) {
11530 // Cases 2 and 3.
11531 return;
11532 }
11533 else {
11534 throw new Error('Invalid mapping: ' + JSON.stringify({
11535 generated: aGenerated,
11536 source: aSource,
11537 original: aOriginal,
11538 name: aName
11539 }));
11540 }
11541 };
11542
11543 /**
11544 * Serialize the accumulated mappings in to the stream of base 64 VLQs
11545 * specified by the source map format.
11546 */
11547 SourceMapGenerator.prototype._serializeMappings =
11548 function SourceMapGenerator_serializeMappings() {
11549 var previousGeneratedColumn = 0;
11550 var previousGeneratedLine = 1;
11551 var previousOriginalColumn = 0;
11552 var previousOriginalLine = 0;
11553 var previousName = 0;
11554 var previousSource = 0;
11555 var result = '';
11556 var next;
11557 var mapping;
11558 var nameIdx;
11559 var sourceIdx;
11560
11561 var mappings = this._mappings.toArray();
11562 for (var i = 0, len = mappings.length; i < len; i++) {
11563 mapping = mappings[i];
11564 next = ''
11565
11566 if (mapping.generatedLine !== previousGeneratedLine) {
11567 previousGeneratedColumn = 0;
11568 while (mapping.generatedLine !== previousGeneratedLine) {
11569 next += ';';
11570 previousGeneratedLine++;
11571 }
11572 }
11573 else {
11574 if (i > 0) {
11575 if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
11576 continue;
11577 }
11578 next += ',';
11579 }
11580 }
11581
11582 next += base64VLQ.encode(mapping.generatedColumn
11583 - previousGeneratedColumn);
11584 previousGeneratedColumn = mapping.generatedColumn;
11585
11586 if (mapping.source != null) {
11587 sourceIdx = this._sources.indexOf(mapping.source);
11588 next += base64VLQ.encode(sourceIdx - previousSource);
11589 previousSource = sourceIdx;
11590
11591 // lines are stored 0-based in SourceMap spec version 3
11592 next += base64VLQ.encode(mapping.originalLine - 1
11593 - previousOriginalLine);
11594 previousOriginalLine = mapping.originalLine - 1;
11595
11596 next += base64VLQ.encode(mapping.originalColumn
11597 - previousOriginalColumn);
11598 previousOriginalColumn = mapping.originalColumn;
11599
11600 if (mapping.name != null) {
11601 nameIdx = this._names.indexOf(mapping.name);
11602 next += base64VLQ.encode(nameIdx - previousName);
11603 previousName = nameIdx;
11604 }
11605 }
11606
11607 result += next;
11608 }
11609
11610 return result;
11611 };
11612
11613 SourceMapGenerator.prototype._generateSourcesContent =
11614 function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
11615 return aSources.map(function (source) {
11616 if (!this._sourcesContents) {
11617 return null;
11618 }
11619 if (aSourceRoot != null) {
11620 source = util.relative(aSourceRoot, source);
11621 }
11622 var key = util.toSetString(source);
11623 return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)
11624 ? this._sourcesContents[key]
11625 : null;
11626 }, this);
11627 };
11628
11629 /**
11630 * Externalize the source map.
11631 */
11632 SourceMapGenerator.prototype.toJSON =
11633 function SourceMapGenerator_toJSON() {
11634 var map = {
11635 version: this._version,
11636 sources: this._sources.toArray(),
11637 names: this._names.toArray(),
11638 mappings: this._serializeMappings()
11639 };
11640 if (this._file != null) {
11641 map.file = this._file;
11642 }
11643 if (this._sourceRoot != null) {
11644 map.sourceRoot = this._sourceRoot;
11645 }
11646 if (this._sourcesContents) {
11647 map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
11648 }
11649
11650 return map;
11651 };
11652
11653 /**
11654 * Render the source map being generated to a string.
11655 */
11656 SourceMapGenerator.prototype.toString =
11657 function SourceMapGenerator_toString() {
11658 return JSON.stringify(this.toJSON());
11659 };
11660
11661 exports.SourceMapGenerator = SourceMapGenerator;
11662
11663
11664/***/ },
11665/* 2 */
11666/***/ function(module, exports, __webpack_require__) {
11667
11668 /* -*- Mode: js; js-indent-level: 2; -*- */
11669 /*
11670 * Copyright 2011 Mozilla Foundation and contributors
11671 * Licensed under the New BSD license. See LICENSE or:
11672 * http://opensource.org/licenses/BSD-3-Clause
11673 *
11674 * Based on the Base 64 VLQ implementation in Closure Compiler:
11675 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
11676 *
11677 * Copyright 2011 The Closure Compiler Authors. All rights reserved.
11678 * Redistribution and use in source and binary forms, with or without
11679 * modification, are permitted provided that the following conditions are
11680 * met:
11681 *
11682 * * Redistributions of source code must retain the above copyright
11683 * notice, this list of conditions and the following disclaimer.
11684 * * Redistributions in binary form must reproduce the above
11685 * copyright notice, this list of conditions and the following
11686 * disclaimer in the documentation and/or other materials provided
11687 * with the distribution.
11688 * * Neither the name of Google Inc. nor the names of its
11689 * contributors may be used to endorse or promote products derived
11690 * from this software without specific prior written permission.
11691 *
11692 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
11693 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11694 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11695 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
11696 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
11697 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11698 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11699 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11700 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
11701 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
11702 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11703 */
11704
11705 var base64 = __webpack_require__(3);
11706
11707 // A single base 64 digit can contain 6 bits of data. For the base 64 variable
11708 // length quantities we use in the source map spec, the first bit is the sign,
11709 // the next four bits are the actual value, and the 6th bit is the
11710 // continuation bit. The continuation bit tells us whether there are more
11711 // digits in this value following this digit.
11712 //
11713 // Continuation
11714 // | Sign
11715 // | |
11716 // V V
11717 // 101011
11718
11719 var VLQ_BASE_SHIFT = 5;
11720
11721 // binary: 100000
11722 var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
11723
11724 // binary: 011111
11725 var VLQ_BASE_MASK = VLQ_BASE - 1;
11726
11727 // binary: 100000
11728 var VLQ_CONTINUATION_BIT = VLQ_BASE;
11729
11730 /**
11731 * Converts from a two-complement value to a value where the sign bit is
11732 * placed in the least significant bit. For example, as decimals:
11733 * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
11734 * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
11735 */
11736 function toVLQSigned(aValue) {
11737 return aValue < 0
11738 ? ((-aValue) << 1) + 1
11739 : (aValue << 1) + 0;
11740 }
11741
11742 /**
11743 * Converts to a two-complement value from a value where the sign bit is
11744 * placed in the least significant bit. For example, as decimals:
11745 * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
11746 * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
11747 */
11748 function fromVLQSigned(aValue) {
11749 var isNegative = (aValue & 1) === 1;
11750 var shifted = aValue >> 1;
11751 return isNegative
11752 ? -shifted
11753 : shifted;
11754 }
11755
11756 /**
11757 * Returns the base 64 VLQ encoded value.
11758 */
11759 exports.encode = function base64VLQ_encode(aValue) {
11760 var encoded = "";
11761 var digit;
11762
11763 var vlq = toVLQSigned(aValue);
11764
11765 do {
11766 digit = vlq & VLQ_BASE_MASK;
11767 vlq >>>= VLQ_BASE_SHIFT;
11768 if (vlq > 0) {
11769 // There are still more digits in this value, so we must make sure the
11770 // continuation bit is marked.
11771 digit |= VLQ_CONTINUATION_BIT;
11772 }
11773 encoded += base64.encode(digit);
11774 } while (vlq > 0);
11775
11776 return encoded;
11777 };
11778
11779 /**
11780 * Decodes the next base 64 VLQ value from the given string and returns the
11781 * value and the rest of the string via the out parameter.
11782 */
11783 exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {
11784 var strLen = aStr.length;
11785 var result = 0;
11786 var shift = 0;
11787 var continuation, digit;
11788
11789 do {
11790 if (aIndex >= strLen) {
11791 throw new Error("Expected more digits in base 64 VLQ value.");
11792 }
11793
11794 digit = base64.decode(aStr.charCodeAt(aIndex++));
11795 if (digit === -1) {
11796 throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1));
11797 }
11798
11799 continuation = !!(digit & VLQ_CONTINUATION_BIT);
11800 digit &= VLQ_BASE_MASK;
11801 result = result + (digit << shift);
11802 shift += VLQ_BASE_SHIFT;
11803 } while (continuation);
11804
11805 aOutParam.value = fromVLQSigned(result);
11806 aOutParam.rest = aIndex;
11807 };
11808
11809
11810/***/ },
11811/* 3 */
11812/***/ function(module, exports) {
11813
11814 /* -*- Mode: js; js-indent-level: 2; -*- */
11815 /*
11816 * Copyright 2011 Mozilla Foundation and contributors
11817 * Licensed under the New BSD license. See LICENSE or:
11818 * http://opensource.org/licenses/BSD-3-Clause
11819 */
11820
11821 var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
11822
11823 /**
11824 * Encode an integer in the range of 0 to 63 to a single base 64 digit.
11825 */
11826 exports.encode = function (number) {
11827 if (0 <= number && number < intToCharMap.length) {
11828 return intToCharMap[number];
11829 }
11830 throw new TypeError("Must be between 0 and 63: " + number);
11831 };
11832
11833 /**
11834 * Decode a single base 64 character code digit to an integer. Returns -1 on
11835 * failure.
11836 */
11837 exports.decode = function (charCode) {
11838 var bigA = 65; // 'A'
11839 var bigZ = 90; // 'Z'
11840
11841 var littleA = 97; // 'a'
11842 var littleZ = 122; // 'z'
11843
11844 var zero = 48; // '0'
11845 var nine = 57; // '9'
11846
11847 var plus = 43; // '+'
11848 var slash = 47; // '/'
11849
11850 var littleOffset = 26;
11851 var numberOffset = 52;
11852
11853 // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ
11854 if (bigA <= charCode && charCode <= bigZ) {
11855 return (charCode - bigA);
11856 }
11857
11858 // 26 - 51: abcdefghijklmnopqrstuvwxyz
11859 if (littleA <= charCode && charCode <= littleZ) {
11860 return (charCode - littleA + littleOffset);
11861 }
11862
11863 // 52 - 61: 0123456789
11864 if (zero <= charCode && charCode <= nine) {
11865 return (charCode - zero + numberOffset);
11866 }
11867
11868 // 62: +
11869 if (charCode == plus) {
11870 return 62;
11871 }
11872
11873 // 63: /
11874 if (charCode == slash) {
11875 return 63;
11876 }
11877
11878 // Invalid base64 digit.
11879 return -1;
11880 };
11881
11882
11883/***/ },
11884/* 4 */
11885/***/ function(module, exports) {
11886
11887 /* -*- Mode: js; js-indent-level: 2; -*- */
11888 /*
11889 * Copyright 2011 Mozilla Foundation and contributors
11890 * Licensed under the New BSD license. See LICENSE or:
11891 * http://opensource.org/licenses/BSD-3-Clause
11892 */
11893
11894 /**
11895 * This is a helper function for getting values from parameter/options
11896 * objects.
11897 *
11898 * @param args The object we are extracting values from
11899 * @param name The name of the property we are getting.
11900 * @param defaultValue An optional value to return if the property is missing
11901 * from the object. If this is not specified and the property is missing, an
11902 * error will be thrown.
11903 */
11904 function getArg(aArgs, aName, aDefaultValue) {
11905 if (aName in aArgs) {
11906 return aArgs[aName];
11907 } else if (arguments.length === 3) {
11908 return aDefaultValue;
11909 } else {
11910 throw new Error('"' + aName + '" is a required argument.');
11911 }
11912 }
11913 exports.getArg = getArg;
11914
11915 var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/;
11916 var dataUrlRegexp = /^data:.+\,.+$/;
11917
11918 function urlParse(aUrl) {
11919 var match = aUrl.match(urlRegexp);
11920 if (!match) {
11921 return null;
11922 }
11923 return {
11924 scheme: match[1],
11925 auth: match[2],
11926 host: match[3],
11927 port: match[4],
11928 path: match[5]
11929 };
11930 }
11931 exports.urlParse = urlParse;
11932
11933 function urlGenerate(aParsedUrl) {
11934 var url = '';
11935 if (aParsedUrl.scheme) {
11936 url += aParsedUrl.scheme + ':';
11937 }
11938 url += '//';
11939 if (aParsedUrl.auth) {
11940 url += aParsedUrl.auth + '@';
11941 }
11942 if (aParsedUrl.host) {
11943 url += aParsedUrl.host;
11944 }
11945 if (aParsedUrl.port) {
11946 url += ":" + aParsedUrl.port
11947 }
11948 if (aParsedUrl.path) {
11949 url += aParsedUrl.path;
11950 }
11951 return url;
11952 }
11953 exports.urlGenerate = urlGenerate;
11954
11955 /**
11956 * Normalizes a path, or the path portion of a URL:
11957 *
11958 * - Replaces consequtive slashes with one slash.
11959 * - Removes unnecessary '.' parts.
11960 * - Removes unnecessary '<dir>/..' parts.
11961 *
11962 * Based on code in the Node.js 'path' core module.
11963 *
11964 * @param aPath The path or url to normalize.
11965 */
11966 function normalize(aPath) {
11967 var path = aPath;
11968 var url = urlParse(aPath);
11969 if (url) {
11970 if (!url.path) {
11971 return aPath;
11972 }
11973 path = url.path;
11974 }
11975 var isAbsolute = exports.isAbsolute(path);
11976
11977 var parts = path.split(/\/+/);
11978 for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
11979 part = parts[i];
11980 if (part === '.') {
11981 parts.splice(i, 1);
11982 } else if (part === '..') {
11983 up++;
11984 } else if (up > 0) {
11985 if (part === '') {
11986 // The first part is blank if the path is absolute. Trying to go
11987 // above the root is a no-op. Therefore we can remove all '..' parts
11988 // directly after the root.
11989 parts.splice(i + 1, up);
11990 up = 0;
11991 } else {
11992 parts.splice(i, 2);
11993 up--;
11994 }
11995 }
11996 }
11997 path = parts.join('/');
11998
11999 if (path === '') {
12000 path = isAbsolute ? '/' : '.';
12001 }
12002
12003 if (url) {
12004 url.path = path;
12005 return urlGenerate(url);
12006 }
12007 return path;
12008 }
12009 exports.normalize = normalize;
12010
12011 /**
12012 * Joins two paths/URLs.
12013 *
12014 * @param aRoot The root path or URL.
12015 * @param aPath The path or URL to be joined with the root.
12016 *
12017 * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
12018 * scheme-relative URL: Then the scheme of aRoot, if any, is prepended
12019 * first.
12020 * - Otherwise aPath is a path. If aRoot is a URL, then its path portion
12021 * is updated with the result and aRoot is returned. Otherwise the result
12022 * is returned.
12023 * - If aPath is absolute, the result is aPath.
12024 * - Otherwise the two paths are joined with a slash.
12025 * - Joining for example 'http://' and 'www.example.com' is also supported.
12026 */
12027 function join(aRoot, aPath) {
12028 if (aRoot === "") {
12029 aRoot = ".";
12030 }
12031 if (aPath === "") {
12032 aPath = ".";
12033 }
12034 var aPathUrl = urlParse(aPath);
12035 var aRootUrl = urlParse(aRoot);
12036 if (aRootUrl) {
12037 aRoot = aRootUrl.path || '/';
12038 }
12039
12040 // `join(foo, '//www.example.org')`
12041 if (aPathUrl && !aPathUrl.scheme) {
12042 if (aRootUrl) {
12043 aPathUrl.scheme = aRootUrl.scheme;
12044 }
12045 return urlGenerate(aPathUrl);
12046 }
12047
12048 if (aPathUrl || aPath.match(dataUrlRegexp)) {
12049 return aPath;
12050 }
12051
12052 // `join('http://', 'www.example.com')`
12053 if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
12054 aRootUrl.host = aPath;
12055 return urlGenerate(aRootUrl);
12056 }
12057
12058 var joined = aPath.charAt(0) === '/'
12059 ? aPath
12060 : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
12061
12062 if (aRootUrl) {
12063 aRootUrl.path = joined;
12064 return urlGenerate(aRootUrl);
12065 }
12066 return joined;
12067 }
12068 exports.join = join;
12069
12070 exports.isAbsolute = function (aPath) {
12071 return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp);
12072 };
12073
12074 /**
12075 * Make a path relative to a URL or another path.
12076 *
12077 * @param aRoot The root path or URL.
12078 * @param aPath The path or URL to be made relative to aRoot.
12079 */
12080 function relative(aRoot, aPath) {
12081 if (aRoot === "") {
12082 aRoot = ".";
12083 }
12084
12085 aRoot = aRoot.replace(/\/$/, '');
12086
12087 // It is possible for the path to be above the root. In this case, simply
12088 // checking whether the root is a prefix of the path won't work. Instead, we
12089 // need to remove components from the root one by one, until either we find
12090 // a prefix that fits, or we run out of components to remove.
12091 var level = 0;
12092 while (aPath.indexOf(aRoot + '/') !== 0) {
12093 var index = aRoot.lastIndexOf("/");
12094 if (index < 0) {
12095 return aPath;
12096 }
12097
12098 // If the only part of the root that is left is the scheme (i.e. http://,
12099 // file:///, etc.), one or more slashes (/), or simply nothing at all, we
12100 // have exhausted all components, so the path is not relative to the root.
12101 aRoot = aRoot.slice(0, index);
12102 if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
12103 return aPath;
12104 }
12105
12106 ++level;
12107 }
12108
12109 // Make sure we add a "../" for each component we removed from the root.
12110 return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
12111 }
12112 exports.relative = relative;
12113
12114 var supportsNullProto = (function () {
12115 var obj = Object.create(null);
12116 return !('__proto__' in obj);
12117 }());
12118
12119 function identity (s) {
12120 return s;
12121 }
12122
12123 /**
12124 * Because behavior goes wacky when you set `__proto__` on objects, we
12125 * have to prefix all the strings in our set with an arbitrary character.
12126 *
12127 * See https://github.com/mozilla/source-map/pull/31 and
12128 * https://github.com/mozilla/source-map/issues/30
12129 *
12130 * @param String aStr
12131 */
12132 function toSetString(aStr) {
12133 if (isProtoString(aStr)) {
12134 return '$' + aStr;
12135 }
12136
12137 return aStr;
12138 }
12139 exports.toSetString = supportsNullProto ? identity : toSetString;
12140
12141 function fromSetString(aStr) {
12142 if (isProtoString(aStr)) {
12143 return aStr.slice(1);
12144 }
12145
12146 return aStr;
12147 }
12148 exports.fromSetString = supportsNullProto ? identity : fromSetString;
12149
12150 function isProtoString(s) {
12151 if (!s) {
12152 return false;
12153 }
12154
12155 var length = s.length;
12156
12157 if (length < 9 /* "__proto__".length */) {
12158 return false;
12159 }
12160
12161 if (s.charCodeAt(length - 1) !== 95 /* '_' */ ||
12162 s.charCodeAt(length - 2) !== 95 /* '_' */ ||
12163 s.charCodeAt(length - 3) !== 111 /* 'o' */ ||
12164 s.charCodeAt(length - 4) !== 116 /* 't' */ ||
12165 s.charCodeAt(length - 5) !== 111 /* 'o' */ ||
12166 s.charCodeAt(length - 6) !== 114 /* 'r' */ ||
12167 s.charCodeAt(length - 7) !== 112 /* 'p' */ ||
12168 s.charCodeAt(length - 8) !== 95 /* '_' */ ||
12169 s.charCodeAt(length - 9) !== 95 /* '_' */) {
12170 return false;
12171 }
12172
12173 for (var i = length - 10; i >= 0; i--) {
12174 if (s.charCodeAt(i) !== 36 /* '$' */) {
12175 return false;
12176 }
12177 }
12178
12179 return true;
12180 }
12181
12182 /**
12183 * Comparator between two mappings where the original positions are compared.
12184 *
12185 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
12186 * mappings with the same original source/line/column, but different generated
12187 * line and column the same. Useful when searching for a mapping with a
12188 * stubbed out mapping.
12189 */
12190 function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
12191 var cmp = mappingA.source - mappingB.source;
12192 if (cmp !== 0) {
12193 return cmp;
12194 }
12195
12196 cmp = mappingA.originalLine - mappingB.originalLine;
12197 if (cmp !== 0) {
12198 return cmp;
12199 }
12200
12201 cmp = mappingA.originalColumn - mappingB.originalColumn;
12202 if (cmp !== 0 || onlyCompareOriginal) {
12203 return cmp;
12204 }
12205
12206 cmp = mappingA.generatedColumn - mappingB.generatedColumn;
12207 if (cmp !== 0) {
12208 return cmp;
12209 }
12210
12211 cmp = mappingA.generatedLine - mappingB.generatedLine;
12212 if (cmp !== 0) {
12213 return cmp;
12214 }
12215
12216 return mappingA.name - mappingB.name;
12217 }
12218 exports.compareByOriginalPositions = compareByOriginalPositions;
12219
12220 /**
12221 * Comparator between two mappings with deflated source and name indices where
12222 * the generated positions are compared.
12223 *
12224 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
12225 * mappings with the same generated line and column, but different
12226 * source/name/original line and column the same. Useful when searching for a
12227 * mapping with a stubbed out mapping.
12228 */
12229 function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
12230 var cmp = mappingA.generatedLine - mappingB.generatedLine;
12231 if (cmp !== 0) {
12232 return cmp;
12233 }
12234
12235 cmp = mappingA.generatedColumn - mappingB.generatedColumn;
12236 if (cmp !== 0 || onlyCompareGenerated) {
12237 return cmp;
12238 }
12239
12240 cmp = mappingA.source - mappingB.source;
12241 if (cmp !== 0) {
12242 return cmp;
12243 }
12244
12245 cmp = mappingA.originalLine - mappingB.originalLine;
12246 if (cmp !== 0) {
12247 return cmp;
12248 }
12249
12250 cmp = mappingA.originalColumn - mappingB.originalColumn;
12251 if (cmp !== 0) {
12252 return cmp;
12253 }
12254
12255 return mappingA.name - mappingB.name;
12256 }
12257 exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
12258
12259 function strcmp(aStr1, aStr2) {
12260 if (aStr1 === aStr2) {
12261 return 0;
12262 }
12263
12264 if (aStr1 > aStr2) {
12265 return 1;
12266 }
12267
12268 return -1;
12269 }
12270
12271 /**
12272 * Comparator between two mappings with inflated source and name strings where
12273 * the generated positions are compared.
12274 */
12275 function compareByGeneratedPositionsInflated(mappingA, mappingB) {
12276 var cmp = mappingA.generatedLine - mappingB.generatedLine;
12277 if (cmp !== 0) {
12278 return cmp;
12279 }
12280
12281 cmp = mappingA.generatedColumn - mappingB.generatedColumn;
12282 if (cmp !== 0) {
12283 return cmp;
12284 }
12285
12286 cmp = strcmp(mappingA.source, mappingB.source);
12287 if (cmp !== 0) {
12288 return cmp;
12289 }
12290
12291 cmp = mappingA.originalLine - mappingB.originalLine;
12292 if (cmp !== 0) {
12293 return cmp;
12294 }
12295
12296 cmp = mappingA.originalColumn - mappingB.originalColumn;
12297 if (cmp !== 0) {
12298 return cmp;
12299 }
12300
12301 return strcmp(mappingA.name, mappingB.name);
12302 }
12303 exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
12304
12305
12306/***/ },
12307/* 5 */
12308/***/ function(module, exports, __webpack_require__) {
12309
12310 /* -*- Mode: js; js-indent-level: 2; -*- */
12311 /*
12312 * Copyright 2011 Mozilla Foundation and contributors
12313 * Licensed under the New BSD license. See LICENSE or:
12314 * http://opensource.org/licenses/BSD-3-Clause
12315 */
12316
12317 var util = __webpack_require__(4);
12318 var has = Object.prototype.hasOwnProperty;
12319
12320 /**
12321 * A data structure which is a combination of an array and a set. Adding a new
12322 * member is O(1), testing for membership is O(1), and finding the index of an
12323 * element is O(1). Removing elements from the set is not supported. Only
12324 * strings are supported for membership.
12325 */
12326 function ArraySet() {
12327 this._array = [];
12328 this._set = Object.create(null);
12329 }
12330
12331 /**
12332 * Static method for creating ArraySet instances from an existing array.
12333 */
12334 ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
12335 var set = new ArraySet();
12336 for (var i = 0, len = aArray.length; i < len; i++) {
12337 set.add(aArray[i], aAllowDuplicates);
12338 }
12339 return set;
12340 };
12341
12342 /**
12343 * Return how many unique items are in this ArraySet. If duplicates have been
12344 * added, than those do not count towards the size.
12345 *
12346 * @returns Number
12347 */
12348 ArraySet.prototype.size = function ArraySet_size() {
12349 return Object.getOwnPropertyNames(this._set).length;
12350 };
12351
12352 /**
12353 * Add the given string to this set.
12354 *
12355 * @param String aStr
12356 */
12357 ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
12358 var sStr = util.toSetString(aStr);
12359 var isDuplicate = has.call(this._set, sStr);
12360 var idx = this._array.length;
12361 if (!isDuplicate || aAllowDuplicates) {
12362 this._array.push(aStr);
12363 }
12364 if (!isDuplicate) {
12365 this._set[sStr] = idx;
12366 }
12367 };
12368
12369 /**
12370 * Is the given string a member of this set?
12371 *
12372 * @param String aStr
12373 */
12374 ArraySet.prototype.has = function ArraySet_has(aStr) {
12375 var sStr = util.toSetString(aStr);
12376 return has.call(this._set, sStr);
12377 };
12378
12379 /**
12380 * What is the index of the given string in the array?
12381 *
12382 * @param String aStr
12383 */
12384 ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
12385 var sStr = util.toSetString(aStr);
12386 if (has.call(this._set, sStr)) {
12387 return this._set[sStr];
12388 }
12389 throw new Error('"' + aStr + '" is not in the set.');
12390 };
12391
12392 /**
12393 * What is the element at the given index?
12394 *
12395 * @param Number aIdx
12396 */
12397 ArraySet.prototype.at = function ArraySet_at(aIdx) {
12398 if (aIdx >= 0 && aIdx < this._array.length) {
12399 return this._array[aIdx];
12400 }
12401 throw new Error('No element indexed by ' + aIdx);
12402 };
12403
12404 /**
12405 * Returns the array representation of this set (which has the proper indices
12406 * indicated by indexOf). Note that this is a copy of the internal array used
12407 * for storing the members so that no one can mess with internal state.
12408 */
12409 ArraySet.prototype.toArray = function ArraySet_toArray() {
12410 return this._array.slice();
12411 };
12412
12413 exports.ArraySet = ArraySet;
12414
12415
12416/***/ },
12417/* 6 */
12418/***/ function(module, exports, __webpack_require__) {
12419
12420 /* -*- Mode: js; js-indent-level: 2; -*- */
12421 /*
12422 * Copyright 2014 Mozilla Foundation and contributors
12423 * Licensed under the New BSD license. See LICENSE or:
12424 * http://opensource.org/licenses/BSD-3-Clause
12425 */
12426
12427 var util = __webpack_require__(4);
12428
12429 /**
12430 * Determine whether mappingB is after mappingA with respect to generated
12431 * position.
12432 */
12433 function generatedPositionAfter(mappingA, mappingB) {
12434 // Optimized for most common case
12435 var lineA = mappingA.generatedLine;
12436 var lineB = mappingB.generatedLine;
12437 var columnA = mappingA.generatedColumn;
12438 var columnB = mappingB.generatedColumn;
12439 return lineB > lineA || lineB == lineA && columnB >= columnA ||
12440 util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
12441 }
12442
12443 /**
12444 * A data structure to provide a sorted view of accumulated mappings in a
12445 * performance conscious manner. It trades a neglibable overhead in general
12446 * case for a large speedup in case of mappings being added in order.
12447 */
12448 function MappingList() {
12449 this._array = [];
12450 this._sorted = true;
12451 // Serves as infimum
12452 this._last = {generatedLine: -1, generatedColumn: 0};
12453 }
12454
12455 /**
12456 * Iterate through internal items. This method takes the same arguments that
12457 * `Array.prototype.forEach` takes.
12458 *
12459 * NOTE: The order of the mappings is NOT guaranteed.
12460 */
12461 MappingList.prototype.unsortedForEach =
12462 function MappingList_forEach(aCallback, aThisArg) {
12463 this._array.forEach(aCallback, aThisArg);
12464 };
12465
12466 /**
12467 * Add the given source mapping.
12468 *
12469 * @param Object aMapping
12470 */
12471 MappingList.prototype.add = function MappingList_add(aMapping) {
12472 if (generatedPositionAfter(this._last, aMapping)) {
12473 this._last = aMapping;
12474 this._array.push(aMapping);
12475 } else {
12476 this._sorted = false;
12477 this._array.push(aMapping);
12478 }
12479 };
12480
12481 /**
12482 * Returns the flat, sorted array of mappings. The mappings are sorted by
12483 * generated position.
12484 *
12485 * WARNING: This method returns internal data without copying, for
12486 * performance. The return value must NOT be mutated, and should be treated as
12487 * an immutable borrow. If you want to take ownership, you must make your own
12488 * copy.
12489 */
12490 MappingList.prototype.toArray = function MappingList_toArray() {
12491 if (!this._sorted) {
12492 this._array.sort(util.compareByGeneratedPositionsInflated);
12493 this._sorted = true;
12494 }
12495 return this._array;
12496 };
12497
12498 exports.MappingList = MappingList;
12499
12500
12501/***/ },
12502/* 7 */
12503/***/ function(module, exports, __webpack_require__) {
12504
12505 /* -*- Mode: js; js-indent-level: 2; -*- */
12506 /*
12507 * Copyright 2011 Mozilla Foundation and contributors
12508 * Licensed under the New BSD license. See LICENSE or:
12509 * http://opensource.org/licenses/BSD-3-Clause
12510 */
12511
12512 var util = __webpack_require__(4);
12513 var binarySearch = __webpack_require__(8);
12514 var ArraySet = __webpack_require__(5).ArraySet;
12515 var base64VLQ = __webpack_require__(2);
12516 var quickSort = __webpack_require__(9).quickSort;
12517
12518 function SourceMapConsumer(aSourceMap) {
12519 var sourceMap = aSourceMap;
12520 if (typeof aSourceMap === 'string') {
12521 sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
12522 }
12523
12524 return sourceMap.sections != null
12525 ? new IndexedSourceMapConsumer(sourceMap)
12526 : new BasicSourceMapConsumer(sourceMap);
12527 }
12528
12529 SourceMapConsumer.fromSourceMap = function(aSourceMap) {
12530 return BasicSourceMapConsumer.fromSourceMap(aSourceMap);
12531 }
12532
12533 /**
12534 * The version of the source mapping spec that we are consuming.
12535 */
12536 SourceMapConsumer.prototype._version = 3;
12537
12538 // `__generatedMappings` and `__originalMappings` are arrays that hold the
12539 // parsed mapping coordinates from the source map's "mappings" attribute. They
12540 // are lazily instantiated, accessed via the `_generatedMappings` and
12541 // `_originalMappings` getters respectively, and we only parse the mappings
12542 // and create these arrays once queried for a source location. We jump through
12543 // these hoops because there can be many thousands of mappings, and parsing
12544 // them is expensive, so we only want to do it if we must.
12545 //
12546 // Each object in the arrays is of the form:
12547 //
12548 // {
12549 // generatedLine: The line number in the generated code,
12550 // generatedColumn: The column number in the generated code,
12551 // source: The path to the original source file that generated this
12552 // chunk of code,
12553 // originalLine: The line number in the original source that
12554 // corresponds to this chunk of generated code,
12555 // originalColumn: The column number in the original source that
12556 // corresponds to this chunk of generated code,
12557 // name: The name of the original symbol which generated this chunk of
12558 // code.
12559 // }
12560 //
12561 // All properties except for `generatedLine` and `generatedColumn` can be
12562 // `null`.
12563 //
12564 // `_generatedMappings` is ordered by the generated positions.
12565 //
12566 // `_originalMappings` is ordered by the original positions.
12567
12568 SourceMapConsumer.prototype.__generatedMappings = null;
12569 Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {
12570 get: function () {
12571 if (!this.__generatedMappings) {
12572 this._parseMappings(this._mappings, this.sourceRoot);
12573 }
12574
12575 return this.__generatedMappings;
12576 }
12577 });
12578
12579 SourceMapConsumer.prototype.__originalMappings = null;
12580 Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {
12581 get: function () {
12582 if (!this.__originalMappings) {
12583 this._parseMappings(this._mappings, this.sourceRoot);
12584 }
12585
12586 return this.__originalMappings;
12587 }
12588 });
12589
12590 SourceMapConsumer.prototype._charIsMappingSeparator =
12591 function SourceMapConsumer_charIsMappingSeparator(aStr, index) {
12592 var c = aStr.charAt(index);
12593 return c === ";" || c === ",";
12594 };
12595
12596 /**
12597 * Parse the mappings in a string in to a data structure which we can easily
12598 * query (the ordered arrays in the `this.__generatedMappings` and
12599 * `this.__originalMappings` properties).
12600 */
12601 SourceMapConsumer.prototype._parseMappings =
12602 function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
12603 throw new Error("Subclasses must implement _parseMappings");
12604 };
12605
12606 SourceMapConsumer.GENERATED_ORDER = 1;
12607 SourceMapConsumer.ORIGINAL_ORDER = 2;
12608
12609 SourceMapConsumer.GREATEST_LOWER_BOUND = 1;
12610 SourceMapConsumer.LEAST_UPPER_BOUND = 2;
12611
12612 /**
12613 * Iterate over each mapping between an original source/line/column and a
12614 * generated line/column in this source map.
12615 *
12616 * @param Function aCallback
12617 * The function that is called with each mapping.
12618 * @param Object aContext
12619 * Optional. If specified, this object will be the value of `this` every
12620 * time that `aCallback` is called.
12621 * @param aOrder
12622 * Either `SourceMapConsumer.GENERATED_ORDER` or
12623 * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
12624 * iterate over the mappings sorted by the generated file's line/column
12625 * order or the original's source/line/column order, respectively. Defaults to
12626 * `SourceMapConsumer.GENERATED_ORDER`.
12627 */
12628 SourceMapConsumer.prototype.eachMapping =
12629 function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
12630 var context = aContext || null;
12631 var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
12632
12633 var mappings;
12634 switch (order) {
12635 case SourceMapConsumer.GENERATED_ORDER:
12636 mappings = this._generatedMappings;
12637 break;
12638 case SourceMapConsumer.ORIGINAL_ORDER:
12639 mappings = this._originalMappings;
12640 break;
12641 default:
12642 throw new Error("Unknown order of iteration.");
12643 }
12644
12645 var sourceRoot = this.sourceRoot;
12646 mappings.map(function (mapping) {
12647 var source = mapping.source === null ? null : this._sources.at(mapping.source);
12648 if (source != null && sourceRoot != null) {
12649 source = util.join(sourceRoot, source);
12650 }
12651 return {
12652 source: source,
12653 generatedLine: mapping.generatedLine,
12654 generatedColumn: mapping.generatedColumn,
12655 originalLine: mapping.originalLine,
12656 originalColumn: mapping.originalColumn,
12657 name: mapping.name === null ? null : this._names.at(mapping.name)
12658 };
12659 }, this).forEach(aCallback, context);
12660 };
12661
12662 /**
12663 * Returns all generated line and column information for the original source,
12664 * line, and column provided. If no column is provided, returns all mappings
12665 * corresponding to a either the line we are searching for or the next
12666 * closest line that has any mappings. Otherwise, returns all mappings
12667 * corresponding to the given line and either the column we are searching for
12668 * or the next closest column that has any offsets.
12669 *
12670 * The only argument is an object with the following properties:
12671 *
12672 * - source: The filename of the original source.
12673 * - line: The line number in the original source.
12674 * - column: Optional. the column number in the original source.
12675 *
12676 * and an array of objects is returned, each with the following properties:
12677 *
12678 * - line: The line number in the generated source, or null.
12679 * - column: The column number in the generated source, or null.
12680 */
12681 SourceMapConsumer.prototype.allGeneratedPositionsFor =
12682 function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {
12683 var line = util.getArg(aArgs, 'line');
12684
12685 // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping
12686 // returns the index of the closest mapping less than the needle. By
12687 // setting needle.originalColumn to 0, we thus find the last mapping for
12688 // the given line, provided such a mapping exists.
12689 var needle = {
12690 source: util.getArg(aArgs, 'source'),
12691 originalLine: line,
12692 originalColumn: util.getArg(aArgs, 'column', 0)
12693 };
12694
12695 if (this.sourceRoot != null) {
12696 needle.source = util.relative(this.sourceRoot, needle.source);
12697 }
12698 if (!this._sources.has(needle.source)) {
12699 return [];
12700 }
12701 needle.source = this._sources.indexOf(needle.source);
12702
12703 var mappings = [];
12704
12705 var index = this._findMapping(needle,
12706 this._originalMappings,
12707 "originalLine",
12708 "originalColumn",
12709 util.compareByOriginalPositions,
12710 binarySearch.LEAST_UPPER_BOUND);
12711 if (index >= 0) {
12712 var mapping = this._originalMappings[index];
12713
12714 if (aArgs.column === undefined) {
12715 var originalLine = mapping.originalLine;
12716
12717 // Iterate until either we run out of mappings, or we run into
12718 // a mapping for a different line than the one we found. Since
12719 // mappings are sorted, this is guaranteed to find all mappings for
12720 // the line we found.
12721 while (mapping && mapping.originalLine === originalLine) {
12722 mappings.push({
12723 line: util.getArg(mapping, 'generatedLine', null),
12724 column: util.getArg(mapping, 'generatedColumn', null),
12725 lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
12726 });
12727
12728 mapping = this._originalMappings[++index];
12729 }
12730 } else {
12731 var originalColumn = mapping.originalColumn;
12732
12733 // Iterate until either we run out of mappings, or we run into
12734 // a mapping for a different line than the one we were searching for.
12735 // Since mappings are sorted, this is guaranteed to find all mappings for
12736 // the line we are searching for.
12737 while (mapping &&
12738 mapping.originalLine === line &&
12739 mapping.originalColumn == originalColumn) {
12740 mappings.push({
12741 line: util.getArg(mapping, 'generatedLine', null),
12742 column: util.getArg(mapping, 'generatedColumn', null),
12743 lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
12744 });
12745
12746 mapping = this._originalMappings[++index];
12747 }
12748 }
12749 }
12750
12751 return mappings;
12752 };
12753
12754 exports.SourceMapConsumer = SourceMapConsumer;
12755
12756 /**
12757 * A BasicSourceMapConsumer instance represents a parsed source map which we can
12758 * query for information about the original file positions by giving it a file
12759 * position in the generated source.
12760 *
12761 * The only parameter is the raw source map (either as a JSON string, or
12762 * already parsed to an object). According to the spec, source maps have the
12763 * following attributes:
12764 *
12765 * - version: Which version of the source map spec this map is following.
12766 * - sources: An array of URLs to the original source files.
12767 * - names: An array of identifiers which can be referrenced by individual mappings.
12768 * - sourceRoot: Optional. The URL root from which all sources are relative.
12769 * - sourcesContent: Optional. An array of contents of the original source files.
12770 * - mappings: A string of base64 VLQs which contain the actual mappings.
12771 * - file: Optional. The generated file this source map is associated with.
12772 *
12773 * Here is an example source map, taken from the source map spec[0]:
12774 *
12775 * {
12776 * version : 3,
12777 * file: "out.js",
12778 * sourceRoot : "",
12779 * sources: ["foo.js", "bar.js"],
12780 * names: ["src", "maps", "are", "fun"],
12781 * mappings: "AA,AB;;ABCDE;"
12782 * }
12783 *
12784 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
12785 */
12786 function BasicSourceMapConsumer(aSourceMap) {
12787 var sourceMap = aSourceMap;
12788 if (typeof aSourceMap === 'string') {
12789 sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
12790 }
12791
12792 var version = util.getArg(sourceMap, 'version');
12793 var sources = util.getArg(sourceMap, 'sources');
12794 // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which
12795 // requires the array) to play nice here.
12796 var names = util.getArg(sourceMap, 'names', []);
12797 var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
12798 var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
12799 var mappings = util.getArg(sourceMap, 'mappings');
12800 var file = util.getArg(sourceMap, 'file', null);
12801
12802 // Once again, Sass deviates from the spec and supplies the version as a
12803 // string rather than a number, so we use loose equality checking here.
12804 if (version != this._version) {
12805 throw new Error('Unsupported version: ' + version);
12806 }
12807
12808 sources = sources
12809 .map(String)
12810 // Some source maps produce relative source paths like "./foo.js" instead of
12811 // "foo.js". Normalize these first so that future comparisons will succeed.
12812 // See bugzil.la/1090768.
12813 .map(util.normalize)
12814 // Always ensure that absolute sources are internally stored relative to
12815 // the source root, if the source root is absolute. Not doing this would
12816 // be particularly problematic when the source root is a prefix of the
12817 // source (valid, but why??). See github issue #199 and bugzil.la/1188982.
12818 .map(function (source) {
12819 return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
12820 ? util.relative(sourceRoot, source)
12821 : source;
12822 });
12823
12824 // Pass `true` below to allow duplicate names and sources. While source maps
12825 // are intended to be compressed and deduplicated, the TypeScript compiler
12826 // sometimes generates source maps with duplicates in them. See Github issue
12827 // #72 and bugzil.la/889492.
12828 this._names = ArraySet.fromArray(names.map(String), true);
12829 this._sources = ArraySet.fromArray(sources, true);
12830
12831 this.sourceRoot = sourceRoot;
12832 this.sourcesContent = sourcesContent;
12833 this._mappings = mappings;
12834 this.file = file;
12835 }
12836
12837 BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
12838 BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;
12839
12840 /**
12841 * Create a BasicSourceMapConsumer from a SourceMapGenerator.
12842 *
12843 * @param SourceMapGenerator aSourceMap
12844 * The source map that will be consumed.
12845 * @returns BasicSourceMapConsumer
12846 */
12847 BasicSourceMapConsumer.fromSourceMap =
12848 function SourceMapConsumer_fromSourceMap(aSourceMap) {
12849 var smc = Object.create(BasicSourceMapConsumer.prototype);
12850
12851 var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
12852 var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
12853 smc.sourceRoot = aSourceMap._sourceRoot;
12854 smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),
12855 smc.sourceRoot);
12856 smc.file = aSourceMap._file;
12857
12858 // Because we are modifying the entries (by converting string sources and
12859 // names to indices into the sources and names ArraySets), we have to make
12860 // a copy of the entry or else bad things happen. Shared mutable state
12861 // strikes again! See github issue #191.
12862
12863 var generatedMappings = aSourceMap._mappings.toArray().slice();
12864 var destGeneratedMappings = smc.__generatedMappings = [];
12865 var destOriginalMappings = smc.__originalMappings = [];
12866
12867 for (var i = 0, length = generatedMappings.length; i < length; i++) {
12868 var srcMapping = generatedMappings[i];
12869 var destMapping = new Mapping;
12870 destMapping.generatedLine = srcMapping.generatedLine;
12871 destMapping.generatedColumn = srcMapping.generatedColumn;
12872
12873 if (srcMapping.source) {
12874 destMapping.source = sources.indexOf(srcMapping.source);
12875 destMapping.originalLine = srcMapping.originalLine;
12876 destMapping.originalColumn = srcMapping.originalColumn;
12877
12878 if (srcMapping.name) {
12879 destMapping.name = names.indexOf(srcMapping.name);
12880 }
12881
12882 destOriginalMappings.push(destMapping);
12883 }
12884
12885 destGeneratedMappings.push(destMapping);
12886 }
12887
12888 quickSort(smc.__originalMappings, util.compareByOriginalPositions);
12889
12890 return smc;
12891 };
12892
12893 /**
12894 * The version of the source mapping spec that we are consuming.
12895 */
12896 BasicSourceMapConsumer.prototype._version = 3;
12897
12898 /**
12899 * The list of original sources.
12900 */
12901 Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {
12902 get: function () {
12903 return this._sources.toArray().map(function (s) {
12904 return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;
12905 }, this);
12906 }
12907 });
12908
12909 /**
12910 * Provide the JIT with a nice shape / hidden class.
12911 */
12912 function Mapping() {
12913 this.generatedLine = 0;
12914 this.generatedColumn = 0;
12915 this.source = null;
12916 this.originalLine = null;
12917 this.originalColumn = null;
12918 this.name = null;
12919 }
12920
12921 /**
12922 * Parse the mappings in a string in to a data structure which we can easily
12923 * query (the ordered arrays in the `this.__generatedMappings` and
12924 * `this.__originalMappings` properties).
12925 */
12926 BasicSourceMapConsumer.prototype._parseMappings =
12927 function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
12928 var generatedLine = 1;
12929 var previousGeneratedColumn = 0;
12930 var previousOriginalLine = 0;
12931 var previousOriginalColumn = 0;
12932 var previousSource = 0;
12933 var previousName = 0;
12934 var length = aStr.length;
12935 var index = 0;
12936 var cachedSegments = {};
12937 var temp = {};
12938 var originalMappings = [];
12939 var generatedMappings = [];
12940 var mapping, str, segment, end, value;
12941
12942 while (index < length) {
12943 if (aStr.charAt(index) === ';') {
12944 generatedLine++;
12945 index++;
12946 previousGeneratedColumn = 0;
12947 }
12948 else if (aStr.charAt(index) === ',') {
12949 index++;
12950 }
12951 else {
12952 mapping = new Mapping();
12953 mapping.generatedLine = generatedLine;
12954
12955 // Because each offset is encoded relative to the previous one,
12956 // many segments often have the same encoding. We can exploit this
12957 // fact by caching the parsed variable length fields of each segment,
12958 // allowing us to avoid a second parse if we encounter the same
12959 // segment again.
12960 for (end = index; end < length; end++) {
12961 if (this._charIsMappingSeparator(aStr, end)) {
12962 break;
12963 }
12964 }
12965 str = aStr.slice(index, end);
12966
12967 segment = cachedSegments[str];
12968 if (segment) {
12969 index += str.length;
12970 } else {
12971 segment = [];
12972 while (index < end) {
12973 base64VLQ.decode(aStr, index, temp);
12974 value = temp.value;
12975 index = temp.rest;
12976 segment.push(value);
12977 }
12978
12979 if (segment.length === 2) {
12980 throw new Error('Found a source, but no line and column');
12981 }
12982
12983 if (segment.length === 3) {
12984 throw new Error('Found a source and line, but no column');
12985 }
12986
12987 cachedSegments[str] = segment;
12988 }
12989
12990 // Generated column.
12991 mapping.generatedColumn = previousGeneratedColumn + segment[0];
12992 previousGeneratedColumn = mapping.generatedColumn;
12993
12994 if (segment.length > 1) {
12995 // Original source.
12996 mapping.source = previousSource + segment[1];
12997 previousSource += segment[1];
12998
12999 // Original line.
13000 mapping.originalLine = previousOriginalLine + segment[2];
13001 previousOriginalLine = mapping.originalLine;
13002 // Lines are stored 0-based
13003 mapping.originalLine += 1;
13004
13005 // Original column.
13006 mapping.originalColumn = previousOriginalColumn + segment[3];
13007 previousOriginalColumn = mapping.originalColumn;
13008
13009 if (segment.length > 4) {
13010 // Original name.
13011 mapping.name = previousName + segment[4];
13012 previousName += segment[4];
13013 }
13014 }
13015
13016 generatedMappings.push(mapping);
13017 if (typeof mapping.originalLine === 'number') {
13018 originalMappings.push(mapping);
13019 }
13020 }
13021 }
13022
13023 quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated);
13024 this.__generatedMappings = generatedMappings;
13025
13026 quickSort(originalMappings, util.compareByOriginalPositions);
13027 this.__originalMappings = originalMappings;
13028 };
13029
13030 /**
13031 * Find the mapping that best matches the hypothetical "needle" mapping that
13032 * we are searching for in the given "haystack" of mappings.
13033 */
13034 BasicSourceMapConsumer.prototype._findMapping =
13035 function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
13036 aColumnName, aComparator, aBias) {
13037 // To return the position we are searching for, we must first find the
13038 // mapping for the given position and then return the opposite position it
13039 // points to. Because the mappings are sorted, we can use binary search to
13040 // find the best mapping.
13041
13042 if (aNeedle[aLineName] <= 0) {
13043 throw new TypeError('Line must be greater than or equal to 1, got '
13044 + aNeedle[aLineName]);
13045 }
13046 if (aNeedle[aColumnName] < 0) {
13047 throw new TypeError('Column must be greater than or equal to 0, got '
13048 + aNeedle[aColumnName]);
13049 }
13050
13051 return binarySearch.search(aNeedle, aMappings, aComparator, aBias);
13052 };
13053
13054 /**
13055 * Compute the last column for each generated mapping. The last column is
13056 * inclusive.
13057 */
13058 BasicSourceMapConsumer.prototype.computeColumnSpans =
13059 function SourceMapConsumer_computeColumnSpans() {
13060 for (var index = 0; index < this._generatedMappings.length; ++index) {
13061 var mapping = this._generatedMappings[index];
13062
13063 // Mappings do not contain a field for the last generated columnt. We
13064 // can come up with an optimistic estimate, however, by assuming that
13065 // mappings are contiguous (i.e. given two consecutive mappings, the
13066 // first mapping ends where the second one starts).
13067 if (index + 1 < this._generatedMappings.length) {
13068 var nextMapping = this._generatedMappings[index + 1];
13069
13070 if (mapping.generatedLine === nextMapping.generatedLine) {
13071 mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;
13072 continue;
13073 }
13074 }
13075
13076 // The last mapping for each line spans the entire line.
13077 mapping.lastGeneratedColumn = Infinity;
13078 }
13079 };
13080
13081 /**
13082 * Returns the original source, line, and column information for the generated
13083 * source's line and column positions provided. The only argument is an object
13084 * with the following properties:
13085 *
13086 * - line: The line number in the generated source.
13087 * - column: The column number in the generated source.
13088 * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
13089 * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
13090 * closest element that is smaller than or greater than the one we are
13091 * searching for, respectively, if the exact element cannot be found.
13092 * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
13093 *
13094 * and an object is returned with the following properties:
13095 *
13096 * - source: The original source file, or null.
13097 * - line: The line number in the original source, or null.
13098 * - column: The column number in the original source, or null.
13099 * - name: The original identifier, or null.
13100 */
13101 BasicSourceMapConsumer.prototype.originalPositionFor =
13102 function SourceMapConsumer_originalPositionFor(aArgs) {
13103 var needle = {
13104 generatedLine: util.getArg(aArgs, 'line'),
13105 generatedColumn: util.getArg(aArgs, 'column')
13106 };
13107
13108 var index = this._findMapping(
13109 needle,
13110 this._generatedMappings,
13111 "generatedLine",
13112 "generatedColumn",
13113 util.compareByGeneratedPositionsDeflated,
13114 util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)
13115 );
13116
13117 if (index >= 0) {
13118 var mapping = this._generatedMappings[index];
13119
13120 if (mapping.generatedLine === needle.generatedLine) {
13121 var source = util.getArg(mapping, 'source', null);
13122 if (source !== null) {
13123 source = this._sources.at(source);
13124 if (this.sourceRoot != null) {
13125 source = util.join(this.sourceRoot, source);
13126 }
13127 }
13128 var name = util.getArg(mapping, 'name', null);
13129 if (name !== null) {
13130 name = this._names.at(name);
13131 }
13132 return {
13133 source: source,
13134 line: util.getArg(mapping, 'originalLine', null),
13135 column: util.getArg(mapping, 'originalColumn', null),
13136 name: name
13137 };
13138 }
13139 }
13140
13141 return {
13142 source: null,
13143 line: null,
13144 column: null,
13145 name: null
13146 };
13147 };
13148
13149 /**
13150 * Return true if we have the source content for every source in the source
13151 * map, false otherwise.
13152 */
13153 BasicSourceMapConsumer.prototype.hasContentsOfAllSources =
13154 function BasicSourceMapConsumer_hasContentsOfAllSources() {
13155 if (!this.sourcesContent) {
13156 return false;
13157 }
13158 return this.sourcesContent.length >= this._sources.size() &&
13159 !this.sourcesContent.some(function (sc) { return sc == null; });
13160 };
13161
13162 /**
13163 * Returns the original source content. The only argument is the url of the
13164 * original source file. Returns null if no original source content is
13165 * available.
13166 */
13167 BasicSourceMapConsumer.prototype.sourceContentFor =
13168 function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
13169 if (!this.sourcesContent) {
13170 return null;
13171 }
13172
13173 if (this.sourceRoot != null) {
13174 aSource = util.relative(this.sourceRoot, aSource);
13175 }
13176
13177 if (this._sources.has(aSource)) {
13178 return this.sourcesContent[this._sources.indexOf(aSource)];
13179 }
13180
13181 var url;
13182 if (this.sourceRoot != null
13183 && (url = util.urlParse(this.sourceRoot))) {
13184 // XXX: file:// URIs and absolute paths lead to unexpected behavior for
13185 // many users. We can help them out when they expect file:// URIs to
13186 // behave like it would if they were running a local HTTP server. See
13187 // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
13188 var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
13189 if (url.scheme == "file"
13190 && this._sources.has(fileUriAbsPath)) {
13191 return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
13192 }
13193
13194 if ((!url.path || url.path == "/")
13195 && this._sources.has("/" + aSource)) {
13196 return this.sourcesContent[this._sources.indexOf("/" + aSource)];
13197 }
13198 }
13199
13200 // This function is used recursively from
13201 // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we
13202 // don't want to throw if we can't find the source - we just want to
13203 // return null, so we provide a flag to exit gracefully.
13204 if (nullOnMissing) {
13205 return null;
13206 }
13207 else {
13208 throw new Error('"' + aSource + '" is not in the SourceMap.');
13209 }
13210 };
13211
13212 /**
13213 * Returns the generated line and column information for the original source,
13214 * line, and column positions provided. The only argument is an object with
13215 * the following properties:
13216 *
13217 * - source: The filename of the original source.
13218 * - line: The line number in the original source.
13219 * - column: The column number in the original source.
13220 * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
13221 * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
13222 * closest element that is smaller than or greater than the one we are
13223 * searching for, respectively, if the exact element cannot be found.
13224 * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
13225 *
13226 * and an object is returned with the following properties:
13227 *
13228 * - line: The line number in the generated source, or null.
13229 * - column: The column number in the generated source, or null.
13230 */
13231 BasicSourceMapConsumer.prototype.generatedPositionFor =
13232 function SourceMapConsumer_generatedPositionFor(aArgs) {
13233 var source = util.getArg(aArgs, 'source');
13234 if (this.sourceRoot != null) {
13235 source = util.relative(this.sourceRoot, source);
13236 }
13237 if (!this._sources.has(source)) {
13238 return {
13239 line: null,
13240 column: null,
13241 lastColumn: null
13242 };
13243 }
13244 source = this._sources.indexOf(source);
13245
13246 var needle = {
13247 source: source,
13248 originalLine: util.getArg(aArgs, 'line'),
13249 originalColumn: util.getArg(aArgs, 'column')
13250 };
13251
13252 var index = this._findMapping(
13253 needle,
13254 this._originalMappings,
13255 "originalLine",
13256 "originalColumn",
13257 util.compareByOriginalPositions,
13258 util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)
13259 );
13260
13261 if (index >= 0) {
13262 var mapping = this._originalMappings[index];
13263
13264 if (mapping.source === needle.source) {
13265 return {
13266 line: util.getArg(mapping, 'generatedLine', null),
13267 column: util.getArg(mapping, 'generatedColumn', null),
13268 lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
13269 };
13270 }
13271 }
13272
13273 return {
13274 line: null,
13275 column: null,
13276 lastColumn: null
13277 };
13278 };
13279
13280 exports.BasicSourceMapConsumer = BasicSourceMapConsumer;
13281
13282 /**
13283 * An IndexedSourceMapConsumer instance represents a parsed source map which
13284 * we can query for information. It differs from BasicSourceMapConsumer in
13285 * that it takes "indexed" source maps (i.e. ones with a "sections" field) as
13286 * input.
13287 *
13288 * The only parameter is a raw source map (either as a JSON string, or already
13289 * parsed to an object). According to the spec for indexed source maps, they
13290 * have the following attributes:
13291 *
13292 * - version: Which version of the source map spec this map is following.
13293 * - file: Optional. The generated file this source map is associated with.
13294 * - sections: A list of section definitions.
13295 *
13296 * Each value under the "sections" field has two fields:
13297 * - offset: The offset into the original specified at which this section
13298 * begins to apply, defined as an object with a "line" and "column"
13299 * field.
13300 * - map: A source map definition. This source map could also be indexed,
13301 * but doesn't have to be.
13302 *
13303 * Instead of the "map" field, it's also possible to have a "url" field
13304 * specifying a URL to retrieve a source map from, but that's currently
13305 * unsupported.
13306 *
13307 * Here's an example source map, taken from the source map spec[0], but
13308 * modified to omit a section which uses the "url" field.
13309 *
13310 * {
13311 * version : 3,
13312 * file: "app.js",
13313 * sections: [{
13314 * offset: {line:100, column:10},
13315 * map: {
13316 * version : 3,
13317 * file: "section.js",
13318 * sources: ["foo.js", "bar.js"],
13319 * names: ["src", "maps", "are", "fun"],
13320 * mappings: "AAAA,E;;ABCDE;"
13321 * }
13322 * }],
13323 * }
13324 *
13325 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt
13326 */
13327 function IndexedSourceMapConsumer(aSourceMap) {
13328 var sourceMap = aSourceMap;
13329 if (typeof aSourceMap === 'string') {
13330 sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
13331 }
13332
13333 var version = util.getArg(sourceMap, 'version');
13334 var sections = util.getArg(sourceMap, 'sections');
13335
13336 if (version != this._version) {
13337 throw new Error('Unsupported version: ' + version);
13338 }
13339
13340 this._sources = new ArraySet();
13341 this._names = new ArraySet();
13342
13343 var lastOffset = {
13344 line: -1,
13345 column: 0
13346 };
13347 this._sections = sections.map(function (s) {
13348 if (s.url) {
13349 // The url field will require support for asynchronicity.
13350 // See https://github.com/mozilla/source-map/issues/16
13351 throw new Error('Support for url field in sections not implemented.');
13352 }
13353 var offset = util.getArg(s, 'offset');
13354 var offsetLine = util.getArg(offset, 'line');
13355 var offsetColumn = util.getArg(offset, 'column');
13356
13357 if (offsetLine < lastOffset.line ||
13358 (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {
13359 throw new Error('Section offsets must be ordered and non-overlapping.');
13360 }
13361 lastOffset = offset;
13362
13363 return {
13364 generatedOffset: {
13365 // The offset fields are 0-based, but we use 1-based indices when
13366 // encoding/decoding from VLQ.
13367 generatedLine: offsetLine + 1,
13368 generatedColumn: offsetColumn + 1
13369 },
13370 consumer: new SourceMapConsumer(util.getArg(s, 'map'))
13371 }
13372 });
13373 }
13374
13375 IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
13376 IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;
13377
13378 /**
13379 * The version of the source mapping spec that we are consuming.
13380 */
13381 IndexedSourceMapConsumer.prototype._version = 3;
13382
13383 /**
13384 * The list of original sources.
13385 */
13386 Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {
13387 get: function () {
13388 var sources = [];
13389 for (var i = 0; i < this._sections.length; i++) {
13390 for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {
13391 sources.push(this._sections[i].consumer.sources[j]);
13392 }
13393 }
13394 return sources;
13395 }
13396 });
13397
13398 /**
13399 * Returns the original source, line, and column information for the generated
13400 * source's line and column positions provided. The only argument is an object
13401 * with the following properties:
13402 *
13403 * - line: The line number in the generated source.
13404 * - column: The column number in the generated source.
13405 *
13406 * and an object is returned with the following properties:
13407 *
13408 * - source: The original source file, or null.
13409 * - line: The line number in the original source, or null.
13410 * - column: The column number in the original source, or null.
13411 * - name: The original identifier, or null.
13412 */
13413 IndexedSourceMapConsumer.prototype.originalPositionFor =
13414 function IndexedSourceMapConsumer_originalPositionFor(aArgs) {
13415 var needle = {
13416 generatedLine: util.getArg(aArgs, 'line'),
13417 generatedColumn: util.getArg(aArgs, 'column')
13418 };
13419
13420 // Find the section containing the generated position we're trying to map
13421 // to an original position.
13422 var sectionIndex = binarySearch.search(needle, this._sections,
13423 function(needle, section) {
13424 var cmp = needle.generatedLine - section.generatedOffset.generatedLine;
13425 if (cmp) {
13426 return cmp;
13427 }
13428
13429 return (needle.generatedColumn -
13430 section.generatedOffset.generatedColumn);
13431 });
13432 var section = this._sections[sectionIndex];
13433
13434 if (!section) {
13435 return {
13436 source: null,
13437 line: null,
13438 column: null,
13439 name: null
13440 };
13441 }
13442
13443 return section.consumer.originalPositionFor({
13444 line: needle.generatedLine -
13445 (section.generatedOffset.generatedLine - 1),
13446 column: needle.generatedColumn -
13447 (section.generatedOffset.generatedLine === needle.generatedLine
13448 ? section.generatedOffset.generatedColumn - 1
13449 : 0),
13450 bias: aArgs.bias
13451 });
13452 };
13453
13454 /**
13455 * Return true if we have the source content for every source in the source
13456 * map, false otherwise.
13457 */
13458 IndexedSourceMapConsumer.prototype.hasContentsOfAllSources =
13459 function IndexedSourceMapConsumer_hasContentsOfAllSources() {
13460 return this._sections.every(function (s) {
13461 return s.consumer.hasContentsOfAllSources();
13462 });
13463 };
13464
13465 /**
13466 * Returns the original source content. The only argument is the url of the
13467 * original source file. Returns null if no original source content is
13468 * available.
13469 */
13470 IndexedSourceMapConsumer.prototype.sourceContentFor =
13471 function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
13472 for (var i = 0; i < this._sections.length; i++) {
13473 var section = this._sections[i];
13474
13475 var content = section.consumer.sourceContentFor(aSource, true);
13476 if (content) {
13477 return content;
13478 }
13479 }
13480 if (nullOnMissing) {
13481 return null;
13482 }
13483 else {
13484 throw new Error('"' + aSource + '" is not in the SourceMap.');
13485 }
13486 };
13487
13488 /**
13489 * Returns the generated line and column information for the original source,
13490 * line, and column positions provided. The only argument is an object with
13491 * the following properties:
13492 *
13493 * - source: The filename of the original source.
13494 * - line: The line number in the original source.
13495 * - column: The column number in the original source.
13496 *
13497 * and an object is returned with the following properties:
13498 *
13499 * - line: The line number in the generated source, or null.
13500 * - column: The column number in the generated source, or null.
13501 */
13502 IndexedSourceMapConsumer.prototype.generatedPositionFor =
13503 function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {
13504 for (var i = 0; i < this._sections.length; i++) {
13505 var section = this._sections[i];
13506
13507 // Only consider this section if the requested source is in the list of
13508 // sources of the consumer.
13509 if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) {
13510 continue;
13511 }
13512 var generatedPosition = section.consumer.generatedPositionFor(aArgs);
13513 if (generatedPosition) {
13514 var ret = {
13515 line: generatedPosition.line +
13516 (section.generatedOffset.generatedLine - 1),
13517 column: generatedPosition.column +
13518 (section.generatedOffset.generatedLine === generatedPosition.line
13519 ? section.generatedOffset.generatedColumn - 1
13520 : 0)
13521 };
13522 return ret;
13523 }
13524 }
13525
13526 return {
13527 line: null,
13528 column: null
13529 };
13530 };
13531
13532 /**
13533 * Parse the mappings in a string in to a data structure which we can easily
13534 * query (the ordered arrays in the `this.__generatedMappings` and
13535 * `this.__originalMappings` properties).
13536 */
13537 IndexedSourceMapConsumer.prototype._parseMappings =
13538 function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {
13539 this.__generatedMappings = [];
13540 this.__originalMappings = [];
13541 for (var i = 0; i < this._sections.length; i++) {
13542 var section = this._sections[i];
13543 var sectionMappings = section.consumer._generatedMappings;
13544 for (var j = 0; j < sectionMappings.length; j++) {
13545 var mapping = sectionMappings[j];
13546
13547 var source = section.consumer._sources.at(mapping.source);
13548 if (section.consumer.sourceRoot !== null) {
13549 source = util.join(section.consumer.sourceRoot, source);
13550 }
13551 this._sources.add(source);
13552 source = this._sources.indexOf(source);
13553
13554 var name = section.consumer._names.at(mapping.name);
13555 this._names.add(name);
13556 name = this._names.indexOf(name);
13557
13558 // The mappings coming from the consumer for the section have
13559 // generated positions relative to the start of the section, so we
13560 // need to offset them to be relative to the start of the concatenated
13561 // generated file.
13562 var adjustedMapping = {
13563 source: source,
13564 generatedLine: mapping.generatedLine +
13565 (section.generatedOffset.generatedLine - 1),
13566 generatedColumn: mapping.generatedColumn +
13567 (section.generatedOffset.generatedLine === mapping.generatedLine
13568 ? section.generatedOffset.generatedColumn - 1
13569 : 0),
13570 originalLine: mapping.originalLine,
13571 originalColumn: mapping.originalColumn,
13572 name: name
13573 };
13574
13575 this.__generatedMappings.push(adjustedMapping);
13576 if (typeof adjustedMapping.originalLine === 'number') {
13577 this.__originalMappings.push(adjustedMapping);
13578 }
13579 }
13580 }
13581
13582 quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);
13583 quickSort(this.__originalMappings, util.compareByOriginalPositions);
13584 };
13585
13586 exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
13587
13588
13589/***/ },
13590/* 8 */
13591/***/ function(module, exports) {
13592
13593 /* -*- Mode: js; js-indent-level: 2; -*- */
13594 /*
13595 * Copyright 2011 Mozilla Foundation and contributors
13596 * Licensed under the New BSD license. See LICENSE or:
13597 * http://opensource.org/licenses/BSD-3-Clause
13598 */
13599
13600 exports.GREATEST_LOWER_BOUND = 1;
13601 exports.LEAST_UPPER_BOUND = 2;
13602
13603 /**
13604 * Recursive implementation of binary search.
13605 *
13606 * @param aLow Indices here and lower do not contain the needle.
13607 * @param aHigh Indices here and higher do not contain the needle.
13608 * @param aNeedle The element being searched for.
13609 * @param aHaystack The non-empty array being searched.
13610 * @param aCompare Function which takes two elements and returns -1, 0, or 1.
13611 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
13612 * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
13613 * closest element that is smaller than or greater than the one we are
13614 * searching for, respectively, if the exact element cannot be found.
13615 */
13616 function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {
13617 // This function terminates when one of the following is true:
13618 //
13619 // 1. We find the exact element we are looking for.
13620 //
13621 // 2. We did not find the exact element, but we can return the index of
13622 // the next-closest element.
13623 //
13624 // 3. We did not find the exact element, and there is no next-closest
13625 // element than the one we are searching for, so we return -1.
13626 var mid = Math.floor((aHigh - aLow) / 2) + aLow;
13627 var cmp = aCompare(aNeedle, aHaystack[mid], true);
13628 if (cmp === 0) {
13629 // Found the element we are looking for.
13630 return mid;
13631 }
13632 else if (cmp > 0) {
13633 // Our needle is greater than aHaystack[mid].
13634 if (aHigh - mid > 1) {
13635 // The element is in the upper half.
13636 return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);
13637 }
13638
13639 // The exact needle element was not found in this haystack. Determine if
13640 // we are in termination case (3) or (2) and return the appropriate thing.
13641 if (aBias == exports.LEAST_UPPER_BOUND) {
13642 return aHigh < aHaystack.length ? aHigh : -1;
13643 } else {
13644 return mid;
13645 }
13646 }
13647 else {
13648 // Our needle is less than aHaystack[mid].
13649 if (mid - aLow > 1) {
13650 // The element is in the lower half.
13651 return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);
13652 }
13653
13654 // we are in termination case (3) or (2) and return the appropriate thing.
13655 if (aBias == exports.LEAST_UPPER_BOUND) {
13656 return mid;
13657 } else {
13658 return aLow < 0 ? -1 : aLow;
13659 }
13660 }
13661 }
13662
13663 /**
13664 * This is an implementation of binary search which will always try and return
13665 * the index of the closest element if there is no exact hit. This is because
13666 * mappings between original and generated line/col pairs are single points,
13667 * and there is an implicit region between each of them, so a miss just means
13668 * that you aren't on the very start of a region.
13669 *
13670 * @param aNeedle The element you are looking for.
13671 * @param aHaystack The array that is being searched.
13672 * @param aCompare A function which takes the needle and an element in the
13673 * array and returns -1, 0, or 1 depending on whether the needle is less
13674 * than, equal to, or greater than the element, respectively.
13675 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
13676 * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
13677 * closest element that is smaller than or greater than the one we are
13678 * searching for, respectively, if the exact element cannot be found.
13679 * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'.
13680 */
13681 exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {
13682 if (aHaystack.length === 0) {
13683 return -1;
13684 }
13685
13686 var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack,
13687 aCompare, aBias || exports.GREATEST_LOWER_BOUND);
13688 if (index < 0) {
13689 return -1;
13690 }
13691
13692 // We have found either the exact element, or the next-closest element than
13693 // the one we are searching for. However, there may be more than one such
13694 // element. Make sure we always return the smallest of these.
13695 while (index - 1 >= 0) {
13696 if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {
13697 break;
13698 }
13699 --index;
13700 }
13701
13702 return index;
13703 };
13704
13705
13706/***/ },
13707/* 9 */
13708/***/ function(module, exports) {
13709
13710 /* -*- Mode: js; js-indent-level: 2; -*- */
13711 /*
13712 * Copyright 2011 Mozilla Foundation and contributors
13713 * Licensed under the New BSD license. See LICENSE or:
13714 * http://opensource.org/licenses/BSD-3-Clause
13715 */
13716
13717 // It turns out that some (most?) JavaScript engines don't self-host
13718 // `Array.prototype.sort`. This makes sense because C++ will likely remain
13719 // faster than JS when doing raw CPU-intensive sorting. However, when using a
13720 // custom comparator function, calling back and forth between the VM's C++ and
13721 // JIT'd JS is rather slow *and* loses JIT type information, resulting in
13722 // worse generated code for the comparator function than would be optimal. In
13723 // fact, when sorting with a comparator, these costs outweigh the benefits of
13724 // sorting in C++. By using our own JS-implemented Quick Sort (below), we get
13725 // a ~3500ms mean speed-up in `bench/bench.html`.
13726
13727 /**
13728 * Swap the elements indexed by `x` and `y` in the array `ary`.
13729 *
13730 * @param {Array} ary
13731 * The array.
13732 * @param {Number} x
13733 * The index of the first item.
13734 * @param {Number} y
13735 * The index of the second item.
13736 */
13737 function swap(ary, x, y) {
13738 var temp = ary[x];
13739 ary[x] = ary[y];
13740 ary[y] = temp;
13741 }
13742
13743 /**
13744 * Returns a random integer within the range `low .. high` inclusive.
13745 *
13746 * @param {Number} low
13747 * The lower bound on the range.
13748 * @param {Number} high
13749 * The upper bound on the range.
13750 */
13751 function randomIntInRange(low, high) {
13752 return Math.round(low + (Math.random() * (high - low)));
13753 }
13754
13755 /**
13756 * The Quick Sort algorithm.
13757 *
13758 * @param {Array} ary
13759 * An array to sort.
13760 * @param {function} comparator
13761 * Function to use to compare two items.
13762 * @param {Number} p
13763 * Start index of the array
13764 * @param {Number} r
13765 * End index of the array
13766 */
13767 function doQuickSort(ary, comparator, p, r) {
13768 // If our lower bound is less than our upper bound, we (1) partition the
13769 // array into two pieces and (2) recurse on each half. If it is not, this is
13770 // the empty array and our base case.
13771
13772 if (p < r) {
13773 // (1) Partitioning.
13774 //
13775 // The partitioning chooses a pivot between `p` and `r` and moves all
13776 // elements that are less than or equal to the pivot to the before it, and
13777 // all the elements that are greater than it after it. The effect is that
13778 // once partition is done, the pivot is in the exact place it will be when
13779 // the array is put in sorted order, and it will not need to be moved
13780 // again. This runs in O(n) time.
13781
13782 // Always choose a random pivot so that an input array which is reverse
13783 // sorted does not cause O(n^2) running time.
13784 var pivotIndex = randomIntInRange(p, r);
13785 var i = p - 1;
13786
13787 swap(ary, pivotIndex, r);
13788 var pivot = ary[r];
13789
13790 // Immediately after `j` is incremented in this loop, the following hold
13791 // true:
13792 //
13793 // * Every element in `ary[p .. i]` is less than or equal to the pivot.
13794 //
13795 // * Every element in `ary[i+1 .. j-1]` is greater than the pivot.
13796 for (var j = p; j < r; j++) {
13797 if (comparator(ary[j], pivot) <= 0) {
13798 i += 1;
13799 swap(ary, i, j);
13800 }
13801 }
13802
13803 swap(ary, i + 1, j);
13804 var q = i + 1;
13805
13806 // (2) Recurse on each half.
13807
13808 doQuickSort(ary, comparator, p, q - 1);
13809 doQuickSort(ary, comparator, q + 1, r);
13810 }
13811 }
13812
13813 /**
13814 * Sort the given array in-place with the given comparator function.
13815 *
13816 * @param {Array} ary
13817 * An array to sort.
13818 * @param {function} comparator
13819 * Function to use to compare two items.
13820 */
13821 exports.quickSort = function (ary, comparator) {
13822 doQuickSort(ary, comparator, 0, ary.length - 1);
13823 };
13824
13825
13826/***/ },
13827/* 10 */
13828/***/ function(module, exports, __webpack_require__) {
13829
13830 /* -*- Mode: js; js-indent-level: 2; -*- */
13831 /*
13832 * Copyright 2011 Mozilla Foundation and contributors
13833 * Licensed under the New BSD license. See LICENSE or:
13834 * http://opensource.org/licenses/BSD-3-Clause
13835 */
13836
13837 var SourceMapGenerator = __webpack_require__(1).SourceMapGenerator;
13838 var util = __webpack_require__(4);
13839
13840 // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
13841 // operating systems these days (capturing the result).
13842 var REGEX_NEWLINE = /(\r?\n)/;
13843
13844 // Newline character code for charCodeAt() comparisons
13845 var NEWLINE_CODE = 10;
13846
13847 // Private symbol for identifying `SourceNode`s when multiple versions of
13848 // the source-map library are loaded. This MUST NOT CHANGE across
13849 // versions!
13850 var isSourceNode = "$$$isSourceNode$$$";
13851
13852 /**
13853 * SourceNodes provide a way to abstract over interpolating/concatenating
13854 * snippets of generated JavaScript source code while maintaining the line and
13855 * column information associated with the original source code.
13856 *
13857 * @param aLine The original line number.
13858 * @param aColumn The original column number.
13859 * @param aSource The original source's filename.
13860 * @param aChunks Optional. An array of strings which are snippets of
13861 * generated JS, or other SourceNodes.
13862 * @param aName The original identifier.
13863 */
13864 function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
13865 this.children = [];
13866 this.sourceContents = {};
13867 this.line = aLine == null ? null : aLine;
13868 this.column = aColumn == null ? null : aColumn;
13869 this.source = aSource == null ? null : aSource;
13870 this.name = aName == null ? null : aName;
13871 this[isSourceNode] = true;
13872 if (aChunks != null) this.add(aChunks);
13873 }
13874
13875 /**
13876 * Creates a SourceNode from generated code and a SourceMapConsumer.
13877 *
13878 * @param aGeneratedCode The generated code
13879 * @param aSourceMapConsumer The SourceMap for the generated code
13880 * @param aRelativePath Optional. The path that relative sources in the
13881 * SourceMapConsumer should be relative to.
13882 */
13883 SourceNode.fromStringWithSourceMap =
13884 function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
13885 // The SourceNode we want to fill with the generated code
13886 // and the SourceMap
13887 var node = new SourceNode();
13888
13889 // All even indices of this array are one line of the generated code,
13890 // while all odd indices are the newlines between two adjacent lines
13891 // (since `REGEX_NEWLINE` captures its match).
13892 // Processed fragments are removed from this array, by calling `shiftNextLine`.
13893 var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
13894 var shiftNextLine = function() {
13895 var lineContents = remainingLines.shift();
13896 // The last line of a file might not have a newline.
13897 var newLine = remainingLines.shift() || "";
13898 return lineContents + newLine;
13899 };
13900
13901 // We need to remember the position of "remainingLines"
13902 var lastGeneratedLine = 1, lastGeneratedColumn = 0;
13903
13904 // The generate SourceNodes we need a code range.
13905 // To extract it current and last mapping is used.
13906 // Here we store the last mapping.
13907 var lastMapping = null;
13908
13909 aSourceMapConsumer.eachMapping(function (mapping) {
13910 if (lastMapping !== null) {
13911 // We add the code from "lastMapping" to "mapping":
13912 // First check if there is a new line in between.
13913 if (lastGeneratedLine < mapping.generatedLine) {
13914 // Associate first line with "lastMapping"
13915 addMappingWithCode(lastMapping, shiftNextLine());
13916 lastGeneratedLine++;
13917 lastGeneratedColumn = 0;
13918 // The remaining code is added without mapping
13919 } else {
13920 // There is no new line in between.
13921 // Associate the code between "lastGeneratedColumn" and
13922 // "mapping.generatedColumn" with "lastMapping"
13923 var nextLine = remainingLines[0];
13924 var code = nextLine.substr(0, mapping.generatedColumn -
13925 lastGeneratedColumn);
13926 remainingLines[0] = nextLine.substr(mapping.generatedColumn -
13927 lastGeneratedColumn);
13928 lastGeneratedColumn = mapping.generatedColumn;
13929 addMappingWithCode(lastMapping, code);
13930 // No more remaining code, continue
13931 lastMapping = mapping;
13932 return;
13933 }
13934 }
13935 // We add the generated code until the first mapping
13936 // to the SourceNode without any mapping.
13937 // Each line is added as separate string.
13938 while (lastGeneratedLine < mapping.generatedLine) {
13939 node.add(shiftNextLine());
13940 lastGeneratedLine++;
13941 }
13942 if (lastGeneratedColumn < mapping.generatedColumn) {
13943 var nextLine = remainingLines[0];
13944 node.add(nextLine.substr(0, mapping.generatedColumn));
13945 remainingLines[0] = nextLine.substr(mapping.generatedColumn);
13946 lastGeneratedColumn = mapping.generatedColumn;
13947 }
13948 lastMapping = mapping;
13949 }, this);
13950 // We have processed all mappings.
13951 if (remainingLines.length > 0) {
13952 if (lastMapping) {
13953 // Associate the remaining code in the current line with "lastMapping"
13954 addMappingWithCode(lastMapping, shiftNextLine());
13955 }
13956 // and add the remaining lines without any mapping
13957 node.add(remainingLines.join(""));
13958 }
13959
13960 // Copy sourcesContent into SourceNode
13961 aSourceMapConsumer.sources.forEach(function (sourceFile) {
13962 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
13963 if (content != null) {
13964 if (aRelativePath != null) {
13965 sourceFile = util.join(aRelativePath, sourceFile);
13966 }
13967 node.setSourceContent(sourceFile, content);
13968 }
13969 });
13970
13971 return node;
13972
13973 function addMappingWithCode(mapping, code) {
13974 if (mapping === null || mapping.source === undefined) {
13975 node.add(code);
13976 } else {
13977 var source = aRelativePath
13978 ? util.join(aRelativePath, mapping.source)
13979 : mapping.source;
13980 node.add(new SourceNode(mapping.originalLine,
13981 mapping.originalColumn,
13982 source,
13983 code,
13984 mapping.name));
13985 }
13986 }
13987 };
13988
13989 /**
13990 * Add a chunk of generated JS to this source node.
13991 *
13992 * @param aChunk A string snippet of generated JS code, another instance of
13993 * SourceNode, or an array where each member is one of those things.
13994 */
13995 SourceNode.prototype.add = function SourceNode_add(aChunk) {
13996 if (Array.isArray(aChunk)) {
13997 aChunk.forEach(function (chunk) {
13998 this.add(chunk);
13999 }, this);
14000 }
14001 else if (aChunk[isSourceNode] || typeof aChunk === "string") {
14002 if (aChunk) {
14003 this.children.push(aChunk);
14004 }
14005 }
14006 else {
14007 throw new TypeError(
14008 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
14009 );
14010 }
14011 return this;
14012 };
14013
14014 /**
14015 * Add a chunk of generated JS to the beginning of this source node.
14016 *
14017 * @param aChunk A string snippet of generated JS code, another instance of
14018 * SourceNode, or an array where each member is one of those things.
14019 */
14020 SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
14021 if (Array.isArray(aChunk)) {
14022 for (var i = aChunk.length-1; i >= 0; i--) {
14023 this.prepend(aChunk[i]);
14024 }
14025 }
14026 else if (aChunk[isSourceNode] || typeof aChunk === "string") {
14027 this.children.unshift(aChunk);
14028 }
14029 else {
14030 throw new TypeError(
14031 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
14032 );
14033 }
14034 return this;
14035 };
14036
14037 /**
14038 * Walk over the tree of JS snippets in this node and its children. The
14039 * walking function is called once for each snippet of JS and is passed that
14040 * snippet and the its original associated source's line/column location.
14041 *
14042 * @param aFn The traversal function.
14043 */
14044 SourceNode.prototype.walk = function SourceNode_walk(aFn) {
14045 var chunk;
14046 for (var i = 0, len = this.children.length; i < len; i++) {
14047 chunk = this.children[i];
14048 if (chunk[isSourceNode]) {
14049 chunk.walk(aFn);
14050 }
14051 else {
14052 if (chunk !== '') {
14053 aFn(chunk, { source: this.source,
14054 line: this.line,
14055 column: this.column,
14056 name: this.name });
14057 }
14058 }
14059 }
14060 };
14061
14062 /**
14063 * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
14064 * each of `this.children`.
14065 *
14066 * @param aSep The separator.
14067 */
14068 SourceNode.prototype.join = function SourceNode_join(aSep) {
14069 var newChildren;
14070 var i;
14071 var len = this.children.length;
14072 if (len > 0) {
14073 newChildren = [];
14074 for (i = 0; i < len-1; i++) {
14075 newChildren.push(this.children[i]);
14076 newChildren.push(aSep);
14077 }
14078 newChildren.push(this.children[i]);
14079 this.children = newChildren;
14080 }
14081 return this;
14082 };
14083
14084 /**
14085 * Call String.prototype.replace on the very right-most source snippet. Useful
14086 * for trimming whitespace from the end of a source node, etc.
14087 *
14088 * @param aPattern The pattern to replace.
14089 * @param aReplacement The thing to replace the pattern with.
14090 */
14091 SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
14092 var lastChild = this.children[this.children.length - 1];
14093 if (lastChild[isSourceNode]) {
14094 lastChild.replaceRight(aPattern, aReplacement);
14095 }
14096 else if (typeof lastChild === 'string') {
14097 this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
14098 }
14099 else {
14100 this.children.push(''.replace(aPattern, aReplacement));
14101 }
14102 return this;
14103 };
14104
14105 /**
14106 * Set the source content for a source file. This will be added to the SourceMapGenerator
14107 * in the sourcesContent field.
14108 *
14109 * @param aSourceFile The filename of the source file
14110 * @param aSourceContent The content of the source file
14111 */
14112 SourceNode.prototype.setSourceContent =
14113 function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
14114 this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
14115 };
14116
14117 /**
14118 * Walk over the tree of SourceNodes. The walking function is called for each
14119 * source file content and is passed the filename and source content.
14120 *
14121 * @param aFn The traversal function.
14122 */
14123 SourceNode.prototype.walkSourceContents =
14124 function SourceNode_walkSourceContents(aFn) {
14125 for (var i = 0, len = this.children.length; i < len; i++) {
14126 if (this.children[i][isSourceNode]) {
14127 this.children[i].walkSourceContents(aFn);
14128 }
14129 }
14130
14131 var sources = Object.keys(this.sourceContents);
14132 for (var i = 0, len = sources.length; i < len; i++) {
14133 aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
14134 }
14135 };
14136
14137 /**
14138 * Return the string representation of this source node. Walks over the tree
14139 * and concatenates all the various snippets together to one string.
14140 */
14141 SourceNode.prototype.toString = function SourceNode_toString() {
14142 var str = "";
14143 this.walk(function (chunk) {
14144 str += chunk;
14145 });
14146 return str;
14147 };
14148
14149 /**
14150 * Returns the string representation of this source node along with a source
14151 * map.
14152 */
14153 SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
14154 var generated = {
14155 code: "",
14156 line: 1,
14157 column: 0
14158 };
14159 var map = new SourceMapGenerator(aArgs);
14160 var sourceMappingActive = false;
14161 var lastOriginalSource = null;
14162 var lastOriginalLine = null;
14163 var lastOriginalColumn = null;
14164 var lastOriginalName = null;
14165 this.walk(function (chunk, original) {
14166 generated.code += chunk;
14167 if (original.source !== null
14168 && original.line !== null
14169 && original.column !== null) {
14170 if(lastOriginalSource !== original.source
14171 || lastOriginalLine !== original.line
14172 || lastOriginalColumn !== original.column
14173 || lastOriginalName !== original.name) {
14174 map.addMapping({
14175 source: original.source,
14176 original: {
14177 line: original.line,
14178 column: original.column
14179 },
14180 generated: {
14181 line: generated.line,
14182 column: generated.column
14183 },
14184 name: original.name
14185 });
14186 }
14187 lastOriginalSource = original.source;
14188 lastOriginalLine = original.line;
14189 lastOriginalColumn = original.column;
14190 lastOriginalName = original.name;
14191 sourceMappingActive = true;
14192 } else if (sourceMappingActive) {
14193 map.addMapping({
14194 generated: {
14195 line: generated.line,
14196 column: generated.column
14197 }
14198 });
14199 lastOriginalSource = null;
14200 sourceMappingActive = false;
14201 }
14202 for (var idx = 0, length = chunk.length; idx < length; idx++) {
14203 if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
14204 generated.line++;
14205 generated.column = 0;
14206 // Mappings end at eol
14207 if (idx + 1 === length) {
14208 lastOriginalSource = null;
14209 sourceMappingActive = false;
14210 } else if (sourceMappingActive) {
14211 map.addMapping({
14212 source: original.source,
14213 original: {
14214 line: original.line,
14215 column: original.column
14216 },
14217 generated: {
14218 line: generated.line,
14219 column: generated.column
14220 },
14221 name: original.name
14222 });
14223 }
14224 } else {
14225 generated.column++;
14226 }
14227 }
14228 });
14229 this.walkSourceContents(function (sourceFile, sourceContent) {
14230 map.setSourceContent(sourceFile, sourceContent);
14231 });
14232
14233 return { code: generated.code, map: map };
14234 };
14235
14236 exports.SourceNode = SourceNode;
14237
14238
14239/***/ }
14240/******/ ])
14241});
14242;//Distributed under the BSD license:
14243//Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
14244define('uglifyjs', ['exports', 'source-map', 'logger', 'env!env/file'], function (exports, MOZ_SourceMap, logger, rjsFile) {
14245
14246/***********************************************************************
14247
14248 A JavaScript tokenizer / parser / beautifier / compressor.
14249 https://github.com/mishoo/UglifyJS2
14250
14251 -------------------------------- (C) ---------------------------------
14252
14253 Author: Mihai Bazon
14254 <mihai.bazon@gmail.com>
14255 http://mihai.bazon.net/blog
14256
14257 Distributed under the BSD license:
14258
14259 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
14260
14261 Redistribution and use in source and binary forms, with or without
14262 modification, are permitted provided that the following conditions
14263 are met:
14264
14265 * Redistributions of source code must retain the above
14266 copyright notice, this list of conditions and the following
14267 disclaimer.
14268
14269 * Redistributions in binary form must reproduce the above
14270 copyright notice, this list of conditions and the following
14271 disclaimer in the documentation and/or other materials
14272 provided with the distribution.
14273
14274 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
14275 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14276 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
14277 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
14278 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
14279 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14280 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14281 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
14282 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
14283 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
14284 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14285 SUCH DAMAGE.
14286
14287 ***********************************************************************/
14288
14289"use strict";
14290
14291function array_to_hash(a) {
14292 var ret = Object.create(null);
14293 for (var i = 0; i < a.length; ++i)
14294 ret[a[i]] = true;
14295 return ret;
14296};
14297
14298function slice(a, start) {
14299 return Array.prototype.slice.call(a, start || 0);
14300};
14301
14302function characters(str) {
14303 return str.split("");
14304};
14305
14306function member(name, array) {
14307 return array.indexOf(name) >= 0;
14308};
14309
14310function find_if(func, array) {
14311 for (var i = 0, n = array.length; i < n; ++i) {
14312 if (func(array[i]))
14313 return array[i];
14314 }
14315};
14316
14317function repeat_string(str, i) {
14318 if (i <= 0) return "";
14319 if (i == 1) return str;
14320 var d = repeat_string(str, i >> 1);
14321 d += d;
14322 if (i & 1) d += str;
14323 return d;
14324};
14325
14326function configure_error_stack(fn) {
14327 Object.defineProperty(fn.prototype, "stack", {
14328 get: function() {
14329 var err = new Error(this.message);
14330 err.name = this.name;
14331 try {
14332 throw err;
14333 } catch(e) {
14334 return e.stack;
14335 }
14336 }
14337 });
14338}
14339
14340function DefaultsError(msg, defs) {
14341 this.message = msg;
14342 this.defs = defs;
14343};
14344DefaultsError.prototype = Object.create(Error.prototype);
14345DefaultsError.prototype.constructor = DefaultsError;
14346DefaultsError.prototype.name = "DefaultsError";
14347configure_error_stack(DefaultsError);
14348
14349DefaultsError.croak = function(msg, defs) {
14350 throw new DefaultsError(msg, defs);
14351};
14352
14353function defaults(args, defs, croak) {
14354 if (args === true)
14355 args = {};
14356 var ret = args || {};
14357 if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i))
14358 DefaultsError.croak("`" + i + "` is not a supported option", defs);
14359 for (var i in defs) if (HOP(defs, i)) {
14360 ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
14361 }
14362 return ret;
14363};
14364
14365function merge(obj, ext) {
14366 var count = 0;
14367 for (var i in ext) if (HOP(ext, i)) {
14368 obj[i] = ext[i];
14369 count++;
14370 }
14371 return count;
14372};
14373
14374function noop() {}
14375function return_false() { return false; }
14376function return_true() { return true; }
14377function return_this() { return this; }
14378function return_null() { return null; }
14379
14380var MAP = (function(){
14381 function MAP(a, f, backwards) {
14382 var ret = [], top = [], i;
14383 function doit() {
14384 var val = f(a[i], i);
14385 var is_last = val instanceof Last;
14386 if (is_last) val = val.v;
14387 if (val instanceof AtTop) {
14388 val = val.v;
14389 if (val instanceof Splice) {
14390 top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
14391 } else {
14392 top.push(val);
14393 }
14394 }
14395 else if (val !== skip) {
14396 if (val instanceof Splice) {
14397 ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
14398 } else {
14399 ret.push(val);
14400 }
14401 }
14402 return is_last;
14403 };
14404 if (a instanceof Array) {
14405 if (backwards) {
14406 for (i = a.length; --i >= 0;) if (doit()) break;
14407 ret.reverse();
14408 top.reverse();
14409 } else {
14410 for (i = 0; i < a.length; ++i) if (doit()) break;
14411 }
14412 }
14413 else {
14414 for (i in a) if (HOP(a, i)) if (doit()) break;
14415 }
14416 return top.concat(ret);
14417 };
14418 MAP.at_top = function(val) { return new AtTop(val) };
14419 MAP.splice = function(val) { return new Splice(val) };
14420 MAP.last = function(val) { return new Last(val) };
14421 var skip = MAP.skip = {};
14422 function AtTop(val) { this.v = val };
14423 function Splice(val) { this.v = val };
14424 function Last(val) { this.v = val };
14425 return MAP;
14426})();
14427
14428function push_uniq(array, el) {
14429 if (array.indexOf(el) < 0)
14430 array.push(el);
14431};
14432
14433function string_template(text, props) {
14434 return text.replace(/\{(.+?)\}/g, function(str, p){
14435 return props && props[p];
14436 });
14437};
14438
14439function remove(array, el) {
14440 for (var i = array.length; --i >= 0;) {
14441 if (array[i] === el) array.splice(i, 1);
14442 }
14443};
14444
14445function mergeSort(array, cmp) {
14446 if (array.length < 2) return array.slice();
14447 function merge(a, b) {
14448 var r = [], ai = 0, bi = 0, i = 0;
14449 while (ai < a.length && bi < b.length) {
14450 cmp(a[ai], b[bi]) <= 0
14451 ? r[i++] = a[ai++]
14452 : r[i++] = b[bi++];
14453 }
14454 if (ai < a.length) r.push.apply(r, a.slice(ai));
14455 if (bi < b.length) r.push.apply(r, b.slice(bi));
14456 return r;
14457 };
14458 function _ms(a) {
14459 if (a.length <= 1)
14460 return a;
14461 var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
14462 left = _ms(left);
14463 right = _ms(right);
14464 return merge(left, right);
14465 };
14466 return _ms(array);
14467};
14468
14469function set_difference(a, b) {
14470 return a.filter(function(el){
14471 return b.indexOf(el) < 0;
14472 });
14473};
14474
14475function set_intersection(a, b) {
14476 return a.filter(function(el){
14477 return b.indexOf(el) >= 0;
14478 });
14479};
14480
14481// this function is taken from Acorn [1], written by Marijn Haverbeke
14482// [1] https://github.com/marijnh/acorn
14483function makePredicate(words) {
14484 if (!(words instanceof Array)) words = words.split(" ");
14485 var f = "", cats = [];
14486 out: for (var i = 0; i < words.length; ++i) {
14487 for (var j = 0; j < cats.length; ++j)
14488 if (cats[j][0].length == words[i].length) {
14489 cats[j].push(words[i]);
14490 continue out;
14491 }
14492 cats.push([words[i]]);
14493 }
14494 function quote(word) {
14495 return JSON.stringify(word).replace(/[\u2028\u2029]/g, function(s) {
14496 switch (s) {
14497 case "\u2028": return "\\u2028";
14498 case "\u2029": return "\\u2029";
14499 }
14500 return s;
14501 });
14502 }
14503 function compareTo(arr) {
14504 if (arr.length == 1) return f += "return str === " + quote(arr[0]) + ";";
14505 f += "switch(str){";
14506 for (var i = 0; i < arr.length; ++i) f += "case " + quote(arr[i]) + ":";
14507 f += "return true}return false;";
14508 }
14509 // When there are more than three length categories, an outer
14510 // switch first dispatches on the lengths, to save on comparisons.
14511 if (cats.length > 3) {
14512 cats.sort(function(a, b) {return b.length - a.length;});
14513 f += "switch(str.length){";
14514 for (var i = 0; i < cats.length; ++i) {
14515 var cat = cats[i];
14516 f += "case " + cat[0].length + ":";
14517 compareTo(cat);
14518 }
14519 f += "}";
14520 // Otherwise, simply generate a flat `switch` statement.
14521 } else {
14522 compareTo(words);
14523 }
14524 return new Function("str", f);
14525};
14526
14527function all(array, predicate) {
14528 for (var i = array.length; --i >= 0;)
14529 if (!predicate(array[i]))
14530 return false;
14531 return true;
14532};
14533
14534function Dictionary() {
14535 this._values = Object.create(null);
14536 this._size = 0;
14537};
14538Dictionary.prototype = {
14539 set: function(key, val) {
14540 if (!this.has(key)) ++this._size;
14541 this._values["$" + key] = val;
14542 return this;
14543 },
14544 add: function(key, val) {
14545 if (this.has(key)) {
14546 this.get(key).push(val);
14547 } else {
14548 this.set(key, [ val ]);
14549 }
14550 return this;
14551 },
14552 get: function(key) { return this._values["$" + key] },
14553 del: function(key) {
14554 if (this.has(key)) {
14555 --this._size;
14556 delete this._values["$" + key];
14557 }
14558 return this;
14559 },
14560 has: function(key) { return ("$" + key) in this._values },
14561 each: function(f) {
14562 for (var i in this._values)
14563 f(this._values[i], i.substr(1));
14564 },
14565 size: function() {
14566 return this._size;
14567 },
14568 map: function(f) {
14569 var ret = [];
14570 for (var i in this._values)
14571 ret.push(f(this._values[i], i.substr(1)));
14572 return ret;
14573 },
14574 toObject: function() { return this._values }
14575};
14576Dictionary.fromObject = function(obj) {
14577 var dict = new Dictionary();
14578 dict._size = merge(dict._values, obj);
14579 return dict;
14580};
14581
14582function HOP(obj, prop) {
14583 return Object.prototype.hasOwnProperty.call(obj, prop);
14584}
14585
14586// return true if the node at the top of the stack (that means the
14587// innermost node in the current output) is lexically the first in
14588// a statement.
14589function first_in_statement(stack) {
14590 var node = stack.parent(-1);
14591 for (var i = 0, p; p = stack.parent(i); i++) {
14592 if (p instanceof AST_Statement && p.body === node)
14593 return true;
14594 if ((p instanceof AST_Seq && p.car === node ) ||
14595 (p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
14596 (p instanceof AST_Dot && p.expression === node ) ||
14597 (p instanceof AST_Sub && p.expression === node ) ||
14598 (p instanceof AST_Conditional && p.condition === node ) ||
14599 (p instanceof AST_Binary && p.left === node ) ||
14600 (p instanceof AST_UnaryPostfix && p.expression === node ))
14601 {
14602 node = p;
14603 } else {
14604 return false;
14605 }
14606 }
14607}
14608
14609/***********************************************************************
14610
14611 A JavaScript tokenizer / parser / beautifier / compressor.
14612 https://github.com/mishoo/UglifyJS2
14613
14614 -------------------------------- (C) ---------------------------------
14615
14616 Author: Mihai Bazon
14617 <mihai.bazon@gmail.com>
14618 http://mihai.bazon.net/blog
14619
14620 Distributed under the BSD license:
14621
14622 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
14623
14624 Redistribution and use in source and binary forms, with or without
14625 modification, are permitted provided that the following conditions
14626 are met:
14627
14628 * Redistributions of source code must retain the above
14629 copyright notice, this list of conditions and the following
14630 disclaimer.
14631
14632 * Redistributions in binary form must reproduce the above
14633 copyright notice, this list of conditions and the following
14634 disclaimer in the documentation and/or other materials
14635 provided with the distribution.
14636
14637 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
14638 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14639 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
14640 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
14641 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
14642 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14643 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14644 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
14645 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
14646 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
14647 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14648 SUCH DAMAGE.
14649
14650 ***********************************************************************/
14651
14652"use strict";
14653
14654function DEFNODE(type, props, methods, base) {
14655 if (arguments.length < 4) base = AST_Node;
14656 if (!props) props = [];
14657 else props = props.split(/\s+/);
14658 var self_props = props;
14659 if (base && base.PROPS)
14660 props = props.concat(base.PROPS);
14661 var code = "return function AST_" + type + "(props){ if (props) { ";
14662 for (var i = props.length; --i >= 0;) {
14663 code += "this." + props[i] + " = props." + props[i] + ";";
14664 }
14665 var proto = base && new base;
14666 if (proto && proto.initialize || (methods && methods.initialize))
14667 code += "this.initialize();";
14668 code += "}}";
14669 var ctor = new Function(code)();
14670 if (proto) {
14671 ctor.prototype = proto;
14672 ctor.BASE = base;
14673 }
14674 if (base) base.SUBCLASSES.push(ctor);
14675 ctor.prototype.CTOR = ctor;
14676 ctor.PROPS = props || null;
14677 ctor.SELF_PROPS = self_props;
14678 ctor.SUBCLASSES = [];
14679 if (type) {
14680 ctor.prototype.TYPE = ctor.TYPE = type;
14681 }
14682 if (methods) for (i in methods) if (HOP(methods, i)) {
14683 if (/^\$/.test(i)) {
14684 ctor[i.substr(1)] = methods[i];
14685 } else {
14686 ctor.prototype[i] = methods[i];
14687 }
14688 }
14689 ctor.DEFMETHOD = function(name, method) {
14690 this.prototype[name] = method;
14691 };
14692 if (typeof exports !== "undefined") {
14693 exports["AST_" + type] = ctor;
14694 }
14695 return ctor;
14696};
14697
14698var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", {
14699}, null);
14700
14701var AST_Node = DEFNODE("Node", "start end", {
14702 _clone: function(deep) {
14703 if (deep) {
14704 var self = this.clone();
14705 return self.transform(new TreeTransformer(function(node) {
14706 if (node !== self) {
14707 return node.clone(true);
14708 }
14709 }));
14710 }
14711 return new this.CTOR(this);
14712 },
14713 clone: function(deep) {
14714 return this._clone(deep);
14715 },
14716 $documentation: "Base class of all AST nodes",
14717 $propdoc: {
14718 start: "[AST_Token] The first token of this node",
14719 end: "[AST_Token] The last token of this node"
14720 },
14721 _walk: function(visitor) {
14722 return visitor._visit(this);
14723 },
14724 walk: function(visitor) {
14725 return this._walk(visitor); // not sure the indirection will be any help
14726 }
14727}, null);
14728
14729AST_Node.warn_function = null;
14730AST_Node.warn = function(txt, props) {
14731 if (AST_Node.warn_function)
14732 AST_Node.warn_function(string_template(txt, props));
14733};
14734
14735/* -----[ statements ]----- */
14736
14737var AST_Statement = DEFNODE("Statement", null, {
14738 $documentation: "Base class of all statements",
14739});
14740
14741var AST_Debugger = DEFNODE("Debugger", null, {
14742 $documentation: "Represents a debugger statement",
14743}, AST_Statement);
14744
14745var AST_Directive = DEFNODE("Directive", "value scope quote", {
14746 $documentation: "Represents a directive, like \"use strict\";",
14747 $propdoc: {
14748 value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
14749 scope: "[AST_Scope/S] The scope that this directive affects",
14750 quote: "[string] the original quote character"
14751 },
14752}, AST_Statement);
14753
14754var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
14755 $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
14756 $propdoc: {
14757 body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
14758 },
14759 _walk: function(visitor) {
14760 return visitor._visit(this, function(){
14761 this.body._walk(visitor);
14762 });
14763 }
14764}, AST_Statement);
14765
14766function walk_body(node, visitor) {
14767 var body = node.body;
14768 if (body instanceof AST_Statement) {
14769 body._walk(visitor);
14770 }
14771 else for (var i = 0, len = body.length; i < len; i++) {
14772 body[i]._walk(visitor);
14773 }
14774};
14775
14776var AST_Block = DEFNODE("Block", "body", {
14777 $documentation: "A body of statements (usually bracketed)",
14778 $propdoc: {
14779 body: "[AST_Statement*] an array of statements"
14780 },
14781 _walk: function(visitor) {
14782 return visitor._visit(this, function(){
14783 walk_body(this, visitor);
14784 });
14785 }
14786}, AST_Statement);
14787
14788var AST_BlockStatement = DEFNODE("BlockStatement", null, {
14789 $documentation: "A block statement",
14790}, AST_Block);
14791
14792var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
14793 $documentation: "The empty statement (empty block or simply a semicolon)",
14794 _walk: function(visitor) {
14795 return visitor._visit(this);
14796 }
14797}, AST_Statement);
14798
14799var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
14800 $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
14801 $propdoc: {
14802 body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
14803 },
14804 _walk: function(visitor) {
14805 return visitor._visit(this, function(){
14806 this.body._walk(visitor);
14807 });
14808 }
14809}, AST_Statement);
14810
14811var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
14812 $documentation: "Statement with a label",
14813 $propdoc: {
14814 label: "[AST_Label] a label definition"
14815 },
14816 _walk: function(visitor) {
14817 return visitor._visit(this, function(){
14818 this.label._walk(visitor);
14819 this.body._walk(visitor);
14820 });
14821 },
14822 clone: function(deep) {
14823 var node = this._clone(deep);
14824 if (deep) {
14825 var label = node.label;
14826 var def = this.label;
14827 node.walk(new TreeWalker(function(node) {
14828 if (node instanceof AST_LoopControl
14829 && node.label && node.label.thedef === def) {
14830 node.label.thedef = label;
14831 label.references.push(node);
14832 }
14833 }));
14834 }
14835 return node;
14836 }
14837}, AST_StatementWithBody);
14838
14839var AST_IterationStatement = DEFNODE("IterationStatement", null, {
14840 $documentation: "Internal class. All loops inherit from it."
14841}, AST_StatementWithBody);
14842
14843var AST_DWLoop = DEFNODE("DWLoop", "condition", {
14844 $documentation: "Base class for do/while statements",
14845 $propdoc: {
14846 condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"
14847 }
14848}, AST_IterationStatement);
14849
14850var AST_Do = DEFNODE("Do", null, {
14851 $documentation: "A `do` statement",
14852 _walk: function(visitor) {
14853 return visitor._visit(this, function(){
14854 this.body._walk(visitor);
14855 this.condition._walk(visitor);
14856 });
14857 }
14858}, AST_DWLoop);
14859
14860var AST_While = DEFNODE("While", null, {
14861 $documentation: "A `while` statement",
14862 _walk: function(visitor) {
14863 return visitor._visit(this, function(){
14864 this.condition._walk(visitor);
14865 this.body._walk(visitor);
14866 });
14867 }
14868}, AST_DWLoop);
14869
14870var AST_For = DEFNODE("For", "init condition step", {
14871 $documentation: "A `for` statement",
14872 $propdoc: {
14873 init: "[AST_Node?] the `for` initialization code, or null if empty",
14874 condition: "[AST_Node?] the `for` termination clause, or null if empty",
14875 step: "[AST_Node?] the `for` update clause, or null if empty"
14876 },
14877 _walk: function(visitor) {
14878 return visitor._visit(this, function(){
14879 if (this.init) this.init._walk(visitor);
14880 if (this.condition) this.condition._walk(visitor);
14881 if (this.step) this.step._walk(visitor);
14882 this.body._walk(visitor);
14883 });
14884 }
14885}, AST_IterationStatement);
14886
14887var AST_ForIn = DEFNODE("ForIn", "init name object", {
14888 $documentation: "A `for ... in` statement",
14889 $propdoc: {
14890 init: "[AST_Node] the `for/in` initialization code",
14891 name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
14892 object: "[AST_Node] the object that we're looping through"
14893 },
14894 _walk: function(visitor) {
14895 return visitor._visit(this, function(){
14896 this.init._walk(visitor);
14897 this.object._walk(visitor);
14898 this.body._walk(visitor);
14899 });
14900 }
14901}, AST_IterationStatement);
14902
14903var AST_With = DEFNODE("With", "expression", {
14904 $documentation: "A `with` statement",
14905 $propdoc: {
14906 expression: "[AST_Node] the `with` expression"
14907 },
14908 _walk: function(visitor) {
14909 return visitor._visit(this, function(){
14910 this.expression._walk(visitor);
14911 this.body._walk(visitor);
14912 });
14913 }
14914}, AST_StatementWithBody);
14915
14916/* -----[ scope and functions ]----- */
14917
14918var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
14919 $documentation: "Base class for all statements introducing a lexical scope",
14920 $propdoc: {
14921 directives: "[string*/S] an array of directives declared in this scope",
14922 variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
14923 functions: "[Object/S] like `variables`, but only lists function declarations",
14924 uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
14925 uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
14926 parent_scope: "[AST_Scope?/S] link to the parent scope",
14927 enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
14928 cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
14929 },
14930}, AST_Block);
14931
14932var AST_Toplevel = DEFNODE("Toplevel", "globals", {
14933 $documentation: "The toplevel scope",
14934 $propdoc: {
14935 globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
14936 },
14937 wrap_enclose: function(arg_parameter_pairs) {
14938 var self = this;
14939 var args = [];
14940 var parameters = [];
14941
14942 arg_parameter_pairs.forEach(function(pair) {
14943 var splitAt = pair.lastIndexOf(":");
14944
14945 args.push(pair.substr(0, splitAt));
14946 parameters.push(pair.substr(splitAt + 1));
14947 });
14948
14949 var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
14950 wrapped_tl = parse(wrapped_tl);
14951 wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
14952 if (node instanceof AST_Directive && node.value == "$ORIG") {
14953 return MAP.splice(self.body);
14954 }
14955 }));
14956 return wrapped_tl;
14957 },
14958 wrap_commonjs: function(name, export_all) {
14959 var self = this;
14960 var to_export = [];
14961 if (export_all) {
14962 self.figure_out_scope();
14963 self.walk(new TreeWalker(function(node){
14964 if (node instanceof AST_SymbolDeclaration && node.definition().global) {
14965 if (!find_if(function(n){ return n.name == node.name }, to_export))
14966 to_export.push(node);
14967 }
14968 }));
14969 }
14970 var wrapped_tl = "(function(exports, global){ '$ORIG'; '$EXPORTS'; global['" + name + "'] = exports; }({}, (function(){return this}())))";
14971 wrapped_tl = parse(wrapped_tl);
14972 wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
14973 if (node instanceof AST_Directive) {
14974 switch (node.value) {
14975 case "$ORIG":
14976 return MAP.splice(self.body);
14977 case "$EXPORTS":
14978 var body = [];
14979 to_export.forEach(function(sym){
14980 body.push(new AST_SimpleStatement({
14981 body: new AST_Assign({
14982 left: new AST_Sub({
14983 expression: new AST_SymbolRef({ name: "exports" }),
14984 property: new AST_String({ value: sym.name }),
14985 }),
14986 operator: "=",
14987 right: new AST_SymbolRef(sym),
14988 }),
14989 }));
14990 });
14991 return MAP.splice(body);
14992 }
14993 }
14994 }));
14995 return wrapped_tl;
14996 }
14997}, AST_Scope);
14998
14999var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
15000 $documentation: "Base class for functions",
15001 $propdoc: {
15002 name: "[AST_SymbolDeclaration?] the name of this function",
15003 argnames: "[AST_SymbolFunarg*] array of function arguments",
15004 uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
15005 },
15006 _walk: function(visitor) {
15007 return visitor._visit(this, function(){
15008 if (this.name) this.name._walk(visitor);
15009 var argnames = this.argnames;
15010 for (var i = 0, len = argnames.length; i < len; i++) {
15011 argnames[i]._walk(visitor);
15012 }
15013 walk_body(this, visitor);
15014 });
15015 }
15016}, AST_Scope);
15017
15018var AST_Accessor = DEFNODE("Accessor", null, {
15019 $documentation: "A setter/getter function. The `name` property is always null."
15020}, AST_Lambda);
15021
15022var AST_Function = DEFNODE("Function", null, {
15023 $documentation: "A function expression"
15024}, AST_Lambda);
15025
15026var AST_Defun = DEFNODE("Defun", null, {
15027 $documentation: "A function definition"
15028}, AST_Lambda);
15029
15030/* -----[ JUMPS ]----- */
15031
15032var AST_Jump = DEFNODE("Jump", null, {
15033 $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
15034}, AST_Statement);
15035
15036var AST_Exit = DEFNODE("Exit", "value", {
15037 $documentation: "Base class for “exits” (`return` and `throw`)",
15038 $propdoc: {
15039 value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
15040 },
15041 _walk: function(visitor) {
15042 return visitor._visit(this, this.value && function(){
15043 this.value._walk(visitor);
15044 });
15045 }
15046}, AST_Jump);
15047
15048var AST_Return = DEFNODE("Return", null, {
15049 $documentation: "A `return` statement"
15050}, AST_Exit);
15051
15052var AST_Throw = DEFNODE("Throw", null, {
15053 $documentation: "A `throw` statement"
15054}, AST_Exit);
15055
15056var AST_LoopControl = DEFNODE("LoopControl", "label", {
15057 $documentation: "Base class for loop control statements (`break` and `continue`)",
15058 $propdoc: {
15059 label: "[AST_LabelRef?] the label, or null if none",
15060 },
15061 _walk: function(visitor) {
15062 return visitor._visit(this, this.label && function(){
15063 this.label._walk(visitor);
15064 });
15065 }
15066}, AST_Jump);
15067
15068var AST_Break = DEFNODE("Break", null, {
15069 $documentation: "A `break` statement"
15070}, AST_LoopControl);
15071
15072var AST_Continue = DEFNODE("Continue", null, {
15073 $documentation: "A `continue` statement"
15074}, AST_LoopControl);
15075
15076/* -----[ IF ]----- */
15077
15078var AST_If = DEFNODE("If", "condition alternative", {
15079 $documentation: "A `if` statement",
15080 $propdoc: {
15081 condition: "[AST_Node] the `if` condition",
15082 alternative: "[AST_Statement?] the `else` part, or null if not present"
15083 },
15084 _walk: function(visitor) {
15085 return visitor._visit(this, function(){
15086 this.condition._walk(visitor);
15087 this.body._walk(visitor);
15088 if (this.alternative) this.alternative._walk(visitor);
15089 });
15090 }
15091}, AST_StatementWithBody);
15092
15093/* -----[ SWITCH ]----- */
15094
15095var AST_Switch = DEFNODE("Switch", "expression", {
15096 $documentation: "A `switch` statement",
15097 $propdoc: {
15098 expression: "[AST_Node] the `switch` “discriminant”"
15099 },
15100 _walk: function(visitor) {
15101 return visitor._visit(this, function(){
15102 this.expression._walk(visitor);
15103 walk_body(this, visitor);
15104 });
15105 }
15106}, AST_Block);
15107
15108var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
15109 $documentation: "Base class for `switch` branches",
15110}, AST_Block);
15111
15112var AST_Default = DEFNODE("Default", null, {
15113 $documentation: "A `default` switch branch",
15114}, AST_SwitchBranch);
15115
15116var AST_Case = DEFNODE("Case", "expression", {
15117 $documentation: "A `case` switch branch",
15118 $propdoc: {
15119 expression: "[AST_Node] the `case` expression"
15120 },
15121 _walk: function(visitor) {
15122 return visitor._visit(this, function(){
15123 this.expression._walk(visitor);
15124 walk_body(this, visitor);
15125 });
15126 }
15127}, AST_SwitchBranch);
15128
15129/* -----[ EXCEPTIONS ]----- */
15130
15131var AST_Try = DEFNODE("Try", "bcatch bfinally", {
15132 $documentation: "A `try` statement",
15133 $propdoc: {
15134 bcatch: "[AST_Catch?] the catch block, or null if not present",
15135 bfinally: "[AST_Finally?] the finally block, or null if not present"
15136 },
15137 _walk: function(visitor) {
15138 return visitor._visit(this, function(){
15139 walk_body(this, visitor);
15140 if (this.bcatch) this.bcatch._walk(visitor);
15141 if (this.bfinally) this.bfinally._walk(visitor);
15142 });
15143 }
15144}, AST_Block);
15145
15146var AST_Catch = DEFNODE("Catch", "argname", {
15147 $documentation: "A `catch` node; only makes sense as part of a `try` statement",
15148 $propdoc: {
15149 argname: "[AST_SymbolCatch] symbol for the exception"
15150 },
15151 _walk: function(visitor) {
15152 return visitor._visit(this, function(){
15153 this.argname._walk(visitor);
15154 walk_body(this, visitor);
15155 });
15156 }
15157}, AST_Block);
15158
15159var AST_Finally = DEFNODE("Finally", null, {
15160 $documentation: "A `finally` node; only makes sense as part of a `try` statement"
15161}, AST_Block);
15162
15163/* -----[ VAR/CONST ]----- */
15164
15165var AST_Definitions = DEFNODE("Definitions", "definitions", {
15166 $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
15167 $propdoc: {
15168 definitions: "[AST_VarDef*] array of variable definitions"
15169 },
15170 _walk: function(visitor) {
15171 return visitor._visit(this, function(){
15172 var definitions = this.definitions;
15173 for (var i = 0, len = definitions.length; i < len; i++) {
15174 definitions[i]._walk(visitor);
15175 }
15176 });
15177 }
15178}, AST_Statement);
15179
15180var AST_Var = DEFNODE("Var", null, {
15181 $documentation: "A `var` statement"
15182}, AST_Definitions);
15183
15184var AST_Const = DEFNODE("Const", null, {
15185 $documentation: "A `const` statement"
15186}, AST_Definitions);
15187
15188var AST_VarDef = DEFNODE("VarDef", "name value", {
15189 $documentation: "A variable declaration; only appears in a AST_Definitions node",
15190 $propdoc: {
15191 name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
15192 value: "[AST_Node?] initializer, or null of there's no initializer"
15193 },
15194 _walk: function(visitor) {
15195 return visitor._visit(this, function(){
15196 this.name._walk(visitor);
15197 if (this.value) this.value._walk(visitor);
15198 });
15199 }
15200});
15201
15202/* -----[ OTHER ]----- */
15203
15204var AST_Call = DEFNODE("Call", "expression args", {
15205 $documentation: "A function call expression",
15206 $propdoc: {
15207 expression: "[AST_Node] expression to invoke as function",
15208 args: "[AST_Node*] array of arguments"
15209 },
15210 _walk: function(visitor) {
15211 return visitor._visit(this, function(){
15212 this.expression._walk(visitor);
15213 var args = this.args;
15214 for (var i = 0, len = args.length; i < len; i++) {
15215 args[i]._walk(visitor);
15216 }
15217 });
15218 }
15219});
15220
15221var AST_New = DEFNODE("New", null, {
15222 $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"
15223}, AST_Call);
15224
15225var AST_Seq = DEFNODE("Seq", "car cdr", {
15226 $documentation: "A sequence expression (two comma-separated expressions)",
15227 $propdoc: {
15228 car: "[AST_Node] first element in sequence",
15229 cdr: "[AST_Node] second element in sequence"
15230 },
15231 $cons: function(x, y) {
15232 var seq = new AST_Seq(x);
15233 seq.car = x;
15234 seq.cdr = y;
15235 return seq;
15236 },
15237 $from_array: function(array) {
15238 if (array.length == 0) return null;
15239 if (array.length == 1) return array[0].clone();
15240 var list = null;
15241 for (var i = array.length; --i >= 0;) {
15242 list = AST_Seq.cons(array[i], list);
15243 }
15244 var p = list;
15245 while (p) {
15246 if (p.cdr && !p.cdr.cdr) {
15247 p.cdr = p.cdr.car;
15248 break;
15249 }
15250 p = p.cdr;
15251 }
15252 return list;
15253 },
15254 to_array: function() {
15255 var p = this, a = [];
15256 while (p) {
15257 a.push(p.car);
15258 if (p.cdr && !(p.cdr instanceof AST_Seq)) {
15259 a.push(p.cdr);
15260 break;
15261 }
15262 p = p.cdr;
15263 }
15264 return a;
15265 },
15266 add: function(node) {
15267 var p = this;
15268 while (p) {
15269 if (!(p.cdr instanceof AST_Seq)) {
15270 var cell = AST_Seq.cons(p.cdr, node);
15271 return p.cdr = cell;
15272 }
15273 p = p.cdr;
15274 }
15275 },
15276 len: function() {
15277 if (this.cdr instanceof AST_Seq) {
15278 return this.cdr.len() + 1;
15279 } else {
15280 return 2;
15281 }
15282 },
15283 _walk: function(visitor) {
15284 return visitor._visit(this, function(){
15285 this.car._walk(visitor);
15286 if (this.cdr) this.cdr._walk(visitor);
15287 });
15288 }
15289});
15290
15291var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
15292 $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
15293 $propdoc: {
15294 expression: "[AST_Node] the “container” expression",
15295 property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
15296 }
15297});
15298
15299var AST_Dot = DEFNODE("Dot", null, {
15300 $documentation: "A dotted property access expression",
15301 _walk: function(visitor) {
15302 return visitor._visit(this, function(){
15303 this.expression._walk(visitor);
15304 });
15305 }
15306}, AST_PropAccess);
15307
15308var AST_Sub = DEFNODE("Sub", null, {
15309 $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
15310 _walk: function(visitor) {
15311 return visitor._visit(this, function(){
15312 this.expression._walk(visitor);
15313 this.property._walk(visitor);
15314 });
15315 }
15316}, AST_PropAccess);
15317
15318var AST_Unary = DEFNODE("Unary", "operator expression", {
15319 $documentation: "Base class for unary expressions",
15320 $propdoc: {
15321 operator: "[string] the operator",
15322 expression: "[AST_Node] expression that this unary operator applies to"
15323 },
15324 _walk: function(visitor) {
15325 return visitor._visit(this, function(){
15326 this.expression._walk(visitor);
15327 });
15328 }
15329});
15330
15331var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
15332 $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
15333}, AST_Unary);
15334
15335var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
15336 $documentation: "Unary postfix expression, i.e. `i++`"
15337}, AST_Unary);
15338
15339var AST_Binary = DEFNODE("Binary", "left operator right", {
15340 $documentation: "Binary expression, i.e. `a + b`",
15341 $propdoc: {
15342 left: "[AST_Node] left-hand side expression",
15343 operator: "[string] the operator",
15344 right: "[AST_Node] right-hand side expression"
15345 },
15346 _walk: function(visitor) {
15347 return visitor._visit(this, function(){
15348 this.left._walk(visitor);
15349 this.right._walk(visitor);
15350 });
15351 }
15352});
15353
15354var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
15355 $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
15356 $propdoc: {
15357 condition: "[AST_Node]",
15358 consequent: "[AST_Node]",
15359 alternative: "[AST_Node]"
15360 },
15361 _walk: function(visitor) {
15362 return visitor._visit(this, function(){
15363 this.condition._walk(visitor);
15364 this.consequent._walk(visitor);
15365 this.alternative._walk(visitor);
15366 });
15367 }
15368});
15369
15370var AST_Assign = DEFNODE("Assign", null, {
15371 $documentation: "An assignment expression — `a = b + 5`",
15372}, AST_Binary);
15373
15374/* -----[ LITERALS ]----- */
15375
15376var AST_Array = DEFNODE("Array", "elements", {
15377 $documentation: "An array literal",
15378 $propdoc: {
15379 elements: "[AST_Node*] array of elements"
15380 },
15381 _walk: function(visitor) {
15382 return visitor._visit(this, function(){
15383 var elements = this.elements;
15384 for (var i = 0, len = elements.length; i < len; i++) {
15385 elements[i]._walk(visitor);
15386 }
15387 });
15388 }
15389});
15390
15391var AST_Object = DEFNODE("Object", "properties", {
15392 $documentation: "An object literal",
15393 $propdoc: {
15394 properties: "[AST_ObjectProperty*] array of properties"
15395 },
15396 _walk: function(visitor) {
15397 return visitor._visit(this, function(){
15398 var properties = this.properties;
15399 for (var i = 0, len = properties.length; i < len; i++) {
15400 properties[i]._walk(visitor);
15401 }
15402 });
15403 }
15404});
15405
15406var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
15407 $documentation: "Base class for literal object properties",
15408 $propdoc: {
15409 key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an AST_SymbolAccessor.",
15410 value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
15411 },
15412 _walk: function(visitor) {
15413 return visitor._visit(this, function(){
15414 this.value._walk(visitor);
15415 });
15416 }
15417});
15418
15419var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
15420 $documentation: "A key: value object property",
15421 $propdoc: {
15422 quote: "[string] the original quote character"
15423 }
15424}, AST_ObjectProperty);
15425
15426var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
15427 $documentation: "An object setter property",
15428}, AST_ObjectProperty);
15429
15430var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
15431 $documentation: "An object getter property",
15432}, AST_ObjectProperty);
15433
15434var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
15435 $propdoc: {
15436 name: "[string] name of this symbol",
15437 scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
15438 thedef: "[SymbolDef/S] the definition of this symbol"
15439 },
15440 $documentation: "Base class for all symbols",
15441});
15442
15443var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
15444 $documentation: "The name of a property accessor (setter/getter function)"
15445}, AST_Symbol);
15446
15447var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
15448 $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
15449}, AST_Symbol);
15450
15451var AST_SymbolVar = DEFNODE("SymbolVar", null, {
15452 $documentation: "Symbol defining a variable",
15453}, AST_SymbolDeclaration);
15454
15455var AST_SymbolConst = DEFNODE("SymbolConst", null, {
15456 $documentation: "A constant declaration"
15457}, AST_SymbolDeclaration);
15458
15459var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
15460 $documentation: "Symbol naming a function argument",
15461}, AST_SymbolVar);
15462
15463var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
15464 $documentation: "Symbol defining a function",
15465}, AST_SymbolDeclaration);
15466
15467var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
15468 $documentation: "Symbol naming a function expression",
15469}, AST_SymbolDeclaration);
15470
15471var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
15472 $documentation: "Symbol naming the exception in catch",
15473}, AST_SymbolDeclaration);
15474
15475var AST_Label = DEFNODE("Label", "references", {
15476 $documentation: "Symbol naming a label (declaration)",
15477 $propdoc: {
15478 references: "[AST_LoopControl*] a list of nodes referring to this label"
15479 },
15480 initialize: function() {
15481 this.references = [];
15482 this.thedef = this;
15483 }
15484}, AST_Symbol);
15485
15486var AST_SymbolRef = DEFNODE("SymbolRef", null, {
15487 $documentation: "Reference to some symbol (not definition/declaration)",
15488}, AST_Symbol);
15489
15490var AST_LabelRef = DEFNODE("LabelRef", null, {
15491 $documentation: "Reference to a label symbol",
15492}, AST_Symbol);
15493
15494var AST_This = DEFNODE("This", null, {
15495 $documentation: "The `this` symbol",
15496}, AST_Symbol);
15497
15498var AST_Constant = DEFNODE("Constant", null, {
15499 $documentation: "Base class for all constants",
15500 getValue: function() {
15501 return this.value;
15502 }
15503});
15504
15505var AST_String = DEFNODE("String", "value quote", {
15506 $documentation: "A string literal",
15507 $propdoc: {
15508 value: "[string] the contents of this string",
15509 quote: "[string] the original quote character"
15510 }
15511}, AST_Constant);
15512
15513var AST_Number = DEFNODE("Number", "value literal", {
15514 $documentation: "A number literal",
15515 $propdoc: {
15516 value: "[number] the numeric value",
15517 literal: "[string] numeric value as string (optional)"
15518 }
15519}, AST_Constant);
15520
15521var AST_RegExp = DEFNODE("RegExp", "value", {
15522 $documentation: "A regexp literal",
15523 $propdoc: {
15524 value: "[RegExp] the actual regexp"
15525 }
15526}, AST_Constant);
15527
15528var AST_Atom = DEFNODE("Atom", null, {
15529 $documentation: "Base class for atoms",
15530}, AST_Constant);
15531
15532var AST_Null = DEFNODE("Null", null, {
15533 $documentation: "The `null` atom",
15534 value: null
15535}, AST_Atom);
15536
15537var AST_NaN = DEFNODE("NaN", null, {
15538 $documentation: "The impossible value",
15539 value: 0/0
15540}, AST_Atom);
15541
15542var AST_Undefined = DEFNODE("Undefined", null, {
15543 $documentation: "The `undefined` value",
15544 value: (function(){}())
15545}, AST_Atom);
15546
15547var AST_Hole = DEFNODE("Hole", null, {
15548 $documentation: "A hole in an array",
15549 value: (function(){}())
15550}, AST_Atom);
15551
15552var AST_Infinity = DEFNODE("Infinity", null, {
15553 $documentation: "The `Infinity` value",
15554 value: 1/0
15555}, AST_Atom);
15556
15557var AST_Boolean = DEFNODE("Boolean", null, {
15558 $documentation: "Base class for booleans",
15559}, AST_Atom);
15560
15561var AST_False = DEFNODE("False", null, {
15562 $documentation: "The `false` atom",
15563 value: false
15564}, AST_Boolean);
15565
15566var AST_True = DEFNODE("True", null, {
15567 $documentation: "The `true` atom",
15568 value: true
15569}, AST_Boolean);
15570
15571/* -----[ TreeWalker ]----- */
15572
15573function TreeWalker(callback) {
15574 this.visit = callback;
15575 this.stack = [];
15576 this.directives = Object.create(null);
15577};
15578TreeWalker.prototype = {
15579 _visit: function(node, descend) {
15580 this.push(node);
15581 var ret = this.visit(node, descend ? function(){
15582 descend.call(node);
15583 } : noop);
15584 if (!ret && descend) {
15585 descend.call(node);
15586 }
15587 this.pop(node);
15588 return ret;
15589 },
15590 parent: function(n) {
15591 return this.stack[this.stack.length - 2 - (n || 0)];
15592 },
15593 push: function (node) {
15594 if (node instanceof AST_Lambda) {
15595 this.directives = Object.create(this.directives);
15596 } else if (node instanceof AST_Directive && !this.directives[node.value]) {
15597 this.directives[node.value] = node;
15598 }
15599 this.stack.push(node);
15600 },
15601 pop: function(node) {
15602 this.stack.pop();
15603 if (node instanceof AST_Lambda) {
15604 this.directives = Object.getPrototypeOf(this.directives);
15605 }
15606 },
15607 self: function() {
15608 return this.stack[this.stack.length - 1];
15609 },
15610 find_parent: function(type) {
15611 var stack = this.stack;
15612 for (var i = stack.length; --i >= 0;) {
15613 var x = stack[i];
15614 if (x instanceof type) return x;
15615 }
15616 },
15617 has_directive: function(type) {
15618 var dir = this.directives[type];
15619 if (dir) return dir;
15620 var node = this.stack[this.stack.length - 1];
15621 if (node instanceof AST_Scope) {
15622 for (var i = 0; i < node.body.length; ++i) {
15623 var st = node.body[i];
15624 if (!(st instanceof AST_Directive)) break;
15625 if (st.value == type) return st;
15626 }
15627 }
15628 },
15629 in_boolean_context: function() {
15630 var stack = this.stack;
15631 var i = stack.length, self = stack[--i];
15632 while (i > 0) {
15633 var p = stack[--i];
15634 if ((p instanceof AST_If && p.condition === self) ||
15635 (p instanceof AST_Conditional && p.condition === self) ||
15636 (p instanceof AST_DWLoop && p.condition === self) ||
15637 (p instanceof AST_For && p.condition === self) ||
15638 (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))
15639 {
15640 return true;
15641 }
15642 if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
15643 return false;
15644 self = p;
15645 }
15646 },
15647 loopcontrol_target: function(node) {
15648 var stack = this.stack;
15649 if (node.label) for (var i = stack.length; --i >= 0;) {
15650 var x = stack[i];
15651 if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)
15652 return x.body;
15653 } else for (var i = stack.length; --i >= 0;) {
15654 var x = stack[i];
15655 if (x instanceof AST_IterationStatement
15656 || node instanceof AST_Break && x instanceof AST_Switch)
15657 return x;
15658 }
15659 }
15660};
15661
15662/***********************************************************************
15663
15664 A JavaScript tokenizer / parser / beautifier / compressor.
15665 https://github.com/mishoo/UglifyJS2
15666
15667 -------------------------------- (C) ---------------------------------
15668
15669 Author: Mihai Bazon
15670 <mihai.bazon@gmail.com>
15671 http://mihai.bazon.net/blog
15672
15673 Distributed under the BSD license:
15674
15675 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
15676 Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/).
15677
15678 Redistribution and use in source and binary forms, with or without
15679 modification, are permitted provided that the following conditions
15680 are met:
15681
15682 * Redistributions of source code must retain the above
15683 copyright notice, this list of conditions and the following
15684 disclaimer.
15685
15686 * Redistributions in binary form must reproduce the above
15687 copyright notice, this list of conditions and the following
15688 disclaimer in the documentation and/or other materials
15689 provided with the distribution.
15690
15691 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
15692 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15693 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15694 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
15695 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
15696 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
15697 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15698 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
15699 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
15700 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
15701 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
15702 SUCH DAMAGE.
15703
15704 ***********************************************************************/
15705
15706"use strict";
15707
15708var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
15709var KEYWORDS_ATOM = 'false null true';
15710var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield'
15711 + " " + KEYWORDS_ATOM + " " + KEYWORDS;
15712var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
15713
15714KEYWORDS = makePredicate(KEYWORDS);
15715RESERVED_WORDS = makePredicate(RESERVED_WORDS);
15716KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
15717KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
15718
15719var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
15720
15721var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
15722var RE_OCT_NUMBER = /^0[0-7]+$/;
15723
15724var OPERATORS = makePredicate([
15725 "in",
15726 "instanceof",
15727 "typeof",
15728 "new",
15729 "void",
15730 "delete",
15731 "++",
15732 "--",
15733 "+",
15734 "-",
15735 "!",
15736 "~",
15737 "&",
15738 "|",
15739 "^",
15740 "*",
15741 "/",
15742 "%",
15743 ">>",
15744 "<<",
15745 ">>>",
15746 "<",
15747 ">",
15748 "<=",
15749 ">=",
15750 "==",
15751 "===",
15752 "!=",
15753 "!==",
15754 "?",
15755 "=",
15756 "+=",
15757 "-=",
15758 "/=",
15759 "*=",
15760 "%=",
15761 ">>=",
15762 "<<=",
15763 ">>>=",
15764 "|=",
15765 "^=",
15766 "&=",
15767 "&&",
15768 "||"
15769]);
15770
15771var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\uFEFF"));
15772
15773var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
15774
15775var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
15776
15777var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
15778
15779var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
15780
15781/* -----[ Tokenizer ]----- */
15782
15783// regexps adapted from http://xregexp.com/plugins/#unicode
15784var UNICODE = {
15785 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\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\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-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
15786 digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]"),
15787 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]"),
15788 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]"),
15789 connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
15790};
15791
15792function is_letter(code) {
15793 return (code >= 97 && code <= 122)
15794 || (code >= 65 && code <= 90)
15795 || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
15796};
15797
15798function is_digit(code) {
15799 return code >= 48 && code <= 57;
15800};
15801
15802function is_alphanumeric_char(code) {
15803 return is_digit(code) || is_letter(code);
15804};
15805
15806function is_unicode_digit(code) {
15807 return UNICODE.digit.test(String.fromCharCode(code));
15808}
15809
15810function is_unicode_combining_mark(ch) {
15811 return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
15812};
15813
15814function is_unicode_connector_punctuation(ch) {
15815 return UNICODE.connector_punctuation.test(ch);
15816};
15817
15818function is_identifier(name) {
15819 return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
15820};
15821
15822function is_identifier_start(code) {
15823 return code == 36 || code == 95 || is_letter(code);
15824};
15825
15826function is_identifier_char(ch) {
15827 var code = ch.charCodeAt(0);
15828 return is_identifier_start(code)
15829 || is_digit(code)
15830 || code == 8204 // \u200c: zero-width non-joiner <ZWNJ>
15831 || code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
15832 || is_unicode_combining_mark(ch)
15833 || is_unicode_connector_punctuation(ch)
15834 || is_unicode_digit(code)
15835 ;
15836};
15837
15838function is_identifier_string(str){
15839 return /^[a-z_$][a-z0-9_$]*$/i.test(str);
15840};
15841
15842function parse_js_number(num) {
15843 if (RE_HEX_NUMBER.test(num)) {
15844 return parseInt(num.substr(2), 16);
15845 } else if (RE_OCT_NUMBER.test(num)) {
15846 return parseInt(num.substr(1), 8);
15847 } else {
15848 var val = parseFloat(num);
15849 if (val == num) return val;
15850 }
15851};
15852
15853function JS_Parse_Error(message, filename, line, col, pos) {
15854 this.message = message;
15855 this.filename = filename;
15856 this.line = line;
15857 this.col = col;
15858 this.pos = pos;
15859};
15860JS_Parse_Error.prototype = Object.create(Error.prototype);
15861JS_Parse_Error.prototype.constructor = JS_Parse_Error;
15862JS_Parse_Error.prototype.name = "SyntaxError";
15863configure_error_stack(JS_Parse_Error);
15864
15865function js_error(message, filename, line, col, pos) {
15866 throw new JS_Parse_Error(message, filename, line, col, pos);
15867};
15868
15869function is_token(token, type, val) {
15870 return token.type == type && (val == null || token.value == val);
15871};
15872
15873var EX_EOF = {};
15874
15875function tokenizer($TEXT, filename, html5_comments, shebang) {
15876
15877 var S = {
15878 text : $TEXT,
15879 filename : filename,
15880 pos : 0,
15881 tokpos : 0,
15882 line : 1,
15883 tokline : 0,
15884 col : 0,
15885 tokcol : 0,
15886 newline_before : false,
15887 regex_allowed : false,
15888 comments_before : [],
15889 directives : {},
15890 directive_stack : []
15891 };
15892
15893 function peek() { return S.text.charAt(S.pos); };
15894
15895 function next(signal_eof, in_string) {
15896 var ch = S.text.charAt(S.pos++);
15897 if (signal_eof && !ch)
15898 throw EX_EOF;
15899 if (NEWLINE_CHARS(ch)) {
15900 S.newline_before = S.newline_before || !in_string;
15901 ++S.line;
15902 S.col = 0;
15903 if (!in_string && ch == "\r" && peek() == "\n") {
15904 // treat a \r\n sequence as a single \n
15905 ++S.pos;
15906 ch = "\n";
15907 }
15908 } else {
15909 ++S.col;
15910 }
15911 return ch;
15912 };
15913
15914 function forward(i) {
15915 while (i-- > 0) next();
15916 };
15917
15918 function looking_at(str) {
15919 return S.text.substr(S.pos, str.length) == str;
15920 };
15921
15922 function find_eol() {
15923 var text = S.text;
15924 for (var i = S.pos, n = S.text.length; i < n; ++i) {
15925 var ch = text[i];
15926 if (NEWLINE_CHARS(ch))
15927 return i;
15928 }
15929 return -1;
15930 };
15931
15932 function find(what, signal_eof) {
15933 var pos = S.text.indexOf(what, S.pos);
15934 if (signal_eof && pos == -1) throw EX_EOF;
15935 return pos;
15936 };
15937
15938 function start_token() {
15939 S.tokline = S.line;
15940 S.tokcol = S.col;
15941 S.tokpos = S.pos;
15942 };
15943
15944 var prev_was_dot = false;
15945 function token(type, value, is_comment) {
15946 S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) ||
15947 (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
15948 (type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
15949 if (type == "punc" && value == ".") {
15950 prev_was_dot = true;
15951 } else if (!is_comment) {
15952 prev_was_dot = false;
15953 }
15954 var ret = {
15955 type : type,
15956 value : value,
15957 line : S.tokline,
15958 col : S.tokcol,
15959 pos : S.tokpos,
15960 endline : S.line,
15961 endcol : S.col,
15962 endpos : S.pos,
15963 nlb : S.newline_before,
15964 file : filename
15965 };
15966 if (/^(?:num|string|regexp)$/i.test(type)) {
15967 ret.raw = $TEXT.substring(ret.pos, ret.endpos);
15968 }
15969 if (!is_comment) {
15970 ret.comments_before = S.comments_before;
15971 S.comments_before = [];
15972 // make note of any newlines in the comments that came before
15973 for (var i = 0, len = ret.comments_before.length; i < len; i++) {
15974 ret.nlb = ret.nlb || ret.comments_before[i].nlb;
15975 }
15976 }
15977 S.newline_before = false;
15978 return new AST_Token(ret);
15979 };
15980
15981 function skip_whitespace() {
15982 while (WHITESPACE_CHARS(peek()))
15983 next();
15984 };
15985
15986 function read_while(pred) {
15987 var ret = "", ch, i = 0;
15988 while ((ch = peek()) && pred(ch, i++))
15989 ret += next();
15990 return ret;
15991 };
15992
15993 function parse_error(err) {
15994 js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
15995 };
15996
15997 function read_num(prefix) {
15998 var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
15999 var num = read_while(function(ch, i){
16000 var code = ch.charCodeAt(0);
16001 switch (code) {
16002 case 120: case 88: // xX
16003 return has_x ? false : (has_x = true);
16004 case 101: case 69: // eE
16005 return has_x ? true : has_e ? false : (has_e = after_e = true);
16006 case 45: // -
16007 return after_e || (i == 0 && !prefix);
16008 case 43: // +
16009 return after_e;
16010 case (after_e = false, 46): // .
16011 return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
16012 }
16013 return is_alphanumeric_char(code);
16014 });
16015 if (prefix) num = prefix + num;
16016 if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
16017 parse_error("Legacy octal literals are not allowed in strict mode");
16018 }
16019 var valid = parse_js_number(num);
16020 if (!isNaN(valid)) {
16021 return token("num", valid);
16022 } else {
16023 parse_error("Invalid syntax: " + num);
16024 }
16025 };
16026
16027 function read_escaped_char(in_string) {
16028 var ch = next(true, in_string);
16029 switch (ch.charCodeAt(0)) {
16030 case 110 : return "\n";
16031 case 114 : return "\r";
16032 case 116 : return "\t";
16033 case 98 : return "\b";
16034 case 118 : return "\u000b"; // \v
16035 case 102 : return "\f";
16036 case 120 : return String.fromCharCode(hex_bytes(2)); // \x
16037 case 117 : return String.fromCharCode(hex_bytes(4)); // \u
16038 case 10 : return ""; // newline
16039 case 13 : // \r
16040 if (peek() == "\n") { // DOS newline
16041 next(true, in_string);
16042 return "";
16043 }
16044 }
16045 if (ch >= "0" && ch <= "7")
16046 return read_octal_escape_sequence(ch);
16047 return ch;
16048 };
16049
16050 function read_octal_escape_sequence(ch) {
16051 // Read
16052 var p = peek();
16053 if (p >= "0" && p <= "7") {
16054 ch += next(true);
16055 if (ch[0] <= "3" && (p = peek()) >= "0" && p <= "7")
16056 ch += next(true);
16057 }
16058
16059 // Parse
16060 if (ch === "0") return "\0";
16061 if (ch.length > 0 && next_token.has_directive("use strict"))
16062 parse_error("Legacy octal escape sequences are not allowed in strict mode");
16063 return String.fromCharCode(parseInt(ch, 8));
16064 }
16065
16066 function hex_bytes(n) {
16067 var num = 0;
16068 for (; n > 0; --n) {
16069 var digit = parseInt(next(true), 16);
16070 if (isNaN(digit))
16071 parse_error("Invalid hex-character pattern in string");
16072 num = (num << 4) | digit;
16073 }
16074 return num;
16075 };
16076
16077 var read_string = with_eof_error("Unterminated string constant", function(quote_char){
16078 var quote = next(), ret = "";
16079 for (;;) {
16080 var ch = next(true, true);
16081 if (ch == "\\") ch = read_escaped_char(true);
16082 else if (NEWLINE_CHARS(ch)) parse_error("Unterminated string constant");
16083 else if (ch == quote) break;
16084 ret += ch;
16085 }
16086 var tok = token("string", ret);
16087 tok.quote = quote_char;
16088 return tok;
16089 });
16090
16091 function skip_line_comment(type) {
16092 var regex_allowed = S.regex_allowed;
16093 var i = find_eol(), ret;
16094 if (i == -1) {
16095 ret = S.text.substr(S.pos);
16096 S.pos = S.text.length;
16097 } else {
16098 ret = S.text.substring(S.pos, i);
16099 S.pos = i;
16100 }
16101 S.col = S.tokcol + (S.pos - S.tokpos);
16102 S.comments_before.push(token(type, ret, true));
16103 S.regex_allowed = regex_allowed;
16104 return next_token;
16105 };
16106
16107 var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
16108 var regex_allowed = S.regex_allowed;
16109 var i = find("*/", true);
16110 var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
16111 // update stream position
16112 forward(text.length /* doesn't count \r\n as 2 char while S.pos - i does */ + 2);
16113 S.comments_before.push(token("comment2", text, true));
16114 S.regex_allowed = regex_allowed;
16115 return next_token;
16116 });
16117
16118 function read_name() {
16119 var backslash = false, name = "", ch, escaped = false, hex;
16120 while ((ch = peek()) != null) {
16121 if (!backslash) {
16122 if (ch == "\\") escaped = backslash = true, next();
16123 else if (is_identifier_char(ch)) name += next();
16124 else break;
16125 }
16126 else {
16127 if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
16128 ch = read_escaped_char();
16129 if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
16130 name += ch;
16131 backslash = false;
16132 }
16133 }
16134 if (KEYWORDS(name) && escaped) {
16135 hex = name.charCodeAt(0).toString(16).toUpperCase();
16136 name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
16137 }
16138 return name;
16139 };
16140
16141 var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
16142 var prev_backslash = false, ch, in_class = false;
16143 while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
16144 parse_error("Unexpected line terminator");
16145 } else if (prev_backslash) {
16146 regexp += "\\" + ch;
16147 prev_backslash = false;
16148 } else if (ch == "[") {
16149 in_class = true;
16150 regexp += ch;
16151 } else if (ch == "]" && in_class) {
16152 in_class = false;
16153 regexp += ch;
16154 } else if (ch == "/" && !in_class) {
16155 break;
16156 } else if (ch == "\\") {
16157 prev_backslash = true;
16158 } else {
16159 regexp += ch;
16160 }
16161 var mods = read_name();
16162 try {
16163 return token("regexp", new RegExp(regexp, mods));
16164 } catch(e) {
16165 parse_error(e.message);
16166 }
16167 });
16168
16169 function read_operator(prefix) {
16170 function grow(op) {
16171 if (!peek()) return op;
16172 var bigger = op + peek();
16173 if (OPERATORS(bigger)) {
16174 next();
16175 return grow(bigger);
16176 } else {
16177 return op;
16178 }
16179 };
16180 return token("operator", grow(prefix || next()));
16181 };
16182
16183 function handle_slash() {
16184 next();
16185 switch (peek()) {
16186 case "/":
16187 next();
16188 return skip_line_comment("comment1");
16189 case "*":
16190 next();
16191 return skip_multiline_comment();
16192 }
16193 return S.regex_allowed ? read_regexp("") : read_operator("/");
16194 };
16195
16196 function handle_dot() {
16197 next();
16198 return is_digit(peek().charCodeAt(0))
16199 ? read_num(".")
16200 : token("punc", ".");
16201 };
16202
16203 function read_word() {
16204 var word = read_name();
16205 if (prev_was_dot) return token("name", word);
16206 return KEYWORDS_ATOM(word) ? token("atom", word)
16207 : !KEYWORDS(word) ? token("name", word)
16208 : OPERATORS(word) ? token("operator", word)
16209 : token("keyword", word);
16210 };
16211
16212 function with_eof_error(eof_error, cont) {
16213 return function(x) {
16214 try {
16215 return cont(x);
16216 } catch(ex) {
16217 if (ex === EX_EOF) parse_error(eof_error);
16218 else throw ex;
16219 }
16220 };
16221 };
16222
16223 function next_token(force_regexp) {
16224 if (force_regexp != null)
16225 return read_regexp(force_regexp);
16226 if (shebang && S.pos == 0 && looking_at("#!")) {
16227 start_token();
16228 forward(2);
16229 skip_line_comment("comment5");
16230 }
16231 for (;;) {
16232 skip_whitespace();
16233 start_token();
16234 if (html5_comments) {
16235 if (looking_at("<!--")) {
16236 forward(4);
16237 skip_line_comment("comment3");
16238 continue;
16239 }
16240 if (looking_at("-->") && S.newline_before) {
16241 forward(3);
16242 skip_line_comment("comment4");
16243 continue;
16244 }
16245 }
16246 var ch = peek();
16247 if (!ch) return token("eof");
16248 var code = ch.charCodeAt(0);
16249 switch (code) {
16250 case 34: case 39: return read_string(ch);
16251 case 46: return handle_dot();
16252 case 47: {
16253 var tok = handle_slash();
16254 if (tok === next_token) continue;
16255 return tok;
16256 }
16257 }
16258 if (is_digit(code)) return read_num();
16259 if (PUNC_CHARS(ch)) return token("punc", next());
16260 if (OPERATOR_CHARS(ch)) return read_operator();
16261 if (code == 92 || is_identifier_start(code)) return read_word();
16262 break;
16263 }
16264 parse_error("Unexpected character '" + ch + "'");
16265 };
16266
16267 next_token.context = function(nc) {
16268 if (nc) S = nc;
16269 return S;
16270 };
16271
16272 next_token.add_directive = function(directive) {
16273 S.directive_stack[S.directive_stack.length - 1].push(directive);
16274
16275 if (S.directives[directive] === undefined) {
16276 S.directives[directive] = 1;
16277 } else {
16278 S.directives[directive]++;
16279 }
16280 }
16281
16282 next_token.push_directives_stack = function() {
16283 S.directive_stack.push([]);
16284 }
16285
16286 next_token.pop_directives_stack = function() {
16287 var directives = S.directive_stack[S.directive_stack.length - 1];
16288
16289 for (var i = 0; i < directives.length; i++) {
16290 S.directives[directives[i]]--;
16291 }
16292
16293 S.directive_stack.pop();
16294 }
16295
16296 next_token.has_directive = function(directive) {
16297 return S.directives[directive] !== undefined &&
16298 S.directives[directive] > 0;
16299 }
16300
16301 return next_token;
16302
16303};
16304
16305/* -----[ Parser (constants) ]----- */
16306
16307var UNARY_PREFIX = makePredicate([
16308 "typeof",
16309 "void",
16310 "delete",
16311 "--",
16312 "++",
16313 "!",
16314 "~",
16315 "-",
16316 "+"
16317]);
16318
16319var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
16320
16321var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
16322
16323var PRECEDENCE = (function(a, ret){
16324 for (var i = 0; i < a.length; ++i) {
16325 var b = a[i];
16326 for (var j = 0; j < b.length; ++j) {
16327 ret[b[j]] = i + 1;
16328 }
16329 }
16330 return ret;
16331})(
16332 [
16333 ["||"],
16334 ["&&"],
16335 ["|"],
16336 ["^"],
16337 ["&"],
16338 ["==", "===", "!=", "!=="],
16339 ["<", ">", "<=", ">=", "in", "instanceof"],
16340 [">>", "<<", ">>>"],
16341 ["+", "-"],
16342 ["*", "/", "%"]
16343 ],
16344 {}
16345);
16346
16347var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
16348
16349var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
16350
16351/* -----[ Parser ]----- */
16352
16353function parse($TEXT, options) {
16354
16355 options = defaults(options, {
16356 bare_returns : false,
16357 cli : false,
16358 expression : false,
16359 filename : null,
16360 html5_comments : true,
16361 shebang : true,
16362 strict : false,
16363 toplevel : null,
16364 });
16365
16366 var S = {
16367 input : (typeof $TEXT == "string"
16368 ? tokenizer($TEXT, options.filename,
16369 options.html5_comments, options.shebang)
16370 : $TEXT),
16371 token : null,
16372 prev : null,
16373 peeked : null,
16374 in_function : 0,
16375 in_directives : true,
16376 in_loop : 0,
16377 labels : []
16378 };
16379
16380 S.token = next();
16381
16382 function is(type, value) {
16383 return is_token(S.token, type, value);
16384 };
16385
16386 function peek() { return S.peeked || (S.peeked = S.input()); };
16387
16388 function next() {
16389 S.prev = S.token;
16390 if (S.peeked) {
16391 S.token = S.peeked;
16392 S.peeked = null;
16393 } else {
16394 S.token = S.input();
16395 }
16396 S.in_directives = S.in_directives && (
16397 S.token.type == "string" || is("punc", ";")
16398 );
16399 return S.token;
16400 };
16401
16402 function prev() {
16403 return S.prev;
16404 };
16405
16406 function croak(msg, line, col, pos) {
16407 var ctx = S.input.context();
16408 js_error(msg,
16409 ctx.filename,
16410 line != null ? line : ctx.tokline,
16411 col != null ? col : ctx.tokcol,
16412 pos != null ? pos : ctx.tokpos);
16413 };
16414
16415 function token_error(token, msg) {
16416 croak(msg, token.line, token.col);
16417 };
16418
16419 function unexpected(token) {
16420 if (token == null)
16421 token = S.token;
16422 token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
16423 };
16424
16425 function expect_token(type, val) {
16426 if (is(type, val)) {
16427 return next();
16428 }
16429 token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
16430 };
16431
16432 function expect(punc) { return expect_token("punc", punc); };
16433
16434 function can_insert_semicolon() {
16435 return !options.strict && (
16436 S.token.nlb || is("eof") || is("punc", "}")
16437 );
16438 };
16439
16440 function semicolon(optional) {
16441 if (is("punc", ";")) next();
16442 else if (!optional && !can_insert_semicolon()) unexpected();
16443 };
16444
16445 function parenthesised() {
16446 expect("(");
16447 var exp = expression(true);
16448 expect(")");
16449 return exp;
16450 };
16451
16452 function embed_tokens(parser) {
16453 return function() {
16454 var start = S.token;
16455 var expr = parser();
16456 var end = prev();
16457 expr.start = start;
16458 expr.end = end;
16459 return expr;
16460 };
16461 };
16462
16463 function handle_regexp() {
16464 if (is("operator", "/") || is("operator", "/=")) {
16465 S.peeked = null;
16466 S.token = S.input(S.token.value.substr(1)); // force regexp
16467 }
16468 };
16469
16470 var statement = embed_tokens(function() {
16471 handle_regexp();
16472 switch (S.token.type) {
16473 case "string":
16474 if (S.in_directives) {
16475 var token = peek();
16476 if (S.token.raw.indexOf("\\") == -1
16477 && (token.nlb
16478 || is_token(token, "eof")
16479 || is_token(token, "punc", ";")
16480 || is_token(token, "punc", "}"))) {
16481 S.input.add_directive(S.token.value);
16482 } else {
16483 S.in_directives = false;
16484 }
16485 }
16486 var dir = S.in_directives, stat = simple_statement();
16487 return dir ? new AST_Directive(stat.body) : stat;
16488 case "num":
16489 case "regexp":
16490 case "operator":
16491 case "atom":
16492 return simple_statement();
16493
16494 case "name":
16495 return is_token(peek(), "punc", ":")
16496 ? labeled_statement()
16497 : simple_statement();
16498
16499 case "punc":
16500 switch (S.token.value) {
16501 case "{":
16502 return new AST_BlockStatement({
16503 start : S.token,
16504 body : block_(),
16505 end : prev()
16506 });
16507 case "[":
16508 case "(":
16509 return simple_statement();
16510 case ";":
16511 S.in_directives = false;
16512 next();
16513 return new AST_EmptyStatement();
16514 default:
16515 unexpected();
16516 }
16517
16518 case "keyword":
16519 switch (S.token.value) {
16520 case "break":
16521 next();
16522 return break_cont(AST_Break);
16523
16524 case "continue":
16525 next();
16526 return break_cont(AST_Continue);
16527
16528 case "debugger":
16529 next();
16530 semicolon();
16531 return new AST_Debugger();
16532
16533 case "do":
16534 next();
16535 var body = in_loop(statement);
16536 expect_token("keyword", "while");
16537 var condition = parenthesised();
16538 semicolon(true);
16539 return new AST_Do({
16540 body : body,
16541 condition : condition
16542 });
16543
16544 case "while":
16545 next();
16546 return new AST_While({
16547 condition : parenthesised(),
16548 body : in_loop(statement)
16549 });
16550
16551 case "for":
16552 next();
16553 return for_();
16554
16555 case "function":
16556 next();
16557 return function_(AST_Defun);
16558
16559 case "if":
16560 next();
16561 return if_();
16562
16563 case "return":
16564 if (S.in_function == 0 && !options.bare_returns)
16565 croak("'return' outside of function");
16566 next();
16567 var value = null;
16568 if (is("punc", ";")) {
16569 next();
16570 } else if (!can_insert_semicolon()) {
16571 value = expression(true);
16572 semicolon();
16573 }
16574 return new AST_Return({
16575 value: value
16576 });
16577
16578 case "switch":
16579 next();
16580 return new AST_Switch({
16581 expression : parenthesised(),
16582 body : in_loop(switch_body_)
16583 });
16584
16585 case "throw":
16586 next();
16587 if (S.token.nlb)
16588 croak("Illegal newline after 'throw'");
16589 var value = expression(true);
16590 semicolon();
16591 return new AST_Throw({
16592 value: value
16593 });
16594
16595 case "try":
16596 next();
16597 return try_();
16598
16599 case "var":
16600 next();
16601 var node = var_();
16602 semicolon();
16603 return node;
16604
16605 case "const":
16606 next();
16607 var node = const_();
16608 semicolon();
16609 return node;
16610
16611 case "with":
16612 if (S.input.has_directive("use strict")) {
16613 croak("Strict mode may not include a with statement");
16614 }
16615 next();
16616 return new AST_With({
16617 expression : parenthesised(),
16618 body : statement()
16619 });
16620 }
16621 }
16622 unexpected();
16623 });
16624
16625 function labeled_statement() {
16626 var label = as_symbol(AST_Label);
16627 if (find_if(function(l){ return l.name == label.name }, S.labels)) {
16628 // ECMA-262, 12.12: An ECMAScript program is considered
16629 // syntactically incorrect if it contains a
16630 // LabelledStatement that is enclosed by a
16631 // LabelledStatement with the same Identifier as label.
16632 croak("Label " + label.name + " defined twice");
16633 }
16634 expect(":");
16635 S.labels.push(label);
16636 var stat = statement();
16637 S.labels.pop();
16638 if (!(stat instanceof AST_IterationStatement)) {
16639 // check for `continue` that refers to this label.
16640 // those should be reported as syntax errors.
16641 // https://github.com/mishoo/UglifyJS2/issues/287
16642 label.references.forEach(function(ref){
16643 if (ref instanceof AST_Continue) {
16644 ref = ref.label.start;
16645 croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
16646 ref.line, ref.col, ref.pos);
16647 }
16648 });
16649 }
16650 return new AST_LabeledStatement({ body: stat, label: label });
16651 };
16652
16653 function simple_statement(tmp) {
16654 return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
16655 };
16656
16657 function break_cont(type) {
16658 var label = null, ldef;
16659 if (!can_insert_semicolon()) {
16660 label = as_symbol(AST_LabelRef, true);
16661 }
16662 if (label != null) {
16663 ldef = find_if(function(l){ return l.name == label.name }, S.labels);
16664 if (!ldef)
16665 croak("Undefined label " + label.name);
16666 label.thedef = ldef;
16667 }
16668 else if (S.in_loop == 0)
16669 croak(type.TYPE + " not inside a loop or switch");
16670 semicolon();
16671 var stat = new type({ label: label });
16672 if (ldef) ldef.references.push(stat);
16673 return stat;
16674 };
16675
16676 function for_() {
16677 expect("(");
16678 var init = null;
16679 if (!is("punc", ";")) {
16680 init = is("keyword", "var")
16681 ? (next(), var_(true))
16682 : expression(true, true);
16683 if (is("operator", "in")) {
16684 if (init instanceof AST_Var && init.definitions.length > 1)
16685 croak("Only one variable declaration allowed in for..in loop");
16686 next();
16687 return for_in(init);
16688 }
16689 }
16690 return regular_for(init);
16691 };
16692
16693 function regular_for(init) {
16694 expect(";");
16695 var test = is("punc", ";") ? null : expression(true);
16696 expect(";");
16697 var step = is("punc", ")") ? null : expression(true);
16698 expect(")");
16699 return new AST_For({
16700 init : init,
16701 condition : test,
16702 step : step,
16703 body : in_loop(statement)
16704 });
16705 };
16706
16707 function for_in(init) {
16708 var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
16709 var obj = expression(true);
16710 expect(")");
16711 return new AST_ForIn({
16712 init : init,
16713 name : lhs,
16714 object : obj,
16715 body : in_loop(statement)
16716 });
16717 };
16718
16719 var function_ = function(ctor) {
16720 var in_statement = ctor === AST_Defun;
16721 var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
16722 if (in_statement && !name)
16723 unexpected();
16724 expect("(");
16725 return new ctor({
16726 name: name,
16727 argnames: (function(first, a){
16728 while (!is("punc", ")")) {
16729 if (first) first = false; else expect(",");
16730 a.push(as_symbol(AST_SymbolFunarg));
16731 }
16732 next();
16733 return a;
16734 })(true, []),
16735 body: (function(loop, labels){
16736 ++S.in_function;
16737 S.in_directives = true;
16738 S.input.push_directives_stack();
16739 S.in_loop = 0;
16740 S.labels = [];
16741 var a = block_();
16742 S.input.pop_directives_stack();
16743 --S.in_function;
16744 S.in_loop = loop;
16745 S.labels = labels;
16746 return a;
16747 })(S.in_loop, S.labels)
16748 });
16749 };
16750
16751 function if_() {
16752 var cond = parenthesised(), body = statement(), belse = null;
16753 if (is("keyword", "else")) {
16754 next();
16755 belse = statement();
16756 }
16757 return new AST_If({
16758 condition : cond,
16759 body : body,
16760 alternative : belse
16761 });
16762 };
16763
16764 function block_() {
16765 expect("{");
16766 var a = [];
16767 while (!is("punc", "}")) {
16768 if (is("eof")) unexpected();
16769 a.push(statement());
16770 }
16771 next();
16772 return a;
16773 };
16774
16775 function switch_body_() {
16776 expect("{");
16777 var a = [], cur = null, branch = null, tmp;
16778 while (!is("punc", "}")) {
16779 if (is("eof")) unexpected();
16780 if (is("keyword", "case")) {
16781 if (branch) branch.end = prev();
16782 cur = [];
16783 branch = new AST_Case({
16784 start : (tmp = S.token, next(), tmp),
16785 expression : expression(true),
16786 body : cur
16787 });
16788 a.push(branch);
16789 expect(":");
16790 }
16791 else if (is("keyword", "default")) {
16792 if (branch) branch.end = prev();
16793 cur = [];
16794 branch = new AST_Default({
16795 start : (tmp = S.token, next(), expect(":"), tmp),
16796 body : cur
16797 });
16798 a.push(branch);
16799 }
16800 else {
16801 if (!cur) unexpected();
16802 cur.push(statement());
16803 }
16804 }
16805 if (branch) branch.end = prev();
16806 next();
16807 return a;
16808 };
16809
16810 function try_() {
16811 var body = block_(), bcatch = null, bfinally = null;
16812 if (is("keyword", "catch")) {
16813 var start = S.token;
16814 next();
16815 expect("(");
16816 var name = as_symbol(AST_SymbolCatch);
16817 expect(")");
16818 bcatch = new AST_Catch({
16819 start : start,
16820 argname : name,
16821 body : block_(),
16822 end : prev()
16823 });
16824 }
16825 if (is("keyword", "finally")) {
16826 var start = S.token;
16827 next();
16828 bfinally = new AST_Finally({
16829 start : start,
16830 body : block_(),
16831 end : prev()
16832 });
16833 }
16834 if (!bcatch && !bfinally)
16835 croak("Missing catch/finally blocks");
16836 return new AST_Try({
16837 body : body,
16838 bcatch : bcatch,
16839 bfinally : bfinally
16840 });
16841 };
16842
16843 function vardefs(no_in, in_const) {
16844 var a = [];
16845 for (;;) {
16846 a.push(new AST_VarDef({
16847 start : S.token,
16848 name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
16849 value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
16850 end : prev()
16851 }));
16852 if (!is("punc", ","))
16853 break;
16854 next();
16855 }
16856 return a;
16857 };
16858
16859 var var_ = function(no_in) {
16860 return new AST_Var({
16861 start : prev(),
16862 definitions : vardefs(no_in, false),
16863 end : prev()
16864 });
16865 };
16866
16867 var const_ = function() {
16868 return new AST_Const({
16869 start : prev(),
16870 definitions : vardefs(false, true),
16871 end : prev()
16872 });
16873 };
16874
16875 var new_ = function(allow_calls) {
16876 var start = S.token;
16877 expect_token("operator", "new");
16878 var newexp = expr_atom(false), args;
16879 if (is("punc", "(")) {
16880 next();
16881 args = expr_list(")");
16882 } else {
16883 args = [];
16884 }
16885 return subscripts(new AST_New({
16886 start : start,
16887 expression : newexp,
16888 args : args,
16889 end : prev()
16890 }), allow_calls);
16891 };
16892
16893 function as_atom_node() {
16894 var tok = S.token, ret;
16895 switch (tok.type) {
16896 case "name":
16897 case "keyword":
16898 ret = _make_symbol(AST_SymbolRef);
16899 break;
16900 case "num":
16901 ret = new AST_Number({ start: tok, end: tok, value: tok.value });
16902 break;
16903 case "string":
16904 ret = new AST_String({
16905 start : tok,
16906 end : tok,
16907 value : tok.value,
16908 quote : tok.quote
16909 });
16910 break;
16911 case "regexp":
16912 ret = new AST_RegExp({ start: tok, end: tok, value: tok.value });
16913 break;
16914 case "atom":
16915 switch (tok.value) {
16916 case "false":
16917 ret = new AST_False({ start: tok, end: tok });
16918 break;
16919 case "true":
16920 ret = new AST_True({ start: tok, end: tok });
16921 break;
16922 case "null":
16923 ret = new AST_Null({ start: tok, end: tok });
16924 break;
16925 }
16926 break;
16927 case "operator":
16928 if (!is_identifier_string(tok.value)) {
16929 croak("Invalid getter/setter name: " + tok.value,
16930 tok.line, tok.col, tok.pos);
16931 }
16932 ret = _make_symbol(AST_SymbolRef);
16933 break;
16934 }
16935 next();
16936 return ret;
16937 };
16938
16939 var expr_atom = function(allow_calls) {
16940 if (is("operator", "new")) {
16941 return new_(allow_calls);
16942 }
16943 var start = S.token;
16944 if (is("punc")) {
16945 switch (start.value) {
16946 case "(":
16947 next();
16948 var ex = expression(true);
16949 ex.start = start;
16950 ex.end = S.token;
16951 expect(")");
16952 return subscripts(ex, allow_calls);
16953 case "[":
16954 return subscripts(array_(), allow_calls);
16955 case "{":
16956 return subscripts(object_(), allow_calls);
16957 }
16958 unexpected();
16959 }
16960 if (is("keyword", "function")) {
16961 next();
16962 var func = function_(AST_Function);
16963 func.start = start;
16964 func.end = prev();
16965 return subscripts(func, allow_calls);
16966 }
16967 if (ATOMIC_START_TOKEN[S.token.type]) {
16968 return subscripts(as_atom_node(), allow_calls);
16969 }
16970 unexpected();
16971 };
16972
16973 function expr_list(closing, allow_trailing_comma, allow_empty) {
16974 var first = true, a = [];
16975 while (!is("punc", closing)) {
16976 if (first) first = false; else expect(",");
16977 if (allow_trailing_comma && is("punc", closing)) break;
16978 if (is("punc", ",") && allow_empty) {
16979 a.push(new AST_Hole({ start: S.token, end: S.token }));
16980 } else {
16981 a.push(expression(false));
16982 }
16983 }
16984 next();
16985 return a;
16986 };
16987
16988 var array_ = embed_tokens(function() {
16989 expect("[");
16990 return new AST_Array({
16991 elements: expr_list("]", !options.strict, true)
16992 });
16993 });
16994
16995 var create_accessor = embed_tokens(function() {
16996 return function_(AST_Accessor);
16997 });
16998
16999 var object_ = embed_tokens(function() {
17000 expect("{");
17001 var first = true, a = [];
17002 while (!is("punc", "}")) {
17003 if (first) first = false; else expect(",");
17004 if (!options.strict && is("punc", "}"))
17005 // allow trailing comma
17006 break;
17007 var start = S.token;
17008 var type = start.type;
17009 var name = as_property_name();
17010 if (type == "name" && !is("punc", ":")) {
17011 var key = new AST_SymbolAccessor({
17012 start: S.token,
17013 name: as_property_name(),
17014 end: prev()
17015 });
17016 if (name == "get") {
17017 a.push(new AST_ObjectGetter({
17018 start : start,
17019 key : key,
17020 value : create_accessor(),
17021 end : prev()
17022 }));
17023 continue;
17024 }
17025 if (name == "set") {
17026 a.push(new AST_ObjectSetter({
17027 start : start,
17028 key : key,
17029 value : create_accessor(),
17030 end : prev()
17031 }));
17032 continue;
17033 }
17034 }
17035 expect(":");
17036 a.push(new AST_ObjectKeyVal({
17037 start : start,
17038 quote : start.quote,
17039 key : name,
17040 value : expression(false),
17041 end : prev()
17042 }));
17043 }
17044 next();
17045 return new AST_Object({ properties: a });
17046 });
17047
17048 function as_property_name() {
17049 var tmp = S.token;
17050 switch (tmp.type) {
17051 case "operator":
17052 if (!KEYWORDS(tmp.value)) unexpected();
17053 case "num":
17054 case "string":
17055 case "name":
17056 case "keyword":
17057 case "atom":
17058 next();
17059 return tmp.value;
17060 default:
17061 unexpected();
17062 }
17063 };
17064
17065 function as_name() {
17066 var tmp = S.token;
17067 if (tmp.type != "name") unexpected();
17068 next();
17069 return tmp.value;
17070 };
17071
17072 function _make_symbol(type) {
17073 var name = S.token.value;
17074 return new (name == "this" ? AST_This : type)({
17075 name : String(name),
17076 start : S.token,
17077 end : S.token
17078 });
17079 };
17080
17081 function as_symbol(type, noerror) {
17082 if (!is("name")) {
17083 if (!noerror) croak("Name expected");
17084 return null;
17085 }
17086 var sym = _make_symbol(type);
17087 next();
17088 return sym;
17089 };
17090
17091 var subscripts = function(expr, allow_calls) {
17092 var start = expr.start;
17093 if (is("punc", ".")) {
17094 next();
17095 return subscripts(new AST_Dot({
17096 start : start,
17097 expression : expr,
17098 property : as_name(),
17099 end : prev()
17100 }), allow_calls);
17101 }
17102 if (is("punc", "[")) {
17103 next();
17104 var prop = expression(true);
17105 expect("]");
17106 return subscripts(new AST_Sub({
17107 start : start,
17108 expression : expr,
17109 property : prop,
17110 end : prev()
17111 }), allow_calls);
17112 }
17113 if (allow_calls && is("punc", "(")) {
17114 next();
17115 return subscripts(new AST_Call({
17116 start : start,
17117 expression : expr,
17118 args : expr_list(")"),
17119 end : prev()
17120 }), true);
17121 }
17122 return expr;
17123 };
17124
17125 var maybe_unary = function(allow_calls) {
17126 var start = S.token;
17127 if (is("operator") && UNARY_PREFIX(start.value)) {
17128 next();
17129 handle_regexp();
17130 var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
17131 ex.start = start;
17132 ex.end = prev();
17133 return ex;
17134 }
17135 var val = expr_atom(allow_calls);
17136 while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
17137 val = make_unary(AST_UnaryPostfix, S.token, val);
17138 val.start = start;
17139 val.end = S.token;
17140 next();
17141 }
17142 return val;
17143 };
17144
17145 function make_unary(ctor, token, expr) {
17146 var op = token.value;
17147 if ((op == "++" || op == "--") && !is_assignable(expr))
17148 croak("Invalid use of " + op + " operator", token.line, token.col, token.pos);
17149 return new ctor({ operator: op, expression: expr });
17150 };
17151
17152 var expr_op = function(left, min_prec, no_in) {
17153 var op = is("operator") ? S.token.value : null;
17154 if (op == "in" && no_in) op = null;
17155 var prec = op != null ? PRECEDENCE[op] : null;
17156 if (prec != null && prec > min_prec) {
17157 next();
17158 var right = expr_op(maybe_unary(true), prec, no_in);
17159 return expr_op(new AST_Binary({
17160 start : left.start,
17161 left : left,
17162 operator : op,
17163 right : right,
17164 end : right.end
17165 }), min_prec, no_in);
17166 }
17167 return left;
17168 };
17169
17170 function expr_ops(no_in) {
17171 return expr_op(maybe_unary(true), 0, no_in);
17172 };
17173
17174 var maybe_conditional = function(no_in) {
17175 var start = S.token;
17176 var expr = expr_ops(no_in);
17177 if (is("operator", "?")) {
17178 next();
17179 var yes = expression(false);
17180 expect(":");
17181 return new AST_Conditional({
17182 start : start,
17183 condition : expr,
17184 consequent : yes,
17185 alternative : expression(false, no_in),
17186 end : prev()
17187 });
17188 }
17189 return expr;
17190 };
17191
17192 function is_assignable(expr) {
17193 if (options.cli) return true;
17194 return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
17195 };
17196
17197 var maybe_assign = function(no_in) {
17198 var start = S.token;
17199 var left = maybe_conditional(no_in), val = S.token.value;
17200 if (is("operator") && ASSIGNMENT(val)) {
17201 if (is_assignable(left)) {
17202 next();
17203 return new AST_Assign({
17204 start : start,
17205 left : left,
17206 operator : val,
17207 right : maybe_assign(no_in),
17208 end : prev()
17209 });
17210 }
17211 croak("Invalid assignment");
17212 }
17213 return left;
17214 };
17215
17216 var expression = function(commas, no_in) {
17217 var start = S.token;
17218 var expr = maybe_assign(no_in);
17219 if (commas && is("punc", ",")) {
17220 next();
17221 return new AST_Seq({
17222 start : start,
17223 car : expr,
17224 cdr : expression(true, no_in),
17225 end : peek()
17226 });
17227 }
17228 return expr;
17229 };
17230
17231 function in_loop(cont) {
17232 ++S.in_loop;
17233 var ret = cont();
17234 --S.in_loop;
17235 return ret;
17236 };
17237
17238 if (options.expression) {
17239 return expression(true);
17240 }
17241
17242 return (function(){
17243 var start = S.token;
17244 var body = [];
17245 S.input.push_directives_stack();
17246 while (!is("eof"))
17247 body.push(statement());
17248 S.input.pop_directives_stack();
17249 var end = prev();
17250 var toplevel = options.toplevel;
17251 if (toplevel) {
17252 toplevel.body = toplevel.body.concat(body);
17253 toplevel.end = end;
17254 } else {
17255 toplevel = new AST_Toplevel({ start: start, body: body, end: end });
17256 }
17257 return toplevel;
17258 })();
17259
17260};
17261
17262/***********************************************************************
17263
17264 A JavaScript tokenizer / parser / beautifier / compressor.
17265 https://github.com/mishoo/UglifyJS2
17266
17267 -------------------------------- (C) ---------------------------------
17268
17269 Author: Mihai Bazon
17270 <mihai.bazon@gmail.com>
17271 http://mihai.bazon.net/blog
17272
17273 Distributed under the BSD license:
17274
17275 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
17276
17277 Redistribution and use in source and binary forms, with or without
17278 modification, are permitted provided that the following conditions
17279 are met:
17280
17281 * Redistributions of source code must retain the above
17282 copyright notice, this list of conditions and the following
17283 disclaimer.
17284
17285 * Redistributions in binary form must reproduce the above
17286 copyright notice, this list of conditions and the following
17287 disclaimer in the documentation and/or other materials
17288 provided with the distribution.
17289
17290 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
17291 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17292 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17293 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
17294 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
17295 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17296 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
17297 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
17298 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
17299 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
17300 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
17301 SUCH DAMAGE.
17302
17303 ***********************************************************************/
17304
17305"use strict";
17306
17307// Tree transformer helpers.
17308
17309function TreeTransformer(before, after) {
17310 TreeWalker.call(this);
17311 this.before = before;
17312 this.after = after;
17313}
17314TreeTransformer.prototype = new TreeWalker;
17315
17316(function(undefined){
17317
17318 function _(node, descend) {
17319 node.DEFMETHOD("transform", function(tw, in_list){
17320 var x, y;
17321 tw.push(this);
17322 if (tw.before) x = tw.before(this, descend, in_list);
17323 if (x === undefined) {
17324 if (!tw.after) {
17325 x = this;
17326 descend(x, tw);
17327 } else {
17328 tw.stack[tw.stack.length - 1] = x = this;
17329 descend(x, tw);
17330 y = tw.after(x, in_list);
17331 if (y !== undefined) x = y;
17332 }
17333 }
17334 tw.pop(this);
17335 return x;
17336 });
17337 };
17338
17339 function do_list(list, tw) {
17340 return MAP(list, function(node){
17341 return node.transform(tw, true);
17342 });
17343 };
17344
17345 _(AST_Node, noop);
17346
17347 _(AST_LabeledStatement, function(self, tw){
17348 self.label = self.label.transform(tw);
17349 self.body = self.body.transform(tw);
17350 });
17351
17352 _(AST_SimpleStatement, function(self, tw){
17353 self.body = self.body.transform(tw);
17354 });
17355
17356 _(AST_Block, function(self, tw){
17357 self.body = do_list(self.body, tw);
17358 });
17359
17360 _(AST_DWLoop, function(self, tw){
17361 self.condition = self.condition.transform(tw);
17362 self.body = self.body.transform(tw);
17363 });
17364
17365 _(AST_For, function(self, tw){
17366 if (self.init) self.init = self.init.transform(tw);
17367 if (self.condition) self.condition = self.condition.transform(tw);
17368 if (self.step) self.step = self.step.transform(tw);
17369 self.body = self.body.transform(tw);
17370 });
17371
17372 _(AST_ForIn, function(self, tw){
17373 self.init = self.init.transform(tw);
17374 self.object = self.object.transform(tw);
17375 self.body = self.body.transform(tw);
17376 });
17377
17378 _(AST_With, function(self, tw){
17379 self.expression = self.expression.transform(tw);
17380 self.body = self.body.transform(tw);
17381 });
17382
17383 _(AST_Exit, function(self, tw){
17384 if (self.value) self.value = self.value.transform(tw);
17385 });
17386
17387 _(AST_LoopControl, function(self, tw){
17388 if (self.label) self.label = self.label.transform(tw);
17389 });
17390
17391 _(AST_If, function(self, tw){
17392 self.condition = self.condition.transform(tw);
17393 self.body = self.body.transform(tw);
17394 if (self.alternative) self.alternative = self.alternative.transform(tw);
17395 });
17396
17397 _(AST_Switch, function(self, tw){
17398 self.expression = self.expression.transform(tw);
17399 self.body = do_list(self.body, tw);
17400 });
17401
17402 _(AST_Case, function(self, tw){
17403 self.expression = self.expression.transform(tw);
17404 self.body = do_list(self.body, tw);
17405 });
17406
17407 _(AST_Try, function(self, tw){
17408 self.body = do_list(self.body, tw);
17409 if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
17410 if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
17411 });
17412
17413 _(AST_Catch, function(self, tw){
17414 self.argname = self.argname.transform(tw);
17415 self.body = do_list(self.body, tw);
17416 });
17417
17418 _(AST_Definitions, function(self, tw){
17419 self.definitions = do_list(self.definitions, tw);
17420 });
17421
17422 _(AST_VarDef, function(self, tw){
17423 self.name = self.name.transform(tw);
17424 if (self.value) self.value = self.value.transform(tw);
17425 });
17426
17427 _(AST_Lambda, function(self, tw){
17428 if (self.name) self.name = self.name.transform(tw);
17429 self.argnames = do_list(self.argnames, tw);
17430 self.body = do_list(self.body, tw);
17431 });
17432
17433 _(AST_Call, function(self, tw){
17434 self.expression = self.expression.transform(tw);
17435 self.args = do_list(self.args, tw);
17436 });
17437
17438 _(AST_Seq, function(self, tw){
17439 self.car = self.car.transform(tw);
17440 self.cdr = self.cdr.transform(tw);
17441 });
17442
17443 _(AST_Dot, function(self, tw){
17444 self.expression = self.expression.transform(tw);
17445 });
17446
17447 _(AST_Sub, function(self, tw){
17448 self.expression = self.expression.transform(tw);
17449 self.property = self.property.transform(tw);
17450 });
17451
17452 _(AST_Unary, function(self, tw){
17453 self.expression = self.expression.transform(tw);
17454 });
17455
17456 _(AST_Binary, function(self, tw){
17457 self.left = self.left.transform(tw);
17458 self.right = self.right.transform(tw);
17459 });
17460
17461 _(AST_Conditional, function(self, tw){
17462 self.condition = self.condition.transform(tw);
17463 self.consequent = self.consequent.transform(tw);
17464 self.alternative = self.alternative.transform(tw);
17465 });
17466
17467 _(AST_Array, function(self, tw){
17468 self.elements = do_list(self.elements, tw);
17469 });
17470
17471 _(AST_Object, function(self, tw){
17472 self.properties = do_list(self.properties, tw);
17473 });
17474
17475 _(AST_ObjectProperty, function(self, tw){
17476 self.value = self.value.transform(tw);
17477 });
17478
17479})();
17480
17481/***********************************************************************
17482
17483 A JavaScript tokenizer / parser / beautifier / compressor.
17484 https://github.com/mishoo/UglifyJS2
17485
17486 -------------------------------- (C) ---------------------------------
17487
17488 Author: Mihai Bazon
17489 <mihai.bazon@gmail.com>
17490 http://mihai.bazon.net/blog
17491
17492 Distributed under the BSD license:
17493
17494 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
17495
17496 Redistribution and use in source and binary forms, with or without
17497 modification, are permitted provided that the following conditions
17498 are met:
17499
17500 * Redistributions of source code must retain the above
17501 copyright notice, this list of conditions and the following
17502 disclaimer.
17503
17504 * Redistributions in binary form must reproduce the above
17505 copyright notice, this list of conditions and the following
17506 disclaimer in the documentation and/or other materials
17507 provided with the distribution.
17508
17509 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
17510 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17511 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17512 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
17513 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
17514 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17515 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
17516 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
17517 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
17518 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
17519 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
17520 SUCH DAMAGE.
17521
17522 ***********************************************************************/
17523
17524"use strict";
17525
17526function SymbolDef(scope, index, orig) {
17527 this.name = orig.name;
17528 this.orig = [ orig ];
17529 this.scope = scope;
17530 this.references = [];
17531 this.global = false;
17532 this.mangled_name = null;
17533 this.undeclared = false;
17534 this.index = index;
17535 this.id = SymbolDef.next_id++;
17536};
17537
17538SymbolDef.next_id = 1;
17539
17540SymbolDef.prototype = {
17541 unmangleable: function(options) {
17542 if (!options) options = {};
17543
17544 return (this.global && !options.toplevel)
17545 || this.undeclared
17546 || (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
17547 || (options.keep_fnames
17548 && (this.orig[0] instanceof AST_SymbolLambda
17549 || this.orig[0] instanceof AST_SymbolDefun));
17550 },
17551 mangle: function(options) {
17552 var cache = options.cache && options.cache.props;
17553 if (this.global && cache && cache.has(this.name)) {
17554 this.mangled_name = cache.get(this.name);
17555 }
17556 else if (!this.mangled_name && !this.unmangleable(options)) {
17557 var s = this.scope;
17558 var sym = this.orig[0];
17559 if (!options.screw_ie8 && sym instanceof AST_SymbolLambda)
17560 s = s.parent_scope;
17561 var def;
17562 if (this.defun && (def = this.defun.variables.get(this.name))) {
17563 this.mangled_name = def.mangled_name || def.name;
17564 } else
17565 this.mangled_name = s.next_mangled(options, this);
17566 if (this.global && cache) {
17567 cache.set(this.name, this.mangled_name);
17568 }
17569 }
17570 }
17571};
17572
17573AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
17574 options = defaults(options, {
17575 cache: null,
17576 screw_ie8: true,
17577 });
17578
17579 // pass 1: setup scope chaining and handle definitions
17580 var self = this;
17581 var scope = self.parent_scope = null;
17582 var labels = new Dictionary();
17583 var defun = null;
17584 var tw = new TreeWalker(function(node, descend){
17585 if (node instanceof AST_Catch) {
17586 var save_scope = scope;
17587 scope = new AST_Scope(node);
17588 scope.init_scope_vars(save_scope);
17589 descend();
17590 scope = save_scope;
17591 return true;
17592 }
17593 if (node instanceof AST_Scope) {
17594 node.init_scope_vars(scope);
17595 var save_scope = scope;
17596 var save_defun = defun;
17597 var save_labels = labels;
17598 defun = scope = node;
17599 labels = new Dictionary();
17600 descend();
17601 scope = save_scope;
17602 defun = save_defun;
17603 labels = save_labels;
17604 return true; // don't descend again in TreeWalker
17605 }
17606 if (node instanceof AST_LabeledStatement) {
17607 var l = node.label;
17608 if (labels.has(l.name)) {
17609 throw new Error(string_template("Label {name} defined twice", l));
17610 }
17611 labels.set(l.name, l);
17612 descend();
17613 labels.del(l.name);
17614 return true; // no descend again
17615 }
17616 if (node instanceof AST_With) {
17617 for (var s = scope; s; s = s.parent_scope)
17618 s.uses_with = true;
17619 return;
17620 }
17621 if (node instanceof AST_Symbol) {
17622 node.scope = scope;
17623 }
17624 if (node instanceof AST_Label) {
17625 node.thedef = node;
17626 node.references = [];
17627 }
17628 if (node instanceof AST_SymbolLambda) {
17629 defun.def_function(node);
17630 }
17631 else if (node instanceof AST_SymbolDefun) {
17632 // Careful here, the scope where this should be defined is
17633 // the parent scope. The reason is that we enter a new
17634 // scope when we encounter the AST_Defun node (which is
17635 // instanceof AST_Scope) but we get to the symbol a bit
17636 // later.
17637 (node.scope = defun.parent_scope).def_function(node);
17638 }
17639 else if (node instanceof AST_SymbolVar
17640 || node instanceof AST_SymbolConst) {
17641 defun.def_variable(node);
17642 if (defun !== scope) {
17643 node.mark_enclosed(options);
17644 var def = scope.find_variable(node);
17645 if (node.thedef !== def) {
17646 node.thedef = def;
17647 node.reference(options);
17648 }
17649 }
17650 }
17651 else if (node instanceof AST_SymbolCatch) {
17652 scope.def_variable(node).defun = defun;
17653 }
17654 else if (node instanceof AST_LabelRef) {
17655 var sym = labels.get(node.name);
17656 if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
17657 name: node.name,
17658 line: node.start.line,
17659 col: node.start.col
17660 }));
17661 node.thedef = sym;
17662 }
17663 });
17664 self.walk(tw);
17665
17666 // pass 2: find back references and eval
17667 var func = null;
17668 var globals = self.globals = new Dictionary();
17669 var tw = new TreeWalker(function(node, descend){
17670 if (node instanceof AST_Lambda) {
17671 var prev_func = func;
17672 func = node;
17673 descend();
17674 func = prev_func;
17675 return true;
17676 }
17677 if (node instanceof AST_LoopControl && node.label) {
17678 node.label.thedef.references.push(node);
17679 return true;
17680 }
17681 if (node instanceof AST_SymbolRef) {
17682 var name = node.name;
17683 if (name == "eval" && tw.parent() instanceof AST_Call) {
17684 for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
17685 s.uses_eval = true;
17686 }
17687 }
17688 var sym = node.scope.find_variable(name);
17689 if (node.scope instanceof AST_Lambda && name == "arguments") {
17690 node.scope.uses_arguments = true;
17691 }
17692 if (!sym) {
17693 sym = self.def_global(node);
17694 }
17695 node.thedef = sym;
17696 node.reference(options);
17697 return true;
17698 }
17699 });
17700 self.walk(tw);
17701
17702 // pass 3: fix up any scoping issue with IE8
17703 if (!options.screw_ie8) {
17704 self.walk(new TreeWalker(function(node, descend) {
17705 if (node instanceof AST_SymbolCatch) {
17706 var name = node.name;
17707 var refs = node.thedef.references;
17708 var scope = node.thedef.defun;
17709 var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
17710 refs.forEach(function(ref) {
17711 ref.thedef = def;
17712 ref.reference(options);
17713 });
17714 node.thedef = def;
17715 return true;
17716 }
17717 }));
17718 }
17719
17720 if (options.cache) {
17721 this.cname = options.cache.cname;
17722 }
17723});
17724
17725AST_Toplevel.DEFMETHOD("def_global", function(node){
17726 var globals = this.globals, name = node.name;
17727 if (globals.has(name)) {
17728 return globals.get(name);
17729 } else {
17730 var g = new SymbolDef(this, globals.size(), node);
17731 g.undeclared = true;
17732 g.global = true;
17733 globals.set(name, g);
17734 return g;
17735 }
17736});
17737
17738AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
17739 this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
17740 this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
17741 this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
17742 this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
17743 this.parent_scope = parent_scope; // the parent scope
17744 this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
17745 this.cname = -1; // the current index for mangling functions/variables
17746});
17747
17748AST_Lambda.DEFMETHOD("init_scope_vars", function(){
17749 AST_Scope.prototype.init_scope_vars.apply(this, arguments);
17750 this.uses_arguments = false;
17751 this.def_variable(new AST_SymbolVar({
17752 name: "arguments",
17753 start: this.start,
17754 end: this.end
17755 }));
17756});
17757
17758AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
17759 var def = this.definition();
17760 var s = this.scope;
17761 while (s) {
17762 push_uniq(s.enclosed, def);
17763 if (options.keep_fnames) {
17764 s.functions.each(function(d) {
17765 push_uniq(def.scope.enclosed, d);
17766 });
17767 }
17768 if (s === def.scope) break;
17769 s = s.parent_scope;
17770 }
17771});
17772
17773AST_Symbol.DEFMETHOD("reference", function(options) {
17774 this.definition().references.push(this);
17775 this.mark_enclosed(options);
17776});
17777
17778AST_Scope.DEFMETHOD("find_variable", function(name){
17779 if (name instanceof AST_Symbol) name = name.name;
17780 return this.variables.get(name)
17781 || (this.parent_scope && this.parent_scope.find_variable(name));
17782});
17783
17784AST_Scope.DEFMETHOD("def_function", function(symbol){
17785 this.functions.set(symbol.name, this.def_variable(symbol));
17786});
17787
17788AST_Scope.DEFMETHOD("def_variable", function(symbol){
17789 var def;
17790 if (!this.variables.has(symbol.name)) {
17791 def = new SymbolDef(this, this.variables.size(), symbol);
17792 this.variables.set(symbol.name, def);
17793 def.global = !this.parent_scope;
17794 } else {
17795 def = this.variables.get(symbol.name);
17796 def.orig.push(symbol);
17797 }
17798 return symbol.thedef = def;
17799});
17800
17801AST_Scope.DEFMETHOD("next_mangled", function(options){
17802 var ext = this.enclosed;
17803 out: while (true) {
17804 var m = base54(++this.cname);
17805 if (!is_identifier(m)) continue; // skip over "do"
17806
17807 // https://github.com/mishoo/UglifyJS2/issues/242 -- do not
17808 // shadow a name excepted from mangling.
17809 if (options.except.indexOf(m) >= 0) continue;
17810
17811 // we must ensure that the mangled name does not shadow a name
17812 // from some parent scope that is referenced in this or in
17813 // inner scopes.
17814 for (var i = ext.length; --i >= 0;) {
17815 var sym = ext[i];
17816 var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
17817 if (m == name) continue out;
17818 }
17819 return m;
17820 }
17821});
17822
17823AST_Function.DEFMETHOD("next_mangled", function(options, def){
17824 // #179, #326
17825 // in Safari strict mode, something like (function x(x){...}) is a syntax error;
17826 // a function expression's argument cannot shadow the function expression's name
17827
17828 var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
17829
17830 // the function's mangled_name is null when keep_fnames is true
17831 var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null;
17832
17833 while (true) {
17834 var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
17835 if (!tricky_name || tricky_name != name)
17836 return name;
17837 }
17838});
17839
17840AST_Symbol.DEFMETHOD("unmangleable", function(options){
17841 return this.definition().unmangleable(options);
17842});
17843
17844// labels are always mangleable
17845AST_Label.DEFMETHOD("unmangleable", function(){
17846 return false;
17847});
17848
17849AST_Symbol.DEFMETHOD("unreferenced", function(){
17850 return this.definition().references.length == 0
17851 && !(this.scope.uses_eval || this.scope.uses_with);
17852});
17853
17854AST_Symbol.DEFMETHOD("undeclared", function(){
17855 return this.definition().undeclared;
17856});
17857
17858AST_LabelRef.DEFMETHOD("undeclared", function(){
17859 return false;
17860});
17861
17862AST_Label.DEFMETHOD("undeclared", function(){
17863 return false;
17864});
17865
17866AST_Symbol.DEFMETHOD("definition", function(){
17867 return this.thedef;
17868});
17869
17870AST_Symbol.DEFMETHOD("global", function(){
17871 return this.definition().global;
17872});
17873
17874AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
17875 return defaults(options, {
17876 eval : false,
17877 except : [],
17878 keep_fnames : false,
17879 screw_ie8 : true,
17880 sort : false, // Ignored. Flag retained for backwards compatibility.
17881 toplevel : false,
17882 });
17883});
17884
17885AST_Toplevel.DEFMETHOD("mangle_names", function(options){
17886 options = this._default_mangler_options(options);
17887
17888 // Never mangle arguments
17889 options.except.push('arguments');
17890
17891 // We only need to mangle declaration nodes. Special logic wired
17892 // into the code generator will display the mangled name if it's
17893 // present (and for AST_SymbolRef-s it'll use the mangled name of
17894 // the AST_SymbolDeclaration that it points to).
17895 var lname = -1;
17896 var to_mangle = [];
17897
17898 if (options.cache) {
17899 this.globals.each(function(symbol){
17900 if (options.except.indexOf(symbol.name) < 0) {
17901 to_mangle.push(symbol);
17902 }
17903 });
17904 }
17905
17906 var tw = new TreeWalker(function(node, descend){
17907 if (node instanceof AST_LabeledStatement) {
17908 // lname is incremented when we get to the AST_Label
17909 var save_nesting = lname;
17910 descend();
17911 lname = save_nesting;
17912 return true; // don't descend again in TreeWalker
17913 }
17914 if (node instanceof AST_Scope) {
17915 var p = tw.parent(), a = [];
17916 node.variables.each(function(symbol){
17917 if (options.except.indexOf(symbol.name) < 0) {
17918 a.push(symbol);
17919 }
17920 });
17921 to_mangle.push.apply(to_mangle, a);
17922 return;
17923 }
17924 if (node instanceof AST_Label) {
17925 var name;
17926 do name = base54(++lname); while (!is_identifier(name));
17927 node.mangled_name = name;
17928 return true;
17929 }
17930 if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
17931 to_mangle.push(node.definition());
17932 return;
17933 }
17934 });
17935 this.walk(tw);
17936 to_mangle.forEach(function(def){ def.mangle(options) });
17937
17938 if (options.cache) {
17939 options.cache.cname = this.cname;
17940 }
17941});
17942
17943AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
17944 options = this._default_mangler_options(options);
17945 var tw = new TreeWalker(function(node){
17946 if (node instanceof AST_Constant)
17947 base54.consider(node.print_to_string());
17948 else if (node instanceof AST_Return)
17949 base54.consider("return");
17950 else if (node instanceof AST_Throw)
17951 base54.consider("throw");
17952 else if (node instanceof AST_Continue)
17953 base54.consider("continue");
17954 else if (node instanceof AST_Break)
17955 base54.consider("break");
17956 else if (node instanceof AST_Debugger)
17957 base54.consider("debugger");
17958 else if (node instanceof AST_Directive)
17959 base54.consider(node.value);
17960 else if (node instanceof AST_While)
17961 base54.consider("while");
17962 else if (node instanceof AST_Do)
17963 base54.consider("do while");
17964 else if (node instanceof AST_If) {
17965 base54.consider("if");
17966 if (node.alternative) base54.consider("else");
17967 }
17968 else if (node instanceof AST_Var)
17969 base54.consider("var");
17970 else if (node instanceof AST_Const)
17971 base54.consider("const");
17972 else if (node instanceof AST_Lambda)
17973 base54.consider("function");
17974 else if (node instanceof AST_For)
17975 base54.consider("for");
17976 else if (node instanceof AST_ForIn)
17977 base54.consider("for in");
17978 else if (node instanceof AST_Switch)
17979 base54.consider("switch");
17980 else if (node instanceof AST_Case)
17981 base54.consider("case");
17982 else if (node instanceof AST_Default)
17983 base54.consider("default");
17984 else if (node instanceof AST_With)
17985 base54.consider("with");
17986 else if (node instanceof AST_ObjectSetter)
17987 base54.consider("set" + node.key);
17988 else if (node instanceof AST_ObjectGetter)
17989 base54.consider("get" + node.key);
17990 else if (node instanceof AST_ObjectKeyVal)
17991 base54.consider(node.key);
17992 else if (node instanceof AST_New)
17993 base54.consider("new");
17994 else if (node instanceof AST_This)
17995 base54.consider("this");
17996 else if (node instanceof AST_Try)
17997 base54.consider("try");
17998 else if (node instanceof AST_Catch)
17999 base54.consider("catch");
18000 else if (node instanceof AST_Finally)
18001 base54.consider("finally");
18002 else if (node instanceof AST_Symbol && node.unmangleable(options))
18003 base54.consider(node.name);
18004 else if (node instanceof AST_Unary || node instanceof AST_Binary)
18005 base54.consider(node.operator);
18006 else if (node instanceof AST_Dot)
18007 base54.consider(node.property);
18008 });
18009 this.walk(tw);
18010 base54.sort();
18011});
18012
18013var base54 = (function() {
18014 var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
18015 var chars, frequency;
18016 function reset() {
18017 frequency = Object.create(null);
18018 chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
18019 chars.forEach(function(ch){ frequency[ch] = 0 });
18020 }
18021 base54.consider = function(str){
18022 for (var i = str.length; --i >= 0;) {
18023 var code = str.charCodeAt(i);
18024 if (code in frequency) ++frequency[code];
18025 }
18026 };
18027 base54.sort = function() {
18028 chars = mergeSort(chars, function(a, b){
18029 if (is_digit(a) && !is_digit(b)) return 1;
18030 if (is_digit(b) && !is_digit(a)) return -1;
18031 return frequency[b] - frequency[a];
18032 });
18033 };
18034 base54.reset = reset;
18035 reset();
18036 base54.get = function(){ return chars };
18037 base54.freq = function(){ return frequency };
18038 function base54(num) {
18039 var ret = "", base = 54;
18040 num++;
18041 do {
18042 num--;
18043 ret += String.fromCharCode(chars[num % base]);
18044 num = Math.floor(num / base);
18045 base = 64;
18046 } while (num > 0);
18047 return ret;
18048 };
18049 return base54;
18050})();
18051
18052AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
18053 options = defaults(options, {
18054 assign_to_global : true,
18055 eval : true,
18056 func_arguments : true,
18057 nested_defuns : true,
18058 undeclared : false, // this makes a lot of noise
18059 unreferenced : true,
18060 });
18061 var tw = new TreeWalker(function(node){
18062 if (options.undeclared
18063 && node instanceof AST_SymbolRef
18064 && node.undeclared())
18065 {
18066 // XXX: this also warns about JS standard names,
18067 // i.e. Object, Array, parseInt etc. Should add a list of
18068 // exceptions.
18069 AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
18070 name: node.name,
18071 file: node.start.file,
18072 line: node.start.line,
18073 col: node.start.col
18074 });
18075 }
18076 if (options.assign_to_global)
18077 {
18078 var sym = null;
18079 if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
18080 sym = node.left;
18081 else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
18082 sym = node.init;
18083 if (sym
18084 && (sym.undeclared()
18085 || (sym.global() && sym.scope !== sym.definition().scope))) {
18086 AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
18087 msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
18088 name: sym.name,
18089 file: sym.start.file,
18090 line: sym.start.line,
18091 col: sym.start.col
18092 });
18093 }
18094 }
18095 if (options.eval
18096 && node instanceof AST_SymbolRef
18097 && node.undeclared()
18098 && node.name == "eval") {
18099 AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
18100 }
18101 if (options.unreferenced
18102 && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
18103 && !(node instanceof AST_SymbolCatch)
18104 && node.unreferenced()) {
18105 AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
18106 type: node instanceof AST_Label ? "Label" : "Symbol",
18107 name: node.name,
18108 file: node.start.file,
18109 line: node.start.line,
18110 col: node.start.col
18111 });
18112 }
18113 if (options.func_arguments
18114 && node instanceof AST_Lambda
18115 && node.uses_arguments) {
18116 AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
18117 name: node.name ? node.name.name : "anonymous",
18118 file: node.start.file,
18119 line: node.start.line,
18120 col: node.start.col
18121 });
18122 }
18123 if (options.nested_defuns
18124 && node instanceof AST_Defun
18125 && !(tw.parent() instanceof AST_Scope)) {
18126 AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
18127 name: node.name.name,
18128 type: tw.parent().TYPE,
18129 file: node.start.file,
18130 line: node.start.line,
18131 col: node.start.col
18132 });
18133 }
18134 });
18135 this.walk(tw);
18136});
18137
18138/***********************************************************************
18139
18140 A JavaScript tokenizer / parser / beautifier / compressor.
18141 https://github.com/mishoo/UglifyJS2
18142
18143 -------------------------------- (C) ---------------------------------
18144
18145 Author: Mihai Bazon
18146 <mihai.bazon@gmail.com>
18147 http://mihai.bazon.net/blog
18148
18149 Distributed under the BSD license:
18150
18151 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
18152
18153 Redistribution and use in source and binary forms, with or without
18154 modification, are permitted provided that the following conditions
18155 are met:
18156
18157 * Redistributions of source code must retain the above
18158 copyright notice, this list of conditions and the following
18159 disclaimer.
18160
18161 * Redistributions in binary form must reproduce the above
18162 copyright notice, this list of conditions and the following
18163 disclaimer in the documentation and/or other materials
18164 provided with the distribution.
18165
18166 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
18167 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18168 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18169 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
18170 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
18171 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
18172 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18173 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
18174 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
18175 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
18176 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
18177 SUCH DAMAGE.
18178
18179 ***********************************************************************/
18180
18181"use strict";
18182
18183var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
18184
18185function is_some_comments(comment) {
18186 // multiline comment
18187 return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value);
18188}
18189
18190function OutputStream(options) {
18191
18192 options = defaults(options, {
18193 ascii_only : false,
18194 beautify : false,
18195 bracketize : false,
18196 comments : false,
18197 indent_level : 4,
18198 indent_start : 0,
18199 inline_script : true,
18200 keep_quoted_props: false,
18201 max_line_len : false,
18202 preamble : null,
18203 preserve_line : false,
18204 quote_keys : false,
18205 quote_style : 0,
18206 screw_ie8 : true,
18207 semicolons : true,
18208 shebang : true,
18209 source_map : null,
18210 space_colon : true,
18211 unescape_regexps : false,
18212 width : 80,
18213 wrap_iife : false,
18214 }, true);
18215
18216 // Convert comment option to RegExp if neccessary and set up comments filter
18217 var comment_filter = return_false; // Default case, throw all comments away
18218 if (options.comments) {
18219 var comments = options.comments;
18220 if (typeof options.comments === "string" && /^\/.*\/[a-zA-Z]*$/.test(options.comments)) {
18221 var regex_pos = options.comments.lastIndexOf("/");
18222 comments = new RegExp(
18223 options.comments.substr(1, regex_pos - 1),
18224 options.comments.substr(regex_pos + 1)
18225 );
18226 }
18227 if (comments instanceof RegExp) {
18228 comment_filter = function(comment) {
18229 return comment.type != "comment5" && comments.test(comment.value);
18230 };
18231 }
18232 else if (typeof comments === "function") {
18233 comment_filter = function(comment) {
18234 return comment.type != "comment5" && comments(this, comment);
18235 };
18236 }
18237 else if (comments === "some") {
18238 comment_filter = is_some_comments;
18239 } else { // NOTE includes "all" option
18240 comment_filter = return_true;
18241 }
18242 }
18243
18244 var indentation = 0;
18245 var current_col = 0;
18246 var current_line = 1;
18247 var current_pos = 0;
18248 var OUTPUT = "";
18249
18250 function to_ascii(str, identifier) {
18251 return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
18252 var code = ch.charCodeAt(0).toString(16);
18253 if (code.length <= 2 && !identifier) {
18254 while (code.length < 2) code = "0" + code;
18255 return "\\x" + code;
18256 } else {
18257 while (code.length < 4) code = "0" + code;
18258 return "\\u" + code;
18259 }
18260 });
18261 };
18262
18263 function make_string(str, quote) {
18264 var dq = 0, sq = 0;
18265 str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g,
18266 function(s, i){
18267 switch (s) {
18268 case '"': ++dq; return '"';
18269 case "'": ++sq; return "'";
18270 case "\\": return "\\\\";
18271 case "\n": return "\\n";
18272 case "\r": return "\\r";
18273 case "\t": return "\\t";
18274 case "\b": return "\\b";
18275 case "\f": return "\\f";
18276 case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B";
18277 case "\u2028": return "\\u2028";
18278 case "\u2029": return "\\u2029";
18279 case "\ufeff": return "\\ufeff";
18280 case "\0":
18281 return /[0-7]/.test(str.charAt(i+1)) ? "\\x00" : "\\0";
18282 }
18283 return s;
18284 });
18285 function quote_single() {
18286 return "'" + str.replace(/\x27/g, "\\'") + "'";
18287 }
18288 function quote_double() {
18289 return '"' + str.replace(/\x22/g, '\\"') + '"';
18290 }
18291 if (options.ascii_only) str = to_ascii(str);
18292 switch (options.quote_style) {
18293 case 1:
18294 return quote_single();
18295 case 2:
18296 return quote_double();
18297 case 3:
18298 return quote == "'" ? quote_single() : quote_double();
18299 default:
18300 return dq > sq ? quote_single() : quote_double();
18301 }
18302 };
18303
18304 function encode_string(str, quote) {
18305 var ret = make_string(str, quote);
18306 if (options.inline_script) {
18307 ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
18308 ret = ret.replace(/\x3c!--/g, "\\x3c!--");
18309 ret = ret.replace(/--\x3e/g, "--\\x3e");
18310 }
18311 return ret;
18312 };
18313
18314 function make_name(name) {
18315 name = name.toString();
18316 if (options.ascii_only)
18317 name = to_ascii(name, true);
18318 return name;
18319 };
18320
18321 function make_indent(back) {
18322 return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
18323 };
18324
18325 /* -----[ beautification/minification ]----- */
18326
18327 var might_need_space = false;
18328 var might_need_semicolon = false;
18329 var might_add_newline = 0;
18330 var last = "";
18331
18332 var ensure_line_len = options.max_line_len ? function() {
18333 if (current_col > options.max_line_len) {
18334 if (might_add_newline) {
18335 var left = OUTPUT.slice(0, might_add_newline);
18336 var right = OUTPUT.slice(might_add_newline);
18337 OUTPUT = left + "\n" + right;
18338 current_line++;
18339 current_pos++;
18340 current_col = right.length;
18341 }
18342 if (current_col > options.max_line_len) {
18343 AST_Node.warn("Output exceeds {max_line_len} characters", options);
18344 }
18345 }
18346 might_add_newline = 0;
18347 } : noop;
18348
18349 var requireSemicolonChars = makePredicate("( [ + * / - , .");
18350
18351 function print(str) {
18352 str = String(str);
18353 var ch = str.charAt(0);
18354 var prev = last.charAt(last.length - 1);
18355 if (might_need_semicolon) {
18356 might_need_semicolon = false;
18357
18358 if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
18359 if (options.semicolons || requireSemicolonChars(ch)) {
18360 OUTPUT += ";";
18361 current_col++;
18362 current_pos++;
18363 } else {
18364 ensure_line_len();
18365 OUTPUT += "\n";
18366 current_pos++;
18367 current_line++;
18368 current_col = 0;
18369
18370 if (/^\s+$/.test(str)) {
18371 // reset the semicolon flag, since we didn't print one
18372 // now and might still have to later
18373 might_need_semicolon = true;
18374 }
18375 }
18376
18377 if (!options.beautify)
18378 might_need_space = false;
18379 }
18380 }
18381
18382 if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
18383 var target_line = stack[stack.length - 1].start.line;
18384 while (current_line < target_line) {
18385 ensure_line_len();
18386 OUTPUT += "\n";
18387 current_pos++;
18388 current_line++;
18389 current_col = 0;
18390 might_need_space = false;
18391 }
18392 }
18393
18394 if (might_need_space) {
18395 if ((is_identifier_char(prev)
18396 && (is_identifier_char(ch) || ch == "\\"))
18397 || (ch == "/" && ch == prev)
18398 || ((ch == "+" || ch == "-") && ch == last))
18399 {
18400 OUTPUT += " ";
18401 current_col++;
18402 current_pos++;
18403 }
18404 might_need_space = false;
18405 }
18406 OUTPUT += str;
18407 current_pos += str.length;
18408 var a = str.split(/\r?\n/), n = a.length - 1;
18409 current_line += n;
18410 current_col += a[0].length;
18411 if (n > 0) {
18412 ensure_line_len();
18413 current_col = a[n].length;
18414 }
18415 last = str;
18416 };
18417
18418 var space = options.beautify ? function() {
18419 print(" ");
18420 } : function() {
18421 might_need_space = true;
18422 };
18423
18424 var indent = options.beautify ? function(half) {
18425 if (options.beautify) {
18426 print(make_indent(half ? 0.5 : 0));
18427 }
18428 } : noop;
18429
18430 var with_indent = options.beautify ? function(col, cont) {
18431 if (col === true) col = next_indent();
18432 var save_indentation = indentation;
18433 indentation = col;
18434 var ret = cont();
18435 indentation = save_indentation;
18436 return ret;
18437 } : function(col, cont) { return cont() };
18438
18439 var newline = options.beautify ? function() {
18440 print("\n");
18441 } : options.max_line_len ? function() {
18442 ensure_line_len();
18443 might_add_newline = OUTPUT.length;
18444 } : noop;
18445
18446 var semicolon = options.beautify ? function() {
18447 print(";");
18448 } : function() {
18449 might_need_semicolon = true;
18450 };
18451
18452 function force_semicolon() {
18453 might_need_semicolon = false;
18454 print(";");
18455 };
18456
18457 function next_indent() {
18458 return indentation + options.indent_level;
18459 };
18460
18461 function with_block(cont) {
18462 var ret;
18463 print("{");
18464 newline();
18465 with_indent(next_indent(), function(){
18466 ret = cont();
18467 });
18468 indent();
18469 print("}");
18470 return ret;
18471 };
18472
18473 function with_parens(cont) {
18474 print("(");
18475 //XXX: still nice to have that for argument lists
18476 //var ret = with_indent(current_col, cont);
18477 var ret = cont();
18478 print(")");
18479 return ret;
18480 };
18481
18482 function with_square(cont) {
18483 print("[");
18484 //var ret = with_indent(current_col, cont);
18485 var ret = cont();
18486 print("]");
18487 return ret;
18488 };
18489
18490 function comma() {
18491 print(",");
18492 space();
18493 };
18494
18495 function colon() {
18496 print(":");
18497 if (options.space_colon) space();
18498 };
18499
18500 var add_mapping = options.source_map ? function(token, name) {
18501 try {
18502 if (token) options.source_map.add(
18503 token.file || "?",
18504 current_line, current_col,
18505 token.line, token.col,
18506 (!name && token.type == "name") ? token.value : name
18507 );
18508 } catch(ex) {
18509 AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
18510 file: token.file,
18511 line: token.line,
18512 col: token.col,
18513 cline: current_line,
18514 ccol: current_col,
18515 name: name || ""
18516 })
18517 }
18518 } : noop;
18519
18520 function get() {
18521 if (might_add_newline) {
18522 ensure_line_len();
18523 }
18524 return OUTPUT;
18525 };
18526
18527 var stack = [];
18528 return {
18529 get : get,
18530 toString : get,
18531 indent : indent,
18532 indentation : function() { return indentation },
18533 current_width : function() { return current_col - indentation },
18534 should_break : function() { return options.width && this.current_width() >= options.width },
18535 newline : newline,
18536 print : print,
18537 space : space,
18538 comma : comma,
18539 colon : colon,
18540 last : function() { return last },
18541 semicolon : semicolon,
18542 force_semicolon : force_semicolon,
18543 to_ascii : to_ascii,
18544 print_name : function(name) { print(make_name(name)) },
18545 print_string : function(str, quote, escape_directive) {
18546 var encoded = encode_string(str, quote);
18547 if (escape_directive === true && encoded.indexOf("\\") === -1) {
18548 // Insert semicolons to break directive prologue
18549 if (!EXPECT_DIRECTIVE.test(OUTPUT)) {
18550 force_semicolon();
18551 }
18552 force_semicolon();
18553 }
18554 print(encoded);
18555 },
18556 encode_string : encode_string,
18557 next_indent : next_indent,
18558 with_indent : with_indent,
18559 with_block : with_block,
18560 with_parens : with_parens,
18561 with_square : with_square,
18562 add_mapping : add_mapping,
18563 option : function(opt) { return options[opt] },
18564 comment_filter : comment_filter,
18565 line : function() { return current_line },
18566 col : function() { return current_col },
18567 pos : function() { return current_pos },
18568 push_node : function(node) { stack.push(node) },
18569 pop_node : function() { return stack.pop() },
18570 parent : function(n) {
18571 return stack[stack.length - 2 - (n || 0)];
18572 }
18573 };
18574
18575};
18576
18577/* -----[ code generators ]----- */
18578
18579(function(){
18580
18581 /* -----[ utils ]----- */
18582
18583 function DEFPRINT(nodetype, generator) {
18584 nodetype.DEFMETHOD("_codegen", generator);
18585 };
18586
18587 var use_asm = false;
18588 var in_directive = false;
18589
18590 AST_Node.DEFMETHOD("print", function(stream, force_parens){
18591 var self = this, generator = self._codegen, prev_use_asm = use_asm;
18592 if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) {
18593 use_asm = true;
18594 }
18595 function doit() {
18596 self.add_comments(stream);
18597 self.add_source_map(stream);
18598 generator(self, stream);
18599 }
18600 stream.push_node(self);
18601 if (force_parens || self.needs_parens(stream)) {
18602 stream.with_parens(doit);
18603 } else {
18604 doit();
18605 }
18606 stream.pop_node();
18607 if (self instanceof AST_Scope) {
18608 use_asm = prev_use_asm;
18609 }
18610 });
18611
18612 AST_Node.DEFMETHOD("print_to_string", function(options){
18613 var s = OutputStream(options);
18614 if (!options) s._readonly = true;
18615 this.print(s);
18616 return s.get();
18617 });
18618
18619 /* -----[ comments ]----- */
18620
18621 AST_Node.DEFMETHOD("add_comments", function(output){
18622 if (output._readonly) return;
18623 var self = this;
18624 var start = self.start;
18625 if (start && !start._comments_dumped) {
18626 start._comments_dumped = true;
18627 var comments = start.comments_before || [];
18628
18629 // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
18630 // and https://github.com/mishoo/UglifyJS2/issues/372
18631 if (self instanceof AST_Exit && self.value) {
18632 self.value.walk(new TreeWalker(function(node){
18633 if (node.start && node.start.comments_before) {
18634 comments = comments.concat(node.start.comments_before);
18635 node.start.comments_before = [];
18636 }
18637 if (node instanceof AST_Function ||
18638 node instanceof AST_Array ||
18639 node instanceof AST_Object)
18640 {
18641 return true; // don't go inside.
18642 }
18643 }));
18644 }
18645
18646 if (output.pos() == 0) {
18647 if (comments.length > 0 && output.option("shebang") && comments[0].type == "comment5") {
18648 output.print("#!" + comments.shift().value + "\n");
18649 output.indent();
18650 }
18651 var preamble = output.option("preamble");
18652 if (preamble) {
18653 output.print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
18654 }
18655 }
18656
18657 comments = comments.filter(output.comment_filter, self);
18658
18659 // Keep single line comments after nlb, after nlb
18660 if (!output.option("beautify") && comments.length > 0 &&
18661 /comment[134]/.test(comments[0].type) &&
18662 output.col() !== 0 && comments[0].nlb)
18663 {
18664 output.print("\n");
18665 }
18666
18667 comments.forEach(function(c){
18668 if (/comment[134]/.test(c.type)) {
18669 output.print("//" + c.value + "\n");
18670 output.indent();
18671 }
18672 else if (c.type == "comment2") {
18673 output.print("/*" + c.value + "*/");
18674 if (start.nlb) {
18675 output.print("\n");
18676 output.indent();
18677 } else {
18678 output.space();
18679 }
18680 }
18681 });
18682 }
18683 });
18684
18685 /* -----[ PARENTHESES ]----- */
18686
18687 function PARENS(nodetype, func) {
18688 if (Array.isArray(nodetype)) {
18689 nodetype.forEach(function(nodetype){
18690 PARENS(nodetype, func);
18691 });
18692 } else {
18693 nodetype.DEFMETHOD("needs_parens", func);
18694 }
18695 };
18696
18697 PARENS(AST_Node, function(){
18698 return false;
18699 });
18700
18701 // a function expression needs parens around it when it's provably
18702 // the first token to appear in a statement.
18703 PARENS(AST_Function, function(output){
18704 if (first_in_statement(output)) {
18705 return true;
18706 }
18707
18708 if (output.option('wrap_iife')) {
18709 var p = output.parent();
18710 return p instanceof AST_Call && p.expression === this;
18711 }
18712
18713 return false;
18714 });
18715
18716 // same goes for an object literal, because otherwise it would be
18717 // interpreted as a block of code.
18718 PARENS(AST_Object, function(output){
18719 return first_in_statement(output);
18720 });
18721
18722 PARENS(AST_Unary, function(output){
18723 var p = output.parent();
18724 return p instanceof AST_PropAccess && p.expression === this
18725 || p instanceof AST_Call && p.expression === this;
18726 });
18727
18728 PARENS(AST_Seq, function(output){
18729 var p = output.parent();
18730 return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
18731 || p instanceof AST_Unary // !(foo, bar, baz)
18732 || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
18733 || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
18734 || p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
18735 || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
18736 || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
18737 || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
18738 * ==> 20 (side effect, set a := 10 and b := 20) */
18739 ;
18740 });
18741
18742 PARENS(AST_Binary, function(output){
18743 var p = output.parent();
18744 // (foo && bar)()
18745 if (p instanceof AST_Call && p.expression === this)
18746 return true;
18747 // typeof (foo && bar)
18748 if (p instanceof AST_Unary)
18749 return true;
18750 // (foo && bar)["prop"], (foo && bar).prop
18751 if (p instanceof AST_PropAccess && p.expression === this)
18752 return true;
18753 // this deals with precedence: 3 * (2 + 1)
18754 if (p instanceof AST_Binary) {
18755 var po = p.operator, pp = PRECEDENCE[po];
18756 var so = this.operator, sp = PRECEDENCE[so];
18757 if (pp > sp
18758 || (pp == sp
18759 && this === p.right)) {
18760 return true;
18761 }
18762 }
18763 });
18764
18765 PARENS(AST_PropAccess, function(output){
18766 var p = output.parent();
18767 if (p instanceof AST_New && p.expression === this) {
18768 // i.e. new (foo.bar().baz)
18769 //
18770 // if there's one call into this subtree, then we need
18771 // parens around it too, otherwise the call will be
18772 // interpreted as passing the arguments to the upper New
18773 // expression.
18774 try {
18775 this.walk(new TreeWalker(function(node){
18776 if (node instanceof AST_Call) throw p;
18777 }));
18778 } catch(ex) {
18779 if (ex !== p) throw ex;
18780 return true;
18781 }
18782 }
18783 });
18784
18785 PARENS(AST_Call, function(output){
18786 var p = output.parent(), p1;
18787 if (p instanceof AST_New && p.expression === this)
18788 return true;
18789
18790 // workaround for Safari bug.
18791 // https://bugs.webkit.org/show_bug.cgi?id=123506
18792 return this.expression instanceof AST_Function
18793 && p instanceof AST_PropAccess
18794 && p.expression === this
18795 && (p1 = output.parent(1)) instanceof AST_Assign
18796 && p1.left === p;
18797 });
18798
18799 PARENS(AST_New, function(output){
18800 var p = output.parent();
18801 if (!need_constructor_parens(this, output)
18802 && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
18803 || p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
18804 return true;
18805 });
18806
18807 PARENS(AST_Number, function(output){
18808 var p = output.parent();
18809 if (p instanceof AST_PropAccess && p.expression === this) {
18810 var value = this.getValue();
18811 if (value < 0 || /^0/.test(make_num(value))) {
18812 return true;
18813 }
18814 }
18815 });
18816
18817 PARENS([ AST_Assign, AST_Conditional ], function (output){
18818 var p = output.parent();
18819 // !(a = false) → true
18820 if (p instanceof AST_Unary)
18821 return true;
18822 // 1 + (a = 2) + 3 → 6, side effect setting a = 2
18823 if (p instanceof AST_Binary && !(p instanceof AST_Assign))
18824 return true;
18825 // (a = func)() —or— new (a = Object)()
18826 if (p instanceof AST_Call && p.expression === this)
18827 return true;
18828 // (a = foo) ? bar : baz
18829 if (p instanceof AST_Conditional && p.condition === this)
18830 return true;
18831 // (a = foo)["prop"] —or— (a = foo).prop
18832 if (p instanceof AST_PropAccess && p.expression === this)
18833 return true;
18834 });
18835
18836 /* -----[ PRINTERS ]----- */
18837
18838 DEFPRINT(AST_Directive, function(self, output){
18839 output.print_string(self.value, self.quote);
18840 output.semicolon();
18841 });
18842 DEFPRINT(AST_Debugger, function(self, output){
18843 output.print("debugger");
18844 output.semicolon();
18845 });
18846
18847 /* -----[ statements ]----- */
18848
18849 function display_body(body, is_toplevel, output, allow_directives) {
18850 var last = body.length - 1;
18851 in_directive = allow_directives;
18852 body.forEach(function(stmt, i){
18853 if (in_directive === true && !(stmt instanceof AST_Directive ||
18854 stmt instanceof AST_EmptyStatement ||
18855 (stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String)
18856 )) {
18857 in_directive = false;
18858 }
18859 if (!(stmt instanceof AST_EmptyStatement)) {
18860 output.indent();
18861 stmt.print(output);
18862 if (!(i == last && is_toplevel)) {
18863 output.newline();
18864 if (is_toplevel) output.newline();
18865 }
18866 }
18867 if (in_directive === true &&
18868 stmt instanceof AST_SimpleStatement &&
18869 stmt.body instanceof AST_String
18870 ) {
18871 in_directive = false;
18872 }
18873 });
18874 in_directive = false;
18875 };
18876
18877 AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){
18878 force_statement(this.body, output);
18879 });
18880
18881 DEFPRINT(AST_Statement, function(self, output){
18882 self.body.print(output);
18883 output.semicolon();
18884 });
18885 DEFPRINT(AST_Toplevel, function(self, output){
18886 display_body(self.body, true, output, true);
18887 output.print("");
18888 });
18889 DEFPRINT(AST_LabeledStatement, function(self, output){
18890 self.label.print(output);
18891 output.colon();
18892 self.body.print(output);
18893 });
18894 DEFPRINT(AST_SimpleStatement, function(self, output){
18895 self.body.print(output);
18896 output.semicolon();
18897 });
18898 function print_bracketed(body, output, allow_directives) {
18899 if (body.length > 0) output.with_block(function(){
18900 display_body(body, false, output, allow_directives);
18901 });
18902 else output.print("{}");
18903 };
18904 DEFPRINT(AST_BlockStatement, function(self, output){
18905 print_bracketed(self.body, output);
18906 });
18907 DEFPRINT(AST_EmptyStatement, function(self, output){
18908 output.semicolon();
18909 });
18910 DEFPRINT(AST_Do, function(self, output){
18911 output.print("do");
18912 output.space();
18913 make_block(self.body, output);
18914 output.space();
18915 output.print("while");
18916 output.space();
18917 output.with_parens(function(){
18918 self.condition.print(output);
18919 });
18920 output.semicolon();
18921 });
18922 DEFPRINT(AST_While, function(self, output){
18923 output.print("while");
18924 output.space();
18925 output.with_parens(function(){
18926 self.condition.print(output);
18927 });
18928 output.space();
18929 self._do_print_body(output);
18930 });
18931 DEFPRINT(AST_For, function(self, output){
18932 output.print("for");
18933 output.space();
18934 output.with_parens(function(){
18935 if (self.init) {
18936 if (self.init instanceof AST_Definitions) {
18937 self.init.print(output);
18938 } else {
18939 parenthesize_for_noin(self.init, output, true);
18940 }
18941 output.print(";");
18942 output.space();
18943 } else {
18944 output.print(";");
18945 }
18946 if (self.condition) {
18947 self.condition.print(output);
18948 output.print(";");
18949 output.space();
18950 } else {
18951 output.print(";");
18952 }
18953 if (self.step) {
18954 self.step.print(output);
18955 }
18956 });
18957 output.space();
18958 self._do_print_body(output);
18959 });
18960 DEFPRINT(AST_ForIn, function(self, output){
18961 output.print("for");
18962 output.space();
18963 output.with_parens(function(){
18964 self.init.print(output);
18965 output.space();
18966 output.print("in");
18967 output.space();
18968 self.object.print(output);
18969 });
18970 output.space();
18971 self._do_print_body(output);
18972 });
18973 DEFPRINT(AST_With, function(self, output){
18974 output.print("with");
18975 output.space();
18976 output.with_parens(function(){
18977 self.expression.print(output);
18978 });
18979 output.space();
18980 self._do_print_body(output);
18981 });
18982
18983 /* -----[ functions ]----- */
18984 AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
18985 var self = this;
18986 if (!nokeyword) {
18987 output.print("function");
18988 }
18989 if (self.name) {
18990 output.space();
18991 self.name.print(output);
18992 }
18993 output.with_parens(function(){
18994 self.argnames.forEach(function(arg, i){
18995 if (i) output.comma();
18996 arg.print(output);
18997 });
18998 });
18999 output.space();
19000 print_bracketed(self.body, output, true);
19001 });
19002 DEFPRINT(AST_Lambda, function(self, output){
19003 self._do_print(output);
19004 });
19005
19006 /* -----[ exits ]----- */
19007 AST_Exit.DEFMETHOD("_do_print", function(output, kind){
19008 output.print(kind);
19009 if (this.value) {
19010 output.space();
19011 this.value.print(output);
19012 }
19013 output.semicolon();
19014 });
19015 DEFPRINT(AST_Return, function(self, output){
19016 self._do_print(output, "return");
19017 });
19018 DEFPRINT(AST_Throw, function(self, output){
19019 self._do_print(output, "throw");
19020 });
19021
19022 /* -----[ loop control ]----- */
19023 AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
19024 output.print(kind);
19025 if (this.label) {
19026 output.space();
19027 this.label.print(output);
19028 }
19029 output.semicolon();
19030 });
19031 DEFPRINT(AST_Break, function(self, output){
19032 self._do_print(output, "break");
19033 });
19034 DEFPRINT(AST_Continue, function(self, output){
19035 self._do_print(output, "continue");
19036 });
19037
19038 /* -----[ if ]----- */
19039 function make_then(self, output) {
19040 var b = self.body;
19041 if (output.option("bracketize")
19042 || !output.option("screw_ie8") && b instanceof AST_Do)
19043 return make_block(b, output);
19044 // The squeezer replaces "block"-s that contain only a single
19045 // statement with the statement itself; technically, the AST
19046 // is correct, but this can create problems when we output an
19047 // IF having an ELSE clause where the THEN clause ends in an
19048 // IF *without* an ELSE block (then the outer ELSE would refer
19049 // to the inner IF). This function checks for this case and
19050 // adds the block brackets if needed.
19051 if (!b) return output.force_semicolon();
19052 while (true) {
19053 if (b instanceof AST_If) {
19054 if (!b.alternative) {
19055 make_block(self.body, output);
19056 return;
19057 }
19058 b = b.alternative;
19059 }
19060 else if (b instanceof AST_StatementWithBody) {
19061 b = b.body;
19062 }
19063 else break;
19064 }
19065 force_statement(self.body, output);
19066 };
19067 DEFPRINT(AST_If, function(self, output){
19068 output.print("if");
19069 output.space();
19070 output.with_parens(function(){
19071 self.condition.print(output);
19072 });
19073 output.space();
19074 if (self.alternative) {
19075 make_then(self, output);
19076 output.space();
19077 output.print("else");
19078 output.space();
19079 if (self.alternative instanceof AST_If)
19080 self.alternative.print(output);
19081 else
19082 force_statement(self.alternative, output);
19083 } else {
19084 self._do_print_body(output);
19085 }
19086 });
19087
19088 /* -----[ switch ]----- */
19089 DEFPRINT(AST_Switch, function(self, output){
19090 output.print("switch");
19091 output.space();
19092 output.with_parens(function(){
19093 self.expression.print(output);
19094 });
19095 output.space();
19096 var last = self.body.length - 1;
19097 if (last < 0) output.print("{}");
19098 else output.with_block(function(){
19099 self.body.forEach(function(branch, i){
19100 output.indent(true);
19101 branch.print(output);
19102 if (i < last && branch.body.length > 0)
19103 output.newline();
19104 });
19105 });
19106 });
19107 AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){
19108 output.newline();
19109 this.body.forEach(function(stmt){
19110 output.indent();
19111 stmt.print(output);
19112 output.newline();
19113 });
19114 });
19115 DEFPRINT(AST_Default, function(self, output){
19116 output.print("default:");
19117 self._do_print_body(output);
19118 });
19119 DEFPRINT(AST_Case, function(self, output){
19120 output.print("case");
19121 output.space();
19122 self.expression.print(output);
19123 output.print(":");
19124 self._do_print_body(output);
19125 });
19126
19127 /* -----[ exceptions ]----- */
19128 DEFPRINT(AST_Try, function(self, output){
19129 output.print("try");
19130 output.space();
19131 print_bracketed(self.body, output);
19132 if (self.bcatch) {
19133 output.space();
19134 self.bcatch.print(output);
19135 }
19136 if (self.bfinally) {
19137 output.space();
19138 self.bfinally.print(output);
19139 }
19140 });
19141 DEFPRINT(AST_Catch, function(self, output){
19142 output.print("catch");
19143 output.space();
19144 output.with_parens(function(){
19145 self.argname.print(output);
19146 });
19147 output.space();
19148 print_bracketed(self.body, output);
19149 });
19150 DEFPRINT(AST_Finally, function(self, output){
19151 output.print("finally");
19152 output.space();
19153 print_bracketed(self.body, output);
19154 });
19155
19156 /* -----[ var/const ]----- */
19157 AST_Definitions.DEFMETHOD("_do_print", function(output, kind){
19158 output.print(kind);
19159 output.space();
19160 this.definitions.forEach(function(def, i){
19161 if (i) output.comma();
19162 def.print(output);
19163 });
19164 var p = output.parent();
19165 var in_for = p instanceof AST_For || p instanceof AST_ForIn;
19166 var avoid_semicolon = in_for && p.init === this;
19167 if (!avoid_semicolon)
19168 output.semicolon();
19169 });
19170 DEFPRINT(AST_Var, function(self, output){
19171 self._do_print(output, "var");
19172 });
19173 DEFPRINT(AST_Const, function(self, output){
19174 self._do_print(output, "const");
19175 });
19176
19177 function parenthesize_for_noin(node, output, noin) {
19178 if (!noin) node.print(output);
19179 else try {
19180 // need to take some precautions here:
19181 // https://github.com/mishoo/UglifyJS2/issues/60
19182 node.walk(new TreeWalker(function(node){
19183 if (node instanceof AST_Binary && node.operator == "in")
19184 throw output;
19185 }));
19186 node.print(output);
19187 } catch(ex) {
19188 if (ex !== output) throw ex;
19189 node.print(output, true);
19190 }
19191 };
19192
19193 DEFPRINT(AST_VarDef, function(self, output){
19194 self.name.print(output);
19195 if (self.value) {
19196 output.space();
19197 output.print("=");
19198 output.space();
19199 var p = output.parent(1);
19200 var noin = p instanceof AST_For || p instanceof AST_ForIn;
19201 parenthesize_for_noin(self.value, output, noin);
19202 }
19203 });
19204
19205 /* -----[ other expressions ]----- */
19206 DEFPRINT(AST_Call, function(self, output){
19207 self.expression.print(output);
19208 if (self instanceof AST_New && !need_constructor_parens(self, output))
19209 return;
19210 output.with_parens(function(){
19211 self.args.forEach(function(expr, i){
19212 if (i) output.comma();
19213 expr.print(output);
19214 });
19215 });
19216 });
19217 DEFPRINT(AST_New, function(self, output){
19218 output.print("new");
19219 output.space();
19220 AST_Call.prototype._codegen(self, output);
19221 });
19222
19223 AST_Seq.DEFMETHOD("_do_print", function(output){
19224 this.car.print(output);
19225 if (this.cdr) {
19226 output.comma();
19227 if (output.should_break()) {
19228 output.newline();
19229 output.indent();
19230 }
19231 this.cdr.print(output);
19232 }
19233 });
19234 DEFPRINT(AST_Seq, function(self, output){
19235 self._do_print(output);
19236 // var p = output.parent();
19237 // if (p instanceof AST_Statement) {
19238 // output.with_indent(output.next_indent(), function(){
19239 // self._do_print(output);
19240 // });
19241 // } else {
19242 // self._do_print(output);
19243 // }
19244 });
19245 DEFPRINT(AST_Dot, function(self, output){
19246 var expr = self.expression;
19247 expr.print(output);
19248 if (expr instanceof AST_Number && expr.getValue() >= 0) {
19249 if (!/[xa-f.)]/i.test(output.last())) {
19250 output.print(".");
19251 }
19252 }
19253 output.print(".");
19254 // the name after dot would be mapped about here.
19255 output.add_mapping(self.end);
19256 output.print_name(self.property);
19257 });
19258 DEFPRINT(AST_Sub, function(self, output){
19259 self.expression.print(output);
19260 output.print("[");
19261 self.property.print(output);
19262 output.print("]");
19263 });
19264 DEFPRINT(AST_UnaryPrefix, function(self, output){
19265 var op = self.operator;
19266 output.print(op);
19267 if (/^[a-z]/i.test(op)
19268 || (/[+-]$/.test(op)
19269 && self.expression instanceof AST_UnaryPrefix
19270 && /^[+-]/.test(self.expression.operator))) {
19271 output.space();
19272 }
19273 self.expression.print(output);
19274 });
19275 DEFPRINT(AST_UnaryPostfix, function(self, output){
19276 self.expression.print(output);
19277 output.print(self.operator);
19278 });
19279 DEFPRINT(AST_Binary, function(self, output){
19280 var op = self.operator;
19281 self.left.print(output);
19282 if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
19283 && self.left instanceof AST_UnaryPostfix
19284 && self.left.operator == "--") {
19285 // space is mandatory to avoid outputting -->
19286 output.print(" ");
19287 } else {
19288 // the space is optional depending on "beautify"
19289 output.space();
19290 }
19291 output.print(op);
19292 if ((op == "<" || op == "<<")
19293 && self.right instanceof AST_UnaryPrefix
19294 && self.right.operator == "!"
19295 && self.right.expression instanceof AST_UnaryPrefix
19296 && self.right.expression.operator == "--") {
19297 // space is mandatory to avoid outputting <!--
19298 output.print(" ");
19299 } else {
19300 // the space is optional depending on "beautify"
19301 output.space();
19302 }
19303 self.right.print(output);
19304 });
19305 DEFPRINT(AST_Conditional, function(self, output){
19306 self.condition.print(output);
19307 output.space();
19308 output.print("?");
19309 output.space();
19310 self.consequent.print(output);
19311 output.space();
19312 output.colon();
19313 self.alternative.print(output);
19314 });
19315
19316 /* -----[ literals ]----- */
19317 DEFPRINT(AST_Array, function(self, output){
19318 output.with_square(function(){
19319 var a = self.elements, len = a.length;
19320 if (len > 0) output.space();
19321 a.forEach(function(exp, i){
19322 if (i) output.comma();
19323 exp.print(output);
19324 // If the final element is a hole, we need to make sure it
19325 // doesn't look like a trailing comma, by inserting an actual
19326 // trailing comma.
19327 if (i === len - 1 && exp instanceof AST_Hole)
19328 output.comma();
19329 });
19330 if (len > 0) output.space();
19331 });
19332 });
19333 DEFPRINT(AST_Object, function(self, output){
19334 if (self.properties.length > 0) output.with_block(function(){
19335 self.properties.forEach(function(prop, i){
19336 if (i) {
19337 output.print(",");
19338 output.newline();
19339 }
19340 output.indent();
19341 prop.print(output);
19342 });
19343 output.newline();
19344 });
19345 else output.print("{}");
19346 });
19347
19348 function print_property_name(key, quote, output) {
19349 if (output.option("quote_keys")) {
19350 output.print_string(key + "");
19351 } else if ((typeof key == "number"
19352 || !output.option("beautify")
19353 && +key + "" == key)
19354 && parseFloat(key) >= 0) {
19355 output.print(make_num(key));
19356 } else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) {
19357 if (quote && output.option("keep_quoted_props")) {
19358 output.print_string(key, quote);
19359 } else {
19360 output.print_name(key);
19361 }
19362 } else {
19363 output.print_string(key, quote);
19364 }
19365 }
19366
19367 DEFPRINT(AST_ObjectKeyVal, function(self, output){
19368 print_property_name(self.key, self.quote, output);
19369 output.colon();
19370 self.value.print(output);
19371 });
19372 AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
19373 output.print(type);
19374 output.space();
19375 print_property_name(this.key.name, this.quote, output);
19376 this.value._do_print(output, true);
19377 });
19378 DEFPRINT(AST_ObjectSetter, function(self, output){
19379 self._print_getter_setter("set", output);
19380 });
19381 DEFPRINT(AST_ObjectGetter, function(self, output){
19382 self._print_getter_setter("get", output);
19383 });
19384 DEFPRINT(AST_Symbol, function(self, output){
19385 var def = self.definition();
19386 output.print_name(def ? def.mangled_name || def.name : self.name);
19387 });
19388 DEFPRINT(AST_Hole, noop);
19389 DEFPRINT(AST_This, function(self, output){
19390 output.print("this");
19391 });
19392 DEFPRINT(AST_Constant, function(self, output){
19393 output.print(self.getValue());
19394 });
19395 DEFPRINT(AST_String, function(self, output){
19396 output.print_string(self.getValue(), self.quote, in_directive);
19397 });
19398 DEFPRINT(AST_Number, function(self, output){
19399 if (use_asm && self.start && self.start.raw != null) {
19400 output.print(self.start.raw);
19401 } else {
19402 output.print(make_num(self.getValue()));
19403 }
19404 });
19405
19406 function regexp_safe_literal(code) {
19407 return [
19408 0x5c , // \
19409 0x2f , // /
19410 0x2e , // .
19411 0x2b , // +
19412 0x2a , // *
19413 0x3f , // ?
19414 0x28 , // (
19415 0x29 , // )
19416 0x5b , // [
19417 0x5d , // ]
19418 0x7b , // {
19419 0x7d , // }
19420 0x24 , // $
19421 0x5e , // ^
19422 0x3a , // :
19423 0x7c , // |
19424 0x21 , // !
19425 0x0a , // \n
19426 0x0d , // \r
19427 0x00 , // \0
19428 0xfeff , // Unicode BOM
19429 0x2028 , // unicode "line separator"
19430 0x2029 , // unicode "paragraph separator"
19431 ].indexOf(code) < 0;
19432 };
19433
19434 DEFPRINT(AST_RegExp, function(self, output){
19435 var str = self.getValue().toString();
19436 if (output.option("ascii_only")) {
19437 str = output.to_ascii(str);
19438 } else if (output.option("unescape_regexps")) {
19439 str = str.split("\\\\").map(function(str){
19440 return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s){
19441 var code = parseInt(s.substr(2), 16);
19442 return regexp_safe_literal(code) ? String.fromCharCode(code) : s;
19443 });
19444 }).join("\\\\");
19445 }
19446 output.print(str);
19447 var p = output.parent();
19448 if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
19449 output.print(" ");
19450 });
19451
19452 function force_statement(stat, output) {
19453 if (output.option("bracketize")) {
19454 make_block(stat, output);
19455 } else {
19456 if (!stat || stat instanceof AST_EmptyStatement)
19457 output.force_semicolon();
19458 else
19459 stat.print(output);
19460 }
19461 };
19462
19463 // self should be AST_New. decide if we want to show parens or not.
19464 function need_constructor_parens(self, output) {
19465 // Always print parentheses with arguments
19466 if (self.args.length > 0) return true;
19467
19468 return output.option("beautify");
19469 };
19470
19471 function best_of(a) {
19472 var best = a[0], len = best.length;
19473 for (var i = 1; i < a.length; ++i) {
19474 if (a[i].length < len) {
19475 best = a[i];
19476 len = best.length;
19477 }
19478 }
19479 return best;
19480 };
19481
19482 function make_num(num) {
19483 var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;
19484 if (Math.floor(num) === num) {
19485 if (num >= 0) {
19486 a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
19487 "0" + num.toString(8)); // same.
19488 } else {
19489 a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
19490 "-0" + (-num).toString(8)); // same.
19491 }
19492 if ((m = /^(.*?)(0+)$/.exec(num))) {
19493 a.push(m[1] + "e" + m[2].length);
19494 }
19495 } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
19496 a.push(m[2] + "e-" + (m[1].length + m[2].length),
19497 str.substr(str.indexOf(".")));
19498 }
19499 return best_of(a);
19500 };
19501
19502 function make_block(stmt, output) {
19503 if (!stmt || stmt instanceof AST_EmptyStatement)
19504 output.print("{}");
19505 else if (stmt instanceof AST_BlockStatement)
19506 stmt.print(output);
19507 else output.with_block(function(){
19508 output.indent();
19509 stmt.print(output);
19510 output.newline();
19511 });
19512 };
19513
19514 /* -----[ source map generators ]----- */
19515
19516 function DEFMAP(nodetype, generator) {
19517 nodetype.DEFMETHOD("add_source_map", function(stream){
19518 generator(this, stream);
19519 });
19520 };
19521
19522 // We could easily add info for ALL nodes, but it seems to me that
19523 // would be quite wasteful, hence this noop in the base class.
19524 DEFMAP(AST_Node, noop);
19525
19526 function basic_sourcemap_gen(self, output) {
19527 output.add_mapping(self.start);
19528 };
19529
19530 // XXX: I'm not exactly sure if we need it for all of these nodes,
19531 // or if we should add even more.
19532
19533 DEFMAP(AST_Directive, basic_sourcemap_gen);
19534 DEFMAP(AST_Debugger, basic_sourcemap_gen);
19535 DEFMAP(AST_Symbol, basic_sourcemap_gen);
19536 DEFMAP(AST_Jump, basic_sourcemap_gen);
19537 DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
19538 DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it
19539 DEFMAP(AST_Lambda, basic_sourcemap_gen);
19540 DEFMAP(AST_Switch, basic_sourcemap_gen);
19541 DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
19542 DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
19543 DEFMAP(AST_Toplevel, noop);
19544 DEFMAP(AST_New, basic_sourcemap_gen);
19545 DEFMAP(AST_Try, basic_sourcemap_gen);
19546 DEFMAP(AST_Catch, basic_sourcemap_gen);
19547 DEFMAP(AST_Finally, basic_sourcemap_gen);
19548 DEFMAP(AST_Definitions, basic_sourcemap_gen);
19549 DEFMAP(AST_Constant, basic_sourcemap_gen);
19550 DEFMAP(AST_ObjectSetter, function(self, output){
19551 output.add_mapping(self.start, self.key.name);
19552 });
19553 DEFMAP(AST_ObjectGetter, function(self, output){
19554 output.add_mapping(self.start, self.key.name);
19555 });
19556 DEFMAP(AST_ObjectProperty, function(self, output){
19557 output.add_mapping(self.start, self.key);
19558 });
19559
19560})();
19561
19562/***********************************************************************
19563
19564 A JavaScript tokenizer / parser / beautifier / compressor.
19565 https://github.com/mishoo/UglifyJS2
19566
19567 -------------------------------- (C) ---------------------------------
19568
19569 Author: Mihai Bazon
19570 <mihai.bazon@gmail.com>
19571 http://mihai.bazon.net/blog
19572
19573 Distributed under the BSD license:
19574
19575 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
19576
19577 Redistribution and use in source and binary forms, with or without
19578 modification, are permitted provided that the following conditions
19579 are met:
19580
19581 * Redistributions of source code must retain the above
19582 copyright notice, this list of conditions and the following
19583 disclaimer.
19584
19585 * Redistributions in binary form must reproduce the above
19586 copyright notice, this list of conditions and the following
19587 disclaimer in the documentation and/or other materials
19588 provided with the distribution.
19589
19590 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
19591 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19592 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19593 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
19594 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
19595 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19596 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19597 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
19598 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
19599 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
19600 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
19601 SUCH DAMAGE.
19602
19603 ***********************************************************************/
19604
19605"use strict";
19606
19607function Compressor(options, false_by_default) {
19608 if (!(this instanceof Compressor))
19609 return new Compressor(options, false_by_default);
19610 TreeTransformer.call(this, this.before, this.after);
19611 this.options = defaults(options, {
19612 angular : false,
19613 booleans : !false_by_default,
19614 cascade : !false_by_default,
19615 collapse_vars : !false_by_default,
19616 comparisons : !false_by_default,
19617 conditionals : !false_by_default,
19618 dead_code : !false_by_default,
19619 drop_console : false,
19620 drop_debugger : !false_by_default,
19621 evaluate : !false_by_default,
19622 expression : false,
19623 global_defs : {},
19624 hoist_funs : !false_by_default,
19625 hoist_vars : false,
19626 if_return : !false_by_default,
19627 join_vars : !false_by_default,
19628 keep_fargs : true,
19629 keep_fnames : false,
19630 keep_infinity : false,
19631 loops : !false_by_default,
19632 negate_iife : !false_by_default,
19633 passes : 1,
19634 properties : !false_by_default,
19635 pure_getters : !false_by_default && "strict",
19636 pure_funcs : null,
19637 reduce_vars : !false_by_default,
19638 screw_ie8 : true,
19639 sequences : !false_by_default,
19640 side_effects : !false_by_default,
19641 switches : !false_by_default,
19642 top_retain : null,
19643 toplevel : !!(options && options["top_retain"]),
19644 unsafe : false,
19645 unsafe_comps : false,
19646 unsafe_math : false,
19647 unsafe_proto : false,
19648 unsafe_regexp : false,
19649 unused : !false_by_default,
19650 warnings : true,
19651 }, true);
19652 var pure_funcs = this.options["pure_funcs"];
19653 if (typeof pure_funcs == "function") {
19654 this.pure_funcs = pure_funcs;
19655 } else {
19656 this.pure_funcs = pure_funcs ? function(node) {
19657 return pure_funcs.indexOf(node.expression.print_to_string()) < 0;
19658 } : return_true;
19659 }
19660 var top_retain = this.options["top_retain"];
19661 if (top_retain instanceof RegExp) {
19662 this.top_retain = function(def) {
19663 return top_retain.test(def.name);
19664 };
19665 } else if (typeof top_retain == "function") {
19666 this.top_retain = top_retain;
19667 } else if (top_retain) {
19668 if (typeof top_retain == "string") {
19669 top_retain = top_retain.split(/,/);
19670 }
19671 this.top_retain = function(def) {
19672 return top_retain.indexOf(def.name) >= 0;
19673 };
19674 }
19675 var sequences = this.options["sequences"];
19676 this.sequences_limit = sequences == 1 ? 200 : sequences | 0;
19677 this.warnings_produced = {};
19678};
19679
19680Compressor.prototype = new TreeTransformer;
19681merge(Compressor.prototype, {
19682 option: function(key) { return this.options[key] },
19683 compress: function(node) {
19684 if (this.option("expression")) {
19685 node = node.process_expression(true);
19686 }
19687 var passes = +this.options.passes || 1;
19688 for (var pass = 0; pass < passes && pass < 3; ++pass) {
19689 if (pass > 0 || this.option("reduce_vars"))
19690 node.reset_opt_flags(this, true);
19691 node = node.transform(this);
19692 }
19693 if (this.option("expression")) {
19694 node = node.process_expression(false);
19695 }
19696 return node;
19697 },
19698 info: function() {
19699 if (this.options.warnings == "verbose") {
19700 AST_Node.warn.apply(AST_Node, arguments);
19701 }
19702 },
19703 warn: function(text, props) {
19704 if (this.options.warnings) {
19705 // only emit unique warnings
19706 var message = string_template(text, props);
19707 if (!(message in this.warnings_produced)) {
19708 this.warnings_produced[message] = true;
19709 AST_Node.warn.apply(AST_Node, arguments);
19710 }
19711 }
19712 },
19713 clear_warnings: function() {
19714 this.warnings_produced = {};
19715 },
19716 before: function(node, descend, in_list) {
19717 if (node._squeezed) return node;
19718 var was_scope = false;
19719 if (node instanceof AST_Scope) {
19720 node = node.hoist_declarations(this);
19721 was_scope = true;
19722 }
19723 // Before https://github.com/mishoo/UglifyJS2/pull/1602 AST_Node.optimize()
19724 // would call AST_Node.transform() if a different instance of AST_Node is
19725 // produced after OPT().
19726 // This corrupts TreeWalker.stack, which cause AST look-ups to malfunction.
19727 // Migrate and defer all children's AST_Node.transform() to below, which
19728 // will now happen after this parent AST_Node has been properly substituted
19729 // thus gives a consistent AST snapshot.
19730 descend(node, this);
19731 // Existing code relies on how AST_Node.optimize() worked, and omitting the
19732 // following replacement call would result in degraded efficiency of both
19733 // output and performance.
19734 descend(node, this);
19735 var opt = node.optimize(this);
19736 if (was_scope && opt instanceof AST_Scope) {
19737 opt.drop_unused(this);
19738 descend(opt, this);
19739 }
19740 if (opt === node) opt._squeezed = true;
19741 return opt;
19742 }
19743});
19744
19745(function(){
19746
19747 function OPT(node, optimizer) {
19748 node.DEFMETHOD("optimize", function(compressor){
19749 var self = this;
19750 if (self._optimized) return self;
19751 if (compressor.has_directive("use asm")) return self;
19752 var opt = optimizer(self, compressor);
19753 opt._optimized = true;
19754 return opt;
19755 });
19756 };
19757
19758 OPT(AST_Node, function(self, compressor){
19759 return self;
19760 });
19761
19762 AST_Node.DEFMETHOD("equivalent_to", function(node){
19763 return this.TYPE == node.TYPE && this.print_to_string() == node.print_to_string();
19764 });
19765
19766 AST_Node.DEFMETHOD("process_expression", function(insert, compressor) {
19767 var self = this;
19768 var tt = new TreeTransformer(function(node) {
19769 if (insert && node instanceof AST_SimpleStatement) {
19770 return make_node(AST_Return, node, {
19771 value: node.body
19772 });
19773 }
19774 if (!insert && node instanceof AST_Return) {
19775 if (compressor) {
19776 var value = node.value && node.value.drop_side_effect_free(compressor, true);
19777 return value ? make_node(AST_SimpleStatement, node, {
19778 body: value
19779 }) : make_node(AST_EmptyStatement, node);
19780 }
19781 return make_node(AST_SimpleStatement, node, {
19782 body: node.value || make_node(AST_UnaryPrefix, node, {
19783 operator: "void",
19784 expression: make_node(AST_Number, node, {
19785 value: 0
19786 })
19787 })
19788 });
19789 }
19790 if (node instanceof AST_Lambda && node !== self) {
19791 return node;
19792 }
19793 if (node instanceof AST_Block) {
19794 var index = node.body.length - 1;
19795 if (index >= 0) {
19796 node.body[index] = node.body[index].transform(tt);
19797 }
19798 }
19799 if (node instanceof AST_If) {
19800 node.body = node.body.transform(tt);
19801 if (node.alternative) {
19802 node.alternative = node.alternative.transform(tt);
19803 }
19804 }
19805 if (node instanceof AST_With) {
19806 node.body = node.body.transform(tt);
19807 }
19808 return node;
19809 });
19810 return self.transform(tt);
19811 });
19812
19813 AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){
19814 var reduce_vars = rescan && compressor.option("reduce_vars");
19815 var toplevel = compressor.option("toplevel");
19816 var safe_ids = Object.create(null);
19817 var suppressor = new TreeWalker(function(node) {
19818 if (node instanceof AST_Symbol) {
19819 var d = node.definition();
19820 if (node instanceof AST_SymbolRef) d.references.push(node);
19821 d.fixed = false;
19822 }
19823 });
19824 var tw = new TreeWalker(function(node, descend){
19825 node._squeezed = false;
19826 node._optimized = false;
19827 if (reduce_vars) {
19828 if (node instanceof AST_Toplevel) node.globals.each(reset_def);
19829 if (node instanceof AST_Scope) node.variables.each(reset_def);
19830 if (node instanceof AST_SymbolRef) {
19831 var d = node.definition();
19832 d.references.push(node);
19833 if (d.fixed === undefined || !is_safe(d)
19834 || is_modified(node, 0, node.fixed_value() instanceof AST_Lambda)) {
19835 d.fixed = false;
19836 } else {
19837 var parent = tw.parent();
19838 if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
19839 || parent instanceof AST_Call && node !== parent.expression
19840 || parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
19841 || parent instanceof AST_VarDef && node === parent.value) {
19842 d.escaped = true;
19843 }
19844 }
19845 }
19846 if (node instanceof AST_SymbolCatch) {
19847 node.definition().fixed = false;
19848 }
19849 if (node instanceof AST_VarDef) {
19850 var d = node.name.definition();
19851 if (d.fixed == null) {
19852 if (node.value) {
19853 d.fixed = function() {
19854 return node.value;
19855 };
19856 mark(d, false);
19857 descend();
19858 } else {
19859 d.fixed = null;
19860 }
19861 mark(d, true);
19862 return true;
19863 } else if (node.value) {
19864 d.fixed = false;
19865 }
19866 }
19867 if (node instanceof AST_Defun) {
19868 var d = node.name.definition();
19869 if (!toplevel && d.global || is_safe(d)) {
19870 d.fixed = false;
19871 } else {
19872 d.fixed = node;
19873 mark(d, true);
19874 }
19875 var save_ids = safe_ids;
19876 safe_ids = Object.create(null);
19877 descend();
19878 safe_ids = save_ids;
19879 return true;
19880 }
19881 if (node instanceof AST_Function) {
19882 push();
19883 var iife;
19884 if (!node.name
19885 && (iife = tw.parent()) instanceof AST_Call
19886 && iife.expression === node) {
19887 // Virtually turn IIFE parameters into variable definitions:
19888 // (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
19889 // So existing transformation rules can work on them.
19890 node.argnames.forEach(function(arg, i) {
19891 var d = arg.definition();
19892 if (!node.uses_arguments && d.fixed === undefined) {
19893 d.fixed = function() {
19894 return iife.args[i] || make_node(AST_Undefined, iife);
19895 };
19896 mark(d, true);
19897 } else {
19898 d.fixed = false;
19899 }
19900 });
19901 }
19902 descend();
19903 pop();
19904 return true;
19905 }
19906 if (node instanceof AST_Accessor) {
19907 var save_ids = safe_ids;
19908 safe_ids = Object.create(null);
19909 descend();
19910 safe_ids = save_ids;
19911 return true;
19912 }
19913 if (node instanceof AST_Binary
19914 && (node.operator == "&&" || node.operator == "||")) {
19915 node.left.walk(tw);
19916 push();
19917 node.right.walk(tw);
19918 pop();
19919 return true;
19920 }
19921 if (node instanceof AST_Conditional) {
19922 node.condition.walk(tw);
19923 push();
19924 node.consequent.walk(tw);
19925 pop();
19926 push();
19927 node.alternative.walk(tw);
19928 pop();
19929 return true;
19930 }
19931 if (node instanceof AST_If || node instanceof AST_DWLoop) {
19932 node.condition.walk(tw);
19933 push();
19934 node.body.walk(tw);
19935 pop();
19936 if (node.alternative) {
19937 push();
19938 node.alternative.walk(tw);
19939 pop();
19940 }
19941 return true;
19942 }
19943 if (node instanceof AST_LabeledStatement) {
19944 push();
19945 node.body.walk(tw);
19946 pop();
19947 return true;
19948 }
19949 if (node instanceof AST_For) {
19950 if (node.init) node.init.walk(tw);
19951 push();
19952 if (node.condition) node.condition.walk(tw);
19953 node.body.walk(tw);
19954 if (node.step) node.step.walk(tw);
19955 pop();
19956 return true;
19957 }
19958 if (node instanceof AST_ForIn) {
19959 node.init.walk(suppressor);
19960 node.object.walk(tw);
19961 push();
19962 node.body.walk(tw);
19963 pop();
19964 return true;
19965 }
19966 if (node instanceof AST_Try) {
19967 push();
19968 walk_body(node, tw);
19969 pop();
19970 if (node.bcatch) {
19971 push();
19972 node.bcatch.walk(tw);
19973 pop();
19974 }
19975 if (node.bfinally) node.bfinally.walk(tw);
19976 return true;
19977 }
19978 if (node instanceof AST_SwitchBranch) {
19979 push();
19980 descend();
19981 pop();
19982 return true;
19983 }
19984 }
19985 });
19986 this.walk(tw);
19987
19988 function mark(def, safe) {
19989 safe_ids[def.id] = safe;
19990 }
19991
19992 function is_safe(def) {
19993 if (safe_ids[def.id]) {
19994 if (def.fixed == null) {
19995 var orig = def.orig[0];
19996 if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
19997 def.fixed = make_node(AST_Undefined, orig);
19998 }
19999 return true;
20000 }
20001 }
20002
20003 function push() {
20004 safe_ids = Object.create(safe_ids);
20005 }
20006
20007 function pop() {
20008 safe_ids = Object.getPrototypeOf(safe_ids);
20009 }
20010
20011 function reset_def(def) {
20012 def.escaped = false;
20013 if (def.scope.uses_eval) {
20014 def.fixed = false;
20015 } else if (toplevel || !def.global || def.orig[0] instanceof AST_SymbolConst) {
20016 def.fixed = undefined;
20017 } else {
20018 def.fixed = false;
20019 }
20020 def.references = [];
20021 def.should_replace = undefined;
20022 }
20023
20024 function is_modified(node, level, func) {
20025 var parent = tw.parent(level);
20026 if (is_lhs(node, parent)
20027 || !func && parent instanceof AST_Call && parent.expression === node) {
20028 return true;
20029 } else if (parent instanceof AST_PropAccess && parent.expression === node) {
20030 return !func && is_modified(parent, level + 1);
20031 }
20032 }
20033 });
20034
20035 AST_SymbolRef.DEFMETHOD("fixed_value", function() {
20036 var fixed = this.definition().fixed;
20037 if (!fixed || fixed instanceof AST_Node) return fixed;
20038 return fixed();
20039 });
20040
20041 function is_reference_const(ref) {
20042 if (!(ref instanceof AST_SymbolRef)) return false;
20043 var orig = ref.definition().orig;
20044 for (var i = orig.length; --i >= 0;) {
20045 if (orig[i] instanceof AST_SymbolConst) return true;
20046 }
20047 }
20048
20049 function find_variable(compressor, name) {
20050 var scope, i = 0;
20051 while (scope = compressor.parent(i++)) {
20052 if (scope instanceof AST_Scope) break;
20053 if (scope instanceof AST_Catch) {
20054 scope = scope.argname.definition().scope;
20055 break;
20056 }
20057 }
20058 return scope.find_variable(name);
20059 }
20060
20061 function make_node(ctor, orig, props) {
20062 if (!props) props = {};
20063 if (orig) {
20064 if (!props.start) props.start = orig.start;
20065 if (!props.end) props.end = orig.end;
20066 }
20067 return new ctor(props);
20068 };
20069
20070 function make_node_from_constant(val, orig) {
20071 switch (typeof val) {
20072 case "string":
20073 return make_node(AST_String, orig, {
20074 value: val
20075 });
20076 case "number":
20077 if (isNaN(val)) return make_node(AST_NaN, orig);
20078 if (isFinite(val)) {
20079 return 1 / val < 0 ? make_node(AST_UnaryPrefix, orig, {
20080 operator: "-",
20081 expression: make_node(AST_Number, orig, { value: -val })
20082 }) : make_node(AST_Number, orig, { value: val });
20083 }
20084 return val < 0 ? make_node(AST_UnaryPrefix, orig, {
20085 operator: "-",
20086 expression: make_node(AST_Infinity, orig)
20087 }) : make_node(AST_Infinity, orig);
20088 case "boolean":
20089 return make_node(val ? AST_True : AST_False, orig);
20090 case "undefined":
20091 return make_node(AST_Undefined, orig);
20092 default:
20093 if (val === null) {
20094 return make_node(AST_Null, orig, { value: null });
20095 }
20096 if (val instanceof RegExp) {
20097 return make_node(AST_RegExp, orig, { value: val });
20098 }
20099 throw new Error(string_template("Can't handle constant of type: {type}", {
20100 type: typeof val
20101 }));
20102 }
20103 };
20104
20105 // we shouldn't compress (1,func)(something) to
20106 // func(something) because that changes the meaning of
20107 // the func (becomes lexical instead of global).
20108 function maintain_this_binding(parent, orig, val) {
20109 if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
20110 || parent instanceof AST_Call && parent.expression === orig
20111 && (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) {
20112 return make_node(AST_Seq, orig, {
20113 car: make_node(AST_Number, orig, {
20114 value: 0
20115 }),
20116 cdr: val
20117 });
20118 }
20119 return val;
20120 }
20121
20122 function as_statement_array(thing) {
20123 if (thing === null) return [];
20124 if (thing instanceof AST_BlockStatement) return thing.body;
20125 if (thing instanceof AST_EmptyStatement) return [];
20126 if (thing instanceof AST_Statement) return [ thing ];
20127 throw new Error("Can't convert thing to statement array");
20128 };
20129
20130 function is_empty(thing) {
20131 if (thing === null) return true;
20132 if (thing instanceof AST_EmptyStatement) return true;
20133 if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
20134 return false;
20135 };
20136
20137 function loop_body(x) {
20138 if (x instanceof AST_Switch) return x;
20139 if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
20140 return (x.body instanceof AST_BlockStatement ? x.body : x);
20141 }
20142 return x;
20143 };
20144
20145 function is_iife_call(node) {
20146 if (node instanceof AST_Call && !(node instanceof AST_New)) {
20147 return node.expression instanceof AST_Function || is_iife_call(node.expression);
20148 }
20149 return false;
20150 }
20151
20152 function tighten_body(statements, compressor) {
20153 var CHANGED, max_iter = 10;
20154 do {
20155 CHANGED = false;
20156 if (compressor.option("angular")) {
20157 statements = process_for_angular(statements);
20158 }
20159 statements = eliminate_spurious_blocks(statements);
20160 if (compressor.option("dead_code")) {
20161 statements = eliminate_dead_code(statements, compressor);
20162 }
20163 if (compressor.option("if_return")) {
20164 statements = handle_if_return(statements, compressor);
20165 }
20166 if (compressor.sequences_limit > 0) {
20167 statements = sequencesize(statements, compressor);
20168 }
20169 if (compressor.option("join_vars")) {
20170 statements = join_consecutive_vars(statements, compressor);
20171 }
20172 if (compressor.option("collapse_vars")) {
20173 statements = collapse_single_use_vars(statements, compressor);
20174 }
20175 } while (CHANGED && max_iter-- > 0);
20176
20177 return statements;
20178
20179 function collapse_single_use_vars(statements, compressor) {
20180 // Iterate statements backwards looking for a statement with a var/const
20181 // declaration immediately preceding it. Grab the rightmost var definition
20182 // and if it has exactly one reference then attempt to replace its reference
20183 // in the statement with the var value and then erase the var definition.
20184
20185 var self = compressor.self();
20186 var var_defs_removed = false;
20187 var toplevel = compressor.option("toplevel");
20188 for (var stat_index = statements.length; --stat_index >= 0;) {
20189 var stat = statements[stat_index];
20190 if (stat instanceof AST_Definitions) continue;
20191
20192 // Process child blocks of statement if present.
20193 [stat, stat.body, stat.alternative, stat.bcatch, stat.bfinally].forEach(function(node) {
20194 node && node.body && collapse_single_use_vars(node.body, compressor);
20195 });
20196
20197 // The variable definition must precede a statement.
20198 if (stat_index <= 0) break;
20199 var prev_stat_index = stat_index - 1;
20200 var prev_stat = statements[prev_stat_index];
20201 if (!(prev_stat instanceof AST_Definitions)) continue;
20202 var var_defs = prev_stat.definitions;
20203 if (var_defs == null) continue;
20204
20205 var var_names_seen = {};
20206 var side_effects_encountered = false;
20207 var lvalues_encountered = false;
20208 var lvalues = {};
20209
20210 // Scan variable definitions from right to left.
20211 for (var var_defs_index = var_defs.length; --var_defs_index >= 0;) {
20212
20213 // Obtain var declaration and var name with basic sanity check.
20214 var var_decl = var_defs[var_defs_index];
20215 if (var_decl.value == null) break;
20216 var var_name = var_decl.name.name;
20217 if (!var_name || !var_name.length) break;
20218
20219 // Bail if we've seen a var definition of same name before.
20220 if (var_name in var_names_seen) break;
20221 var_names_seen[var_name] = true;
20222
20223 // Only interested in cases with just one reference to the variable.
20224 var def = self.find_variable && self.find_variable(var_name);
20225 if (!def || !def.references || def.references.length !== 1
20226 || var_name == "arguments" || (!toplevel && def.global)) {
20227 side_effects_encountered = true;
20228 continue;
20229 }
20230 var ref = def.references[0];
20231
20232 // Don't replace ref if eval() or with statement in scope.
20233 if (ref.scope.uses_eval || ref.scope.uses_with) break;
20234
20235 // Constant single use vars can be replaced in any scope.
20236 if (var_decl.value.is_constant()) {
20237 var ctt = new TreeTransformer(function(node) {
20238 var parent = ctt.parent();
20239 if (parent instanceof AST_IterationStatement
20240 && (parent.condition === node || parent.init === node)) {
20241 return node;
20242 }
20243 if (node === ref)
20244 return replace_var(node, parent, true);
20245 });
20246 stat.transform(ctt);
20247 continue;
20248 }
20249
20250 // Restrict var replacement to constants if side effects encountered.
20251 if (side_effects_encountered |= lvalues_encountered) continue;
20252
20253 var value_has_side_effects = var_decl.value.has_side_effects(compressor);
20254 // Non-constant single use vars can only be replaced in same scope.
20255 if (ref.scope !== self) {
20256 side_effects_encountered |= value_has_side_effects;
20257 continue;
20258 }
20259
20260 // Detect lvalues in var value.
20261 var tw = new TreeWalker(function(node){
20262 if (node instanceof AST_SymbolRef && is_lvalue(node, tw.parent())) {
20263 lvalues[node.name] = lvalues_encountered = true;
20264 }
20265 });
20266 var_decl.value.walk(tw);
20267
20268 // Replace the non-constant single use var in statement if side effect free.
20269 var unwind = false;
20270 var tt = new TreeTransformer(
20271 function preorder(node) {
20272 if (unwind) return node;
20273 var parent = tt.parent();
20274 if (node instanceof AST_Lambda
20275 || node instanceof AST_Try
20276 || node instanceof AST_With
20277 || node instanceof AST_Case
20278 || node instanceof AST_IterationStatement
20279 || (parent instanceof AST_If && node !== parent.condition)
20280 || (parent instanceof AST_Conditional && node !== parent.condition)
20281 || (node instanceof AST_SymbolRef
20282 && value_has_side_effects
20283 && !are_references_in_scope(node.definition(), self))
20284 || (parent instanceof AST_Binary
20285 && (parent.operator == "&&" || parent.operator == "||")
20286 && node === parent.right)
20287 || (parent instanceof AST_Switch && node !== parent.expression)) {
20288 return side_effects_encountered = unwind = true, node;
20289 }
20290 function are_references_in_scope(def, scope) {
20291 if (def.orig.length === 1
20292 && def.orig[0] instanceof AST_SymbolDefun) return true;
20293 if (def.scope !== scope) return false;
20294 var refs = def.references;
20295 for (var i = 0, len = refs.length; i < len; i++) {
20296 if (refs[i].scope !== scope) return false;
20297 }
20298 return true;
20299 }
20300 },
20301 function postorder(node) {
20302 if (unwind) return node;
20303 if (node === ref)
20304 return unwind = true, replace_var(node, tt.parent(), false);
20305 if (side_effects_encountered |= node.has_side_effects(compressor))
20306 return unwind = true, node;
20307 if (lvalues_encountered && node instanceof AST_SymbolRef && node.name in lvalues) {
20308 side_effects_encountered = true;
20309 return unwind = true, node;
20310 }
20311 }
20312 );
20313 stat.transform(tt);
20314 }
20315 }
20316
20317 // Remove extraneous empty statments in block after removing var definitions.
20318 // Leave at least one statement in `statements`.
20319 if (var_defs_removed) for (var i = statements.length; --i >= 0;) {
20320 if (statements.length > 1 && statements[i] instanceof AST_EmptyStatement)
20321 statements.splice(i, 1);
20322 }
20323
20324 return statements;
20325
20326 function is_lvalue(node, parent) {
20327 return node instanceof AST_SymbolRef && is_lhs(node, parent);
20328 }
20329 function replace_var(node, parent, is_constant) {
20330 if (is_lvalue(node, parent)) return node;
20331
20332 // Remove var definition and return its value to the TreeTransformer to replace.
20333 var value = maintain_this_binding(parent, node, var_decl.value);
20334 var_decl.value = null;
20335
20336 var_defs.splice(var_defs_index, 1);
20337 if (var_defs.length === 0) {
20338 statements[prev_stat_index] = make_node(AST_EmptyStatement, self);
20339 var_defs_removed = true;
20340 }
20341 // Further optimize statement after substitution.
20342 stat.reset_opt_flags(compressor);
20343
20344 compressor.info("Collapsing " + (is_constant ? "constant" : "variable") +
20345 " " + var_name + " [{file}:{line},{col}]", node.start);
20346 CHANGED = true;
20347 return value;
20348 }
20349 }
20350
20351 function process_for_angular(statements) {
20352 function has_inject(comment) {
20353 return /@ngInject/.test(comment.value);
20354 }
20355 function make_arguments_names_list(func) {
20356 return func.argnames.map(function(sym){
20357 return make_node(AST_String, sym, { value: sym.name });
20358 });
20359 }
20360 function make_array(orig, elements) {
20361 return make_node(AST_Array, orig, { elements: elements });
20362 }
20363 function make_injector(func, name) {
20364 return make_node(AST_SimpleStatement, func, {
20365 body: make_node(AST_Assign, func, {
20366 operator: "=",
20367 left: make_node(AST_Dot, name, {
20368 expression: make_node(AST_SymbolRef, name, name),
20369 property: "$inject"
20370 }),
20371 right: make_array(func, make_arguments_names_list(func))
20372 })
20373 });
20374 }
20375 function check_expression(body) {
20376 if (body && body.args) {
20377 // if this is a function call check all of arguments passed
20378 body.args.forEach(function(argument, index, array) {
20379 var comments = argument.start.comments_before;
20380 // if the argument is function preceded by @ngInject
20381 if (argument instanceof AST_Lambda && comments.length && has_inject(comments[0])) {
20382 // replace the function with an array of names of its parameters and function at the end
20383 array[index] = make_array(argument, make_arguments_names_list(argument).concat(argument));
20384 }
20385 });
20386 // if this is chained call check previous one recursively
20387 if (body.expression && body.expression.expression) {
20388 check_expression(body.expression.expression);
20389 }
20390 }
20391 }
20392 return statements.reduce(function(a, stat){
20393 a.push(stat);
20394
20395 if (stat.body && stat.body.args) {
20396 check_expression(stat.body);
20397 } else {
20398 var token = stat.start;
20399 var comments = token.comments_before;
20400 if (comments && comments.length > 0) {
20401 var last = comments.pop();
20402 if (has_inject(last)) {
20403 // case 1: defun
20404 if (stat instanceof AST_Defun) {
20405 a.push(make_injector(stat, stat.name));
20406 }
20407 else if (stat instanceof AST_Definitions) {
20408 stat.definitions.forEach(function(def) {
20409 if (def.value && def.value instanceof AST_Lambda) {
20410 a.push(make_injector(def.value, def.name));
20411 }
20412 });
20413 }
20414 else {
20415 compressor.warn("Unknown statement marked with @ngInject [{file}:{line},{col}]", token);
20416 }
20417 }
20418 }
20419 }
20420
20421 return a;
20422 }, []);
20423 }
20424
20425 function eliminate_spurious_blocks(statements) {
20426 var seen_dirs = [];
20427 return statements.reduce(function(a, stat){
20428 if (stat instanceof AST_BlockStatement) {
20429 CHANGED = true;
20430 a.push.apply(a, eliminate_spurious_blocks(stat.body));
20431 } else if (stat instanceof AST_EmptyStatement) {
20432 CHANGED = true;
20433 } else if (stat instanceof AST_Directive) {
20434 if (seen_dirs.indexOf(stat.value) < 0) {
20435 a.push(stat);
20436 seen_dirs.push(stat.value);
20437 } else {
20438 CHANGED = true;
20439 }
20440 } else {
20441 a.push(stat);
20442 }
20443 return a;
20444 }, []);
20445 };
20446
20447 function handle_if_return(statements, compressor) {
20448 var self = compressor.self();
20449 var multiple_if_returns = has_multiple_if_returns(statements);
20450 var in_lambda = self instanceof AST_Lambda;
20451 var ret = []; // Optimized statements, build from tail to front
20452 loop: for (var i = statements.length; --i >= 0;) {
20453 var stat = statements[i];
20454 switch (true) {
20455 case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0):
20456 CHANGED = true;
20457 // note, ret.length is probably always zero
20458 // because we drop unreachable code before this
20459 // step. nevertheless, it's good to check.
20460 continue loop;
20461 case stat instanceof AST_If:
20462 if (stat.body instanceof AST_Return) {
20463 //---
20464 // pretty silly case, but:
20465 // if (foo()) return; return; ==> foo(); return;
20466 if (((in_lambda && ret.length == 0)
20467 || (ret[0] instanceof AST_Return && !ret[0].value))
20468 && !stat.body.value && !stat.alternative) {
20469 CHANGED = true;
20470 var cond = make_node(AST_SimpleStatement, stat.condition, {
20471 body: stat.condition
20472 });
20473 ret.unshift(cond);
20474 continue loop;
20475 }
20476 //---
20477 // if (foo()) return x; return y; ==> return foo() ? x : y;
20478 if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
20479 CHANGED = true;
20480 stat = stat.clone();
20481 stat.alternative = ret[0];
20482 ret[0] = stat.transform(compressor);
20483 continue loop;
20484 }
20485 //---
20486 // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined;
20487 if (multiple_if_returns && (ret.length == 0 || ret[0] instanceof AST_Return)
20488 && stat.body.value && !stat.alternative && in_lambda) {
20489 CHANGED = true;
20490 stat = stat.clone();
20491 stat.alternative = ret[0] || make_node(AST_Return, stat, {
20492 value: null
20493 });
20494 ret[0] = stat.transform(compressor);
20495 continue loop;
20496 }
20497 //---
20498 // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... }
20499 if (!stat.body.value && in_lambda) {
20500 CHANGED = true;
20501 stat = stat.clone();
20502 stat.condition = stat.condition.negate(compressor);
20503 var body = as_statement_array(stat.alternative).concat(ret);
20504 var funs = extract_functions_from_statement_array(body);
20505 stat.body = make_node(AST_BlockStatement, stat, {
20506 body: body
20507 });
20508 stat.alternative = null;
20509 ret = funs.concat([ stat.transform(compressor) ]);
20510 continue loop;
20511 }
20512
20513 //---
20514 // if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e;
20515 //
20516 // if sequences is not enabled, this can lead to an endless loop (issue #866).
20517 // however, with sequences on this helps producing slightly better output for
20518 // the example code.
20519 if (compressor.option("sequences")
20520 && i > 0 && statements[i - 1] instanceof AST_If && statements[i - 1].body instanceof AST_Return
20521 && ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
20522 && !stat.alternative) {
20523 CHANGED = true;
20524 ret.push(make_node(AST_Return, ret[0], {
20525 value: null
20526 }).transform(compressor));
20527 ret.unshift(stat);
20528 continue loop;
20529 }
20530 }
20531
20532 var ab = aborts(stat.body);
20533 var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
20534 if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
20535 || (ab instanceof AST_Continue && self === loop_body(lct))
20536 || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
20537 if (ab.label) {
20538 remove(ab.label.thedef.references, ab);
20539 }
20540 CHANGED = true;
20541 var body = as_statement_array(stat.body).slice(0, -1);
20542 stat = stat.clone();
20543 stat.condition = stat.condition.negate(compressor);
20544 stat.body = make_node(AST_BlockStatement, stat, {
20545 body: as_statement_array(stat.alternative).concat(ret)
20546 });
20547 stat.alternative = make_node(AST_BlockStatement, stat, {
20548 body: body
20549 });
20550 ret = [ stat.transform(compressor) ];
20551 continue loop;
20552 }
20553
20554 var ab = aborts(stat.alternative);
20555 var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
20556 if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
20557 || (ab instanceof AST_Continue && self === loop_body(lct))
20558 || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
20559 if (ab.label) {
20560 remove(ab.label.thedef.references, ab);
20561 }
20562 CHANGED = true;
20563 stat = stat.clone();
20564 stat.body = make_node(AST_BlockStatement, stat.body, {
20565 body: as_statement_array(stat.body).concat(ret)
20566 });
20567 stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
20568 body: as_statement_array(stat.alternative).slice(0, -1)
20569 });
20570 ret = [ stat.transform(compressor) ];
20571 continue loop;
20572 }
20573
20574 ret.unshift(stat);
20575 break;
20576 default:
20577 ret.unshift(stat);
20578 break;
20579 }
20580 }
20581 return ret;
20582
20583 function has_multiple_if_returns(statements) {
20584 var n = 0;
20585 for (var i = statements.length; --i >= 0;) {
20586 var stat = statements[i];
20587 if (stat instanceof AST_If && stat.body instanceof AST_Return) {
20588 if (++n > 1) return true;
20589 }
20590 }
20591 return false;
20592 }
20593 };
20594
20595 function eliminate_dead_code(statements, compressor) {
20596 var has_quit = false;
20597 var orig = statements.length;
20598 var self = compressor.self();
20599 statements = statements.reduce(function(a, stat){
20600 if (has_quit) {
20601 extract_declarations_from_unreachable_code(compressor, stat, a);
20602 } else {
20603 if (stat instanceof AST_LoopControl) {
20604 var lct = compressor.loopcontrol_target(stat);
20605 if ((stat instanceof AST_Break
20606 && !(lct instanceof AST_IterationStatement)
20607 && loop_body(lct) === self) || (stat instanceof AST_Continue
20608 && loop_body(lct) === self)) {
20609 if (stat.label) {
20610 remove(stat.label.thedef.references, stat);
20611 }
20612 } else {
20613 a.push(stat);
20614 }
20615 } else {
20616 a.push(stat);
20617 }
20618 if (aborts(stat)) has_quit = true;
20619 }
20620 return a;
20621 }, []);
20622 CHANGED = statements.length != orig;
20623 return statements;
20624 };
20625
20626 function sequencesize(statements, compressor) {
20627 if (statements.length < 2) return statements;
20628 var seq = [], ret = [];
20629 function push_seq() {
20630 seq = AST_Seq.from_array(seq);
20631 if (seq) ret.push(make_node(AST_SimpleStatement, seq, {
20632 body: seq
20633 }));
20634 seq = [];
20635 };
20636 statements.forEach(function(stat){
20637 if (stat instanceof AST_SimpleStatement) {
20638 if (seqLength(seq) >= compressor.sequences_limit) push_seq();
20639 var body = stat.body;
20640 if (seq.length > 0) body = body.drop_side_effect_free(compressor);
20641 if (body) seq.push(body);
20642 } else {
20643 push_seq();
20644 ret.push(stat);
20645 }
20646 });
20647 push_seq();
20648 ret = sequencesize_2(ret, compressor);
20649 CHANGED = ret.length != statements.length;
20650 return ret;
20651 };
20652
20653 function seqLength(a) {
20654 for (var len = 0, i = 0; i < a.length; ++i) {
20655 var stat = a[i];
20656 if (stat instanceof AST_Seq) {
20657 len += stat.len();
20658 } else {
20659 len++;
20660 }
20661 }
20662 return len;
20663 };
20664
20665 function sequencesize_2(statements, compressor) {
20666 function cons_seq(right) {
20667 ret.pop();
20668 var left = prev.body;
20669 if (left instanceof AST_Seq) {
20670 left.add(right);
20671 } else {
20672 left = AST_Seq.cons(left, right);
20673 }
20674 return left.transform(compressor);
20675 };
20676 var ret = [], prev = null;
20677 statements.forEach(function(stat){
20678 if (prev) {
20679 if (stat instanceof AST_For) {
20680 var opera = {};
20681 try {
20682 prev.body.walk(new TreeWalker(function(node){
20683 if (node instanceof AST_Binary && node.operator == "in")
20684 throw opera;
20685 }));
20686 if (stat.init && !(stat.init instanceof AST_Definitions)) {
20687 stat.init = cons_seq(stat.init);
20688 }
20689 else if (!stat.init) {
20690 stat.init = prev.body.drop_side_effect_free(compressor);
20691 ret.pop();
20692 }
20693 } catch(ex) {
20694 if (ex !== opera) throw ex;
20695 }
20696 }
20697 else if (stat instanceof AST_If) {
20698 stat.condition = cons_seq(stat.condition);
20699 }
20700 else if (stat instanceof AST_With) {
20701 stat.expression = cons_seq(stat.expression);
20702 }
20703 else if (stat instanceof AST_Exit && stat.value) {
20704 stat.value = cons_seq(stat.value);
20705 }
20706 else if (stat instanceof AST_Exit) {
20707 stat.value = cons_seq(make_node(AST_Undefined, stat).transform(compressor));
20708 }
20709 else if (stat instanceof AST_Switch) {
20710 stat.expression = cons_seq(stat.expression);
20711 }
20712 }
20713 ret.push(stat);
20714 prev = stat instanceof AST_SimpleStatement ? stat : null;
20715 });
20716 return ret;
20717 };
20718
20719 function join_consecutive_vars(statements, compressor) {
20720 var prev = null;
20721 return statements.reduce(function(a, stat){
20722 if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
20723 prev.definitions = prev.definitions.concat(stat.definitions);
20724 CHANGED = true;
20725 }
20726 else if (stat instanceof AST_For
20727 && prev instanceof AST_Var
20728 && (!stat.init || stat.init.TYPE == prev.TYPE)) {
20729 CHANGED = true;
20730 a.pop();
20731 if (stat.init) {
20732 stat.init.definitions = prev.definitions.concat(stat.init.definitions);
20733 } else {
20734 stat.init = prev;
20735 }
20736 a.push(stat);
20737 prev = stat;
20738 }
20739 else {
20740 prev = stat;
20741 a.push(stat);
20742 }
20743 return a;
20744 }, []);
20745 };
20746
20747 };
20748
20749 function extract_functions_from_statement_array(statements) {
20750 var funs = [];
20751 for (var i = statements.length - 1; i >= 0; --i) {
20752 var stat = statements[i];
20753 if (stat instanceof AST_Defun) {
20754 statements.splice(i, 1);
20755 funs.unshift(stat);
20756 }
20757 }
20758 return funs;
20759 }
20760
20761 function extract_declarations_from_unreachable_code(compressor, stat, target) {
20762 if (!(stat instanceof AST_Defun)) {
20763 compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
20764 }
20765 stat.walk(new TreeWalker(function(node){
20766 if (node instanceof AST_Definitions) {
20767 compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
20768 node.remove_initializers();
20769 target.push(node);
20770 return true;
20771 }
20772 if (node instanceof AST_Defun) {
20773 target.push(node);
20774 return true;
20775 }
20776 if (node instanceof AST_Scope) {
20777 return true;
20778 }
20779 }));
20780 };
20781
20782 function is_undefined(node, compressor) {
20783 return node.is_undefined
20784 || node instanceof AST_Undefined
20785 || node instanceof AST_UnaryPrefix
20786 && node.operator == "void"
20787 && !node.expression.has_side_effects(compressor);
20788 }
20789
20790 // may_throw_on_access()
20791 // returns true if this node may be null, undefined or contain `AST_Accessor`
20792 (function(def) {
20793 AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
20794 var pure_getters = compressor.option("pure_getters");
20795 return !pure_getters || this._throw_on_access(pure_getters);
20796 });
20797
20798 function is_strict(pure_getters) {
20799 return /strict/.test(pure_getters);
20800 }
20801
20802 def(AST_Node, is_strict);
20803 def(AST_Null, return_true);
20804 def(AST_Undefined, return_true);
20805 def(AST_Constant, return_false);
20806 def(AST_Array, return_false);
20807 def(AST_Object, function(pure_getters) {
20808 if (!is_strict(pure_getters)) return false;
20809 for (var i = this.properties.length; --i >=0;)
20810 if (this.properties[i].value instanceof AST_Accessor) return true;
20811 return false;
20812 });
20813 def(AST_Function, return_false);
20814 def(AST_UnaryPostfix, return_false);
20815 def(AST_UnaryPrefix, function() {
20816 return this.operator == "void";
20817 });
20818 def(AST_Binary, function(pure_getters) {
20819 switch (this.operator) {
20820 case "&&":
20821 return this.left._throw_on_access(pure_getters);
20822 case "||":
20823 return this.left._throw_on_access(pure_getters)
20824 && this.right._throw_on_access(pure_getters);
20825 default:
20826 return false;
20827 }
20828 })
20829 def(AST_Assign, function(pure_getters) {
20830 return this.operator == "="
20831 && this.right._throw_on_access(pure_getters);
20832 })
20833 def(AST_Conditional, function(pure_getters) {
20834 return this.consequent._throw_on_access(pure_getters)
20835 || this.alternative._throw_on_access(pure_getters);
20836 })
20837 def(AST_Seq, function(pure_getters) {
20838 return this.cdr._throw_on_access(pure_getters);
20839 });
20840 def(AST_SymbolRef, function(pure_getters) {
20841 if (this.is_undefined) return true;
20842 if (!is_strict(pure_getters)) return false;
20843 var fixed = this.fixed_value();
20844 return !fixed || fixed._throw_on_access(pure_getters);
20845 });
20846 })(function(node, func) {
20847 node.DEFMETHOD("_throw_on_access", func);
20848 });
20849
20850 /* -----[ boolean/negation helpers ]----- */
20851
20852 // methods to determine whether an expression has a boolean result type
20853 (function (def){
20854 var unary_bool = [ "!", "delete" ];
20855 var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
20856 def(AST_Node, return_false);
20857 def(AST_UnaryPrefix, function(){
20858 return member(this.operator, unary_bool);
20859 });
20860 def(AST_Binary, function(){
20861 return member(this.operator, binary_bool) ||
20862 ( (this.operator == "&&" || this.operator == "||") &&
20863 this.left.is_boolean() && this.right.is_boolean() );
20864 });
20865 def(AST_Conditional, function(){
20866 return this.consequent.is_boolean() && this.alternative.is_boolean();
20867 });
20868 def(AST_Assign, function(){
20869 return this.operator == "=" && this.right.is_boolean();
20870 });
20871 def(AST_Seq, function(){
20872 return this.cdr.is_boolean();
20873 });
20874 def(AST_True, return_true);
20875 def(AST_False, return_true);
20876 })(function(node, func){
20877 node.DEFMETHOD("is_boolean", func);
20878 });
20879
20880 // methods to determine if an expression has a numeric result type
20881 (function (def){
20882 def(AST_Node, return_false);
20883 def(AST_Number, return_true);
20884 var unary = makePredicate("+ - ~ ++ --");
20885 def(AST_Unary, function(){
20886 return unary(this.operator);
20887 });
20888 var binary = makePredicate("- * / % & | ^ << >> >>>");
20889 def(AST_Binary, function(compressor){
20890 return binary(this.operator) || this.operator == "+"
20891 && this.left.is_number(compressor)
20892 && this.right.is_number(compressor);
20893 });
20894 def(AST_Assign, function(compressor){
20895 return binary(this.operator.slice(0, -1))
20896 || this.operator == "=" && this.right.is_number(compressor);
20897 });
20898 def(AST_Seq, function(compressor){
20899 return this.cdr.is_number(compressor);
20900 });
20901 def(AST_Conditional, function(compressor){
20902 return this.consequent.is_number(compressor) && this.alternative.is_number(compressor);
20903 });
20904 })(function(node, func){
20905 node.DEFMETHOD("is_number", func);
20906 });
20907
20908 // methods to determine if an expression has a string result type
20909 (function (def){
20910 def(AST_Node, return_false);
20911 def(AST_String, return_true);
20912 def(AST_UnaryPrefix, function(){
20913 return this.operator == "typeof";
20914 });
20915 def(AST_Binary, function(compressor){
20916 return this.operator == "+" &&
20917 (this.left.is_string(compressor) || this.right.is_string(compressor));
20918 });
20919 def(AST_Assign, function(compressor){
20920 return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
20921 });
20922 def(AST_Seq, function(compressor){
20923 return this.cdr.is_string(compressor);
20924 });
20925 def(AST_Conditional, function(compressor){
20926 return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
20927 });
20928 })(function(node, func){
20929 node.DEFMETHOD("is_string", func);
20930 });
20931
20932 var unary_side_effects = makePredicate("delete ++ --");
20933
20934 function is_lhs(node, parent) {
20935 if (parent instanceof AST_Unary && unary_side_effects(parent.operator)) return parent.expression;
20936 if (parent instanceof AST_Assign && parent.left === node) return node;
20937 }
20938
20939 (function (def){
20940 AST_Node.DEFMETHOD("resolve_defines", function(compressor) {
20941 if (!compressor.option("global_defs")) return;
20942 var def = this._find_defs(compressor, "");
20943 if (def) {
20944 var node, parent = this, level = 0;
20945 do {
20946 node = parent;
20947 parent = compressor.parent(level++);
20948 } while (parent instanceof AST_PropAccess && parent.expression === node);
20949 if (is_lhs(node, parent)) {
20950 compressor.warn('global_defs ' + this.print_to_string() + ' redefined [{file}:{line},{col}]', this.start);
20951 } else {
20952 return def;
20953 }
20954 }
20955 });
20956 function to_node(value, orig) {
20957 if (value instanceof AST_Node) return make_node(value.CTOR, orig, value);
20958 if (Array.isArray(value)) return make_node(AST_Array, orig, {
20959 elements: value.map(function(value) {
20960 return to_node(value, orig);
20961 })
20962 });
20963 if (value && typeof value == "object") {
20964 var props = [];
20965 for (var key in value) {
20966 props.push(make_node(AST_ObjectKeyVal, orig, {
20967 key: key,
20968 value: to_node(value[key], orig)
20969 }));
20970 }
20971 return make_node(AST_Object, orig, {
20972 properties: props
20973 });
20974 }
20975 return make_node_from_constant(value, orig);
20976 }
20977 def(AST_Node, noop);
20978 def(AST_Dot, function(compressor, suffix){
20979 return this.expression._find_defs(compressor, "." + this.property + suffix);
20980 });
20981 def(AST_SymbolRef, function(compressor, suffix){
20982 if (!this.global()) return;
20983 var name;
20984 var defines = compressor.option("global_defs");
20985 if (defines && HOP(defines, (name = this.name + suffix))) {
20986 var node = to_node(defines[name], this);
20987 var top = compressor.find_parent(AST_Toplevel);
20988 node.walk(new TreeWalker(function(node) {
20989 if (node instanceof AST_SymbolRef) {
20990 node.scope = top;
20991 node.thedef = top.def_global(node);
20992 }
20993 }));
20994 return node;
20995 }
20996 });
20997 })(function(node, func){
20998 node.DEFMETHOD("_find_defs", func);
20999 });
21000
21001 function best_of_expression(ast1, ast2) {
21002 return ast1.print_to_string().length >
21003 ast2.print_to_string().length
21004 ? ast2 : ast1;
21005 }
21006
21007 function best_of_statement(ast1, ast2) {
21008 return best_of_expression(make_node(AST_SimpleStatement, ast1, {
21009 body: ast1
21010 }), make_node(AST_SimpleStatement, ast2, {
21011 body: ast2
21012 })).body;
21013 }
21014
21015 function best_of(compressor, ast1, ast2) {
21016 return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2);
21017 }
21018
21019 // methods to evaluate a constant expression
21020 (function (def){
21021 // If the node has been successfully reduced to a constant,
21022 // then its value is returned; otherwise the element itself
21023 // is returned.
21024 // They can be distinguished as constant value is never a
21025 // descendant of AST_Node.
21026 AST_Node.DEFMETHOD("evaluate", function(compressor){
21027 if (!compressor.option("evaluate")) return this;
21028 try {
21029 var val = this._eval(compressor);
21030 return !val || val instanceof RegExp || typeof val != "object" ? val : this;
21031 } catch(ex) {
21032 if (ex !== def) throw ex;
21033 return this;
21034 }
21035 });
21036 var unaryPrefix = makePredicate("! ~ - + void");
21037 AST_Node.DEFMETHOD("is_constant", function(){
21038 // Accomodate when compress option evaluate=false
21039 // as well as the common constant expressions !0 and -1
21040 if (this instanceof AST_Constant) {
21041 return !(this instanceof AST_RegExp);
21042 } else {
21043 return this instanceof AST_UnaryPrefix
21044 && this.expression instanceof AST_Constant
21045 && unaryPrefix(this.operator);
21046 }
21047 });
21048 // Obtain the constant value of an expression already known to be constant.
21049 // Result only valid iff this.is_constant() is true.
21050 AST_Node.DEFMETHOD("constant_value", function(compressor){
21051 // Accomodate when option evaluate=false.
21052 if (this instanceof AST_Constant && !(this instanceof AST_RegExp)) {
21053 return this.value;
21054 }
21055 // Accomodate the common constant expressions !0 and -1 when option evaluate=false.
21056 if (this instanceof AST_UnaryPrefix
21057 && this.expression instanceof AST_Constant) switch (this.operator) {
21058 case "!":
21059 return !this.expression.value;
21060 case "~":
21061 return ~this.expression.value;
21062 case "-":
21063 return -this.expression.value;
21064 case "+":
21065 return +this.expression.value;
21066 default:
21067 throw new Error(string_template("Cannot evaluate unary expression {value}", {
21068 value: this.print_to_string()
21069 }));
21070 }
21071 var result = this.evaluate(compressor);
21072 if (result !== this) {
21073 return result;
21074 }
21075 throw new Error(string_template("Cannot evaluate constant [{file}:{line},{col}]", this.start));
21076 });
21077 def(AST_Statement, function(){
21078 throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
21079 });
21080 def(AST_Lambda, function(){
21081 throw def;
21082 });
21083 function ev(node, compressor) {
21084 if (!compressor) throw new Error("Compressor must be passed");
21085
21086 return node._eval(compressor);
21087 };
21088 def(AST_Node, function(){
21089 throw def; // not constant
21090 });
21091 def(AST_Constant, function(){
21092 return this.getValue();
21093 });
21094 def(AST_Array, function(compressor){
21095 if (compressor.option("unsafe")) {
21096 return this.elements.map(function(element) {
21097 return ev(element, compressor);
21098 });
21099 }
21100 throw def;
21101 });
21102 def(AST_Object, function(compressor){
21103 if (compressor.option("unsafe")) {
21104 var val = {};
21105 for (var i = 0, len = this.properties.length; i < len; i++) {
21106 var prop = this.properties[i];
21107 var key = prop.key;
21108 if (key instanceof AST_Symbol) {
21109 key = key.name;
21110 } else if (key instanceof AST_Node) {
21111 key = ev(key, compressor);
21112 }
21113 if (typeof Object.prototype[key] === 'function') {
21114 throw def;
21115 }
21116 val[key] = ev(prop.value, compressor);
21117 }
21118 return val;
21119 }
21120 throw def;
21121 });
21122 def(AST_UnaryPrefix, function(compressor){
21123 var e = this.expression;
21124 switch (this.operator) {
21125 case "!": return !ev(e, compressor);
21126 case "typeof":
21127 // Function would be evaluated to an array and so typeof would
21128 // incorrectly return 'object'. Hence making is a special case.
21129 if (e instanceof AST_Function) return typeof function(){};
21130
21131 e = ev(e, compressor);
21132
21133 // typeof <RegExp> returns "object" or "function" on different platforms
21134 // so cannot evaluate reliably
21135 if (e instanceof RegExp) throw def;
21136
21137 return typeof e;
21138 case "void": return void ev(e, compressor);
21139 case "~": return ~ev(e, compressor);
21140 case "-": return -ev(e, compressor);
21141 case "+": return +ev(e, compressor);
21142 }
21143 throw def;
21144 });
21145 def(AST_Binary, function(c){
21146 var left = this.left, right = this.right, result;
21147 switch (this.operator) {
21148 case "&&" : result = ev(left, c) && ev(right, c); break;
21149 case "||" : result = ev(left, c) || ev(right, c); break;
21150 case "|" : result = ev(left, c) | ev(right, c); break;
21151 case "&" : result = ev(left, c) & ev(right, c); break;
21152 case "^" : result = ev(left, c) ^ ev(right, c); break;
21153 case "+" : result = ev(left, c) + ev(right, c); break;
21154 case "*" : result = ev(left, c) * ev(right, c); break;
21155 case "/" : result = ev(left, c) / ev(right, c); break;
21156 case "%" : result = ev(left, c) % ev(right, c); break;
21157 case "-" : result = ev(left, c) - ev(right, c); break;
21158 case "<<" : result = ev(left, c) << ev(right, c); break;
21159 case ">>" : result = ev(left, c) >> ev(right, c); break;
21160 case ">>>" : result = ev(left, c) >>> ev(right, c); break;
21161 case "==" : result = ev(left, c) == ev(right, c); break;
21162 case "===" : result = ev(left, c) === ev(right, c); break;
21163 case "!=" : result = ev(left, c) != ev(right, c); break;
21164 case "!==" : result = ev(left, c) !== ev(right, c); break;
21165 case "<" : result = ev(left, c) < ev(right, c); break;
21166 case "<=" : result = ev(left, c) <= ev(right, c); break;
21167 case ">" : result = ev(left, c) > ev(right, c); break;
21168 case ">=" : result = ev(left, c) >= ev(right, c); break;
21169 default:
21170 throw def;
21171 }
21172 if (isNaN(result) && c.find_parent(AST_With)) {
21173 // leave original expression as is
21174 throw def;
21175 }
21176 return result;
21177 });
21178 def(AST_Conditional, function(compressor){
21179 return ev(this.condition, compressor)
21180 ? ev(this.consequent, compressor)
21181 : ev(this.alternative, compressor);
21182 });
21183 def(AST_SymbolRef, function(compressor){
21184 if (!compressor.option("reduce_vars") || this._evaluating) throw def;
21185 this._evaluating = true;
21186 try {
21187 var fixed = this.fixed_value();
21188 if (!fixed) throw def;
21189 var value = ev(fixed, compressor);
21190 if (!HOP(fixed, "_eval")) fixed._eval = function() {
21191 return value;
21192 };
21193 if (value && typeof value == "object" && this.definition().escaped) throw def;
21194 return value;
21195 } finally {
21196 this._evaluating = false;
21197 }
21198 });
21199 def(AST_PropAccess, function(compressor){
21200 if (compressor.option("unsafe")) {
21201 var key = this.property;
21202 if (key instanceof AST_Node) {
21203 key = ev(key, compressor);
21204 }
21205 var val = ev(this.expression, compressor);
21206 if (val && HOP(val, key)) {
21207 return val[key];
21208 }
21209 }
21210 throw def;
21211 });
21212 })(function(node, func){
21213 node.DEFMETHOD("_eval", func);
21214 });
21215
21216 // method to negate an expression
21217 (function(def){
21218 function basic_negation(exp) {
21219 return make_node(AST_UnaryPrefix, exp, {
21220 operator: "!",
21221 expression: exp
21222 });
21223 }
21224 function best(orig, alt, first_in_statement) {
21225 var negated = basic_negation(orig);
21226 if (first_in_statement) {
21227 var stat = make_node(AST_SimpleStatement, alt, {
21228 body: alt
21229 });
21230 return best_of_expression(negated, stat) === stat ? alt : negated;
21231 }
21232 return best_of_expression(negated, alt);
21233 }
21234 def(AST_Node, function(){
21235 return basic_negation(this);
21236 });
21237 def(AST_Statement, function(){
21238 throw new Error("Cannot negate a statement");
21239 });
21240 def(AST_Function, function(){
21241 return basic_negation(this);
21242 });
21243 def(AST_UnaryPrefix, function(){
21244 if (this.operator == "!")
21245 return this.expression;
21246 return basic_negation(this);
21247 });
21248 def(AST_Seq, function(compressor){
21249 var self = this.clone();
21250 self.cdr = self.cdr.negate(compressor);
21251 return self;
21252 });
21253 def(AST_Conditional, function(compressor, first_in_statement){
21254 var self = this.clone();
21255 self.consequent = self.consequent.negate(compressor);
21256 self.alternative = self.alternative.negate(compressor);
21257 return best(this, self, first_in_statement);
21258 });
21259 def(AST_Binary, function(compressor, first_in_statement){
21260 var self = this.clone(), op = this.operator;
21261 if (compressor.option("unsafe_comps")) {
21262 switch (op) {
21263 case "<=" : self.operator = ">" ; return self;
21264 case "<" : self.operator = ">=" ; return self;
21265 case ">=" : self.operator = "<" ; return self;
21266 case ">" : self.operator = "<=" ; return self;
21267 }
21268 }
21269 switch (op) {
21270 case "==" : self.operator = "!="; return self;
21271 case "!=" : self.operator = "=="; return self;
21272 case "===": self.operator = "!=="; return self;
21273 case "!==": self.operator = "==="; return self;
21274 case "&&":
21275 self.operator = "||";
21276 self.left = self.left.negate(compressor, first_in_statement);
21277 self.right = self.right.negate(compressor);
21278 return best(this, self, first_in_statement);
21279 case "||":
21280 self.operator = "&&";
21281 self.left = self.left.negate(compressor, first_in_statement);
21282 self.right = self.right.negate(compressor);
21283 return best(this, self, first_in_statement);
21284 }
21285 return basic_negation(this);
21286 });
21287 })(function(node, func){
21288 node.DEFMETHOD("negate", function(compressor, first_in_statement){
21289 return func.call(this, compressor, first_in_statement);
21290 });
21291 });
21292
21293 AST_Call.DEFMETHOD("has_pure_annotation", function(compressor) {
21294 if (!compressor.option("side_effects")) return false;
21295 if (this.pure !== undefined) return this.pure;
21296 var pure = false;
21297 var comments, last_comment;
21298 if (this.start
21299 && (comments = this.start.comments_before)
21300 && comments.length
21301 && /[@#]__PURE__/.test((last_comment = comments[comments.length - 1]).value)) {
21302 pure = last_comment;
21303 }
21304 return this.pure = pure;
21305 });
21306
21307 // determine if expression has side effects
21308 (function(def){
21309 def(AST_Node, return_true);
21310
21311 def(AST_EmptyStatement, return_false);
21312 def(AST_Constant, return_false);
21313 def(AST_This, return_false);
21314
21315 def(AST_Call, function(compressor){
21316 if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return true;
21317 for (var i = this.args.length; --i >= 0;) {
21318 if (this.args[i].has_side_effects(compressor))
21319 return true;
21320 }
21321 return false;
21322 });
21323
21324 function any(list, compressor) {
21325 for (var i = list.length; --i >= 0;)
21326 if (list[i].has_side_effects(compressor))
21327 return true;
21328 return false;
21329 }
21330
21331 def(AST_Block, function(compressor){
21332 return any(this.body, compressor);
21333 });
21334 def(AST_Switch, function(compressor){
21335 return this.expression.has_side_effects(compressor)
21336 || any(this.body, compressor);
21337 });
21338 def(AST_Case, function(compressor){
21339 return this.expression.has_side_effects(compressor)
21340 || any(this.body, compressor);
21341 });
21342 def(AST_Try, function(compressor){
21343 return any(this.body, compressor)
21344 || this.bcatch && this.bcatch.has_side_effects(compressor)
21345 || this.bfinally && this.bfinally.has_side_effects(compressor);
21346 });
21347 def(AST_If, function(compressor){
21348 return this.condition.has_side_effects(compressor)
21349 || this.body && this.body.has_side_effects(compressor)
21350 || this.alternative && this.alternative.has_side_effects(compressor);
21351 });
21352 def(AST_LabeledStatement, function(compressor){
21353 return this.body.has_side_effects(compressor);
21354 });
21355 def(AST_SimpleStatement, function(compressor){
21356 return this.body.has_side_effects(compressor);
21357 });
21358 def(AST_Defun, return_true);
21359 def(AST_Function, return_false);
21360 def(AST_Binary, function(compressor){
21361 return this.left.has_side_effects(compressor)
21362 || this.right.has_side_effects(compressor);
21363 });
21364 def(AST_Assign, return_true);
21365 def(AST_Conditional, function(compressor){
21366 return this.condition.has_side_effects(compressor)
21367 || this.consequent.has_side_effects(compressor)
21368 || this.alternative.has_side_effects(compressor);
21369 });
21370 def(AST_Unary, function(compressor){
21371 return unary_side_effects(this.operator)
21372 || this.expression.has_side_effects(compressor);
21373 });
21374 def(AST_SymbolRef, function(compressor){
21375 return this.undeclared();
21376 });
21377 def(AST_Object, function(compressor){
21378 return any(this.properties, compressor);
21379 });
21380 def(AST_ObjectProperty, function(compressor){
21381 return this.value.has_side_effects(compressor);
21382 });
21383 def(AST_Array, function(compressor){
21384 return any(this.elements, compressor);
21385 });
21386 def(AST_Dot, function(compressor){
21387 return this.expression.may_throw_on_access(compressor)
21388 || this.expression.has_side_effects(compressor);
21389 });
21390 def(AST_Sub, function(compressor){
21391 return this.expression.may_throw_on_access(compressor)
21392 || this.expression.has_side_effects(compressor)
21393 || this.property.has_side_effects(compressor);
21394 });
21395 def(AST_Seq, function(compressor){
21396 return this.car.has_side_effects(compressor)
21397 || this.cdr.has_side_effects(compressor);
21398 });
21399 })(function(node, func){
21400 node.DEFMETHOD("has_side_effects", func);
21401 });
21402
21403 // tell me if a statement aborts
21404 function aborts(thing) {
21405 return thing && thing.aborts();
21406 };
21407 (function(def){
21408 def(AST_Statement, return_null);
21409 def(AST_Jump, return_this);
21410 function block_aborts(){
21411 var n = this.body.length;
21412 return n > 0 && aborts(this.body[n - 1]);
21413 };
21414 def(AST_BlockStatement, block_aborts);
21415 def(AST_SwitchBranch, block_aborts);
21416 def(AST_If, function(){
21417 return this.alternative && aborts(this.body) && aborts(this.alternative) && this;
21418 });
21419 })(function(node, func){
21420 node.DEFMETHOD("aborts", func);
21421 });
21422
21423 /* -----[ optimizers ]----- */
21424
21425 OPT(AST_Directive, function(self, compressor){
21426 if (compressor.has_directive(self.value) !== self) {
21427 return make_node(AST_EmptyStatement, self);
21428 }
21429 return self;
21430 });
21431
21432 OPT(AST_Debugger, function(self, compressor){
21433 if (compressor.option("drop_debugger"))
21434 return make_node(AST_EmptyStatement, self);
21435 return self;
21436 });
21437
21438 OPT(AST_LabeledStatement, function(self, compressor){
21439 if (self.body instanceof AST_Break
21440 && compressor.loopcontrol_target(self.body) === self.body) {
21441 return make_node(AST_EmptyStatement, self);
21442 }
21443 return self.label.references.length == 0 ? self.body : self;
21444 });
21445
21446 OPT(AST_Block, function(self, compressor){
21447 self.body = tighten_body(self.body, compressor);
21448 return self;
21449 });
21450
21451 OPT(AST_BlockStatement, function(self, compressor){
21452 self.body = tighten_body(self.body, compressor);
21453 switch (self.body.length) {
21454 case 1: return self.body[0];
21455 case 0: return make_node(AST_EmptyStatement, self);
21456 }
21457 return self;
21458 });
21459
21460 AST_Scope.DEFMETHOD("drop_unused", function(compressor){
21461 var self = this;
21462 if (compressor.has_directive("use asm")) return self;
21463 var toplevel = compressor.option("toplevel");
21464 if (compressor.option("unused")
21465 && (!(self instanceof AST_Toplevel) || toplevel)
21466 && !self.uses_eval
21467 && !self.uses_with) {
21468 var assign_as_unused = !/keep_assign/.test(compressor.option("unused"));
21469 var drop_funcs = /funcs/.test(toplevel);
21470 var drop_vars = /vars/.test(toplevel);
21471 if (!(self instanceof AST_Toplevel) || toplevel == true) {
21472 drop_funcs = drop_vars = true;
21473 }
21474 var in_use = [];
21475 var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
21476 if (self instanceof AST_Toplevel && compressor.top_retain) {
21477 self.variables.each(function(def) {
21478 if (compressor.top_retain(def) && !(def.id in in_use_ids)) {
21479 in_use_ids[def.id] = true;
21480 in_use.push(def);
21481 }
21482 });
21483 }
21484 var initializations = new Dictionary();
21485 // pass 1: find out which symbols are directly used in
21486 // this scope (not in nested scopes).
21487 var scope = this;
21488 var tw = new TreeWalker(function(node, descend){
21489 if (node !== self) {
21490 if (node instanceof AST_Defun) {
21491 if (!drop_funcs && scope === self) {
21492 var node_def = node.name.definition();
21493 if (!(node_def.id in in_use_ids)) {
21494 in_use_ids[node_def.id] = true;
21495 in_use.push(node_def);
21496 }
21497 }
21498 initializations.add(node.name.name, node);
21499 return true; // don't go in nested scopes
21500 }
21501 if (node instanceof AST_Definitions && scope === self) {
21502 node.definitions.forEach(function(def){
21503 if (!drop_vars) {
21504 var node_def = def.name.definition();
21505 if (!(node_def.id in in_use_ids)) {
21506 in_use_ids[node_def.id] = true;
21507 in_use.push(node_def);
21508 }
21509 }
21510 if (def.value) {
21511 initializations.add(def.name.name, def.value);
21512 if (def.value.has_side_effects(compressor)) {
21513 def.value.walk(tw);
21514 }
21515 }
21516 });
21517 return true;
21518 }
21519 if (assign_as_unused
21520 && node instanceof AST_Assign
21521 && node.operator == "="
21522 && node.left instanceof AST_SymbolRef
21523 && !is_reference_const(node.left)
21524 && scope === self) {
21525 node.right.walk(tw);
21526 return true;
21527 }
21528 if (node instanceof AST_SymbolRef) {
21529 var node_def = node.definition();
21530 if (!(node_def.id in in_use_ids)) {
21531 in_use_ids[node_def.id] = true;
21532 in_use.push(node_def);
21533 }
21534 return true;
21535 }
21536 if (node instanceof AST_Scope) {
21537 var save_scope = scope;
21538 scope = node;
21539 descend();
21540 scope = save_scope;
21541 return true;
21542 }
21543 }
21544 });
21545 self.walk(tw);
21546 // pass 2: for every used symbol we need to walk its
21547 // initialization code to figure out if it uses other
21548 // symbols (that may not be in_use).
21549 for (var i = 0; i < in_use.length; ++i) {
21550 in_use[i].orig.forEach(function(decl){
21551 // undeclared globals will be instanceof AST_SymbolRef
21552 var init = initializations.get(decl.name);
21553 if (init) init.forEach(function(init){
21554 var tw = new TreeWalker(function(node){
21555 if (node instanceof AST_SymbolRef) {
21556 var node_def = node.definition();
21557 if (!(node_def.id in in_use_ids)) {
21558 in_use_ids[node_def.id] = true;
21559 in_use.push(node_def);
21560 }
21561 }
21562 });
21563 init.walk(tw);
21564 });
21565 });
21566 }
21567 // pass 3: we should drop declarations not in_use
21568 var tt = new TreeTransformer(
21569 function before(node, descend, in_list) {
21570 if (node instanceof AST_Function
21571 && node.name
21572 && !compressor.option("keep_fnames")) {
21573 var def = node.name.definition();
21574 // any declarations with same name will overshadow
21575 // name of this anonymous function and can therefore
21576 // never be used anywhere
21577 if (!(def.id in in_use_ids) || def.orig.length > 1)
21578 node.name = null;
21579 }
21580 if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
21581 var trim = !compressor.option("keep_fargs");
21582 for (var a = node.argnames, i = a.length; --i >= 0;) {
21583 var sym = a[i];
21584 if (!(sym.definition().id in in_use_ids)) {
21585 sym.__unused = true;
21586 if (trim) {
21587 a.pop();
21588 compressor[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", {
21589 name : sym.name,
21590 file : sym.start.file,
21591 line : sym.start.line,
21592 col : sym.start.col
21593 });
21594 }
21595 }
21596 else {
21597 trim = false;
21598 }
21599 }
21600 }
21601 if (drop_funcs && node instanceof AST_Defun && node !== self) {
21602 if (!(node.name.definition().id in in_use_ids)) {
21603 compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", {
21604 name : node.name.name,
21605 file : node.name.start.file,
21606 line : node.name.start.line,
21607 col : node.name.start.col
21608 });
21609 return make_node(AST_EmptyStatement, node);
21610 }
21611 return node;
21612 }
21613 if (drop_vars && node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn && tt.parent().init === node)) {
21614 var def = node.definitions.filter(function(def){
21615 if (def.value) def.value = def.value.transform(tt);
21616 var sym = def.name.definition();
21617 if (sym.id in in_use_ids) return true;
21618 if (sym.orig[0] instanceof AST_SymbolCatch) {
21619 def.value = def.value && def.value.drop_side_effect_free(compressor);
21620 return true;
21621 }
21622 var w = {
21623 name : def.name.name,
21624 file : def.name.start.file,
21625 line : def.name.start.line,
21626 col : def.name.start.col
21627 };
21628 if (def.value && (def._unused_side_effects = def.value.drop_side_effect_free(compressor))) {
21629 compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
21630 return true;
21631 }
21632 compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", w);
21633 return false;
21634 });
21635 // place uninitialized names at the start
21636 def = mergeSort(def, function(a, b){
21637 if (!a.value && b.value) return -1;
21638 if (!b.value && a.value) return 1;
21639 return 0;
21640 });
21641 // for unused names whose initialization has
21642 // side effects, we can cascade the init. code
21643 // into the next one, or next statement.
21644 var side_effects = [];
21645 for (var i = 0; i < def.length;) {
21646 var x = def[i];
21647 if (x._unused_side_effects) {
21648 side_effects.push(x._unused_side_effects);
21649 def.splice(i, 1);
21650 } else {
21651 if (side_effects.length > 0) {
21652 side_effects.push(x.value);
21653 x.value = AST_Seq.from_array(side_effects);
21654 side_effects = [];
21655 }
21656 ++i;
21657 }
21658 }
21659 if (side_effects.length > 0) {
21660 side_effects = make_node(AST_BlockStatement, node, {
21661 body: [ make_node(AST_SimpleStatement, node, {
21662 body: AST_Seq.from_array(side_effects)
21663 }) ]
21664 });
21665 } else {
21666 side_effects = null;
21667 }
21668 if (def.length == 0 && !side_effects) {
21669 return make_node(AST_EmptyStatement, node);
21670 }
21671 if (def.length == 0) {
21672 return in_list ? MAP.splice(side_effects.body) : side_effects;
21673 }
21674 node.definitions = def;
21675 if (side_effects) {
21676 side_effects.body.unshift(node);
21677 return in_list ? MAP.splice(side_effects.body) : side_effects;
21678 }
21679 return node;
21680 }
21681 if (drop_vars && assign_as_unused
21682 && node instanceof AST_Assign
21683 && node.operator == "="
21684 && node.left instanceof AST_SymbolRef) {
21685 var def = node.left.definition();
21686 if (!(def.id in in_use_ids)
21687 && self.variables.get(def.name) === def) {
21688 return maintain_this_binding(tt.parent(), node, node.right.transform(tt));
21689 }
21690 }
21691 // certain combination of unused name + side effect leads to:
21692 // https://github.com/mishoo/UglifyJS2/issues/44
21693 // https://github.com/mishoo/UglifyJS2/issues/1830
21694 // that's an invalid AST.
21695 // We fix it at this stage by moving the `var` outside the `for`.
21696 if (node instanceof AST_For) {
21697 descend(node, this);
21698 if (node.init instanceof AST_BlockStatement) {
21699 var block = node.init;
21700 node.init = block.body.pop();
21701 block.body.push(node);
21702 return in_list ? MAP.splice(block.body) : block;
21703 } else if (is_empty(node.init)) {
21704 node.init = null;
21705 }
21706 return node;
21707 }
21708 if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) {
21709 descend(node, this);
21710 if (node.body instanceof AST_BlockStatement) {
21711 var block = node.body;
21712 node.body = block.body.pop();
21713 block.body.push(node);
21714 return in_list ? MAP.splice(block.body) : block;
21715 }
21716 return node;
21717 }
21718 if (node instanceof AST_Scope && node !== self)
21719 return node;
21720 }
21721 );
21722 self.transform(tt);
21723 }
21724 });
21725
21726 AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
21727 var self = this;
21728 if (compressor.has_directive("use asm")) return self;
21729 var hoist_funs = compressor.option("hoist_funs");
21730 var hoist_vars = compressor.option("hoist_vars");
21731 if (hoist_funs || hoist_vars) {
21732 var dirs = [];
21733 var hoisted = [];
21734 var vars = new Dictionary(), vars_found = 0, var_decl = 0;
21735 // let's count var_decl first, we seem to waste a lot of
21736 // space if we hoist `var` when there's only one.
21737 self.walk(new TreeWalker(function(node){
21738 if (node instanceof AST_Scope && node !== self)
21739 return true;
21740 if (node instanceof AST_Var) {
21741 ++var_decl;
21742 return true;
21743 }
21744 }));
21745 hoist_vars = hoist_vars && var_decl > 1;
21746 var tt = new TreeTransformer(
21747 function before(node) {
21748 if (node !== self) {
21749 if (node instanceof AST_Directive) {
21750 dirs.push(node);
21751 return make_node(AST_EmptyStatement, node);
21752 }
21753 if (node instanceof AST_Defun && hoist_funs) {
21754 hoisted.push(node);
21755 return make_node(AST_EmptyStatement, node);
21756 }
21757 if (node instanceof AST_Var && hoist_vars) {
21758 node.definitions.forEach(function(def){
21759 vars.set(def.name.name, def);
21760 ++vars_found;
21761 });
21762 var seq = node.to_assignments(compressor);
21763 var p = tt.parent();
21764 if (p instanceof AST_ForIn && p.init === node) {
21765 if (seq == null) {
21766 var def = node.definitions[0].name;
21767 return make_node(AST_SymbolRef, def, def);
21768 }
21769 return seq;
21770 }
21771 if (p instanceof AST_For && p.init === node) {
21772 return seq;
21773 }
21774 if (!seq) return make_node(AST_EmptyStatement, node);
21775 return make_node(AST_SimpleStatement, node, {
21776 body: seq
21777 });
21778 }
21779 if (node instanceof AST_Scope)
21780 return node; // to avoid descending in nested scopes
21781 }
21782 }
21783 );
21784 self = self.transform(tt);
21785 if (vars_found > 0) {
21786 // collect only vars which don't show up in self's arguments list
21787 var defs = [];
21788 vars.each(function(def, name){
21789 if (self instanceof AST_Lambda
21790 && find_if(function(x){ return x.name == def.name.name },
21791 self.argnames)) {
21792 vars.del(name);
21793 } else {
21794 def = def.clone();
21795 def.value = null;
21796 defs.push(def);
21797 vars.set(name, def);
21798 }
21799 });
21800 if (defs.length > 0) {
21801 // try to merge in assignments
21802 for (var i = 0; i < self.body.length;) {
21803 if (self.body[i] instanceof AST_SimpleStatement) {
21804 var expr = self.body[i].body, sym, assign;
21805 if (expr instanceof AST_Assign
21806 && expr.operator == "="
21807 && (sym = expr.left) instanceof AST_Symbol
21808 && vars.has(sym.name))
21809 {
21810 var def = vars.get(sym.name);
21811 if (def.value) break;
21812 def.value = expr.right;
21813 remove(defs, def);
21814 defs.push(def);
21815 self.body.splice(i, 1);
21816 continue;
21817 }
21818 if (expr instanceof AST_Seq
21819 && (assign = expr.car) instanceof AST_Assign
21820 && assign.operator == "="
21821 && (sym = assign.left) instanceof AST_Symbol
21822 && vars.has(sym.name))
21823 {
21824 var def = vars.get(sym.name);
21825 if (def.value) break;
21826 def.value = assign.right;
21827 remove(defs, def);
21828 defs.push(def);
21829 self.body[i].body = expr.cdr;
21830 continue;
21831 }
21832 }
21833 if (self.body[i] instanceof AST_EmptyStatement) {
21834 self.body.splice(i, 1);
21835 continue;
21836 }
21837 if (self.body[i] instanceof AST_BlockStatement) {
21838 var tmp = [ i, 1 ].concat(self.body[i].body);
21839 self.body.splice.apply(self.body, tmp);
21840 continue;
21841 }
21842 break;
21843 }
21844 defs = make_node(AST_Var, self, {
21845 definitions: defs
21846 });
21847 hoisted.push(defs);
21848 };
21849 }
21850 self.body = dirs.concat(hoisted, self.body);
21851 }
21852 return self;
21853 });
21854
21855 // drop_side_effect_free()
21856 // remove side-effect-free parts which only affects return value
21857 (function(def){
21858 // Drop side-effect-free elements from an array of expressions.
21859 // Returns an array of expressions with side-effects or null
21860 // if all elements were dropped. Note: original array may be
21861 // returned if nothing changed.
21862 function trim(nodes, compressor, first_in_statement) {
21863 var ret = [], changed = false;
21864 for (var i = 0, len = nodes.length; i < len; i++) {
21865 var node = nodes[i].drop_side_effect_free(compressor, first_in_statement);
21866 changed |= node !== nodes[i];
21867 if (node) {
21868 ret.push(node);
21869 first_in_statement = false;
21870 }
21871 }
21872 return changed ? ret.length ? ret : null : nodes;
21873 }
21874
21875 def(AST_Node, return_this);
21876 def(AST_Constant, return_null);
21877 def(AST_This, return_null);
21878 def(AST_Call, function(compressor, first_in_statement){
21879 if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) {
21880 if (this.expression instanceof AST_Function
21881 && (!this.expression.name || !this.expression.name.definition().references.length)) {
21882 var node = this.clone();
21883 node.expression = node.expression.process_expression(false, compressor);
21884 return node;
21885 }
21886 return this;
21887 }
21888 if (this.pure) {
21889 compressor.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start);
21890 this.pure.value = this.pure.value.replace(/[@#]__PURE__/g, ' ');
21891 }
21892 var args = trim(this.args, compressor, first_in_statement);
21893 return args && AST_Seq.from_array(args);
21894 });
21895 def(AST_Accessor, return_null);
21896 def(AST_Function, return_null);
21897 def(AST_Binary, function(compressor, first_in_statement){
21898 var right = this.right.drop_side_effect_free(compressor);
21899 if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
21900 switch (this.operator) {
21901 case "&&":
21902 case "||":
21903 if (right === this.right) return this;
21904 var node = this.clone();
21905 node.right = right;
21906 return node;
21907 default:
21908 var left = this.left.drop_side_effect_free(compressor, first_in_statement);
21909 if (!left) return this.right.drop_side_effect_free(compressor, first_in_statement);
21910 return make_node(AST_Seq, this, {
21911 car: left,
21912 cdr: right
21913 });
21914 }
21915 });
21916 def(AST_Assign, return_this);
21917 def(AST_Conditional, function(compressor){
21918 var consequent = this.consequent.drop_side_effect_free(compressor);
21919 var alternative = this.alternative.drop_side_effect_free(compressor);
21920 if (consequent === this.consequent && alternative === this.alternative) return this;
21921 if (!consequent) return alternative ? make_node(AST_Binary, this, {
21922 operator: "||",
21923 left: this.condition,
21924 right: alternative
21925 }) : this.condition.drop_side_effect_free(compressor);
21926 if (!alternative) return make_node(AST_Binary, this, {
21927 operator: "&&",
21928 left: this.condition,
21929 right: consequent
21930 });
21931 var node = this.clone();
21932 node.consequent = consequent;
21933 node.alternative = alternative;
21934 return node;
21935 });
21936 def(AST_Unary, function(compressor, first_in_statement){
21937 if (unary_side_effects(this.operator)) return this;
21938 if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) return null;
21939 var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
21940 if (first_in_statement
21941 && this instanceof AST_UnaryPrefix
21942 && is_iife_call(expression)) {
21943 if (expression === this.expression && this.operator.length === 1) return this;
21944 return make_node(AST_UnaryPrefix, this, {
21945 operator: this.operator.length === 1 ? this.operator : "!",
21946 expression: expression
21947 });
21948 }
21949 return expression;
21950 });
21951 def(AST_SymbolRef, function() {
21952 return this.undeclared() ? this : null;
21953 });
21954 def(AST_Object, function(compressor, first_in_statement){
21955 var values = trim(this.properties, compressor, first_in_statement);
21956 return values && AST_Seq.from_array(values);
21957 });
21958 def(AST_ObjectProperty, function(compressor, first_in_statement){
21959 return this.value.drop_side_effect_free(compressor, first_in_statement);
21960 });
21961 def(AST_Array, function(compressor, first_in_statement){
21962 var values = trim(this.elements, compressor, first_in_statement);
21963 return values && AST_Seq.from_array(values);
21964 });
21965 def(AST_Dot, function(compressor, first_in_statement){
21966 if (this.expression.may_throw_on_access(compressor)) return this;
21967 return this.expression.drop_side_effect_free(compressor, first_in_statement);
21968 });
21969 def(AST_Sub, function(compressor, first_in_statement){
21970 if (this.expression.may_throw_on_access(compressor)) return this;
21971 var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
21972 if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement);
21973 var property = this.property.drop_side_effect_free(compressor);
21974 if (!property) return expression;
21975 return make_node(AST_Seq, this, {
21976 car: expression,
21977 cdr: property
21978 });
21979 });
21980 def(AST_Seq, function(compressor){
21981 var cdr = this.cdr.drop_side_effect_free(compressor);
21982 if (cdr === this.cdr) return this;
21983 if (!cdr) return this.car;
21984 return make_node(AST_Seq, this, {
21985 car: this.car,
21986 cdr: cdr
21987 });
21988 });
21989 })(function(node, func){
21990 node.DEFMETHOD("drop_side_effect_free", func);
21991 });
21992
21993 OPT(AST_SimpleStatement, function(self, compressor){
21994 if (compressor.option("side_effects")) {
21995 var body = self.body;
21996 var node = body.drop_side_effect_free(compressor, true);
21997 if (!node) {
21998 compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
21999 return make_node(AST_EmptyStatement, self);
22000 }
22001 if (node !== body) {
22002 return make_node(AST_SimpleStatement, self, { body: node });
22003 }
22004 }
22005 return self;
22006 });
22007
22008 OPT(AST_DWLoop, function(self, compressor){
22009 if (!compressor.option("loops")) return self;
22010 var cond = self.condition.evaluate(compressor);
22011 if (cond !== self.condition) {
22012 if (cond) {
22013 return make_node(AST_For, self, {
22014 body: self.body
22015 });
22016 }
22017 if (compressor.option("dead_code") && self instanceof AST_While) {
22018 var a = [];
22019 extract_declarations_from_unreachable_code(compressor, self.body, a);
22020 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
22021 }
22022 if (self instanceof AST_Do) {
22023 var has_loop_control = false;
22024 var tw = new TreeWalker(function(node) {
22025 if (node instanceof AST_Scope || has_loop_control) return true;
22026 if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
22027 return has_loop_control = true;
22028 });
22029 var parent = compressor.parent();
22030 (parent instanceof AST_LabeledStatement ? parent : self).walk(tw);
22031 if (!has_loop_control) return self.body;
22032 }
22033 }
22034 if (self instanceof AST_While) {
22035 return make_node(AST_For, self, self).optimize(compressor);
22036 }
22037 return self;
22038 });
22039
22040 function if_break_in_loop(self, compressor) {
22041 function drop_it(rest) {
22042 rest = as_statement_array(rest);
22043 if (self.body instanceof AST_BlockStatement) {
22044 self.body = self.body.clone();
22045 self.body.body = rest.concat(self.body.body.slice(1));
22046 self.body = self.body.transform(compressor);
22047 } else {
22048 self.body = make_node(AST_BlockStatement, self.body, {
22049 body: rest
22050 }).transform(compressor);
22051 }
22052 if_break_in_loop(self, compressor);
22053 }
22054 var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
22055 if (first instanceof AST_If) {
22056 if (first.body instanceof AST_Break
22057 && compressor.loopcontrol_target(first.body) === compressor.self()) {
22058 if (self.condition) {
22059 self.condition = make_node(AST_Binary, self.condition, {
22060 left: self.condition,
22061 operator: "&&",
22062 right: first.condition.negate(compressor),
22063 });
22064 } else {
22065 self.condition = first.condition.negate(compressor);
22066 }
22067 drop_it(first.alternative);
22068 }
22069 else if (first.alternative instanceof AST_Break
22070 && compressor.loopcontrol_target(first.alternative) === compressor.self()) {
22071 if (self.condition) {
22072 self.condition = make_node(AST_Binary, self.condition, {
22073 left: self.condition,
22074 operator: "&&",
22075 right: first.condition,
22076 });
22077 } else {
22078 self.condition = first.condition;
22079 }
22080 drop_it(first.body);
22081 }
22082 }
22083 };
22084
22085 OPT(AST_For, function(self, compressor){
22086 if (!compressor.option("loops")) return self;
22087 if (self.condition) {
22088 var cond = self.condition.evaluate(compressor);
22089 if (compressor.option("dead_code") && !cond) {
22090 var a = [];
22091 if (self.init instanceof AST_Statement) {
22092 a.push(self.init);
22093 }
22094 else if (self.init) {
22095 a.push(make_node(AST_SimpleStatement, self.init, {
22096 body: self.init
22097 }));
22098 }
22099 extract_declarations_from_unreachable_code(compressor, self.body, a);
22100 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
22101 }
22102 if (cond !== self.condition) {
22103 cond = make_node_from_constant(cond, self.condition).transform(compressor);
22104 self.condition = best_of_expression(cond, self.condition);
22105 }
22106 }
22107 if_break_in_loop(self, compressor);
22108 return self;
22109 });
22110
22111 OPT(AST_If, function(self, compressor){
22112 if (is_empty(self.alternative)) self.alternative = null;
22113
22114 if (!compressor.option("conditionals")) return self;
22115 // if condition can be statically determined, warn and drop
22116 // one of the blocks. note, statically determined implies
22117 // “has no side effects”; also it doesn't work for cases like
22118 // `x && true`, though it probably should.
22119 var cond = self.condition.evaluate(compressor);
22120 if (cond !== self.condition) {
22121 if (cond) {
22122 compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
22123 if (compressor.option("dead_code")) {
22124 var a = [];
22125 if (self.alternative) {
22126 extract_declarations_from_unreachable_code(compressor, self.alternative, a);
22127 }
22128 a.push(self.body);
22129 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
22130 }
22131 } else {
22132 compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
22133 if (compressor.option("dead_code")) {
22134 var a = [];
22135 extract_declarations_from_unreachable_code(compressor, self.body, a);
22136 if (self.alternative) a.push(self.alternative);
22137 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
22138 }
22139 }
22140 cond = make_node_from_constant(cond, self.condition).transform(compressor);
22141 self.condition = best_of_expression(cond, self.condition);
22142 }
22143 var negated = self.condition.negate(compressor);
22144 var self_condition_length = self.condition.print_to_string().length;
22145 var negated_length = negated.print_to_string().length;
22146 var negated_is_best = negated_length < self_condition_length;
22147 if (self.alternative && negated_is_best) {
22148 negated_is_best = false; // because we already do the switch here.
22149 // no need to swap values of self_condition_length and negated_length
22150 // here because they are only used in an equality comparison later on.
22151 self.condition = negated;
22152 var tmp = self.body;
22153 self.body = self.alternative || make_node(AST_EmptyStatement, self);
22154 self.alternative = tmp;
22155 }
22156 if (is_empty(self.body) && is_empty(self.alternative)) {
22157 return make_node(AST_SimpleStatement, self.condition, {
22158 body: self.condition.clone()
22159 }).optimize(compressor);
22160 }
22161 if (self.body instanceof AST_SimpleStatement
22162 && self.alternative instanceof AST_SimpleStatement) {
22163 return make_node(AST_SimpleStatement, self, {
22164 body: make_node(AST_Conditional, self, {
22165 condition : self.condition,
22166 consequent : self.body.body,
22167 alternative : self.alternative.body
22168 })
22169 }).optimize(compressor);
22170 }
22171 if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
22172 if (self_condition_length === negated_length && !negated_is_best
22173 && self.condition instanceof AST_Binary && self.condition.operator == "||") {
22174 // although the code length of self.condition and negated are the same,
22175 // negated does not require additional surrounding parentheses.
22176 // see https://github.com/mishoo/UglifyJS2/issues/979
22177 negated_is_best = true;
22178 }
22179 if (negated_is_best) return make_node(AST_SimpleStatement, self, {
22180 body: make_node(AST_Binary, self, {
22181 operator : "||",
22182 left : negated,
22183 right : self.body.body
22184 })
22185 }).optimize(compressor);
22186 return make_node(AST_SimpleStatement, self, {
22187 body: make_node(AST_Binary, self, {
22188 operator : "&&",
22189 left : self.condition,
22190 right : self.body.body
22191 })
22192 }).optimize(compressor);
22193 }
22194 if (self.body instanceof AST_EmptyStatement
22195 && self.alternative instanceof AST_SimpleStatement) {
22196 return make_node(AST_SimpleStatement, self, {
22197 body: make_node(AST_Binary, self, {
22198 operator : "||",
22199 left : self.condition,
22200 right : self.alternative.body
22201 })
22202 }).optimize(compressor);
22203 }
22204 if (self.body instanceof AST_Exit
22205 && self.alternative instanceof AST_Exit
22206 && self.body.TYPE == self.alternative.TYPE) {
22207 return make_node(self.body.CTOR, self, {
22208 value: make_node(AST_Conditional, self, {
22209 condition : self.condition,
22210 consequent : self.body.value || make_node(AST_Undefined, self.body),
22211 alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
22212 }).transform(compressor)
22213 }).optimize(compressor);
22214 }
22215 if (self.body instanceof AST_If
22216 && !self.body.alternative
22217 && !self.alternative) {
22218 self = make_node(AST_If, self, {
22219 condition: make_node(AST_Binary, self.condition, {
22220 operator: "&&",
22221 left: self.condition,
22222 right: self.body.condition
22223 }),
22224 body: self.body.body,
22225 alternative: null
22226 });
22227 }
22228 if (aborts(self.body)) {
22229 if (self.alternative) {
22230 var alt = self.alternative;
22231 self.alternative = null;
22232 return make_node(AST_BlockStatement, self, {
22233 body: [ self, alt ]
22234 }).optimize(compressor);
22235 }
22236 }
22237 if (aborts(self.alternative)) {
22238 var body = self.body;
22239 self.body = self.alternative;
22240 self.condition = negated_is_best ? negated : self.condition.negate(compressor);
22241 self.alternative = null;
22242 return make_node(AST_BlockStatement, self, {
22243 body: [ self, body ]
22244 }).optimize(compressor);
22245 }
22246 return self;
22247 });
22248
22249 OPT(AST_Switch, function(self, compressor){
22250 if (!compressor.option("switches")) return self;
22251 var branch;
22252 var value = self.expression.evaluate(compressor);
22253 if (value !== self.expression) {
22254 var expression = make_node_from_constant(value, self.expression).transform(compressor);
22255 self.expression = best_of_expression(expression, self.expression);
22256 }
22257 if (!compressor.option("dead_code")) return self;
22258 var decl = [];
22259 var body = [];
22260 var default_branch;
22261 var exact_match;
22262 for (var i = 0, len = self.body.length; i < len && !exact_match; i++) {
22263 branch = self.body[i];
22264 if (branch instanceof AST_Default) {
22265 if (!default_branch) {
22266 default_branch = branch;
22267 } else {
22268 eliminate_branch(branch, body[body.length - 1]);
22269 }
22270 } else if (value !== self.expression) {
22271 var exp = branch.expression.evaluate(compressor);
22272 if (exp === value) {
22273 exact_match = branch;
22274 if (default_branch) {
22275 var default_index = body.indexOf(default_branch);
22276 body.splice(default_index, 1);
22277 eliminate_branch(default_branch, body[default_index - 1]);
22278 default_branch = null;
22279 }
22280 } else if (exp !== branch.expression) {
22281 eliminate_branch(branch, body[body.length - 1]);
22282 continue;
22283 }
22284 }
22285 if (aborts(branch)) {
22286 var prev = body[body.length - 1];
22287 if (aborts(prev) && prev.body.length == branch.body.length
22288 && make_node(AST_BlockStatement, prev, prev).equivalent_to(make_node(AST_BlockStatement, branch, branch))) {
22289 prev.body = [];
22290 }
22291 }
22292 body.push(branch);
22293 }
22294 while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
22295 if (body.length > 0) {
22296 body[0].body = decl.concat(body[0].body);
22297 }
22298 self.body = body;
22299 while (branch = body[body.length - 1]) {
22300 var stat = branch.body[branch.body.length - 1];
22301 if (stat instanceof AST_Break && compressor.loopcontrol_target(stat) === self)
22302 branch.body.pop();
22303 if (branch.body.length || branch instanceof AST_Case
22304 && (default_branch || branch.expression.has_side_effects(compressor))) break;
22305 if (body.pop() === default_branch) default_branch = null;
22306 }
22307 if (body.length == 0) {
22308 return make_node(AST_BlockStatement, self, {
22309 body: decl.concat(make_node(AST_SimpleStatement, self.expression, {
22310 body: self.expression
22311 }))
22312 }).optimize(compressor);
22313 }
22314 if (body.length == 1 && (body[0] === exact_match || body[0] === default_branch)) {
22315 var has_break = false;
22316 var tw = new TreeWalker(function(node) {
22317 if (has_break
22318 || node instanceof AST_Lambda
22319 || node instanceof AST_SimpleStatement) return true;
22320 if (node instanceof AST_Break && tw.loopcontrol_target(node) === self)
22321 has_break = true;
22322 });
22323 self.walk(tw);
22324 if (!has_break) {
22325 body = body[0].body.slice();
22326 body.unshift(make_node(AST_SimpleStatement, self.expression, {
22327 body: self.expression
22328 }));
22329 return make_node(AST_BlockStatement, self, {
22330 body: body
22331 }).optimize(compressor);
22332 }
22333 }
22334 return self;
22335
22336 function eliminate_branch(branch, prev) {
22337 if (prev && !aborts(prev)) {
22338 prev.body = prev.body.concat(branch.body);
22339 } else {
22340 extract_declarations_from_unreachable_code(compressor, branch, decl);
22341 }
22342 }
22343 });
22344
22345 OPT(AST_Try, function(self, compressor){
22346 self.body = tighten_body(self.body, compressor);
22347 if (self.bcatch && self.bfinally && all(self.bfinally.body, is_empty)) self.bfinally = null;
22348 if (all(self.body, is_empty)) {
22349 var body = [];
22350 if (self.bcatch) extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
22351 if (self.bfinally) body = body.concat(self.bfinally.body);
22352 return make_node(AST_BlockStatement, self, {
22353 body: body
22354 }).optimize(compressor);
22355 }
22356 return self;
22357 });
22358
22359 AST_Definitions.DEFMETHOD("remove_initializers", function(){
22360 this.definitions.forEach(function(def){ def.value = null });
22361 });
22362
22363 AST_Definitions.DEFMETHOD("to_assignments", function(compressor){
22364 var reduce_vars = compressor.option("reduce_vars");
22365 var assignments = this.definitions.reduce(function(a, def){
22366 if (def.value) {
22367 var name = make_node(AST_SymbolRef, def.name, def.name);
22368 a.push(make_node(AST_Assign, def, {
22369 operator : "=",
22370 left : name,
22371 right : def.value
22372 }));
22373 if (reduce_vars) name.definition().fixed = false;
22374 }
22375 return a;
22376 }, []);
22377 if (assignments.length == 0) return null;
22378 return AST_Seq.from_array(assignments);
22379 });
22380
22381 OPT(AST_Definitions, function(self, compressor){
22382 if (self.definitions.length == 0)
22383 return make_node(AST_EmptyStatement, self);
22384 return self;
22385 });
22386
22387 OPT(AST_Call, function(self, compressor){
22388 var exp = self.expression;
22389 if (compressor.option("reduce_vars")
22390 && exp instanceof AST_SymbolRef) {
22391 var def = exp.definition();
22392 var fixed = exp.fixed_value();
22393 if (fixed instanceof AST_Defun) {
22394 def.fixed = fixed = make_node(AST_Function, fixed, fixed).clone(true);
22395 }
22396 if (fixed instanceof AST_Function) {
22397 exp = fixed;
22398 if (compressor.option("unused")
22399 && def.references.length == 1
22400 && !(def.scope.uses_arguments
22401 && def.orig[0] instanceof AST_SymbolFunarg)
22402 && !def.scope.uses_eval
22403 && compressor.find_parent(AST_Scope) === def.scope) {
22404 self.expression = exp;
22405 }
22406 }
22407 }
22408 if (compressor.option("unused")
22409 && exp instanceof AST_Function
22410 && !exp.uses_arguments
22411 && !exp.uses_eval) {
22412 var pos = 0, last = 0;
22413 for (var i = 0, len = self.args.length; i < len; i++) {
22414 var trim = i >= exp.argnames.length;
22415 if (trim || exp.argnames[i].__unused) {
22416 var node = self.args[i].drop_side_effect_free(compressor);
22417 if (node) {
22418 self.args[pos++] = node;
22419 } else if (!trim) {
22420 self.args[pos++] = make_node(AST_Number, self.args[i], {
22421 value: 0
22422 });
22423 continue;
22424 }
22425 } else {
22426 self.args[pos++] = self.args[i];
22427 }
22428 last = pos;
22429 }
22430 self.args.length = last;
22431 }
22432 if (compressor.option("unsafe")) {
22433 if (exp instanceof AST_SymbolRef && exp.undeclared()) {
22434 switch (exp.name) {
22435 case "Array":
22436 if (self.args.length != 1) {
22437 return make_node(AST_Array, self, {
22438 elements: self.args
22439 }).optimize(compressor);
22440 }
22441 break;
22442 case "Object":
22443 if (self.args.length == 0) {
22444 return make_node(AST_Object, self, {
22445 properties: []
22446 });
22447 }
22448 break;
22449 case "String":
22450 if (self.args.length == 0) return make_node(AST_String, self, {
22451 value: ""
22452 });
22453 if (self.args.length <= 1) return make_node(AST_Binary, self, {
22454 left: self.args[0],
22455 operator: "+",
22456 right: make_node(AST_String, self, { value: "" })
22457 }).optimize(compressor);
22458 break;
22459 case "Number":
22460 if (self.args.length == 0) return make_node(AST_Number, self, {
22461 value: 0
22462 });
22463 if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
22464 expression: self.args[0],
22465 operator: "+"
22466 }).optimize(compressor);
22467 case "Boolean":
22468 if (self.args.length == 0) return make_node(AST_False, self);
22469 if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
22470 expression: make_node(AST_UnaryPrefix, self, {
22471 expression: self.args[0],
22472 operator: "!"
22473 }),
22474 operator: "!"
22475 }).optimize(compressor);
22476 break;
22477 case "Function":
22478 // new Function() => function(){}
22479 if (self.args.length == 0) return make_node(AST_Function, self, {
22480 argnames: [],
22481 body: []
22482 });
22483 if (all(self.args, function(x){ return x instanceof AST_String })) {
22484 // quite a corner-case, but we can handle it:
22485 // https://github.com/mishoo/UglifyJS2/issues/203
22486 // if the code argument is a constant, then we can minify it.
22487 try {
22488 var code = "(function(" + self.args.slice(0, -1).map(function(arg){
22489 return arg.value;
22490 }).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
22491 var ast = parse(code);
22492 ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
22493 var comp = new Compressor(compressor.options);
22494 ast = ast.transform(comp);
22495 ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
22496 ast.mangle_names();
22497 var fun;
22498 try {
22499 ast.walk(new TreeWalker(function(node){
22500 if (node instanceof AST_Lambda) {
22501 fun = node;
22502 throw ast;
22503 }
22504 }));
22505 } catch(ex) {
22506 if (ex !== ast) throw ex;
22507 };
22508 if (!fun) return self;
22509 var args = fun.argnames.map(function(arg, i){
22510 return make_node(AST_String, self.args[i], {
22511 value: arg.print_to_string()
22512 });
22513 });
22514 var code = OutputStream();
22515 AST_BlockStatement.prototype._codegen.call(fun, fun, code);
22516 code = code.toString().replace(/^\{|\}$/g, "");
22517 args.push(make_node(AST_String, self.args[self.args.length - 1], {
22518 value: code
22519 }));
22520 self.args = args;
22521 return self;
22522 } catch(ex) {
22523 if (ex instanceof JS_Parse_Error) {
22524 compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
22525 compressor.warn(ex.toString());
22526 } else {
22527 console.log(ex);
22528 throw ex;
22529 }
22530 }
22531 }
22532 break;
22533 }
22534 }
22535 else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
22536 return make_node(AST_Binary, self, {
22537 left: make_node(AST_String, self, { value: "" }),
22538 operator: "+",
22539 right: exp.expression
22540 }).optimize(compressor);
22541 }
22542 else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
22543 var separator;
22544 if (self.args.length > 0) {
22545 separator = self.args[0].evaluate(compressor);
22546 if (separator === self.args[0]) break EXIT; // not a constant
22547 }
22548 var elements = [];
22549 var consts = [];
22550 exp.expression.elements.forEach(function(el) {
22551 var value = el.evaluate(compressor);
22552 if (value !== el) {
22553 consts.push(value);
22554 } else {
22555 if (consts.length > 0) {
22556 elements.push(make_node(AST_String, self, {
22557 value: consts.join(separator)
22558 }));
22559 consts.length = 0;
22560 }
22561 elements.push(el);
22562 }
22563 });
22564 if (consts.length > 0) {
22565 elements.push(make_node(AST_String, self, {
22566 value: consts.join(separator)
22567 }));
22568 }
22569 if (elements.length == 0) return make_node(AST_String, self, { value: "" });
22570 if (elements.length == 1) {
22571 if (elements[0].is_string(compressor)) {
22572 return elements[0];
22573 }
22574 return make_node(AST_Binary, elements[0], {
22575 operator : "+",
22576 left : make_node(AST_String, self, { value: "" }),
22577 right : elements[0]
22578 });
22579 }
22580 if (separator == "") {
22581 var first;
22582 if (elements[0].is_string(compressor)
22583 || elements[1].is_string(compressor)) {
22584 first = elements.shift();
22585 } else {
22586 first = make_node(AST_String, self, { value: "" });
22587 }
22588 return elements.reduce(function(prev, el){
22589 return make_node(AST_Binary, el, {
22590 operator : "+",
22591 left : prev,
22592 right : el
22593 });
22594 }, first).optimize(compressor);
22595 }
22596 // need this awkward cloning to not affect original element
22597 // best_of will decide which one to get through.
22598 var node = self.clone();
22599 node.expression = node.expression.clone();
22600 node.expression.expression = node.expression.expression.clone();
22601 node.expression.expression.elements = elements;
22602 return best_of(compressor, self, node);
22603 }
22604 else if (exp instanceof AST_Dot && exp.expression.is_string(compressor) && exp.property == "charAt") {
22605 var arg = self.args[0];
22606 var index = arg ? arg.evaluate(compressor) : 0;
22607 if (index !== arg) {
22608 return make_node(AST_Sub, exp, {
22609 expression: exp.expression,
22610 property: make_node_from_constant(index | 0, arg || exp)
22611 }).optimize(compressor);
22612 }
22613 }
22614 }
22615 if (exp instanceof AST_Function) {
22616 if (exp.body[0] instanceof AST_Return) {
22617 var value = exp.body[0].value;
22618 if (!value || value.is_constant()) {
22619 var args = self.args.concat(value || make_node(AST_Undefined, self));
22620 return AST_Seq.from_array(args).transform(compressor);
22621 }
22622 }
22623 if (compressor.option("side_effects") && all(exp.body, is_empty)) {
22624 var args = self.args.concat(make_node(AST_Undefined, self));
22625 return AST_Seq.from_array(args).transform(compressor);
22626 }
22627 }
22628 if (compressor.option("drop_console")) {
22629 if (exp instanceof AST_PropAccess) {
22630 var name = exp.expression;
22631 while (name.expression) {
22632 name = name.expression;
22633 }
22634 if (name instanceof AST_SymbolRef
22635 && name.name == "console"
22636 && name.undeclared()) {
22637 return make_node(AST_Undefined, self).optimize(compressor);
22638 }
22639 }
22640 }
22641 if (compressor.option("negate_iife")
22642 && compressor.parent() instanceof AST_SimpleStatement
22643 && is_iife_call(self)) {
22644 return self.negate(compressor, true);
22645 }
22646 return self;
22647 });
22648
22649 OPT(AST_New, function(self, compressor){
22650 if (compressor.option("unsafe")) {
22651 var exp = self.expression;
22652 if (exp instanceof AST_SymbolRef && exp.undeclared()) {
22653 switch (exp.name) {
22654 case "Object":
22655 case "RegExp":
22656 case "Function":
22657 case "Error":
22658 case "Array":
22659 return make_node(AST_Call, self, self).transform(compressor);
22660 }
22661 }
22662 }
22663 return self;
22664 });
22665
22666 OPT(AST_Seq, function(self, compressor){
22667 if (!compressor.option("side_effects"))
22668 return self;
22669 self.car = self.car.drop_side_effect_free(compressor, first_in_statement(compressor));
22670 if (!self.car) return maintain_this_binding(compressor.parent(), self, self.cdr);
22671 if (compressor.option("cascade")) {
22672 var left;
22673 if (self.car instanceof AST_Assign
22674 && !self.car.left.has_side_effects(compressor)) {
22675 left = self.car.left;
22676 } else if (self.car instanceof AST_Unary
22677 && (self.car.operator == "++" || self.car.operator == "--")) {
22678 left = self.car.expression;
22679 }
22680 if (left
22681 && !(left instanceof AST_SymbolRef
22682 && (left.definition().orig[0] instanceof AST_SymbolLambda
22683 || is_reference_const(left)))) {
22684 var parent, field;
22685 var cdr = self.cdr;
22686 while (true) {
22687 if (cdr.equivalent_to(left)) {
22688 var car = self.car instanceof AST_UnaryPostfix ? make_node(AST_UnaryPrefix, self.car, {
22689 operator: self.car.operator,
22690 expression: left
22691 }) : self.car;
22692 if (parent) {
22693 parent[field] = car;
22694 return self.cdr;
22695 }
22696 return car;
22697 }
22698 if (cdr instanceof AST_Binary && !(cdr instanceof AST_Assign)) {
22699 if (cdr.left.is_constant()) {
22700 if (cdr.operator == "||" || cdr.operator == "&&") break;
22701 field = "right";
22702 } else {
22703 field = "left";
22704 }
22705 } else if (cdr instanceof AST_Call
22706 || cdr instanceof AST_Unary && !unary_side_effects(cdr.operator)) {
22707 field = "expression";
22708 } else break;
22709 parent = cdr;
22710 cdr = cdr[field];
22711 }
22712 }
22713 }
22714 if (is_undefined(self.cdr, compressor)) {
22715 return make_node(AST_UnaryPrefix, self, {
22716 operator : "void",
22717 expression : self.car
22718 });
22719 }
22720 return self;
22721 });
22722
22723 AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
22724 if (compressor.option("sequences")) {
22725 if (this.expression instanceof AST_Seq) {
22726 var seq = this.expression;
22727 var x = seq.to_array();
22728 var e = this.clone();
22729 e.expression = x.pop();
22730 x.push(e);
22731 seq = AST_Seq.from_array(x).transform(compressor);
22732 return seq;
22733 }
22734 }
22735 return this;
22736 });
22737
22738 OPT(AST_UnaryPostfix, function(self, compressor){
22739 return self.lift_sequences(compressor);
22740 });
22741
22742 OPT(AST_UnaryPrefix, function(self, compressor){
22743 var e = self.expression;
22744 if (self.operator == "delete"
22745 && !(e instanceof AST_SymbolRef
22746 || e instanceof AST_PropAccess
22747 || e instanceof AST_NaN
22748 || e instanceof AST_Infinity
22749 || e instanceof AST_Undefined)) {
22750 if (e instanceof AST_Seq) {
22751 e = e.to_array();
22752 e.push(make_node(AST_True, self));
22753 return AST_Seq.from_array(e).optimize(compressor);
22754 }
22755 return make_node(AST_Seq, self, {
22756 car: e,
22757 cdr: make_node(AST_True, self)
22758 }).optimize(compressor);
22759 }
22760 var seq = self.lift_sequences(compressor);
22761 if (seq !== self) {
22762 return seq;
22763 }
22764 if (compressor.option("side_effects") && self.operator == "void") {
22765 e = e.drop_side_effect_free(compressor);
22766 if (e) {
22767 self.expression = e;
22768 return self;
22769 } else {
22770 return make_node(AST_Undefined, self).optimize(compressor);
22771 }
22772 }
22773 if (compressor.option("booleans") && compressor.in_boolean_context()) {
22774 switch (self.operator) {
22775 case "!":
22776 if (e instanceof AST_UnaryPrefix && e.operator == "!") {
22777 // !!foo ==> foo, if we're in boolean context
22778 return e.expression;
22779 }
22780 if (e instanceof AST_Binary) {
22781 self = best_of(compressor, self, e.negate(compressor, first_in_statement(compressor)));
22782 }
22783 break;
22784 case "typeof":
22785 // typeof always returns a non-empty string, thus it's
22786 // always true in booleans
22787 compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
22788 return (e instanceof AST_SymbolRef ? make_node(AST_True, self) : make_node(AST_Seq, self, {
22789 car: e,
22790 cdr: make_node(AST_True, self)
22791 })).optimize(compressor);
22792 }
22793 }
22794 if (self.operator == "-" && e instanceof AST_Infinity) {
22795 e = e.transform(compressor);
22796 }
22797 if (e instanceof AST_Binary
22798 && (self.operator == "+" || self.operator == "-")
22799 && (e.operator == "*" || e.operator == "/" || e.operator == "%")) {
22800 return make_node(AST_Binary, self, {
22801 operator: e.operator,
22802 left: make_node(AST_UnaryPrefix, e.left, {
22803 operator: self.operator,
22804 expression: e.left
22805 }),
22806 right: e.right
22807 });
22808 }
22809 // avoids infinite recursion of numerals
22810 if (self.operator != "-"
22811 || !(e instanceof AST_Number || e instanceof AST_Infinity)) {
22812 var ev = self.evaluate(compressor);
22813 if (ev !== self) {
22814 ev = make_node_from_constant(ev, self).optimize(compressor);
22815 return best_of(compressor, ev, self);
22816 }
22817 }
22818 return self;
22819 });
22820
22821 AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
22822 if (compressor.option("sequences")) {
22823 if (this.left instanceof AST_Seq) {
22824 var seq = this.left;
22825 var x = seq.to_array();
22826 var e = this.clone();
22827 e.left = x.pop();
22828 x.push(e);
22829 return AST_Seq.from_array(x).optimize(compressor);
22830 }
22831 if (this.right instanceof AST_Seq && !this.left.has_side_effects(compressor)) {
22832 var assign = this.operator == "=" && this.left instanceof AST_SymbolRef;
22833 var root = this.right.clone();
22834 var cursor, seq = root;
22835 while (assign || !seq.car.has_side_effects(compressor)) {
22836 cursor = seq;
22837 if (seq.cdr instanceof AST_Seq) {
22838 seq = seq.cdr = seq.cdr.clone();
22839 } else break;
22840 }
22841 if (cursor) {
22842 var e = this.clone();
22843 e.right = cursor.cdr;
22844 cursor.cdr = e;
22845 return root.optimize(compressor);
22846 }
22847 }
22848 }
22849 return this;
22850 });
22851
22852 var commutativeOperators = makePredicate("== === != !== * & | ^");
22853
22854 OPT(AST_Binary, function(self, compressor){
22855 function reversible() {
22856 return self.left.is_constant()
22857 || self.right.is_constant()
22858 || !self.left.has_side_effects(compressor)
22859 && !self.right.has_side_effects(compressor);
22860 }
22861 function reverse(op) {
22862 if (reversible()) {
22863 if (op) self.operator = op;
22864 var tmp = self.left;
22865 self.left = self.right;
22866 self.right = tmp;
22867 }
22868 }
22869 if (commutativeOperators(self.operator)) {
22870 if (self.right.is_constant()
22871 && !self.left.is_constant()) {
22872 // if right is a constant, whatever side effects the
22873 // left side might have could not influence the
22874 // result. hence, force switch.
22875
22876 if (!(self.left instanceof AST_Binary
22877 && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
22878 reverse();
22879 }
22880 }
22881 }
22882 self = self.lift_sequences(compressor);
22883 if (compressor.option("comparisons")) switch (self.operator) {
22884 case "===":
22885 case "!==":
22886 if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
22887 (self.left.is_number(compressor) && self.right.is_number(compressor)) ||
22888 (self.left.is_boolean() && self.right.is_boolean())) {
22889 self.operator = self.operator.substr(0, 2);
22890 }
22891 // XXX: intentionally falling down to the next case
22892 case "==":
22893 case "!=":
22894 // "undefined" == typeof x => undefined === x
22895 if (self.left instanceof AST_String
22896 && self.left.value == "undefined"
22897 && self.right instanceof AST_UnaryPrefix
22898 && self.right.operator == "typeof") {
22899 var expr = self.right.expression;
22900 if (expr instanceof AST_SymbolRef ? !expr.undeclared()
22901 : !(expr instanceof AST_PropAccess) || compressor.option("screw_ie8")) {
22902 self.right = expr;
22903 self.left = make_node(AST_Undefined, self.left).optimize(compressor);
22904 if (self.operator.length == 2) self.operator += "=";
22905 }
22906 }
22907 break;
22908 }
22909 if (compressor.option("booleans") && self.operator == "+" && compressor.in_boolean_context()) {
22910 var ll = self.left.evaluate(compressor);
22911 var rr = self.right.evaluate(compressor);
22912 if (ll && typeof ll == "string") {
22913 compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
22914 return make_node(AST_Seq, self, {
22915 car: self.right,
22916 cdr: make_node(AST_True, self)
22917 }).optimize(compressor);
22918 }
22919 if (rr && typeof rr == "string") {
22920 compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
22921 return make_node(AST_Seq, self, {
22922 car: self.left,
22923 cdr: make_node(AST_True, self)
22924 }).optimize(compressor);
22925 }
22926 }
22927 if (compressor.option("comparisons") && self.is_boolean()) {
22928 if (!(compressor.parent() instanceof AST_Binary)
22929 || compressor.parent() instanceof AST_Assign) {
22930 var negated = make_node(AST_UnaryPrefix, self, {
22931 operator: "!",
22932 expression: self.negate(compressor, first_in_statement(compressor))
22933 });
22934 self = best_of(compressor, self, negated);
22935 }
22936 if (compressor.option("unsafe_comps")) {
22937 switch (self.operator) {
22938 case "<": reverse(">"); break;
22939 case "<=": reverse(">="); break;
22940 }
22941 }
22942 }
22943 if (self.operator == "+") {
22944 if (self.right instanceof AST_String
22945 && self.right.getValue() == ""
22946 && self.left.is_string(compressor)) {
22947 return self.left;
22948 }
22949 if (self.left instanceof AST_String
22950 && self.left.getValue() == ""
22951 && self.right.is_string(compressor)) {
22952 return self.right;
22953 }
22954 if (self.left instanceof AST_Binary
22955 && self.left.operator == "+"
22956 && self.left.left instanceof AST_String
22957 && self.left.left.getValue() == ""
22958 && self.right.is_string(compressor)) {
22959 self.left = self.left.right;
22960 return self.transform(compressor);
22961 }
22962 }
22963 if (compressor.option("evaluate")) {
22964 switch (self.operator) {
22965 case "&&":
22966 var ll = self.left.evaluate(compressor);
22967 if (!ll) {
22968 compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
22969 return maintain_this_binding(compressor.parent(), self, self.left).optimize(compressor);
22970 } else if (ll !== self.left) {
22971 compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
22972 return maintain_this_binding(compressor.parent(), self, self.right).optimize(compressor);
22973 }
22974 if (compressor.option("booleans") && compressor.in_boolean_context()) {
22975 var rr = self.right.evaluate(compressor);
22976 if (!rr) {
22977 compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
22978 return make_node(AST_Seq, self, {
22979 car: self.left,
22980 cdr: make_node(AST_False, self)
22981 }).optimize(compressor);
22982 } else if (rr !== self.right) {
22983 compressor.warn("Dropping side-effect-free && in boolean context [{file}:{line},{col}]", self.start);
22984 return self.left.optimize(compressor);
22985 }
22986 }
22987 break;
22988 case "||":
22989 var ll = self.left.evaluate(compressor);
22990 if (!ll) {
22991 compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
22992 return maintain_this_binding(compressor.parent(), self, self.right).optimize(compressor);
22993 } else if (ll !== self.left) {
22994 compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
22995 return maintain_this_binding(compressor.parent(), self, self.left).optimize(compressor);
22996 }
22997 if (compressor.option("booleans") && compressor.in_boolean_context()) {
22998 var rr = self.right.evaluate(compressor);
22999 if (!rr) {
23000 compressor.warn("Dropping side-effect-free || in boolean context [{file}:{line},{col}]", self.start);
23001 return self.left.optimize(compressor);
23002 } else if (rr !== self.right) {
23003 compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
23004 return make_node(AST_Seq, self, {
23005 car: self.left,
23006 cdr: make_node(AST_True, self)
23007 }).optimize(compressor);
23008 }
23009 }
23010 break;
23011 }
23012 var associative = true;
23013 switch (self.operator) {
23014 case "+":
23015 // "foo" + ("bar" + x) => "foobar" + x
23016 if (self.left instanceof AST_Constant
23017 && self.right instanceof AST_Binary
23018 && self.right.operator == "+"
23019 && self.right.left instanceof AST_Constant
23020 && self.right.is_string(compressor)) {
23021 self = make_node(AST_Binary, self, {
23022 operator: "+",
23023 left: make_node(AST_String, self.left, {
23024 value: "" + self.left.getValue() + self.right.left.getValue(),
23025 start: self.left.start,
23026 end: self.right.left.end
23027 }),
23028 right: self.right.right
23029 });
23030 }
23031 // (x + "foo") + "bar" => x + "foobar"
23032 if (self.right instanceof AST_Constant
23033 && self.left instanceof AST_Binary
23034 && self.left.operator == "+"
23035 && self.left.right instanceof AST_Constant
23036 && self.left.is_string(compressor)) {
23037 self = make_node(AST_Binary, self, {
23038 operator: "+",
23039 left: self.left.left,
23040 right: make_node(AST_String, self.right, {
23041 value: "" + self.left.right.getValue() + self.right.getValue(),
23042 start: self.left.right.start,
23043 end: self.right.end
23044 })
23045 });
23046 }
23047 // (x + "foo") + ("bar" + y) => (x + "foobar") + y
23048 if (self.left instanceof AST_Binary
23049 && self.left.operator == "+"
23050 && self.left.is_string(compressor)
23051 && self.left.right instanceof AST_Constant
23052 && self.right instanceof AST_Binary
23053 && self.right.operator == "+"
23054 && self.right.left instanceof AST_Constant
23055 && self.right.is_string(compressor)) {
23056 self = make_node(AST_Binary, self, {
23057 operator: "+",
23058 left: make_node(AST_Binary, self.left, {
23059 operator: "+",
23060 left: self.left.left,
23061 right: make_node(AST_String, self.left.right, {
23062 value: "" + self.left.right.getValue() + self.right.left.getValue(),
23063 start: self.left.right.start,
23064 end: self.right.left.end
23065 })
23066 }),
23067 right: self.right.right
23068 });
23069 }
23070 // a + -b => a - b
23071 if (self.right instanceof AST_UnaryPrefix
23072 && self.right.operator == "-"
23073 && self.left.is_number(compressor)) {
23074 self = make_node(AST_Binary, self, {
23075 operator: "-",
23076 left: self.left,
23077 right: self.right.expression
23078 });
23079 break;
23080 }
23081 // -a + b => b - a
23082 if (self.left instanceof AST_UnaryPrefix
23083 && self.left.operator == "-"
23084 && reversible()
23085 && self.right.is_number(compressor)) {
23086 self = make_node(AST_Binary, self, {
23087 operator: "-",
23088 left: self.right,
23089 right: self.left.expression
23090 });
23091 break;
23092 }
23093 case "*":
23094 associative = compressor.option("unsafe_math");
23095 case "&":
23096 case "|":
23097 case "^":
23098 // a + +b => +b + a
23099 if (self.left.is_number(compressor)
23100 && self.right.is_number(compressor)
23101 && reversible()
23102 && !(self.left instanceof AST_Binary
23103 && self.left.operator != self.operator
23104 && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
23105 var reversed = make_node(AST_Binary, self, {
23106 operator: self.operator,
23107 left: self.right,
23108 right: self.left
23109 });
23110 if (self.right instanceof AST_Constant
23111 && !(self.left instanceof AST_Constant)) {
23112 self = best_of(compressor, reversed, self);
23113 } else {
23114 self = best_of(compressor, self, reversed);
23115 }
23116 }
23117 if (associative && self.is_number(compressor)) {
23118 // a + (b + c) => (a + b) + c
23119 if (self.right instanceof AST_Binary
23120 && self.right.operator == self.operator) {
23121 self = make_node(AST_Binary, self, {
23122 operator: self.operator,
23123 left: make_node(AST_Binary, self.left, {
23124 operator: self.operator,
23125 left: self.left,
23126 right: self.right.left,
23127 start: self.left.start,
23128 end: self.right.left.end
23129 }),
23130 right: self.right.right
23131 });
23132 }
23133 // (n + 2) + 3 => 5 + n
23134 // (2 * n) * 3 => 6 + n
23135 if (self.right instanceof AST_Constant
23136 && self.left instanceof AST_Binary
23137 && self.left.operator == self.operator) {
23138 if (self.left.left instanceof AST_Constant) {
23139 self = make_node(AST_Binary, self, {
23140 operator: self.operator,
23141 left: make_node(AST_Binary, self.left, {
23142 operator: self.operator,
23143 left: self.left.left,
23144 right: self.right,
23145 start: self.left.left.start,
23146 end: self.right.end
23147 }),
23148 right: self.left.right
23149 });
23150 } else if (self.left.right instanceof AST_Constant) {
23151 self = make_node(AST_Binary, self, {
23152 operator: self.operator,
23153 left: make_node(AST_Binary, self.left, {
23154 operator: self.operator,
23155 left: self.left.right,
23156 right: self.right,
23157 start: self.left.right.start,
23158 end: self.right.end
23159 }),
23160 right: self.left.left
23161 });
23162 }
23163 }
23164 // (a | 1) | (2 | d) => (3 | a) | b
23165 if (self.left instanceof AST_Binary
23166 && self.left.operator == self.operator
23167 && self.left.right instanceof AST_Constant
23168 && self.right instanceof AST_Binary
23169 && self.right.operator == self.operator
23170 && self.right.left instanceof AST_Constant) {
23171 self = make_node(AST_Binary, self, {
23172 operator: self.operator,
23173 left: make_node(AST_Binary, self.left, {
23174 operator: self.operator,
23175 left: make_node(AST_Binary, self.left.left, {
23176 operator: self.operator,
23177 left: self.left.right,
23178 right: self.right.left,
23179 start: self.left.right.start,
23180 end: self.right.left.end
23181 }),
23182 right: self.left.left
23183 }),
23184 right: self.right.right
23185 });
23186 }
23187 }
23188 }
23189 }
23190 // x && (y && z) ==> x && y && z
23191 // x || (y || z) ==> x || y || z
23192 // x + ("y" + z) ==> x + "y" + z
23193 // "x" + (y + "z")==> "x" + y + "z"
23194 if (self.right instanceof AST_Binary
23195 && self.right.operator == self.operator
23196 && (self.operator == "&&"
23197 || self.operator == "||"
23198 || (self.operator == "+"
23199 && (self.right.left.is_string(compressor)
23200 || (self.left.is_string(compressor)
23201 && self.right.right.is_string(compressor))))))
23202 {
23203 self.left = make_node(AST_Binary, self.left, {
23204 operator : self.operator,
23205 left : self.left,
23206 right : self.right.left
23207 });
23208 self.right = self.right.right;
23209 return self.transform(compressor);
23210 }
23211 var ev = self.evaluate(compressor);
23212 if (ev !== self) {
23213 ev = make_node_from_constant(ev, self).optimize(compressor);
23214 return best_of(compressor, ev, self);
23215 }
23216 return self;
23217 });
23218
23219 OPT(AST_SymbolRef, function(self, compressor){
23220 var def = self.resolve_defines(compressor);
23221 if (def) {
23222 return def.optimize(compressor);
23223 }
23224 // testing against !self.scope.uses_with first is an optimization
23225 if (compressor.option("screw_ie8")
23226 && self.undeclared()
23227 && (!self.scope.uses_with || !compressor.find_parent(AST_With))) {
23228 switch (self.name) {
23229 case "undefined":
23230 return make_node(AST_Undefined, self).optimize(compressor);
23231 case "NaN":
23232 return make_node(AST_NaN, self).optimize(compressor);
23233 case "Infinity":
23234 return make_node(AST_Infinity, self).optimize(compressor);
23235 }
23236 }
23237 if (compressor.option("evaluate")
23238 && compressor.option("reduce_vars")
23239 && is_lhs(self, compressor.parent()) !== self) {
23240 var d = self.definition();
23241 var fixed = self.fixed_value();
23242 if (fixed) {
23243 if (d.should_replace === undefined) {
23244 var init = fixed.evaluate(compressor);
23245 if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) {
23246 init = make_node_from_constant(init, fixed);
23247 var value = init.optimize(compressor).print_to_string().length;
23248 var fn;
23249 if (has_symbol_ref(fixed)) {
23250 fn = function() {
23251 var result = init.optimize(compressor);
23252 return result === init ? result.clone(true) : result;
23253 };
23254 } else {
23255 value = Math.min(value, fixed.print_to_string().length);
23256 fn = function() {
23257 var result = best_of_expression(init.optimize(compressor), fixed);
23258 return result === init || result === fixed ? result.clone(true) : result;
23259 };
23260 }
23261 var name = d.name.length;
23262 var overhead = 0;
23263 if (compressor.option("unused") && (!d.global || compressor.option("toplevel"))) {
23264 overhead = (name + 2 + value) / d.references.length;
23265 }
23266 d.should_replace = value <= name + overhead ? fn : false;
23267 } else {
23268 d.should_replace = false;
23269 }
23270 }
23271 if (d.should_replace) {
23272 return d.should_replace();
23273 }
23274 }
23275 }
23276 return self;
23277
23278 function has_symbol_ref(value) {
23279 var found;
23280 value.walk(new TreeWalker(function(node) {
23281 if (node instanceof AST_SymbolRef) found = true;
23282 if (found) return true;
23283 }));
23284 return found;
23285 }
23286 });
23287
23288 function is_atomic(lhs, self) {
23289 return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;
23290 }
23291
23292 OPT(AST_Undefined, function(self, compressor){
23293 if (compressor.option("unsafe")) {
23294 var undef = find_variable(compressor, "undefined");
23295 if (undef) {
23296 var ref = make_node(AST_SymbolRef, self, {
23297 name : "undefined",
23298 scope : undef.scope,
23299 thedef : undef
23300 });
23301 ref.is_undefined = true;
23302 return ref;
23303 }
23304 }
23305 var lhs = is_lhs(compressor.self(), compressor.parent());
23306 if (lhs && is_atomic(lhs, self)) return self;
23307 return make_node(AST_UnaryPrefix, self, {
23308 operator: "void",
23309 expression: make_node(AST_Number, self, {
23310 value: 0
23311 })
23312 });
23313 });
23314
23315 OPT(AST_Infinity, function(self, compressor){
23316 var lhs = is_lhs(compressor.self(), compressor.parent());
23317 if (lhs && is_atomic(lhs, self)) return self;
23318 if (compressor.option("keep_infinity")
23319 && !(lhs && !is_atomic(lhs, self))
23320 && !find_variable(compressor, "Infinity"))
23321 return self;
23322 return make_node(AST_Binary, self, {
23323 operator: "/",
23324 left: make_node(AST_Number, self, {
23325 value: 1
23326 }),
23327 right: make_node(AST_Number, self, {
23328 value: 0
23329 })
23330 });
23331 });
23332
23333 OPT(AST_NaN, function(self, compressor){
23334 var lhs = is_lhs(compressor.self(), compressor.parent());
23335 if (lhs && !is_atomic(lhs, self)
23336 || find_variable(compressor, "NaN")) {
23337 return make_node(AST_Binary, self, {
23338 operator: "/",
23339 left: make_node(AST_Number, self, {
23340 value: 0
23341 }),
23342 right: make_node(AST_Number, self, {
23343 value: 0
23344 })
23345 });
23346 }
23347 return self;
23348 });
23349
23350 var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
23351 var ASSIGN_OPS_COMMUTATIVE = [ '*', '|', '^', '&' ];
23352 OPT(AST_Assign, function(self, compressor){
23353 self = self.lift_sequences(compressor);
23354 if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
23355 // x = expr1 OP expr2
23356 if (self.right.left instanceof AST_SymbolRef
23357 && self.right.left.name == self.left.name
23358 && member(self.right.operator, ASSIGN_OPS)) {
23359 // x = x - 2 ---> x -= 2
23360 self.operator = self.right.operator + "=";
23361 self.right = self.right.right;
23362 }
23363 else if (self.right.right instanceof AST_SymbolRef
23364 && self.right.right.name == self.left.name
23365 && member(self.right.operator, ASSIGN_OPS_COMMUTATIVE)
23366 && !self.right.left.has_side_effects(compressor)) {
23367 // x = 2 & x ---> x &= 2
23368 self.operator = self.right.operator + "=";
23369 self.right = self.right.left;
23370 }
23371 }
23372 return self;
23373 });
23374
23375 OPT(AST_Conditional, function(self, compressor){
23376 if (!compressor.option("conditionals")) return self;
23377 if (self.condition instanceof AST_Seq) {
23378 var car = self.condition.car;
23379 self.condition = self.condition.cdr;
23380 return AST_Seq.cons(car, self);
23381 }
23382 var cond = self.condition.evaluate(compressor);
23383 if (cond !== self.condition) {
23384 if (cond) {
23385 compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
23386 return maintain_this_binding(compressor.parent(), self, self.consequent);
23387 } else {
23388 compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
23389 return maintain_this_binding(compressor.parent(), self, self.alternative);
23390 }
23391 }
23392 var negated = cond.negate(compressor, first_in_statement(compressor));
23393 if (best_of(compressor, cond, negated) === negated) {
23394 self = make_node(AST_Conditional, self, {
23395 condition: negated,
23396 consequent: self.alternative,
23397 alternative: self.consequent
23398 });
23399 }
23400 var condition = self.condition;
23401 var consequent = self.consequent;
23402 var alternative = self.alternative;
23403 // x?x:y --> x||y
23404 if (condition instanceof AST_SymbolRef
23405 && consequent instanceof AST_SymbolRef
23406 && condition.definition() === consequent.definition()) {
23407 return make_node(AST_Binary, self, {
23408 operator: "||",
23409 left: condition,
23410 right: alternative
23411 });
23412 }
23413 // if (foo) exp = something; else exp = something_else;
23414 // |
23415 // v
23416 // exp = foo ? something : something_else;
23417 if (consequent instanceof AST_Assign
23418 && alternative instanceof AST_Assign
23419 && consequent.operator == alternative.operator
23420 && consequent.left.equivalent_to(alternative.left)
23421 && (!self.condition.has_side_effects(compressor)
23422 || consequent.operator == "="
23423 && !consequent.left.has_side_effects(compressor))) {
23424 return make_node(AST_Assign, self, {
23425 operator: consequent.operator,
23426 left: consequent.left,
23427 right: make_node(AST_Conditional, self, {
23428 condition: self.condition,
23429 consequent: consequent.right,
23430 alternative: alternative.right
23431 })
23432 });
23433 }
23434 // x ? y(a) : y(b) --> y(x ? a : b)
23435 if (consequent instanceof AST_Call
23436 && alternative.TYPE === consequent.TYPE
23437 && consequent.args.length == 1
23438 && alternative.args.length == 1
23439 && consequent.expression.equivalent_to(alternative.expression)
23440 && !consequent.expression.has_side_effects(compressor)) {
23441 consequent.args[0] = make_node(AST_Conditional, self, {
23442 condition: self.condition,
23443 consequent: consequent.args[0],
23444 alternative: alternative.args[0]
23445 });
23446 return consequent;
23447 }
23448 // x?y?z:a:a --> x&&y?z:a
23449 if (consequent instanceof AST_Conditional
23450 && consequent.alternative.equivalent_to(alternative)) {
23451 return make_node(AST_Conditional, self, {
23452 condition: make_node(AST_Binary, self, {
23453 left: self.condition,
23454 operator: "&&",
23455 right: consequent.condition
23456 }),
23457 consequent: consequent.consequent,
23458 alternative: alternative
23459 });
23460 }
23461 // x ? y : y --> x, y
23462 if (consequent.equivalent_to(alternative)) {
23463 return make_node(AST_Seq, self, {
23464 car: self.condition,
23465 cdr: consequent
23466 }).optimize(compressor);
23467 }
23468
23469 if (is_true(self.consequent)) {
23470 if (is_false(self.alternative)) {
23471 // c ? true : false ---> !!c
23472 return booleanize(self.condition);
23473 }
23474 // c ? true : x ---> !!c || x
23475 return make_node(AST_Binary, self, {
23476 operator: "||",
23477 left: booleanize(self.condition),
23478 right: self.alternative
23479 });
23480 }
23481 if (is_false(self.consequent)) {
23482 if (is_true(self.alternative)) {
23483 // c ? false : true ---> !c
23484 return booleanize(self.condition.negate(compressor));
23485 }
23486 // c ? false : x ---> !c && x
23487 return make_node(AST_Binary, self, {
23488 operator: "&&",
23489 left: booleanize(self.condition.negate(compressor)),
23490 right: self.alternative
23491 });
23492 }
23493 if (is_true(self.alternative)) {
23494 // c ? x : true ---> !c || x
23495 return make_node(AST_Binary, self, {
23496 operator: "||",
23497 left: booleanize(self.condition.negate(compressor)),
23498 right: self.consequent
23499 });
23500 }
23501 if (is_false(self.alternative)) {
23502 // c ? x : false ---> !!c && x
23503 return make_node(AST_Binary, self, {
23504 operator: "&&",
23505 left: booleanize(self.condition),
23506 right: self.consequent
23507 });
23508 }
23509
23510 return self;
23511
23512 function booleanize(node) {
23513 if (node.is_boolean()) return node;
23514 // !!expression
23515 return make_node(AST_UnaryPrefix, node, {
23516 operator: "!",
23517 expression: node.negate(compressor)
23518 });
23519 }
23520
23521 // AST_True or !0
23522 function is_true(node) {
23523 return node instanceof AST_True
23524 || (node instanceof AST_UnaryPrefix
23525 && node.operator == "!"
23526 && node.expression instanceof AST_Constant
23527 && !node.expression.value);
23528 }
23529 // AST_False or !1
23530 function is_false(node) {
23531 return node instanceof AST_False
23532 || (node instanceof AST_UnaryPrefix
23533 && node.operator == "!"
23534 && node.expression instanceof AST_Constant
23535 && !!node.expression.value);
23536 }
23537 });
23538
23539 OPT(AST_Boolean, function(self, compressor){
23540 if (compressor.option("booleans")) {
23541 var p = compressor.parent();
23542 if (p instanceof AST_Binary && (p.operator == "=="
23543 || p.operator == "!=")) {
23544 compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
23545 operator : p.operator,
23546 value : self.value,
23547 file : p.start.file,
23548 line : p.start.line,
23549 col : p.start.col,
23550 });
23551 return make_node(AST_Number, self, {
23552 value: +self.value
23553 });
23554 }
23555 return make_node(AST_UnaryPrefix, self, {
23556 operator: "!",
23557 expression: make_node(AST_Number, self, {
23558 value: 1 - self.value
23559 })
23560 });
23561 }
23562 return self;
23563 });
23564
23565 OPT(AST_Sub, function(self, compressor){
23566 var prop = self.property;
23567 if (prop instanceof AST_String && compressor.option("properties")) {
23568 prop = prop.getValue();
23569 if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) {
23570 return make_node(AST_Dot, self, {
23571 expression : self.expression,
23572 property : prop
23573 }).optimize(compressor);
23574 }
23575 var v = parseFloat(prop);
23576 if (!isNaN(v) && v.toString() == prop) {
23577 self.property = make_node(AST_Number, self.property, {
23578 value: v
23579 });
23580 }
23581 }
23582 var ev = self.evaluate(compressor);
23583 if (ev !== self) {
23584 ev = make_node_from_constant(ev, self).optimize(compressor);
23585 return best_of(compressor, ev, self);
23586 }
23587 return self;
23588 });
23589
23590 OPT(AST_Dot, function(self, compressor){
23591 var def = self.resolve_defines(compressor);
23592 if (def) {
23593 return def.optimize(compressor);
23594 }
23595 var prop = self.property;
23596 if (RESERVED_WORDS(prop) && !compressor.option("screw_ie8")) {
23597 return make_node(AST_Sub, self, {
23598 expression : self.expression,
23599 property : make_node(AST_String, self, {
23600 value: prop
23601 })
23602 }).optimize(compressor);
23603 }
23604 if (compressor.option("unsafe_proto")
23605 && self.expression instanceof AST_Dot
23606 && self.expression.property == "prototype") {
23607 var exp = self.expression.expression;
23608 if (exp instanceof AST_SymbolRef && exp.undeclared()) switch (exp.name) {
23609 case "Array":
23610 self.expression = make_node(AST_Array, self.expression, {
23611 elements: []
23612 });
23613 break;
23614 case "Object":
23615 self.expression = make_node(AST_Object, self.expression, {
23616 properties: []
23617 });
23618 break;
23619 case "String":
23620 self.expression = make_node(AST_String, self.expression, {
23621 value: ""
23622 });
23623 break;
23624 }
23625 }
23626 var ev = self.evaluate(compressor);
23627 if (ev !== self) {
23628 ev = make_node_from_constant(ev, self).optimize(compressor);
23629 return best_of(compressor, ev, self);
23630 }
23631 return self;
23632 });
23633
23634 function literals_in_boolean_context(self, compressor) {
23635 if (compressor.option("booleans") && compressor.in_boolean_context()) {
23636 return best_of(compressor, self, make_node(AST_Seq, self, {
23637 car: self,
23638 cdr: make_node(AST_True, self)
23639 }).optimize(compressor));
23640 }
23641 return self;
23642 };
23643 OPT(AST_Array, literals_in_boolean_context);
23644 OPT(AST_Object, literals_in_boolean_context);
23645 OPT(AST_RegExp, literals_in_boolean_context);
23646
23647 OPT(AST_Return, function(self, compressor){
23648 if (self.value && is_undefined(self.value, compressor)) {
23649 self.value = null;
23650 }
23651 return self;
23652 });
23653
23654 OPT(AST_VarDef, function(self, compressor){
23655 var defines = compressor.option("global_defs");
23656 if (defines && HOP(defines, self.name.name)) {
23657 compressor.warn('global_defs ' + self.name.name + ' redefined [{file}:{line},{col}]', self.start);
23658 }
23659 return self;
23660 });
23661
23662})();
23663
23664/***********************************************************************
23665
23666 A JavaScript tokenizer / parser / beautifier / compressor.
23667 https://github.com/mishoo/UglifyJS2
23668
23669 -------------------------------- (C) ---------------------------------
23670
23671 Author: Mihai Bazon
23672 <mihai.bazon@gmail.com>
23673 http://mihai.bazon.net/blog
23674
23675 Distributed under the BSD license:
23676
23677 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
23678
23679 Redistribution and use in source and binary forms, with or without
23680 modification, are permitted provided that the following conditions
23681 are met:
23682
23683 * Redistributions of source code must retain the above
23684 copyright notice, this list of conditions and the following
23685 disclaimer.
23686
23687 * Redistributions in binary form must reproduce the above
23688 copyright notice, this list of conditions and the following
23689 disclaimer in the documentation and/or other materials
23690 provided with the distribution.
23691
23692 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
23693 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23694 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23695 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
23696 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23697 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23698 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23699 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23700 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
23701 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
23702 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23703 SUCH DAMAGE.
23704
23705 ***********************************************************************/
23706
23707"use strict";
23708
23709// a small wrapper around fitzgen's source-map library
23710function SourceMap(options) {
23711 options = defaults(options, {
23712 file : null,
23713 root : null,
23714 orig : null,
23715
23716 orig_line_diff : 0,
23717 dest_line_diff : 0,
23718 });
23719 var generator = new MOZ_SourceMap.SourceMapGenerator({
23720 file : options.file,
23721 sourceRoot : options.root
23722 });
23723 var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
23724
23725 if (orig_map && Array.isArray(options.orig.sources)) {
23726 orig_map._sources.toArray().forEach(function(source) {
23727 var sourceContent = orig_map.sourceContentFor(source, true);
23728 if (sourceContent) {
23729 generator.setSourceContent(source, sourceContent);
23730 }
23731 });
23732 }
23733
23734 function add(source, gen_line, gen_col, orig_line, orig_col, name) {
23735 if (orig_map) {
23736 var info = orig_map.originalPositionFor({
23737 line: orig_line,
23738 column: orig_col
23739 });
23740 if (info.source === null) {
23741 return;
23742 }
23743 source = info.source;
23744 orig_line = info.line;
23745 orig_col = info.column;
23746 name = info.name || name;
23747 }
23748 generator.addMapping({
23749 generated : { line: gen_line + options.dest_line_diff, column: gen_col },
23750 original : { line: orig_line + options.orig_line_diff, column: orig_col },
23751 source : source,
23752 name : name
23753 });
23754 };
23755 return {
23756 add : add,
23757 get : function() { return generator },
23758 toString : function() { return JSON.stringify(generator.toJSON()); }
23759 };
23760};
23761
23762/***********************************************************************
23763
23764 A JavaScript tokenizer / parser / beautifier / compressor.
23765 https://github.com/mishoo/UglifyJS2
23766
23767 -------------------------------- (C) ---------------------------------
23768
23769 Author: Mihai Bazon
23770 <mihai.bazon@gmail.com>
23771 http://mihai.bazon.net/blog
23772
23773 Distributed under the BSD license:
23774
23775 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
23776
23777 Redistribution and use in source and binary forms, with or without
23778 modification, are permitted provided that the following conditions
23779 are met:
23780
23781 * Redistributions of source code must retain the above
23782 copyright notice, this list of conditions and the following
23783 disclaimer.
23784
23785 * Redistributions in binary form must reproduce the above
23786 copyright notice, this list of conditions and the following
23787 disclaimer in the documentation and/or other materials
23788 provided with the distribution.
23789
23790 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
23791 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23792 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23793 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
23794 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23795 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23796 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23797 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23798 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
23799 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
23800 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23801 SUCH DAMAGE.
23802
23803 ***********************************************************************/
23804
23805"use strict";
23806
23807(function(){
23808
23809 var normalize_directives = function(body) {
23810 var in_directive = true;
23811
23812 for (var i = 0; i < body.length; i++) {
23813 if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
23814 body[i] = new AST_Directive({
23815 start: body[i].start,
23816 end: body[i].end,
23817 value: body[i].body.value
23818 });
23819 } else if (in_directive && !(body[i] instanceof AST_Statement && body[i].body instanceof AST_String)) {
23820 in_directive = false;
23821 }
23822 }
23823
23824 return body;
23825 };
23826
23827 var MOZ_TO_ME = {
23828 Program: function(M) {
23829 return new AST_Toplevel({
23830 start: my_start_token(M),
23831 end: my_end_token(M),
23832 body: normalize_directives(M.body.map(from_moz))
23833 });
23834 },
23835 FunctionDeclaration: function(M) {
23836 return new AST_Defun({
23837 start: my_start_token(M),
23838 end: my_end_token(M),
23839 name: from_moz(M.id),
23840 argnames: M.params.map(from_moz),
23841 body: normalize_directives(from_moz(M.body).body)
23842 });
23843 },
23844 FunctionExpression: function(M) {
23845 return new AST_Function({
23846 start: my_start_token(M),
23847 end: my_end_token(M),
23848 name: from_moz(M.id),
23849 argnames: M.params.map(from_moz),
23850 body: normalize_directives(from_moz(M.body).body)
23851 });
23852 },
23853 ExpressionStatement: function(M) {
23854 return new AST_SimpleStatement({
23855 start: my_start_token(M),
23856 end: my_end_token(M),
23857 body: from_moz(M.expression)
23858 });
23859 },
23860 TryStatement: function(M) {
23861 var handlers = M.handlers || [M.handler];
23862 if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
23863 throw new Error("Multiple catch clauses are not supported.");
23864 }
23865 return new AST_Try({
23866 start : my_start_token(M),
23867 end : my_end_token(M),
23868 body : from_moz(M.block).body,
23869 bcatch : from_moz(handlers[0]),
23870 bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
23871 });
23872 },
23873 Property: function(M) {
23874 var key = M.key;
23875 var args = {
23876 start : my_start_token(key),
23877 end : my_end_token(M.value),
23878 key : key.type == "Identifier" ? key.name : key.value,
23879 value : from_moz(M.value)
23880 };
23881 if (M.kind == "init") return new AST_ObjectKeyVal(args);
23882 args.key = new AST_SymbolAccessor({
23883 name: args.key
23884 });
23885 args.value = new AST_Accessor(args.value);
23886 if (M.kind == "get") return new AST_ObjectGetter(args);
23887 if (M.kind == "set") return new AST_ObjectSetter(args);
23888 },
23889 ArrayExpression: function(M) {
23890 return new AST_Array({
23891 start : my_start_token(M),
23892 end : my_end_token(M),
23893 elements : M.elements.map(function(elem){
23894 return elem === null ? new AST_Hole() : from_moz(elem);
23895 })
23896 });
23897 },
23898 ObjectExpression: function(M) {
23899 return new AST_Object({
23900 start : my_start_token(M),
23901 end : my_end_token(M),
23902 properties : M.properties.map(function(prop){
23903 prop.type = "Property";
23904 return from_moz(prop)
23905 })
23906 });
23907 },
23908 SequenceExpression: function(M) {
23909 return AST_Seq.from_array(M.expressions.map(from_moz));
23910 },
23911 MemberExpression: function(M) {
23912 return new (M.computed ? AST_Sub : AST_Dot)({
23913 start : my_start_token(M),
23914 end : my_end_token(M),
23915 property : M.computed ? from_moz(M.property) : M.property.name,
23916 expression : from_moz(M.object)
23917 });
23918 },
23919 SwitchCase: function(M) {
23920 return new (M.test ? AST_Case : AST_Default)({
23921 start : my_start_token(M),
23922 end : my_end_token(M),
23923 expression : from_moz(M.test),
23924 body : M.consequent.map(from_moz)
23925 });
23926 },
23927 VariableDeclaration: function(M) {
23928 return new (M.kind === "const" ? AST_Const : AST_Var)({
23929 start : my_start_token(M),
23930 end : my_end_token(M),
23931 definitions : M.declarations.map(from_moz)
23932 });
23933 },
23934 Literal: function(M) {
23935 var val = M.value, args = {
23936 start : my_start_token(M),
23937 end : my_end_token(M)
23938 };
23939 if (val === null) return new AST_Null(args);
23940 switch (typeof val) {
23941 case "string":
23942 args.value = val;
23943 return new AST_String(args);
23944 case "number":
23945 args.value = val;
23946 return new AST_Number(args);
23947 case "boolean":
23948 return new (val ? AST_True : AST_False)(args);
23949 default:
23950 var rx = M.regex;
23951 if (rx && rx.pattern) {
23952 // RegExpLiteral as per ESTree AST spec
23953 args.value = new RegExp(rx.pattern, rx.flags).toString();
23954 } else {
23955 // support legacy RegExp
23956 args.value = M.regex && M.raw ? M.raw : val;
23957 }
23958 return new AST_RegExp(args);
23959 }
23960 },
23961 Identifier: function(M) {
23962 var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
23963 return new ( p.type == "LabeledStatement" ? AST_Label
23964 : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
23965 : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
23966 : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
23967 : p.type == "CatchClause" ? AST_SymbolCatch
23968 : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
23969 : AST_SymbolRef)({
23970 start : my_start_token(M),
23971 end : my_end_token(M),
23972 name : M.name
23973 });
23974 }
23975 };
23976
23977 MOZ_TO_ME.UpdateExpression =
23978 MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
23979 var prefix = "prefix" in M ? M.prefix
23980 : M.type == "UnaryExpression" ? true : false;
23981 return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
23982 start : my_start_token(M),
23983 end : my_end_token(M),
23984 operator : M.operator,
23985 expression : from_moz(M.argument)
23986 });
23987 };
23988
23989 map("EmptyStatement", AST_EmptyStatement);
23990 map("BlockStatement", AST_BlockStatement, "body@body");
23991 map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
23992 map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
23993 map("BreakStatement", AST_Break, "label>label");
23994 map("ContinueStatement", AST_Continue, "label>label");
23995 map("WithStatement", AST_With, "object>expression, body>body");
23996 map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
23997 map("ReturnStatement", AST_Return, "argument>value");
23998 map("ThrowStatement", AST_Throw, "argument>value");
23999 map("WhileStatement", AST_While, "test>condition, body>body");
24000 map("DoWhileStatement", AST_Do, "test>condition, body>body");
24001 map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
24002 map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
24003 map("DebuggerStatement", AST_Debugger);
24004 map("VariableDeclarator", AST_VarDef, "id>name, init>value");
24005 map("CatchClause", AST_Catch, "param>argname, body%body");
24006
24007 map("ThisExpression", AST_This);
24008 map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
24009 map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
24010 map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
24011 map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
24012 map("NewExpression", AST_New, "callee>expression, arguments@args");
24013 map("CallExpression", AST_Call, "callee>expression, arguments@args");
24014
24015 def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
24016 return to_moz_scope("Program", M);
24017 });
24018
24019 def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
24020 return {
24021 type: "FunctionDeclaration",
24022 id: to_moz(M.name),
24023 params: M.argnames.map(to_moz),
24024 body: to_moz_scope("BlockStatement", M)
24025 }
24026 });
24027
24028 def_to_moz(AST_Function, function To_Moz_FunctionExpression(M) {
24029 return {
24030 type: "FunctionExpression",
24031 id: to_moz(M.name),
24032 params: M.argnames.map(to_moz),
24033 body: to_moz_scope("BlockStatement", M)
24034 }
24035 });
24036
24037 def_to_moz(AST_Directive, function To_Moz_Directive(M) {
24038 return {
24039 type: "ExpressionStatement",
24040 expression: {
24041 type: "Literal",
24042 value: M.value
24043 }
24044 };
24045 });
24046
24047 def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
24048 return {
24049 type: "ExpressionStatement",
24050 expression: to_moz(M.body)
24051 };
24052 });
24053
24054 def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
24055 return {
24056 type: "SwitchCase",
24057 test: to_moz(M.expression),
24058 consequent: M.body.map(to_moz)
24059 };
24060 });
24061
24062 def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
24063 return {
24064 type: "TryStatement",
24065 block: to_moz_block(M),
24066 handler: to_moz(M.bcatch),
24067 guardedHandlers: [],
24068 finalizer: to_moz(M.bfinally)
24069 };
24070 });
24071
24072 def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
24073 return {
24074 type: "CatchClause",
24075 param: to_moz(M.argname),
24076 guard: null,
24077 body: to_moz_block(M)
24078 };
24079 });
24080
24081 def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
24082 return {
24083 type: "VariableDeclaration",
24084 kind: M instanceof AST_Const ? "const" : "var",
24085 declarations: M.definitions.map(to_moz)
24086 };
24087 });
24088
24089 def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
24090 return {
24091 type: "SequenceExpression",
24092 expressions: M.to_array().map(to_moz)
24093 };
24094 });
24095
24096 def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
24097 var isComputed = M instanceof AST_Sub;
24098 return {
24099 type: "MemberExpression",
24100 object: to_moz(M.expression),
24101 computed: isComputed,
24102 property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property}
24103 };
24104 });
24105
24106 def_to_moz(AST_Unary, function To_Moz_Unary(M) {
24107 return {
24108 type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
24109 operator: M.operator,
24110 prefix: M instanceof AST_UnaryPrefix,
24111 argument: to_moz(M.expression)
24112 };
24113 });
24114
24115 def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
24116 return {
24117 type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
24118 left: to_moz(M.left),
24119 operator: M.operator,
24120 right: to_moz(M.right)
24121 };
24122 });
24123
24124 def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {
24125 return {
24126 type: "ArrayExpression",
24127 elements: M.elements.map(to_moz)
24128 };
24129 });
24130
24131 def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
24132 return {
24133 type: "ObjectExpression",
24134 properties: M.properties.map(to_moz)
24135 };
24136 });
24137
24138 def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
24139 var key = {
24140 type: "Literal",
24141 value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key
24142 };
24143 var kind;
24144 if (M instanceof AST_ObjectKeyVal) {
24145 kind = "init";
24146 } else
24147 if (M instanceof AST_ObjectGetter) {
24148 kind = "get";
24149 } else
24150 if (M instanceof AST_ObjectSetter) {
24151 kind = "set";
24152 }
24153 return {
24154 type: "Property",
24155 kind: kind,
24156 key: key,
24157 value: to_moz(M.value)
24158 };
24159 });
24160
24161 def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
24162 var def = M.definition();
24163 return {
24164 type: "Identifier",
24165 name: def ? def.mangled_name || def.name : M.name
24166 };
24167 });
24168
24169 def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
24170 var value = M.value;
24171 return {
24172 type: "Literal",
24173 value: value,
24174 raw: value.toString(),
24175 regex: {
24176 pattern: value.source,
24177 flags: value.toString().match(/[gimuy]*$/)[0]
24178 }
24179 };
24180 });
24181
24182 def_to_moz(AST_Constant, function To_Moz_Literal(M) {
24183 var value = M.value;
24184 if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
24185 return {
24186 type: "UnaryExpression",
24187 operator: "-",
24188 prefix: true,
24189 argument: {
24190 type: "Literal",
24191 value: -value,
24192 raw: M.start.raw
24193 }
24194 };
24195 }
24196 return {
24197 type: "Literal",
24198 value: value,
24199 raw: M.start.raw
24200 };
24201 });
24202
24203 def_to_moz(AST_Atom, function To_Moz_Atom(M) {
24204 return {
24205 type: "Identifier",
24206 name: String(M.value)
24207 };
24208 });
24209
24210 AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
24211 AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
24212 AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null });
24213
24214 AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
24215 AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
24216
24217 /* -----[ tools ]----- */
24218
24219 function raw_token(moznode) {
24220 if (moznode.type == "Literal") {
24221 return moznode.raw != null ? moznode.raw : moznode.value + "";
24222 }
24223 }
24224
24225 function my_start_token(moznode) {
24226 var loc = moznode.loc, start = loc && loc.start;
24227 var range = moznode.range;
24228 return new AST_Token({
24229 file : loc && loc.source,
24230 line : start && start.line,
24231 col : start && start.column,
24232 pos : range ? range[0] : moznode.start,
24233 endline : start && start.line,
24234 endcol : start && start.column,
24235 endpos : range ? range[0] : moznode.start,
24236 raw : raw_token(moznode),
24237 });
24238 };
24239
24240 function my_end_token(moznode) {
24241 var loc = moznode.loc, end = loc && loc.end;
24242 var range = moznode.range;
24243 return new AST_Token({
24244 file : loc && loc.source,
24245 line : end && end.line,
24246 col : end && end.column,
24247 pos : range ? range[1] : moznode.end,
24248 endline : end && end.line,
24249 endcol : end && end.column,
24250 endpos : range ? range[1] : moznode.end,
24251 raw : raw_token(moznode),
24252 });
24253 };
24254
24255 function map(moztype, mytype, propmap) {
24256 var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
24257 moz_to_me += "return new U2." + mytype.name + "({\n" +
24258 "start: my_start_token(M),\n" +
24259 "end: my_end_token(M)";
24260
24261 var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
24262 me_to_moz += "return {\n" +
24263 "type: " + JSON.stringify(moztype);
24264
24265 if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
24266 var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
24267 if (!m) throw new Error("Can't understand property map: " + prop);
24268 var moz = m[1], how = m[2], my = m[3];
24269 moz_to_me += ",\n" + my + ": ";
24270 me_to_moz += ",\n" + moz + ": ";
24271 switch (how) {
24272 case "@":
24273 moz_to_me += "M." + moz + ".map(from_moz)";
24274 me_to_moz += "M." + my + ".map(to_moz)";
24275 break;
24276 case ">":
24277 moz_to_me += "from_moz(M." + moz + ")";
24278 me_to_moz += "to_moz(M." + my + ")";
24279 break;
24280 case "=":
24281 moz_to_me += "M." + moz;
24282 me_to_moz += "M." + my;
24283 break;
24284 case "%":
24285 moz_to_me += "from_moz(M." + moz + ").body";
24286 me_to_moz += "to_moz_block(M)";
24287 break;
24288 default:
24289 throw new Error("Can't understand operator in propmap: " + prop);
24290 }
24291 });
24292
24293 moz_to_me += "\n})\n}";
24294 me_to_moz += "\n}\n}";
24295
24296 //moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
24297 //me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
24298 //console.log(moz_to_me);
24299
24300 moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
24301 exports, my_start_token, my_end_token, from_moz
24302 );
24303 me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")(
24304 to_moz, to_moz_block, to_moz_scope
24305 );
24306 MOZ_TO_ME[moztype] = moz_to_me;
24307 def_to_moz(mytype, me_to_moz);
24308 };
24309
24310 var FROM_MOZ_STACK = null;
24311
24312 function from_moz(node) {
24313 FROM_MOZ_STACK.push(node);
24314 var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
24315 FROM_MOZ_STACK.pop();
24316 return ret;
24317 };
24318
24319 AST_Node.from_mozilla_ast = function(node){
24320 var save_stack = FROM_MOZ_STACK;
24321 FROM_MOZ_STACK = [];
24322 var ast = from_moz(node);
24323 FROM_MOZ_STACK = save_stack;
24324 return ast;
24325 };
24326
24327 function set_moz_loc(mynode, moznode, myparent) {
24328 var start = mynode.start;
24329 var end = mynode.end;
24330 if (start.pos != null && end.endpos != null) {
24331 moznode.range = [start.pos, end.endpos];
24332 }
24333 if (start.line) {
24334 moznode.loc = {
24335 start: {line: start.line, column: start.col},
24336 end: end.endline ? {line: end.endline, column: end.endcol} : null
24337 };
24338 if (start.file) {
24339 moznode.loc.source = start.file;
24340 }
24341 }
24342 return moznode;
24343 };
24344
24345 function def_to_moz(mytype, handler) {
24346 mytype.DEFMETHOD("to_mozilla_ast", function() {
24347 return set_moz_loc(this, handler(this));
24348 });
24349 };
24350
24351 function to_moz(node) {
24352 return node != null ? node.to_mozilla_ast() : null;
24353 };
24354
24355 function to_moz_block(node) {
24356 return {
24357 type: "BlockStatement",
24358 body: node.body.map(to_moz)
24359 };
24360 };
24361
24362 function to_moz_scope(type, node) {
24363 var body = node.body.map(to_moz);
24364 if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {
24365 body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));
24366 }
24367 return {
24368 type: type,
24369 body: body
24370 };
24371 };
24372})();
24373
24374/***********************************************************************
24375
24376 A JavaScript tokenizer / parser / beautifier / compressor.
24377 https://github.com/mishoo/UglifyJS2
24378
24379 -------------------------------- (C) ---------------------------------
24380
24381 Author: Mihai Bazon
24382 <mihai.bazon@gmail.com>
24383 http://mihai.bazon.net/blog
24384
24385 Distributed under the BSD license:
24386
24387 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
24388
24389 Redistribution and use in source and binary forms, with or without
24390 modification, are permitted provided that the following conditions
24391 are met:
24392
24393 * Redistributions of source code must retain the above
24394 copyright notice, this list of conditions and the following
24395 disclaimer.
24396
24397 * Redistributions in binary form must reproduce the above
24398 copyright notice, this list of conditions and the following
24399 disclaimer in the documentation and/or other materials
24400 provided with the distribution.
24401
24402 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
24403 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24404 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24405 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
24406 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24407 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24408 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24409 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24410 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
24411 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
24412 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24413 SUCH DAMAGE.
24414
24415 ***********************************************************************/
24416
24417"use strict";
24418
24419function find_builtins() {
24420 // NaN will be included due to Number.NaN
24421 var a = [
24422 "null",
24423 "true",
24424 "false",
24425 "Infinity",
24426 "-Infinity",
24427 "undefined",
24428 ];
24429 [ Object, Array, Function, Number,
24430 String, Boolean, Error, Math,
24431 Date, RegExp
24432 ].forEach(function(ctor){
24433 Object.getOwnPropertyNames(ctor).map(add);
24434 if (ctor.prototype) {
24435 Object.getOwnPropertyNames(ctor.prototype).map(add);
24436 }
24437 });
24438 function add(name) {
24439 push_uniq(a, name);
24440 }
24441 return a;
24442}
24443
24444function mangle_properties(ast, options) {
24445 options = defaults(options, {
24446 cache: null,
24447 debug: false,
24448 ignore_quoted: false,
24449 only_cache: false,
24450 regex: null,
24451 reserved: null,
24452 });
24453
24454 var reserved = options.reserved;
24455 if (reserved == null)
24456 reserved = find_builtins();
24457
24458 var cache = options.cache;
24459 if (cache == null) {
24460 cache = {
24461 cname: -1,
24462 props: new Dictionary()
24463 };
24464 }
24465
24466 var regex = options.regex;
24467 var ignore_quoted = options.ignore_quoted;
24468
24469 // note debug is either false (disabled), or a string of the debug suffix to use (enabled).
24470 // note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
24471 // the same as passing an empty string.
24472 var debug = (options.debug !== false);
24473 var debug_name_suffix;
24474 if (debug) {
24475 debug_name_suffix = (options.debug === true ? "" : options.debug);
24476 }
24477
24478 var names_to_mangle = [];
24479 var unmangleable = [];
24480 var ignored = {};
24481
24482 // step 1: find candidates to mangle
24483 ast.walk(new TreeWalker(function(node){
24484 if (node instanceof AST_ObjectKeyVal) {
24485 add(node.key, ignore_quoted && node.quote);
24486 }
24487 else if (node instanceof AST_ObjectProperty) {
24488 // setter or getter, since KeyVal is handled above
24489 add(node.key.name);
24490 }
24491 else if (node instanceof AST_Dot) {
24492 add(node.property);
24493 }
24494 else if (node instanceof AST_Sub) {
24495 addStrings(node.property, ignore_quoted);
24496 }
24497 }));
24498
24499 // step 2: transform the tree, renaming properties
24500 return ast.transform(new TreeTransformer(function(node){
24501 if (node instanceof AST_ObjectKeyVal) {
24502 if (!(ignore_quoted && node.quote))
24503 node.key = mangle(node.key);
24504 }
24505 else if (node instanceof AST_ObjectProperty) {
24506 // setter or getter
24507 node.key.name = mangle(node.key.name);
24508 }
24509 else if (node instanceof AST_Dot) {
24510 node.property = mangle(node.property);
24511 }
24512 else if (node instanceof AST_Sub) {
24513 if (!ignore_quoted)
24514 node.property = mangleStrings(node.property);
24515 }
24516 // else if (node instanceof AST_String) {
24517 // if (should_mangle(node.value)) {
24518 // AST_Node.warn(
24519 // "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
24520 // file : node.start.file,
24521 // line : node.start.line,
24522 // col : node.start.col,
24523 // prop : node.value
24524 // }
24525 // );
24526 // }
24527 // }
24528 }));
24529
24530 // only function declarations after this line
24531
24532 function can_mangle(name) {
24533 if (unmangleable.indexOf(name) >= 0) return false;
24534 if (reserved.indexOf(name) >= 0) return false;
24535 if (options.only_cache) {
24536 return cache.props.has(name);
24537 }
24538 if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
24539 return true;
24540 }
24541
24542 function should_mangle(name) {
24543 if (ignore_quoted && name in ignored) return false;
24544 if (regex && !regex.test(name)) return false;
24545 if (reserved.indexOf(name) >= 0) return false;
24546 return cache.props.has(name)
24547 || names_to_mangle.indexOf(name) >= 0;
24548 }
24549
24550 function add(name, ignore) {
24551 if (ignore) {
24552 ignored[name] = true;
24553 return;
24554 }
24555
24556 if (can_mangle(name))
24557 push_uniq(names_to_mangle, name);
24558
24559 if (!should_mangle(name)) {
24560 push_uniq(unmangleable, name);
24561 }
24562 }
24563
24564 function mangle(name) {
24565 if (!should_mangle(name)) {
24566 return name;
24567 }
24568
24569 var mangled = cache.props.get(name);
24570 if (!mangled) {
24571 if (debug) {
24572 // debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
24573 var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
24574
24575 if (can_mangle(debug_mangled) && !(ignore_quoted && debug_mangled in ignored)) {
24576 mangled = debug_mangled;
24577 }
24578 }
24579
24580 // either debug mode is off, or it is on and we could not use the mangled name
24581 if (!mangled) {
24582 // note can_mangle() does not check if the name collides with the 'ignored' set
24583 // (filled with quoted properties when ignore_quoted set). Make sure we add this
24584 // check so we don't collide with a quoted name.
24585 do {
24586 mangled = base54(++cache.cname);
24587 } while (!can_mangle(mangled) || (ignore_quoted && mangled in ignored));
24588 }
24589
24590 cache.props.set(name, mangled);
24591 }
24592 return mangled;
24593 }
24594
24595 function addStrings(node, ignore) {
24596 var out = {};
24597 try {
24598 (function walk(node){
24599 node.walk(new TreeWalker(function(node){
24600 if (node instanceof AST_Seq) {
24601 walk(node.cdr);
24602 return true;
24603 }
24604 if (node instanceof AST_String) {
24605 add(node.value, ignore);
24606 return true;
24607 }
24608 if (node instanceof AST_Conditional) {
24609 walk(node.consequent);
24610 walk(node.alternative);
24611 return true;
24612 }
24613 throw out;
24614 }));
24615 })(node);
24616 } catch(ex) {
24617 if (ex !== out) throw ex;
24618 }
24619 }
24620
24621 function mangleStrings(node) {
24622 return node.transform(new TreeTransformer(function(node){
24623 if (node instanceof AST_Seq) {
24624 node.cdr = mangleStrings(node.cdr);
24625 }
24626 else if (node instanceof AST_String) {
24627 node.value = mangle(node.value);
24628 }
24629 else if (node instanceof AST_Conditional) {
24630 node.consequent = mangleStrings(node.consequent);
24631 node.alternative = mangleStrings(node.alternative);
24632 }
24633 return node;
24634 }));
24635 }
24636
24637}
24638
24639exports["Compressor"] = Compressor;
24640exports["DefaultsError"] = DefaultsError;
24641exports["Dictionary"] = Dictionary;
24642exports["JS_Parse_Error"] = JS_Parse_Error;
24643exports["MAP"] = MAP;
24644exports["OutputStream"] = OutputStream;
24645exports["SourceMap"] = SourceMap;
24646exports["TreeTransformer"] = TreeTransformer;
24647exports["TreeWalker"] = TreeWalker;
24648exports["base54"] = base54;
24649exports["defaults"] = defaults;
24650exports["mangle_properties"] = mangle_properties;
24651exports["merge"] = merge;
24652exports["parse"] = parse;
24653exports["push_uniq"] = push_uniq;
24654exports["string_template"] = string_template;
24655exports["tokenizer"] = tokenizer;
24656exports["is_identifier"] = is_identifier;
24657exports["SymbolDef"] = SymbolDef;
24658
24659AST_Node.warn_function = function(txt) { logger.error("uglifyjs WARN: " + txt); };
24660// workaround for tty output truncation upon process.exit()
24661[process.stdout, process.stderr].forEach(function(stream){
24662 if (stream._handle && stream._handle.setBlocking)
24663 stream._handle.setBlocking(true);
24664});
24665
24666exports.AST_Node.warn_function = function(txt) {
24667 console.error("WARN: %s", txt);
24668};
24669
24670function read_source_map(code) {
24671 var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
24672 if (!match) {
24673 exports.AST_Node.warn("inline source map not found");
24674 return null;
24675 }
24676 return JSON.parse(new Buffer(match[2], "base64"));
24677}
24678
24679exports.minify = function(files, options, name) {
24680 options = exports.defaults(options, {
24681 compress : {},
24682 fromString : false,
24683 inSourceMap : null,
24684 mangle : {},
24685 mangleProperties : false,
24686 nameCache : null,
24687 outFileName : null,
24688 output : null,
24689 outSourceMap : null,
24690 parse : {},
24691 sourceMapInline : false,
24692 sourceMapUrl : null,
24693 sourceRoot : null,
24694 spidermonkey : false,
24695 warnings : false,
24696 });
24697 exports.base54.reset();
24698
24699 var inMap = options.inSourceMap;
24700 if (typeof inMap == "string" && inMap != "inline") {
24701 inMap = JSON.parse(rjsFile.readFile(inMap, "utf8"));
24702 }
24703
24704 // 1. parse
24705 var toplevel = null,
24706 sourcesContent = {};
24707
24708 if (options.spidermonkey) {
24709 if (inMap == "inline") {
24710 throw new Error("inline source map only works with built-in parser");
24711 }
24712 toplevel = exports.AST_Node.from_mozilla_ast(files);
24713 } else {
24714 var addFile = function(file, fileUrl) {
24715 var code = options.fromString
24716 ? file
24717 : rjsFile.readFile(file, "utf8");
24718 if (inMap == "inline") {
24719 inMap = read_source_map(code);
24720 }
24721 sourcesContent[fileUrl] = code;
24722 toplevel = exports.parse(code, {
24723 filename: fileUrl,
24724 toplevel: toplevel,
24725 bare_returns: options.parse ? options.parse.bare_returns : undefined
24726 });
24727 }
24728 if (!options.fromString) {
24729 files = exports.simple_glob(files);
24730 if (inMap == "inline" && files.length > 1) {
24731 throw new Error("inline source map only works with singular input");
24732 }
24733 }
24734 [].concat(files).forEach(function (files, i) {
24735 if (typeof files === 'string') {
24736 addFile(files, options.fromString ? i : files);
24737 } else {
24738 for (var fileUrl in files) {
24739 addFile(files[fileUrl], fileUrl);
24740 }
24741 }
24742 });
24743 }
24744 if (options.wrap) {
24745 toplevel = toplevel.wrap_commonjs(options.wrap, options.exportAll);
24746 }
24747
24748 // 2. compress
24749 if (options.compress) {
24750 var compress = { warnings: options.warnings };
24751 exports.merge(compress, options.compress);
24752 toplevel.figure_out_scope(options.mangle);
24753 var sq = exports.Compressor(compress);
24754 toplevel = sq.compress(toplevel);
24755 }
24756
24757 // 3. mangle properties
24758 if (options.mangleProperties || options.nameCache) {
24759 options.mangleProperties.cache = exports.readNameCache(options.nameCache, "props");
24760 toplevel = exports.mangle_properties(toplevel, options.mangleProperties);
24761 exports.writeNameCache(options.nameCache, "props", options.mangleProperties.cache);
24762 }
24763
24764 // 4. mangle
24765 if (options.mangle) {
24766 toplevel.figure_out_scope(options.mangle);
24767 toplevel.compute_char_frequency(options.mangle);
24768 toplevel.mangle_names(options.mangle);
24769 }
24770
24771 // 5. output
24772 var output = { max_line_len: 32000 };
24773 if (options.outSourceMap || options.sourceMapInline) {
24774 output.source_map = exports.SourceMap({
24775 // prefer outFileName, otherwise use outSourceMap without .map suffix
24776 file: options.outFileName || (typeof options.outSourceMap === 'string' ? options.outSourceMap.replace(/\.map$/i, '') : null),
24777 orig: inMap,
24778 root: options.sourceRoot
24779 });
24780 if (options.sourceMapIncludeSources) {
24781 for (var file in sourcesContent) {
24782 if (sourcesContent.hasOwnProperty(file)) {
24783 output.source_map.get().setSourceContent(file, sourcesContent[file]);
24784 }
24785 }
24786 }
24787
24788 }
24789 if (options.output) {
24790 exports.merge(output, options.output);
24791 }
24792 var stream = exports.OutputStream(output);
24793 toplevel.print(stream);
24794
24795
24796 var source_map = output.source_map;
24797 if (source_map) {
24798 source_map = source_map + "";
24799 }
24800
24801 var mappingUrlPrefix = "\n//# sourceMappingURL=";
24802 if (options.sourceMapInline) {
24803 stream += mappingUrlPrefix + "data:application/json;charset=utf-8;base64," + new Buffer(source_map).toString("base64");
24804 } else if (options.outSourceMap && typeof options.outSourceMap === "string" && options.sourceMapUrl !== false) {
24805 stream += mappingUrlPrefix + (typeof options.sourceMapUrl === "string" ? options.sourceMapUrl : options.outSourceMap);
24806 }
24807
24808 return {
24809 code : stream + "",
24810 map : source_map
24811 };
24812};
24813
24814// exports.describe_ast = function() {
24815// function doitem(ctor) {
24816// var sub = {};
24817// ctor.SUBCLASSES.forEach(function(ctor){
24818// sub[ctor.TYPE] = doitem(ctor);
24819// });
24820// var ret = {};
24821// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS;
24822// if (ctor.SUBCLASSES.length > 0) ret.sub = sub;
24823// return ret;
24824// }
24825// return doitem(exports.AST_Node).sub;
24826// }
24827
24828exports.describe_ast = function() {
24829 var out = exports.OutputStream({ beautify: true });
24830 function doitem(ctor) {
24831 out.print("AST_" + ctor.TYPE);
24832 var props = ctor.SELF_PROPS.filter(function(prop){
24833 return !/^\$/.test(prop);
24834 });
24835 if (props.length > 0) {
24836 out.space();
24837 out.with_parens(function(){
24838 props.forEach(function(prop, i){
24839 if (i) out.space();
24840 out.print(prop);
24841 });
24842 });
24843 }
24844 if (ctor.documentation) {
24845 out.space();
24846 out.print_string(ctor.documentation);
24847 }
24848 if (ctor.SUBCLASSES.length > 0) {
24849 out.space();
24850 out.with_block(function(){
24851 ctor.SUBCLASSES.forEach(function(ctor, i){
24852 out.indent();
24853 doitem(ctor);
24854 out.newline();
24855 });
24856 });
24857 }
24858 };
24859 doitem(exports.AST_Node);
24860 return out + "";
24861};
24862
24863function readReservedFile(filename, reserved) {
24864 if (!reserved) {
24865 reserved = { vars: [], props: [] };
24866 }
24867 var data = rjsFile.readFile(filename, "utf8");
24868 data = JSON.parse(data);
24869 if (data.vars) {
24870 data.vars.forEach(function(name){
24871 exports.push_uniq(reserved.vars, name);
24872 });
24873 }
24874 if (data.props) {
24875 data.props.forEach(function(name){
24876 exports.push_uniq(reserved.props, name);
24877 });
24878 }
24879 return reserved;
24880}
24881
24882exports.readReservedFile = readReservedFile;
24883
24884exports.readDefaultReservedFile = function(reserved) {
24885 return readReservedFile(require.resolve("./domprops.json"), reserved);
24886};
24887
24888exports.readNameCache = function(filename, key) {
24889 var cache = null;
24890 if (filename) {
24891 try {
24892 var cache = rjsFile.readFile(filename, "utf8");
24893 cache = JSON.parse(cache)[key];
24894 if (!cache) throw "init";
24895 cache.props = exports.Dictionary.fromObject(cache.props);
24896 } catch(ex) {
24897 cache = {
24898 cname: -1,
24899 props: new exports.Dictionary()
24900 };
24901 }
24902 }
24903 return cache;
24904};
24905
24906exports.writeNameCache = function(filename, key, cache) {
24907 if (filename) {
24908 var data;
24909 try {
24910 data = rjsFile.readFile(filename, "utf8");
24911 data = JSON.parse(data);
24912 } catch(ex) {
24913 data = {};
24914 }
24915 data[key] = {
24916 cname: cache.cname,
24917 props: cache.props.toObject()
24918 };
24919 rjsFile.writeFile(filename, JSON.stringify(data, null, 2), "utf8");
24920 }
24921};
24922
24923// A file glob function that only supports "*" and "?" wildcards in the basename.
24924// Example: "foo/bar/*baz??.*.js"
24925// Argument `glob` may be a string or an array of strings.
24926// Returns an array of strings. Garbage in, garbage out.
24927exports.simple_glob = function simple_glob(glob) {
24928 if (Array.isArray(glob)) {
24929 return [].concat.apply([], glob.map(simple_glob));
24930 }
24931 if (glob.match(/\*|\?/)) {
24932 var dir = path.dirname(glob);
24933 try {
24934 var entries = fs.readdirSync(dir);
24935 } catch (ex) {}
24936 if (entries) {
24937 var pattern = "^" + path.basename(glob)
24938 .replace(/[.+^$[\]\\(){}]/g, "\\$&")
24939 .replace(/\*/g, "[^/\\\\]*")
24940 .replace(/\?/g, "[^/\\\\]") + "$";
24941 var mod = process.platform === "win32" ? "i" : "";
24942 var rx = new RegExp(pattern, mod);
24943 var results = entries.filter(function(name) {
24944 return rx.test(name);
24945 }).map(function(name) {
24946 return path.join(dir, name);
24947 });
24948 if (results.length) return results;
24949 }
24950 }
24951 return [ glob ];
24952};
24953
24954
24955});
24956/*jslint plusplus: true */
24957/*global define: false */
24958
24959define('parse', ['./esprimaAdapter', 'lang'], function (esprima, lang) {
24960 'use strict';
24961
24962 function arrayToString(ary) {
24963 var output = '[';
24964 if (ary) {
24965 ary.forEach(function (item, i) {
24966 output += (i > 0 ? ',' : '') + '"' + lang.jsEscape(item) + '"';
24967 });
24968 }
24969 output += ']';
24970
24971 return output;
24972 }
24973
24974 //This string is saved off because JSLint complains
24975 //about obj.arguments use, as 'reserved word'
24976 var argPropName = 'arguments',
24977 //Default object to use for "scope" checking for UMD identifiers.
24978 emptyScope = {},
24979 mixin = lang.mixin,
24980 hasProp = lang.hasProp;
24981
24982 //From an esprima example for traversing its ast.
24983 function traverse(object, visitor) {
24984 var child;
24985
24986 if (!object) {
24987 return;
24988 }
24989
24990 if (visitor.call(null, object) === false) {
24991 return false;
24992 }
24993 for (var i = 0, keys = Object.keys(object); i < keys.length; i++) {
24994 child = object[keys[i]];
24995 if (typeof child === 'object' && child !== null) {
24996 if (traverse(child, visitor) === false) {
24997 return false;
24998 }
24999 }
25000 }
25001 }
25002
25003 //Like traverse, but visitor returning false just
25004 //stops that subtree analysis, not the rest of tree
25005 //visiting.
25006 function traverseBroad(object, visitor) {
25007 var child;
25008
25009 if (!object) {
25010 return;
25011 }
25012
25013 if (visitor.call(null, object) === false) {
25014 return false;
25015 }
25016 for (var i = 0, keys = Object.keys(object); i < keys.length; i++) {
25017 child = object[key];
25018 if (typeof child === 'object' && child !== null) {
25019 traverseBroad(child, visitor);
25020 }
25021 }
25022 }
25023
25024 /**
25025 * Pulls out dependencies from an array literal with just string members.
25026 * If string literals, will just return those string values in an array,
25027 * skipping other items in the array.
25028 *
25029 * @param {Node} node an AST node.
25030 *
25031 * @returns {Array} an array of strings.
25032 * If null is returned, then it means the input node was not a valid
25033 * dependency.
25034 */
25035 function getValidDeps(node) {
25036 if (!node || node.type !== 'ArrayExpression' || !node.elements) {
25037 return;
25038 }
25039
25040 var deps = [];
25041
25042 node.elements.some(function (elem) {
25043 if (elem.type === 'Literal') {
25044 deps.push(elem.value);
25045 }
25046 });
25047
25048 return deps.length ? deps : undefined;
25049 }
25050
25051 // Detects regular or arrow function expressions as the desired expression
25052 // type.
25053 function isFnExpression(node) {
25054 return (node && (node.type === 'FunctionExpression' ||
25055 node.type === 'ArrowFunctionExpression'));
25056 }
25057
25058 /**
25059 * Main parse function. Returns a string of any valid require or
25060 * define/require.def calls as part of one JavaScript source string.
25061 * @param {String} moduleName the module name that represents this file.
25062 * It is used to create a default define if there is not one already for the
25063 * file. This allows properly tracing dependencies for builds. Otherwise, if
25064 * the file just has a require() call, the file dependencies will not be
25065 * properly reflected: the file will come before its dependencies.
25066 * @param {String} moduleName
25067 * @param {String} fileName
25068 * @param {String} fileContents
25069 * @param {Object} options optional options. insertNeedsDefine: true will
25070 * add calls to require.needsDefine() if appropriate.
25071 * @returns {String} JS source string or null, if no require or
25072 * define/require.def calls are found.
25073 */
25074 function parse(moduleName, fileName, fileContents, options) {
25075 options = options || {};
25076
25077 //Set up source input
25078 var i, moduleCall, depString,
25079 moduleDeps = [],
25080 result = '',
25081 moduleList = [],
25082 needsDefine = true,
25083 astRoot = esprima.parse(fileContents);
25084
25085 parse.recurse(astRoot, function (callName, config, name, deps, node, factoryIdentifier, fnExpScope) {
25086 if (!deps) {
25087 deps = [];
25088 }
25089
25090 if (callName === 'define' && (!name || name === moduleName)) {
25091 needsDefine = false;
25092 }
25093
25094 if (!name) {
25095 //If there is no module name, the dependencies are for
25096 //this file/default module name.
25097 moduleDeps = moduleDeps.concat(deps);
25098 } else {
25099 moduleList.push({
25100 name: name,
25101 deps: deps
25102 });
25103 }
25104
25105 if (callName === 'define' && factoryIdentifier && hasProp(fnExpScope, factoryIdentifier)) {
25106 return factoryIdentifier;
25107 }
25108
25109 //If define was found, no need to dive deeper, unless
25110 //the config explicitly wants to dig deeper.
25111 return !!options.findNestedDependencies;
25112 }, options);
25113
25114 if (options.insertNeedsDefine && needsDefine) {
25115 result += 'require.needsDefine("' + moduleName + '");';
25116 }
25117
25118 if (moduleDeps.length || moduleList.length) {
25119 for (i = 0; i < moduleList.length; i++) {
25120 moduleCall = moduleList[i];
25121 if (result) {
25122 result += '\n';
25123 }
25124
25125 //If this is the main module for this file, combine any
25126 //"anonymous" dependencies (could come from a nested require
25127 //call) with this module.
25128 if (moduleCall.name === moduleName) {
25129 moduleCall.deps = moduleCall.deps.concat(moduleDeps);
25130 moduleDeps = [];
25131 }
25132
25133 depString = arrayToString(moduleCall.deps);
25134 result += 'define("' + moduleCall.name + '",' +
25135 depString + ');';
25136 }
25137 if (moduleDeps.length) {
25138 if (result) {
25139 result += '\n';
25140 }
25141 depString = arrayToString(moduleDeps);
25142 result += 'define("' + moduleName + '",' + depString + ');';
25143 }
25144 }
25145
25146 return result || null;
25147 }
25148
25149 parse.traverse = traverse;
25150 parse.traverseBroad = traverseBroad;
25151 parse.isFnExpression = isFnExpression;
25152
25153 /**
25154 * Handles parsing a file recursively for require calls.
25155 * @param {Array} parentNode the AST node to start with.
25156 * @param {Function} onMatch function to call on a parse match.
25157 * @param {Object} [options] This is normally the build config options if
25158 * it is passed.
25159 * @param {Object} [fnExpScope] holds list of function expresssion
25160 * argument identifiers, set up internally, not passed in
25161 */
25162 parse.recurse = function (object, onMatch, options, fnExpScope) {
25163 //Like traverse, but skips if branches that would not be processed
25164 //after has application that results in tests of true or false boolean
25165 //literal values.
25166 var keys, child, result, i, params, param, tempObject,
25167 hasHas = options && options.has;
25168
25169 fnExpScope = fnExpScope || emptyScope;
25170
25171 if (!object) {
25172 return;
25173 }
25174
25175 //If has replacement has resulted in if(true){} or if(false){}, take
25176 //the appropriate branch and skip the other one.
25177 if (hasHas && object.type === 'IfStatement' && object.test.type &&
25178 object.test.type === 'Literal') {
25179 if (object.test.value) {
25180 //Take the if branch
25181 this.recurse(object.consequent, onMatch, options, fnExpScope);
25182 } else {
25183 //Take the else branch
25184 this.recurse(object.alternate, onMatch, options, fnExpScope);
25185 }
25186 } else {
25187 result = this.parseNode(object, onMatch, fnExpScope);
25188 if (result === false) {
25189 return;
25190 } else if (typeof result === 'string') {
25191 return result;
25192 }
25193
25194 //Build up a "scope" object that informs nested recurse calls if
25195 //the define call references an identifier that is likely a UMD
25196 //wrapped function expression argument.
25197 //Catch (function(a) {... wrappers
25198 if (object.type === 'ExpressionStatement' && object.expression &&
25199 object.expression.type === 'CallExpression' && object.expression.callee &&
25200 isFnExpression(object.expression.callee)) {
25201 tempObject = object.expression.callee;
25202 }
25203 // Catch !function(a) {... wrappers
25204 if (object.type === 'UnaryExpression' && object.argument &&
25205 object.argument.type === 'CallExpression' && object.argument.callee &&
25206 isFnExpression(object.argument.callee)) {
25207 tempObject = object.argument.callee;
25208 }
25209 if (tempObject && tempObject.params && tempObject.params.length) {
25210 params = tempObject.params;
25211 fnExpScope = mixin({}, fnExpScope, true);
25212 for (i = 0; i < params.length; i++) {
25213 param = params[i];
25214 if (param.type === 'Identifier') {
25215 fnExpScope[param.name] = true;
25216 }
25217 }
25218 }
25219
25220 for (i = 0, keys = Object.keys(object); i < keys.length; i++) {
25221 child = object[keys[i]];
25222 if (typeof child === 'object' && child !== null) {
25223 result = this.recurse(child, onMatch, options, fnExpScope);
25224 if (typeof result === 'string' && hasProp(fnExpScope, result)) {
25225 //The result was still in fnExpScope so break. Otherwise,
25226 //was a return from a a tree that had a UMD definition,
25227 //but now out of that scope so keep siblings.
25228 break;
25229 }
25230 }
25231 }
25232
25233 //Check for an identifier for a factory function identifier being
25234 //passed in as a function expression, indicating a UMD-type of
25235 //wrapping.
25236 if (typeof result === 'string') {
25237 if (hasProp(fnExpScope, result)) {
25238 //result still in scope, keep jumping out indicating the
25239 //identifier still in use.
25240 return result;
25241 }
25242
25243 return;
25244 }
25245 }
25246 };
25247
25248 /**
25249 * Determines if the file defines the require/define module API.
25250 * Specifically, it looks for the `define.amd = ` expression.
25251 * @param {String} fileName
25252 * @param {String} fileContents
25253 * @returns {Boolean}
25254 */
25255 parse.definesRequire = function (fileName, fileContents) {
25256 var foundDefine = false,
25257 foundDefineAmd = false;
25258
25259 traverse(esprima.parse(fileContents), function (node) {
25260 // Look for a top level declaration of a define, like
25261 // var requirejs, require, define, off Program body.
25262 if (node.type === 'Program' && node.body && node.body.length) {
25263 foundDefine = node.body.some(function(bodyNode) {
25264 // var define
25265 if (bodyNode.type === 'VariableDeclaration') {
25266 var decls = bodyNode.declarations;
25267 if (decls) {
25268 var hasVarDefine = decls.some(function(declNode) {
25269 return (declNode.type === 'VariableDeclarator' &&
25270 declNode.id &&
25271 declNode.id.type === 'Identifier' &&
25272 declNode.id.name === 'define');
25273 });
25274 if (hasVarDefine) {
25275 return true;
25276 }
25277 }
25278 }
25279
25280 // function define() {}
25281 if (bodyNode.type === 'FunctionDeclaration' &&
25282 bodyNode.id &&
25283 bodyNode.id.type === 'Identifier' &&
25284 bodyNode.id.name === 'define') {
25285 return true;
25286 }
25287
25288
25289
25290
25291
25292
25293 });
25294 }
25295
25296 // Need define variable found first, before detecting define.amd.
25297 if (foundDefine && parse.hasDefineAmd(node)) {
25298 foundDefineAmd = true;
25299
25300 //Stop traversal
25301 return false;
25302 }
25303 });
25304
25305 return foundDefine && foundDefineAmd;
25306 };
25307
25308 /**
25309 * Finds require("") calls inside a CommonJS anonymous module wrapped in a
25310 * define(function(require, exports, module){}) wrapper. These dependencies
25311 * will be added to a modified define() call that lists the dependencies
25312 * on the outside of the function.
25313 * @param {String} fileName
25314 * @param {String|Object} fileContents: a string of contents, or an already
25315 * parsed AST tree.
25316 * @returns {Array} an array of module names that are dependencies. Always
25317 * returns an array, but could be of length zero.
25318 */
25319 parse.getAnonDeps = function (fileName, fileContents) {
25320 var astRoot = typeof fileContents === 'string' ?
25321 esprima.parse(fileContents) : fileContents,
25322 defFunc = this.findAnonDefineFactory(astRoot);
25323
25324 return parse.getAnonDepsFromNode(defFunc);
25325 };
25326
25327 /**
25328 * Finds require("") calls inside a CommonJS anonymous module wrapped
25329 * in a define function, given an AST node for the definition function.
25330 * @param {Node} node the AST node for the definition function.
25331 * @returns {Array} and array of dependency names. Can be of zero length.
25332 */
25333 parse.getAnonDepsFromNode = function (node) {
25334 var deps = [],
25335 funcArgLength;
25336
25337 if (node) {
25338 this.findRequireDepNames(node, deps);
25339
25340 //If no deps, still add the standard CommonJS require, exports,
25341 //module, in that order, to the deps, but only if specified as
25342 //function args. In particular, if exports is used, it is favored
25343 //over the return value of the function, so only add it if asked.
25344 funcArgLength = node.params && node.params.length;
25345 if (funcArgLength) {
25346 deps = (funcArgLength > 1 ? ["require", "exports", "module"] :
25347 ["require"]).concat(deps);
25348 }
25349 }
25350 return deps;
25351 };
25352
25353 parse.isDefineNodeWithArgs = function (node) {
25354 return node && node.type === 'CallExpression' &&
25355 node.callee && node.callee.type === 'Identifier' &&
25356 node.callee.name === 'define' && node[argPropName];
25357 };
25358
25359 /**
25360 * Finds the function in define(function (require, exports, module){});
25361 * @param {Array} node
25362 * @returns {Boolean}
25363 */
25364 parse.findAnonDefineFactory = function (node) {
25365 var match;
25366
25367 traverse(node, function (node) {
25368 var arg0, arg1;
25369
25370 if (parse.isDefineNodeWithArgs(node)) {
25371
25372 //Just the factory function passed to define
25373 arg0 = node[argPropName][0];
25374 if (isFnExpression(arg0)) {
25375 match = arg0;
25376 return false;
25377 }
25378
25379 //A string literal module ID followed by the factory function.
25380 arg1 = node[argPropName][1];
25381 if (arg0.type === 'Literal' && isFnExpression(arg1)) {
25382 match = arg1;
25383 return false;
25384 }
25385 }
25386 });
25387
25388 return match;
25389 };
25390
25391 /**
25392 * Finds any config that is passed to requirejs. That includes calls to
25393 * require/requirejs.config(), as well as require({}, ...) and
25394 * requirejs({}, ...)
25395 * @param {String} fileContents
25396 *
25397 * @returns {Object} a config details object with the following properties:
25398 * - config: {Object} the config object found. Can be undefined if no
25399 * config found.
25400 * - range: {Array} the start index and end index in the contents where
25401 * the config was found. Can be undefined if no config found.
25402 * Can throw an error if the config in the file cannot be evaluated in
25403 * a build context to valid JavaScript.
25404 */
25405 parse.findConfig = function (fileContents) {
25406 /*jslint evil: true */
25407 var jsConfig, foundConfig, stringData, foundRange, quote, quoteMatch,
25408 quoteRegExp = /(:\s|\[\s*)(['"])/,
25409 astRoot = esprima.parse(fileContents, {
25410 loc: true
25411 });
25412
25413 traverse(astRoot, function (node) {
25414 var arg,
25415 requireType = parse.hasRequire(node);
25416
25417 if (requireType && (requireType === 'require' ||
25418 requireType === 'requirejs' ||
25419 requireType === 'requireConfig' ||
25420 requireType === 'requirejsConfig')) {
25421
25422 arg = node[argPropName] && node[argPropName][0];
25423
25424 if (arg && arg.type === 'ObjectExpression') {
25425 stringData = parse.nodeToString(fileContents, arg);
25426 jsConfig = stringData.value;
25427 foundRange = stringData.range;
25428 return false;
25429 }
25430 } else {
25431 arg = parse.getRequireObjectLiteral(node);
25432 if (arg) {
25433 stringData = parse.nodeToString(fileContents, arg);
25434 jsConfig = stringData.value;
25435 foundRange = stringData.range;
25436 return false;
25437 }
25438 }
25439 });
25440
25441 if (jsConfig) {
25442 // Eval the config
25443 quoteMatch = quoteRegExp.exec(jsConfig);
25444 quote = (quoteMatch && quoteMatch[2]) || '"';
25445 foundConfig = eval('(' + jsConfig + ')');
25446 }
25447
25448 return {
25449 config: foundConfig,
25450 range: foundRange,
25451 quote: quote
25452 };
25453 };
25454
25455 /** Returns the node for the object literal assigned to require/requirejs,
25456 * for holding a declarative config.
25457 */
25458 parse.getRequireObjectLiteral = function (node) {
25459 if (node.id && node.id.type === 'Identifier' &&
25460 (node.id.name === 'require' || node.id.name === 'requirejs') &&
25461 node.init && node.init.type === 'ObjectExpression') {
25462 return node.init;
25463 }
25464 };
25465
25466 /**
25467 * Renames require/requirejs/define calls to be ns + '.' + require/requirejs/define
25468 * Does *not* do .config calls though. See pragma.namespace for the complete
25469 * set of namespace transforms. This function is used because require calls
25470 * inside a define() call should not be renamed, so a simple regexp is not
25471 * good enough.
25472 * @param {String} fileContents the contents to transform.
25473 * @param {String} ns the namespace, *not* including trailing dot.
25474 * @return {String} the fileContents with the namespace applied
25475 */
25476 parse.renameNamespace = function (fileContents, ns) {
25477 var lines,
25478 locs = [],
25479 astRoot = esprima.parse(fileContents, {
25480 loc: true
25481 });
25482
25483 parse.recurse(astRoot, function (callName, config, name, deps, node) {
25484 locs.push(node.loc);
25485 //Do not recurse into define functions, they should be using
25486 //local defines.
25487 return callName !== 'define';
25488 }, {});
25489
25490 if (locs.length) {
25491 lines = fileContents.split('\n');
25492
25493 //Go backwards through the found locs, adding in the namespace name
25494 //in front.
25495 locs.reverse();
25496 locs.forEach(function (loc) {
25497 var startIndex = loc.start.column,
25498 //start.line is 1-based, not 0 based.
25499 lineIndex = loc.start.line - 1,
25500 line = lines[lineIndex];
25501
25502 lines[lineIndex] = line.substring(0, startIndex) +
25503 ns + '.' +
25504 line.substring(startIndex,
25505 line.length);
25506 });
25507
25508 fileContents = lines.join('\n');
25509 }
25510
25511 return fileContents;
25512 };
25513
25514 /**
25515 * Finds all dependencies specified in dependency arrays and inside
25516 * simplified commonjs wrappers.
25517 * @param {String} fileName
25518 * @param {String} fileContents
25519 *
25520 * @returns {Array} an array of dependency strings. The dependencies
25521 * have not been normalized, they may be relative IDs.
25522 */
25523 parse.findDependencies = function (fileName, fileContents, options) {
25524 var dependencies = [],
25525 astRoot = esprima.parse(fileContents);
25526
25527 parse.recurse(astRoot, function (callName, config, name, deps) {
25528 if (deps) {
25529 dependencies = dependencies.concat(deps);
25530 }
25531 }, options);
25532
25533 return dependencies;
25534 };
25535
25536 /**
25537 * Finds only CJS dependencies, ones that are the form
25538 * require('stringLiteral')
25539 */
25540 parse.findCjsDependencies = function (fileName, fileContents) {
25541 var dependencies = [];
25542
25543 traverse(esprima.parse(fileContents), function (node) {
25544 var arg;
25545
25546 if (node && node.type === 'CallExpression' && node.callee &&
25547 node.callee.type === 'Identifier' &&
25548 node.callee.name === 'require' && node[argPropName] &&
25549 node[argPropName].length === 1) {
25550 arg = node[argPropName][0];
25551 if (arg.type === 'Literal') {
25552 dependencies.push(arg.value);
25553 }
25554 }
25555 });
25556
25557 return dependencies;
25558 };
25559
25560 //function define() {}
25561 parse.hasDefDefine = function (node) {
25562 return node.type === 'FunctionDeclaration' && node.id &&
25563 node.id.type === 'Identifier' && node.id.name === 'define';
25564 };
25565
25566 //define.amd = ...
25567 parse.hasDefineAmd = function (node) {
25568 return node && node.type === 'AssignmentExpression' &&
25569 node.left && node.left.type === 'MemberExpression' &&
25570 node.left.object && node.left.object.name === 'define' &&
25571 node.left.property && node.left.property.name === 'amd';
25572 };
25573
25574 //define.amd reference, as in: if (define.amd)
25575 parse.refsDefineAmd = function (node) {
25576 return node && node.type === 'MemberExpression' &&
25577 node.object && node.object.name === 'define' &&
25578 node.object.type === 'Identifier' &&
25579 node.property && node.property.name === 'amd' &&
25580 node.property.type === 'Identifier';
25581 };
25582
25583 //require(), requirejs(), require.config() and requirejs.config()
25584 parse.hasRequire = function (node) {
25585 var callName,
25586 c = node && node.callee;
25587
25588 if (node && node.type === 'CallExpression' && c) {
25589 if (c.type === 'Identifier' &&
25590 (c.name === 'require' ||
25591 c.name === 'requirejs')) {
25592 //A require/requirejs({}, ...) call
25593 callName = c.name;
25594 } else if (c.type === 'MemberExpression' &&
25595 c.object &&
25596 c.object.type === 'Identifier' &&
25597 (c.object.name === 'require' ||
25598 c.object.name === 'requirejs') &&
25599 c.property && c.property.name === 'config') {
25600 // require/requirejs.config({}) call
25601 callName = c.object.name + 'Config';
25602 }
25603 }
25604
25605 return callName;
25606 };
25607
25608 //define()
25609 parse.hasDefine = function (node) {
25610 return node && node.type === 'CallExpression' && node.callee &&
25611 node.callee.type === 'Identifier' &&
25612 node.callee.name === 'define';
25613 };
25614
25615 /**
25616 * If there is a named define in the file, returns the name. Does not
25617 * scan for mulitple names, just the first one.
25618 */
25619 parse.getNamedDefine = function (fileContents) {
25620 var name;
25621 traverse(esprima.parse(fileContents), function (node) {
25622 if (node && node.type === 'CallExpression' && node.callee &&
25623 node.callee.type === 'Identifier' &&
25624 node.callee.name === 'define' &&
25625 node[argPropName] && node[argPropName][0] &&
25626 node[argPropName][0].type === 'Literal') {
25627 name = node[argPropName][0].value;
25628 return false;
25629 }
25630 });
25631
25632 return name;
25633 };
25634
25635 /**
25636 * Finds all the named define module IDs in a file.
25637 */
25638 parse.getAllNamedDefines = function (fileContents, excludeMap) {
25639 var names = [];
25640 parse.recurse(esprima.parse(fileContents),
25641 function (callName, config, name, deps, node, factoryIdentifier, fnExpScope) {
25642 if (callName === 'define' && name) {
25643 if (!excludeMap.hasOwnProperty(name)) {
25644 names.push(name);
25645 }
25646 }
25647
25648 //If a UMD definition that points to a factory that is an Identifier,
25649 //indicate processing should not traverse inside the UMD definition.
25650 if (callName === 'define' && factoryIdentifier && hasProp(fnExpScope, factoryIdentifier)) {
25651 return factoryIdentifier;
25652 }
25653
25654 //If define was found, no need to dive deeper, unless
25655 //the config explicitly wants to dig deeper.
25656 return true;
25657 }, {});
25658
25659 return names;
25660 };
25661
25662 /**
25663 * Determines if define(), require({}|[]) or requirejs was called in the
25664 * file. Also finds out if define() is declared and if define.amd is called.
25665 */
25666 parse.usesAmdOrRequireJs = function (fileName, fileContents) {
25667 var uses;
25668
25669 traverse(esprima.parse(fileContents), function (node) {
25670 var type, callName, arg;
25671
25672 if (parse.hasDefDefine(node)) {
25673 //function define() {}
25674 type = 'declaresDefine';
25675 } else if (parse.hasDefineAmd(node)) {
25676 type = 'defineAmd';
25677 } else {
25678 callName = parse.hasRequire(node);
25679 if (callName) {
25680 arg = node[argPropName] && node[argPropName][0];
25681 if (arg && (arg.type === 'ObjectExpression' ||
25682 arg.type === 'ArrayExpression')) {
25683 type = callName;
25684 }
25685 } else if (parse.hasDefine(node)) {
25686 type = 'define';
25687 }
25688 }
25689
25690 if (type) {
25691 if (!uses) {
25692 uses = {};
25693 }
25694 uses[type] = true;
25695 }
25696 });
25697
25698 return uses;
25699 };
25700
25701 /**
25702 * Determines if require(''), exports.x =, module.exports =,
25703 * __dirname, __filename are used. So, not strictly traditional CommonJS,
25704 * also checks for Node variants.
25705 */
25706 parse.usesCommonJs = function (fileName, fileContents) {
25707 var uses = null,
25708 assignsExports = false;
25709
25710
25711 traverse(esprima.parse(fileContents), function (node) {
25712 var type,
25713 exp = node.expression || node.init;
25714
25715 if (node.type === 'Identifier' &&
25716 (node.name === '__dirname' || node.name === '__filename')) {
25717 type = node.name.substring(2);
25718 } else if (node.type === 'VariableDeclarator' && node.id &&
25719 node.id.type === 'Identifier' &&
25720 node.id.name === 'exports') {
25721 //Hmm, a variable assignment for exports, so does not use cjs
25722 //exports.
25723 type = 'varExports';
25724 } else if (exp && exp.type === 'AssignmentExpression' && exp.left &&
25725 exp.left.type === 'MemberExpression' && exp.left.object) {
25726 if (exp.left.object.name === 'module' && exp.left.property &&
25727 exp.left.property.name === 'exports') {
25728 type = 'moduleExports';
25729 } else if (exp.left.object.name === 'exports' &&
25730 exp.left.property) {
25731 type = 'exports';
25732 } else if (exp.left.object.type === 'MemberExpression' &&
25733 exp.left.object.object.name === 'module' &&
25734 exp.left.object.property.name === 'exports' &&
25735 exp.left.object.property.type === 'Identifier') {
25736 type = 'moduleExports';
25737 }
25738
25739 } else if (node && node.type === 'CallExpression' && node.callee &&
25740 node.callee.type === 'Identifier' &&
25741 node.callee.name === 'require' && node[argPropName] &&
25742 node[argPropName].length === 1 &&
25743 node[argPropName][0].type === 'Literal') {
25744 type = 'require';
25745 }
25746
25747 if (type) {
25748 if (type === 'varExports') {
25749 assignsExports = true;
25750 } else if (type !== 'exports' || !assignsExports) {
25751 if (!uses) {
25752 uses = {};
25753 }
25754 uses[type] = true;
25755 }
25756 }
25757 });
25758
25759 return uses;
25760 };
25761
25762
25763 parse.findRequireDepNames = function (node, deps) {
25764 traverse(node, function (node) {
25765 var arg;
25766
25767 if (node && node.type === 'CallExpression' && node.callee &&
25768 node.callee.type === 'Identifier' &&
25769 node.callee.name === 'require' &&
25770 node[argPropName] && node[argPropName].length === 1) {
25771
25772 arg = node[argPropName][0];
25773 if (arg.type === 'Literal') {
25774 deps.push(arg.value);
25775 }
25776 }
25777 });
25778 };
25779
25780 /**
25781 * Determines if a specific node is a valid require or define/require.def
25782 * call.
25783 * @param {Array} node
25784 * @param {Function} onMatch a function to call when a match is found.
25785 * It is passed the match name, and the config, name, deps possible args.
25786 * The config, name and deps args are not normalized.
25787 * @param {Object} fnExpScope an object whose keys are all function
25788 * expression identifiers that should be in scope. Useful for UMD wrapper
25789 * detection to avoid parsing more into the wrapped UMD code.
25790 *
25791 * @returns {String} a JS source string with the valid require/define call.
25792 * Otherwise null.
25793 */
25794 parse.parseNode = function (node, onMatch, fnExpScope) {
25795 var name, deps, cjsDeps, arg, factory, exp, refsDefine, bodyNode,
25796 args = node && node[argPropName],
25797 callName = parse.hasRequire(node),
25798 isUmd = false;
25799
25800 if (callName === 'require' || callName === 'requirejs') {
25801 //A plain require/requirejs call
25802 arg = node[argPropName] && node[argPropName][0];
25803 if (arg && arg.type !== 'ArrayExpression') {
25804 if (arg.type === 'ObjectExpression') {
25805 //A config call, try the second arg.
25806 arg = node[argPropName][1];
25807 }
25808 }
25809
25810 deps = getValidDeps(arg);
25811 if (!deps) {
25812 return;
25813 }
25814
25815 return onMatch("require", null, null, deps, node);
25816 } else if (parse.hasDefine(node) && args && args.length) {
25817 name = args[0];
25818 deps = args[1];
25819 factory = args[2];
25820
25821 if (name.type === 'ArrayExpression') {
25822 //No name, adjust args
25823 factory = deps;
25824 deps = name;
25825 name = null;
25826 } else if (isFnExpression(name)) {
25827 //Just the factory, no name or deps
25828 factory = name;
25829 name = deps = null;
25830 } else if (name.type === 'Identifier' && args.length === 1 &&
25831 hasProp(fnExpScope, name.name)) {
25832 //define(e) where e is a UMD identifier for the factory
25833 //function.
25834 isUmd = true;
25835 factory = name;
25836 name = null;
25837 } else if (name.type !== 'Literal') {
25838 //An object literal, just null out
25839 name = deps = factory = null;
25840 }
25841
25842 if (name && name.type === 'Literal' && deps) {
25843 if (isFnExpression(deps)) {
25844 //deps is the factory
25845 factory = deps;
25846 deps = null;
25847 } else if (deps.type === 'ObjectExpression') {
25848 //deps is object literal, null out
25849 deps = factory = null;
25850 } else if (deps.type === 'Identifier') {
25851 if (args.length === 2) {
25852 //define('id', factory)
25853 deps = factory = null;
25854 } else if (args.length === 3 && isFnExpression(factory)) {
25855 //define('id', depsIdentifier, factory)
25856 //Since identifier, cannot know the deps, but do not
25857 //error out, assume they are taken care of outside of
25858 //static parsing.
25859 deps = null;
25860 }
25861 }
25862 }
25863
25864 if (deps && deps.type === 'ArrayExpression') {
25865 deps = getValidDeps(deps);
25866 } else if (isFnExpression(factory)) {
25867 //If no deps and a factory function, could be a commonjs sugar
25868 //wrapper, scan the function for dependencies.
25869 cjsDeps = parse.getAnonDepsFromNode(factory);
25870 if (cjsDeps.length) {
25871 deps = cjsDeps;
25872 }
25873 } else if (deps || (factory && !isUmd)) {
25874 //Does not match the shape of an AMD call.
25875 return;
25876 }
25877
25878 //Just save off the name as a string instead of an AST object.
25879 if (name && name.type === 'Literal') {
25880 name = name.value;
25881 }
25882
25883 return onMatch("define", null, name, deps, node,
25884 (factory && factory.type === 'Identifier' ? factory.name : undefined),
25885 fnExpScope);
25886 } else if (node.type === 'CallExpression' && node.callee &&
25887 isFnExpression(node.callee) &&
25888 node.callee.body && node.callee.body.body &&
25889 node.callee.body.body.length === 1 &&
25890 node.callee.body.body[0].type === 'IfStatement') {
25891 bodyNode = node.callee.body.body[0];
25892 //Look for a define(Identifier) case, but only if inside an
25893 //if that has a define.amd test
25894 if (bodyNode.consequent && bodyNode.consequent.body) {
25895 exp = bodyNode.consequent.body[0];
25896 if (exp.type === 'ExpressionStatement' && exp.expression &&
25897 parse.hasDefine(exp.expression) &&
25898 exp.expression.arguments &&
25899 exp.expression.arguments.length === 1 &&
25900 exp.expression.arguments[0].type === 'Identifier') {
25901
25902 //Calls define(Identifier) as first statement in body.
25903 //Confirm the if test references define.amd
25904 traverse(bodyNode.test, function (node) {
25905 if (parse.refsDefineAmd(node)) {
25906 refsDefine = true;
25907 return false;
25908 }
25909 });
25910
25911 if (refsDefine) {
25912 return onMatch("define", null, null, null, exp.expression,
25913 exp.expression.arguments[0].name, fnExpScope);
25914 }
25915 }
25916 }
25917 }
25918 };
25919
25920 /**
25921 * Converts an AST node into a JS source string by extracting
25922 * the node's location from the given contents string. Assumes
25923 * esprima.parse() with loc was done.
25924 * @param {String} contents
25925 * @param {Object} node
25926 * @returns {String} a JS source string.
25927 */
25928 parse.nodeToString = function (contents, node) {
25929 var extracted,
25930 loc = node.loc,
25931 lines = contents.split('\n'),
25932 firstLine = loc.start.line > 1 ?
25933 lines.slice(0, loc.start.line - 1).join('\n') + '\n' :
25934 '',
25935 preamble = firstLine +
25936 lines[loc.start.line - 1].substring(0, loc.start.column);
25937
25938 if (loc.start.line === loc.end.line) {
25939 extracted = lines[loc.start.line - 1].substring(loc.start.column,
25940 loc.end.column);
25941 } else {
25942 extracted = lines[loc.start.line - 1].substring(loc.start.column) +
25943 '\n' +
25944 lines.slice(loc.start.line, loc.end.line - 1).join('\n') +
25945 '\n' +
25946 lines[loc.end.line - 1].substring(0, loc.end.column);
25947 }
25948
25949 return {
25950 value: extracted,
25951 range: [
25952 preamble.length,
25953 preamble.length + extracted.length
25954 ]
25955 };
25956 };
25957
25958 /**
25959 * Extracts license comments from JS text.
25960 * @param {String} fileName
25961 * @param {String} contents
25962 * @returns {String} a string of license comments.
25963 */
25964 parse.getLicenseComments = function (fileName, contents) {
25965 var commentNode, refNode, subNode, value, i, j,
25966 //xpconnect's Reflect does not support comment or range, but
25967 //prefer continued operation vs strict parity of operation,
25968 //as license comments can be expressed in other ways, like
25969 //via wrap args, or linked via sourcemaps.
25970 ast = esprima.parse(contents, {
25971 comment: true,
25972 range: true
25973 }),
25974 result = '',
25975 existsMap = {},
25976 lineEnd = contents.indexOf('\r') === -1 ? '\n' : '\r\n';
25977
25978 if (ast.comments) {
25979 for (i = 0; i < ast.comments.length; i++) {
25980 commentNode = ast.comments[i];
25981
25982 if (commentNode.type === 'Line') {
25983 value = '//' + commentNode.value + lineEnd;
25984 refNode = commentNode;
25985
25986 if (i + 1 >= ast.comments.length) {
25987 value += lineEnd;
25988 } else {
25989 //Look for immediately adjacent single line comments
25990 //since it could from a multiple line comment made out
25991 //of single line comments. Like this comment.
25992 for (j = i + 1; j < ast.comments.length; j++) {
25993 subNode = ast.comments[j];
25994 if (subNode.type === 'Line' &&
25995 subNode.range[0] === refNode.range[1] + 1) {
25996 //Adjacent single line comment. Collect it.
25997 value += '//' + subNode.value + lineEnd;
25998 refNode = subNode;
25999 } else {
26000 //No more single line comment blocks. Break out
26001 //and continue outer looping.
26002 break;
26003 }
26004 }
26005 value += lineEnd;
26006 i = j - 1;
26007 }
26008 } else {
26009 value = '/*' + commentNode.value + '*/' + lineEnd + lineEnd;
26010 }
26011
26012 if (!existsMap[value] && (value.indexOf('license') !== -1 ||
26013 (commentNode.type === 'Block' &&
26014 value.indexOf('/*!') === 0) ||
26015 value.indexOf('opyright') !== -1 ||
26016 value.indexOf('(c)') !== -1)) {
26017
26018 result += value;
26019 existsMap[value] = true;
26020 }
26021
26022 }
26023 }
26024
26025 return result;
26026 };
26027
26028 return parse;
26029});
26030/*global define */
26031
26032define('transform', [ './esprimaAdapter', './parse', 'logger', 'lang'],
26033function (esprima, parse, logger, lang) {
26034 'use strict';
26035 var transform,
26036 baseIndentRegExp = /^([ \t]+)/,
26037 indentRegExp = /\{[\r\n]+([ \t]+)/,
26038 keyRegExp = /^[_A-Za-z]([A-Za-z\d_]*)$/,
26039 bulkIndentRegExps = {
26040 '\n': /\n/g,
26041 '\r\n': /\r\n/g
26042 };
26043
26044 function applyIndent(str, indent, lineReturn) {
26045 var regExp = bulkIndentRegExps[lineReturn];
26046 return str.replace(regExp, '$&' + indent);
26047 }
26048
26049 transform = {
26050 toTransport: function (namespace, moduleName, path, contents, onFound, options) {
26051 options = options || {};
26052
26053 var astRoot, contentLines, modLine,
26054 foundAnon,
26055 scanCount = 0,
26056 scanReset = false,
26057 defineInfos = [],
26058 applySourceUrl = function (contents) {
26059 if (options.useSourceUrl) {
26060 contents = 'eval("' + lang.jsEscape(contents) +
26061 '\\n//# sourceURL=' + (path.indexOf('/') === 0 ? '' : '/') +
26062 path +
26063 '");\n';
26064 }
26065 return contents;
26066 };
26067
26068 try {
26069 astRoot = esprima.parse(contents, {
26070 loc: true
26071 });
26072 } catch (e) {
26073 logger.trace('toTransport skipping ' + path + ': ' +
26074 e.toString());
26075 return contents;
26076 }
26077
26078 //Find the define calls and their position in the files.
26079 parse.traverse(astRoot, function (node) {
26080 var args, firstArg, firstArgLoc, factoryNode,
26081 needsId, depAction, foundId, init,
26082 sourceUrlData, range,
26083 namespaceExists = false;
26084
26085 // If a bundle script with a define declaration, do not
26086 // parse any further at this level. Likely a built layer
26087 // by some other tool.
26088 if (node.type === 'VariableDeclarator' &&
26089 node.id && node.id.name === 'define' &&
26090 node.id.type === 'Identifier') {
26091 init = node.init;
26092 if (init && init.callee &&
26093 init.callee.type === 'CallExpression' &&
26094 init.callee.callee &&
26095 init.callee.callee.type === 'Identifier' &&
26096 init.callee.callee.name === 'require' &&
26097 init.callee.arguments && init.callee.arguments.length === 1 &&
26098 init.callee.arguments[0].type === 'Literal' &&
26099 init.callee.arguments[0].value &&
26100 init.callee.arguments[0].value.indexOf('amdefine') !== -1) {
26101 // the var define = require('amdefine')(module) case,
26102 // keep going in that case.
26103 } else {
26104 return false;
26105 }
26106 }
26107
26108 namespaceExists = namespace &&
26109 node.type === 'CallExpression' &&
26110 node.callee && node.callee.object &&
26111 node.callee.object.type === 'Identifier' &&
26112 node.callee.object.name === namespace &&
26113 node.callee.property.type === 'Identifier' &&
26114 node.callee.property.name === 'define';
26115
26116 if (namespaceExists || parse.isDefineNodeWithArgs(node)) {
26117 //The arguments are where its at.
26118 args = node.arguments;
26119 if (!args || !args.length) {
26120 return;
26121 }
26122
26123 firstArg = args[0];
26124 firstArgLoc = firstArg.loc;
26125
26126 if (args.length === 1) {
26127 if (firstArg.type === 'Identifier') {
26128 //The define(factory) case, but
26129 //only allow it if one Identifier arg,
26130 //to limit impact of false positives.
26131 needsId = true;
26132 depAction = 'empty';
26133 } else if (parse.isFnExpression(firstArg)) {
26134 //define(function(){})
26135 factoryNode = firstArg;
26136 needsId = true;
26137 depAction = 'scan';
26138 } else if (firstArg.type === 'ObjectExpression') {
26139 //define({});
26140 needsId = true;
26141 depAction = 'skip';
26142 } else if (firstArg.type === 'Literal' &&
26143 typeof firstArg.value === 'number') {
26144 //define('12345');
26145 needsId = true;
26146 depAction = 'skip';
26147 } else if (firstArg.type === 'UnaryExpression' &&
26148 firstArg.operator === '-' &&
26149 firstArg.argument &&
26150 firstArg.argument.type === 'Literal' &&
26151 typeof firstArg.argument.value === 'number') {
26152 //define('-12345');
26153 needsId = true;
26154 depAction = 'skip';
26155 } else if (firstArg.type === 'MemberExpression' &&
26156 firstArg.object &&
26157 firstArg.property &&
26158 firstArg.property.type === 'Identifier') {
26159 //define(this.key);
26160 needsId = true;
26161 depAction = 'empty';
26162 }
26163 } else if (firstArg.type === 'ArrayExpression') {
26164 //define([], ...);
26165 needsId = true;
26166 depAction = 'skip';
26167 } else if (firstArg.type === 'Literal' &&
26168 typeof firstArg.value === 'string') {
26169 //define('string', ....)
26170 //Already has an ID.
26171 needsId = false;
26172 if (args.length === 2 &&
26173 parse.isFnExpression(args[1])) {
26174 //Needs dependency scanning.
26175 factoryNode = args[1];
26176 depAction = 'scan';
26177 } else {
26178 depAction = 'skip';
26179 }
26180 } else {
26181 //Unknown define entity, keep looking, even
26182 //in the subtree for this node.
26183 return;
26184 }
26185
26186 range = {
26187 foundId: foundId,
26188 needsId: needsId,
26189 depAction: depAction,
26190 namespaceExists: namespaceExists,
26191 node: node,
26192 defineLoc: node.loc,
26193 firstArgLoc: firstArgLoc,
26194 factoryNode: factoryNode,
26195 sourceUrlData: sourceUrlData
26196 };
26197
26198 //Only transform ones that do not have IDs. If it has an
26199 //ID but no dependency array, assume it is something like
26200 //a phonegap implementation, that has its own internal
26201 //define that cannot handle dependency array constructs,
26202 //and if it is a named module, then it means it has been
26203 //set for transport form.
26204 if (range.needsId) {
26205 if (foundAnon) {
26206 logger.trace(path + ' has more than one anonymous ' +
26207 'define. May be a built file from another ' +
26208 'build system like, Ender. Skipping normalization.');
26209 defineInfos = [];
26210 return false;
26211 } else {
26212 foundAnon = range;
26213 defineInfos.push(range);
26214 }
26215 } else if (depAction === 'scan') {
26216 scanCount += 1;
26217 if (scanCount > 1) {
26218 //Just go back to an array that just has the
26219 //anon one, since this is an already optimized
26220 //file like the phonegap one.
26221 if (!scanReset) {
26222 defineInfos = foundAnon ? [foundAnon] : [];
26223 scanReset = true;
26224 }
26225 } else {
26226 defineInfos.push(range);
26227 }
26228 }
26229 }
26230 });
26231
26232
26233 if (!defineInfos.length) {
26234 return applySourceUrl(contents);
26235 }
26236
26237 //Reverse the matches, need to start from the bottom of
26238 //the file to modify it, so that the ranges are still true
26239 //further up.
26240 defineInfos.reverse();
26241
26242 contentLines = contents.split('\n');
26243
26244 modLine = function (loc, contentInsertion) {
26245 var startIndex = loc.start.column,
26246 //start.line is 1-based, not 0 based.
26247 lineIndex = loc.start.line - 1,
26248 line = contentLines[lineIndex];
26249 contentLines[lineIndex] = line.substring(0, startIndex) +
26250 contentInsertion +
26251 line.substring(startIndex,
26252 line.length);
26253 };
26254
26255 defineInfos.forEach(function (info) {
26256 var deps,
26257 contentInsertion = '',
26258 depString = '';
26259
26260 //Do the modifications "backwards", in other words, start with the
26261 //one that is farthest down and work up, so that the ranges in the
26262 //defineInfos still apply. So that means deps, id, then namespace.
26263 if (info.needsId && moduleName) {
26264 contentInsertion += "'" + moduleName + "',";
26265 }
26266
26267 if (info.depAction === 'scan') {
26268 deps = parse.getAnonDepsFromNode(info.factoryNode);
26269
26270 if (deps.length) {
26271 depString = '[' + deps.map(function (dep) {
26272 return "'" + dep + "'";
26273 }) + ']';
26274 } else {
26275 depString = '[]';
26276 }
26277 depString += ',';
26278
26279 if (info.factoryNode) {
26280 //Already have a named module, need to insert the
26281 //dependencies after the name.
26282 modLine(info.factoryNode.loc, depString);
26283 } else {
26284 contentInsertion += depString;
26285 }
26286 }
26287
26288 if (contentInsertion) {
26289 modLine(info.firstArgLoc, contentInsertion);
26290 }
26291
26292 //Do namespace last so that ui does not mess upthe parenRange
26293 //used above.
26294 if (namespace && !info.namespaceExists) {
26295 modLine(info.defineLoc, namespace + '.');
26296 }
26297
26298 //Notify any listener for the found info
26299 if (onFound) {
26300 onFound(info);
26301 }
26302 });
26303
26304 contents = contentLines.join('\n');
26305
26306 return applySourceUrl(contents);
26307 },
26308
26309 /**
26310 * Modify the contents of a require.config/requirejs.config call. This
26311 * call will LOSE any existing comments that are in the config string.
26312 *
26313 * @param {String} fileContents String that may contain a config call
26314 * @param {Function} onConfig Function called when the first config
26315 * call is found. It will be passed an Object which is the current
26316 * config, and the onConfig function should return an Object to use
26317 * as the config.
26318 * @return {String} the fileContents with the config changes applied.
26319 */
26320 modifyConfig: function (fileContents, onConfig) {
26321 var details = parse.findConfig(fileContents),
26322 config = details.config;
26323
26324 if (config) {
26325 config = onConfig(config);
26326 if (config) {
26327 return transform.serializeConfig(config,
26328 fileContents,
26329 details.range[0],
26330 details.range[1],
26331 {
26332 quote: details.quote
26333 });
26334 }
26335 }
26336
26337 return fileContents;
26338 },
26339
26340 serializeConfig: function (config, fileContents, start, end, options) {
26341 //Calculate base level of indent
26342 var indent, match, configString, outDentRegExp,
26343 baseIndent = '',
26344 startString = fileContents.substring(0, start),
26345 existingConfigString = fileContents.substring(start, end),
26346 lineReturn = existingConfigString.indexOf('\r') === -1 ? '\n' : '\r\n',
26347 lastReturnIndex = startString.lastIndexOf('\n');
26348
26349 //Get the basic amount of indent for the require config call.
26350 if (lastReturnIndex === -1) {
26351 lastReturnIndex = 0;
26352 }
26353
26354 match = baseIndentRegExp.exec(startString.substring(lastReturnIndex + 1, start));
26355 if (match && match[1]) {
26356 baseIndent = match[1];
26357 }
26358
26359 //Calculate internal indentation for config
26360 match = indentRegExp.exec(existingConfigString);
26361 if (match && match[1]) {
26362 indent = match[1];
26363 }
26364
26365 if (!indent || indent.length < baseIndent) {
26366 indent = ' ';
26367 } else {
26368 indent = indent.substring(baseIndent.length);
26369 }
26370
26371 outDentRegExp = new RegExp('(' + lineReturn + ')' + indent, 'g');
26372
26373 configString = transform.objectToString(config, {
26374 indent: indent,
26375 lineReturn: lineReturn,
26376 outDentRegExp: outDentRegExp,
26377 quote: options && options.quote
26378 });
26379
26380 //Add in the base indenting level.
26381 configString = applyIndent(configString, baseIndent, lineReturn);
26382
26383 return startString + configString + fileContents.substring(end);
26384 },
26385
26386 /**
26387 * Tries converting a JS object to a string. This will likely suck, and
26388 * is tailored to the type of config expected in a loader config call.
26389 * So, hasOwnProperty fields, strings, numbers, arrays and functions,
26390 * no weird recursively referenced stuff.
26391 * @param {Object} obj the object to convert
26392 * @param {Object} options options object with the following values:
26393 * {String} indent the indentation to use for each level
26394 * {String} lineReturn the type of line return to use
26395 * {outDentRegExp} outDentRegExp the regexp to use to outdent functions
26396 * {String} quote the quote type to use, ' or ". Optional. Default is "
26397 * @param {String} totalIndent the total indent to print for this level
26398 * @return {String} a string representation of the object.
26399 */
26400 objectToString: function (obj, options, totalIndent) {
26401 var startBrace, endBrace, nextIndent,
26402 first = true,
26403 value = '',
26404 lineReturn = options.lineReturn,
26405 indent = options.indent,
26406 outDentRegExp = options.outDentRegExp,
26407 quote = options.quote || '"';
26408
26409 totalIndent = totalIndent || '';
26410 nextIndent = totalIndent + indent;
26411
26412 if (obj === null) {
26413 value = 'null';
26414 } else if (obj === undefined) {
26415 value = 'undefined';
26416 } else if (typeof obj === 'number' || typeof obj === 'boolean') {
26417 value = obj;
26418 } else if (typeof obj === 'string') {
26419 //Use double quotes in case the config may also work as JSON.
26420 value = quote + lang.jsEscape(obj) + quote;
26421 } else if (lang.isArray(obj)) {
26422 lang.each(obj, function (item, i) {
26423 value += (i !== 0 ? ',' + lineReturn : '' ) +
26424 nextIndent +
26425 transform.objectToString(item,
26426 options,
26427 nextIndent);
26428 });
26429
26430 startBrace = '[';
26431 endBrace = ']';
26432 } else if (lang.isFunction(obj) || lang.isRegExp(obj)) {
26433 //The outdent regexp just helps pretty up the conversion
26434 //just in node. Rhino strips comments and does a different
26435 //indent scheme for Function toString, so not really helpful
26436 //there.
26437 value = obj.toString().replace(outDentRegExp, '$1');
26438 } else {
26439 //An object
26440 lang.eachProp(obj, function (v, prop) {
26441 value += (first ? '': ',' + lineReturn) +
26442 nextIndent +
26443 (keyRegExp.test(prop) ? prop : quote + lang.jsEscape(prop) + quote )+
26444 ': ' +
26445 transform.objectToString(v,
26446 options,
26447 nextIndent);
26448 first = false;
26449 });
26450 startBrace = '{';
26451 endBrace = '}';
26452 }
26453
26454 if (startBrace) {
26455 value = startBrace +
26456 lineReturn +
26457 value +
26458 lineReturn + totalIndent +
26459 endBrace;
26460 }
26461
26462 return value;
26463 }
26464 };
26465
26466 return transform;
26467});
26468/*jslint regexp: true, plusplus: true */
26469/*global define: false */
26470
26471define('pragma', ['parse', 'logger'], function (parse, logger) {
26472 'use strict';
26473 function Temp() {}
26474
26475 function create(obj, mixin) {
26476 Temp.prototype = obj;
26477 var temp = new Temp(), prop;
26478
26479 //Avoid any extra memory hanging around
26480 Temp.prototype = null;
26481
26482 if (mixin) {
26483 for (prop in mixin) {
26484 if (mixin.hasOwnProperty(prop) && !temp.hasOwnProperty(prop)) {
26485 temp[prop] = mixin[prop];
26486 }
26487 }
26488 }
26489
26490 return temp; // Object
26491 }
26492
26493 var pragma = {
26494 conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
26495 useStrictRegExp: /(^|[^{]\r?\n)['"]use strict['"];/g,
26496 hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
26497 configRegExp: /(^|[^\.])(requirejs|require)(\.config)\s*\(/g,
26498 nsWrapRegExp: /\/\*requirejs namespace: true \*\//,
26499 apiDefRegExp: /var requirejs,\s*require,\s*define;/,
26500 defineCheckRegExp: /typeof(\s+|\s*\(\s*)define(\s*\))?\s*===?\s*["']function["']\s*&&\s*define\s*\.\s*amd/g,
26501 defineStringCheckRegExp: /typeof\s+define\s*===?\s*["']function["']\s*&&\s*define\s*\[\s*["']amd["']\s*\]/g,
26502 defineTypeFirstCheckRegExp: /\s*["']function["']\s*==(=?)\s*typeof\s+define\s*&&\s*define\s*\.\s*amd/g,
26503 defineJQueryRegExp: /typeof\s+define\s*===?\s*["']function["']\s*&&\s*define\s*\.\s*amd\s*&&\s*define\s*\.\s*amd\s*\.\s*jQuery/g,
26504 defineHasRegExp: /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g,
26505 defineTernaryRegExp: /typeof\s+define\s*===?\s*['"]function["']\s*&&\s*define\s*\.\s*amd\s*\?\s*define/,
26506 defineExistsRegExp: /\s+typeof\s+define\s*!==?\s*['"]undefined["']\s*/,
26507 defineExistsAndAmdRegExp: /typeof\s+define\s*!==?\s*['"]undefined["']\s*&&\s*define\s*\.\s*amd\s*/,
26508 amdefineRegExp: /if\s*\(\s*typeof define\s*\!==\s*['"]function['"]\s*\)\s*\{\s*[^\{\}]+amdefine[^\{\}]+\}/g,
26509
26510 removeStrict: function (contents, config) {
26511 return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '$1');
26512 },
26513
26514 namespace: function (fileContents, ns, onLifecycleName) {
26515 if (ns) {
26516 //Namespace require/define calls
26517 fileContents = fileContents.replace(pragma.configRegExp, '$1' + ns + '.$2$3(');
26518
26519
26520 fileContents = parse.renameNamespace(fileContents, ns);
26521
26522 //Namespace define ternary use:
26523 fileContents = fileContents.replace(pragma.defineTernaryRegExp,
26524 "typeof " + ns + ".define === 'function' && " + ns + ".define.amd ? " + ns + ".define");
26525
26526 //Namespace define jquery use:
26527 fileContents = fileContents.replace(pragma.defineJQueryRegExp,
26528 "typeof " + ns + ".define === 'function' && " + ns + ".define.amd && " + ns + ".define.amd.jQuery");
26529
26530 //Namespace has.js define use:
26531 fileContents = fileContents.replace(pragma.defineHasRegExp,
26532 "typeof " + ns + ".define === 'function' && typeof " + ns + ".define.amd === 'object' && " + ns + ".define.amd");
26533
26534 //Namespace async.js define use:
26535 fileContents = fileContents.replace(pragma.defineExistsAndAmdRegExp,
26536 "typeof " + ns + ".define !== 'undefined' && " + ns + ".define.amd");
26537
26538 //Namespace define checks.
26539 //Do these ones last, since they are a subset of the more specific
26540 //checks above.
26541 fileContents = fileContents.replace(pragma.defineCheckRegExp,
26542 "typeof " + ns + ".define === 'function' && " + ns + ".define.amd");
26543 fileContents = fileContents.replace(pragma.defineStringCheckRegExp,
26544 "typeof " + ns + ".define === 'function' && " + ns + ".define['amd']");
26545 fileContents = fileContents.replace(pragma.defineTypeFirstCheckRegExp,
26546 "'function' === typeof " + ns + ".define && " + ns + ".define.amd");
26547 fileContents = fileContents.replace(pragma.defineExistsRegExp,
26548 "typeof " + ns + ".define !== 'undefined'");
26549
26550 //Check for require.js with the require/define definitions
26551 if (pragma.apiDefRegExp.test(fileContents) &&
26552 fileContents.indexOf("if (!" + ns + " || !" + ns + ".requirejs)") === -1) {
26553 //Wrap the file contents in a typeof check, and a function
26554 //to contain the API globals.
26555 fileContents = "var " + ns + ";(function () { if (!" + ns + " || !" + ns + ".requirejs) {\n" +
26556 "if (!" + ns + ") { " + ns + ' = {}; } else { require = ' + ns + '; }\n' +
26557 fileContents +
26558 "\n" +
26559 ns + ".requirejs = requirejs;" +
26560 ns + ".require = require;" +
26561 ns + ".define = define;\n" +
26562 "}\n}());";
26563 }
26564
26565 //Finally, if the file wants a special wrapper because it ties
26566 //in to the requirejs internals in a way that would not fit
26567 //the above matches, do that. Look for /*requirejs namespace: true*/
26568 if (pragma.nsWrapRegExp.test(fileContents)) {
26569 //Remove the pragma.
26570 fileContents = fileContents.replace(pragma.nsWrapRegExp, '');
26571
26572 //Alter the contents.
26573 fileContents = '(function () {\n' +
26574 'var require = ' + ns + '.require,' +
26575 'requirejs = ' + ns + '.requirejs,' +
26576 'define = ' + ns + '.define;\n' +
26577 fileContents +
26578 '\n}());';
26579 }
26580 }
26581
26582 return fileContents;
26583 },
26584
26585 /**
26586 * processes the fileContents for some //>> conditional statements
26587 */
26588 process: function (fileName, fileContents, config, onLifecycleName, pluginCollector) {
26589 /*jslint evil: true */
26590 var foundIndex = -1, startIndex = 0, lineEndIndex, conditionLine,
26591 matches, type, marker, condition, isTrue, endRegExp, endMatches,
26592 endMarkerIndex, shouldInclude, startLength, lifecycleHas, deps,
26593 i, dep, moduleName, collectorMod,
26594 lifecyclePragmas, pragmas = config.pragmas, hasConfig = config.has,
26595 //Legacy arg defined to help in dojo conversion script. Remove later
26596 //when dojo no longer needs conversion:
26597 kwArgs = pragmas;
26598
26599 //Mix in a specific lifecycle scoped object, to allow targeting
26600 //some pragmas/has tests to only when files are saved, or at different
26601 //lifecycle events. Do not bother with kwArgs in this section, since
26602 //the old dojo kwArgs were for all points in the build lifecycle.
26603 if (onLifecycleName) {
26604 lifecyclePragmas = config['pragmas' + onLifecycleName];
26605 lifecycleHas = config['has' + onLifecycleName];
26606
26607 if (lifecyclePragmas) {
26608 pragmas = create(pragmas || {}, lifecyclePragmas);
26609 }
26610
26611 if (lifecycleHas) {
26612 hasConfig = create(hasConfig || {}, lifecycleHas);
26613 }
26614 }
26615
26616 //Replace has references if desired
26617 if (hasConfig) {
26618 fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) {
26619 if (hasConfig.hasOwnProperty(test)) {
26620 return !!hasConfig[test];
26621 }
26622 return match;
26623 });
26624 }
26625
26626 if (!config.skipPragmas) {
26627
26628 while ((foundIndex = fileContents.indexOf("//>>", startIndex)) !== -1) {
26629 //Found a conditional. Get the conditional line.
26630 lineEndIndex = fileContents.indexOf("\n", foundIndex);
26631 if (lineEndIndex === -1) {
26632 lineEndIndex = fileContents.length - 1;
26633 }
26634
26635 //Increment startIndex past the line so the next conditional search can be done.
26636 startIndex = lineEndIndex + 1;
26637
26638 //Break apart the conditional.
26639 conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
26640 matches = conditionLine.match(pragma.conditionalRegExp);
26641 if (matches) {
26642 type = matches[1];
26643 marker = matches[2];
26644 condition = matches[3];
26645 isTrue = false;
26646 //See if the condition is true.
26647 try {
26648 isTrue = !!eval("(" + condition + ")");
26649 } catch (e) {
26650 throw "Error in file: " +
26651 fileName +
26652 ". Conditional comment: " +
26653 conditionLine +
26654 " failed with this error: " + e;
26655 }
26656
26657 //Find the endpoint marker.
26658 endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
26659 endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
26660 if (endMatches) {
26661 endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
26662
26663 //Find the next line return based on the match position.
26664 lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
26665 if (lineEndIndex === -1) {
26666 lineEndIndex = fileContents.length - 1;
26667 }
26668
26669 //Should we include the segment?
26670 shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue));
26671
26672 //Remove the conditional comments, and optionally remove the content inside
26673 //the conditional comments.
26674 startLength = startIndex - foundIndex;
26675 fileContents = fileContents.substring(0, foundIndex) +
26676 (shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") +
26677 fileContents.substring(lineEndIndex + 1, fileContents.length);
26678
26679 //Move startIndex to foundIndex, since that is the new position in the file
26680 //where we need to look for more conditionals in the next while loop pass.
26681 startIndex = foundIndex;
26682 } else {
26683 throw "Error in file: " +
26684 fileName +
26685 ". Cannot find end marker for conditional comment: " +
26686 conditionLine;
26687
26688 }
26689 }
26690 }
26691 }
26692
26693 //If need to find all plugin resources to optimize, do that now,
26694 //before namespacing, since the namespacing will change the API
26695 //names.
26696 //If there is a plugin collector, scan the file for plugin resources.
26697 if (config.optimizeAllPluginResources && pluginCollector) {
26698 try {
26699 deps = parse.findDependencies(fileName, fileContents);
26700 if (deps.length) {
26701 for (i = 0; i < deps.length; i++) {
26702 dep = deps[i];
26703 if (dep.indexOf('!') !== -1) {
26704 moduleName = dep.split('!')[0];
26705 collectorMod = pluginCollector[moduleName];
26706 if (!collectorMod) {
26707 collectorMod = pluginCollector[moduleName] = [];
26708 }
26709 collectorMod.push(dep);
26710 }
26711 }
26712 }
26713 } catch (eDep) {
26714 logger.error('Parse error looking for plugin resources in ' +
26715 fileName + ', skipping.');
26716 }
26717 }
26718
26719 //Strip amdefine use for node-shared modules.
26720 if (!config.keepAmdefine) {
26721 fileContents = fileContents.replace(pragma.amdefineRegExp, '');
26722 }
26723
26724 //Do namespacing
26725 if (onLifecycleName === 'OnSave' && config.namespace) {
26726 fileContents = pragma.namespace(fileContents, config.namespace, onLifecycleName);
26727 }
26728
26729
26730 return pragma.removeStrict(fileContents, config);
26731 }
26732 };
26733
26734 return pragma;
26735});
26736
26737if(env === 'browser') {
26738/*jslint strict: false */
26739/*global define: false */
26740
26741define('browser/optimize', {});
26742
26743}
26744
26745if(env === 'node') {
26746/*jslint strict: false */
26747/*global define: false */
26748
26749define('node/optimize', {});
26750
26751}
26752
26753if(env === 'rhino') {
26754/*jslint sloppy: true, plusplus: true */
26755/*global define, java, Packages, com */
26756
26757define('rhino/optimize', ['logger', 'env!env/file'], function (logger, file) {
26758
26759 //Add .reduce to Rhino so UglifyJS can run in Rhino,
26760 //inspired by https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
26761 //but rewritten for brevity, and to be good enough for use by UglifyJS.
26762 if (!Array.prototype.reduce) {
26763 Array.prototype.reduce = function (fn /*, initialValue */) {
26764 var i = 0,
26765 length = this.length,
26766 accumulator;
26767
26768 if (arguments.length >= 2) {
26769 accumulator = arguments[1];
26770 } else {
26771 if (length) {
26772 while (!(i in this)) {
26773 i++;
26774 }
26775 accumulator = this[i++];
26776 }
26777 }
26778
26779 for (; i < length; i++) {
26780 if (i in this) {
26781 accumulator = fn.call(undefined, accumulator, this[i], i, this);
26782 }
26783 }
26784
26785 return accumulator;
26786 };
26787 }
26788
26789 var JSSourceFilefromCode, optimize,
26790 mapRegExp = /"file":"[^"]+"/;
26791
26792 //Bind to Closure compiler, but if it is not available, do not sweat it.
26793 try {
26794 // Try older closure compiler that worked on Java 6
26795 JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]);
26796 } catch (e) {
26797 try {
26798 // Try for newer closure compiler that needs Java 7+
26799 JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.SourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]);
26800 } catch (e) {
26801 try {
26802 // Try Nashorn style
26803 var stringClass = Java.type("java.lang.String").class;
26804 JSSourceFilefromCode = Java.type("com.google.javascript.jscomp.SourceFile").class.getMethod("fromCode", [stringClass, stringClass]);
26805 } catch (e) {}
26806 }
26807 }
26808
26809 //Helper for closure compiler, because of weird Java-JavaScript interactions.
26810 function closurefromCode(filename, content) {
26811 return JSSourceFilefromCode.invoke(null, [filename, content]);
26812 }
26813
26814
26815 function getFileWriter(fileName, encoding) {
26816 var outFile = new java.io.File(fileName), outWriter, parentDir;
26817
26818 parentDir = outFile.getAbsoluteFile().getParentFile();
26819 if (!parentDir.exists()) {
26820 if (!parentDir.mkdirs()) {
26821 throw "Could not create directory: " + parentDir.getAbsolutePath();
26822 }
26823 }
26824
26825 if (encoding) {
26826 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
26827 } else {
26828 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
26829 }
26830
26831 return new java.io.BufferedWriter(outWriter);
26832 }
26833
26834 optimize = {
26835 closure: function (fileName, fileContents, outFileName, keepLines, config) {
26836 config = config || {};
26837 var result, mappings, optimized, compressed, baseName, writer,
26838 outBaseName, outFileNameMap, outFileNameMapContent,
26839 srcOutFileName, concatNameMap,
26840 jscomp = Packages.com.google.javascript.jscomp,
26841 flags = Packages.com.google.common.flags,
26842 //Set up source input
26843 jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
26844 sourceListArray = new java.util.ArrayList(),
26845 externList = new java.util.ArrayList(),
26846 options, option, FLAG_compilation_level, compiler, externExportsPath,
26847 Compiler = Packages.com.google.javascript.jscomp.Compiler,
26848 CommandLineRunner = Packages.com.google.javascript.jscomp.CommandLineRunner;
26849
26850 logger.trace("Minifying file: " + fileName);
26851
26852 baseName = (new java.io.File(fileName)).getName();
26853
26854 //Set up options
26855 options = new jscomp.CompilerOptions();
26856 for (option in config.CompilerOptions) {
26857 // options are false by default and jslint wanted an if statement in this for loop
26858 if (config.CompilerOptions[option]) {
26859 options[option] = config.CompilerOptions[option];
26860 }
26861
26862 }
26863 options.prettyPrint = keepLines || options.prettyPrint;
26864
26865 FLAG_compilation_level = jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS'];
26866 FLAG_compilation_level.setOptionsForCompilationLevel(options);
26867
26868 if (config.generateSourceMaps) {
26869 mappings = new java.util.ArrayList();
26870
26871 mappings.add(new com.google.javascript.jscomp.SourceMap.LocationMapping(fileName, baseName + ".src.js"));
26872 options.setSourceMapLocationMappings(mappings);
26873 options.setSourceMapOutputPath(fileName + ".map");
26874 }
26875
26876 //If we need to pass an externs file to Closure so that it does not create aliases
26877 //for certain symbols, do so here.
26878 externList.addAll(CommandLineRunner.getDefaultExterns());
26879 if (config.externExportsPath) {
26880 externExportsPath = config.externExportsPath;
26881 externList.add(jscomp.SourceFile.fromFile(externExportsPath));
26882 }
26883
26884 //Trigger the compiler
26885 Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']);
26886 compiler = new Compiler();
26887
26888 //fill the sourceArrrayList; we need the ArrayList because the only overload of compile
26889 //accepting the getDefaultExterns return value (a List) also wants the sources as a List
26890 sourceListArray.add(jsSourceFile);
26891
26892 result = compiler.compile(externList, sourceListArray, options);
26893 if (result.success) {
26894 optimized = String(compiler.toSource());
26895
26896 if (config.generateSourceMaps && result.sourceMap && outFileName) {
26897 outBaseName = (new java.io.File(outFileName)).getName();
26898
26899 srcOutFileName = outFileName + ".src.js";
26900 outFileNameMap = outFileName + ".map";
26901
26902 //If previous .map file exists, move it to the ".src.js"
26903 //location. Need to update the sourceMappingURL part in the
26904 //src.js file too.
26905 if (file.exists(outFileNameMap)) {
26906 concatNameMap = outFileNameMap.replace(/\.map$/, '.src.js.map');
26907 file.saveFile(concatNameMap, file.readFile(outFileNameMap));
26908 file.saveFile(srcOutFileName,
26909 fileContents.replace(/\/\# sourceMappingURL=(.+).map/,
26910 '/# sourceMappingURL=$1.src.js.map'));
26911 } else {
26912 file.saveUtf8File(srcOutFileName, fileContents);
26913 }
26914
26915 writer = getFileWriter(outFileNameMap, "utf-8");
26916 result.sourceMap.appendTo(writer, outFileName);
26917 writer.close();
26918
26919 //Not sure how better to do this, but right now the .map file
26920 //leaks the full OS path in the "file" property. Manually
26921 //modify it to not do that.
26922 file.saveFile(outFileNameMap,
26923 file.readFile(outFileNameMap).replace(mapRegExp, '"file":"' + baseName + '"'));
26924
26925 fileContents = optimized + "\n//# sourceMappingURL=" + outBaseName + ".map";
26926 } else {
26927 fileContents = optimized;
26928 }
26929 return fileContents;
26930 } else {
26931 throw new Error('Cannot closure compile file: ' + fileName + '. Skipping it.');
26932 }
26933
26934 return fileContents;
26935 }
26936 };
26937
26938 return optimize;
26939});
26940}
26941
26942if(env === 'xpconnect') {
26943define('xpconnect/optimize', {});
26944}
26945/*jslint plusplus: true, nomen: true, regexp: true */
26946/*global define: false */
26947
26948define('optimize', [ 'lang', 'logger', 'env!env/optimize', 'env!env/file', 'parse',
26949 'pragma', 'uglifyjs',
26950 'source-map'],
26951function (lang, logger, envOptimize, file, parse,
26952 pragma, uglify,
26953 sourceMap) {
26954 'use strict';
26955
26956 var optimize,
26957 cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/ig,
26958 cssCommentImportRegExp = /\/\*[^\*]*@import[^\*]*\*\//g,
26959 cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g,
26960 protocolRegExp = /^\w+:/,
26961 SourceMapGenerator = sourceMap.SourceMapGenerator,
26962 SourceMapConsumer = sourceMap.SourceMapConsumer,
26963 es5PlusGuidance = 'If the source uses ES2015 or later syntax, please pass "optimize: \'none\'" to r.js and use an ES2015+ compatible minifier after running r.js. The included UglifyJS only understands ES5 or earlier syntax.';
26964
26965 /**
26966 * If an URL from a CSS url value contains start/end quotes, remove them.
26967 * This is not done in the regexp, since my regexp fu is not that strong,
26968 * and the CSS spec allows for ' and " in the URL if they are backslash escaped.
26969 * @param {String} url
26970 */
26971 function cleanCssUrlQuotes(url) {
26972 //Make sure we are not ending in whitespace.
26973 //Not very confident of the css regexps above that there will not be ending
26974 //whitespace.
26975 url = url.replace(/\s+$/, "");
26976
26977 if (url.charAt(0) === "'" || url.charAt(0) === "\"") {
26978 url = url.substring(1, url.length - 1);
26979 }
26980
26981 return url;
26982 }
26983
26984 function fixCssUrlPaths(fileName, path, contents, cssPrefix) {
26985 return contents.replace(cssUrlRegExp, function (fullMatch, urlMatch) {
26986 var firstChar, hasProtocol, parts, i,
26987 fixedUrlMatch = cleanCssUrlQuotes(urlMatch);
26988
26989 fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/");
26990
26991 //Only do the work for relative URLs. Skip things that start with / or #, or have
26992 //a protocol.
26993 firstChar = fixedUrlMatch.charAt(0);
26994 hasProtocol = protocolRegExp.test(fixedUrlMatch);
26995 if (firstChar !== "/" && firstChar !== "#" && !hasProtocol) {
26996 //It is a relative URL, tack on the cssPrefix and path prefix
26997 urlMatch = cssPrefix + path + fixedUrlMatch;
26998 } else if (!hasProtocol) {
26999 logger.trace(fileName + "\n URL not a relative URL, skipping: " + urlMatch);
27000 }
27001
27002 //Collapse .. and .
27003 parts = urlMatch.split("/");
27004 for (i = parts.length - 1; i > 0; i--) {
27005 if (parts[i] === ".") {
27006 parts.splice(i, 1);
27007 } else if (parts[i] === "..") {
27008 if (i !== 0 && parts[i - 1] !== "..") {
27009 parts.splice(i - 1, 2);
27010 i -= 1;
27011 }
27012 }
27013 }
27014
27015 return "url(" + parts.join("/") + ")";
27016 });
27017 }
27018
27019 /**
27020 * Inlines nested stylesheets that have @import calls in them.
27021 * @param {String} fileName the file name
27022 * @param {String} fileContents the file contents
27023 * @param {String} cssImportIgnore comma delimited string of files to ignore
27024 * @param {String} cssPrefix string to be prefixed before relative URLs
27025 * @param {Object} included an object used to track the files already imported
27026 */
27027 function flattenCss(fileName, fileContents, cssImportIgnore, cssPrefix, included, topLevel) {
27028 //Find the last slash in the name.
27029 fileName = fileName.replace(lang.backSlashRegExp, "/");
27030 var endIndex = fileName.lastIndexOf("/"),
27031 //Make a file path based on the last slash.
27032 //If no slash, so must be just a file name. Use empty string then.
27033 filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "",
27034 //store a list of merged files
27035 importList = [],
27036 skippedList = [];
27037
27038 //First make a pass by removing any commented out @import calls.
27039 fileContents = fileContents.replace(cssCommentImportRegExp, '');
27040
27041 //Make sure we have a delimited ignore list to make matching faster
27042 if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") {
27043 cssImportIgnore += ",";
27044 }
27045
27046 fileContents = fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) {
27047 //Only process media type "all" or empty media type rules.
27048 if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) {
27049 skippedList.push(fileName);
27050 return fullMatch;
27051 }
27052
27053 importFileName = cleanCssUrlQuotes(importFileName);
27054
27055 //Ignore the file import if it is part of an ignore list.
27056 if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) {
27057 return fullMatch;
27058 }
27059
27060 //Make sure we have a unix path for the rest of the operation.
27061 importFileName = importFileName.replace(lang.backSlashRegExp, "/");
27062
27063 try {
27064 //if a relative path, then tack on the filePath.
27065 //If it is not a relative path, then the readFile below will fail,
27066 //and we will just skip that import.
27067 var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName,
27068 importContents = file.readFile(fullImportFileName),
27069 importEndIndex, importPath, flat;
27070
27071 //Skip the file if it has already been included.
27072 if (included[fullImportFileName]) {
27073 return '';
27074 }
27075 included[fullImportFileName] = true;
27076
27077 //Make sure to flatten any nested imports.
27078 flat = flattenCss(fullImportFileName, importContents, cssImportIgnore, cssPrefix, included);
27079 importContents = flat.fileContents;
27080
27081 if (flat.importList.length) {
27082 importList.push.apply(importList, flat.importList);
27083 }
27084 if (flat.skippedList.length) {
27085 skippedList.push.apply(skippedList, flat.skippedList);
27086 }
27087
27088 //Make the full import path
27089 importEndIndex = importFileName.lastIndexOf("/");
27090
27091 //Make a file path based on the last slash.
27092 //If no slash, so must be just a file name. Use empty string then.
27093 importPath = (importEndIndex !== -1) ? importFileName.substring(0, importEndIndex + 1) : "";
27094
27095 //fix url() on relative import (#5)
27096 importPath = importPath.replace(/^\.\//, '');
27097
27098 //Modify URL paths to match the path represented by this file.
27099 importContents = fixCssUrlPaths(importFileName, importPath, importContents, cssPrefix);
27100
27101 importList.push(fullImportFileName);
27102 return importContents;
27103 } catch (e) {
27104 logger.warn(fileName + "\n Cannot inline css import, skipping: " + importFileName);
27105 return fullMatch;
27106 }
27107 });
27108
27109 if (cssPrefix && topLevel) {
27110 //Modify URL paths to match the path represented by this file.
27111 fileContents = fixCssUrlPaths(fileName, '', fileContents, cssPrefix);
27112 }
27113
27114 return {
27115 importList : importList,
27116 skippedList: skippedList,
27117 fileContents : fileContents
27118 };
27119 }
27120
27121 optimize = {
27122 /**
27123 * Optimizes a file that contains JavaScript content. Optionally collects
27124 * plugin resources mentioned in a file, and then passes the content
27125 * through an minifier if one is specified via config.optimize.
27126 *
27127 * @param {String} fileName the name of the file to optimize
27128 * @param {String} fileContents the contents to optimize. If this is
27129 * a null value, then fileName will be used to read the fileContents.
27130 * @param {String} outFileName the name of the file to use for the
27131 * saved optimized content.
27132 * @param {Object} config the build config object.
27133 * @param {Array} [pluginCollector] storage for any plugin resources
27134 * found.
27135 */
27136 jsFile: function (fileName, fileContents, outFileName, config, pluginCollector) {
27137 if (!fileContents) {
27138 fileContents = file.readFile(fileName);
27139 }
27140
27141 fileContents = optimize.js(fileName, fileContents, outFileName, config, pluginCollector);
27142
27143 file.saveUtf8File(outFileName, fileContents);
27144 },
27145
27146 /**
27147 * Optimizes a file that contains JavaScript content. Optionally collects
27148 * plugin resources mentioned in a file, and then passes the content
27149 * through an minifier if one is specified via config.optimize.
27150 *
27151 * @param {String} fileName the name of the file that matches the
27152 * fileContents.
27153 * @param {String} fileContents the string of JS to optimize.
27154 * @param {Object} [config] the build config object.
27155 * @param {Array} [pluginCollector] storage for any plugin resources
27156 * found.
27157 */
27158 js: function (fileName, fileContents, outFileName, config, pluginCollector) {
27159 var optFunc, optConfig,
27160 parts = (String(config.optimize)).split('.'),
27161 optimizerName = parts[0],
27162 keepLines = parts[1] === 'keepLines',
27163 licenseContents = '';
27164
27165 config = config || {};
27166
27167 //Apply pragmas/namespace renaming
27168 fileContents = pragma.process(fileName, fileContents, config, 'OnSave', pluginCollector);
27169
27170 //Optimize the JS files if asked.
27171 if (optimizerName && optimizerName !== 'none') {
27172 optFunc = envOptimize[optimizerName] || optimize.optimizers[optimizerName];
27173 if (!optFunc) {
27174 throw new Error('optimizer with name of "' +
27175 optimizerName +
27176 '" not found for this environment');
27177 }
27178
27179 optConfig = config[optimizerName] || {};
27180 if (config.generateSourceMaps) {
27181 optConfig.generateSourceMaps = !!config.generateSourceMaps;
27182 optConfig._buildSourceMap = config._buildSourceMap;
27183 }
27184
27185 try {
27186 if (config.preserveLicenseComments) {
27187 //Pull out any license comments for prepending after optimization.
27188 try {
27189 licenseContents = parse.getLicenseComments(fileName, fileContents);
27190 } catch (e) {
27191 throw new Error('Cannot parse file: ' + fileName + ' for comments. Skipping it. Error is:\n' + e.toString());
27192 }
27193 }
27194
27195 if (config.generateSourceMaps && licenseContents) {
27196 optConfig.preamble = licenseContents;
27197 licenseContents = '';
27198 }
27199
27200 fileContents = licenseContents + optFunc(fileName,
27201 fileContents,
27202 outFileName,
27203 keepLines,
27204 optConfig);
27205 if (optConfig._buildSourceMap && optConfig._buildSourceMap !== config._buildSourceMap) {
27206 config._buildSourceMap = optConfig._buildSourceMap;
27207 }
27208 } catch (e) {
27209 if (config.throwWhen && config.throwWhen.optimize) {
27210 throw e;
27211 } else {
27212 logger.error(e);
27213 }
27214 }
27215 } else {
27216 if (config._buildSourceMap) {
27217 config._buildSourceMap = null;
27218 }
27219 }
27220
27221 return fileContents;
27222 },
27223
27224 /**
27225 * Optimizes one CSS file, inlining @import calls, stripping comments, and
27226 * optionally removes line returns.
27227 * @param {String} fileName the path to the CSS file to optimize
27228 * @param {String} outFileName the path to save the optimized file.
27229 * @param {Object} config the config object with the optimizeCss and
27230 * cssImportIgnore options.
27231 */
27232 cssFile: function (fileName, outFileName, config) {
27233
27234 //Read in the file. Make sure we have a JS string.
27235 var originalFileContents = file.readFile(fileName),
27236 flat = flattenCss(fileName, originalFileContents, config.cssImportIgnore, config.cssPrefix, {}, true),
27237 //Do not use the flattened CSS if there was one that was skipped.
27238 fileContents = flat.skippedList.length ? originalFileContents : flat.fileContents,
27239 startIndex, endIndex, buildText, comment;
27240
27241 if (flat.skippedList.length) {
27242 logger.warn('Cannot inline @imports for ' + fileName +
27243 ',\nthe following files had media queries in them:\n' +
27244 flat.skippedList.join('\n'));
27245 }
27246
27247 //Do comment removal.
27248 try {
27249 if (config.optimizeCss.indexOf(".keepComments") === -1) {
27250 startIndex = 0;
27251 //Get rid of comments.
27252 while ((startIndex = fileContents.indexOf("/*", startIndex)) !== -1) {
27253 endIndex = fileContents.indexOf("*/", startIndex + 2);
27254 if (endIndex === -1) {
27255 throw "Improper comment in CSS file: " + fileName;
27256 }
27257 comment = fileContents.substring(startIndex, endIndex);
27258
27259 if (config.preserveLicenseComments &&
27260 (comment.indexOf('license') !== -1 ||
27261 comment.indexOf('opyright') !== -1 ||
27262 comment.indexOf('(c)') !== -1)) {
27263 //Keep the comment, just increment the startIndex
27264 startIndex = endIndex;
27265 } else {
27266 fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length);
27267 startIndex = 0;
27268 }
27269 }
27270 }
27271 //Get rid of newlines.
27272 if (config.optimizeCss.indexOf(".keepLines") === -1) {
27273 fileContents = fileContents.replace(/[\r\n]/g, " ");
27274 fileContents = fileContents.replace(/\s+/g, " ");
27275 fileContents = fileContents.replace(/\{\s/g, "{");
27276 fileContents = fileContents.replace(/\s\}/g, "}");
27277 } else {
27278 //Remove multiple empty lines.
27279 fileContents = fileContents.replace(/(\r\n)+/g, "\r\n");
27280 fileContents = fileContents.replace(/(\n)+/g, "\n");
27281 }
27282 //Remove unnecessary whitespace
27283 if (config.optimizeCss.indexOf(".keepWhitespace") === -1) {
27284 //Remove leading and trailing whitespace from lines
27285 fileContents = fileContents.replace(/^[ \t]+/gm, "");
27286 fileContents = fileContents.replace(/[ \t]+$/gm, "");
27287 //Remove whitespace after semicolon, colon, curly brackets and commas
27288 fileContents = fileContents.replace(/(;|:|\{|}|,)[ \t]+/g, "$1");
27289 //Remove whitespace before opening curly brackets
27290 fileContents = fileContents.replace(/[ \t]+(\{)/g, "$1");
27291 //Truncate double whitespace
27292 fileContents = fileContents.replace(/([ \t])+/g, "$1");
27293 //Remove empty lines
27294 fileContents = fileContents.replace(/^[ \t]*[\r\n]/gm,'');
27295 }
27296 } catch (e) {
27297 fileContents = originalFileContents;
27298 logger.error("Could not optimized CSS file: " + fileName + ", error: " + e);
27299 }
27300
27301 file.saveUtf8File(outFileName, fileContents);
27302
27303 //text output to stdout and/or written to build.txt file
27304 buildText = "\n"+ outFileName.replace(config.dir, "") +"\n----------------\n";
27305 flat.importList.push(fileName);
27306 buildText += flat.importList.map(function(path){
27307 return path.replace(config.dir, "");
27308 }).join("\n");
27309
27310 return {
27311 importList: flat.importList,
27312 buildText: buildText +"\n"
27313 };
27314 },
27315
27316 /**
27317 * Optimizes CSS files, inlining @import calls, stripping comments, and
27318 * optionally removes line returns.
27319 * @param {String} startDir the path to the top level directory
27320 * @param {Object} config the config object with the optimizeCss and
27321 * cssImportIgnore options.
27322 */
27323 css: function (startDir, config) {
27324 var buildText = "",
27325 importList = [],
27326 shouldRemove = config.dir && config.removeCombined,
27327 i, fileName, result, fileList;
27328 if (config.optimizeCss.indexOf("standard") !== -1) {
27329 fileList = file.getFilteredFileList(startDir, /\.css$/, true);
27330 if (fileList) {
27331 for (i = 0; i < fileList.length; i++) {
27332 fileName = fileList[i];
27333 logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName);
27334 result = optimize.cssFile(fileName, fileName, config);
27335 buildText += result.buildText;
27336 if (shouldRemove) {
27337 result.importList.pop();
27338 importList = importList.concat(result.importList);
27339 }
27340 }
27341 }
27342
27343 if (shouldRemove) {
27344 importList.forEach(function (path) {
27345 if (file.exists(path)) {
27346 file.deleteFile(path);
27347 }
27348 });
27349 }
27350 }
27351 return buildText;
27352 },
27353
27354 optimizers: {
27355 uglify: function (fileName, fileContents, outFileName, keepLines, config) {
27356 var result, existingMap, resultMap, finalMap, sourceIndex,
27357 uconfig = {},
27358 existingMapPath = outFileName + '.map',
27359 baseName = fileName && fileName.split('/').pop();
27360
27361 config = config || {};
27362
27363 lang.mixin(uconfig, config, true);
27364
27365 uconfig.fromString = true;
27366
27367 if (config.preamble) {
27368 uconfig.output = {preamble: config.preamble};
27369 }
27370
27371
27372 if (config.generateSourceMaps && (outFileName || config._buildSourceMap)) {
27373 uconfig.outSourceMap = baseName + '.map';
27374
27375 if (config._buildSourceMap) {
27376 existingMap = JSON.parse(config._buildSourceMap);
27377 uconfig.inSourceMap = existingMap;
27378 } else if (file.exists(existingMapPath)) {
27379 uconfig.inSourceMap = existingMapPath;
27380 existingMap = JSON.parse(file.readFile(existingMapPath));
27381 }
27382 }
27383
27384 logger.trace("Uglify file: " + fileName);
27385
27386 try {
27387 //var tempContents = fileContents.replace(/\/\/\# sourceMappingURL=.*$/, '');
27388 result = uglify.minify(fileContents, uconfig, baseName + '.src.js');
27389 if (uconfig.outSourceMap && result.map) {
27390 resultMap = result.map;
27391 if (!existingMap && !config._buildSourceMap) {
27392 file.saveFile(outFileName + '.src.js', fileContents);
27393 }
27394
27395 fileContents = result.code;
27396
27397 if (config._buildSourceMap) {
27398 config._buildSourceMap = resultMap;
27399 } else {
27400 file.saveFile(outFileName + '.map', resultMap);
27401 }
27402 } else {
27403 fileContents = result.code;
27404 }
27405 } catch (e) {
27406 var errorString = e.toString();
27407 var isSyntaxError = /SyntaxError/.test(errorString);
27408 throw new Error('Cannot uglify file: ' + fileName +
27409 '. Skipping it. Error is:\n' + errorString +
27410 (isSyntaxError ? '\n\n' + es5PlusGuidance : ''));
27411 }
27412 return fileContents;
27413 }
27414 }
27415 };
27416
27417 return optimize;
27418});
27419/*
27420 * This file patches require.js to communicate with the build system.
27421 */
27422
27423//Using sloppy since this uses eval for some code like plugins,
27424//which may not be strict mode compliant. So if use strict is used
27425//below they will have strict rules applied and may cause an error.
27426/*jslint sloppy: true, nomen: true, plusplus: true, regexp: true */
27427/*global require, define: true */
27428
27429//NOT asking for require as a dependency since the goal is to modify the
27430//global require below
27431define('requirePatch', [ 'env!env/file', 'pragma', 'parse', 'lang', 'logger', 'commonJs', 'prim'], function (
27432 file,
27433 pragma,
27434 parse,
27435 lang,
27436 logger,
27437 commonJs,
27438 prim
27439) {
27440
27441 var allowRun = true,
27442 hasProp = lang.hasProp,
27443 falseProp = lang.falseProp,
27444 getOwn = lang.getOwn,
27445 // Used to strip out use strict from toString()'d functions for the
27446 // shim config since they will explicitly want to not be bound by strict,
27447 // but some envs, explicitly xpcshell, adds a use strict.
27448 useStrictRegExp = /['"]use strict['"];/g,
27449 //Absolute path if starts with /, \, or x:
27450 absoluteUrlRegExp = /^[\/\\]|^\w:/;
27451
27452 //Turn off throwing on resolution conflict, that was just an older prim
27453 //idea about finding errors early, but does not comply with how promises
27454 //should operate.
27455 prim.hideResolutionConflict = true;
27456
27457 //This method should be called when the patches to require should take hold.
27458 return function () {
27459 if (!allowRun) {
27460 return;
27461 }
27462 allowRun = false;
27463
27464 var layer,
27465 pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/,
27466 oldNewContext = require.s.newContext,
27467 oldDef,
27468
27469 //create local undefined values for module and exports,
27470 //so that when files are evaled in this function they do not
27471 //see the node values used for r.js
27472 exports,
27473 module;
27474
27475 /**
27476 * Reset "global" build caches that are kept around between
27477 * build layer builds. Useful to do when there are multiple
27478 * top level requirejs.optimize() calls.
27479 */
27480 require._cacheReset = function () {
27481 //Stored raw text caches, used by browser use.
27482 require._cachedRawText = {};
27483 //Stored cached file contents for reuse in other layers.
27484 require._cachedFileContents = {};
27485 //Store which cached files contain a require definition.
27486 require._cachedDefinesRequireUrls = {};
27487 };
27488 require._cacheReset();
27489
27490 /**
27491 * Makes sure the URL is something that can be supported by the
27492 * optimization tool.
27493 * @param {String} url
27494 * @returns {Boolean}
27495 */
27496 require._isSupportedBuildUrl = function (url) {
27497 //Ignore URLs with protocols, hosts or question marks, means either network
27498 //access is needed to fetch it or it is too dynamic. Note that
27499 //on Windows, full paths are used for some urls, which include
27500 //the drive, like c:/something, so need to test for something other
27501 //than just a colon.
27502 if (url.indexOf("://") === -1 && url.indexOf("?") === -1 &&
27503 url.indexOf('empty:') !== 0 && url.indexOf('//') !== 0) {
27504 return true;
27505 } else {
27506 if (!layer.ignoredUrls[url]) {
27507 if (url.indexOf('empty:') === -1) {
27508 logger.info('Cannot optimize network URL, skipping: ' + url);
27509 }
27510 layer.ignoredUrls[url] = true;
27511 }
27512 return false;
27513 }
27514 };
27515
27516 function normalizeUrlWithBase(context, moduleName, url) {
27517 //Adjust the URL if it was not transformed to use baseUrl, but only
27518 //if the URL is not already an absolute path.
27519 if (require.jsExtRegExp.test(moduleName) &&
27520 !absoluteUrlRegExp.test(url)) {
27521 url = (context.config.dir || context.config.dirBaseUrl) + url;
27522 }
27523 return url;
27524 }
27525
27526 //Overrides the new context call to add existing tracking features.
27527 require.s.newContext = function (name) {
27528 var context = oldNewContext(name),
27529 oldEnable = context.enable,
27530 moduleProto = context.Module.prototype,
27531 oldInit = moduleProto.init,
27532 oldCallPlugin = moduleProto.callPlugin;
27533
27534 //Only do this for the context used for building.
27535 if (name === '_') {
27536 //For build contexts, do everything sync
27537 context.nextTick = function (fn) {
27538 fn();
27539 };
27540
27541 context.needFullExec = {};
27542 context.fullExec = {};
27543 context.plugins = {};
27544 context.buildShimExports = {};
27545
27546 //Override the shim exports function generator to just
27547 //spit out strings that can be used in the stringified
27548 //build output.
27549 context.makeShimExports = function (value) {
27550 var fn;
27551 if (context.config.wrapShim) {
27552 fn = function () {
27553 var str = 'return ';
27554 // If specifies an export that is just a global
27555 // name, no dot for a `this.` and such, then also
27556 // attach to the global, for `var a = {}` files
27557 // where the function closure would hide that from
27558 // the global object.
27559 if (value.exports && value.exports.indexOf('.') === -1) {
27560 str += 'root.' + value.exports + ' = ';
27561 }
27562
27563 if (value.init) {
27564 str += '(' + value.init.toString()
27565 .replace(useStrictRegExp, '') + '.apply(this, arguments))';
27566 }
27567 if (value.init && value.exports) {
27568 str += ' || ';
27569 }
27570 if (value.exports) {
27571 str += value.exports;
27572 }
27573 str += ';';
27574 return str;
27575 };
27576 } else {
27577 fn = function () {
27578 return '(function (global) {\n' +
27579 ' return function () {\n' +
27580 ' var ret, fn;\n' +
27581 (value.init ?
27582 (' fn = ' + value.init.toString()
27583 .replace(useStrictRegExp, '') + ';\n' +
27584 ' ret = fn.apply(global, arguments);\n') : '') +
27585 (value.exports ?
27586 ' return ret || global.' + value.exports + ';\n' :
27587 ' return ret;\n') +
27588 ' };\n' +
27589 '}(this))';
27590 };
27591 }
27592
27593 return fn;
27594 };
27595
27596 context.enable = function (depMap, parent) {
27597 var id = depMap.id,
27598 parentId = parent && parent.map.id,
27599 needFullExec = context.needFullExec,
27600 fullExec = context.fullExec,
27601 mod = getOwn(context.registry, id);
27602
27603 if (mod && !mod.defined) {
27604 if (parentId && getOwn(needFullExec, parentId)) {
27605 needFullExec[id] = depMap;
27606 }
27607
27608 } else if ((getOwn(needFullExec, id) && falseProp(fullExec, id)) ||
27609 (parentId && getOwn(needFullExec, parentId) &&
27610 falseProp(fullExec, id))) {
27611 context.require.undef(id);
27612 }
27613
27614 return oldEnable.apply(context, arguments);
27615 };
27616
27617 //Override load so that the file paths can be collected.
27618 context.load = function (moduleName, url) {
27619 /*jslint evil: true */
27620 var contents, pluginBuilderMatch, builderName,
27621 shim, shimExports;
27622
27623 //Do not mark the url as fetched if it is
27624 //not an empty: URL, used by the optimizer.
27625 //In that case we need to be sure to call
27626 //load() for each module that is mapped to
27627 //empty: so that dependencies are satisfied
27628 //correctly.
27629 if (url.indexOf('empty:') === 0) {
27630 delete context.urlFetched[url];
27631 }
27632
27633 //Only handle urls that can be inlined, so that means avoiding some
27634 //URLs like ones that require network access or may be too dynamic,
27635 //like JSONP
27636 if (require._isSupportedBuildUrl(url)) {
27637 //Adjust the URL if it was not transformed to use baseUrl.
27638 url = normalizeUrlWithBase(context, moduleName, url);
27639
27640 //Save the module name to path and path to module name mappings.
27641 layer.buildPathMap[moduleName] = url;
27642 layer.buildFileToModule[url] = moduleName;
27643
27644 if (hasProp(context.plugins, moduleName)) {
27645 //plugins need to have their source evaled as-is.
27646 context.needFullExec[moduleName] = true;
27647 }
27648
27649 prim().start(function () {
27650 if (hasProp(require._cachedFileContents, url) &&
27651 (falseProp(context.needFullExec, moduleName) ||
27652 getOwn(context.fullExec, moduleName))) {
27653 contents = require._cachedFileContents[url];
27654
27655 //If it defines require, mark it so it can be hoisted.
27656 //Done here and in the else below, before the
27657 //else block removes code from the contents.
27658 //Related to #263
27659 if (!layer.existingRequireUrl && require._cachedDefinesRequireUrls[url]) {
27660 layer.existingRequireUrl = url;
27661 }
27662 } else {
27663 //Load the file contents, process for conditionals, then
27664 //evaluate it.
27665 return require._cacheReadAsync(url).then(function (text) {
27666 contents = text;
27667
27668 if (context.config.cjsTranslate &&
27669 (!context.config.shim || !lang.hasProp(context.config.shim, moduleName))) {
27670 contents = commonJs.convert(url, contents);
27671 }
27672
27673 //If there is a read filter, run it now.
27674 if (context.config.onBuildRead) {
27675 contents = context.config.onBuildRead(moduleName, url, contents);
27676 }
27677
27678 contents = pragma.process(url, contents, context.config, 'OnExecute');
27679
27680 //Find out if the file contains a require() definition. Need to know
27681 //this so we can inject plugins right after it, but before they are needed,
27682 //and to make sure this file is first, so that define calls work.
27683 try {
27684 if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) {
27685 layer.existingRequireUrl = url;
27686 require._cachedDefinesRequireUrls[url] = true;
27687 }
27688 } catch (e1) {
27689 throw new Error('Parse error using esprima ' +
27690 'for file: ' + url + '\n' + e1);
27691 }
27692 }).then(function () {
27693 if (hasProp(context.plugins, moduleName)) {
27694 //This is a loader plugin, check to see if it has a build extension,
27695 //otherwise the plugin will act as the plugin builder too.
27696 pluginBuilderMatch = pluginBuilderRegExp.exec(contents);
27697 if (pluginBuilderMatch) {
27698 //Load the plugin builder for the plugin contents.
27699 builderName = context.makeModuleMap(pluginBuilderMatch[3],
27700 context.makeModuleMap(moduleName),
27701 null,
27702 true).id;
27703 return require._cacheReadAsync(context.nameToUrl(builderName));
27704 }
27705 }
27706 return contents;
27707 }).then(function (text) {
27708 contents = text;
27709
27710 //Parse out the require and define calls.
27711 //Do this even for plugins in case they have their own
27712 //dependencies that may be separate to how the pluginBuilder works.
27713 try {
27714 if (falseProp(context.needFullExec, moduleName)) {
27715 contents = parse(moduleName, url, contents, {
27716 insertNeedsDefine: true,
27717 has: context.config.has,
27718 findNestedDependencies: context.config.findNestedDependencies
27719 });
27720 }
27721 } catch (e2) {
27722 throw new Error('Parse error using esprima ' +
27723 'for file: ' + url + '\n' + e2);
27724 }
27725
27726 require._cachedFileContents[url] = contents;
27727 });
27728 }
27729 }).then(function () {
27730 if (contents) {
27731 eval(contents);
27732 }
27733
27734 try {
27735 //If have a string shim config, and this is
27736 //a fully executed module, try to see if
27737 //it created a variable in this eval scope
27738 if (getOwn(context.needFullExec, moduleName)) {
27739 shim = getOwn(context.config.shim, moduleName);
27740 if (shim && shim.exports) {
27741 shimExports = eval(shim.exports);
27742 if (typeof shimExports !== 'undefined') {
27743 context.buildShimExports[moduleName] = shimExports;
27744 }
27745 }
27746 }
27747
27748 //Need to close out completion of this module
27749 //so that listeners will get notified that it is available.
27750 context.completeLoad(moduleName);
27751 } catch (e) {
27752 //Track which module could not complete loading.
27753 if (!e.moduleTree) {
27754 e.moduleTree = [];
27755 }
27756 e.moduleTree.push(moduleName);
27757 throw e;
27758 }
27759 }).then(null, function (eOuter) {
27760
27761 if (!eOuter.fileName) {
27762 eOuter.fileName = url;
27763 }
27764 throw eOuter;
27765 }).end();
27766 } else {
27767 //With unsupported URLs still need to call completeLoad to
27768 //finish loading.
27769 context.completeLoad(moduleName);
27770 }
27771 };
27772
27773 //Marks module has having a name, and optionally executes the
27774 //callback, but only if it meets certain criteria.
27775 context.execCb = function (name, cb, args, exports) {
27776 var buildShimExports = getOwn(layer.context.buildShimExports, name);
27777
27778 if (buildShimExports) {
27779 return buildShimExports;
27780 } else if (cb.__requireJsBuild || getOwn(layer.context.needFullExec, name)) {
27781 return cb.apply(exports, args);
27782 }
27783 return undefined;
27784 };
27785
27786 moduleProto.init = function (depMaps) {
27787 if (context.needFullExec[this.map.id]) {
27788 lang.each(depMaps, lang.bind(this, function (depMap) {
27789 if (typeof depMap === 'string') {
27790 depMap = context.makeModuleMap(depMap,
27791 (this.map.isDefine ? this.map : this.map.parentMap),
27792 false, true);
27793 }
27794
27795 if (!context.fullExec[depMap.id]) {
27796 context.require.undef(depMap.id);
27797 }
27798 }));
27799 }
27800
27801 return oldInit.apply(this, arguments);
27802 };
27803
27804 moduleProto.callPlugin = function () {
27805 var map = this.map,
27806 pluginMap = context.makeModuleMap(map.prefix),
27807 pluginId = pluginMap.id,
27808 pluginMod = getOwn(context.registry, pluginId);
27809
27810 context.plugins[pluginId] = true;
27811 context.needFullExec[pluginId] = map;
27812
27813 //If the module is not waiting to finish being defined,
27814 //undef it and start over, to get full execution.
27815 if (falseProp(context.fullExec, pluginId) && (!pluginMod || pluginMod.defined)) {
27816 context.require.undef(pluginMap.id);
27817 }
27818
27819 return oldCallPlugin.apply(this, arguments);
27820 };
27821 }
27822
27823 return context;
27824 };
27825
27826 //Clear up the existing context so that the newContext modifications
27827 //above will be active.
27828 delete require.s.contexts._;
27829
27830 /** Reset state for each build layer pass. */
27831 require._buildReset = function () {
27832 var oldContext = require.s.contexts._;
27833
27834 //Clear up the existing context.
27835 delete require.s.contexts._;
27836
27837 //Set up new context, so the layer object can hold onto it.
27838 require({});
27839
27840 layer = require._layer = {
27841 buildPathMap: {},
27842 buildFileToModule: {},
27843 buildFilePaths: [],
27844 pathAdded: {},
27845 modulesWithNames: {},
27846 needsDefine: {},
27847 existingRequireUrl: "",
27848 ignoredUrls: {},
27849 context: require.s.contexts._
27850 };
27851
27852 //Return the previous context in case it is needed, like for
27853 //the basic config object.
27854 return oldContext;
27855 };
27856
27857 require._buildReset();
27858
27859 //Override define() to catch modules that just define an object, so that
27860 //a dummy define call is not put in the build file for them. They do
27861 //not end up getting defined via context.execCb, so we need to catch them
27862 //at the define call.
27863 oldDef = define;
27864
27865 //This function signature does not have to be exact, just match what we
27866 //are looking for.
27867 define = function (name) {
27868 if (typeof name === "string" && falseProp(layer.needsDefine, name)) {
27869 layer.modulesWithNames[name] = true;
27870 }
27871 return oldDef.apply(require, arguments);
27872 };
27873
27874 define.amd = oldDef.amd;
27875
27876 //Add some utilities for plugins
27877 require._readFile = file.readFile;
27878 require._fileExists = function (path) {
27879 return file.exists(path);
27880 };
27881
27882 //Called when execManager runs for a dependency. Used to figure out
27883 //what order of execution.
27884 require.onResourceLoad = function (context, map) {
27885 var id = map.id,
27886 url;
27887
27888 // Fix up any maps that need to be normalized as part of the fullExec
27889 // plumbing for plugins to participate in the build.
27890 if (context.plugins && lang.hasProp(context.plugins, id)) {
27891 lang.eachProp(context.needFullExec, function(value, prop) {
27892 // For plugin entries themselves, they do not have a map
27893 // value in needFullExec, just a "true" entry.
27894 if (value !== true && value.prefix === id && value.unnormalized) {
27895 var map = context.makeModuleMap(value.originalName, value.parentMap);
27896 context.needFullExec[map.id] = map;
27897 }
27898 });
27899 }
27900
27901 //If build needed a full execution, indicate it
27902 //has been done now. But only do it if the context is tracking
27903 //that. Only valid for the context used in a build, not for
27904 //other contexts being run, like for useLib, plain requirejs
27905 //use in node/rhino.
27906 if (context.needFullExec && getOwn(context.needFullExec, id)) {
27907 context.fullExec[id] = map;
27908 }
27909
27910 //A plugin.
27911 if (map.prefix) {
27912 if (falseProp(layer.pathAdded, id)) {
27913 layer.buildFilePaths.push(id);
27914 //For plugins the real path is not knowable, use the name
27915 //for both module to file and file to module mappings.
27916 layer.buildPathMap[id] = id;
27917 layer.buildFileToModule[id] = id;
27918 layer.modulesWithNames[id] = true;
27919 layer.pathAdded[id] = true;
27920 }
27921 } else if (map.url && require._isSupportedBuildUrl(map.url)) {
27922 //If the url has not been added to the layer yet, and it
27923 //is from an actual file that was loaded, add it now.
27924 url = normalizeUrlWithBase(context, id, map.url);
27925 if (!layer.pathAdded[url] && getOwn(layer.buildPathMap, id)) {
27926 //Remember the list of dependencies for this layer.
27927 layer.buildFilePaths.push(url);
27928 layer.pathAdded[url] = true;
27929 }
27930 }
27931 };
27932
27933 //Called by output of the parse() function, when a file does not
27934 //explicitly call define, probably just require, but the parse()
27935 //function normalizes on define() for dependency mapping and file
27936 //ordering works correctly.
27937 require.needsDefine = function (moduleName) {
27938 layer.needsDefine[moduleName] = true;
27939 };
27940 };
27941});
27942/*jslint */
27943/*global define: false, console: false */
27944
27945define('commonJs', ['env!env/file', 'parse'], function (file, parse) {
27946 'use strict';
27947 var commonJs = {
27948 //Set to false if you do not want this file to log. Useful in environments
27949 //like node where you want the work to happen without noise.
27950 useLog: true,
27951
27952 convertDir: function (commonJsPath, savePath) {
27953 var fileList, i,
27954 jsFileRegExp = /\.js$/,
27955 fileName, convertedFileName, fileContents;
27956
27957 //Get list of files to convert.
27958 fileList = file.getFilteredFileList(commonJsPath, /\w/, true);
27959
27960 //Normalize on front slashes and make sure the paths do not end in a slash.
27961 commonJsPath = commonJsPath.replace(/\\/g, "/");
27962 savePath = savePath.replace(/\\/g, "/");
27963 if (commonJsPath.charAt(commonJsPath.length - 1) === "/") {
27964 commonJsPath = commonJsPath.substring(0, commonJsPath.length - 1);
27965 }
27966 if (savePath.charAt(savePath.length - 1) === "/") {
27967 savePath = savePath.substring(0, savePath.length - 1);
27968 }
27969
27970 //Cycle through all the JS files and convert them.
27971 if (!fileList || !fileList.length) {
27972 if (commonJs.useLog) {
27973 if (commonJsPath === "convert") {
27974 //A request just to convert one file.
27975 console.log('\n\n' + commonJs.convert(savePath, file.readFile(savePath)));
27976 } else {
27977 console.log("No files to convert in directory: " + commonJsPath);
27978 }
27979 }
27980 } else {
27981 for (i = 0; i < fileList.length; i++) {
27982 fileName = fileList[i];
27983 convertedFileName = fileName.replace(commonJsPath, savePath);
27984
27985 //Handle JS files.
27986 if (jsFileRegExp.test(fileName)) {
27987 fileContents = file.readFile(fileName);
27988 fileContents = commonJs.convert(fileName, fileContents);
27989 file.saveUtf8File(convertedFileName, fileContents);
27990 } else {
27991 //Just copy the file over.
27992 file.copyFile(fileName, convertedFileName, true);
27993 }
27994 }
27995 }
27996 },
27997
27998 /**
27999 * Does the actual file conversion.
28000 *
28001 * @param {String} fileName the name of the file.
28002 *
28003 * @param {String} fileContents the contents of a file :)
28004 *
28005 * @returns {String} the converted contents
28006 */
28007 convert: function (fileName, fileContents) {
28008 //Strip out comments.
28009 try {
28010 var preamble = '',
28011 commonJsProps = parse.usesCommonJs(fileName, fileContents);
28012
28013 //First see if the module is not already RequireJS-formatted.
28014 if (parse.usesAmdOrRequireJs(fileName, fileContents) || !commonJsProps) {
28015 return fileContents;
28016 }
28017
28018 if (commonJsProps.dirname || commonJsProps.filename) {
28019 preamble = 'var __filename = module.uri || "", ' +
28020 '__dirname = __filename.substring(0, __filename.lastIndexOf("/") + 1); ';
28021 }
28022
28023 //Construct the wrapper boilerplate.
28024 fileContents = 'define(function (require, exports, module) {' +
28025 preamble +
28026 fileContents +
28027 '\n});\n';
28028
28029 } catch (e) {
28030 console.log("commonJs.convert: COULD NOT CONVERT: " + fileName + ", so skipping it. Error was: " + e);
28031 return fileContents;
28032 }
28033
28034 return fileContents;
28035 }
28036 };
28037
28038 return commonJs;
28039});
28040/*jslint plusplus: true, nomen: true, regexp: true */
28041/*global define, requirejs, java, process, console */
28042
28043
28044define('build', function (require) {
28045 'use strict';
28046
28047 var build,
28048 lang = require('lang'),
28049 prim = require('prim'),
28050 logger = require('logger'),
28051 file = require('env!env/file'),
28052 parse = require('parse'),
28053 optimize = require('optimize'),
28054 pragma = require('pragma'),
28055 transform = require('transform'),
28056 requirePatch = require('requirePatch'),
28057 env = require('env'),
28058 commonJs = require('commonJs'),
28059 SourceMapGenerator = require('source-map').SourceMapGenerator,
28060 hasProp = lang.hasProp,
28061 getOwn = lang.getOwn,
28062 falseProp = lang.falseProp,
28063 endsWithSemiColonRegExp = /;\s*$/,
28064 endsWithSlashRegExp = /[\/\\]$/,
28065 resourceIsModuleIdRegExp = /^[\w\/\\\.]+$/,
28066 deepCopyProps = {
28067 layer: true
28068 };
28069
28070 //Deep copy a config object, but do not copy over the "layer" property,
28071 //as it can be a deeply nested structure with a full requirejs context.
28072 function copyConfig(obj) {
28073 return lang.deeplikeCopy(obj, deepCopyProps);
28074 }
28075
28076 prim.nextTick = function (fn) {
28077 fn();
28078 };
28079
28080 //Now map require to the outermost requirejs, now that we have
28081 //local dependencies for this module. The rest of the require use is
28082 //manipulating the requirejs loader.
28083 require = requirejs;
28084
28085 //Caching function for performance. Attached to
28086 //require so it can be reused in requirePatch.js. _cachedRawText
28087 //set up by requirePatch.js
28088 require._cacheReadAsync = function (path, encoding) {
28089 var d;
28090
28091 if (lang.hasProp(require._cachedRawText, path)) {
28092 d = prim();
28093 d.resolve(require._cachedRawText[path]);
28094 return d.promise;
28095 } else {
28096 return file.readFileAsync(path, encoding).then(function (text) {
28097 require._cachedRawText[path] = text;
28098 return text;
28099 });
28100 }
28101 };
28102
28103 function makeBuildBaseConfig() {
28104 return {
28105 appDir: "",
28106 pragmas: {},
28107 paths: {},
28108 optimize: "uglify",
28109 optimizeCss: "standard.keepLines.keepWhitespace",
28110 inlineText: true,
28111 isBuild: true,
28112 optimizeAllPluginResources: false,
28113 findNestedDependencies: false,
28114 preserveLicenseComments: true,
28115 writeBuildTxt: true,
28116 //Some builds can take a while, up the default limit.
28117 waitSeconds: 30,
28118 //By default, all files/directories are copied, unless
28119 //they match this regexp, by default just excludes .folders
28120 dirExclusionRegExp: file.dirExclusionRegExp,
28121 _buildPathToModuleIndex: {}
28122 };
28123 }
28124
28125 /**
28126 * Some JS may not be valid if concatenated with other JS, in particular
28127 * the style of omitting semicolons and rely on ASI. Add a semicolon in
28128 * those cases.
28129 */
28130 function addSemiColon(text, config) {
28131 if (config.skipSemiColonInsertion || endsWithSemiColonRegExp.test(text)) {
28132 return text;
28133 } else {
28134 return text + ";";
28135 }
28136 }
28137
28138 function endsWithSlash(dirName) {
28139 if (dirName.charAt(dirName.length - 1) !== "/") {
28140 dirName += "/";
28141 }
28142 return dirName;
28143 }
28144
28145 function endsWithNewLine(text) {
28146 if (text.charAt(text.length - 1) !== "\n") {
28147 text += "\n";
28148 }
28149 return text;
28150 }
28151
28152 //Method used by plugin writeFile calls, defined up here to avoid
28153 //jslint warning about "making a function in a loop".
28154 function makeWriteFile(namespace, layer) {
28155 function writeFile(name, contents) {
28156 logger.trace('Saving plugin-optimized file: ' + name);
28157 file.saveUtf8File(name, contents);
28158 }
28159
28160 writeFile.asModule = function (moduleName, fileName, contents) {
28161 writeFile(fileName,
28162 build.toTransport(namespace, moduleName, fileName, contents, layer));
28163 };
28164
28165 return writeFile;
28166 }
28167
28168 /**
28169 * Appends singleContents to fileContents and returns the result. If a sourceMapGenerator
28170 * is provided, adds singleContents to the source map.
28171 *
28172 * @param {string} fileContents - The file contents to which to append singleContents
28173 * @param {string} singleContents - The additional contents to append to fileContents
28174 * @param {string} path - An absolute path of a file whose name to use in the source map.
28175 * The file need not actually exist if the code in singleContents is generated.
28176 * @param {{out: ?string, baseUrl: ?string}} config - The build configuration object.
28177 * @param {?{_buildPath: ?string}} module - An object with module information.
28178 * @param {?SourceMapGenerator} sourceMapGenerator - An instance of Mozilla's SourceMapGenerator,
28179 * or null if no source map is being generated.
28180 * @returns {string} fileContents with singleContents appended
28181 */
28182 function appendToFileContents(fileContents, singleContents, path, config, module, sourceMapGenerator) {
28183 var refPath, sourceMapPath, resourcePath, pluginId, sourceMapLineNumber, lineCount, parts, i;
28184 if (sourceMapGenerator) {
28185 if (config.out) {
28186 refPath = config.baseUrl;
28187 } else if (module && module._buildPath) {
28188 refPath = module._buildPath;
28189 } else {
28190 refPath = "";
28191 }
28192 parts = path.split('!');
28193 if (parts.length === 1) {
28194 //Not a plugin resource, fix the path
28195 sourceMapPath = build.makeRelativeFilePath(refPath, path);
28196 } else {
28197 //Plugin resource. If it looks like just a plugin
28198 //followed by a module ID, pull off the plugin
28199 //and put it at the end of the name, otherwise
28200 //just leave it alone.
28201 pluginId = parts.shift();
28202 resourcePath = parts.join('!');
28203 if (resourceIsModuleIdRegExp.test(resourcePath)) {
28204 sourceMapPath = build.makeRelativeFilePath(refPath, require.toUrl(resourcePath)) +
28205 '!' + pluginId;
28206 } else {
28207 sourceMapPath = path;
28208 }
28209 }
28210
28211 sourceMapLineNumber = fileContents.split('\n').length - 1;
28212 lineCount = singleContents.split('\n').length;
28213 for (i = 1; i <= lineCount; i += 1) {
28214 sourceMapGenerator.addMapping({
28215 generated: {
28216 line: sourceMapLineNumber + i,
28217 column: 0
28218 },
28219 original: {
28220 line: i,
28221 column: 0
28222 },
28223 source: sourceMapPath
28224 });
28225 }
28226
28227 //Store the content of the original in the source
28228 //map since other transforms later like minification
28229 //can mess up translating back to the original
28230 //source.
28231 sourceMapGenerator.setSourceContent(sourceMapPath, singleContents);
28232 }
28233 fileContents += singleContents;
28234 return fileContents;
28235 }
28236
28237 /**
28238 * Main API entry point into the build. The args argument can either be
28239 * an array of arguments (like the onese passed on a command-line),
28240 * or it can be a JavaScript object that has the format of a build profile
28241 * file.
28242 *
28243 * If it is an object, then in addition to the normal properties allowed in
28244 * a build profile file, the object should contain one other property:
28245 *
28246 * The object could also contain a "buildFile" property, which is a string
28247 * that is the file path to a build profile that contains the rest
28248 * of the build profile directives.
28249 *
28250 * This function does not return a status, it should throw an error if
28251 * there is a problem completing the build.
28252 */
28253 build = function (args) {
28254 var buildFile, cmdConfig, errorMsg, errorStack, stackMatch, errorTree,
28255 i, j, errorMod,
28256 stackRegExp = /( {4}at[^\n]+)\n/,
28257 standardIndent = ' ';
28258
28259 return prim().start(function () {
28260 if (!args || lang.isArray(args)) {
28261 if (!args || args.length < 1) {
28262 logger.error("build.js buildProfile.js\n" +
28263 "where buildProfile.js is the name of the build file (see example.build.js for hints on how to make a build file).");
28264 return undefined;
28265 }
28266
28267 //Next args can include a build file path as well as other build args.
28268 //build file path comes first. If it does not contain an = then it is
28269 //a build file path. Otherwise, just all build args.
28270 if (args[0].indexOf("=") === -1) {
28271 buildFile = args[0];
28272 args.splice(0, 1);
28273 }
28274
28275 //Remaining args are options to the build
28276 cmdConfig = build.convertArrayToObject(args);
28277 cmdConfig.buildFile = buildFile;
28278 } else {
28279 cmdConfig = args;
28280 }
28281
28282 return build._run(cmdConfig);
28283 }).then(null, function (e) {
28284 var err;
28285
28286 errorMsg = e.toString();
28287 errorTree = e.moduleTree;
28288 stackMatch = stackRegExp.exec(errorMsg);
28289
28290 if (stackMatch) {
28291 errorMsg += errorMsg.substring(0, stackMatch.index + stackMatch[0].length + 1);
28292 }
28293
28294 //If a module tree that shows what module triggered the error,
28295 //print it out.
28296 if (errorTree && errorTree.length > 0) {
28297 errorMsg += '\nIn module tree:\n';
28298
28299 for (i = errorTree.length - 1; i > -1; i--) {
28300 errorMod = errorTree[i];
28301 if (errorMod) {
28302 for (j = errorTree.length - i; j > -1; j--) {
28303 errorMsg += standardIndent;
28304 }
28305 errorMsg += errorMod + '\n';
28306 }
28307 }
28308
28309 logger.error(errorMsg);
28310 }
28311
28312 errorStack = e.stack;
28313
28314 if (typeof args === 'string' && args.indexOf('stacktrace=true') !== -1) {
28315 errorMsg += '\n' + errorStack;
28316 } else {
28317 if (!stackMatch && errorStack) {
28318 //Just trim out the first "at" in the stack.
28319 stackMatch = stackRegExp.exec(errorStack);
28320 if (stackMatch) {
28321 errorMsg += '\n' + stackMatch[0] || '';
28322 }
28323 }
28324 }
28325
28326 err = new Error(errorMsg);
28327 err.originalError = e;
28328 throw err;
28329 });
28330 };
28331
28332 build._run = function (cmdConfig) {
28333 var buildPaths, fileName, fileNames,
28334 paths, i,
28335 baseConfig, config,
28336 modules, srcPath, buildContext,
28337 destPath, moduleMap, parentModuleMap, context,
28338 resources, resource, plugin, fileContents,
28339 pluginProcessed = {},
28340 buildFileContents = "",
28341 pluginCollector = {};
28342
28343 return prim().start(function () {
28344 var prop;
28345
28346 //Can now run the patches to require.js to allow it to be used for
28347 //build generation. Do it here instead of at the top of the module
28348 //because we want normal require behavior to load the build tool
28349 //then want to switch to build mode.
28350 requirePatch();
28351
28352 config = build.createConfig(cmdConfig);
28353 paths = config.paths;
28354
28355 //Remove the previous build dir, in case it contains source transforms,
28356 //like the ones done with onBuildRead and onBuildWrite.
28357 if (config.dir && !config.keepBuildDir && file.exists(config.dir)) {
28358 file.deleteFile(config.dir);
28359 }
28360
28361 if (!config.out && !config.cssIn) {
28362 //This is not just a one-off file build but a full build profile, with
28363 //lots of files to process.
28364
28365 //First copy all the baseUrl content
28366 file.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true);
28367
28368 //Adjust baseUrl if config.appDir is in play, and set up build output paths.
28369 buildPaths = {};
28370 if (config.appDir) {
28371 //All the paths should be inside the appDir, so just adjust
28372 //the paths to use the dirBaseUrl
28373 for (prop in paths) {
28374 if (hasProp(paths, prop)) {
28375 buildPaths[prop] = paths[prop].replace(config.appDir, config.dir);
28376 }
28377 }
28378 } else {
28379 //If no appDir, then make sure to copy the other paths to this directory.
28380 for (prop in paths) {
28381 if (hasProp(paths, prop)) {
28382 //Set up build path for each path prefix, but only do so
28383 //if the path falls out of the current baseUrl
28384 if (paths[prop].indexOf(config.baseUrl) === 0) {
28385 buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl);
28386 } else {
28387 buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop;
28388
28389 //Make sure source path is fully formed with baseUrl,
28390 //if it is a relative URL.
28391 srcPath = paths[prop];
28392 if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) {
28393 srcPath = config.baseUrl + srcPath;
28394 }
28395
28396 destPath = config.dirBaseUrl + buildPaths[prop];
28397
28398 //Skip empty: paths
28399 if (srcPath !== 'empty:') {
28400 //If the srcPath is a directory, copy the whole directory.
28401 if (file.exists(srcPath) && file.isDirectory(srcPath)) {
28402 //Copy files to build area. Copy all files (the /\w/ regexp)
28403 file.copyDir(srcPath, destPath, /\w/, true);
28404 } else {
28405 //Try a .js extension
28406 srcPath += '.js';
28407 destPath += '.js';
28408 file.copyFile(srcPath, destPath);
28409 }
28410 }
28411 }
28412 }
28413 }
28414 }
28415 }
28416
28417 //Figure out source file location for each module layer. Do this by seeding require
28418 //with source area configuration. This is needed so that later the module layers
28419 //can be manually copied over to the source area, since the build may be
28420 //require multiple times and the above copyDir call only copies newer files.
28421 require({
28422 baseUrl: config.baseUrl,
28423 paths: paths,
28424 packagePaths: config.packagePaths,
28425 packages: config.packages
28426 });
28427 buildContext = require.s.contexts._;
28428 modules = config.modules;
28429
28430 if (modules) {
28431 modules.forEach(function (module) {
28432 if (module.name) {
28433 module._sourcePath = buildContext.nameToUrl(module.name);
28434 //If the module does not exist, and this is not a "new" module layer,
28435 //as indicated by a true "create" property on the module, and
28436 //it is not a plugin-loaded resource, and there is no
28437 //'rawText' containing the module's source then throw an error.
28438 if (!file.exists(module._sourcePath) && !module.create &&
28439 module.name.indexOf('!') === -1 &&
28440 (!config.rawText || !lang.hasProp(config.rawText, module.name))) {
28441 throw new Error("ERROR: module path does not exist: " +
28442 module._sourcePath + " for module named: " + module.name +
28443 ". Path is relative to: " + file.absPath('.'));
28444 }
28445 }
28446 });
28447 }
28448
28449 if (config.out) {
28450 //Just set up the _buildPath for the module layer.
28451 require(config);
28452 if (!config.cssIn) {
28453 config.modules[0]._buildPath = typeof config.out === 'function' ?
28454 'FUNCTION' : config.out;
28455 }
28456 } else if (!config.cssIn) {
28457 //Now set up the config for require to use the build area, and calculate the
28458 //build file locations. Pass along any config info too.
28459 baseConfig = {
28460 baseUrl: config.dirBaseUrl,
28461 paths: buildPaths
28462 };
28463
28464 lang.mixin(baseConfig, config);
28465 require(baseConfig);
28466
28467 if (modules) {
28468 modules.forEach(function (module) {
28469 if (module.name) {
28470 module._buildPath = buildContext.nameToUrl(module.name, null);
28471
28472 //If buildPath and sourcePath are the same, throw since this
28473 //would result in modifying source. This condition can happen
28474 //with some more tricky paths: config and appDir/baseUrl
28475 //setting, which is a sign of incorrect config.
28476 if (module._buildPath === module._sourcePath &&
28477 !config.allowSourceOverwrites) {
28478 throw new Error('Module ID \'' + module.name +
28479 '\' has a source path that is same as output path: ' +
28480 module._sourcePath +
28481 '. Stopping, config is malformed.');
28482 }
28483
28484 // Copy the file, but only if it is not provided in rawText.
28485 if (!module.create && (!config.rawText || !lang.hasProp(config.rawText, module.name))) {
28486 file.copyFile(module._sourcePath, module._buildPath);
28487 }
28488 }
28489 });
28490 }
28491 }
28492
28493 //Run CSS optimizations before doing JS module tracing, to allow
28494 //things like text loader plugins loading CSS to get the optimized
28495 //CSS.
28496 if (config.optimizeCss && config.optimizeCss !== "none" && config.dir) {
28497 buildFileContents += optimize.css(config.dir, config);
28498 }
28499 }).then(function() {
28500 baseConfig = copyConfig(require.s.contexts._.config);
28501 }).then(function () {
28502 var actions = [];
28503
28504 if (modules) {
28505 actions = modules.map(function (module, i) {
28506 return function () {
28507 //Save off buildPath to module index in a hash for quicker
28508 //lookup later.
28509 config._buildPathToModuleIndex[file.normalize(module._buildPath)] = i;
28510
28511 //Call require to calculate dependencies.
28512 return build.traceDependencies(module, config, baseConfig)
28513 .then(function (layer) {
28514 module.layer = layer;
28515 });
28516 };
28517 });
28518
28519 return prim.serial(actions);
28520 }
28521 }).then(function () {
28522 var actions;
28523
28524 if (modules) {
28525 //Now build up shadow layers for anything that should be excluded.
28526 //Do this after tracing dependencies for each module, in case one
28527 //of those modules end up being one of the excluded values.
28528 actions = modules.map(function (module) {
28529 return function () {
28530 if (module.exclude) {
28531 module.excludeLayers = [];
28532 return prim.serial(module.exclude.map(function (exclude, i) {
28533 return function () {
28534 //See if it is already in the list of modules.
28535 //If not trace dependencies for it.
28536 var found = build.findBuildModule(exclude, modules);
28537 if (found) {
28538 module.excludeLayers[i] = found;
28539 } else {
28540 return build.traceDependencies({name: exclude}, config, baseConfig)
28541 .then(function (layer) {
28542 module.excludeLayers[i] = { layer: layer };
28543 });
28544 }
28545 };
28546 }));
28547 }
28548 };
28549 });
28550
28551 return prim.serial(actions);
28552 }
28553 }).then(function () {
28554 if (modules) {
28555 return prim.serial(modules.map(function (module) {
28556 return function () {
28557 if (module.exclude) {
28558 //module.exclude is an array of module names. For each one,
28559 //get the nested dependencies for it via a matching entry
28560 //in the module.excludeLayers array.
28561 module.exclude.forEach(function (excludeModule, i) {
28562 var excludeLayer = module.excludeLayers[i].layer,
28563 map = excludeLayer.buildFileToModule;
28564 excludeLayer.buildFilePaths.forEach(function(filePath){
28565 build.removeModulePath(map[filePath], filePath, module.layer);
28566 });
28567 });
28568 }
28569 if (module.excludeShallow) {
28570 //module.excludeShallow is an array of module names.
28571 //shallow exclusions are just that module itself, and not
28572 //its nested dependencies.
28573 module.excludeShallow.forEach(function (excludeShallowModule) {
28574 var path = getOwn(module.layer.buildPathMap, excludeShallowModule);
28575 if (path) {
28576 build.removeModulePath(excludeShallowModule, path, module.layer);
28577 }
28578 });
28579 }
28580
28581 //Flatten them and collect the build output for each module.
28582 return build.flattenModule(module, module.layer, config).then(function (builtModule) {
28583 var finalText, baseName;
28584 //Save it to a temp file for now, in case there are other layers that
28585 //contain optimized content that should not be included in later
28586 //layer optimizations. See issue #56.
28587 if (module._buildPath === 'FUNCTION') {
28588 module._buildText = builtModule.text;
28589 module._buildSourceMap = builtModule.sourceMap;
28590 } else {
28591 finalText = builtModule.text;
28592 if (builtModule.sourceMap) {
28593 baseName = module._buildPath.split('/');
28594 baseName = baseName.pop();
28595 finalText += '\n//# sourceMappingURL=' + baseName + '.map';
28596 file.saveUtf8File(module._buildPath + '.map', builtModule.sourceMap);
28597 }
28598 file.saveUtf8File(module._buildPath + '-temp', finalText);
28599
28600 }
28601 buildFileContents += builtModule.buildText;
28602 });
28603 };
28604 }));
28605 }
28606 }).then(function () {
28607 var moduleName, outOrigSourceMap,
28608 bundlesConfig = {},
28609 bundlesConfigOutFile = config.bundlesConfigOutFile;
28610
28611 if (modules) {
28612 //Now move the build layers to their final position.
28613 modules.forEach(function (module) {
28614 var entryConfig,
28615 finalPath = module._buildPath;
28616
28617 if (finalPath !== 'FUNCTION') {
28618 if (file.exists(finalPath)) {
28619 file.deleteFile(finalPath);
28620 }
28621 file.renameFile(finalPath + '-temp', finalPath);
28622
28623 //If bundles config should be written out, scan the
28624 //built file for module IDs. Favor doing this reparse
28625 //since tracking the IDs as the file is built has some
28626 //edge cases around files that had more than one ID in
28627 //them already, and likely loader plugin-written contents.
28628 if (bundlesConfigOutFile) {
28629 entryConfig = bundlesConfig[module.name] = [];
28630 var bundleContents = file.readFile(finalPath);
28631 var excludeMap = {};
28632 excludeMap[module.name] = true;
28633 var parsedIds = parse.getAllNamedDefines(bundleContents, excludeMap);
28634 entryConfig.push.apply(entryConfig, parsedIds);
28635 }
28636
28637 //And finally, if removeCombined is specified, remove
28638 //any of the files that were used in this layer.
28639 //Be sure not to remove other build layers.
28640 if (config.removeCombined && !config.out) {
28641 module.layer.buildFilePaths.forEach(function (path) {
28642 var isLayer = modules.some(function (mod) {
28643 return mod._buildPath === path;
28644 }),
28645 relPath = build.makeRelativeFilePath(config.dir, path);
28646
28647 if (file.exists(path) &&
28648 // not a build layer target
28649 !isLayer &&
28650 // not outside the build directory
28651 relPath.indexOf('..') !== 0) {
28652 file.deleteFile(path);
28653 }
28654 });
28655 }
28656 }
28657
28658 //Signal layer is done
28659 if (config.onModuleBundleComplete) {
28660 config.onModuleBundleComplete(module.onCompleteData);
28661 }
28662 });
28663
28664 //Write out bundles config, if it is wanted.
28665 if (bundlesConfigOutFile) {
28666 var text = file.readFile(bundlesConfigOutFile);
28667 text = transform.modifyConfig(text, function (config) {
28668 if (!config.bundles) {
28669 config.bundles = {};
28670 }
28671
28672 lang.eachProp(bundlesConfig, function (value, prop) {
28673 config.bundles[prop] = value;
28674 });
28675
28676 return config;
28677 });
28678
28679 file.saveUtf8File(bundlesConfigOutFile, text);
28680 }
28681 }
28682
28683 //If removeCombined in play, remove any empty directories that
28684 //may now exist because of its use
28685 if (config.removeCombined && !config.out && config.dir) {
28686 file.deleteEmptyDirs(config.dir);
28687 }
28688
28689 //Do other optimizations.
28690 if (config.out && !config.cssIn) {
28691 //Just need to worry about one JS file.
28692 fileName = config.modules[0]._buildPath;
28693 if (fileName === 'FUNCTION') {
28694 outOrigSourceMap = config.modules[0]._buildSourceMap;
28695 config._buildSourceMap = outOrigSourceMap;
28696 config.modules[0]._buildText = optimize.js((config.modules[0].name ||
28697 config.modules[0].include[0] ||
28698 fileName) + '.build.js',
28699 config.modules[0]._buildText,
28700 null,
28701 config);
28702 if (config._buildSourceMap && config._buildSourceMap !== outOrigSourceMap) {
28703 config.modules[0]._buildSourceMap = config._buildSourceMap;
28704 config._buildSourceMap = null;
28705 }
28706 } else {
28707 optimize.jsFile(fileName, null, fileName, config);
28708 }
28709 } else if (!config.cssIn) {
28710 //Normal optimizations across modules.
28711
28712 //JS optimizations.
28713 fileNames = file.getFilteredFileList(config.dir, /\.js$/, true);
28714 fileNames.forEach(function (fileName) {
28715 var cfg, override, moduleIndex;
28716
28717 //Generate the module name from the config.dir root.
28718 moduleName = fileName.replace(config.dir, '');
28719 //Get rid of the extension
28720 moduleName = moduleName.substring(0, moduleName.length - 3);
28721
28722 //If there is an override for a specific layer build module,
28723 //and this file is that module, mix in the override for use
28724 //by optimize.jsFile.
28725 moduleIndex = getOwn(config._buildPathToModuleIndex, fileName);
28726 //Normalize, since getOwn could have returned undefined
28727 moduleIndex = moduleIndex === 0 || moduleIndex > 0 ? moduleIndex : -1;
28728
28729 //Try to avoid extra work if the other files do not need to
28730 //be read. Build layers should be processed at the very
28731 //least for optimization.
28732 if (moduleIndex > -1 || !config.skipDirOptimize ||
28733 config.normalizeDirDefines === "all" ||
28734 config.cjsTranslate) {
28735 //Convert the file to transport format, but without a name
28736 //inserted (by passing null for moduleName) since the files are
28737 //standalone, one module per file.
28738 fileContents = file.readFile(fileName);
28739
28740
28741 //For builds, if wanting cjs translation, do it now, so that
28742 //the individual modules can be loaded cross domain via
28743 //plain script tags.
28744 if (config.cjsTranslate &&
28745 (!config.shim || !lang.hasProp(config.shim, moduleName))) {
28746 fileContents = commonJs.convert(fileName, fileContents);
28747 }
28748
28749 if (moduleIndex === -1) {
28750 if (config.onBuildRead) {
28751 fileContents = config.onBuildRead(moduleName,
28752 fileName,
28753 fileContents);
28754 }
28755
28756 //Only do transport normalization if this is not a build
28757 //layer (since it was already normalized) and if
28758 //normalizeDirDefines indicated all should be done.
28759 if (config.normalizeDirDefines === "all") {
28760 fileContents = build.toTransport(config.namespace,
28761 null,
28762 fileName,
28763 fileContents);
28764 }
28765
28766 if (config.onBuildWrite) {
28767 fileContents = config.onBuildWrite(moduleName,
28768 fileName,
28769 fileContents);
28770 }
28771 }
28772
28773 override = moduleIndex > -1 ?
28774 config.modules[moduleIndex].override : null;
28775 if (override) {
28776 cfg = build.createOverrideConfig(config, override);
28777 } else {
28778 cfg = config;
28779 }
28780
28781 if (moduleIndex > -1 || !config.skipDirOptimize) {
28782 optimize.jsFile(fileName, fileContents, fileName, cfg, pluginCollector);
28783 }
28784 }
28785 });
28786
28787 //Normalize all the plugin resources.
28788 context = require.s.contexts._;
28789
28790 for (moduleName in pluginCollector) {
28791 if (hasProp(pluginCollector, moduleName)) {
28792 parentModuleMap = context.makeModuleMap(moduleName);
28793 resources = pluginCollector[moduleName];
28794 for (i = 0; i < resources.length; i++) {
28795 resource = resources[i];
28796 moduleMap = context.makeModuleMap(resource, parentModuleMap);
28797 if (falseProp(context.plugins, moduleMap.prefix)) {
28798 //Set the value in context.plugins so it
28799 //will be evaluated as a full plugin.
28800 context.plugins[moduleMap.prefix] = true;
28801
28802 //Do not bother if the plugin is not available.
28803 if (!file.exists(require.toUrl(moduleMap.prefix + '.js'))) {
28804 continue;
28805 }
28806
28807 //Rely on the require in the build environment
28808 //to be synchronous
28809 context.require([moduleMap.prefix]);
28810
28811 //Now that the plugin is loaded, redo the moduleMap
28812 //since the plugin will need to normalize part of the path.
28813 moduleMap = context.makeModuleMap(resource, parentModuleMap);
28814 }
28815
28816 //Only bother with plugin resources that can be handled
28817 //processed by the plugin, via support of the writeFile
28818 //method.
28819 if (falseProp(pluginProcessed, moduleMap.id)) {
28820 //Only do the work if the plugin was really loaded.
28821 //Using an internal access because the file may
28822 //not really be loaded.
28823 plugin = getOwn(context.defined, moduleMap.prefix);
28824 if (plugin && plugin.writeFile) {
28825 plugin.writeFile(
28826 moduleMap.prefix,
28827 moduleMap.name,
28828 require,
28829 makeWriteFile(
28830 config.namespace
28831 ),
28832 context.config
28833 );
28834 }
28835
28836 pluginProcessed[moduleMap.id] = true;
28837 }
28838 }
28839
28840 }
28841 }
28842
28843 //console.log('PLUGIN COLLECTOR: ' + JSON.stringify(pluginCollector, null, " "));
28844
28845
28846 //All module layers are done, write out the build.txt file.
28847 if (config.writeBuildTxt) {
28848 file.saveUtf8File(config.dir + "build.txt", buildFileContents);
28849 }
28850 }
28851
28852 //If just have one CSS file to optimize, do that here.
28853 if (config.cssIn) {
28854 buildFileContents += optimize.cssFile(config.cssIn, config.out, config).buildText;
28855 }
28856
28857 if (typeof config.out === 'function') {
28858 config.out(config.modules[0]._buildText, config.modules[0]._buildSourceMap);
28859 }
28860
28861 //Print out what was built into which layers.
28862 if (buildFileContents) {
28863 logger.info(buildFileContents);
28864 return buildFileContents;
28865 }
28866
28867 return '';
28868 });
28869 };
28870
28871 /**
28872 * Converts command line args like "paths.foo=../some/path"
28873 * result.paths = { foo: '../some/path' } where prop = paths,
28874 * name = paths.foo and value = ../some/path, so it assumes the
28875 * name=value splitting has already happened.
28876 */
28877 function stringDotToObj(result, name, value) {
28878 var parts = name.split('.');
28879
28880 parts.forEach(function (prop, i) {
28881 if (i === parts.length - 1) {
28882 result[prop] = value;
28883 } else {
28884 if (falseProp(result, prop)) {
28885 result[prop] = {};
28886 }
28887 result = result[prop];
28888 }
28889
28890 });
28891 }
28892
28893 build.objProps = {
28894 paths: true,
28895 wrap: true,
28896 pragmas: true,
28897 pragmasOnSave: true,
28898 has: true,
28899 hasOnSave: true,
28900 uglify: true,
28901 uglify2: true,
28902 closure: true,
28903 map: true,
28904 throwWhen: true
28905 };
28906
28907 build.hasDotPropMatch = function (prop) {
28908 var dotProp,
28909 index = prop.indexOf('.');
28910
28911 if (index !== -1) {
28912 dotProp = prop.substring(0, index);
28913 return hasProp(build.objProps, dotProp);
28914 }
28915 return false;
28916 };
28917
28918 /**
28919 * Converts an array that has String members of "name=value"
28920 * into an object, where the properties on the object are the names in the array.
28921 * Also converts the strings "true" and "false" to booleans for the values.
28922 * member name/value pairs, and converts some comma-separated lists into
28923 * arrays.
28924 * @param {Array} ary
28925 */
28926 build.convertArrayToObject = function (ary) {
28927 var result = {}, i, separatorIndex, prop, value,
28928 needArray = {
28929 "include": true,
28930 "exclude": true,
28931 "excludeShallow": true,
28932 "insertRequire": true,
28933 "stubModules": true,
28934 "deps": true,
28935 "mainConfigFile": true,
28936 "wrap.startFile": true,
28937 "wrap.endFile": true
28938 };
28939
28940 for (i = 0; i < ary.length; i++) {
28941 separatorIndex = ary[i].indexOf("=");
28942 if (separatorIndex === -1) {
28943 throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value";
28944 }
28945
28946 value = ary[i].substring(separatorIndex + 1, ary[i].length);
28947 if (value === "true") {
28948 value = true;
28949 } else if (value === "false") {
28950 value = false;
28951 }
28952
28953 prop = ary[i].substring(0, separatorIndex);
28954
28955 //Convert to array if necessary
28956 if (getOwn(needArray, prop)) {
28957 value = value.split(",");
28958 }
28959
28960 if (build.hasDotPropMatch(prop)) {
28961 stringDotToObj(result, prop, value);
28962 } else {
28963 result[prop] = value;
28964 }
28965 }
28966 return result; //Object
28967 };
28968
28969 build.makeAbsPath = function (path, absFilePath) {
28970 if (!absFilePath) {
28971 return path;
28972 }
28973
28974 //Add abspath if necessary. If path starts with a slash or has a colon,
28975 //then already is an abolute path.
28976 if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) {
28977 path = absFilePath +
28978 (absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') +
28979 path;
28980 path = file.normalize(path);
28981 }
28982 return path.replace(lang.backSlashRegExp, '/');
28983 };
28984
28985 build.makeAbsObject = function (props, obj, absFilePath) {
28986 var i, prop;
28987 if (obj) {
28988 for (i = 0; i < props.length; i++) {
28989 prop = props[i];
28990 if (hasProp(obj, prop) && typeof obj[prop] === 'string') {
28991 obj[prop] = build.makeAbsPath(obj[prop], absFilePath);
28992 }
28993 }
28994 }
28995 };
28996
28997 /**
28998 * For any path in a possible config, make it absolute relative
28999 * to the absFilePath passed in.
29000 */
29001 build.makeAbsConfig = function (config, absFilePath) {
29002 var props, prop, i;
29003
29004 props = ["appDir", "dir", "baseUrl"];
29005 for (i = 0; i < props.length; i++) {
29006 prop = props[i];
29007
29008 if (getOwn(config, prop)) {
29009 //Add abspath if necessary, make sure these paths end in
29010 //slashes
29011 if (prop === "baseUrl") {
29012 config.originalBaseUrl = config.baseUrl;
29013 if (config.appDir) {
29014 //If baseUrl with an appDir, the baseUrl is relative to
29015 //the appDir, *not* the absFilePath. appDir and dir are
29016 //made absolute before baseUrl, so this will work.
29017 config.baseUrl = build.makeAbsPath(config.originalBaseUrl, config.appDir);
29018 } else {
29019 //The dir output baseUrl is same as regular baseUrl, both
29020 //relative to the absFilePath.
29021 config.baseUrl = build.makeAbsPath(config[prop], absFilePath);
29022 }
29023 } else {
29024 config[prop] = build.makeAbsPath(config[prop], absFilePath);
29025 }
29026
29027 config[prop] = endsWithSlash(config[prop]);
29028 }
29029 }
29030
29031 build.makeAbsObject((config.out === "stdout" ? ["cssIn"] : ["out", "cssIn"]),
29032 config, absFilePath);
29033 build.makeAbsObject(["startFile", "endFile"], config.wrap, absFilePath);
29034 build.makeAbsObject(["externExportsPath"], config.closure, absFilePath);
29035 };
29036
29037 /**
29038 * Creates a relative path to targetPath from refPath.
29039 * Only deals with file paths, not folders. If folders,
29040 * make sure paths end in a trailing '/'.
29041 */
29042 build.makeRelativeFilePath = function (refPath, targetPath) {
29043 var i, dotLength, finalParts, length, targetParts, targetName,
29044 refParts = refPath.split('/'),
29045 hasEndSlash = endsWithSlashRegExp.test(targetPath),
29046 dotParts = [];
29047
29048 targetPath = file.normalize(targetPath);
29049 if (hasEndSlash && !endsWithSlashRegExp.test(targetPath)) {
29050 targetPath += '/';
29051 }
29052 targetParts = targetPath.split('/');
29053 //Pull off file name
29054 targetName = targetParts.pop();
29055
29056 //Also pop off the ref file name to make the matches against
29057 //targetParts equivalent.
29058 refParts.pop();
29059
29060 length = refParts.length;
29061
29062 for (i = 0; i < length; i += 1) {
29063 if (refParts[i] !== targetParts[i]) {
29064 break;
29065 }
29066 }
29067
29068 //Now i is the index in which they diverge.
29069 finalParts = targetParts.slice(i);
29070
29071 dotLength = length - i;
29072 for (i = 0; i > -1 && i < dotLength; i += 1) {
29073 dotParts.push('..');
29074 }
29075
29076 return dotParts.join('/') + (dotParts.length ? '/' : '') +
29077 finalParts.join('/') + (finalParts.length ? '/' : '') +
29078 targetName;
29079 };
29080
29081 build.nestedMix = {
29082 paths: true,
29083 has: true,
29084 hasOnSave: true,
29085 pragmas: true,
29086 pragmasOnSave: true
29087 };
29088
29089 /**
29090 * Mixes additional source config into target config, and merges some
29091 * nested config, like paths, correctly.
29092 */
29093 function mixConfig(target, source, skipArrays) {
29094 var prop, value, isArray, targetValue;
29095
29096 for (prop in source) {
29097 if (hasProp(source, prop)) {
29098 //If the value of the property is a plain object, then
29099 //allow a one-level-deep mixing of it.
29100 value = source[prop];
29101 isArray = lang.isArray(value);
29102 if (typeof value === 'object' && value &&
29103 !isArray && !lang.isFunction(value) &&
29104 !lang.isRegExp(value)) {
29105
29106 // TODO: need to generalize this work, maybe also reuse
29107 // the work done in requirejs configure, perhaps move to
29108 // just a deep copy/merge overall. However, given the
29109 // amount of observable change, wait for a dot release.
29110 // This change is in relation to #645
29111 if (prop === 'map') {
29112 if (!target.map) {
29113 target.map = {};
29114 }
29115 lang.deepMix(target.map, source.map);
29116 } else {
29117 target[prop] = lang.mixin({}, target[prop], value, true);
29118 }
29119 } else if (isArray) {
29120 if (!skipArrays) {
29121 // Some config, like packages, are arrays. For those,
29122 // just merge the results.
29123 targetValue = target[prop];
29124 if (lang.isArray(targetValue)) {
29125 target[prop] = targetValue.concat(value);
29126 } else {
29127 target[prop] = value;
29128 }
29129 }
29130 } else {
29131 target[prop] = value;
29132 }
29133 }
29134 }
29135
29136 //Set up log level since it can affect if errors are thrown
29137 //or caught and passed to errbacks while doing config setup.
29138 if (lang.hasProp(target, 'logLevel')) {
29139 logger.logLevel(target.logLevel);
29140 }
29141 }
29142
29143 /**
29144 * Converts a wrap.startFile or endFile to be start/end as a string.
29145 * the startFile/endFile values can be arrays.
29146 */
29147 function flattenWrapFile(config, keyName, absFilePath) {
29148 var wrap = config.wrap,
29149 keyFileName = keyName + 'File',
29150 keyMapName = '__' + keyName + 'Map';
29151
29152 if (typeof wrap[keyName] !== 'string' && wrap[keyFileName]) {
29153 wrap[keyName] = '';
29154 if (typeof wrap[keyFileName] === 'string') {
29155 wrap[keyFileName] = [wrap[keyFileName]];
29156 }
29157 wrap[keyMapName] = [];
29158 wrap[keyFileName].forEach(function (fileName) {
29159 var absPath = build.makeAbsPath(fileName, absFilePath),
29160 fileText = endsWithNewLine(file.readFile(absPath));
29161 wrap[keyMapName].push(function (fileContents, cfg, sourceMapGenerator) {
29162 return appendToFileContents(fileContents, fileText, absPath, cfg, null, sourceMapGenerator);
29163 });
29164 wrap[keyName] += fileText;
29165 });
29166 } else if (wrap[keyName] === null || wrap[keyName] === undefined) {
29167 //Allow missing one, just set to empty string.
29168 wrap[keyName] = '';
29169 } else if (typeof wrap[keyName] === 'string') {
29170 wrap[keyName] = endsWithNewLine(wrap[keyName]);
29171 wrap[keyMapName] = [
29172 function (fileContents, cfg, sourceMapGenerator) {
29173 var absPath = build.makeAbsPath("config-wrap-" + keyName + "-default.js", absFilePath);
29174 return appendToFileContents(fileContents, wrap[keyName], absPath, cfg, null, sourceMapGenerator);
29175 }
29176 ];
29177 } else {
29178 throw new Error('wrap.' + keyName + ' or wrap.' + keyFileName + ' malformed');
29179 }
29180 }
29181
29182 function normalizeWrapConfig(config, absFilePath) {
29183 //Get any wrap text.
29184 try {
29185 if (config.wrap) {
29186 if (config.wrap === true) {
29187 //Use default values.
29188 config.wrap = {
29189 start: '(function () {\n',
29190 end: '}());',
29191 __startMap: [
29192 function (fileContents, cfg, sourceMapGenerator) {
29193 return appendToFileContents(fileContents, "(function () {\n",
29194 build.makeAbsPath("config-wrap-start-default.js",
29195 absFilePath), cfg, null,
29196 sourceMapGenerator);
29197 }
29198 ],
29199 __endMap: [
29200 function (fileContents, cfg, sourceMapGenerator) {
29201 return appendToFileContents(fileContents, "}());",
29202 build.makeAbsPath("config-wrap-end-default.js", absFilePath),
29203 cfg, null, sourceMapGenerator);
29204 }
29205 ]
29206 };
29207 } else {
29208 flattenWrapFile(config, 'start', absFilePath);
29209 flattenWrapFile(config, 'end', absFilePath);
29210 }
29211 }
29212 } catch (wrapError) {
29213 throw new Error('Malformed wrap config: ' + wrapError.toString());
29214 }
29215 }
29216
29217 /**
29218 * Creates a config object for an optimization build.
29219 * It will also read the build profile if it is available, to create
29220 * the configuration.
29221 *
29222 * @param {Object} cfg config options that take priority
29223 * over defaults and ones in the build file. These options could
29224 * be from a command line, for instance.
29225 *
29226 * @param {Object} the created config object.
29227 */
29228 build.createConfig = function (cfg) {
29229 /*jslint evil: true */
29230 var buildFileContents, buildFileConfig, mainConfig,
29231 mainConfigFile, mainConfigPath, buildFile, absFilePath,
29232 config = {},
29233 buildBaseConfig = makeBuildBaseConfig();
29234
29235 //Make sure all paths are relative to current directory.
29236 absFilePath = file.absPath('.');
29237 build.makeAbsConfig(cfg, absFilePath);
29238 build.makeAbsConfig(buildBaseConfig, absFilePath);
29239
29240 lang.mixin(config, buildBaseConfig);
29241 lang.mixin(config, cfg, true);
29242
29243 //Set up log level early since it can affect if errors are thrown
29244 //or caught and passed to errbacks, even while constructing config.
29245 if (lang.hasProp(config, 'logLevel')) {
29246 logger.logLevel(config.logLevel);
29247 }
29248
29249 if (config.buildFile) {
29250 //A build file exists, load it to get more config.
29251 buildFile = file.absPath(config.buildFile);
29252
29253 //Find the build file, and make sure it exists, if this is a build
29254 //that has a build profile, and not just command line args with an in=path
29255 if (!file.exists(buildFile)) {
29256 throw new Error("ERROR: build file does not exist: " + buildFile);
29257 }
29258
29259 absFilePath = config.baseUrl = file.absPath(file.parent(buildFile));
29260
29261 //Load build file options.
29262 buildFileContents = file.readFile(buildFile);
29263 try {
29264 //Be a bit lenient in the file ending in a ; or ending with
29265 //a //# sourceMappingUrl comment, mostly for compiled languages
29266 //that create a config, like typescript.
29267 buildFileContents = buildFileContents
29268 .replace(/\/\/\#[^\n\r]+[\n\r]*$/, '')
29269 .trim()
29270 .replace(/;$/, '');
29271
29272 buildFileConfig = eval("(" + buildFileContents + ")");
29273 build.makeAbsConfig(buildFileConfig, absFilePath);
29274
29275 //Mix in the config now so that items in mainConfigFile can
29276 //be resolved relative to them if necessary, like if appDir
29277 //is set here, but the baseUrl is in mainConfigFile. Will
29278 //re-mix in the same build config later after mainConfigFile
29279 //is processed, since build config should take priority.
29280 mixConfig(config, buildFileConfig);
29281 } catch (e) {
29282 throw new Error("Build file " + buildFile + " is malformed: " + e);
29283 }
29284 }
29285
29286 mainConfigFile = config.mainConfigFile || (buildFileConfig && buildFileConfig.mainConfigFile);
29287 if (mainConfigFile) {
29288 if (typeof mainConfigFile === 'string') {
29289 mainConfigFile = [mainConfigFile];
29290 }
29291
29292 mainConfigFile.forEach(function (configFile) {
29293 configFile = build.makeAbsPath(configFile, absFilePath);
29294 if (!file.exists(configFile)) {
29295 throw new Error(configFile + ' does not exist.');
29296 }
29297 try {
29298 mainConfig = parse.findConfig(file.readFile(configFile)).config;
29299 } catch (configError) {
29300 throw new Error('The config in mainConfigFile ' +
29301 configFile +
29302 ' cannot be used because it cannot be evaluated' +
29303 ' correctly while running in the optimizer. Try only' +
29304 ' using a config that is also valid JSON, or do not use' +
29305 ' mainConfigFile and instead copy the config values needed' +
29306 ' into a build file or command line arguments given to the optimizer.\n' +
29307 'Source error from parsing: ' + configFile + ': ' + configError);
29308 }
29309 if (mainConfig) {
29310 mainConfigPath = configFile.substring(0, configFile.lastIndexOf('/'));
29311
29312 //Add in some existing config, like appDir, since they can be
29313 //used inside the configFile -- paths and baseUrl are
29314 //relative to them.
29315 if (config.appDir && !mainConfig.appDir) {
29316 mainConfig.appDir = config.appDir;
29317 }
29318
29319 //If no baseUrl, then use the directory holding the main config.
29320 if (!mainConfig.baseUrl) {
29321 mainConfig.baseUrl = mainConfigPath;
29322 }
29323
29324 build.makeAbsConfig(mainConfig, mainConfigPath);
29325 mixConfig(config, mainConfig);
29326 }
29327 });
29328 }
29329
29330 //Mix in build file config, but only after mainConfig has been mixed in.
29331 //Since this is a re-application, skip array merging.
29332 if (buildFileConfig) {
29333 mixConfig(config, buildFileConfig, true);
29334 }
29335
29336 //Re-apply the override config values. Command line
29337 //args should take precedence over build file values.
29338 //Since this is a re-application, skip array merging.
29339 mixConfig(config, cfg, true);
29340
29341 //Fix paths to full paths so that they can be adjusted consistently
29342 //lately to be in the output area.
29343 lang.eachProp(config.paths, function (value, prop) {
29344 if (lang.isArray(value)) {
29345 throw new Error('paths fallback not supported in optimizer. ' +
29346 'Please provide a build config path override ' +
29347 'for ' + prop);
29348 }
29349 config.paths[prop] = build.makeAbsPath(value, config.baseUrl);
29350 });
29351
29352 //Set final output dir
29353 if (hasProp(config, "baseUrl")) {
29354 if (config.appDir) {
29355 if (!config.originalBaseUrl) {
29356 throw new Error('Please set a baseUrl in the build config');
29357 }
29358 config.dirBaseUrl = build.makeAbsPath(config.originalBaseUrl, config.dir);
29359 } else {
29360 config.dirBaseUrl = config.dir || config.baseUrl;
29361 }
29362 //Make sure dirBaseUrl ends in a slash, since it is
29363 //concatenated with other strings.
29364 config.dirBaseUrl = endsWithSlash(config.dirBaseUrl);
29365 }
29366
29367 if (config.bundlesConfigOutFile) {
29368 if (!config.dir) {
29369 throw new Error('bundlesConfigOutFile can only be used with optimizations ' +
29370 'that use "dir".');
29371 }
29372 config.bundlesConfigOutFile = build.makeAbsPath(config.bundlesConfigOutFile, config.dir);
29373 }
29374
29375 //If out=stdout, write output to STDOUT instead of a file.
29376 if (config.out && config.out === 'stdout') {
29377 config.out = function (content) {
29378 var e = env.get();
29379 if (e === 'rhino') {
29380 var out = new java.io.PrintStream(java.lang.System.out, true, 'UTF-8');
29381 out.println(content);
29382 } else if (e === 'node') {
29383 process.stdout.write(content, 'utf8');
29384 } else {
29385 console.log(content);
29386 }
29387 };
29388 }
29389
29390 //Check for errors in config
29391 if (config.main) {
29392 throw new Error('"main" passed as an option, but the ' +
29393 'supported option is called "name".');
29394 }
29395 if (config.out && !config.name && !config.modules && !config.include &&
29396 !config.cssIn) {
29397 throw new Error('Missing either a "name", "include" or "modules" ' +
29398 'option');
29399 }
29400 if (config.cssIn) {
29401 if (config.dir || config.appDir) {
29402 throw new Error('cssIn is only for the output of single file ' +
29403 'CSS optimizations and is not compatible with "dir" or "appDir" configuration.');
29404 }
29405 if (!config.out) {
29406 throw new Error('"out" option missing.');
29407 }
29408 }
29409 if (!config.cssIn && !config.baseUrl) {
29410 //Just use the current directory as the baseUrl
29411 config.baseUrl = './';
29412 }
29413 if (!config.out && !config.dir) {
29414 throw new Error('Missing either an "out" or "dir" config value. ' +
29415 'If using "appDir" for a full project optimization, ' +
29416 'use "dir". If you want to optimize to one file, ' +
29417 'use "out".');
29418 }
29419 if (config.appDir && config.out) {
29420 throw new Error('"appDir" is not compatible with "out". Use "dir" ' +
29421 'instead. appDir is used to copy whole projects, ' +
29422 'where "out" with "baseUrl" is used to just ' +
29423 'optimize to one file.');
29424 }
29425 if (config.out && config.dir) {
29426 throw new Error('The "out" and "dir" options are incompatible.' +
29427 ' Use "out" if you are targeting a single file' +
29428 ' for optimization, and "dir" if you want the appDir' +
29429 ' or baseUrl directories optimized.');
29430 }
29431
29432
29433 if (config.dir) {
29434 // Make sure the output dir is not set to a parent of the
29435 // source dir or the same dir, as it will result in source
29436 // code deletion.
29437 if (!config.allowSourceOverwrites && (config.dir === config.baseUrl ||
29438 config.dir === config.appDir ||
29439 (config.baseUrl && build.makeRelativeFilePath(config.dir,
29440 config.baseUrl).indexOf('..') !== 0) ||
29441 (config.appDir &&
29442 build.makeRelativeFilePath(config.dir, config.appDir).indexOf('..') !== 0))) {
29443 throw new Error('"dir" is set to a parent or same directory as' +
29444 ' "appDir" or "baseUrl". This can result in' +
29445 ' the deletion of source code. Stopping. If' +
29446 ' you want to allow possible overwriting of' +
29447 ' source code, set "allowSourceOverwrites"' +
29448 ' to true in the build config, but do so at' +
29449 ' your own risk. In that case, you may want' +
29450 ' to also set "keepBuildDir" to true.');
29451 }
29452 }
29453
29454 if (config.insertRequire && !lang.isArray(config.insertRequire)) {
29455 throw new Error('insertRequire should be a list of module IDs' +
29456 ' to insert in to a require([]) call.');
29457 }
29458
29459 //Support older configs with uglify2 settings, but now that uglify1 has
29460 //been removed, just translate it to 'uglify' settings.
29461 if (config.optimize === 'uglify2') {
29462 config.optimize = 'uglify';
29463 }
29464 if (config.uglify2) {
29465 config.uglify = config.uglify2;
29466 delete config.uglify2;
29467 }
29468
29469 if (config.generateSourceMaps) {
29470 if (config.preserveLicenseComments && !(config.optimize === 'none' || config.optimize === 'uglify')) {
29471 throw new Error('Cannot use preserveLicenseComments and ' +
29472 'generateSourceMaps together, unless optimize is set ' +
29473 'to \'uglify\'. Either explicitly set preserveLicenseComments ' +
29474 'to false (default is true) or turn off generateSourceMaps. ' +
29475 'If you want source maps with license comments, see: ' +
29476 'http://requirejs.org/docs/errors.html#sourcemapcomments');
29477 } else if (config.optimize !== 'none' &&
29478 config.optimize !== 'closure' &&
29479 config.optimize !== 'uglify') {
29480 //Allow optimize: none to pass, since it is useful when toggling
29481 //minification on and off to debug something, and it implicitly
29482 //works, since it does not need a source map.
29483 throw new Error('optimize: "' + config.optimize +
29484 '" does not support generateSourceMaps.');
29485 }
29486 }
29487
29488 if ((config.name || config.include) && !config.modules) {
29489 //Just need to build one file, but may be part of a whole appDir/
29490 //baseUrl copy, but specified on the command line, so cannot do
29491 //the modules array setup. So create a modules section in that
29492 //case.
29493 config.modules = [
29494 {
29495 name: config.name,
29496 out: config.out,
29497 create: config.create,
29498 include: config.include,
29499 exclude: config.exclude,
29500 excludeShallow: config.excludeShallow,
29501 insertRequire: config.insertRequire,
29502 stubModules: config.stubModules
29503 }
29504 ];
29505 delete config.stubModules;
29506 } else if (config.modules && config.out) {
29507 throw new Error('If the "modules" option is used, then there ' +
29508 'should be a "dir" option set and "out" should ' +
29509 'not be used since "out" is only for single file ' +
29510 'optimization output.');
29511 } else if (config.modules && config.name) {
29512 throw new Error('"name" and "modules" options are incompatible. ' +
29513 'Either use "name" if doing a single file ' +
29514 'optimization, or "modules" if you want to target ' +
29515 'more than one file for optimization.');
29516 }
29517
29518 if (config.out && !config.cssIn) {
29519 //Just one file to optimize.
29520
29521 //Does not have a build file, so set up some defaults.
29522 //Optimizing CSS should not be allowed, unless explicitly
29523 //asked for on command line. In that case the only task is
29524 //to optimize a CSS file.
29525 if (!cfg.optimizeCss) {
29526 config.optimizeCss = "none";
29527 }
29528 }
29529
29530 //Normalize cssPrefix
29531 if (config.cssPrefix) {
29532 //Make sure cssPrefix ends in a slash
29533 config.cssPrefix = endsWithSlash(config.cssPrefix);
29534 } else {
29535 config.cssPrefix = '';
29536 }
29537
29538 //Cycle through modules and normalize
29539 if (config.modules && config.modules.length) {
29540 config.modules.forEach(function (mod) {
29541 if (lang.isArray(mod) || typeof mod === 'string' || !mod) {
29542 throw new Error('modules config item is malformed: it should' +
29543 ' be an object with a \'name\' property.');
29544 }
29545
29546 //Combine any local stubModules with global values.
29547 if (config.stubModules) {
29548 mod.stubModules = config.stubModules.concat(mod.stubModules || []);
29549 }
29550
29551 //Create a hash lookup for the stubModules config to make lookup
29552 //cheaper later.
29553 if (mod.stubModules) {
29554 mod.stubModules._byName = {};
29555 mod.stubModules.forEach(function (id) {
29556 mod.stubModules._byName[id] = true;
29557 });
29558 }
29559
29560 // Legacy command support, which allowed a single string ID
29561 // for include.
29562 if (typeof mod.include === 'string') {
29563 mod.include = [mod.include];
29564 }
29565
29566 //Allow wrap config in overrides, but normalize it.
29567 if (mod.override) {
29568 normalizeWrapConfig(mod.override, absFilePath);
29569 }
29570 });
29571 }
29572
29573 normalizeWrapConfig(config, absFilePath);
29574
29575 //Do final input verification
29576 if (config.context) {
29577 throw new Error('The build argument "context" is not supported' +
29578 ' in a build. It should only be used in web' +
29579 ' pages.');
29580 }
29581
29582 //Set up normalizeDirDefines. If not explicitly set, if optimize "none",
29583 //set to "skip" otherwise set to "all".
29584 if (!hasProp(config, 'normalizeDirDefines')) {
29585 if (config.optimize === 'none' || config.skipDirOptimize) {
29586 config.normalizeDirDefines = 'skip';
29587 } else {
29588 config.normalizeDirDefines = 'all';
29589 }
29590 }
29591
29592 //Set file.fileExclusionRegExp if desired
29593 if (hasProp(config, 'fileExclusionRegExp')) {
29594 if (typeof config.fileExclusionRegExp === "string") {
29595 file.exclusionRegExp = new RegExp(config.fileExclusionRegExp);
29596 } else {
29597 file.exclusionRegExp = config.fileExclusionRegExp;
29598 }
29599 } else if (hasProp(config, 'dirExclusionRegExp')) {
29600 //Set file.dirExclusionRegExp if desired, this is the old
29601 //name for fileExclusionRegExp before 1.0.2. Support for backwards
29602 //compatibility
29603 file.exclusionRegExp = config.dirExclusionRegExp;
29604 }
29605
29606 //Track the deps, but in a different key, so that they are not loaded
29607 //as part of config seeding before all config is in play (#648). Was
29608 //going to merge this in with "include", but include is added after
29609 //the "name" target. To preserve what r.js has done previously, make
29610 //sure "deps" comes before the "name".
29611 if (config.deps) {
29612 config._depsInclude = config.deps;
29613 }
29614
29615
29616 //Remove things that may cause problems in the build.
29617 //deps already merged above
29618 delete config.deps;
29619 delete config.jQuery;
29620 delete config.enforceDefine;
29621 delete config.urlArgs;
29622
29623 return config;
29624 };
29625
29626 /**
29627 * finds the module being built/optimized with the given moduleName,
29628 * or returns null.
29629 * @param {String} moduleName
29630 * @param {Array} modules
29631 * @returns {Object} the module object from the build profile, or null.
29632 */
29633 build.findBuildModule = function (moduleName, modules) {
29634 var i, module;
29635 for (i = 0; i < modules.length; i++) {
29636 module = modules[i];
29637 if (module.name === moduleName) {
29638 return module;
29639 }
29640 }
29641 return null;
29642 };
29643
29644 /**
29645 * Removes a module name and path from a layer, if it is supposed to be
29646 * excluded from the layer.
29647 * @param {String} moduleName the name of the module
29648 * @param {String} path the file path for the module
29649 * @param {Object} layer the layer to remove the module/path from
29650 */
29651 build.removeModulePath = function (module, path, layer) {
29652 var index = layer.buildFilePaths.indexOf(path);
29653 if (index !== -1) {
29654 layer.buildFilePaths.splice(index, 1);
29655 }
29656 };
29657
29658 /**
29659 * Uses the module build config object to trace the dependencies for the
29660 * given module.
29661 *
29662 * @param {Object} module the module object from the build config info.
29663 * @param {Object} config the build config object.
29664 * @param {Object} [baseLoaderConfig] the base loader config to use for env resets.
29665 *
29666 * @returns {Object} layer information about what paths and modules should
29667 * be in the flattened module.
29668 */
29669 build.traceDependencies = function (module, config, baseLoaderConfig) {
29670 var include, override, layer, context, oldContext,
29671 rawTextByIds,
29672 syncChecks = {
29673 rhino: true,
29674 node: true,
29675 xpconnect: true
29676 },
29677 deferred = prim();
29678
29679 //Reset some state set up in requirePatch.js, and clean up require's
29680 //current context.
29681 oldContext = require._buildReset();
29682
29683 //Grab the reset layer and context after the reset, but keep the
29684 //old config to reuse in the new context.
29685 layer = require._layer;
29686 context = layer.context;
29687
29688 //Put back basic config, use a fresh object for it.
29689 if (baseLoaderConfig) {
29690 require(copyConfig(baseLoaderConfig));
29691 }
29692
29693 logger.trace("\nTracing dependencies for: " + (module.name ||
29694 (typeof module.out === 'function' ? 'FUNCTION' : module.out)));
29695 include = config._depsInclude || [];
29696 include = include.concat(module.name && !module.create ? [module.name] : []);
29697 if (module.include) {
29698 include = include.concat(module.include);
29699 }
29700
29701 //If there are overrides to basic config, set that up now.;
29702 if (module.override) {
29703 if (baseLoaderConfig) {
29704 override = build.createOverrideConfig(baseLoaderConfig, module.override);
29705 } else {
29706 override = copyConfig(module.override);
29707 }
29708 require(override);
29709 }
29710
29711 //Now, populate the rawText cache with any values explicitly passed in
29712 //via config.
29713 rawTextByIds = require.s.contexts._.config.rawText;
29714 if (rawTextByIds) {
29715 lang.eachProp(rawTextByIds, function (contents, id) {
29716 var url = require.toUrl(id) + '.js';
29717 require._cachedRawText[url] = contents;
29718 });
29719 }
29720
29721
29722 //Configure the callbacks to be called.
29723 deferred.reject.__requireJsBuild = true;
29724
29725 //Use a wrapping function so can check for errors.
29726 function includeFinished(value) {
29727 //If a sync build environment, check for errors here, instead of
29728 //in the then callback below, since some errors, like two IDs pointed
29729 //to same URL but only one anon ID will leave the loader in an
29730 //unresolved state since a setTimeout cannot be used to check for
29731 //timeout.
29732 var hasError = false;
29733 if (syncChecks[env.get()]) {
29734 try {
29735 build.checkForErrors(context, layer);
29736 } catch (e) {
29737 hasError = true;
29738 deferred.reject(e);
29739 }
29740 }
29741
29742 if (!hasError) {
29743 deferred.resolve(value);
29744 }
29745 }
29746 includeFinished.__requireJsBuild = true;
29747
29748 //Figure out module layer dependencies by calling require to do the work.
29749 require(include, includeFinished, deferred.reject);
29750
29751 // If a sync env, then with the "two IDs to same anon module path"
29752 // issue, the require never completes, need to check for errors
29753 // here.
29754 if (syncChecks[env.get()]) {
29755 build.checkForErrors(context, layer);
29756 }
29757
29758 return deferred.promise.then(function () {
29759 //Reset config
29760 if (module.override && baseLoaderConfig) {
29761 require(copyConfig(baseLoaderConfig));
29762 }
29763
29764 build.checkForErrors(context, layer);
29765
29766 return layer;
29767 });
29768 };
29769
29770 build.checkForErrors = function (context, layer) {
29771 //Check to see if it all loaded. If not, then throw, and give
29772 //a message on what is left.
29773 var id, prop, mod, idParts, pluginId, pluginResources,
29774 errMessage = '',
29775 failedPluginMap = {},
29776 failedPluginIds = [],
29777 errIds = [],
29778 errUrlMap = {},
29779 errUrlConflicts = {},
29780 hasErrUrl = false,
29781 hasUndefined = false,
29782 defined = context.defined,
29783 registry = context.registry;
29784
29785 function populateErrUrlMap(id, errUrl, skipNew) {
29786 // Loader plugins do not have an errUrl, so skip them.
29787 if (!errUrl) {
29788 return;
29789 }
29790
29791 if (!skipNew) {
29792 errIds.push(id);
29793 }
29794
29795 if (errUrlMap[errUrl]) {
29796 hasErrUrl = true;
29797 //This error module has the same URL as another
29798 //error module, could be misconfiguration.
29799 if (!errUrlConflicts[errUrl]) {
29800 errUrlConflicts[errUrl] = [];
29801 //Store the original module that had the same URL.
29802 errUrlConflicts[errUrl].push(errUrlMap[errUrl]);
29803 }
29804 errUrlConflicts[errUrl].push(id);
29805 } else if (!skipNew) {
29806 errUrlMap[errUrl] = id;
29807 }
29808 }
29809
29810 for (id in registry) {
29811 if (hasProp(registry, id) && id.indexOf('_@r') !== 0) {
29812 hasUndefined = true;
29813 mod = getOwn(registry, id);
29814 idParts = id.split('!');
29815 pluginId = idParts[0];
29816
29817 if (id.indexOf('_unnormalized') === -1 && mod && mod.enabled) {
29818 populateErrUrlMap(id, mod.map.url);
29819 }
29820
29821 //Look for plugins that did not call load()
29822 //But skip plugin IDs that were already inlined and called
29823 //define() with a name.
29824 if (!hasProp(layer.modulesWithNames, id) && idParts.length > 1) {
29825 if (falseProp(failedPluginMap, pluginId)) {
29826 failedPluginIds.push(pluginId);
29827 }
29828 pluginResources = failedPluginMap[pluginId];
29829 if (!pluginResources) {
29830 pluginResources = failedPluginMap[pluginId] = [];
29831 }
29832 pluginResources.push(id + (mod.error ? ': ' + mod.error : ''));
29833 }
29834 }
29835 }
29836
29837 // If have some modules that are not defined/stuck in the registry,
29838 // then check defined modules for URL overlap.
29839 if (hasUndefined) {
29840 for (id in defined) {
29841 if (hasProp(defined, id) && id.indexOf('!') === -1) {
29842 populateErrUrlMap(id, require.toUrl(id) + '.js', true);
29843 }
29844 }
29845 }
29846
29847 if (errIds.length || failedPluginIds.length) {
29848 if (failedPluginIds.length) {
29849 errMessage += 'Loader plugin' +
29850 (failedPluginIds.length === 1 ? '' : 's') +
29851 ' did not call ' +
29852 'the load callback in the build:\n' +
29853 failedPluginIds.map(function (pluginId) {
29854 var pluginResources = failedPluginMap[pluginId];
29855 return pluginId + ':\n ' + pluginResources.join('\n ');
29856 }).join('\n') + '\n';
29857 }
29858 errMessage += 'Module loading did not complete for: ' + errIds.join(', ');
29859
29860 if (hasErrUrl) {
29861 errMessage += '\nThe following modules share the same URL. This ' +
29862 'could be a misconfiguration if that URL only has ' +
29863 'one anonymous module in it:';
29864 for (prop in errUrlConflicts) {
29865 if (hasProp(errUrlConflicts, prop)) {
29866 errMessage += '\n' + prop + ': ' +
29867 errUrlConflicts[prop].join(', ');
29868 }
29869 }
29870 }
29871 throw new Error(errMessage);
29872 }
29873 };
29874
29875 build.createOverrideConfig = function (config, override) {
29876 var cfg = copyConfig(config),
29877 oride = copyConfig(override);
29878
29879 lang.eachProp(oride, function (value, prop) {
29880 if (hasProp(build.objProps, prop)) {
29881 //An object property, merge keys. Start a new object
29882 //so that source object in config does not get modified.
29883 cfg[prop] = {};
29884 lang.mixin(cfg[prop], config[prop], true);
29885 lang.mixin(cfg[prop], override[prop], true);
29886 } else {
29887 cfg[prop] = override[prop];
29888 }
29889 });
29890
29891 return cfg;
29892 };
29893
29894 /**
29895 * Uses the module build config object to create an flattened version
29896 * of the module, with deep dependencies included.
29897 *
29898 * @param {Object} module the module object from the build config info.
29899 *
29900 * @param {Object} layer the layer object returned from build.traceDependencies.
29901 *
29902 * @param {Object} the build config object.
29903 *
29904 * @returns {Object} with two properties: "text", the text of the flattened
29905 * module, and "buildText", a string of text representing which files were
29906 * included in the flattened module text.
29907 */
29908 build.flattenModule = function (module, layer, config) {
29909 var fileContents, sourceMapGenerator,
29910 sourceMapBase,
29911 buildFileContents = '';
29912
29913 return prim().start(function () {
29914 var reqIndex, currContents, fileForSourceMap,
29915 moduleName, shim, packageName,
29916 parts, builder, writeApi,
29917 namespace, namespaceWithDot, stubModulesByName,
29918 context = layer.context,
29919 onLayerEnds = [],
29920 onLayerEndAdded = {},
29921 pkgsMainMap = {};
29922
29923 //Use override settings, particularly for pragmas
29924 //Do this before the var readings since it reads config values.
29925 if (module.override) {
29926 config = build.createOverrideConfig(config, module.override);
29927 }
29928
29929 namespace = config.namespace || '';
29930 namespaceWithDot = namespace ? namespace + '.' : '';
29931 stubModulesByName = (module.stubModules && module.stubModules._byName) || {};
29932
29933 //Start build output for the module.
29934 module.onCompleteData = {
29935 name: module.name,
29936 path: (config.dir ? module._buildPath.replace(config.dir, "") : module._buildPath),
29937 included: []
29938 };
29939
29940 buildFileContents += "\n" +
29941 module.onCompleteData.path +
29942 "\n----------------\n";
29943
29944 //If there was an existing file with require in it, hoist to the top.
29945 if (layer.existingRequireUrl) {
29946 reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl);
29947 if (reqIndex !== -1) {
29948 layer.buildFilePaths.splice(reqIndex, 1);
29949 layer.buildFilePaths.unshift(layer.existingRequireUrl);
29950 }
29951 }
29952
29953 if (config.generateSourceMaps) {
29954 sourceMapBase = config.dir || config.baseUrl;
29955 if (module._buildPath === 'FUNCTION') {
29956 fileForSourceMap = (module.name || module.include[0] || 'FUNCTION') + '.build.js';
29957 } else if (config.out) {
29958 fileForSourceMap = module._buildPath.split('/').pop();
29959 } else {
29960 fileForSourceMap = module._buildPath.replace(sourceMapBase, '');
29961 }
29962 sourceMapGenerator = new SourceMapGenerator({
29963 file: fileForSourceMap
29964 });
29965 }
29966
29967 //Create a reverse lookup for packages main module IDs to their package
29968 //names, useful for knowing when to write out define() package main ID
29969 //adapters.
29970 lang.eachProp(layer.context.config.pkgs, function(value, prop) {
29971 pkgsMainMap[value] = prop;
29972 });
29973
29974 //Write the built module to disk, and build up the build output.
29975 fileContents = "";
29976 if (config.wrap && config.wrap.__startMap) {
29977 config.wrap.__startMap.forEach(function (wrapFunction) {
29978 fileContents = wrapFunction(fileContents, config, sourceMapGenerator);
29979 });
29980 }
29981
29982 return prim.serial(layer.buildFilePaths.map(function (path) {
29983 return function () {
29984 var singleContents = '';
29985
29986 moduleName = layer.buildFileToModule[path];
29987
29988 //If the moduleName is a package main, then hold on to the
29989 //packageName in case an adapter needs to be written.
29990 packageName = getOwn(pkgsMainMap, moduleName);
29991
29992 return prim().start(function () {
29993 //Figure out if the module is a result of a build plugin, and if so,
29994 //then delegate to that plugin.
29995 parts = context.makeModuleMap(moduleName);
29996 builder = parts.prefix && getOwn(context.defined, parts.prefix);
29997 if (builder) {
29998 if (builder.onLayerEnd && falseProp(onLayerEndAdded, parts.prefix)) {
29999 onLayerEnds.push(builder);
30000 onLayerEndAdded[parts.prefix] = true;
30001 }
30002
30003 if (builder.write) {
30004 writeApi = function (input) {
30005 singleContents += "\n" + addSemiColon(input, config);
30006 if (config.onBuildWrite) {
30007 singleContents = config.onBuildWrite(moduleName, path, singleContents);
30008 }
30009 };
30010 writeApi.asModule = function (moduleName, input) {
30011 singleContents += "\n" +
30012 addSemiColon(build.toTransport(namespace, moduleName, path, input, layer, {
30013 useSourceUrl: layer.context.config.useSourceUrl
30014 }), config);
30015 if (config.onBuildWrite) {
30016 singleContents = config.onBuildWrite(moduleName, path, singleContents);
30017 }
30018 };
30019 builder.write(parts.prefix, parts.name, writeApi);
30020 }
30021 return;
30022 } else {
30023 return prim().start(function () {
30024 if (hasProp(stubModulesByName, moduleName)) {
30025 //Just want to insert a simple module definition instead
30026 //of the source module. Useful for plugins that inline
30027 //all their resources.
30028 if (hasProp(layer.context.plugins, moduleName)) {
30029 //Slightly different content for plugins, to indicate
30030 //that dynamic loading will not work.
30031 return 'define({load: function(id){throw new Error("Dynamic load not allowed: " + id);}});';
30032 } else {
30033 return 'define({});';
30034 }
30035 } else {
30036 return require._cacheReadAsync(path);
30037 }
30038 }).then(function (text) {
30039 var hasPackageName;
30040
30041 currContents = text;
30042
30043 if (config.cjsTranslate &&
30044 (!config.shim || !lang.hasProp(config.shim, moduleName))) {
30045 currContents = commonJs.convert(path, currContents);
30046 }
30047
30048 if (config.onBuildRead) {
30049 currContents = config.onBuildRead(moduleName, path, currContents);
30050 }
30051
30052 if (packageName) {
30053 hasPackageName = (packageName === parse.getNamedDefine(currContents));
30054 }
30055
30056 if (namespace) {
30057 currContents = pragma.namespace(currContents, namespace);
30058 }
30059
30060 currContents = build.toTransport(namespace, moduleName, path, currContents, layer, {
30061 useSourceUrl: config.useSourceUrl
30062 });
30063
30064 if (packageName && !hasPackageName) {
30065 currContents = addSemiColon(currContents, config) + '\n';
30066 currContents += namespaceWithDot + "define('" +
30067 packageName + "', ['" + moduleName +
30068 "'], function (main) { return main; });\n";
30069 }
30070
30071 if (config.onBuildWrite) {
30072 currContents = config.onBuildWrite(moduleName, path, currContents);
30073 }
30074
30075 //Semicolon is for files that are not well formed when
30076 //concatenated with other content.
30077 singleContents += addSemiColon(currContents, config);
30078 });
30079 }
30080 }).then(function () {
30081 var shimDeps, shortPath = path.replace(config.dir, "");
30082
30083 module.onCompleteData.included.push(shortPath);
30084 buildFileContents += shortPath + "\n";
30085
30086 //Some files may not have declared a require module, and if so,
30087 //put in a placeholder call so the require does not try to load them
30088 //after the module is processed.
30089 //If we have a name, but no defined module, then add in the placeholder.
30090 if (moduleName && falseProp(layer.modulesWithNames, moduleName) && !config.skipModuleInsertion) {
30091 shim = config.shim && (getOwn(config.shim, moduleName) || (packageName && getOwn(config.shim, packageName)));
30092 if (shim) {
30093 shimDeps = lang.isArray(shim) ? shim : shim.deps;
30094 if (config.wrapShim) {
30095
30096 singleContents = '(function(root) {\n' +
30097 namespaceWithDot + 'define("' + moduleName + '", ' +
30098 (shimDeps && shimDeps.length ?
30099 build.makeJsArrayString(shimDeps) + ', ' : '[], ') +
30100 'function() {\n' +
30101 ' return (function() {\n' +
30102 singleContents +
30103 // Start with a \n in case last line is a comment
30104 // in the singleContents, like a sourceURL comment.
30105 '\n' + (shim.exportsFn ? shim.exportsFn() : '') +
30106 '\n' +
30107 ' }).apply(root, arguments);\n' +
30108 '});\n' +
30109 '}(this));\n';
30110 } else {
30111 singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", ' +
30112 (shimDeps && shimDeps.length ?
30113 build.makeJsArrayString(shimDeps) + ', ' : '') +
30114 (shim.exportsFn ? shim.exportsFn() : 'function(){}') +
30115 ');\n';
30116 }
30117 } else {
30118 singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", function(){});\n';
30119 }
30120 }
30121
30122 //Add line break at end of file, instead of at beginning,
30123 //so source map line numbers stay correct, but still allow
30124 //for some space separation between files in case ASI issues
30125 //for concatenation would cause an error otherwise.
30126 singleContents += '\n';
30127
30128 //Add to the source map and to the final contents
30129 fileContents = appendToFileContents(fileContents, singleContents, path, config, module,
30130 sourceMapGenerator);
30131 });
30132 };
30133 })).then(function () {
30134 if (onLayerEnds.length) {
30135 onLayerEnds.forEach(function (builder, index) {
30136 var path;
30137 if (typeof module.out === 'string') {
30138 path = module.out;
30139 } else if (typeof module._buildPath === 'string') {
30140 path = module._buildPath;
30141 }
30142 builder.onLayerEnd(function (input) {
30143 fileContents =
30144 appendToFileContents(fileContents, "\n" + addSemiColon(input, config),
30145 'onLayerEnd' + index + '.js', config, module, sourceMapGenerator);
30146 }, {
30147 name: module.name,
30148 path: path
30149 });
30150 });
30151 }
30152
30153 if (module.create) {
30154 //The ID is for a created layer. Write out
30155 //a module definition for it in case the
30156 //built file is used with enforceDefine
30157 //(#432)
30158 fileContents =
30159 appendToFileContents(fileContents, '\n' + namespaceWithDot + 'define("' + module.name +
30160 '", function(){});\n', 'module-create.js', config, module,
30161 sourceMapGenerator);
30162 }
30163
30164 //Add a require at the end to kick start module execution, if that
30165 //was desired. Usually this is only specified when using small shim
30166 //loaders like almond.
30167 if (module.insertRequire) {
30168 fileContents =
30169 appendToFileContents(fileContents, '\n' + namespaceWithDot + 'require(["' + module.insertRequire.join('", "') +
30170 '"]);\n', 'module-insertRequire.js', config, module,
30171 sourceMapGenerator);
30172 }
30173 });
30174 }).then(function () {
30175 if (config.wrap && config.wrap.__endMap) {
30176 config.wrap.__endMap.forEach(function (wrapFunction) {
30177 fileContents = wrapFunction(fileContents, config, sourceMapGenerator);
30178 });
30179 }
30180 return {
30181 text: fileContents,
30182 buildText: buildFileContents,
30183 sourceMap: sourceMapGenerator ?
30184 JSON.stringify(sourceMapGenerator.toJSON(), null, ' ') :
30185 undefined
30186 };
30187 });
30188 };
30189
30190 //Converts an JS array of strings to a string representation.
30191 //Not using JSON.stringify() for Rhino's sake.
30192 build.makeJsArrayString = function (ary) {
30193 return '["' + ary.map(function (item) {
30194 //Escape any double quotes, backslashes
30195 return lang.jsEscape(item);
30196 }).join('","') + '"]';
30197 };
30198
30199 build.toTransport = function (namespace, moduleName, path, contents, layer, options) {
30200 var baseUrl = layer && layer.context.config.baseUrl;
30201
30202 function onFound(info) {
30203 //Only mark this module as having a name if not a named module,
30204 //or if a named module and the name matches expectations.
30205 if (layer && (info.needsId || info.foundId === moduleName)) {
30206 layer.modulesWithNames[moduleName] = true;
30207 }
30208 }
30209
30210 //Convert path to be a local one to the baseUrl, useful for
30211 //useSourceUrl.
30212 if (baseUrl) {
30213 path = path.replace(baseUrl, '');
30214 }
30215
30216 return transform.toTransport(namespace, moduleName, path, contents, onFound, options);
30217 };
30218
30219 return build;
30220});
30221
30222 }
30223
30224
30225 /**
30226 * Sets the default baseUrl for requirejs to be directory of top level
30227 * script.
30228 */
30229 function setBaseUrl(fileName) {
30230 //Use the file name's directory as the baseUrl if available.
30231 dir = fileName.replace(/\\/g, '/');
30232 if (dir.indexOf('/') !== -1) {
30233 dir = dir.split('/');
30234 dir.pop();
30235 dir = dir.join('/');
30236 //Make sure dir is JS-escaped, since it will be part of a JS string.
30237 exec("require({baseUrl: '" + dir.replace(/[\\"']/g, '\\$&') + "'});");
30238 }
30239 }
30240
30241 function createRjsApi() {
30242 //Create a method that will run the optimzer given an object
30243 //config.
30244 requirejs.optimize = function (config, callback, errback) {
30245 if (!loadedOptimizedLib) {
30246 loadLib();
30247 loadedOptimizedLib = true;
30248 }
30249
30250 //Create the function that will be called once build modules
30251 //have been loaded.
30252 var runBuild = function (build, logger, quit) {
30253 //Make sure config has a log level, and if not,
30254 //make it "silent" by default.
30255 config.logLevel = config.hasOwnProperty('logLevel') ?
30256 config.logLevel : logger.SILENT;
30257
30258 //Reset build internals first in case this is part
30259 //of a long-running server process that could have
30260 //exceptioned out in a bad state. It is only defined
30261 //after the first call though.
30262 if (requirejs._buildReset) {
30263 requirejs._buildReset();
30264 requirejs._cacheReset();
30265 }
30266
30267 function done(result) {
30268 //And clean up, in case something else triggers
30269 //a build in another pathway.
30270 if (requirejs._buildReset) {
30271 requirejs._buildReset();
30272 requirejs._cacheReset();
30273 }
30274
30275 // Ensure errors get propagated to the errback
30276 if (result instanceof Error) {
30277 throw result;
30278 }
30279
30280 return result;
30281 }
30282
30283 errback = errback || function (err) {
30284 // Using console here since logger may have
30285 // turned off error logging. Since quit is
30286 // called want to be sure a message is printed.
30287 console.log(err);
30288 quit(1);
30289 };
30290
30291 build(config).then(done, done).then(callback, errback);
30292 };
30293
30294 requirejs({
30295 context: 'build'
30296 }, ['build', 'logger', 'env!env/quit'], runBuild);
30297 };
30298
30299 requirejs.tools = {
30300 useLib: function (contextName, callback) {
30301 if (!callback) {
30302 callback = contextName;
30303 contextName = 'uselib';
30304 }
30305
30306 if (!useLibLoaded[contextName]) {
30307 loadLib();
30308 useLibLoaded[contextName] = true;
30309 }
30310
30311 var req = requirejs({
30312 context: contextName
30313 });
30314
30315 req(['build'], function () {
30316 callback(req);
30317 });
30318 }
30319 };
30320
30321 requirejs.define = define;
30322 }
30323
30324 //If in Node, and included via a require('requirejs'), just export and
30325 //THROW IT ON THE GROUND!
30326 if (env === 'node' && reqMain !== module) {
30327 setBaseUrl(path.resolve(reqMain ? reqMain.filename : '.'));
30328
30329 createRjsApi();
30330
30331 module.exports = requirejs;
30332 return;
30333 } else if (env === 'browser') {
30334 //Only option is to use the API.
30335 setBaseUrl(location.href);
30336 createRjsApi();
30337 return;
30338 } else if ((env === 'rhino' || env === 'xpconnect') &&
30339 //User sets up requirejsAsLib variable to indicate it is loaded
30340 //via load() to be used as a library.
30341 typeof requirejsAsLib !== 'undefined' && requirejsAsLib) {
30342 //This script is loaded via rhino's load() method, expose the
30343 //API and get out.
30344 setBaseUrl(fileName);
30345 createRjsApi();
30346 return;
30347 }
30348
30349 if (commandOption === 'o') {
30350 //Do the optimizer work.
30351 loadLib();
30352
30353 /*
30354 * Create a build.js file that has the build options you want and pass that
30355 * build file to this file to do the build. See example.build.js for more information.
30356 */
30357
30358/*jslint strict: false, nomen: false */
30359/*global require: false */
30360
30361require({
30362 baseUrl: require.s.contexts._.config.baseUrl,
30363 //Use a separate context than the default context so that the
30364 //build can use the default context.
30365 context: 'build',
30366 catchError: {
30367 define: true
30368 }
30369}, ['env!env/args', 'env!env/quit', 'logger', 'build'],
30370function (args, quit, logger, build) {
30371 build(args).then(function () {}, function (err) {
30372 logger.error(err);
30373 quit(1);
30374 });
30375});
30376
30377
30378 } else if (commandOption === 'v') {
30379 console.log('r.js: ' + version +
30380 ', RequireJS: ' + this.requirejsVars.require.version +
30381 ', UglifyJS: 2.8.29');
30382 } else if (commandOption === 'convert') {
30383 loadLib();
30384
30385 this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'],
30386 function (args, commonJs, print) {
30387
30388 var srcDir, outDir;
30389 srcDir = args[0];
30390 outDir = args[1];
30391
30392 if (!srcDir || !outDir) {
30393 print('Usage: path/to/commonjs/modules output/dir');
30394 return;
30395 }
30396
30397 commonJs.convertDir(args[0], args[1]);
30398 });
30399 } else {
30400 //Just run an app
30401
30402 //Load the bundled libraries for use in the app.
30403 if (commandOption === 'lib') {
30404 loadLib();
30405 }
30406
30407 setBaseUrl(fileName);
30408
30409 if (exists(fileName)) {
30410 exec(readFile(fileName), fileName);
30411 } else {
30412 showHelp();
30413 }
30414 }
30415
30416}((typeof console !== 'undefined' ? console : undefined),
30417 (typeof Packages !== 'undefined' || (typeof window === 'undefined' &&
30418 typeof Components !== 'undefined' && Components.interfaces) ?
30419 Array.prototype.slice.call(arguments, 0) : []),
30420 (typeof readFile !== 'undefined' ? readFile : undefined)));