1/** 2 * @license r.js 2.3.6 Copyright jQuery Foundation and other contributors. 3 * Released under MIT license, http://github.com/requirejs/r.js/LICENSE 4 */ 5 6/* 7 * This is a bootstrap script to allow running RequireJS in the command line 8 * in either a Java/Rhino or Node environment. It is modified by the top-level 9 * dist.js file to inject other files to completely enable this file. It is 10 * the shell of the r.js file. 11 */ 12 13/*jslint evil: true, nomen: true, sloppy: true */ 14/*global readFile: true, process: false, Packages: false, print: false, 15console: false, java: false, module: false, requirejsVars, navigator, 16document, importScripts, self, location, Components, FileUtils */ 17 18var requirejs, require, define, xpcUtil; 19(function (console, args, readFileFunc) { 20 var fileName, env, fs, vm, path, exec, rhinoContext, dir, nodeRequire, 21 nodeDefine, exists, reqMain, loadedOptimizedLib, existsForNode, Cc, Ci, 22 version = '2.3.6', 23 jsSuffixRegExp = /\.js$/, 24 commandOption = '', 25 useLibLoaded = {}, 26 //Used by jslib/rhino/args.js 27 rhinoArgs = args, 28 //Used by jslib/xpconnect/args.js 29 xpconnectArgs = args, 30 readFile = typeof readFileFunc !== 'undefined' ? readFileFunc : null; 31 32 function showHelp() { 33 console.log('See https://github.com/requirejs/r.js for usage.'); 34 } 35 36 if (typeof process !== 'undefined' && process.versions && !!process.versions.node) { 37 env = 'node'; 38 39 //Get the fs module via Node's require before it 40 //gets replaced. Used in require/node.js 41 fs = require('fs'); 42 vm = require('vm'); 43 path = require('path'); 44 //In Node 0.7+ existsSync is on fs. 45 existsForNode = fs.existsSync || path.existsSync; 46 47 nodeRequire = require; 48 nodeDefine = define; 49 reqMain = require.main; 50 51 //Temporarily hide require and define to allow require.js to define 52 //them. 53 require = undefined; 54 define = undefined; 55 56 readFile = function (path) { 57 return fs.readFileSync(path, 'utf8'); 58 }; 59 60 exec = function (string, name) { 61 return vm.runInThisContext(this.requirejsVars.require.makeNodeWrapper(string), 62 name ? fs.realpathSync(name) : ''); 63 }; 64 65 exists = function (fileName) { 66 return existsForNode(fileName); 67 }; 68 69 70 fileName = process.argv[2]; 71 72 if (fileName && fileName.indexOf('-') === 0) { 73 commandOption = fileName.substring(1); 74 fileName = process.argv[3]; 75 } 76 } else if (typeof Packages !== 'undefined') { 77 env = 'rhino'; 78 79 fileName = args[0]; 80 81 if (fileName && fileName.indexOf('-') === 0) { 82 commandOption = fileName.substring(1); 83 fileName = args[1]; 84 } 85 86 //Exec/readFile differs between Rhino and Nashorn. Rhino has an 87 //importPackage where Nashorn does not, so branch on that. This is a 88 //coarser check -- detecting readFile existence might also be enough for 89 //this spot. However, sticking with importPackage to keep it the same 90 //as other Rhino/Nashorn detection branches. 91 if (typeof importPackage !== 'undefined') { 92 rhinoContext = Packages.org.mozilla.javascript.ContextFactory.getGlobal().enterContext(); 93 94 exec = function (string, name) { 95 return rhinoContext.evaluateString(this, string, name, 0, null); 96 }; 97 } else { 98 exec = function (string, name) { 99 load({ script: string, name: name}); 100 }; 101 readFile = readFully; 102 } 103 104 exists = function (fileName) { 105 return (new java.io.File(fileName)).exists(); 106 }; 107 108 //Define a console.log for easier logging. Don't 109 //get fancy though. 110 if (typeof console === 'undefined') { 111 console = { 112 log: function () { 113 print.apply(undefined, arguments); 114 } 115 }; 116 } 117 } else if ((typeof navigator !== 'undefined' && typeof document !== 'undefined') || 118 (typeof importScripts !== 'undefined' && typeof self !== 'undefined')) { 119 env = 'browser'; 120 121 readFile = function (path) { 122 return fs.readFileSync(path, 'utf8'); 123 }; 124 125 exec = function (string) { 126 return eval(string); 127 }; 128 129 exists = function () { 130 console.log('x.js exists not applicable in browser env'); 131 return false;
132 }; 133 134 } else if (typeof Components !== 'undefined' && Components.classes && Components.interfaces) { 135 env = 'xpconnect'; 136 137 Components.utils['import']('resource://gre/modules/FileUtils.jsm'); 138 Cc = Components.classes; 139 Ci = Components.interfaces; 140 141 fileName = args[0]; 142 143 if (fileName && fileName.indexOf('-') === 0) { 144 commandOption = fileName.substring(1); 145 fileName = args[1]; 146 } 147 148 xpcUtil = { 149 isWindows: ('@mozilla.org/windows-registry-key;1' in Cc), 150 cwd: function () { 151 return FileUtils.getFile("CurWorkD", []).path; 152 }, 153 154 //Remove . and .. from paths, normalize on front slashes 155 normalize: function (path) { 156 //There has to be an easier way to do this. 157 var i, part, ary, 158 firstChar = path.charAt(0); 159 160 if (firstChar !== '/' && 161 firstChar !== '\\' && 162 path.indexOf(':') === -1) { 163 //A relative path. Use the current working directory. 164 path = xpcUtil.cwd() + '/' + path; 165 } 166 167 ary = path.replace(/\\/g, '/').split('/'); 168 169 for (i = 0; i < ary.length; i += 1) { 170 part = ary[i]; 171 if (part === '.') { 172 ary.splice(i, 1); 173 i -= 1; 174 } else if (part === '..') { 175 ary.splice(i - 1, 2); 176 i -= 2; 177 } 178 } 179 return ary.join('/'); 180 }, 181 182 xpfile: function (path) { 183 var fullPath; 184 try { 185 fullPath = xpcUtil.normalize(path); 186 if (xpcUtil.isWindows) { 187 fullPath = fullPath.replace(/\//g, '\\'); 188 } 189 return new FileUtils.File(fullPath); 190 } catch (e) { 191 throw new Error((fullPath || path) + ' failed: ' + e); 192 } 193 }, 194 195 readFile: function (/*String*/path, /*String?*/encoding) { 196 //A file read function that can deal with BOMs 197 encoding = encoding || "utf-8"; 198 199 var inStream, convertStream, 200 readData = {}, 201 fileObj = xpcUtil.xpfile(path); 202 203 //XPCOM, you so crazy 204 try { 205 inStream = Cc['@mozilla.org/network/file-input-stream;1'] 206 .createInstance(Ci.nsIFileInputStream); 207 inStream.init(fileObj, 1, 0, false); 208 209 convertStream = Cc['@mozilla.org/intl/converter-input-stream;1'] 210 .createInstance(Ci.nsIConverterInputStream); 211 convertStream.init(inStream, encoding, inStream.available(), 212 Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); 213 214 convertStream.readString(inStream.available(), readData); 215 return readData.value; 216 } catch (e) { 217 throw new Error((fileObj && fileObj.path || '') + ': ' + e); 218 } finally { 219 if (convertStream) { 220 convertStream.close(); 221 } 222 if (inStream) { 223 inStream.close(); 224 } 225 } 226 } 227 }; 228 229 readFile = xpcUtil.readFile; 230 231 exec = function (string) { 232 return eval(string); 233 }; 234 235 exists = function (fileName) { 236 return xpcUtil.xpfile(fileName).exists(); 237 }; 238 239 //Define a console.log for easier logging. Don't 240 //get fancy though. 241 if (typeof console === 'undefined') { 242 console = { 243 log: function () { 244 print.apply(undefined, arguments); 245 } 246 }; 247 } 248 } 249 250 /** vim: et:ts=4:sw=4:sts=4 251 * @license RequireJS 2.3.6 Copyright jQuery Foundation and other contributors. 252 * Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE 253 */ 254//Not using strict: uneven strict support in browsers, #392, and causes 255//problems with requirejs.exec()/transpiler plugins that may not be strict. 256 /*jslint regexp: true, nomen: true, sloppy: true */ 257 /*global window, navigator, document, importScripts, setTimeout, opera */ 258 259 260 (function (global, setTimeout) { 261 var req, s, head, baseElement, dataMain, src, 262 interactiveScript, currentlyAddingScript, mainScript, subPath, 263 version = '2.3.6', 264 commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/mg, 265 cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, 266 jsSuffixRegExp = /\.js$/, 267 currDirRegExp = /^\.\//, 268 op = Object.prototype, 269 ostring = op.toString, 270 hasOwn = op.hasOwnProperty, 271 isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document), 272 isWebWorker = !isBrowser && typeof importScripts !== 'undefined', 273 //PS3 indicates loaded and complete, but need to wait for complete 274 //specifically. Sequence is 'loading', 'loaded', execution, 275 // then 'complete'. The UA check is unfortunate, but not sure how 276 //to feature test w/o causing perf issues. 277 readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? 278 /^complete$/ : /^(complete|loaded)$/, 279 defContextName = '_', 280 //Oh the tragedy, detecting opera. See the usage of isOpera for reason. 281 isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]', 282 contexts = {}, 283 cfg = {}, 284 globalDefQueue = [], 285 useInteractive = false;
vendor: 88,489 bytes, lines 286-2326
286 287 //Could match something like ')//comment', do not lose the prefix to comment. 288 function commentReplace(match, singlePrefix) { 289 return singlePrefix || ''; 290 } 291 292 function isFunction(it) { 293 return ostring.call(it) === '[object Function]'; 294 } 295 296 function isArray(it) { 297 return ostring.call(it) === '[object Array]'; 298 } 299 300 /** 301 * Helper function for iterating over an array. If the func returns 302 * a true value, it will break out of the loop. 303 */ 304 function each(ary, func) { 305 if (ary) { 306 var i; 307 for (i = 0; i < ary.length; i += 1) { 308 if (ary[i] && func(ary[i], i, ary)) { 309 break; 310 } 311 } 312 } 313 } 314 315 /** 316 * Helper function for iterating over an array backwards. If the func 317 * returns a true value, it will break out of the loop. 318 */ 319 function eachReverse(ary, func) { 320 if (ary) { 321 var i; 322 for (i = ary.length - 1; i > -1; i -= 1) { 323 if (ary[i] && func(ary[i], i, ary)) { 324 break; 325 } 326 } 327 } 328 } 329 330 function hasProp(obj, prop) { 331 return hasOwn.call(obj, prop); 332 } 333 334 function getOwn(obj, prop) { 335 return hasProp(obj, prop) && obj[prop]; 336 } 337 338 /** 339 * Cycles over properties in an object and calls a function for each 340 * property value. If the function returns a truthy value, then the 341 * iteration is stopped. 342 */ 343 function eachProp(obj, func) { 344 var prop; 345 for (prop in obj) { 346 if (hasProp(obj, prop)) { 347 if (func(obj[prop], prop)) { 348 break; 349 } 350 } 351 } 352 } 353 354 /** 355 * Simple function to mix in properties from source into target, 356 * but only if target does not already have a property of the same name. 357 */ 358 function mixin(target, source, force, deepStringMixin) { 359 if (source) { 360 eachProp(source, function (value, prop) { 361 if (force || !hasProp(target, prop)) { 362 if (deepStringMixin && typeof value === 'object' && value && 363 !isArray(value) && !isFunction(value) && 364 !(value instanceof RegExp)) { 365 366 if (!target[prop]) { 367 target[prop] = {}; 368 } 369 mixin(target[prop], value, force, deepStringMixin); 370 } else { 371 target[prop] = value; 372 } 373 } 374 }); 375 } 376 return target; 377 } 378 379 //Similar to Function.prototype.bind, but the 'this' object is specified 380 //first, since it is easier to read/figure out what 'this' will be. 381 function bind(obj, fn) { 382 return function () { 383 return fn.apply(obj, arguments); 384 }; 385 } 386 387 function scripts() { 388 return document.getElementsByTagName('script'); 389 } 390 391 function defaultOnError(err) { 392 throw err; 393 } 394 395 //Allow getting a global that is expressed in 396 //dot notation, like 'a.b.c'. 397 function getGlobal(value) { 398 if (!value) { 399 return value; 400 } 401 var g = global; 402 each(value.split('.'), function (part) { 403 g = g[part]; 404 }); 405 return g; 406 } 407 408 /** 409 * Constructs an error with a pointer to an URL with more information. 410 * @param {String} id the error ID that maps to an ID on a web page. 411 * @param {String} message human readable error. 412 * @param {Error} [err] the original error, if there is one. 413 * 414 * @returns {Error} 415 */ 416 function makeError(id, msg, err, requireModules) { 417 var e = new Error(msg + '\nhttps://requirejs.org/docs/errors.html#' + id); 418 e.requireType = id; 419 e.requireModules = requireModules; 420 if (err) { 421 e.originalError = err; 422 } 423 return e; 424 } 425 426 if (typeof define !== 'undefined') { 427 //If a define is already in play via another AMD loader, 428 //do not overwrite. 429 return; 430 } 431 432 if (typeof requirejs !== 'undefined') { 433 if (isFunction(requirejs)) { 434 //Do not overwrite an existing requirejs instance. 435 return; 436 } 437 cfg = requirejs; 438 requirejs = undefined; 439 } 440 441 //Allow for a require config object 442 if (typeof require !== 'undefined' && !isFunction(require)) { 443 //assume it is a config object. 444 cfg = require; 445 require = undefined; 446 } 447 448 function newContext(contextName) { 449 var inCheckLoaded, Module, context, handlers, 450 checkLoadedTimeoutId, 451 config = { 452 //Defaults. Do not set a default for map 453 //config to speed up normalize(), which 454 //will run faster if there is no default. 455 waitSeconds: 7, 456 baseUrl: './', 457 paths: {}, 458 bundles: {}, 459 pkgs: {}, 460 shim: {}, 461 config: {} 462 }, 463 registry = {}, 464 //registry of just enabled modules, to speed 465 //cycle breaking code when lots of modules 466 //are registered, but not activated. 467 enabledRegistry = {}, 468 undefEvents = {}, 469 defQueue = [], 470 defined = {}, 471 urlFetched = {}, 472 bundlesMap = {}, 473 requireCounter = 1, 474 unnormalizedCounter = 1; 475 476 /** 477 * Trims the . and .. from an array of path segments. 478 * It will keep a leading path segment if a .. will become 479 * the first path segment, to help with module name lookups, 480 * which act like paths, but can be remapped. But the end result, 481 * all paths that use this function should look normalized. 482 * NOTE: this method MODIFIES the input array. 483 * @param {Array} ary the array of path segments. 484 */ 485 function trimDots(ary) { 486 var i, part; 487 for (i = 0; i < ary.length; i++) { 488 part = ary[i]; 489 if (part === '.') { 490 ary.splice(i, 1); 491 i -= 1; 492 } else if (part === '..') { 493 // If at the start, or previous value is still .., 494 // keep them so that when converted to a path it may 495 // still work when converted to a path, even though 496 // as an ID it is less than ideal. In larger point 497 // releases, may be better to just kick out an error. 498 if (i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1] === '..') { 499 continue; 500 } else if (i > 0) { 501 ary.splice(i - 1, 2); 502 i -= 2; 503 } 504 } 505 } 506 } 507 508 /** 509 * Given a relative module name, like ./something, normalize it to 510 * a real name that can be mapped to a path. 511 * @param {String} name the relative name 512 * @param {String} baseName a real name that the name arg is relative 513 * to. 514 * @param {Boolean} applyMap apply the map config to the value. Should 515 * only be done if this normalization is for a dependency ID. 516 * @returns {String} normalized name 517 */ 518 function normalize(name, baseName, applyMap) { 519 var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex, 520 foundMap, foundI, foundStarMap, starI, normalizedBaseParts, 521 baseParts = (baseName && baseName.split('/')), 522 map = config.map, 523 starMap = map && map['*']; 524 525 //Adjust any relative paths. 526 if (name) { 527 name = name.split('/'); 528 lastIndex = name.length - 1; 529 530 // If wanting node ID compatibility, strip .js from end 531 // of IDs. Have to do this here, and not in nameToUrl 532 // because node allows either .js or non .js to map 533 // to same file. 534 if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { 535 name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); 536 } 537 538 // Starts with a '.' so need the baseName 539 if (name[0].charAt(0) === '.' && baseParts) { 540 //Convert baseName to array, and lop off the last part, 541 //so that . matches that 'directory' and not name of the baseName's 542 //module. For instance, baseName of 'one/two/three', maps to 543 //'one/two/three.js', but we want the directory, 'one/two' for 544 //this normalization. 545 normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); 546 name = normalizedBaseParts.concat(name); 547 } 548 549 trimDots(name); 550 name = name.join('/'); 551 } 552 553 //Apply map config if available. 554 if (applyMap && map && (baseParts || starMap)) { 555 nameParts = name.split('/'); 556 557 outerLoop: for (i = nameParts.length; i > 0; i -= 1) { 558 nameSegment = nameParts.slice(0, i).join('/'); 559 560 if (baseParts) { 561 //Find the longest baseName segment match in the config. 562 //So, do joins on the biggest to smallest lengths of baseParts. 563 for (j = baseParts.length; j > 0; j -= 1) { 564 mapValue = getOwn(map, baseParts.slice(0, j).join('/')); 565 566 //baseName segment has config, find if it has one for 567 //this name. 568 if (mapValue) { 569 mapValue = getOwn(mapValue, nameSegment); 570 if (mapValue) { 571 //Match, update name to the new value. 572 foundMap = mapValue; 573 foundI = i; 574 break outerLoop; 575 } 576 } 577 } 578 } 579 580 //Check for a star map match, but just hold on to it, 581 //if there is a shorter segment match later in a matching 582 //config, then favor over this star map. 583 if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) { 584 foundStarMap = getOwn(starMap, nameSegment); 585 starI = i; 586 } 587 } 588 589 if (!foundMap && foundStarMap) { 590 foundMap = foundStarMap; 591 foundI = starI; 592 } 593 594 if (foundMap) { 595 nameParts.splice(0, foundI, foundMap); 596 name = nameParts.join('/'); 597 } 598 } 599 600 // If the name points to a package's name, use 601 // the package main instead. 602 pkgMain = getOwn(config.pkgs, name); 603 604 return pkgMain ? pkgMain : name; 605 } 606 607 function removeScript(name) { 608 if (isBrowser) { 609 each(scripts(), function (scriptNode) { 610 if (scriptNode.getAttribute('data-requiremodule') === name && 611 scriptNode.getAttribute('data-requirecontext') === context.contextName) { 612 scriptNode.parentNode.removeChild(scriptNode); 613 return true; 614 } 615 }); 616 } 617 } 618 619 function hasPathFallback(id) { 620 var pathConfig = getOwn(config.paths, id); 621 if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) { 622 //Pop off the first array value, since it failed, and 623 //retry 624 pathConfig.shift(); 625 context.require.undef(id); 626 627 //Custom require that does not do map translation, since 628 //ID is "absolute", already mapped/resolved. 629 context.makeRequire(null, { 630 skipMap: true 631 })([id]); 632 633 return true; 634 } 635 } 636 637 //Turns a plugin!resource to [plugin, resource] 638 //with the plugin being undefined if the name 639 //did not have a plugin prefix. 640 function splitPrefix(name) { 641 var prefix, 642 index = name ? name.indexOf('!') : -1; 643 if (index > -1) { 644 prefix = name.substring(0, index); 645 name = name.substring(index + 1, name.length); 646 } 647 return [prefix, name]; 648 } 649 650 /** 651 * Creates a module mapping that includes plugin prefix, module 652 * name, and path. If parentModuleMap is provided it will 653 * also normalize the name via require.normalize() 654 * 655 * @param {String} name the module name 656 * @param {String} [parentModuleMap] parent module map 657 * for the module name, used to resolve relative names. 658 * @param {Boolean} isNormalized: is the ID already normalized. 659 * This is true if this call is done for a define() module ID. 660 * @param {Boolean} applyMap: apply the map config to the ID. 661 * Should only be true if this map is for a dependency. 662 * 663 * @returns {Object} 664 */ 665 function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { 666 var url, pluginModule, suffix, nameParts, 667 prefix = null, 668 parentName = parentModuleMap ? parentModuleMap.name : null, 669 originalName = name, 670 isDefine = true, 671 normalizedName = ''; 672 673 //If no name, then it means it is a require call, generate an 674 //internal name. 675 if (!name) { 676 isDefine = false; 677 name = '_@r' + (requireCounter += 1); 678 } 679 680 nameParts = splitPrefix(name); 681 prefix = nameParts[0]; 682 name = nameParts[1]; 683 684 if (prefix) { 685 prefix = normalize(prefix, parentName, applyMap); 686 pluginModule = getOwn(defined, prefix); 687 } 688 689 //Account for relative paths if there is a base name. 690 if (name) { 691 if (prefix) { 692 if (isNormalized) { 693 normalizedName = name; 694 } else if (pluginModule && pluginModule.normalize) { 695 //Plugin is loaded, use its normalize method. 696 normalizedName = pluginModule.normalize(name, function (name) { 697 return normalize(name, parentName, applyMap); 698 }); 699 } else { 700 // If nested plugin references, then do not try to 701 // normalize, as it will not normalize correctly. This 702 // places a restriction on resourceIds, and the longer 703 // term solution is not to normalize until plugins are 704 // loaded and all normalizations to allow for async 705 // loading of a loader plugin. But for now, fixes the 706 // common uses. Details in #1131 707 normalizedName = name.indexOf('!') === -1 ? 708 normalize(name, parentName, applyMap) : 709 name; 710 } 711 } else { 712 //A regular module. 713 normalizedName = normalize(name, parentName, applyMap); 714 715 //Normalized name may be a plugin ID due to map config 716 //application in normalize. The map config values must 717 //already be normalized, so do not need to redo that part. 718 nameParts = splitPrefix(normalizedName); 719 prefix = nameParts[0]; 720 normalizedName = nameParts[1]; 721 isNormalized = true; 722 723 url = context.nameToUrl(normalizedName); 724 } 725 } 726 727 //If the id is a plugin id that cannot be determined if it needs 728 //normalization, stamp it with a unique ID so two matching relative 729 //ids that may conflict can be separate. 730 suffix = prefix && !pluginModule && !isNormalized ? 731 '_unnormalized' + (unnormalizedCounter += 1) : 732 ''; 733 734 return { 735 prefix: prefix, 736 name: normalizedName, 737 parentMap: parentModuleMap, 738 unnormalized: !!suffix, 739 url: url, 740 originalName: originalName, 741 isDefine: isDefine, 742 id: (prefix ? 743 prefix + '!' + normalizedName : 744 normalizedName) + suffix 745 }; 746 } 747 748 function getModule(depMap) { 749 var id = depMap.id, 750 mod = getOwn(registry, id); 751 752 if (!mod) { 753 mod = registry[id] = new context.Module(depMap); 754 } 755 756 return mod; 757 } 758 759 function on(depMap, name, fn) { 760 var id = depMap.id, 761 mod = getOwn(registry, id); 762 763 if (hasProp(defined, id) && 764 (!mod || mod.defineEmitComplete)) { 765 if (name === 'defined') { 766 fn(defined[id]); 767 } 768 } else { 769 mod = getModule(depMap); 770 if (mod.error && name === 'error') { 771 fn(mod.error); 772 } else { 773 mod.on(name, fn); 774 } 775 } 776 } 777 778 function onError(err, errback) { 779 var ids = err.requireModules, 780 notified = false; 781 782 if (errback) { 783 errback(err); 784 } else { 785 each(ids, function (id) { 786 var mod = getOwn(registry, id); 787 if (mod) { 788 //Set error on module, so it skips timeout checks. 789 mod.error = err; 790 if (mod.events.error) { 791 notified = true; 792 mod.emit('error', err); 793 } 794 } 795 }); 796 797 if (!notified) { 798 req.onError(err); 799 } 800 } 801 } 802 803 /** 804 * Internal method to transfer globalQueue items to this context's 805 * defQueue. 806 */ 807 function takeGlobalQueue() { 808 //Push all the globalDefQueue items into the context's defQueue 809 if (globalDefQueue.length) { 810 each(globalDefQueue, function(queueItem) { 811 var id = queueItem[0]; 812 if (typeof id === 'string') { 813 context.defQueueMap[id] = true; 814 } 815 defQueue.push(queueItem); 816 }); 817 globalDefQueue = []; 818 } 819 } 820 821 handlers = { 822 'require': function (mod) { 823 if (mod.require) { 824 return mod.require; 825 } else { 826 return (mod.require = context.makeRequire(mod.map)); 827 } 828 }, 829 'exports': function (mod) { 830 mod.usingExports = true; 831 if (mod.map.isDefine) { 832 if (mod.exports) { 833 return (defined[mod.map.id] = mod.exports); 834 } else { 835 return (mod.exports = defined[mod.map.id] = {}); 836 } 837 } 838 }, 839 'module': function (mod) { 840 if (mod.module) { 841 return mod.module; 842 } else { 843 return (mod.module = { 844 id: mod.map.id, 845 uri: mod.map.url, 846 config: function () { 847 return getOwn(config.config, mod.map.id) || {}; 848 }, 849 exports: mod.exports || (mod.exports = {}) 850 }); 851 } 852 } 853 }; 854 855 function cleanRegistry(id) { 856 //Clean up machinery used for waiting modules. 857 delete registry[id]; 858 delete enabledRegistry[id]; 859 } 860 861 function breakCycle(mod, traced, processed) { 862 var id = mod.map.id; 863 864 if (mod.error) { 865 mod.emit('error', mod.error); 866 } else { 867 traced[id] = true; 868 each(mod.depMaps, function (depMap, i) { 869 var depId = depMap.id, 870 dep = getOwn(registry, depId); 871 872 //Only force things that have not completed 873 //being defined, so still in the registry, 874 //and only if it has not been matched up 875 //in the module already. 876 if (dep && !mod.depMatched[i] && !processed[depId]) { 877 if (getOwn(traced, depId)) { 878 mod.defineDep(i, defined[depId]); 879 mod.check(); //pass false? 880 } else { 881 breakCycle(dep, traced, processed); 882 } 883 } 884 }); 885 processed[id] = true; 886 } 887 } 888 889 function checkLoaded() { 890 var err, usingPathFallback, 891 waitInterval = config.waitSeconds * 1000, 892 //It is possible to disable the wait interval by using waitSeconds of 0. 893 expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), 894 noLoads = [], 895 reqCalls = [], 896 stillLoading = false, 897 needCycleCheck = true; 898 899 //Do not bother if this call was a result of a cycle break. 900 if (inCheckLoaded) { 901 return; 902 } 903 904 inCheckLoaded = true; 905 906 //Figure out the state of all the modules. 907 eachProp(enabledRegistry, function (mod) { 908 var map = mod.map, 909 modId = map.id; 910 911 //Skip things that are not enabled or in error state. 912 if (!mod.enabled) { 913 return; 914 } 915 916 if (!map.isDefine) { 917 reqCalls.push(mod); 918 } 919 920 if (!mod.error) { 921 //If the module should be executed, and it has not 922 //been inited and time is up, remember it. 923 if (!mod.inited && expired) { 924 if (hasPathFallback(modId)) { 925 usingPathFallback = true; 926 stillLoading = true; 927 } else { 928 noLoads.push(modId); 929 removeScript(modId); 930 } 931 } else if (!mod.inited && mod.fetched && map.isDefine) { 932 stillLoading = true; 933 if (!map.prefix) { 934 //No reason to keep looking for unfinished 935 //loading. If the only stillLoading is a 936 //plugin resource though, keep going, 937 //because it may be that a plugin resource 938 //is waiting on a non-plugin cycle. 939 return (needCycleCheck = false); 940 } 941 } 942 } 943 }); 944 945 if (expired && noLoads.length) { 946 //If wait time expired, throw error of unloaded modules. 947 err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads); 948 err.contextName = context.contextName; 949 return onError(err); 950 } 951 952 //Not expired, check for a cycle. 953 if (needCycleCheck) { 954 each(reqCalls, function (mod) { 955 breakCycle(mod, {}, {}); 956 }); 957 } 958 959 //If still waiting on loads, and the waiting load is something 960 //other than a plugin resource, or there are still outstanding 961 //scripts, then just try back later. 962 if ((!expired || usingPathFallback) && stillLoading) { 963 //Something is still waiting to load. Wait for it, but only 964 //if a timeout is not already in effect. 965 if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { 966 checkLoadedTimeoutId = setTimeout(function () { 967 checkLoadedTimeoutId = 0; 968 checkLoaded(); 969 }, 50); 970 } 971 } 972 973 inCheckLoaded = false; 974 } 975 976 Module = function (map) { 977 this.events = getOwn(undefEvents, map.id) || {}; 978 this.map = map; 979 this.shim = getOwn(config.shim, map.id); 980 this.depExports = []; 981 this.depMaps = []; 982 this.depMatched = []; 983 this.pluginMaps = {}; 984 this.depCount = 0; 985 986 /* this.exports this.factory 987 this.depMaps = [], 988 this.enabled, this.fetched 989 */ 990 }; 991 992 Module.prototype = { 993 init: function (depMaps, factory, errback, options) { 994 options = options || {}; 995 996 //Do not do more inits if already done. Can happen if there 997 //are multiple define calls for the same module. That is not 998 //a normal, common case, but it is also not unexpected. 999 if (this.inited) { 1000 return; 1001 } 1002 1003 this.factory = factory; 1004 1005 if (errback) { 1006 //Register for errors on this module. 1007 this.on('error', errback); 1008 } else if (this.events.error) { 1009 //If no errback already, but there are error listeners 1010 //on this module, set up an errback to pass to the deps. 1011 errback = bind(this, function (err) { 1012 this.emit('error', err); 1013 }); 1014 } 1015 1016 //Do a copy of the dependency array, so that 1017 //source inputs are not modified. For example 1018 //"shim" deps are passed in here directly, and 1019 //doing a direct modification of the depMaps array 1020 //would affect that config. 1021 this.depMaps = depMaps && depMaps.slice(0); 1022 1023 this.errback = errback; 1024 1025 //Indicate this module has be initialized 1026 this.inited = true; 1027 1028 this.ignore = options.ignore; 1029 1030 //Could have option to init this module in enabled mode, 1031 //or could have been previously marked as enabled. However, 1032 //the dependencies are not known until init is called. So 1033 //if enabled previously, now trigger dependencies as enabled. 1034 if (options.enabled || this.enabled) { 1035 //Enable this module and dependencies. 1036 //Will call this.check() 1037 this.enable(); 1038 } else { 1039 this.check(); 1040 } 1041 }, 1042 1043 defineDep: function (i, depExports) { 1044 //Because of cycles, defined callback for a given 1045 //export can be called more than once. 1046 if (!this.depMatched[i]) { 1047 this.depMatched[i] = true; 1048 this.depCount -= 1; 1049 this.depExports[i] = depExports; 1050 } 1051 }, 1052 1053 fetch: function () { 1054 if (this.fetched) { 1055 return; 1056 } 1057 this.fetched = true; 1058 1059 context.startTime = (new Date()).getTime(); 1060 1061 var map = this.map; 1062 1063 //If the manager is for a plugin managed resource, 1064 //ask the plugin to load it now. 1065 if (this.shim) { 1066 context.makeRequire(this.map, { 1067 enableBuildCallback: true 1068 })(this.shim.deps || [], bind(this, function () { 1069 return map.prefix ? this.callPlugin() : this.load(); 1070 })); 1071 } else { 1072 //Regular dependency. 1073 return map.prefix ? this.callPlugin() : this.load(); 1074 } 1075 }, 1076 1077 load: function () { 1078 var url = this.map.url; 1079 1080 //Regular dependency. 1081 if (!urlFetched[url]) { 1082 urlFetched[url] = true; 1083 context.load(this.map.id, url); 1084 } 1085 }, 1086 1087 /** 1088 * Checks if the module is ready to define itself, and if so, 1089 * define it. 1090 */ 1091 check: function () { 1092 if (!this.enabled || this.enabling) { 1093 return; 1094 } 1095 1096 var err, cjsModule, 1097 id = this.map.id, 1098 depExports = this.depExports, 1099 exports = this.exports, 1100 factory = this.factory; 1101 1102 if (!this.inited) { 1103 // Only fetch if not already in the defQueue. 1104 if (!hasProp(context.defQueueMap, id)) { 1105 this.fetch(); 1106 } 1107 } else if (this.error) { 1108 this.emit('error', this.error); 1109 } else if (!this.defining) { 1110 //The factory could trigger another require call 1111 //that would result in checking this module to 1112 //define itself again. If already in the process 1113 //of doing that, skip this work. 1114 this.defining = true; 1115 1116 if (this.depCount < 1 && !this.defined) { 1117 if (isFunction(factory)) { 1118 //If there is an error listener, favor passing 1119 //to that instead of throwing an error. However, 1120 //only do it for define()'d modules. require 1121 //errbacks should not be called for failures in 1122 //their callbacks (#699). However if a global 1123 //onError is set, use that. 1124 if ((this.events.error && this.map.isDefine) || 1125 req.onError !== defaultOnError) { 1126 try { 1127 exports = context.execCb(id, factory, depExports, exports); 1128 } catch (e) { 1129 err = e; 1130 } 1131 } else { 1132 exports = context.execCb(id, factory, depExports, exports); 1133 } 1134 1135 // Favor return value over exports. If node/cjs in play, 1136 // then will not have a return value anyway. Favor 1137 // module.exports assignment over exports object. 1138 if (this.map.isDefine && exports === undefined) { 1139 cjsModule = this.module; 1140 if (cjsModule) { 1141 exports = cjsModule.exports; 1142 } else if (this.usingExports) { 1143 //exports already set the defined value. 1144 exports = this.exports; 1145 } 1146 } 1147 1148 if (err) { 1149 err.requireMap = this.map; 1150 err.requireModules = this.map.isDefine ? [this.map.id] : null; 1151 err.requireType = this.map.isDefine ? 'define' : 'require'; 1152 return onError((this.error = err)); 1153 } 1154 1155 } else { 1156 //Just a literal value 1157 exports = factory; 1158 } 1159 1160 this.exports = exports; 1161 1162 if (this.map.isDefine && !this.ignore) { 1163 defined[id] = exports; 1164 1165 if (req.onResourceLoad) { 1166 var resLoadMaps = []; 1167 each(this.depMaps, function (depMap) { 1168 resLoadMaps.push(depMap.normalizedMap || depMap); 1169 }); 1170 req.onResourceLoad(context, this.map, resLoadMaps); 1171 } 1172 } 1173 1174 //Clean up 1175 cleanRegistry(id); 1176 1177 this.defined = true; 1178 } 1179 1180 //Finished the define stage. Allow calling check again 1181 //to allow define notifications below in the case of a 1182 //cycle. 1183 this.defining = false; 1184 1185 if (this.defined && !this.defineEmitted) { 1186 this.defineEmitted = true; 1187 this.emit('defined', this.exports); 1188 this.defineEmitComplete = true; 1189 } 1190 1191 } 1192 }, 1193 1194 callPlugin: function () { 1195 var map = this.map, 1196 id = map.id, 1197 //Map already normalized the prefix. 1198 pluginMap = makeModuleMap(map.prefix); 1199 1200 //Mark this as a dependency for this plugin, so it 1201 //can be traced for cycles. 1202 this.depMaps.push(pluginMap); 1203 1204 on(pluginMap, 'defined', bind(this, function (plugin) { 1205 var load, normalizedMap, normalizedMod, 1206 bundleId = getOwn(bundlesMap, this.map.id), 1207 name = this.map.name, 1208 parentName = this.map.parentMap ? this.map.parentMap.name : null, 1209 localRequire = context.makeRequire(map.parentMap, { 1210 enableBuildCallback: true 1211 }); 1212 1213 //If current map is not normalized, wait for that 1214 //normalized name to load instead of continuing. 1215 if (this.map.unnormalized) { 1216 //Normalize the ID if the plugin allows it. 1217 if (plugin.normalize) { 1218 name = plugin.normalize(name, function (name) { 1219 return normalize(name, parentName, true); 1220 }) || ''; 1221 } 1222 1223 //prefix and name should already be normalized, no need 1224 //for applying map config again either. 1225 normalizedMap = makeModuleMap(map.prefix + '!' + name, 1226 this.map.parentMap, 1227 true); 1228 on(normalizedMap, 1229 'defined', bind(this, function (value) { 1230 this.map.normalizedMap = normalizedMap; 1231 this.init([], function () { return value; }, null, { 1232 enabled: true, 1233 ignore: true 1234 }); 1235 })); 1236 1237 normalizedMod = getOwn(registry, normalizedMap.id); 1238 if (normalizedMod) { 1239 //Mark this as a dependency for this plugin, so it 1240 //can be traced for cycles. 1241 this.depMaps.push(normalizedMap); 1242 1243 if (this.events.error) { 1244 normalizedMod.on('error', bind(this, function (err) { 1245 this.emit('error', err); 1246 })); 1247 } 1248 normalizedMod.enable(); 1249 } 1250 1251 return; 1252 } 1253 1254 //If a paths config, then just load that file instead to 1255 //resolve the plugin, as it is built into that paths layer. 1256 if (bundleId) { 1257 this.map.url = context.nameToUrl(bundleId); 1258 this.load(); 1259 return; 1260 } 1261 1262 load = bind(this, function (value) { 1263 this.init([], function () { return value; }, null, { 1264 enabled: true 1265 }); 1266 }); 1267 1268 load.error = bind(this, function (err) { 1269 this.inited = true; 1270 this.error = err; 1271 err.requireModules = [id]; 1272 1273 //Remove temp unnormalized modules for this module, 1274 //since they will never be resolved otherwise now. 1275 eachProp(registry, function (mod) { 1276 if (mod.map.id.indexOf(id + '_unnormalized') === 0) { 1277 cleanRegistry(mod.map.id); 1278 } 1279 }); 1280 1281 onError(err); 1282 }); 1283 1284 //Allow plugins to load other code without having to know the 1285 //context or how to 'complete' the load. 1286 load.fromText = bind(this, function (text, textAlt) { 1287 /*jslint evil: true */ 1288 var moduleName = map.name, 1289 moduleMap = makeModuleMap(moduleName), 1290 hasInteractive = useInteractive; 1291 1292 //As of 2.1.0, support just passing the text, to reinforce 1293 //fromText only being called once per resource. Still 1294 //support old style of passing moduleName but discard 1295 //that moduleName in favor of the internal ref. 1296 if (textAlt) { 1297 text = textAlt; 1298 } 1299 1300 //Turn off interactive script matching for IE for any define 1301 //calls in the text, then turn it back on at the end. 1302 if (hasInteractive) { 1303 useInteractive = false; 1304 } 1305 1306 //Prime the system by creating a module instance for 1307 //it. 1308 getModule(moduleMap); 1309 1310 //Transfer any config to this other module. 1311 if (hasProp(config.config, id)) { 1312 config.config[moduleName] = config.config[id]; 1313 } 1314 1315 try { 1316 req.exec(text); 1317 } catch (e) { 1318 return onError(makeError('fromtexteval', 1319 'fromText eval for ' + id + 1320 ' failed: ' + e, 1321 e, 1322 [id])); 1323 } 1324 1325 if (hasInteractive) { 1326 useInteractive = true; 1327 } 1328 1329 //Mark this as a dependency for the plugin 1330 //resource 1331 this.depMaps.push(moduleMap); 1332 1333 //Support anonymous modules. 1334 context.completeLoad(moduleName); 1335 1336 //Bind the value of that module to the value for this 1337 //resource ID. 1338 localRequire([moduleName], load); 1339 }); 1340 1341 //Use parentName here since the plugin's name is not reliable, 1342 //could be some weird string with no path that actually wants to 1343 //reference the parentName's path. 1344 plugin.load(map.name, localRequire, load, config); 1345 })); 1346 1347 context.enable(pluginMap, this); 1348 this.pluginMaps[pluginMap.id] = pluginMap; 1349 }, 1350 1351 enable: function () { 1352 enabledRegistry[this.map.id] = this; 1353 this.enabled = true; 1354 1355 //Set flag mentioning that the module is enabling, 1356 //so that immediate calls to the defined callbacks 1357 //for dependencies do not trigger inadvertent load 1358 //with the depCount still being zero. 1359 this.enabling = true; 1360 1361 //Enable each dependency 1362 each(this.depMaps, bind(this, function (depMap, i) { 1363 var id, mod, handler; 1364 1365 if (typeof depMap === 'string') { 1366 //Dependency needs to be converted to a depMap 1367 //and wired up to this module. 1368 depMap = makeModuleMap(depMap, 1369 (this.map.isDefine ? this.map : this.map.parentMap), 1370 false, 1371 !this.skipMap); 1372 this.depMaps[i] = depMap; 1373 1374 handler = getOwn(handlers, depMap.id); 1375 1376 if (handler) { 1377 this.depExports[i] = handler(this); 1378 return; 1379 } 1380 1381 this.depCount += 1; 1382 1383 on(depMap, 'defined', bind(this, function (depExports) { 1384 if (this.undefed) { 1385 return; 1386 } 1387 this.defineDep(i, depExports); 1388 this.check(); 1389 })); 1390 1391 if (this.errback) { 1392 on(depMap, 'error', bind(this, this.errback)); 1393 } else if (this.events.error) { 1394 // No direct errback on this module, but something 1395 // else is listening for errors, so be sure to 1396 // propagate the error correctly. 1397 on(depMap, 'error', bind(this, function(err) { 1398 this.emit('error', err); 1399 })); 1400 } 1401 } 1402 1403 id = depMap.id; 1404 mod = registry[id]; 1405 1406 //Skip special modules like 'require', 'exports', 'module' 1407 //Also, don't call enable if it is already enabled, 1408 //important in circular dependency cases. 1409 if (!hasProp(handlers, id) && mod && !mod.enabled) { 1410 context.enable(depMap, this); 1411 } 1412 })); 1413 1414 //Enable each plugin that is used in 1415 //a dependency 1416 eachProp(this.pluginMaps, bind(this, function (pluginMap) { 1417 var mod = getOwn(registry, pluginMap.id); 1418 if (mod && !mod.enabled) { 1419 context.enable(pluginMap, this); 1420 } 1421 })); 1422 1423 this.enabling = false; 1424 1425 this.check(); 1426 }, 1427 1428 on: function (name, cb) { 1429 var cbs = this.events[name]; 1430 if (!cbs) { 1431 cbs = this.events[name] = []; 1432 } 1433 cbs.push(cb); 1434 }, 1435 1436 emit: function (name, evt) { 1437 each(this.events[name], function (cb) { 1438 cb(evt); 1439 }); 1440 if (name === 'error') { 1441 //Now that the error handler was triggered, remove 1442 //the listeners, since this broken Module instance 1443 //can stay around for a while in the registry. 1444 delete this.events[name]; 1445 } 1446 } 1447 }; 1448 1449 function callGetModule(args) { 1450 //Skip modules already defined. 1451 if (!hasProp(defined, args[0])) { 1452 getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]); 1453 } 1454 } 1455 1456 function removeListener(node, func, name, ieName) { 1457 //Favor detachEvent because of IE9 1458 //issue, see attachEvent/addEventListener comment elsewhere 1459 //in this file. 1460 if (node.detachEvent && !isOpera) { 1461 //Probably IE. If not it will throw an error, which will be 1462 //useful to know. 1463 if (ieName) { 1464 node.detachEvent(ieName, func); 1465 } 1466 } else { 1467 node.removeEventListener(name, func, false); 1468 } 1469 } 1470 1471 /** 1472 * Given an event from a script node, get the requirejs info from it, 1473 * and then removes the event listeners on the node. 1474 * @param {Event} evt 1475 * @returns {Object} 1476 */ 1477 function getScriptData(evt) { 1478 //Using currentTarget instead of target for Firefox 2.0's sake. Not 1479 //all old browsers will be supported, but this one was easy enough 1480 //to support and still makes sense. 1481 var node = evt.currentTarget || evt.srcElement; 1482 1483 //Remove the listeners once here. 1484 removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange'); 1485 removeListener(node, context.onScriptError, 'error'); 1486 1487 return { 1488 node: node, 1489 id: node && node.getAttribute('data-requiremodule') 1490 }; 1491 } 1492 1493 function intakeDefines() { 1494 var args; 1495 1496 //Any defined modules in the global queue, intake them now. 1497 takeGlobalQueue(); 1498 1499 //Make sure any remaining defQueue items get properly processed. 1500 while (defQueue.length) { 1501 args = defQueue.shift(); 1502 if (args[0] === null) { 1503 return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + 1504 args[args.length - 1])); 1505 } else { 1506 //args are id, deps, factory. Should be normalized by the 1507 //define() function. 1508 callGetModule(args); 1509 } 1510 } 1511 context.defQueueMap = {}; 1512 } 1513 1514 context = { 1515 config: config, 1516 contextName: contextName, 1517 registry: registry, 1518 defined: defined, 1519 urlFetched: urlFetched, 1520 defQueue: defQueue, 1521 defQueueMap: {}, 1522 Module: Module, 1523 makeModuleMap: makeModuleMap, 1524 nextTick: req.nextTick, 1525 onError: onError, 1526 1527 /** 1528 * Set a configuration for the context. 1529 * @param {Object} cfg config object to integrate. 1530 */ 1531 configure: function (cfg) { 1532 //Make sure the baseUrl ends in a slash. 1533 if (cfg.baseUrl) { 1534 if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') { 1535 cfg.baseUrl += '/'; 1536 } 1537 } 1538 1539 // Convert old style urlArgs string to a function. 1540 if (typeof cfg.urlArgs === 'string') { 1541 var urlArgs = cfg.urlArgs; 1542 cfg.urlArgs = function(id, url) { 1543 return (url.indexOf('?') === -1 ? '?' : '&') + urlArgs; 1544 }; 1545 } 1546 1547 //Save off the paths since they require special processing, 1548 //they are additive. 1549 var shim = config.shim, 1550 objs = { 1551 paths: true, 1552 bundles: true, 1553 config: true, 1554 map: true 1555 }; 1556 1557 eachProp(cfg, function (value, prop) { 1558 if (objs[prop]) { 1559 if (!config[prop]) { 1560 config[prop] = {}; 1561 } 1562 mixin(config[prop], value, true, true); 1563 } else { 1564 config[prop] = value; 1565 } 1566 }); 1567 1568 //Reverse map the bundles 1569 if (cfg.bundles) { 1570 eachProp(cfg.bundles, function (value, prop) { 1571 each(value, function (v) { 1572 if (v !== prop) { 1573 bundlesMap[v] = prop; 1574 } 1575 }); 1576 }); 1577 } 1578 1579 //Merge shim 1580 if (cfg.shim) { 1581 eachProp(cfg.shim, function (value, id) { 1582 //Normalize the structure 1583 if (isArray(value)) { 1584 value = { 1585 deps: value 1586 }; 1587 } 1588 if ((value.exports || value.init) && !value.exportsFn) { 1589 value.exportsFn = context.makeShimExports(value); 1590 } 1591 shim[id] = value; 1592 }); 1593 config.shim = shim; 1594 } 1595 1596 //Adjust packages if necessary. 1597 if (cfg.packages) { 1598 each(cfg.packages, function (pkgObj) { 1599 var location, name; 1600 1601 pkgObj = typeof pkgObj === 'string' ? {name: pkgObj} : pkgObj; 1602 1603 name = pkgObj.name; 1604 location = pkgObj.location; 1605 if (location) { 1606 config.paths[name] = pkgObj.location; 1607 } 1608 1609 //Save pointer to main module ID for pkg name. 1610 //Remove leading dot in main, so main paths are normalized, 1611 //and remove any trailing .js, since different package 1612 //envs have different conventions: some use a module name, 1613 //some use a file name. 1614 config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main') 1615 .replace(currDirRegExp, '') 1616 .replace(jsSuffixRegExp, ''); 1617 }); 1618 } 1619 1620 //If there are any "waiting to execute" modules in the registry, 1621 //update the maps for them, since their info, like URLs to load, 1622 //may have changed. 1623 eachProp(registry, function (mod, id) { 1624 //If module already has init called, since it is too 1625 //late to modify them, and ignore unnormalized ones 1626 //since they are transient. 1627 if (!mod.inited && !mod.map.unnormalized) { 1628 mod.map = makeModuleMap(id, null, true); 1629 } 1630 }); 1631 1632 //If a deps array or a config callback is specified, then call 1633 //require with those args. This is useful when require is defined as a 1634 //config object before require.js is loaded. 1635 if (cfg.deps || cfg.callback) { 1636 context.require(cfg.deps || [], cfg.callback); 1637 } 1638 }, 1639 1640 makeShimExports: function (value) { 1641 function fn() { 1642 var ret; 1643 if (value.init) { 1644 ret = value.init.apply(global, arguments); 1645 } 1646 return ret || (value.exports && getGlobal(value.exports)); 1647 } 1648 return fn; 1649 }, 1650 1651 makeRequire: function (relMap, options) { 1652 options = options || {}; 1653 1654 function localRequire(deps, callback, errback) { 1655 var id, map, requireMod; 1656 1657 if (options.enableBuildCallback && callback && isFunction(callback)) { 1658 callback.__requireJsBuild = true; 1659 } 1660 1661 if (typeof deps === 'string') { 1662 if (isFunction(callback)) { 1663 //Invalid call 1664 return onError(makeError('requireargs', 'Invalid require call'), errback); 1665 } 1666 1667 //If require|exports|module are requested, get the 1668 //value for them from the special handlers. Caveat: 1669 //this only works while module is being defined. 1670 if (relMap && hasProp(handlers, deps)) { 1671 return handlers[deps](registry[relMap.id]); 1672 } 1673 1674 //Synchronous access to one module. If require.get is 1675 //available (as in the Node adapter), prefer that. 1676 if (req.get) { 1677 return req.get(context, deps, relMap, localRequire); 1678 } 1679 1680 //Normalize module name, if it contains . or .. 1681 map = makeModuleMap(deps, relMap, false, true); 1682 id = map.id; 1683 1684 if (!hasProp(defined, id)) { 1685 return onError(makeError('notloaded', 'Module name "' + 1686 id + 1687 '" has not been loaded yet for context: ' + 1688 contextName + 1689 (relMap ? '' : '. Use require([])'))); 1690 } 1691 return defined[id]; 1692 } 1693 1694 //Grab defines waiting in the global queue. 1695 intakeDefines(); 1696 1697 //Mark all the dependencies as needing to be loaded. 1698 context.nextTick(function () { 1699 //Some defines could have been added since the 1700 //require call, collect them. 1701 intakeDefines(); 1702 1703 requireMod = getModule(makeModuleMap(null, relMap)); 1704 1705 //Store if map config should be applied to this require 1706 //call for dependencies. 1707 requireMod.skipMap = options.skipMap; 1708 1709 requireMod.init(deps, callback, errback, { 1710 enabled: true 1711 }); 1712 1713 checkLoaded(); 1714 }); 1715 1716 return localRequire; 1717 } 1718 1719 mixin(localRequire, { 1720 isBrowser: isBrowser, 1721 1722 /** 1723 * Converts a module name + .extension into an URL path. 1724 * *Requires* the use of a module name. It does not support using 1725 * plain URLs like nameToUrl. 1726 */ 1727 toUrl: function (moduleNamePlusExt) { 1728 var ext, 1729 index = moduleNamePlusExt.lastIndexOf('.'), 1730 segment = moduleNamePlusExt.split('/')[0], 1731 isRelative = segment === '.' || segment === '..'; 1732 1733 //Have a file extension alias, and it is not the 1734 //dots from a relative path. 1735 if (index !== -1 && (!isRelative || index > 1)) { 1736 ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); 1737 moduleNamePlusExt = moduleNamePlusExt.substring(0, index); 1738 } 1739 1740 return context.nameToUrl(normalize(moduleNamePlusExt, 1741 relMap && relMap.id, true), ext, true); 1742 }, 1743 1744 defined: function (id) { 1745 return hasProp(defined, makeModuleMap(id, relMap, false, true).id); 1746 }, 1747 1748 specified: function (id) { 1749 id = makeModuleMap(id, relMap, false, true).id; 1750 return hasProp(defined, id) || hasProp(registry, id); 1751 } 1752 }); 1753 1754 //Only allow undef on top level require calls 1755 if (!relMap) { 1756 localRequire.undef = function (id) { 1757 //Bind any waiting define() calls to this context, 1758 //fix for #408 1759 takeGlobalQueue(); 1760 1761 var map = makeModuleMap(id, relMap, true), 1762 mod = getOwn(registry, id); 1763 1764 mod.undefed = true; 1765 removeScript(id); 1766 1767 delete defined[id]; 1768 delete urlFetched[map.url]; 1769 delete undefEvents[id]; 1770 1771 //Clean queued defines too. Go backwards 1772 //in array so that the splices do not 1773 //mess up the iteration. 1774 eachReverse(defQueue, function(args, i) { 1775 if (args[0] === id) { 1776 defQueue.splice(i, 1); 1777 } 1778 }); 1779 delete context.defQueueMap[id]; 1780 1781 if (mod) { 1782 //Hold on to listeners in case the 1783 //module will be attempted to be reloaded 1784 //using a different config. 1785 if (mod.events.defined) { 1786 undefEvents[id] = mod.events; 1787 } 1788 1789 cleanRegistry(id); 1790 } 1791 }; 1792 } 1793 1794 return localRequire; 1795 }, 1796 1797 /** 1798 * Called to enable a module if it is still in the registry 1799 * awaiting enablement. A second arg, parent, the parent module, 1800 * is passed in for context, when this method is overridden by 1801 * the optimizer. Not shown here to keep code compact. 1802 */ 1803 enable: function (depMap) { 1804 var mod = getOwn(registry, depMap.id); 1805 if (mod) { 1806 getModule(depMap).enable(); 1807 } 1808 }, 1809 1810 /** 1811 * Internal method used by environment adapters to complete a load event. 1812 * A load event could be a script load or just a load pass from a synchronous 1813 * load call. 1814 * @param {String} moduleName the name of the module to potentially complete. 1815 */ 1816 completeLoad: function (moduleName) { 1817 var found, args, mod, 1818 shim = getOwn(config.shim, moduleName) || {}, 1819 shExports = shim.exports; 1820 1821 takeGlobalQueue(); 1822 1823 while (defQueue.length) { 1824 args = defQueue.shift(); 1825 if (args[0] === null) { 1826 args[0] = moduleName; 1827 //If already found an anonymous module and bound it 1828 //to this name, then this is some other anon module 1829 //waiting for its completeLoad to fire. 1830 if (found) { 1831 break; 1832 } 1833 found = true; 1834 } else if (args[0] === moduleName) { 1835 //Found matching define call for this script! 1836 found = true; 1837 } 1838 1839 callGetModule(args); 1840 } 1841 context.defQueueMap = {}; 1842 1843 //Do this after the cycle of callGetModule in case the result 1844 //of those calls/init calls changes the registry. 1845 mod = getOwn(registry, moduleName); 1846 1847 if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) { 1848 if (config.enforceDefine && (!shExports || !getGlobal(shExports))) { 1849 if (hasPathFallback(moduleName)) { 1850 return; 1851 } else { 1852 return onError(makeError('nodefine', 1853 'No define call for ' + moduleName, 1854 null, 1855 [moduleName])); 1856 } 1857 } else { 1858 //A script that does not call define(), so just simulate 1859 //the call for it. 1860 callGetModule([moduleName, (shim.deps || []), shim.exportsFn]); 1861 } 1862 } 1863 1864 checkLoaded(); 1865 }, 1866 1867 /** 1868 * Converts a module name to a file path. Supports cases where 1869 * moduleName may actually be just an URL. 1870 * Note that it **does not** call normalize on the moduleName, 1871 * it is assumed to have already been normalized. This is an 1872 * internal API, not a public one. Use toUrl for the public API. 1873 */ 1874 nameToUrl: function (moduleName, ext, skipExt) { 1875 var paths, syms, i, parentModule, url, 1876 parentPath, bundleId, 1877 pkgMain = getOwn(config.pkgs, moduleName); 1878 1879 if (pkgMain) { 1880 moduleName = pkgMain; 1881 } 1882 1883 bundleId = getOwn(bundlesMap, moduleName); 1884 1885 if (bundleId) { 1886 return context.nameToUrl(bundleId, ext, skipExt); 1887 } 1888 1889 //If a colon is in the URL, it indicates a protocol is used and it is just 1890 //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?) 1891 //or ends with .js, then assume the user meant to use an url and not a module id. 1892 //The slash is important for protocol-less URLs as well as full paths. 1893 if (req.jsExtRegExp.test(moduleName)) { 1894 //Just a plain path, not module name lookup, so just return it. 1895 //Add extension if it is included. This is a bit wonky, only non-.js things pass 1896 //an extension, this method probably needs to be reworked. 1897 url = moduleName + (ext || ''); 1898 } else { 1899 //A module that needs to be converted to a path. 1900 paths = config.paths; 1901 1902 syms = moduleName.split('/'); 1903 //For each module name segment, see if there is a path 1904 //registered for it. Start with most specific name 1905 //and work up from it. 1906 for (i = syms.length; i > 0; i -= 1) { 1907 parentModule = syms.slice(0, i).join('/'); 1908 1909 parentPath = getOwn(paths, parentModule); 1910 if (parentPath) { 1911 //If an array, it means there are a few choices, 1912 //Choose the one that is desired 1913 if (isArray(parentPath)) { 1914 parentPath = parentPath[0]; 1915 } 1916 syms.splice(0, i, parentPath); 1917 break; 1918 } 1919 } 1920 1921 //Join the path parts together, then figure out if baseUrl is needed. 1922 url = syms.join('/'); 1923 url += (ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? '' : '.js')); 1924 url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; 1925 } 1926 1927 return config.urlArgs && !/^blob\:/.test(url) ? 1928 url + config.urlArgs(moduleName, url) : url; 1929 }, 1930 1931 //Delegates to req.load. Broken out as a separate function to 1932 //allow overriding in the optimizer. 1933 load: function (id, url) { 1934 req.load(context, id, url); 1935 }, 1936 1937 /** 1938 * Executes a module callback function. Broken out as a separate function 1939 * solely to allow the build system to sequence the files in the built 1940 * layer in the right sequence. 1941 * 1942 * @private 1943 */ 1944 execCb: function (name, callback, args, exports) { 1945 return callback.apply(exports, args); 1946 }, 1947 1948 /** 1949 * callback for script loads, used to check status of loading. 1950 * 1951 * @param {Event} evt the event from the browser for the script 1952 * that was loaded. 1953 */ 1954 onScriptLoad: function (evt) { 1955 //Using currentTarget instead of target for Firefox 2.0's sake. Not 1956 //all old browsers will be supported, but this one was easy enough 1957 //to support and still makes sense. 1958 if (evt.type === 'load' || 1959 (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) { 1960 //Reset interactive script so a script node is not held onto for 1961 //to long. 1962 interactiveScript = null; 1963 1964 //Pull out the name of the module and the context. 1965 var data = getScriptData(evt); 1966 context.completeLoad(data.id); 1967 } 1968 }, 1969 1970 /** 1971 * Callback for script errors. 1972 */ 1973 onScriptError: function (evt) { 1974 var data = getScriptData(evt); 1975 if (!hasPathFallback(data.id)) { 1976 var parents = []; 1977 eachProp(registry, function(value, key) { 1978 if (key.indexOf('_@r') !== 0) { 1979 each(value.depMaps, function(depMap) { 1980 if (depMap.id === data.id) { 1981 parents.push(key); 1982 return true; 1983 } 1984 }); 1985 } 1986 }); 1987 return onError(makeError('scripterror', 'Script error for "' + data.id + 1988 (parents.length ? 1989 '", needed by: ' + parents.join(', ') : 1990 '"'), evt, [data.id])); 1991 } 1992 } 1993 }; 1994 1995 context.require = context.makeRequire(); 1996 return context; 1997 } 1998 1999 /** 2000 * Main entry point. 2001 * 2002 * If the only argument to require is a string, then the module that 2003 * is represented by that string is fetched for the appropriate context. 2004 * 2005 * If the first argument is an array, then it will be treated as an array 2006 * of dependency string names to fetch. An optional function callback can 2007 * be specified to execute when all of those dependencies are available. 2008 * 2009 * Make a local req variable to help Caja compliance (it assumes things 2010 * on a require that are not standardized), and to give a short 2011 * name for minification/local scope use. 2012 */ 2013 req = requirejs = function (deps, callback, errback, optional) { 2014 2015 //Find the right context, use default 2016 var context, config, 2017 contextName = defContextName; 2018 2019 // Determine if have config object in the call. 2020 if (!isArray(deps) && typeof deps !== 'string') { 2021 // deps is a config object 2022 config = deps; 2023 if (isArray(callback)) { 2024 // Adjust args if there are dependencies 2025 deps = callback; 2026 callback = errback; 2027 errback = optional; 2028 } else { 2029 deps = []; 2030 } 2031 } 2032 2033 if (config && config.context) { 2034 contextName = config.context; 2035 } 2036 2037 context = getOwn(contexts, contextName); 2038 if (!context) { 2039 context = contexts[contextName] = req.s.newContext(contextName); 2040 } 2041 2042 if (config) { 2043 context.configure(config); 2044 } 2045 2046 return context.require(deps, callback, errback); 2047 }; 2048 2049 /** 2050 * Support require.config() to make it easier to cooperate with other 2051 * AMD loaders on globally agreed names. 2052 */ 2053 req.config = function (config) { 2054 return req(config); 2055 }; 2056 2057 /** 2058 * Execute something after the current tick 2059 * of the event loop. Override for other envs 2060 * that have a better solution than setTimeout. 2061 * @param {Function} fn function to execute later. 2062 */ 2063 req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) { 2064 setTimeout(fn, 4); 2065 } : function (fn) { fn(); }; 2066 2067 /** 2068 * Export require as a global, but only if it does not already exist. 2069 */ 2070 if (!require) { 2071 require = req; 2072 } 2073 2074 req.version = version; 2075 2076 //Used to filter out dependencies that are already paths. 2077 req.jsExtRegExp = /^\/|:|\?|\.js$/; 2078 req.isBrowser = isBrowser; 2079 s = req.s = { 2080 contexts: contexts, 2081 newContext: newContext 2082 }; 2083 2084 //Create default context. 2085 req({}); 2086 2087 //Exports some context-sensitive methods on global require. 2088 each([ 2089 'toUrl', 2090 'undef', 2091 'defined', 2092 'specified' 2093 ], function (prop) { 2094 //Reference from contexts instead of early binding to default context, 2095 //so that during builds, the latest instance of the default context 2096 //with its config gets used. 2097 req[prop] = function () { 2098 var ctx = contexts[defContextName]; 2099 return ctx.require[prop].apply(ctx, arguments); 2100 }; 2101 }); 2102 2103 if (isBrowser) { 2104 head = s.head = document.getElementsByTagName('head')[0]; 2105 //If BASE tag is in play, using appendChild is a problem for IE6. 2106 //When that browser dies, this can be removed. Details in this jQuery bug: 2107 //http://dev.jquery.com/ticket/2709 2108 baseElement = document.getElementsByTagName('base')[0]; 2109 if (baseElement) { 2110 head = s.head = baseElement.parentNode; 2111 } 2112 } 2113 2114 /** 2115 * Any errors that require explicitly generates will be passed to this 2116 * function. Intercept/override it if you want custom error handling. 2117 * @param {Error} err the error object. 2118 */ 2119 req.onError = defaultOnError; 2120 2121 /** 2122 * Creates the node for the load command. Only used in browser envs. 2123 */ 2124 req.createNode = function (config, moduleName, url) { 2125 var node = config.xhtml ? 2126 document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') : 2127 document.createElement('script'); 2128 node.type = config.scriptType || 'text/javascript'; 2129 node.charset = 'utf-8'; 2130 node.async = true; 2131 return node; 2132 }; 2133 2134 /** 2135 * Does the request to load a module for the browser case. 2136 * Make this a separate function to allow other environments 2137 * to override it. 2138 * 2139 * @param {Object} context the require context to find state. 2140 * @param {String} moduleName the name of the module. 2141 * @param {Object} url the URL to the module. 2142 */ 2143 req.load = function (context, moduleName, url) { 2144 var config = (context && context.config) || {}, 2145 node; 2146 if (isBrowser) { 2147 //In the browser so use a script tag 2148 node = req.createNode(config, moduleName, url); 2149 2150 node.setAttribute('data-requirecontext', context.contextName); 2151 node.setAttribute('data-requiremodule', moduleName); 2152 2153 //Set up load listener. Test attachEvent first because IE9 has 2154 //a subtle issue in its addEventListener and script onload firings 2155 //that do not match the behavior of all other browsers with 2156 //addEventListener support, which fire the onload event for a 2157 //script right after the script execution. See: 2158 //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution 2159 //UNFORTUNATELY Opera implements attachEvent but does not follow the script 2160 //script execution mode. 2161 if (node.attachEvent && 2162 //Check if node.attachEvent is artificially added by custom script or 2163 //natively supported by browser 2164 //read https://github.com/requirejs/requirejs/issues/187 2165 //if we can NOT find [native code] then it must NOT natively supported. 2166 //in IE8, node.attachEvent does not have toString() 2167 //Note the test for "[native code" with no closing brace, see: 2168 //https://github.com/requirejs/requirejs/issues/273 2169 !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && 2170 !isOpera) { 2171 //Probably IE. IE (at least 6-8) do not fire 2172 //script onload right after executing the script, so 2173 //we cannot tie the anonymous define call to a name. 2174 //However, IE reports the script as being in 'interactive' 2175 //readyState at the time of the define call. 2176 useInteractive = true; 2177 2178 node.attachEvent('onreadystatechange', context.onScriptLoad); 2179 //It would be great to add an error handler here to catch 2180 //404s in IE9+. However, onreadystatechange will fire before 2181 //the error handler, so that does not help. If addEventListener 2182 //is used, then IE will fire error before load, but we cannot 2183 //use that pathway given the connect.microsoft.com issue 2184 //mentioned above about not doing the 'script execute, 2185 //then fire the script load event listener before execute 2186 //next script' that other browsers do. 2187 //Best hope: IE10 fixes the issues, 2188 //and then destroys all installs of IE 6-9. 2189 //node.attachEvent('onerror', context.onScriptError); 2190 } else { 2191 node.addEventListener('load', context.onScriptLoad, false); 2192 node.addEventListener('error', context.onScriptError, false); 2193 } 2194 node.src = url; 2195 2196 //Calling onNodeCreated after all properties on the node have been 2197 //set, but before it is placed in the DOM. 2198 if (config.onNodeCreated) { 2199 config.onNodeCreated(node, config, moduleName, url); 2200 } 2201 2202 //For some cache cases in IE 6-8, the script executes before the end 2203 //of the appendChild execution, so to tie an anonymous define 2204 //call to the module name (which is stored on the node), hold on 2205 //to a reference to this node, but clear after the DOM insertion. 2206 currentlyAddingScript = node; 2207 if (baseElement) { 2208 head.insertBefore(node, baseElement); 2209 } else { 2210 head.appendChild(node); 2211 } 2212 currentlyAddingScript = null; 2213 2214 return node; 2215 } else if (isWebWorker) { 2216 try { 2217 //In a web worker, use importScripts. This is not a very 2218 //efficient use of importScripts, importScripts will block until 2219 //its script is downloaded and evaluated. However, if web workers 2220 //are in play, the expectation is that a build has been done so 2221 //that only one script needs to be loaded anyway. This may need 2222 //to be reevaluated if other use cases become common. 2223 2224 // Post a task to the event loop to work around a bug in WebKit 2225 // where the worker gets garbage-collected after calling 2226 // importScripts(): https://webkit.org/b/153317 2227 setTimeout(function() {}, 0); 2228 importScripts(url); 2229 2230 //Account for anonymous modules 2231 context.completeLoad(moduleName); 2232 } catch (e) { 2233 context.onError(makeError('importscripts', 2234 'importScripts failed for ' + 2235 moduleName + ' at ' + url, 2236 e, 2237 [moduleName])); 2238 } 2239 } 2240 }; 2241 2242 function getInteractiveScript() { 2243 if (interactiveScript && interactiveScript.readyState === 'interactive') { 2244 return interactiveScript; 2245 } 2246 2247 eachReverse(scripts(), function (script) { 2248 if (script.readyState === 'interactive') { 2249 return (interactiveScript = script); 2250 } 2251 }); 2252 return interactiveScript; 2253 } 2254 2255 //Look for a data-main script attribute, which could also adjust the baseUrl. 2256 if (isBrowser && !cfg.skipDataMain) { 2257 //Figure out baseUrl. Get it from the script tag with require.js in it. 2258 eachReverse(scripts(), function (script) { 2259 //Set the 'head' where we can append children by 2260 //using the script's parent. 2261 if (!head) { 2262 head = script.parentNode; 2263 } 2264 2265 //Look for a data-main attribute to set main script for the page 2266 //to load. If it is there, the path to data main becomes the 2267 //baseUrl, if it is not already set. 2268 dataMain = script.getAttribute('data-main'); 2269 if (dataMain) { 2270 //Preserve dataMain in case it is a path (i.e. contains '?') 2271 mainScript = dataMain; 2272 2273 //Set final baseUrl if there is not already an explicit one, 2274 //but only do so if the data-main value is not a loader plugin 2275 //module ID. 2276 if (!cfg.baseUrl && mainScript.indexOf('!') === -1) { 2277 //Pull off the directory of data-main for use as the 2278 //baseUrl. 2279 src = mainScript.split('/'); 2280 mainScript = src.pop(); 2281 subPath = src.length ? src.join('/') + '/' : './'; 2282 2283 cfg.baseUrl = subPath; 2284 } 2285 2286 //Strip off any trailing .js since mainScript is now 2287 //like a module name. 2288 mainScript = mainScript.replace(jsSuffixRegExp, ''); 2289 2290 //If mainScript is still a path, fall back to dataMain 2291 if (req.jsExtRegExp.test(mainScript)) { 2292 mainScript = dataMain; 2293 } 2294 2295 //Put the data-main script in the files to load. 2296 cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; 2297 2298 return true; 2299 } 2300 }); 2301 } 2302 2303 /** 2304 * The function that handles definitions of modules. Differs from 2305 * require() in that a string for the module should be the first argument, 2306 * and the function to execute after dependencies are loaded should 2307 * return a value to define the module corresponding to the first argument's 2308 * name. 2309 */ 2310 define = function (name, deps, callback) { 2311 var node, context; 2312 2313 //Allow for anonymous modules 2314 if (typeof name !== 'string') { 2315 //Adjust args appropriately 2316 callback = deps; 2317 deps = name; 2318 name = null; 2319 } 2320 2321 //This module may not have dependencies 2322 if (!isArray(deps)) { 2323 callback = deps; 2324 deps = null; 2325 } 2326
2327 //If no name, and callback is a function, then figure out if it a 2328 //CommonJS thing with dependencies. 2329 if (!deps && isFunction(callback)) { 2330 deps = []; 2331 //Remove comments from the callback string, 2332 //look for require calls, and pull them into the dependencies, 2333 //but only if there are function args. 2334 if (callback.length) { 2335 callback 2336 .toString() 2337 .replace(commentRegExp, commentReplace) 2338 .replace(cjsRequireRegExp, function (match, dep) { 2339 deps.push(dep); 2340 }); 2341 2342 //May be a CommonJS thing even without require calls, but still 2343 //could use exports, and module. Avoid doing exports and module 2344 //work though if it just needs require. 2345 //REQUIRES the function to expect the CommonJS variables in the 2346 //order listed below. 2347 deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps); 2348 } 2349 } 2350 2351 //If in IE 6-8 and hit an anonymous define() call, do the interactive 2352 //work. 2353 if (useInteractive) { 2354 node = currentlyAddingScript || getInteractiveScript(); 2355 if (node) { 2356 if (!name) { 2357 name = node.getAttribute('data-requiremodule'); 2358 } 2359 context = contexts[node.getAttribute('data-requirecontext')]; 2360 } 2361 } 2362 2363 //Always save off evaluating the def call until the script onload handler. 2364 //This allows multiple modules to be in a file without prematurely 2365 //tracing dependencies, and allows for anonymous module support, 2366 //where the module name is not known until the script onload event 2367 //occurs. If no context, use the global queue, and get it processed 2368 //in the onscript load callback. 2369 if (context) { 2370 context.defQueue.push([name, deps, callback]); 2371 context.defQueueMap[name] = true; 2372 } else { 2373 globalDefQueue.push([name, deps, callback]); 2374 } 2375 }; 2376 2377 define.amd = { 2378 jQuery: true 2379 }; 2380 2381 /** 2382 * Executes the text. Normally just uses eval, but can be modified 2383 * to use a better, environment-specific call. Only used for transpiling 2384 * loader plugins, not for plain JS modules. 2385 * @param {String} text the text to execute/evaluate. 2386 */ 2387 req.exec = function (text) { 2388 /*jslint evil: true */ 2389 return eval(text); 2390 }; 2391 2392 //Set up with config info. 2393 req(cfg); 2394 }(this, (typeof setTimeout === 'undefined' ? undefined : setTimeout))); 2395 2396 2397 2398 this.requirejsVars = { 2399 require: require, 2400 requirejs: require, 2401 define: define 2402 }; 2403 2404 if (env === 'browser') { 2405 //sloppy since eval enclosed with use strict causes problems if the source 2406//text is not strict-compliant. 2407 /*jslint sloppy: true, evil: true */ 2408 /*global require, XMLHttpRequest */ 2409 2410 (function () { 2411 // Separate function to avoid eval pollution, same with arguments use. 2412 function exec() { 2413 eval(arguments[0]); 2414 } 2415 2416 require.load = function (context, moduleName, url) { 2417 var xhr = new XMLHttpRequest(); 2418 2419 xhr.open('GET', url, true); 2420 xhr.send(); 2421 2422 xhr.onreadystatechange = function () { 2423 if (xhr.readyState === 4) { 2424 exec(xhr.responseText); 2425 2426 //Support anonymous modules. 2427 context.completeLoad(moduleName); 2428 } 2429 }; 2430 }; 2431 }()); 2432 } else if (env === 'rhino') { 2433 /*global require: false, java: false, load: false */ 2434 2435 (function () { 2436 'use strict'; 2437 require.load = function (context, moduleName, url) { 2438 2439 load(url); 2440 2441 //Support anonymous modules. 2442 context.completeLoad(moduleName); 2443 }; 2444 2445 }()); 2446 } else if (env === 'node') { 2447 this.requirejsVars.nodeRequire = nodeRequire; 2448 require.nodeRequire = nodeRequire; 2449 2450 //Explicity not strict since this file contains an eval call, and do not want 2451//to enforce strict on code evaluated that way. See 2452//https://github.com/requirejs/r.js/issues/774 2453 /*jslint regexp: false, sloppy: true*/ 2454 /*global require: false, define: false, requirejsVars: false, process: false */ 2455 2456 /** 2457 * This adapter assumes that x.js has loaded it and set up 2458 * some variables. This adapter just allows limited RequireJS 2459 * usage from within the requirejs directory. The general 2460 * node adapater is r.js. 2461 */ 2462 2463 (function () { 2464 var nodeReq = requirejsVars.nodeRequire, 2465 req = requirejsVars.require, 2466 def = requirejsVars.define, 2467 fs = nodeReq('fs'), 2468 path = nodeReq('path'), 2469 vm = nodeReq('vm'), 2470 //In Node 0.7+ existsSync is on fs. 2471 exists = fs.existsSync || path.existsSync, 2472 hasOwn = Object.prototype.hasOwnProperty; 2473 2474 function hasProp(obj, prop) { 2475 return hasOwn.call(obj, prop); 2476 } 2477 2478 function syncTick(fn) { 2479 fn(); 2480 } 2481 2482 function makeError(message, moduleName) { 2483 var err = new Error(message); 2484 err.requireModules = [moduleName]; 2485 return err; 2486 } 2487 2488 //Supply an implementation that allows synchronous get of a module. 2489 req.get = function (context, moduleName, relModuleMap, localRequire) { 2490 if (moduleName === "require" || moduleName === "exports" || moduleName === "module") { 2491 context.onError(makeError("Explicit require of " + moduleName + " is not allowed.", moduleName)); 2492 } 2493 2494 var ret, oldTick, 2495 moduleMap = context.makeModuleMap(moduleName, relModuleMap, false, true); 2496 2497 //Normalize module name, if it contains . or .. 2498 moduleName = moduleMap.id; 2499 2500 if (hasProp(context.defined, moduleName)) { 2501 ret = context.defined[moduleName]; 2502 } else { 2503 if (ret === undefined) { 2504 //Make sure nextTick for this type of call is sync-based. 2505 oldTick = context.nextTick; 2506 context.nextTick = syncTick; 2507 try { 2508 if (moduleMap.prefix) { 2509 //A plugin, call requirejs to handle it. Now that 2510 //nextTick is syncTick, the require will complete 2511 //synchronously. 2512 localRequire([moduleMap.originalName]); 2513 2514 //Now that plugin is loaded, can regenerate the moduleMap 2515 //to get the final, normalized ID. 2516 moduleMap = context.makeModuleMap(moduleMap.originalName, relModuleMap, false, true); 2517 moduleName = moduleMap.id; 2518 } else { 2519 //Try to dynamically fetch it. 2520 req.load(context, moduleName, moduleMap.url); 2521 2522 //Enable the module 2523 context.enable(moduleMap, relModuleMap); 2524 } 2525 2526 //Break any cycles by requiring it normally, but this will 2527 //finish synchronously 2528 context.require([moduleName]); 2529 2530 //The above calls are sync, so can do the next thing safely. 2531 ret = context.defined[moduleName]; 2532 } finally { 2533 context.nextTick = oldTick; 2534 } 2535 } 2536 } 2537 2538 return ret; 2539 }; 2540 2541 req.nextTick = function (fn) { 2542 process.nextTick(fn); 2543 }; 2544 2545 //Add wrapper around the code so that it gets the requirejs 2546 //API instead of the Node API, and it is done lexically s
2546o 2547 //that it survives later execution. 2548 req.makeNodeWrapper = function (contents) { 2549 return '(function (require, requirejs, define) { ' + 2550 contents + 2551 '\n}(requirejsVars.require, requirejsVars.requirejs, requirejsVars.define));'; 2552 }; 2553 2554 req.load = function (context, moduleName, url) { 2555 var contents, err, 2556 config = context.config; 2557 2558 if (config.shim[moduleName] && (!config.suppress || !config.suppress.nodeShim)) { 2559 console.warn('Shim config not supported in Node, may or may not work. Detected ' + 2560 'for module: ' + moduleName); 2561 } 2562 2563 if (exists(url)) { 2564 contents = fs.readFileSync(url, 'utf8'); 2565 2566 contents = req.makeNodeWrapper(contents); 2567 try { 2568 vm.runInThisContext(contents, fs.realpathSync(url)); 2569 } catch (e) { 2570 err = new Error('Evaluating ' + url + ' as module "' + 2571 moduleName + '" failed with error: ' + e); 2572 err.originalError = e; 2573 err.moduleName = moduleName; 2574 err.requireModules = [moduleName]; 2575 err.fileName = url; 2576 return context.onError(err); 2577 } 2578 } else { 2579 def(moduleName, function () { 2580 //Get the original name, since relative requires may be 2581 //resolved differently in node (issue #202). Also, if relative, 2582 //make it relative to the URL of the item requesting it 2583 //(issue #393) 2584 var dirName, 2585 map = hasProp(context.registry, moduleName) && 2586 context.registry[moduleName].map, 2587 parentMap = map && map.parentMap, 2588 originalName = map && map.originalName; 2589 2590 if (originalName.charAt(0) === '.' && parentMap) { 2591 dirName = parentMap.url.split('/'); 2592 dirName.pop(); 2593 originalName = dirName.join('/') + '/' + originalName; 2594 } 2595 2596 try { 2597 return (context.config.nodeRequire || req.nodeRequire)(originalName); 2598 } catch (e) { 2599 err = new Error('Tried loading "' + moduleName + '" at ' + 2600 url + ' then tried node\'s require("' + 2601 originalName + '") and it failed ' + 2602 'with error: ' + e); 2603 err.originalError = e; 2604 err.moduleName = originalName; 2605 err.requireModules = [moduleName]; 2606 throw err; 2607 } 2608 }); 2609 } 2610 2611 //Support anonymous modules. 2612 context.completeLoad(moduleName); 2613 }; 2614 2615 //Override to provide the function wrapper for define/require. 2616 req.exec = function (text) { 2617 /*jslint evil: true */ 2618 text = req.makeNodeWrapper(text); 2619 return eval(text); 2620 }; 2621 }()); 2622 2623 } else if (env === 'xpconnect') { 2624 /*jslint */ 2625 /*global require, load */ 2626 2627 (function () { 2628 'use strict'; 2629 require.load = function (context, moduleName, url) { 2630 2631 load(url); 2632 2633 //Support anonymous modules. 2634 context.completeLoad(moduleName); 2635 }; 2636 2637 }()); 2638 2639 } 2640 2641 //Support a default file name to execute. Useful for hosted envs 2642 //like Joyent where it defaults to a server.js as the only executed 2643 //script. But only do it if this is not an optimization run. 2644 if (commandOption !== 'o' && (!fileName || !jsSuffixRegExp.test(fileName))) { 2645 fileName = 'main.js'; 2646 } 2647 2648 /** 2649 * Loads the library files that can be used for the optimizer, or for other 2650 * tasks. 2651 */ 2652 function loadLib() { 2653 /*jslint strict: false */ 2654 /*global Packages: false, process: false, window: false, navigator: false, 2655 document: false, define: false */ 2656 2657 /** 2658 * A plugin that modifies any /env/ path to be the right path based on 2659 * the host environment. Right now only works for Node, Rhino and browser. 2660 */ 2661 (function () { 2662 var pathRegExp = /(\/|^)env\/|\{env\}/, 2663 env = 'unknown'; 2664 2665 if (typeof process !== 'undefined' && process.versions && !!process.versions.node) { 2666 env = 'node'; 2667 } else if (typeof Packages !== 'undefined') { 2668 env = 'rhino'; 2669 } else if ((typeof navigator !== 'undefined' && typeof document !== 'undefined') || 2670 (typeof importScripts !== 'undefined' && typeof self !== 'undefined')) { 2671 env = 'browser'; 2672 } else if (typeof Components !== 'undefined' && Components.classes && Components.interfaces) { 2673 env = 'xpconnect'; 2674 } 2675 2676 define('env', { 2677 get: function () { 2678 return env; 2679 }, 2680 2681 load: function (name, req, load, config) { 2682 //Allow override in the config. 2683 if (config.env) { 2684 env = config.env; 2685 } 2686 2687 name = name.replace(pathRegExp, function (match, prefix) { 2688 if (match.indexOf('{') === -1) { 2689 return prefix + env + '/'; 2690 } else { 2691 return env; 2692 } 2693 }); 2694 2695 req([name], function (mod) { 2696 load(mod); 2697 }); 2698 } 2699 }); 2700 }()); 2701 /*jslint plusplus: true */ 2702 /*global define, java */ 2703 2704 define('lang', function () { 2705 'use strict'; 2706 2707 var lang, isJavaObj, 2708 hasOwn = Object.prototype.hasOwnProperty; 2709 2710 function hasProp(obj, prop) { 2711 return hasOwn.call(obj, prop); 2712 } 2713 2714 isJavaObj = function () { 2715 return false;
2716 }; 2717 2718 //Rhino, but not Nashorn (detected by importPackage not existing) 2719 //Can have some strange foreign objects. 2720 if (typeof java !== 'undefined' && java.lang && java.lang.Object && typeof importPackage !== 'undefined') { 2721 isJavaObj = function (obj) { 2722 return obj instanceof java.lang.Object; 2723 }; 2724 } 2725 2726 lang = { 2727 backSlashRegExp: /\\/g, 2728 ostring: Object.prototype.toString, 2729 2730 isArray: Array.isArray || function (it) { 2731 return lang.ostring.call(it) === "[object Array]"; 2732 }, 2733 2734 isFunction: function(it) { 2735 return lang.ostring.call(it) === "[object Function]"; 2736 }, 2737 2738 isRegExp: function(it) { 2739 return it && it instanceof RegExp; 2740 }, 2741 2742 hasProp: hasProp, 2743 2744 //returns true if the object does not have an own property prop, 2745 //or if it does, it is a falsy value. 2746 falseProp: function (obj, prop) { 2747 return !hasProp(obj, prop) || !obj[prop]; 2748 }, 2749 2750 //gets own property value for given prop on object 2751 getOwn: function (obj, prop) { 2752 return hasProp(obj, prop) && obj[prop]; 2753 }, 2754 2755 _mixin: function(dest, source, override){ 2756 var name; 2757 for (name in source) { 2758 if(source.hasOwnProperty(name) && 2759 (override || !dest.hasOwnProperty(name))) { 2760 dest[name] = source[name]; 2761 } 2762 } 2763 2764 return dest; // Object 2765 }, 2766 2767 /** 2768 * mixin({}, obj1, obj2) is allowed. If the last argument is a boolean, 2769 * then the source objects properties are force copied over to dest. 2770 */ 2771 mixin: function(dest){ 2772 var parameters = Array.prototype.slice.call(arguments), 2773 override, i, l; 2774 2775 if (!dest) { dest = {}; } 2776 2777 if (parameters.length > 2 && typeof arguments[parameters.length-1] === 'boolean') { 2778 override = parameters.pop(); 2779 } 2780 2781 for (i = 1, l = parameters.length; i < l; i++) { 2782 lang._mixin(dest, parameters[i], override); 2783 } 2784 return dest; // Object 2785 }, 2786 2787 /** 2788 * Does a deep mix of source into dest, where source values override 2789 * dest values if a winner is needed. 2790 * @param {Object} dest destination object that receives the mixed 2791 * values. 2792 * @param {Object} source source object contributing properties to mix 2793 * in. 2794 * @return {[Object]} returns dest object with the modification. 2795 */ 2796 deepMix: function(dest, source) { 2797 lang.eachProp(source, function (value, prop) { 2798 if (typeof value === 'object' && value && 2799 !lang.isArray(value) && !lang.isFunction(value) && 2800 !(value instanceof RegExp)) { 2801 2802 if (!dest[prop]) { 2803 dest[prop] = {}; 2804 } 2805 lang.deepMix(dest[prop], value); 2806 } else { 2807 dest[prop] = value; 2808 } 2809 }); 2810 return dest; 2811 }, 2812 2813 /** 2814 * Does a type of deep copy. Do not give it anything fancy, best 2815 * for basic object copies of objects that also work well as 2816 * JSON-serialized things, or has properties pointing to functions. 2817 * For non-array/object values, just returns the same object. 2818 * @param {Object} obj copy properties from this object 2819 * @param {Object} [ignoredProps] optional object whose own properties 2820 * are keys that should be ignored. 2821 * @return {Object} 2822 */ 2823 deeplikeCopy: function (obj, ignoredProps) { 2824 var type, result; 2825 2826 if (lang.isArray(obj)) { 2827 result = [];
2828 obj.forEach(function(value) { 2829 result.push(lang.deeplikeCopy(value, ignoredProps)); 2830 }); 2831 return result; 2832 } 2833 2834 type = typeof obj; 2835 if (obj === null || obj === undefined || type === 'boolean' || 2836 type === 'string' || type === 'number' || lang.isFunction(obj) || 2837 lang.isRegExp(obj)|| isJavaObj(obj)) { 2838 return obj; 2839 } 2840 2841 //Anything else is an object, hopefully. 2842 result = {}; 2843 lang.eachProp(obj, function(value, key) { 2844 if (!ignoredProps || !hasProp(ignoredProps, key)) { 2845 result[key] = lang.deeplikeCopy(value, ignoredProps); 2846 } 2847 }); 2848 return result; 2849 }, 2850 2851 delegate: (function () { 2852 // boodman/crockford delegation w/ cornford optimization 2853 function TMP() {} 2854 return function (obj, props) { 2855 TMP.prototype = obj; 2856 var tmp = new TMP(); 2857 TMP.prototype = null; 2858 if (props) { 2859 lang.mixin(tmp, props); 2860 } 2861 return tmp; // Object 2862 }; 2863 }()), 2864 2865 /** 2866 * Helper function for iterating over an array. If the func returns 2867 * a true value, it will break out of the loop. 2868 */ 2869 each: function each(ary, func) { 2870 if (ary) { 2871 var i; 2872 for (i = 0; i < ary.length; i += 1) { 2873 if (func(ary[i], i, ary)) { 2874 break; 2875 } 2876 } 2877 } 2878 }, 2879 2880 /** 2881 * Cycles over properties in an object and calls a function for each 2882 * property value. If the function returns a truthy value, then the 2883 * iteration is stopped. 2884 */ 2885 eachProp: function eachProp(obj, func) { 2886 var prop; 2887 for (prop in obj) { 2888 if (hasProp(obj, prop)) { 2889 if (func(obj[prop], prop)) { 2890 break; 2891 } 2892 } 2893 } 2894 }, 2895 2896 //Similar to Function.prototype.bind, but the "this" object is specified 2897 //first, since it is easier to read/figure out what "this" will be. 2898 bind: function bind(obj, fn) { 2899 return function () { 2900 return fn.apply(obj, arguments); 2901 }; 2902 }, 2903 2904 //Escapes a content string to be be a string that has characters escaped 2905 //for inclusion as part of a JS string. 2906 jsEscape: function (content) { 2907 return content.replace(/(["'\\])/g, '\\$1') 2908 .replace(/[\f]/g, "\\f") 2909 .replace(/[\b]/g, "\\b") 2910 .replace(/[\n]/g, "\\n") 2911 .replace(/[\t]/g, "\\t") 2912 .replace(/[\r]/g, "\\r"); 2913 } 2914 }; 2915 return lang; 2916 }); 2917 /** 2918 * prim 0.0.1 Copyright (c) 2012-2014, The Dojo Foundation All Rights Reserved. 2919 * Available via the MIT or new BSD license. 2920 * see: http://github.com/requirejs/prim for details 2921 */ 2922 2923 /*global setImmediate, process, setTimeout, define, module */ 2924 2925//Set prime.hideResolutionConflict = true to allow "resolution-races" 2926//in promise-tests to pass. 2927//Since the goal of prim is to be a small impl for trusted code, it is 2928//more important to normally throw in this case so that we can find 2929//logic errors quicker. 2930 2931 var prim; 2932 (function () { 2933 'use strict'; 2934 var op = Object.prototype, 2935 hasOwn = op.hasOwnProperty; 2936 2937 function hasProp(obj, prop) { 2938 return hasOwn.call(obj, prop); 2939 } 2940 2941 /** 2942 * Helper function for iterating over an array. If the func returns 2943 * a true value, it will break out of the loop. 2944 */ 2945 function each(ary, func) { 2946 if (ary) { 2947 var i; 2948 for (i = 0; i < ary.length; i += 1) { 2949 if (ary[i]) { 2950 func(ary[i], i, ary); 2951 } 2952 } 2953 } 2954 } 2955 2956 function check(p) { 2957 if (hasProp(p, 'e') || hasProp(p, 'v')) { 2958 if (!prim.hideResolutionConflict) { 2959 throw new Error('Prim promise already resolved: ' + 2960 JSON.stringify(p)); 2961 } 2962 return false;
2963 } 2964 return true; 2965 } 2966 2967 function notify(ary, value) { 2968 prim.nextTick(function () { 2969 each(ary, function (item) { 2970 item(value); 2971 }); 2972 }); 2973 } 2974 2975 prim = function prim() { 2976 var p, 2977 ok = [], 2978 fail = []; 2979 2980 return (p = { 2981 callback: function (yes, no) { 2982 if (no) { 2983 p.errback(no); 2984 } 2985 2986 if (hasProp(p, 'v')) { 2987 prim.nextTick(function () { 2988 yes(p.v); 2989 }); 2990 } else { 2991 ok.push(yes); 2992 } 2993 }, 2994 2995 errback: function (no) { 2996 if (hasProp(p, 'e')) { 2997 prim.nextTick(function () { 2998 no(p.e); 2999 }); 3000 } else { 3001 fail.push(no); 3002 } 3003 }, 3004 3005 finished: function () { 3006 return hasProp(p, 'e') || hasProp(p, 'v'); 3007 }, 3008 3009 rejected: function () { 3010 return hasProp(p, 'e'); 3011 }, 3012 3013 resolve: function (v) { 3014 if (check(p)) { 3015 p.v = v; 3016 notify(ok, v); 3017 } 3018 return p; 3019 }, 3020 reject: function (e) { 3021 if (check(p)) { 3022 p.e = e; 3023 notify(fail, e); 3024 } 3025 return p; 3026 }, 3027 3028 start: function (fn) { 3029 p.resolve(); 3030 return p.promise.then(fn); 3031 }, 3032 3033 promise: { 3034 then: function (yes, no) { 3035 var next = prim(); 3036 3037 p.callback(function (v) { 3038 try { 3039 if (yes && typeof yes === 'function') { 3040 v = yes(v); 3041 } 3042 3043 if (v && v.then) { 3044 v.then(next.resolve, next.reject); 3045 } else { 3046 next.resolve(v); 3047 } 3048 } catch (e) { 3049 next.reject(e); 3050 } 3051 }, function (e) { 3052 var err; 3053 3054 try { 3055 if (!no || typeof no !== 'function') { 3056 next.reject(e); 3057 } else { 3058 err = no(e); 3059 3060 if (err && err.then) { 3061 err.then(next.resolve, next.reject); 3062 } else { 3063 next.resolve(err); 3064 } 3065 } 3066 } catch (e2) { 3067 next.reject(e2); 3068 } 3069 }); 3070 3071 return next.promise; 3072 }, 3073 3074 fail: function (no) { 3075 return p.promise.then(null, no); 3076 }, 3077 3078 end: function () { 3079 p.errback(function (e) { 3080 throw e; 3081 }); 3082 } 3083 } 3084 }); 3085 }; 3086 3087 prim.serial = function (ary) { 3088 var result = prim().resolve().promise; 3089 each(ary, function (item) { 3090 result = result.then(function () { 3091 return item(); 3092 }); 3093 }); 3094 return result; 3095 }; 3096 3097 prim.nextTick = typeof setImmediate === 'function' ? setImmediate : 3098 (typeof process !== 'undefined' && process.nextTick ? 3099 process.nextTick : (typeof setTimeout !== 'undefined' ? 3100 function (fn) { 3101 setTimeout(fn, 0); 3102 } : function (fn) { 3103 fn(); 3104 })); 3105 3106 if (typeof define === 'function' && define.amd) { 3107 define('prim', function () { return prim; }); 3108 } else if (typeof module !== 'undefined' && module.exports) { 3109 module.exports = prim; 3110 } 3111 }()); 3112 if(env === 'browser') { 3113 /*jslint strict: false */ 3114 /*global define: false, load: false */ 3115 3116//Just a stub for use with uglify's consolidator.js 3117 define('browser/assert', function () { 3118 return {}; 3119 }); 3120 3121 } 3122 3123 if(env === 'node') { 3124 /*jslint strict: false */ 3125 /*global define: false, load: false */ 3126 3127//Needed so that rhino/assert can return a stub for uglify's consolidator.js 3128 define('node/assert', ['assert'], function (assert) { 3129 return assert; 3130 }); 3131 3132 } 3133 3134 if(env === 'rhino') { 3135 /*jslint strict: false */ 3136 /*global define: false, load: false */ 3137 3138//Just a stub for use with uglify's consolidator.js 3139 define('rhino/assert', function () { 3140 return {}; 3141 }); 3142 3143 } 3144 3145 if(env === 'xpconnect') { 3146 /*jslint strict: false */ 3147 /*global define: false, load: false */ 3148 3149//Just a stub for use with uglify's consolidator.js 3150 define('xpconnect/assert', function () { 3151 return {}; 3152 }); 3153 3154 } 3155 3156 if(env === 'browser') { 3157 /*jslint strict: false */ 3158 /*global define: false, process: false */ 3159 3160 define('browser/args', function () { 3161 //Always expect config via an API call 3162 return []; 3163 }); 3164 3165 } 3166 3167 if(env === 'node') { 3168 /*jslint strict: false */ 3169 /*global define: false, process: false */ 3170 3171 define('node/args', function () { 3172 //Do not return the "node" or "r.js" arguments 3173 var args = process.argv.slice(2); 3174 3175 //Ignore any command option used for main x.js branching 3176 if (args[0] && args[0].indexOf('-') === 0) { 3177 args = args.slice(1); 3178 } 3179 3180 return args; 3181 }); 3182 3183 } 3184 3185 if(env === 'rhino') { 3186 /*jslint strict: false */ 3187 /*global define: false, process: false */ 3188 3189 var jsLibRhinoArgs = (typeof rhinoArgs !== 'undefined' && rhinoArgs) || [].concat(Array.prototype.slice.call(arguments, 0)); 3190 3191 define('rhino/args', function () { 3192 var args = jsLibRhinoArgs; 3193 3194 //Ignore any command option used for main x.js branching 3195 if (args[0] && args[0].indexOf('-') === 0) { 3196 args = args.slice(1); 3197 } 3198 3199 return args; 3200 }); 3201 3202 } 3203 3204 if(env === 'xpconnect') { 3205 /*jslint strict: false */ 3206 /*global define, xpconnectArgs */ 3207 3208 var jsLibXpConnectArgs = (typeof xpconnectArgs !== 'undefined' && xpconnectArgs) || [].concat(Array.prototype.slice.call(arguments, 0)); 3209 3210 define('xpconnect/args', function () { 3211 var args = jsLibXpConnectArgs; 3212 3213 //Ignore any command option used for main x.js branching 3214 if (args[0] && args[0].indexOf('-') === 0) { 3215 args = args.slice(1); 3216 } 3217 3218 return args; 3219 }); 3220 3221 } 3222 3223 if(env === 'browser') { 3224 /*jslint strict: false */ 3225 /*global define: false, console: false */ 3226 3227 define('browser/load', ['./file'], function (file) { 3228 function load(fileName) { 3229 eval(file.readFile(fileName)); 3230 } 3231 3232 return load; 3233 }); 3234 3235 } 3236 3237 if(env === 'node') { 3238 /*jslint strict: false */ 3239 /*global define: false, console: false */ 3240 3241 define('node/load', ['fs'], function (fs) { 3242 function load(fileName) { 3243 var contents = fs.readFileSync(fileName, 'utf8'); 3244 process.compile(contents, fileName); 3245 } 3246 3247 return load; 3248 }); 3249 3250 } 3251 3252 if(env === 'rhino') { 3253 /*jslint strict: false */ 3254 /*global define: false, load: false */ 3255 3256 define('rhino/load', function () { 3257 return load; 3258 }); 3259 3260 } 3261 3262 if(env === 'xpconnect') { 3263 /*jslint strict: false */ 3264 /*global define: false, load: false */ 3265 3266 define('xpconnect/load', function () { 3267 return load; 3268 }); 3269 3270 } 3271 3272 if(env === 'browser') { 3273 /*jslint sloppy: true, nomen: true */
3274 /*global require, define, console, XMLHttpRequest, requirejs, location */ 3275 3276 define('browser/file', ['prim'], function (prim) { 3277 3278 var file, 3279 currDirRegExp = /^\.(\/|$)/; 3280 3281 function frontSlash(path) { 3282 return path.replace(/\\/g, '/'); 3283 } 3284 3285 function exists(path) { 3286 var status, xhr = new XMLHttpRequest(); 3287 3288 //Oh yeah, that is right SYNC IO. Behold its glory 3289 //and horrible blocking behavior. 3290 xhr.open('HEAD', path, false); 3291 xhr.send(); 3292 status = xhr.status; 3293 3294 return status === 200 || status === 304; 3295 } 3296 3297 function mkDir(dir) { 3298 console.log('mkDir is no-op in browser'); 3299 } 3300 3301 function mkFullDir(dir) { 3302 console.log('mkFullDir is no-op in browser'); 3303 } 3304 3305 file = { 3306 backSlashRegExp: /\\/g, 3307 exclusionRegExp: /^\./, 3308 getLineSeparator: function () { 3309 return '/'; 3310 }, 3311 3312 exists: function (fileName) { 3313 return exists(fileName); 3314 }, 3315 3316 parent: function (fileName) { 3317 var parts = fileName.split('/'); 3318 parts.pop(); 3319 return parts.join('/'); 3320 }, 3321 3322 /** 3323 * Gets the absolute file path as a string, normalized 3324 * to using front slashes for path separators. 3325 * @param {String} fileName 3326 */ 3327 absPath: function (fileName) { 3328 var dir; 3329 if (currDirRegExp.test(fileName)) { 3330 dir = frontSlash(location.href); 3331 if (dir.indexOf('/') !== -1) { 3332 dir = dir.split('/'); 3333 3334 //Pull off protocol and host, just want 3335 //to allow paths (other build parts, like 3336 //require._isSupportedBuildUrl do not support 3337 //full URLs), but a full path from 3338 //the root. 3339 dir.splice(0, 3); 3340 3341 dir.pop(); 3342 dir = '/' + dir.join('/'); 3343 } 3344 3345 fileName = dir + fileName.substring(1); 3346 } 3347 3348 return fileName; 3349 }, 3350 3351 normalize: function (fileName) { 3352 return fileName; 3353 }, 3354 3355 isFile: function (path) { 3356 return true; 3357 }, 3358 3359 isDirectory: function (path) { 3360 return false; 3361 }, 3362 3363 getFilteredFileList: function (startDir, regExpFilters, makeUnixPaths) { 3364 console.log('file.getFilteredFileList is no-op in browser'); 3365 }, 3366 3367 copyDir: function (srcDir, destDir, regExpFilter, onlyCopyNew) { 3368 console.log('file.copyDir is no-op in browser'); 3369 3370 }, 3371 3372 copyFile: function (srcFileName, destFileName, onlyCopyNew) { 3373 console.log('file.copyFile is no-op in browser'); 3374 }, 3375 3376 /** 3377 * Renames a file. May fail if "to" already exists or is on another drive. 3378 */ 3379 renameFile: function (from, to) { 3380 console.log('file.renameFile is no-op in browser'); 3381 }, 3382 3383 /** 3384 * Reads a *text* file. 3385 */ 3386 readFile: function (path, encoding) { 3387 var xhr = new XMLHttpRequest(); 3388 3389 //Oh yeah, that is right SYNC IO. Behold its glory 3390 //and horrible blocking behavior. 3391 xhr.open('GET', path, false); 3392 xhr.send(); 3393 3394 return xhr.responseText; 3395 }, 3396 3397 readFileAsync: function (path, encoding) { 3398 var xhr = new XMLHttpRequest(), 3399 d = prim(); 3400 3401 xhr.open('GET', path, true); 3402 xhr.send(); 3403 3404 xhr.onreadystatechange = function () { 3405 if (xhr.readyState === 4) { 3406 if (xhr.status > 400) { 3407 d.reject(new Error('Status: ' + xhr.status + ': ' + xhr.statusText)); 3408 } else { 3409 d.resolve(xhr.responseText); 3410 } 3411 } 3412 }; 3413 3414 return d.promise; 3415 }, 3416 3417 saveUtf8File: function (fileName, fileContents) { 3418 //summary: saves a *text* file using UTF-8 encoding. 3419 file.saveFile(fileName, fileContents, "utf8"); 3420 }, 3421 3422 saveFile: function (fileName, fileContents, encoding) { 3423 requirejs.browser.saveFile(fileName, fileContents, encoding); 3424 }, 3425 3426 deleteFile: function (fileName) { 3427 console.log('file.deleteFile is no-op in browser'); 3428 }, 3429 3430 /** 3431 * Deletes any empty directories under the given directory. 3432 */ 3433 deleteEmptyDirs: function (startDir) { 3434 console.log('file.deleteEmptyDirs is no-op in browser'); 3435 } 3436 }; 3437 3438 return file; 3439 3440 }); 3441 3442 } 3443 3444 if(env === 'node') { 3445 /*jslint plusplus: false, octal:false, strict: false */ 3446 /*global define: false, process: false */ 3447 3448 define('node/file', ['fs', 'path', 'prim'], function (fs, path, prim) { 3449 3450 var isWindows = process.platform === 'win32', 3451 windowsDriveRegExp = /^[a-zA-Z]\:\/$/, 3452 file; 3453 3454 function frontSlash(path) { 3455 return path.replace(/\\/g, '/'); 3456 } 3457 3458 function exists(path) {
3459 if (isWindows && path.charAt(path.length - 1) === '/' && 3460 path.charAt(path.length - 2) !== ':') { 3461 path = path.substring(0, path.length - 1); 3462 } 3463 3464 try { 3465 fs.statSync(path); 3466 return true; 3467 } catch (e) { 3468 return false; 3469 } 3470 } 3471 3472 function mkDir(dir) { 3473 if (!exists(dir) && (!isWindows || !windowsDriveRegExp.test(dir))) { 3474 fs.mkdirSync(dir, 511); 3475 } 3476 } 3477 3478 function mkFullDir(dir) { 3479 var parts = dir.split('/'), 3480 currDir = '', 3481 first = true; 3482 3483 parts.forEach(function (part) { 3484 //First part may be empty string if path starts with a slash. 3485 currDir += part + '/'; 3486 first = false; 3487 3488 if (part) { 3489 mkDir(currDir); 3490 } 3491 }); 3492 } 3493 3494 file = { 3495 backSlashRegExp: /\\/g, 3496 exclusionRegExp: /^\./, 3497 getLineSeparator: function () { 3498 return '/'; 3499 }, 3500 3501 exists: function (fileName) { 3502 return exists(fileName); 3503 }, 3504 3505 parent: function (fileName) { 3506 var parts = fileName.split('/'); 3507 parts.pop(); 3508 return parts.join('/'); 3509 }, 3510 3511 /** 3512 * Gets the absolute file path as a string, normalized 3513 * to using front slashes for path separators. 3514 * @param {String} fileName 3515 */ 3516 absPath: function (fileName) { 3517 return frontSlash(path.normalize(frontSlash(fs.realpathSync(fileName)))); 3518 }, 3519 3520 normalize: function (fileName) { 3521 return frontSlash(path.normalize(fileName)); 3522 }, 3523 3524 isFile: function (path) { 3525 return fs.statSync(path).isFile(); 3526 }, 3527 3528 isDirectory: function (path) { 3529 return fs.statSync(path).isDirectory(); 3530 }, 3531 3532 getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths) { 3533 //summary: Recurses startDir and finds matches to the files that match regExpFilters.include 3534 //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters, 3535 //and it will be treated as the "include" case. 3536 //Ignores files/directories that start with a period (.) unless exclusionRegExp 3537 //is set to another value. 3538 var files = [], topDir, regExpInclude, regExpExclude, dirFileArray, 3539 i, stat, filePath, ok, dirFiles, fileName; 3540 3541 topDir = startDir; 3542 3543 regExpInclude = regExpFilters.include || regExpFilters; 3544 regExpExclude = regExpFilters.exclude || null; 3545 3546 if (file.exists(topDir)) { 3547 dirFileArray = fs.readdirSync(topDir); 3548 for (i = 0; i < dirFileArray.length; i++) { 3549 fileName = dirFileArray[i]; 3550 filePath = path.join(topDir, fileName); 3551 stat = fs.statSync(filePath); 3552 if (stat.isFile()) { 3553 if (makeUnixPaths) { 3554 //Make sure we have a JS string. 3555 if (filePath.indexOf("/") === -1) { 3556 filePath = frontSlash(filePath); 3557 } 3558 } 3559 3560 ok = true; 3561 if (regExpInclude) { 3562 ok = filePath.match(regExpInclude); 3563 } 3564 if (ok && regExpExclude) { 3565 ok = !filePath.match(regExpExclude); 3566 } 3567 3568 if (ok && (!file.exclusionRegExp || 3569 !file.exclusionRegExp.test(fileName))) { 3570 files.push(filePath); 3571 } 3572 } else if (stat.isDirectory() && 3573 (!file.exclusionRegExp || !file.exclusionRegExp.test(fileName))) { 3574 dirFiles = this.getFilteredFileList(filePath, regExpFilters, makeUnixPaths); 3575 //Do not use push.apply for dir listings, can hit limit of max number 3576 //of arguments to a function call, #921.
3577 dirFiles.forEach(function (dirFile) { 3578 files.push(dirFile); 3579 }); 3580 } 3581 } 3582 } 3583 3584 return files; //Array 3585 }, 3586 3587 copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) { 3588 //summary: copies files from srcDir to destDir using the regExpFilter to determine if the 3589 //file should be copied. Returns a list file name strings of the destinations that were copied. 3590 regExpFilter = regExpFilter || /\w/; 3591 3592 //Normalize th directory names, but keep front slashes. 3593 //path module on windows now returns backslashed paths. 3594 srcDir = frontSlash(path.normalize(srcDir)); 3595 destDir = frontSlash(path.normalize(destDir)); 3596 3597 var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true), 3598 copiedFiles = [], i, srcFileName, destFileName; 3599 3600 for (i = 0; i < fileNames.length; i++) { 3601 srcFileName = fileNames[i]; 3602 destFileName = srcFileName.replace(srcDir, destDir); 3603 3604 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) { 3605 copiedFiles.push(destFileName); 3606 } 3607 } 3608 3609 return copiedFiles.length ? copiedFiles : null; //Array or null 3610 }, 3611 3612 copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) { 3613 //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if 3614 //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred. 3615 var parentDir; 3616 3617 //logger.trace("Src filename: " + srcFileName); 3618 //logger.trace("Dest filename: " + destFileName); 3619 3620 //If onlyCopyNew is true, then compare dates and only copy if the src is newer 3621 //than dest. 3622 if (onlyCopyNew) { 3623 if (file.exists(destFileName) && fs.statSync(destFileName).mtime.getTime() >= fs.statSync(srcFileName).mtime.getTime()) { 3624 return false; //Boolean 3625 } 3626 } 3627 3628 //Make sure destination dir exists. 3629 parentDir = path.dirname(destFileName); 3630 if (!file.exists(parentDir)) { 3631 mkFullDir(parentDir); 3632 } 3633 3634 fs.writeFileSync(destFileName, fs.readFileSync(srcFileName, 'binary'), 'binary'); 3635 3636 return true; //Boolean 3637 }, 3638 3639 /** 3640 * Renames a file. May fail if "to" already exists or is on another drive. 3641 */ 3642 renameFile: function (from, to) { 3643 return fs.renameSync(from, to); 3644 }, 3645 3646 /** 3647 * Reads a *text* file. 3648 */ 3649 readFile: function (/*String*/path, /*String?*/encoding) { 3650 if (encoding === 'utf-8') { 3651 encoding = 'utf8'; 3652 } 3653 if (!encoding) { 3654 encoding = 'utf8'; 3655 } 3656 3657 var text = fs.readFileSync(path, encoding); 3658 3659 //Hmm, would not expect to get A BOM, but it seems to happen, 3660 //remove it just in case. 3661 if (text.indexOf('\uFEFF') === 0) { 3662 text = text.substring(1, text.length); 3663 } 3664 3665 return text; 3666 }, 3667 3668 readFileAsync: function (path, encoding) { 3669 var d = prim(); 3670 try { 3671 d.resolve(file.readFile(path, encoding)); 3672 } catch (e) { 3673 d.reject(e); 3674 } 3675 return d.promise; 3676 }, 3677 3678 saveUtf8File: function (/*String*/fileName, /*String*/fileContents) { 3679 //summary: saves a *text* file using UTF-8 encoding. 3680 file.saveFile(fileName, fileContents, "utf8"); 3681 }, 3682 3683 saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) { 3684 //summary: saves a *text* file. 3685 var parentDir; 3686 3687 if (encoding === 'utf-8') { 3688 encoding = 'utf8'; 3689 } 3690 if (!encoding) { 3691 encoding = 'utf8'; 3692 } 3693 3694 //Make sure destination directories exist. 3695 parentDir = path.dirname(fileName); 3696 if (!file.exists(parentDir)) { 3697 mkFullDir(parentDir); 3698 } 3699 3700 fs.writeFileSync(fileName, fileContents, encoding); 3701 }, 3702 3703 deleteFile: function (/*String*/fileName) { 3704 //summary: deletes a file or directory if it exists. 3705 var files, i, stat; 3706 if (file.exists(fileName)) { 3707 stat = fs.lstatSync(fileName); 3708 if (stat.isDirectory()) { 3709 files = fs.readdirSync(fileName); 3710 for (i = 0; i < files.length; i++) { 3711 this.deleteFile(path.join(fileName, files[i])); 3712 } 3713 fs.rmdirSync(fileName); 3714 } else { 3715 fs.unlinkSync(fileName); 3716 } 3717 } 3718 }, 3719 3720 3721 /** 3722 * Deletes any empty directories under the given directory. 3723 */ 3724 deleteEmptyDirs: function (startDir) { 3725 var dirFileArray, i, fileName, filePath, stat; 3726 3727 if (file.exists(startDir)) { 3728 dirFileArray = fs.readdirSync(startDir); 3729 for (i = 0; i < dirFileArray.length; i++) { 3730 fileName = dirFileArray[i]; 3731 filePath = path.join(startDir, fileName); 3732 stat = fs.lstatSync(filePath); 3733 if (stat.isDirectory()) { 3734 file.deleteEmptyDirs(filePath); 3735 } 3736 } 3737 3738 //If directory is now empty, remove it. 3739 if (fs.readdirSync(startDir).length === 0) { 3740 file.deleteFile(startDir); 3741 } 3742 } 3743 } 3744 }; 3745 3746 return file; 3747 3748 }); 3749 3750 } 3751 3752 if(env === 'rhino') { 3753//Helper functions to deal with file I/O. 3754 3755 /*jslint plusplus: false */ 3756 /*global java: false, define: false */ 3757 3758 define('rhino/file', ['prim'], function (prim) { 3759 var file = {
3760 backSlashRegExp: /\\/g, 3761 3762 exclusionRegExp: /^\./, 3763 3764 getLineSeparator: function () { 3765 return file.lineSeparator; 3766 }, 3767 3768 lineSeparator: java.lang.System.getProperty("line.separator"), //Java String 3769 3770 exists: function (fileName) { 3771 return (new java.io.File(fileName)).exists(); 3772 }, 3773 3774 parent: function (fileName) { 3775 return file.absPath((new java.io.File(fileName)).getParentFile()); 3776 }, 3777 3778 normalize: function (fileName) { 3779 return file.absPath(fileName); 3780 }, 3781 3782 isFile: function (path) { 3783 return (new java.io.File(path)).isFile(); 3784 }, 3785 3786 isDirectory: function (path) { 3787 return (new java.io.File(path)).isDirectory(); 3788 }, 3789 3790 /** 3791 * Gets the absolute file path as a string, normalized 3792 * to using front slashes for path separators. 3793 * @param {java.io.File||String} file 3794 */ 3795 absPath: function (fileObj) { 3796 if (typeof fileObj === "string") { 3797 fileObj = new java.io.File(fileObj); 3798 } 3799 return (fileObj.getCanonicalPath() + "").replace(file.backSlashRegExp, "/"); 3800 }, 3801 3802 getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) { 3803 //summary: Recurses startDir and finds matches to the files that match regExpFilters.include 3804 //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters, 3805 //and it will be treated as the "include" case. 3806 //Ignores files/directories that start with a period (.) unless exclusionRegExp 3807 //is set to another value. 3808 var files = [], topDir, regExpInclude, regExpExclude, dirFileArray, 3809 i, fileObj, filePath, ok, dirFiles; 3810 3811 topDir = startDir; 3812 if (!startDirIsJavaObject) { 3813 topDir = new java.io.File(startDir); 3814 } 3815 3816 regExpInclude = regExpFilters.include || regExpFilters; 3817 regExpExclude = regExpFilters.exclude || null; 3818 3819 if (topDir.exists()) { 3820 dirFileArray = topDir.listFiles(); 3821 for (i = 0; i < dirFileArray.length; i++) { 3822 fileObj = dirFileArray[i]; 3823 if (fileObj.isFile()) { 3824 filePath = fileObj.getPath(); 3825 if (makeUnixPaths) { 3826 //Make sure we have a JS string. 3827 filePath = String(filePath); 3828 if (filePath.indexOf("/") === -1) { 3829 filePath = filePath.replace(/\\/g, "/"); 3830 } 3831 } 3832 3833 ok = true; 3834 if (regExpInclude) { 3835 ok = filePath.match(regExpInclude); 3836 } 3837 if (ok && regExpExclude) { 3838 ok = !filePath.match(regExpExclude); 3839 } 3840 3841 if (ok && (!file.exclusionRegExp || 3842 !file.exclusionRegExp.test(fileObj.getName()))) { 3843 files.push(filePath); 3844 } 3845 } else if (fileObj.isDirectory() && 3846 (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.getName()))) { 3847 dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true); 3848 //Do not use push.apply for dir listings, can hit limit of max number 3849 //of arguments to a function call, #921.
3850 dirFiles.forEach(function (dirFile) { 3851 files.push(dirFile); 3852 }); 3853 } 3854 } 3855 } 3856 3857 return files; //Array 3858 }, 3859 3860 copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) { 3861 //summary: copies files from srcDir to destDir using the regExpFilter to determine if the 3862 //file should be copied. Returns a list file name strings of the destinations that were copied. 3863 regExpFilter = regExpFilter || /\w/; 3864 3865 var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true), 3866 copiedFiles = [], i, srcFileName, destFileName; 3867 3868 for (i = 0; i < fileNames.length; i++) { 3869 srcFileName = fileNames[i]; 3870 destFileName = srcFileName.replace(srcDir, destDir); 3871 3872 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) { 3873 copiedFiles.push(destFileName); 3874 } 3875 } 3876 3877 return copiedFiles.length ? copiedFiles : null; //Array or null 3878 }, 3879 3880 copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) { 3881 //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if 3882 //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred. 3883 var destFile = new java.io.File(destFileName), srcFile, parentDir, 3884 srcChannel, destChannel; 3885 3886 //logger.trace("Src filename: " + srcFileName); 3887 //logger.trace("Dest filename: " + destFileName); 3888 3889 //If onlyCopyNew is true, then compare dates and only copy if the src is newer 3890 //than dest. 3891 if (onlyCopyNew) { 3892 srcFile = new java.io.File(srcFileName); 3893 if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) { 3894 return false; //Boolean 3895 } 3896 } 3897 3898 //Make sure destination dir exists. 3899 parentDir = destFile.getParentFile(); 3900 if (!parentDir.exists()) { 3901 if (!parentDir.mkdirs()) { 3902 throw "Could not create directory: " + parentDir.getCanonicalPath(); 3903 } 3904 } 3905 3906 //Java's version of copy file. 3907 srcChannel = new java.io.FileInputStream(srcFileName).getChannel(); 3908 destChannel = new java.io.FileOutputStream(destFileName).getChannel(); 3909 destChannel.transferFrom(srcChannel, 0, srcChannel.size()); 3910 srcChannel.close(); 3911 destChannel.close(); 3912 3913 return true; //Boolean 3914 }, 3915 3916 /** 3917 * Renames a file. May fail if "to" already exists or is on another drive. 3918 */ 3919 renameFile: function (from, to) { 3920 return (new java.io.File(from)).renameTo((new java.io.File(to))); 3921 }, 3922 3923 readFile: function (/*String*/path, /*String?*/encoding) { 3924 //A file read function that can deal with BOMs 3925 encoding = encoding || "utf-8"; 3926 var fileObj = new java.io.File(path), 3927 input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(fileObj), encoding)),
3928 stringBuffer, line; 3929 try { 3930 stringBuffer = new java.lang.StringBuffer(); 3931 line = input.readLine(); 3932 3933 // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 3934 // http://www.unicode.org/faq/utf_bom.html 3935 3936 // 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: 3937 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 3938 if (line && line.length() && line.charAt(0) === 0xfeff) { 3939 // Eat the BOM, since we've already found the encoding on this file, 3940 // and we plan to concatenating this buffer with others; the BOM should 3941 // only appear at the top of a file. 3942 line = line.substring(1); 3943 } 3944 while (line !== null) { 3945 stringBuffer.append(line); 3946 stringBuffer.append(file.lineSeparator); 3947 line = input.readLine(); 3948 } 3949 //Make sure we return a JavaScript string and not a Java string. 3950 return String(stringBuffer.toString()); //String 3951 } finally { 3952 input.close(); 3953 } 3954 }, 3955 3956 readFileAsync: function (path, encoding) { 3957 var d = prim(); 3958 try { 3959 d.resolve(file.readFile(path, encoding)); 3960 } catch (e) { 3961 d.reject(e); 3962 } 3963 return d.promise; 3964 }, 3965 3966 saveUtf8File: function (/*String*/fileName, /*String*/fileContents) { 3967 //summary: saves a file using UTF-8 encoding. 3968 file.saveFile(fileName, fileContents, "utf-8"); 3969 }, 3970 3971 saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) { 3972 //summary: saves a file. 3973 var outFile = new java.io.File(fileName), outWriter, parentDir, os; 3974 3975 parentDir = outFile.getAbsoluteFile().getParentFile(); 3976 if (!parentDir.exists()) { 3977 if (!parentDir.mkdirs()) { 3978 throw "Could not create directory: " + parentDir.getAbsolutePath(); 3979 } 3980 } 3981 3982 if (encoding) { 3983 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding); 3984 } else { 3985 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile)); 3986 } 3987 3988 os = new java.io.BufferedWriter(outWriter); 3989 try { 3990 //If in Nashorn, need to coerce the JS string to a Java string so that 3991 //writer.write method dispatch correctly detects the type. 3992 if (typeof importPackage !== 'undefined') { 3993 os.write(fileContents); 3994 } else { 3995 os.write(new java.lang.String(fileContents)); 3996 } 3997 } finally { 3998 os.close(); 3999 } 4000 }, 4001 4002 deleteFile: function (/*String*/fileName) { 4003 //summary: deletes a file or directory if it exists. 4004 var fileObj = new java.io.File(fileName), files, i; 4005 if (fileObj.exists()) { 4006 if (fileObj.isDirectory()) { 4007 files = fileObj.listFiles(); 4008 for (i = 0; i < files.length; i++) { 4009 this.deleteFile(files[i]); 4010 } 4011 } 4012 fileObj["delete"](); 4013 } 4014 }, 4015 4016 /** 4017 * Deletes any empty directories under the given directory. 4018 * The startDirIsJavaObject is private to this implementation's 4019 * recursion needs. 4020 */ 4021 deleteEmptyDirs: function (startDir, startDirIsJavaObject) { 4022 var topDir = startDir, 4023 dirFileArray, i, fileObj; 4024 4025 if (!startDirIsJavaObject) {
4026 topDir = new java.io.File(startDir); 4027 } 4028 4029 if (topDir.exists()) { 4030 dirFileArray = topDir.listFiles(); 4031 for (i = 0; i < dirFileArray.length; i++) { 4032 fileObj = dirFileArray[i]; 4033 if (fileObj.isDirectory()) { 4034 file.deleteEmptyDirs(fileObj, true); 4035 } 4036 } 4037 4038 //If the directory is empty now, delete it. 4039 if (topDir.listFiles().length === 0) { 4040 file.deleteFile(String(topDir.getPath())); 4041 } 4042 } 4043 } 4044 }; 4045 4046 return file; 4047 }); 4048 4049 } 4050 4051 if(env === 'xpconnect') { 4052//Helper functions to deal with file I/O. 4053 4054 /*jslint plusplus: false */ 4055 /*global define, Components, xpcUtil */ 4056 4057 define('xpconnect/file', ['prim'], function (prim) { 4058 var file, 4059 Cc = Components.classes, 4060 Ci = Components.interfaces, 4061 //Depends on xpcUtil which is set up in x.js 4062 xpfile = xpcUtil.xpfile; 4063 4064 function mkFullDir(dirObj) { 4065 //1 is DIRECTORY_TYPE, 511 is 0777 permissions 4066 if (!dirObj.exists()) { 4067 dirObj.create(1, 511); 4068 } 4069 } 4070 4071 file = { 4072 backSlashRegExp: /\\/g, 4073 4074 exclusionRegExp: /^\./, 4075 4076 getLineSeparator: function () { 4077 return file.lineSeparator; 4078 }, 4079 4080 lineSeparator: ('@mozilla.org/windows-registry-key;1' in Cc) ? 4081 '\r\n' : '\n', 4082 4083 exists: function (fileName) { 4084 return xpfile(fileName).exists(); 4085 }, 4086 4087 parent: function (fileName) { 4088 return xpfile(fileName).parent; 4089 }, 4090 4091 normalize: function (fileName) { 4092 return file.absPath(fileName); 4093 }, 4094 4095 isFile: function (path) { 4096 return xpfile(path).isFile(); 4097 }, 4098 4099 isDirectory: function (path) { 4100 return xpfile(path).isDirectory(); 4101 }, 4102 4103 /** 4104 * Gets the absolute file path as a string, normalized 4105 * to using front slashes for path separators. 4106 * @param {java.io.File||String} file 4107 */ 4108 absPath: function (fileObj) { 4109 if (typeof fileObj === "string") { 4110 fileObj = xpfile(fileObj); 4111 } 4112 return fileObj.path; 4113 }, 4114 4115 getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsObject) { 4116 //summary: Recurses startDir and finds matches to the files that match regExpFilters.include 4117 //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters, 4118 //and it will be treated as the "include" case. 4119 //Ignores files/directories that start with a period (.) unless exclusionRegExp 4120 //is set to another value. 4121 var files = [], topDir, regExpInclude, regExpExclude, dirFileArray, 4122 fileObj, filePath, ok, dirFiles; 4123 4124 topDir = startDir; 4125 if (!startDirIsObject) { 4126 topDir = xpfile(startDir); 4127 } 4128 4129 regExpInclude = regExpFilters.include || regExpFilters; 4130 regExpExclude = regExpFilters.exclude || null; 4131 4132 if (topDir.exists()) { 4133 dirFileArray = topDir.directoryEntries; 4134 while (dirFileArray.hasMoreElements()) { 4135 fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile); 4136 if (fileObj.isFile()) { 4137 filePath = fileObj.path; 4138 if (makeUnixPaths) { 4139 if (filePath.indexOf("/") === -1) { 4140 filePath = filePath.replace(/\\/g, "/"); 4141 } 4142 } 4143 4144 ok = true; 4145 if (regExpInclude) { 4146 ok = filePath.match(regExpInclude); 4147 } 4148 if (ok && regExpExclude) { 4149 ok = !filePath.match(regExpExclude); 4150 } 4151 4152 if (ok && (!file.exclusionRegExp || 4153 !file.exclusionRegExp.test(fileObj.leafName))) { 4154 files.push(filePath); 4155 } 4156 } else if (fileObj.isDirectory() && 4157 (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.leafName))) { 4158 dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true); 4159 //Do not use push.apply for dir listings, can hit limit of max number 4160 //of arguments to a function call, #921.
4161 dirFiles.forEach(function (dirFile) { 4162 files.push(dirFile); 4163 }); 4164 } 4165 } 4166 } 4167 4168 return files; //Array 4169 }, 4170 4171 copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) { 4172 //summary: copies files from srcDir to destDir using the regExpFilter to determine if the 4173 //file should be copied. Returns a list file name strings of the destinations that were copied. 4174 regExpFilter = regExpFilter || /\w/; 4175 4176 var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true), 4177 copiedFiles = [], i, srcFileName, destFileName; 4178 4179 for (i = 0; i < fileNames.length; i += 1) { 4180 srcFileName = fileNames[i]; 4181 destFileName = srcFileName.replace(srcDir, destDir); 4182 4183 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) { 4184 copiedFiles.push(destFileName); 4185 } 4186 } 4187 4188 return copiedFiles.length ? copiedFiles : null; //Array or null 4189 }, 4190 4191 copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) { 4192 //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if 4193 //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred. 4194 var destFile = xpfile(destFileName), 4195 srcFile = xpfile(srcFileName); 4196 4197 //logger.trace("Src filename: " + srcFileName); 4198 //logger.trace("Dest filename: " + destFileName); 4199 4200 //If onlyCopyNew is true, then compare dates and only copy if the src is newer 4201 //than dest. 4202 if (onlyCopyNew) { 4203 if (destFile.exists() && destFile.lastModifiedTime >= srcFile.lastModifiedTime) { 4204 return false; //Boolean 4205 } 4206 } 4207 4208 srcFile.copyTo(destFile.parent, destFile.leafName); 4209 4210 return true; //Boolean 4211 }, 4212 4213 /** 4214 * Renames a file. May fail if "to" already exists or is on another drive. 4215 */ 4216 renameFile: function (from, to) { 4217 var toFile = xpfile(to); 4218 return xpfile(from).moveTo(toFile.parent, toFile.leafName); 4219 }, 4220 4221 readFile: xpcUtil.readFile, 4222 4223 readFileAsync: function (path, encoding) { 4224 var d = prim(); 4225 try { 4226 d.resolve(file.readFile(path, encoding)); 4227 } catch (e) { 4228 d.reject(e); 4229 } 4230 return d.promise; 4231 }, 4232 4233 saveUtf8File: function (/*String*/fileName, /*String*/fileContents) { 4234 //summary: saves a file using UTF-8 encoding. 4235 file.saveFile(fileName, fileContents, "utf-8"); 4236 }, 4237 4238 saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) { 4239 var outStream, convertStream, 4240 fileObj = xpfile(fileName); 4241 4242 mkFullDir(fileObj.parent); 4243 4244 try { 4245 outStream = Cc['@mozilla.org/network/file-output-stream;1'] 4246 .createInstance(Ci.nsIFileOutputStream); 4247 //438 is decimal for 0777 4248 outStream.init(fileObj, 0x02 | 0x08 | 0x20, 511, 0); 4249 4250 convertStream = Cc['@mozilla.org/intl/converter-output-stream;1'] 4251 .createInstance(Ci.nsIConverterOutputStream); 4252 4253 convertStream.init(outStream, encoding, 0, 0
4253); 4254 convertStream.writeString(fileContents); 4255 } catch (e) { 4256 throw new Error((fileObj && fileObj.path || '') + ': ' + e); 4257 } finally { 4258 if (convertStream) { 4259 convertStream.close(); 4260 } 4261 if (outStream) { 4262 outStream.close(); 4263 } 4264 } 4265 }, 4266 4267 deleteFile: function (/*String*/fileName) { 4268 //summary: deletes a file or directory if it exists. 4269 var fileObj = xpfile(fileName); 4270 if (fileObj.exists()) { 4271 fileObj.remove(true); 4272 } 4273 }, 4274 4275 /** 4276 * Deletes any empty directories under the given directory. 4277 * The startDirIsJavaObject is private to this implementation's 4278 * recursion needs. 4279 */ 4280 deleteEmptyDirs: function (startDir, startDirIsObject) { 4281 var topDir = startDir, 4282 dirFileArray, fileObj; 4283 4284 if (!startDirIsObject) { 4285 topDir = xpfile(startDir); 4286 } 4287 4288 if (topDir.exists()) { 4289 dirFileArray = topDir.directoryEntries; 4290 while (dirFileArray.hasMoreElements()) { 4291 fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile); 4292 4293 if (fileObj.isDirectory()) { 4294 file.deleteEmptyDirs(fileObj, true); 4295 } 4296 } 4297 4298 //If the directory is empty now, delete it. 4299 dirFileArray = topDir.directoryEntries; 4300 if (!dirFileArray.hasMoreElements()) { 4301 file.deleteFile(topDir.path); 4302 } 4303 } 4304 } 4305 }; 4306 4307 return file; 4308 }); 4309 4310 } 4311 4312 if(env === 'browser') { 4313 /*global process */ 4314 define('browser/quit', function () { 4315 'use strict'; 4316 return function (code) { 4317 }; 4318 }); 4319 } 4320 4321 if(env === 'node') { 4322 /*global process */ 4323 define('node/quit', function () { 4324 'use strict'; 4325 return function (code) { 4326 var draining = 0; 4327 var exit = function () { 4328 if (draining === 0) { 4329 process.exit(code); 4330 } else { 4331 draining -= 1; 4332 } 4333 }; 4334 if (process.stdout.bufferSize) { 4335 draining += 1; 4336 process.stdout.once('drain', exit); 4337 } 4338 if (process.stderr.bufferSize) { 4339 draining += 1; 4340 process.stderr.once('drain', exit); 4341 } 4342 exit(); 4343 }; 4344 }); 4345 4346 } 4347 4348 if(env === 'rhino') { 4349 /*global quit */ 4350 define('rhino/quit', function () { 4351 'use strict'; 4352 return function (code) { 4353 return quit(code); 4354 }; 4355 }); 4356 4357 } 4358 4359 if(env === 'xpconnect') { 4360 /*global quit */ 4361 define('xpconnect/quit', function () { 4362 'use strict'; 4363 return function (code) { 4364 return quit(code); 4365 }; 4366 }); 4367 4368 } 4369 4370 if(env === 'browser') { 4371 /*jslint strict: false */ 4372 /*global define: false, console: false */ 4373 4374 define('browser/print', function () { 4375 function print(msg) { 4376 console.log(msg); 4377 } 4378 4379 return print; 4380 }); 4381 4382 } 4383 4384 if(env === 'node') { 4385 /*jslint strict: false */ 4386 /*global define: false, console: false */ 4387 4388 define('node/print', function () { 4389 function print(msg) { 4390 console.log(msg); 4391 } 4392 4393 return print; 4394 }); 4395 4396 } 4397 4398 if(env === 'rhino') { 4399 /*jslint strict: false */ 4400 /*global define: false, print: false */ 4401 4402 define('rhino/print', function () { 4403 return print; 4404 }); 4405 4406 } 4407 4408 if(env === 'xpconnect') { 4409 /*jslint strict: false */ 4410 /*global define: false, print: false */ 4411 4412 define('xpconnect/print', function () { 4413 return print; 4414 }); 4415 4416 } 4417 /*jslint nomen: false, strict: false */ 4418 /*global define: false */ 4419 4420 define('logger', ['env!env/print'], function (print) { 4421 var logger = { 4422 TRACE: 0, 4423 INFO: 1, 4424 WARN: 2, 4425 ERROR: 3, 4426 SILENT: 4, 4427 level: 0, 4428 logPrefix: "", 4429 4430 logLevel: function( level ) { 4431 this.level = level; 4432 }, 4433 4434 trace: function (message) { 4435 if (this.level <= this.TRACE) { 4436 this._print(message); 4437 } 4438 }, 4439 4440 info: function (message) { 4441 if (this.level <= this.INFO) { 4442 this._print(message); 4443 } 4444 }, 4445 4446 warn: function (message) { 4447 if (this.level <= this.WARN) { 4448 this._print(message); 4449 } 4450 }, 4451 4452 error: function (message) { 4453 if (this.level <= this.ERROR) { 4454 this._print(message); 4455 } 4456 }, 4457 4458 _print: function (message) { 4459 this._sysPrint((this.logPrefix ? (this.logPrefix + " ") : "") + message); 4460 }, 4461 4462 _sysPrint: function (message) { 4463 print(message); 4464 } 4465 }; 4466 4467 return logger; 4468 }); 4469//Just a blank file to use when building the optimizer with the optimizer, 4470//so that the build does not attempt to inline some env modules, 4471//like Node's fs and path. 4472 4473 (function webpackUniversalModuleDefinition(root, factory) { 4474 /* istanbul ignore next */ 4475 if(typeof define === 'function' && define.amd) 4476 define('esprima', [], factory); 4477 else if(typeof exports === 'object' && typeof module === 'object') 4478 module.exports = factory(); 4479 /* istanbul ignore next */ 4480 else if(typeof exports === 'object') 4481 exports["esprima"] = factory(); 4482 else 4483 root["esprima"] = factory(); 4484 })(this, function() { 4485 return /******/ (function(modules) { // webpackBootstrap 4486 /******/ // The module cache 4487 /******/ var installedModules = {}; 4488 4489 /******/ // The require function 4490 /******/ function __webpack_require__(moduleId) { 4491 4492 /******/ // Check if module is in cache 4493 /* istanbul ignore if */ 4494 /******/ if(installedModules[moduleId]) 4495 /******/ return installedModules[moduleId].exports; 4496 4497 /******/ // Create a new module (and put it into the cache) 4498 /******/ var module = installedModules[moduleId] = { 4499 /******/ exports: {}, 4500 /******/ id: moduleId, 4501 /******/ loaded: false 4502 /******/ }; 4503 4504 /******/ // Execute the module function 4505 /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 4506 4507 /******/ // Flag the module as loaded 4508 /******/ module.loaded = true; 4509 4510 /******/ // Return the exports of the module 4511 /******/ return module.exports; 4512 /******/ } 4513 4514 4515 /******/ // expose the modules object (__webpack_modules__) 4516 /******/ __webpack_require__.m = modules; 4517 4518 /******/ // expose the module cache 4519 /******/ __webpack_require__.c = installedModules; 4520 4521 /******/ // __webpack_public_path__ 4522 /******/ __webpack_require__.p = ""; 4523 4524 /******/ // Load entry module and return exports 4525 /******/ return __webpack_require__(0); 4526 /******/ }) 4527 /************************************************************************/ 4528 /******/ ([ 4529 /* 0 */ 4530 /***/ function(module, exports, __webpack_require__) { 4531 4532 "use strict"; 4533 /* 4534 Copyright JS Foundation and other contributors, https://js.foundation/ 4535 4536 Redistribution and use in source and binary forms, with or without 4537 modification, are permitted provided that the following conditions are met: 4538 4539 * Redistributions of source code must retain the above copyright 4540 notice, this list of conditions and the following disclaimer. 4541 * Redistributions in binary form must reproduce the above copyright 4542 notice, this list of conditions and the following disclaimer in the 4543 documentation and/or other materials provided with the distribution. 4544 4545 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 4546 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4547 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4548 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 4549 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 4550 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4551 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 4552 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 4553 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 4554 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4555 */ 4556 Object.defineProperty(exports, "__esModule", { value: true }); 4557 var comment_handler_1 = __webpack_require__(1); 4558 var jsx_parser_1 = __webpack_require__(3); 4559 var parser_1 = __webpack_require__(8); 4560 var tokenizer_1 = __webpack_require__(15); 4561 function parse(code, options, delegate) { 4562 var commentHandler = null; 4563 var proxyDelegate = function (node, metadata) { 4564 if (delegate) { 4565 delegate(node, metadata); 4566 } 4567 if (commentHandler) { 4568 commentHandler.visit(node, metadata); 4569 } 4570 }; 4571 var parserDelegate = (typeof delegate === 'function') ? proxyDelegate : null; 4572 var collectComment = false;
vendor: 52,807 bytes, lines 4573-5427
4573 if (options) { 4574 collectComment = (typeof options.comment === 'boolean' && options.comment); 4575 var attachComment = (typeof options.attachComment === 'boolean' && options.attachComment); 4576 if (collectComment || attachComment) { 4577 commentHandler = new comment_handler_1.CommentHandler(); 4578 commentHandler.attach = attachComment; 4579 options.comment = true; 4580 parserDelegate = proxyDelegate; 4581 } 4582 } 4583 var isModule = false; 4584 if (options && typeof options.sourceType === 'string') { 4585 isModule = (options.sourceType === 'module'); 4586 } 4587 var parser; 4588 if (options && typeof options.jsx === 'boolean' && options.jsx) { 4589 parser = new jsx_parser_1.JSXParser(code, options, parserDelegate); 4590 } 4591 else { 4592 parser = new parser_1.Parser(code, options, parserDelegate); 4593 } 4594 var program = isModule ? parser.parseModule() : parser.parseScript(); 4595 var ast = program; 4596 if (collectComment && commentHandler) { 4597 ast.comments = commentHandler.comments; 4598 } 4599 if (parser.config.tokens) { 4600 ast.tokens = parser.tokens; 4601 } 4602 if (parser.config.tolerant) { 4603 ast.errors = parser.errorHandler.errors; 4604 } 4605 return ast; 4606 } 4607 exports.parse = parse; 4608 function parseModule(code, options, delegate) { 4609 var parsingOptions = options || {}; 4610 parsingOptions.sourceType = 'module'; 4611 return parse(code, parsingOptions, delegate); 4612 } 4613 exports.parseModule = parseModule; 4614 function parseScript(code, options, delegate) { 4615 var parsingOptions = options || {}; 4616 parsingOptions.sourceType = 'script'; 4617 return parse(code, parsingOptions, delegate); 4618 } 4619 exports.parseScript = parseScript; 4620 function tokenize(code, options, delegate) { 4621 var tokenizer = new tokenizer_1.Tokenizer(code, options); 4622 var tokens; 4623 tokens = []; 4624 try { 4625 while (true) { 4626 var token = tokenizer.getNextToken(); 4627 if (!token) { 4628 break; 4629 } 4630 if (delegate) { 4631 token = delegate(token); 4632 } 4633 tokens.push(token); 4634 } 4635 } 4636 catch (e) { 4637 tokenizer.errorHandler.tolerate(e); 4638 } 4639 if (tokenizer.errorHandler.tolerant) { 4640 tokens.errors = tokenizer.errors(); 4641 } 4642 return tokens; 4643 } 4644 exports.tokenize = tokenize; 4645 var syntax_1 = __webpack_require__(2); 4646 exports.Syntax = syntax_1.Syntax; 4647 // Sync with *.json manifests. 4648 exports.version = '4.0.1'; 4649 4650 4651 /***/ }, 4652 /* 1 */ 4653 /***/ function(module, exports, __webpack_require__) { 4654 4655 "use strict"; 4656 Object.defineProperty(exports, "__esModule", { value: true }); 4657 var syntax_1 = __webpack_require__(2); 4658 var CommentHandler = (function () { 4659 function CommentHandler() { 4660 this.attach = false; 4661 this.comments = []; 4662 this.stack = []; 4663 this.leading = []; 4664 this.trailing = []; 4665 } 4666 CommentHandler.prototype.insertInnerComments = function (node, metadata) { 4667 // innnerComments for properties empty block 4668 // `function a() {/** comments **\/}` 4669 if (node.type === syntax_1.Syntax.BlockStatement && node.body.length === 0) { 4670 var innerComments = []; 4671 for (var i = this.leading.length - 1; i >= 0; --i) { 4672 var entry = this.leading[i]; 4673 if (metadata.end.offset >= entry.start) { 4674 innerComments.unshift(entry.comment); 4675 this.leading.splice(i, 1); 4676 this.trailing.splice(i, 1); 4677 } 4678 } 4679 if (innerComments.length) { 4680 node.innerComments = innerComments; 4681 } 4682 } 4683 }; 4684 CommentHandler.prototype.findTrailingComments = function (metadata) { 4685 var trailingComments = []; 4686 if (this.trailing.length > 0) { 4687 for (var i = this.trailing.length - 1; i >= 0; --i) { 4688 var entry_1 = this.trailing[i]; 4689 if (entry_1.start >= metadata.end.offset) { 4690 trailingComments.unshift(entry_1.comment); 4691 } 4692 } 4693 this.trailing.length = 0; 4694 return trailingComments; 4695 } 4696 var entry = this.stack[this.stack.length - 1]; 4697 if (entry && entry.node.trailingComments) { 4698 var firstComment = entry.node.trailingComments[0]; 4699 if (firstComment && firstComment.range[0] >= metadata.end.offset) { 4700 trailingComments = entry.node.trailingComments; 4701 delete entry.node.trailingComments; 4702 } 4703 } 4704 return trailingComments; 4705 }; 4706 CommentHandler.prototype.findLeadingComments = function (metadata) { 4707 var leadingComments = []; 4708 var target; 4709 while (this.stack.length > 0) { 4710 var entry = this.stack[this.stack.length - 1]; 4711 if (entry && entry.start >= metadata.start.offset) { 4712 target = entry.node; 4713 this.stack.pop(); 4714 } 4715 else { 4716 break; 4717 } 4718 } 4719 if (target) { 4720 var count = target.leadingComments ? target.leadingComments.length : 0; 4721 for (var i = count - 1; i >= 0; --i) { 4722 var comment = target.leadingComments[i]; 4723 if (comment.range[1] <= metadata.start.offset) { 4724 leadingComments.unshift(comment); 4725 target.leadingComments.splice(i, 1); 4726 } 4727 } 4728 if (target.leadingComments && target.leadingComments.length === 0) { 4729 delete target.leadingComments; 4730 } 4731 return leadingComments; 4732 } 4733 for (var i = this.leading.length - 1; i >= 0; --i) { 4734 var entry = this.leading[i]; 4735 if (entry.start <= metadata.start.offset) { 4736 leadingComments.unshift(entry.comment); 4737 this.leading.splice(i, 1); 4738 } 4739 } 4740 return leadingComments; 4741 }; 4742 CommentHandler.prototype.visitNode = function (node, metadata) { 4743 if (node.type === syntax_1.Syntax.Program && node.body.length > 0) { 4744 return; 4745 } 4746 this.insertInnerComments(node, metadata); 4747 var trailingComments = this.findTrailingComments(metadata); 4748 var leadingComments = this.findLeadingComments(metadata); 4749 if (leadingComments.length > 0) { 4750 node.leadingComments = leadingComments; 4751 } 4752 if (trailingComments.length > 0) { 4753 node.trailingComments = trailingComments; 4754 } 4755 this.stack.push({ 4756 node: node, 4757 start: metadata.start.offset 4758 }); 4759 }; 4760 CommentHandler.prototype.visitComment = function (node, metadata) { 4761 var type = (node.type[0] === 'L') ? 'Line' : 'Block'; 4762 var comment = { 4763 type: type, 4764 value: node.value 4765 }; 4766 if (node.range) { 4767 comment.range = node.range; 4768 } 4769 if (node.loc) { 4770 comment.loc = node.loc; 4771 } 4772 this.comments.push(comment); 4773 if (this.attach) { 4774 var entry = { 4775 comment: { 4776 type: type, 4777 value: node.value, 4778 range: [metadata.start.offset, metadata.end.offset] 4779 }, 4780 start: metadata.start.offset 4781 }; 4782 if (node.loc) { 4783 entry.comment.loc = node.loc; 4784 } 4785 node.type = type; 4786 this.leading.push(entry); 4787 this.trailing.push(entry); 4788 } 4789 }; 4790 CommentHandler.prototype.visit = function (node, metadata) { 4791 if (node.type === 'LineComment') { 4792 this.visitComment(node, metadata); 4793 } 4794 else if (node.type === 'BlockComment') { 4795 this.visitComment(node, metadata); 4796 } 4797 else if (this.attach) { 4798 this.visitNode(node, metadata); 4799 } 4800 }; 4801 return CommentHandler; 4802 }()); 4803 exports.CommentHandler = CommentHandler; 4804 4805 4806 /***/ }, 4807 /* 2 */ 4808 /***/ function(module, exports) { 4809 4810 "use strict"; 4811 Object.defineProperty(exports, "__esModule", { value: true }); 4812 exports.Syntax = { 4813 AssignmentExpression: 'AssignmentExpression', 4814 AssignmentPattern: 'AssignmentPattern', 4815 ArrayExpression: 'ArrayExpression', 4816 ArrayPattern: 'ArrayPattern', 4817 ArrowFunctionExpression: 'ArrowFunctionExpression', 4818 AwaitExpression: 'AwaitExpression', 4819 BlockStatement: 'BlockStatement', 4820 BinaryExpression: 'BinaryExpression', 4821 BreakStatement: 'BreakStatement', 4822 CallExpression: 'CallExpression', 4823 CatchClause: 'CatchClause', 4824 ClassBody: 'ClassBody', 4825 ClassDeclaration: 'ClassDeclaration', 4826 ClassExpression: 'ClassExpression', 4827 ConditionalExpression: 'ConditionalExpression', 4828 ContinueStatement: 'ContinueStatement', 4829 DoWhileStatement: 'DoWhileStatement', 4830 DebuggerStatement: 'DebuggerStatement', 4831 EmptyStatement: 'EmptyStatement', 4832 ExportAllDeclaration: 'ExportAllDeclaration', 4833 ExportDefaultDeclaration: 'ExportDefaultDeclaration', 4834 ExportNamedDeclaration: 'ExportNamedDeclaration', 4835 ExportSpecifier: 'ExportSpecifier', 4836 ExpressionStatement: 'ExpressionStatement', 4837 ForStatement: 'ForStatement', 4838 ForOfStatement: 'ForOfStatement', 4839 ForInStatement: 'ForInStatement', 4840 FunctionDeclaration: 'FunctionDeclaration', 4841 FunctionExpression: 'FunctionExpression', 4842 Identifier: 'Identifier', 4843 IfStatement: 'IfStatement', 4844 ImportDeclaration: 'ImportDeclaration', 4845 ImportDefaultSpecifier: 'ImportDefaultSpecifier', 4846 ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', 4847 ImportSpecifier: 'ImportSpecifier', 4848 Literal: 'Literal', 4849 LabeledStatement: 'LabeledStatement', 4850 LogicalExpression: 'LogicalExpression', 4851 MemberExpression: 'MemberExpression', 4852 MetaProperty: 'MetaProperty', 4853 MethodDefinition: 'MethodDefinition', 4854 NewExpression: 'NewExpression', 4855 ObjectExpression: 'ObjectExpression', 4856 ObjectPattern: 'ObjectPattern', 4857 Program: 'Program', 4858 Property: 'Property', 4859 RestElement: 'RestElement', 4860 ReturnStatement: 'ReturnStatement', 4861 SequenceExpression: 'SequenceExpression', 4862 SpreadElement: 'SpreadElement', 4863 Super: 'Super', 4864 SwitchCase: 'SwitchCase', 4865 SwitchStatement: 'SwitchStatement', 4866 TaggedTemplateExpression: 'TaggedTemplateExpression', 4867 TemplateElement: 'TemplateElement', 4868 TemplateLiteral: 'TemplateLiteral', 4869 ThisExpression: 'ThisExpression', 4870 ThrowStatement: 'ThrowStatement', 4871 TryStatement: 'TryStatement', 4872 UnaryExpression: 'UnaryExpression', 4873 UpdateExpression: 'UpdateExpression', 4874 VariableDeclaration: 'VariableDeclaration', 4875 VariableDeclarator: 'VariableDeclarator', 4876 WhileStatement: 'WhileStatement', 4877 WithStatement: 'WithStatement', 4878 YieldExpression: 'YieldExpression' 4879 }; 4880 4881 4882 /***/ }, 4883 /* 3 */ 4884 /***/ function(module, exports, __webpack_require__) { 4885 4886 "use strict"; 4887 /* istanbul ignore next */ 4888 var __extends = (this && this.__extends) || (function () { 4889 var extendStatics = Object.setPrototypeOf || 4890 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 4891 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 4892 return function (d, b) { 4893 extendStatics(d, b); 4894 function __() { this.constructor = d; } 4895 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 4896 }; 4897 })(); 4898 Object.defineProperty(exports, "__esModule", { value: true }); 4899 var character_1 = __webpack_require__(4); 4900 var JSXNode = __webpack_require__(5); 4901 var jsx_syntax_1 = __webpack_require__(6); 4902 var Node = __webpack_require__(7); 4903 var parser_1 = __webpack_require__(8); 4904 var token_1 = __webpack_require__(13); 4905 var xhtml_entities_1 = __webpack_require__(14); 4906 token_1.TokenName[100 /* Identifier */] = 'JSXIdentifier'; 4907 token_1.TokenName[101 /* Text */] = 'JSXText'; 4908 // Fully qualified element name, e.g. <svg:path> returns "svg:path" 4909 function getQualifiedElementName(elementName) { 4910 var qualifiedName; 4911 switch (elementName.type) { 4912 case jsx_syntax_1.JSXSyntax.JSXIdentifier: 4913 var id = elementName; 4914 qualifiedName = id.name; 4915 break; 4916 case jsx_syntax_1.JSXSyntax.JSXNamespacedName: 4917 var ns = elementName; 4918 qualifiedName = getQualifiedElementName(ns.namespace) + ':' + 4919 getQualifiedElementName(ns.name); 4920 break; 4921 case jsx_syntax_1.JSXSyntax.JSXMemberExpression: 4922 var expr = elementName; 4923 qualifiedName = getQualifiedElementName(expr.object) + '.' + 4924 getQualifiedElementName(expr.property); 4925 break; 4926 /* istanbul ignore next */ 4927 default: 4928 break; 4929 } 4930 return qualifiedName; 4931 } 4932 var JSXParser = (function (_super) { 4933 __extends(JSXParser, _super); 4934 function JSXParser(code, options, delegate) { 4935 return _super.call(this, code, options, delegate) || this; 4936 } 4937 JSXParser.prototype.parsePrimaryExpression = function () { 4938 return this.match('<') ? this.parseJSXRoot() : _super.prototype.parsePrimaryExpression.call(this); 4939 }; 4940 JSXParser.prototype.startJSX = function () { 4941 // Unwind the scanner before the lookahead token. 4942 this.scanner.index = this.startMarker.index; 4943 this.scanner.lineNumber = this.startMarker.line; 4944 this.scanner.lineStart = this.startMarker.index - this.startMarker.column; 4945 }; 4946 JSXParser.prototype.finishJSX = function () { 4947 // Prime the next lookahead. 4948 this.nextToken(); 4949 }; 4950 JSXParser.prototype.reenterJSX = function () { 4951 this.startJSX(); 4952 this.expectJSX('}'); 4953 // Pop the closing '}' added from the lookahead. 4954 if (this.config.tokens) { 4955 this.tokens.pop(); 4956 } 4957 }; 4958 JSXParser.prototype.createJSXNode = function () { 4959 this.collectComments(); 4960 return { 4961 index: this.scanner.index, 4962 line: this.scanner.lineNumber, 4963 column: this.scanner.index - this.scanner.lineStart 4964 }; 4965 }; 4966 JSXParser.prototype.createJSXChildNode = function () { 4967 return { 4968 index: this.scanner.index, 4969 line: this.scanner.lineNumber, 4970 column: this.scanner.index - this.scanner.lineStart 4971 }; 4972 }; 4973 JSXParser.prototype.scanXHTMLEntity = function (quote) { 4974 var result = '&'; 4975 var valid = true; 4976 var terminated = false; 4977 var numeric = false; 4978 var hex = false; 4979 while (!this.scanner.eof() && valid && !terminated) { 4980 var ch = this.scanner.source[this.scanner.index]; 4981 if (ch === quote) { 4982 break; 4983 } 4984 terminated = (ch === ';'); 4985 result += ch; 4986 ++this.scanner.index; 4987 if (!terminated) { 4988 switch (result.length) { 4989 case 2: 4990 // e.g. '{' 4991 numeric = (ch === '#'); 4992 break; 4993 case 3: 4994 if (numeric) { 4995 // e.g. 'A' 4996 hex = (ch === 'x'); 4997 valid = hex || character_1.Character.isDecimalDigit(ch.charCodeAt(0)); 4998 numeric = numeric && !hex; 4999 } 5000 break; 5001 default: 5002 valid = valid && !(numeric && !character_1.Character.isDecimalDigit(ch.charCodeAt(0))); 5003 valid = valid && !(hex && !character_1.Character.isHexDigit(ch.charCodeAt(0))); 5004 break; 5005 } 5006 } 5007 } 5008 if (valid && terminated && result.length > 2) { 5009 // e.g. 'A' becomes just '#x41' 5010 var str = result.substr(1, result.length - 2); 5011 if (numeric && str.length > 1) { 5012 result = String.fromCharCode(parseInt(str.substr(1), 10)); 5013 } 5014 else if (hex && str.length > 2) { 5015 result = String.fromCharCode(parseInt('0' + str.substr(1), 16)); 5016 } 5017 else if (!numeric && !hex && xhtml_entities_1.XHTMLEntities[str]) { 5018 result = xhtml_entities_1.XHTMLEntities[str]; 5019 } 5020 } 5021 return result; 5022 }; 5023 // Scan the next JSX token. This replaces Scanner#lex when in JSX mode. 5024 JSXParser.prototype.lexJSX = function () { 5025 var cp = this.scanner.source.charCodeAt(this.scanner.index); 5026 // < > / : = { } 5027 if (cp === 60 || cp === 62 || cp === 47 || cp === 58 || cp === 61 || cp === 123 || cp === 125) { 5028 var value = this.scanner.source[this.scanner.index++]; 5029 return { 5030 type: 7 /* Punctuator */, 5031 value: value, 5032 lineNumber: this.scanner.lineNumber, 5033 lineStart: this.scanner.lineStart, 5034 start: this.scanner.index - 1, 5035 end: this.scanner.index 5036 }; 5037 } 5038 // " ' 5039 if (cp === 34 || cp === 39) { 5040 var start = this.scanner.index; 5041 var quote = this.scanner.source[this.scanner.index++]; 5042 var str = ''; 5043 while (!this.scanner.eof()) { 5044 var ch = this.scanner.source[this.scanner.index++]; 5045 if (ch === quote) { 5046 break; 5047 } 5048 else if (ch === '&') { 5049 str += this.scanXHTMLEntity(quote); 5050 } 5051 else { 5052 str += ch; 5053 } 5054 } 5055 return { 5056 type: 8 /* StringLiteral */, 5057 value: str, 5058 lineNumber: this.scanner.lineNumber, 5059 lineStart: this.scanner.lineStart, 5060 start: start, 5061 end: this.scanner.index 5062 }; 5063 } 5064 // ... or . 5065 if (cp === 46) { 5066 var n1 = this.scanner.source.charCodeAt(this.scanner.index + 1); 5067 var n2 = this.scanner.source.charCodeAt(this.scanner.index + 2); 5068 var value = (n1 === 46 && n2 === 46) ? '...' : '.'; 5069 var start = this.scanner.index; 5070 this.scanner.index += value.length; 5071 return { 5072 type: 7 /* Punctuator */, 5073 value: value, 5074 lineNumber: this.scanner.lineNumber, 5075 lineStart: this.scanner.lineStart, 5076 start: start, 5077 end: this.scanner.index 5078 }; 5079 } 5080 // ` 5081 if (cp === 96) { 5082 // Only placeholder, since it will be rescanned as a real assignment expression. 5083 return { 5084 type: 10 /* Template */, 5085 value: '', 5086 lineNumber: this.scanner.lineNumber, 5087 lineStart: this.scanner.lineStart, 5088 start: this.scanner.index, 5089 end: this.scanner.index 5090 }; 5091 } 5092 // Identifer can not contain backslash (char code 92). 5093 if (character_1.Character.isIdentifierStart(cp) && (cp !== 92)) { 5094 var start = this.scanner.index; 5095 ++this.scanner.index; 5096 while (!this.scanner.eof()) { 5097 var ch = this.scanner.source.charCodeAt(this.scanner.index); 5098 if (character_1.Character.isIdentifierPart(ch) && (ch !== 92)) { 5099 ++this.scanner.index; 5100 } 5101 else if (ch === 45) { 5102 // Hyphen (char code 45) can be part of an identifier. 5103 ++this.scanner.index; 5104 } 5105 else { 5106 break; 5107 } 5108 } 5109 var id = this.scanner.source.slice(start, this.scanner.index); 5110 return { 5111 type: 100 /* Identifier */, 5112 value: id, 5113 lineNumber: this.scanner.lineNumber, 5114 lineStart: this.scanner.lineStart, 5115 start: start, 5116 end: this.scanner.index 5117 }; 5118 } 5119 return this.scanner.lex(); 5120 }; 5121 JSXParser.prototype.nextJSXToken = function () { 5122 this.collectComments(); 5123 this.startMarker.index = this.scanner.index; 5124 this.startMarker.line = this.scanner.lineNumber; 5125 this.startMarker.column = this.scanner.index - this.scanner.lineStart; 5126 var token = this.lexJSX(); 5127 this.lastMarker.index = this.scanner.index; 5128 this.lastMarker.line = this.scanner.lineNumber; 5129 this.lastMarker.column = this.scanner.index - this.scanner.lineStart; 5130 if (this.config.tokens) { 5131 this.tokens.push(this.convertToken(token)); 5132 } 5133 return token; 5134 }; 5135 JSXParser.prototype.nextJSXText = function () { 5136 this.startMarker.index = this.scanner.index; 5137 this.startMarker.line = this.scanner.lineNumber; 5138 this.startMarker.column = this.scanner.index - this.scanner.lineStart; 5139 var start = this.scanner.index; 5140 var text = ''; 5141 while (!this.scanner.eof()) { 5142 var ch = this.scanner.source[this.scanner.index]; 5143 if (ch === '{' || ch === '<') { 5144 break; 5145 } 5146 ++this.scanner.index; 5147 text += ch; 5148 if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { 5149 ++this.scanner.lineNumber; 5150 if (ch === '\r' && this.scanner.source[this.scanner.index] === '\n') { 5151 ++this.scanner.index; 5152 } 5153 this.scanner.lineStart = this.scanner.index; 5154 } 5155 } 5156 this.lastMarker.index = this.scanner.index; 5157 this.lastMarker.line = this.scanner.lineNumber; 5158 this.lastMarker.column = this.scanner.index - this.scanner.lineStart; 5159 var token = { 5160 type: 101 /* Text */, 5161 value: text, 5162 lineNumber: this.scanner.lineNumber, 5163 lineStart: this.scanner.lineStart, 5164 start: start, 5165 end: this.scanner.index 5166 }; 5167 if ((text.length > 0) && this.config.tokens) { 5168 this.tokens.push(this.convertToken(token)); 5169 } 5170 return token; 5171 }; 5172 JSXParser.prototype.peekJSXToken = function () { 5173 var state = this.scanner.saveState(); 5174 this.scanner.scanComments(); 5175 var next = this.lexJSX(); 5176 this.scanner.restoreState(state); 5177 return next; 5178 }; 5179 // Expect the next JSX token to match the specified punctuator. 5180 // If not, an exception will be thrown. 5181 JSXParser.prototype.expectJSX = function (value) { 5182 var token = this.nextJSXToken(); 5183 if (token.type !== 7 /* Punctuator */ || token.value !== value) { 5184 this.throwUnexpectedToken(token); 5185 } 5186 }; 5187 // Return true if the next JSX token matches the specified punctuator. 5188 JSXParser.prototype.matchJSX = function (value) { 5189 var next = this.peekJSXToken(); 5190 return next.type === 7 /* Punctuator */ && next.value === value; 5191 }; 5192 JSXParser.prototype.parseJSXIdentifier = function () { 5193 var node = this.createJSXNode(); 5194 var token = this.nextJSXToken(); 5195 if (token.type !== 100 /* Identifier */) { 5196 this.throwUnexpectedToken(token); 5197 } 5198 return this.finalize(node, new JSXNode.JSXIdentifier(token.value)); 5199 }; 5200 JSXParser.prototype.parseJSXElementName = function () { 5201 var node = this.createJSXNode(); 5202 var elementName = this.parseJSXIdentifier(); 5203 if (this.matchJSX(':')) { 5204 var namespace = elementName; 5205 this.expectJSX(':'); 5206 var name_1 = this.parseJSXIdentifier(); 5207 elementName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_1)); 5208 } 5209 else if (this.matchJSX('.')) { 5210 while (this.matchJSX('.')) { 5211 var object = elementName; 5212 this.expectJSX('.'); 5213 var property = this.parseJSXIdentifier(); 5214 elementName = this.finalize(node, new JSXNode.JSXMemberExpression(object, property)); 5215 } 5216 } 5217 return elementName; 5218 }; 5219 JSXParser.prototype.parseJSXAttributeName = function () { 5220 var node = this.createJSXNode(); 5221 var attributeName; 5222 var identifier = this.parseJSXIdentifier(); 5223 if (this.matchJSX(':')) { 5224 var namespace = identifier; 5225 this.expectJSX(':'); 5226 var name_2 = this.parseJSXIdentifier(); 5227 attributeName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_2)); 5228 } 5229 else { 5230 attributeName = identifier; 5231 } 5232 return attributeName; 5233 }; 5234 JSXParser.prototype.parseJSXStringLiteralAttribute = function () { 5235 var node = this.createJSXNode(); 5236 var token = this.nextJSXToken(); 5237 if (token.type !== 8 /* StringLiteral */) { 5238 this.throwUnexpectedToken(token); 5239 } 5240 var raw = this.getTokenRaw(token); 5241 return this.finalize(node, new Node.Literal(token.value, raw)); 5242 }; 5243 JSXParser.prototype.parseJSXExpressionAttribute = function () { 5244 var node = this.createJSXNode(); 5245 this.expectJSX('{'); 5246 this.finishJSX(); 5247 if (this.match('}')) { 5248 this.tolerateError('JSX attributes must only be assigned a non-empty expression'); 5249 } 5250 var expression = this.parseAssignmentExpression(); 5251 this.reenterJSX(); 5252 return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); 5253 }; 5254 JSXParser.prototype.parseJSXAttributeValue = function () { 5255 return this.matchJSX('{') ? this.parseJSXExpressionAttribute() : 5256 this.matchJSX('<') ? this.parseJSXElement() : this.parseJSXStringLiteralAttribute(); 5257 }; 5258 JSXParser.prototype.parseJSXNameValueAttribute = function () { 5259 var node = this.createJSXNode(); 5260 var name = this.parseJSXAttributeName(); 5261 var value = null; 5262 if (this.matchJSX('=')) { 5263 this.expectJSX('='); 5264 value = this.parseJSXAttributeValue(); 5265 } 5266 return this.finalize(node, new JSXNode.JSXAttribute(name, value)); 5267 }; 5268 JSXParser.prototype.parseJSXSpreadAttribute = function () { 5269 var node = this.createJSXNode(); 5270 this.expectJSX('{'); 5271 this.expectJSX('...'); 5272 this.finishJSX(); 5273 var argument = this.parseAssignmentExpression(); 5274 this.reenterJSX(); 5275 return this.finalize(node, new JSXNode.JSXSpreadAttribute(argument)); 5276 }; 5277 JSXParser.prototype.parseJSXAttributes = function () { 5278 var attributes = []; 5279 while (!this.matchJSX('/') && !this.matchJSX('>')) { 5280 var attribute = this.matchJSX('{') ? this.parseJSXSpreadAttribute() : 5281 this.parseJSXNameValueAttribute(); 5282 attributes.push(attribute); 5283 } 5284 return attributes; 5285 }; 5286 JSXParser.prototype.parseJSXOpeningElement = function () { 5287 var node = this.createJSXNode(); 5288 this.expectJSX('<'); 5289 var name = this.parseJSXElementName(); 5290 var attributes = this.parseJSXAttributes(); 5291 var selfClosing = this.matchJSX('/'); 5292 if (selfClosing) { 5293 this.expectJSX('/'); 5294 } 5295 this.expectJSX('>'); 5296 return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); 5297 }; 5298 JSXParser.prototype.parseJSXBoundaryElement = function () { 5299 var node = this.createJSXNode(); 5300 this.expectJSX('<'); 5301 if (this.matchJSX('/')) { 5302 this.expectJSX('/'); 5303 var name_3 = this.parseJSXElementName(); 5304 this.expectJSX('>'); 5305 return this.finalize(node, new JSXNode.JSXClosingElement(name_3)); 5306 } 5307 var name = this.parseJSXElementName(); 5308 var attributes = this.parseJSXAttributes(); 5309 var selfClosing = this.matchJSX('/'); 5310 if (selfClosing) { 5311 this.expectJSX('/'); 5312 } 5313 this.expectJSX('>'); 5314 return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); 5315 }; 5316 JSXParser.prototype.parseJSXEmptyExpression = function () { 5317 var node = this.createJSXChildNode(); 5318 this.collectComments(); 5319 this.lastMarker.index = this.scanner.index; 5320 this.lastMarker.line = this.scanner.lineNumber; 5321 this.lastMarker.column = this.scanner.index - this.scanner.lineStart; 5322 return this.finalize(node, new JSXNode.JSXEmptyExpression()); 5323 }; 5324 JSXParser.prototype.parseJSXExpressionContainer = function () { 5325 var node = this.createJSXNode(); 5326 this.expectJSX('{'); 5327 var expression; 5328 if (this.matchJSX('}')) { 5329 expression = this.parseJSXEmptyExpression(); 5330 this.expectJSX('}'); 5331 } 5332 else { 5333 this.finishJSX(); 5334 expression = this.parseAssignmentExpression(); 5335 this.reenterJSX(); 5336 } 5337 return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); 5338 }; 5339 JSXParser.prototype.parseJSXChildren = function () { 5340 var children = []; 5341 while (!this.scanner.eof()) { 5342 var node = this.createJSXChildNode(); 5343 var token = this.nextJSXText(); 5344 if (token.start < token.end) { 5345 var raw = this.getTokenRaw(token); 5346 var child = this.finalize(node, new JSXNode.JSXText(token.value, raw)); 5347 children.push(child); 5348 } 5349 if (this.scanner.source[this.scanner.index] === '{') { 5350 var container = this.parseJSXExpressionContainer(); 5351 children.push(container); 5352 } 5353 else { 5354 break; 5355 } 5356 } 5357 return children; 5358 }; 5359 JSXParser.prototype.parseComplexJSXElement = function (el) { 5360 var stack = []; 5361 while (!this.scanner.eof()) { 5362 el.children = el.children.concat(this.parseJSXChildren()); 5363 var node = this.createJSXChildNode(); 5364 var element = this.parseJSXBoundaryElement(); 5365 if (element.type === jsx_syntax_1.JSXSyntax.JSXOpeningElement) { 5366 var opening = element; 5367 if (opening.selfClosing) { 5368 var child = this.finalize(node, new JSXNode.JSXElement(opening, [], null)); 5369 el.children.push(child); 5370 } 5371 else { 5372 stack.push(el); 5373 el = { node: node, opening: opening, closing: null, children: [] }; 5374 } 5375 } 5376 if (element.type === jsx_syntax_1.JSXSyntax.JSXClosingElement) { 5377 el.closing = element; 5378 var open_1 = getQualifiedElementName(el.opening.name); 5379 var close_1 = getQualifiedElementName(el.closing.name); 5380 if (open_1 !== close_1) { 5381 this.tolerateError('Expected corresponding JSX closing tag for %0', open_1); 5382 } 5383 if (stack.length > 0) { 5384 var child = this.finalize(el.node, new JSXNode.JSXElement(el.opening, el.children, el.closing)); 5385 el = stack[stack.length - 1]; 5386 el.children.push(child); 5387 stack.pop(); 5388 } 5389 else { 5390 break; 5391 } 5392 } 5393 } 5394 return el; 5395 }; 5396 JSXParser.prototype.parseJSXElement = function () { 5397 var node = this.createJSXNode(); 5398 var opening = this.parseJSXOpeningElement(); 5399 var children = []; 5400 var closing = null; 5401 if (!opening.selfClosing) { 5402 var el = this.parseComplexJSXElement({ node: node, opening: opening, closing: closing, children: children }); 5403 children = el.children; 5404 closing = el.closing; 5405 } 5406 return this.finalize(node, new JSXNode.JSXElement(opening, children, closing)); 5407 }; 5408 JSXParser.prototype.parseJSXRoot = function () { 5409 // Pop the opening '<' added from the lookahead. 5410 if (this.config.tokens) { 5411 this.tokens.pop(); 5412 } 5413 this.startJSX(); 5414 var element = this.parseJSXElement(); 5415 this.finishJSX(); 5416 return element; 5417 }; 5418 JSXParser.prototype.isStartOfExpression = function () { 5419 return _super.prototype.isStartOfExpression.call(this) || this.match('<'); 5420 }; 5421 return JSXParser; 5422 }(parser_1.Parser)); 5423 exports.JSXParser = JSXParser; 5424 5425 5426 /***/ }, 5427 /* 4 */
5428 /***/ function(module, exports) { 5429 5430 "use strict"; 5431 Object.defineProperty(exports, "__esModule", { value: true }); 5432 // See also tools/generate-unicode-regex.js. 5433 var Regex = { 5434 // Unicode v8.0.0 NonAsciiIdentifierStart: 5435 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\uFB
5435D3-\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]/, 5436 // Unicode v8.0.0 NonAsciiIdentifierPart: 5437 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\uFB
5437D3-\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]/ 5438 }; 5439 exports.Character = { 5440 /* tslint:disable:no-bitwise */ 5441 fromCodePoint: function (cp) { 5442 return (cp < 0x10000) ? String.fromCharCode(cp) : 5443 String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) + 5444 String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023)); 5445 }, 5446 // https://tc39.github.io/ecma262/#sec-white-space 5447 isWhiteSpace: function (cp) { 5448 return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) || 5449 (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0); 5450 }, 5451 // https://tc39.github.io/ecma262/#sec-line-terminators 5452 isLineTerminator: function (cp) { 5453 return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029); 5454 }, 5455 // https://tc39.github.io/ecma262/#sec-names-and-keywords 5456 isIdentifierStart: function (cp) { 5457 return (cp === 0x24) || (cp === 0x5F) || 5458 (cp >= 0x41 && cp <= 0x5A) || 5459 (cp >= 0x61 && cp <= 0x7A) || 5460 (cp === 0x5C) || 5461 ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(exports.Character.fromCodePoint(c
vendor: 7,169 bytes, lines 5461-5592
5461p))); 5462 }, 5463 isIdentifierPart: function (cp) { 5464 return (cp === 0x24) || (cp === 0x5F) || 5465 (cp >= 0x41 && cp <= 0x5A) || 5466 (cp >= 0x61 && cp <= 0x7A) || 5467 (cp >= 0x30 && cp <= 0x39) || 5468 (cp === 0x5C) || 5469 ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(exports.Character.fromCodePoint(cp))); 5470 }, 5471 // https://tc39.github.io/ecma262/#sec-literals-numeric-literals 5472 isDecimalDigit: function (cp) { 5473 return (cp >= 0x30 && cp <= 0x39); // 0..9 5474 }, 5475 isHexDigit: function (cp) { 5476 return (cp >= 0x30 && cp <= 0x39) || 5477 (cp >= 0x41 && cp <= 0x46) || 5478 (cp >= 0x61 && cp <= 0x66); // a..f 5479 }, 5480 isOctalDigit: function (cp) { 5481 return (cp >= 0x30 && cp <= 0x37); // 0..7 5482 } 5483 }; 5484 5485 5486 /***/ }, 5487 /* 5 */ 5488 /***/ function(module, exports, __webpack_require__) { 5489 5490 "use strict"; 5491 Object.defineProperty(exports, "__esModule", { value: true }); 5492 var jsx_syntax_1 = __webpack_require__(6); 5493 /* tslint:disable:max-classes-per-file */ 5494 var JSXClosingElement = (function () { 5495 function JSXClosingElement(name) { 5496 this.type = jsx_syntax_1.JSXSyntax.JSXClosingElement; 5497 this.name = name; 5498 } 5499 return JSXClosingElement; 5500 }()); 5501 exports.JSXClosingElement = JSXClosingElement; 5502 var JSXElement = (function () { 5503 function JSXElement(openingElement, children, closingElement) { 5504 this.type = jsx_syntax_1.JSXSyntax.JSXElement; 5505 this.openingElement = openingElement; 5506 this.children = children; 5507 this.closingElement = closingElement; 5508 } 5509 return JSXElement; 5510 }()); 5511 exports.JSXElement = JSXElement; 5512 var JSXEmptyExpression = (function () { 5513 function JSXEmptyExpression() { 5514 this.type = jsx_syntax_1.JSXSyntax.JSXEmptyExpression; 5515 } 5516 return JSXEmptyExpression; 5517 }()); 5518 exports.JSXEmptyExpression = JSXEmptyExpression; 5519 var JSXExpressionContainer = (function () { 5520 function JSXExpressionContainer(expression) { 5521 this.type = jsx_syntax_1.JSXSyntax.JSXExpressionContainer; 5522 this.expression = expression; 5523 } 5524 return JSXExpressionContainer; 5525 }()); 5526 exports.JSXExpressionContainer = JSXExpressionContainer; 5527 var JSXIdentifier = (function () { 5528 function JSXIdentifier(name) { 5529 this.type = jsx_syntax_1.JSXSyntax.JSXIdentifier; 5530 this.name = name; 5531 } 5532 return JSXIdentifier; 5533 }()); 5534 exports.JSXIdentifier = JSXIdentifier; 5535 var JSXMemberExpression = (function () { 5536 function JSXMemberExpression(object, property) { 5537 this.type = jsx_syntax_1.JSXSyntax.JSXMemberExpression; 5538 this.object = object; 5539 this.property = property; 5540 } 5541 return JSXMemberExpression; 5542 }()); 5543 exports.JSXMemberExpression = JSXMemberExpression; 5544 var JSXAttribute = (function () { 5545 function JSXAttribute(name, value) { 5546 this.type = jsx_syntax_1.JSXSyntax.JSXAttribute; 5547 this.name = name; 5548 this.value = value; 5549 } 5550 return JSXAttribute; 5551 }()); 5552 exports.JSXAttribute = JSXAttribute; 5553 var JSXNamespacedName = (function () { 5554 function JSXNamespacedName(namespace, name) { 5555 this.type = jsx_syntax_1.JSXSyntax.JSXNamespacedName; 5556 this.namespace = namespace; 5557 this.name = name; 5558 } 5559 return JSXNamespacedName; 5560 }()); 5561 exports.JSXNamespacedName = JSXNamespacedName; 5562 var JSXOpeningElement = (function () { 5563 function JSXOpeningElement(name, selfClosing, attributes) { 5564 this.type = jsx_syntax_1.JSXSyntax.JSXOpeningElement; 5565 this.name = name; 5566 this.selfClosing = selfClosing; 5567 this.attributes = attributes; 5568 } 5569 return JSXOpeningElement; 5570 }()); 5571 exports.JSXOpeningElement = JSXOpeningElement; 5572 var JSXSpreadAttribute = (function () { 5573 function JSXSpreadAttribute(argument) { 5574 this.type = jsx_syntax_1.JSXSyntax.JSXSpreadAttribute; 5575 this.argument = argument; 5576 } 5577 return JSXSpreadAttribute; 5578 }()); 5579 exports.JSXSpreadAttribute = JSXSpreadAttribute; 5580 var JSXText = (function () { 5581 function JSXText(value, raw) { 5582 this.type = jsx_syntax_1.JSXSyntax.JSXText; 5583 this.value = value; 5584 this.raw = raw; 5585 } 5586 return JSXText; 5587 }()); 5588 exports.JSXText = JSXText; 5589 5590 5591 /***/ }, 5592 /* 6 */
5593 /***/ function(module, exports) { 5594 5595 "use strict"; 5596 Object.defineProperty(exports, "__esModule", { value: true }); 5597 exports.JSXSyntax = { 5598 JSXAttribute: 'JSXAttribute', 5599 JSXClosingElement: 'JSXClosingElement', 5600 JSXElement: 'JSXElement', 5601 JSXEmptyExpression: 'JSXEmptyExpression', 5602 JSXExpressionContainer: 'JSXExpressionContainer', 5603 JSXIdentifier: 'JSXIdentifier', 5604 JSXMemberExpression: 'JSXMemberExpression', 5605 JSXNamespacedName: 'JSXNamespacedName', 5606 JSXOpeningElement: 'JSXOpeningElement', 5607 JSXSpreadAttribute: 'JSXSpreadAttribute', 5608 JSXText: 'JSXText' 5609 }; 5610 5611 5612 /***/ }, 5613 /* 7 */ 5614 /***/ function(module, exports, __webpack_require__) { 5615 5616 "use strict"; 5617 Object.defineProperty(exports, "__esModule", { value: true }); 5618 var syntax_1 = __webpack_require__(2); 5619 /* tslint:disable:max-classes-per-file */ 5620 var ArrayExpression = (function () { 5621 function ArrayExpression(elements) { 5622 this.type = syntax_1.Syntax.ArrayExpression; 5623 this.elements = elements; 5624 } 5625 return ArrayExpression; 5626 }()); 5627 exports.ArrayExpression = ArrayExpression; 5628 var ArrayPattern = (function () { 5629 function ArrayPattern(elements) { 5630 this.type = syntax_1.Syntax.ArrayPattern; 5631 this.elements = elements; 5632 } 5633 return ArrayPattern; 5634 }()); 5635 exports.ArrayPattern = ArrayPattern; 5636 var ArrowFunctionExpression = (function () { 5637 function ArrowFunctionExpression(params, body, expression) { 5638 this.type = syntax_1.Syntax.ArrowFunctionExpression; 5639 this.id = null; 5640 this.params = params; 5641 this.body = body; 5642 this.generator = false; 5643 this.expression = expression; 5644 this.async = false; 5645 } 5646 return ArrowFunctionExpression; 5647 }()); 5648 exports.ArrowFunctionExpression = ArrowFunctionExpression; 5649 var AssignmentExpression = (function () { 5650 function AssignmentExpression(operator, left, right) { 5651 this.type = syntax_1.Syntax.AssignmentExpression; 5652 this.operator = operator; 5653 this.left = left; 5654 this.right = right; 5655 } 5656 return AssignmentExpression; 5657 }()); 5658 exports.AssignmentExpression = AssignmentExpression; 5659 var AssignmentPattern = (function () { 5660 function AssignmentPattern(left, right) { 5661 this.type = syntax_1.Syntax.AssignmentPattern; 5662 this.left = left; 5663 this.right = right; 5664 } 5665 return AssignmentPattern; 5666 }()); 5667 exports.AssignmentPattern = AssignmentPattern; 5668 var AsyncArrowFunctionExpression = (function () { 5669 function AsyncArrowFunctionExpression(params, body, expression) { 5670 this.type = syntax_1.Syntax.ArrowFunctionExpression; 5671 this.id = null; 5672 this.params = params; 5673 this.body = body; 5674 this.generator = false;
5675 this.expression = expression; 5676 this.async = true; 5677 } 5678 return AsyncArrowFunctionExpression; 5679 }()); 5680 exports.AsyncArrowFunctionExpression = AsyncArrowFunctionExpression; 5681 var AsyncFunctionDeclaration = (function () { 5682 function AsyncFunctionDeclaration(id, params, body) { 5683 this.type = syntax_1.Syntax.FunctionDeclaration; 5684 this.id = id; 5685 this.params = params; 5686 this.body = body; 5687 this.generator = false; 5688 this.expression = false; 5689 this.async = true; 5690 } 5691 return AsyncFunctionDeclaration; 5692 }()); 5693 exports.AsyncFunctionDeclaration = AsyncFunctionDeclaration; 5694 var AsyncFunctionExpression = (function () { 5695 function AsyncFunctionExpression(id, params, body) { 5696 this.type = syntax_1.Syntax.FunctionExpression; 5697 this.id = id; 5698 this.params = params; 5699 this.body = body; 5700 this.generator = false; 5701 this.expression = false; 5702 this.async = true; 5703 } 5704 return AsyncFunctionExpression; 5705 }()); 5706 exports.AsyncFunctionExpression = AsyncFunctionExpression; 5707 var AwaitExpression = (function () { 5708 function AwaitExpression(argument) { 5709 this.type = syntax_1.Syntax.AwaitExpression; 5710 this.argument = argument; 5711 } 5712 return AwaitExpression; 5713 }()); 5714 exports.AwaitExpression = AwaitExpression; 5715 var BinaryExpression = (function () { 5716 function BinaryExpression(operator, left, right) { 5717 var logical = (operator === '||' || operator === '&&'); 5718 this.type = logical ? syntax_1.Syntax.LogicalExpression : syntax_1.Syntax.BinaryExpression; 5719 this.operator = operator; 5720 this.left = left; 5721 this.right = right; 5722 } 5723 return BinaryExpression; 5724 }()); 5725 exports.BinaryExpression = BinaryExpression; 5726 var BlockStatement = (function () { 5727 function BlockStatement(body) { 5728 this.type = syntax_1.Syntax.BlockStatement; 5729 this.body = body; 5730 } 5731 return BlockStatement; 5732 }()); 5733 exports.BlockStatement = BlockStatement; 5734 var BreakStatement = (function () { 5735 function BreakStatement(label) { 5736 this.type = syntax_1.Syntax.BreakStatement; 5737 this.label = label; 5738 } 5739 return BreakStatement; 5740 }()); 5741 exports.BreakStatement = BreakStatement; 5742 var CallExpression = (function () { 5743 function CallExpression(callee, args) { 5744 this.type = syntax_1.Syntax.CallExpression; 5745 this.callee = callee; 5746 this.arguments = args; 5747 } 5748 return CallExpression; 5749 }()); 5750 exports.CallExpression = CallExpression; 5751 var CatchClause = (function () { 5752 function CatchClause(param, body) { 5753 this.type = syntax_1.Syntax.CatchClause; 5754 this.param = param; 5755 this.body = body; 5756 } 5757 return CatchClause; 5758 }()); 5759 exports.CatchClause = CatchClause; 5760 var ClassBody = (function () { 5761 function ClassBody(body) { 5762 this.type = syntax_1.Syntax.ClassBody; 5763 this.body = body; 5764 } 5765 return ClassBody; 5766 }()); 5767 exports.ClassBody = ClassBody; 5768 var ClassDeclaration = (function () { 5769 function ClassDeclaration(id, superClass, body) { 5770 this.type = syntax_1.Syntax.ClassDeclaration; 5771 this.id = id; 5772 this.superClass = superClass; 5773 this.body = body; 5774 } 5775 return ClassDeclaration; 5776 }()); 5777 exports.ClassDeclaration = ClassDeclaration; 5778 var ClassExpression = (function () { 5779 function ClassExpression(id, superClass, body) { 5780 this.type = syntax_1.Syntax.ClassExpression; 5781 this.id = id; 5782 this.superClass = superClass; 5783 this.body = body; 5784 } 5785 return ClassExpression; 5786 }()); 5787 exports.ClassExpression = ClassExpression; 5788 var ComputedMemberExpression = (function () { 5789 function ComputedMemberExpression(object, property) { 5790 this.type = syntax_1.Syntax.MemberExpression; 5791 this.computed = true; 5792 this.object = object; 5793 this.property = property; 5794 } 5795 return ComputedMemberExpression; 5796 }()); 5797 exports.ComputedMemberExpression = ComputedMemberExpression; 5798 var ConditionalExpression = (function () { 5799 function ConditionalExpression(test, consequent, alternate) { 5800 this.type = syntax_1.Syntax.ConditionalExpression; 5801 this.test = test; 5802 this.consequent = consequent; 5803 this.alternate = alternate; 5804 } 5805 return ConditionalExpression; 5806 }()); 5807 exports.ConditionalExpression = ConditionalExpression; 5808 var ContinueStatement = (function () {
5809 function ContinueStatement(label) { 5810 this.type = syntax_1.Syntax.ContinueStatement; 5811 this.label = label; 5812 } 5813 return ContinueStatement; 5814 }()); 5815 exports.ContinueStatement = ContinueStatement; 5816 var DebuggerStatement = (function () { 5817 function DebuggerStatement() { 5818 this.type = syntax_1.Syntax.DebuggerStatement; 5819 } 5820 return DebuggerStatement; 5821 }()); 5822 exports.DebuggerStatement = DebuggerStatement; 5823 var Directive = (function () { 5824 function Directive(expression, directive) { 5825 this.type = syntax_1.Syntax.ExpressionStatement; 5826 this.expression = expression; 5827 this.directive = directive; 5828 } 5829 return Directive; 5830 }()); 5831 exports.Directive = Directive; 5832 var DoWhileStatement = (function () { 5833 function DoWhileStatement(body, test) { 5834 this.type = syntax_1.Syntax.DoWhileStatement; 5835 this.body = body; 5836 this.test = test; 5837 } 5838 return DoWhileStatement; 5839 }()); 5840 exports.DoWhileStatement = DoWhileStatement; 5841 var EmptyStatement = (function () { 5842 function EmptyStatement() { 5843 this.type = syntax_1.Syntax.EmptyStatement; 5844 } 5845 return EmptyStatement; 5846 }()); 5847 exports.EmptyStatement = EmptyStatement; 5848 var ExportAllDeclaration = (function () { 5849 function ExportAllDeclaration(source) { 5850 this.type = syntax_1.Syntax.ExportAllDeclaration; 5851 this.source = source; 5852 } 5853 return ExportAllDeclaration; 5854 }()); 5855 exports.ExportAllDeclaration = ExportAllDeclaration; 5856 var ExportDefaultDeclaration = (function () { 5857 function ExportDefaultDeclaration(declaration) { 5858 this.type = syntax_1.Syntax.ExportDefaultDeclaration; 5859 this.declaration = declaration; 5860 } 5861 return ExportDefaultDeclaration; 5862 }()); 5863 exports.ExportDefaultDeclaration = ExportDefaultDeclaration; 5864 var ExportNamedDeclaration = (function () { 5865 function ExportNamedDeclaration(declaration, specifiers, source) { 5866 this.type = syntax_1.Syntax.ExportNamedDeclaration; 5867 this.declaration = declaration; 5868 this.specifiers = specifiers; 5869 this.source = source; 5870 } 5871 return ExportNamedDeclaration; 5872 }()); 5873 exports.ExportNamedDeclaration = ExportNamedDeclaration; 5874 var ExportSpecifier = (function () { 5875 function ExportSpecifier(local, exported) { 5876 this.type = syntax_1.Syntax.ExportSpecifier; 5877 this.exported = exported; 5878 this.local = local; 5879 } 5880 return ExportSpecifier; 5881 }()); 5882 exports.ExportSpecifier = ExportSpecifier; 5883 var ExpressionStatement = (function () {
5884 function ExpressionStatement(expression) { 5885 this.type = syntax_1.Syntax.ExpressionStatement; 5886 this.expression = expression; 5887 } 5888 return ExpressionStatement; 5889 }()); 5890 exports.ExpressionStatement = ExpressionStatement; 5891 var ForInStatement = (function () { 5892 function ForInStatement(left, right, body) { 5893 this.type = syntax_1.Syntax.ForInStatement; 5894 this.left = left; 5895 this.right = right; 5896 this.body = body; 5897 this.each = false; 5898 } 5899 return ForInStatement; 5900 }()); 5901 exports.ForInStatement = ForInStatement; 5902 var ForOfStatement = (function () { 5903 function ForOfStatement(left, right, body) { 5904 this.type = syntax_1.Syntax.ForOfStatement; 5905 this.left = left; 5906 this.right = right; 5907 this.body = body; 5908 } 5909 return ForOfStatement; 5910 }()); 5911 exports.ForOfStatement = ForOfStatement; 5912 var ForStatement = (function () { 5913 function ForStatement(init, test, update, body) { 5914 this.type = syntax_1.Syntax.ForStatement; 5915 this.init = init; 5916 this.test = test; 5917 this.update = update; 5918 this.body = body; 5919 } 5920 return ForStatement; 5921 }()); 5922 exports.ForStatement = ForStatement; 5923 var FunctionDeclaration = (function () { 5924 function FunctionDeclaration(id, params, body, generator) { 5925 this.type = syntax_1.Syntax.FunctionDeclaration; 5926 this.id = id; 5927 this.params = params; 5928 this.body = body; 5929 this.generator = generator; 5930 this.expression = false; 5931 this.async = false; 5932 } 5933 return FunctionDeclaration; 5934 }()); 5935 exports.FunctionDeclaration = FunctionDeclaration; 5936 var FunctionExpression = (function () { 5937 function FunctionExpression(id, params, body, generator) { 5938 this.type = syntax_1.Syntax.FunctionExpression; 5939 this.id = id; 5940 this.params = params; 5941 this.body = body; 5942 this.generator = generator; 5943 this.expression = false; 5944 this.async = false; 5945 } 5946 return FunctionExpression; 5947 }()); 5948 exports.FunctionExpression = FunctionExpression; 5949 var Identifier = (function () { 5950 function Identifier(name) { 5951 this.type = syntax_1.Syntax.Identifier; 5952 this.name = name; 5953 } 5954 return Identifier; 5955 }()); 5956 exports.Identifier = Identifier; 5957 var IfStatement = (function () {
5958 function IfStatement(test, consequent, alternate) { 5959 this.type = syntax_1.Syntax.IfStatement; 5960 this.test = test; 5961 this.consequent = consequent; 5962 this.alternate = alternate; 5963 } 5964 return IfStatement; 5965 }()); 5966 exports.IfStatement = IfStatement; 5967 var ImportDeclaration = (function () { 5968 function ImportDeclaration(specifiers, source) { 5969 this.type = syntax_1.Syntax.ImportDeclaration; 5970 this.specifiers = specifiers; 5971 this.source = source; 5972 } 5973 return ImportDeclaration; 5974 }()); 5975 exports.ImportDeclaration = ImportDeclaration; 5976 var ImportDefaultSpecifier = (function () { 5977 function ImportDefaultSpecifier(local) { 5978 this.type = syntax_1.Syntax.ImportDefaultSpecifier; 5979 this.local = local; 5980 } 5981 return ImportDefaultSpecifier; 5982 }()); 5983 exports.ImportDefaultSpecifier = ImportDefaultSpecifier; 5984 var ImportNamespaceSpecifier = (function () { 5985 function ImportNamespaceSpecifier(local) { 5986 this.type = syntax_1.Syntax.ImportNamespaceSpecifier; 5987 this.local = local; 5988 } 5989 return ImportNamespaceSpecifier; 5990 }()); 5991 exports.ImportNamespaceSpecifier = ImportNamespaceSpecifier; 5992 var ImportSpecifier = (function () { 5993 function ImportSpecifier(local, imported) { 5994 this.type = syntax_1.Syntax.ImportSpecifier; 5995 this.local = local; 5996 this.imported = imported; 5997 } 5998 return ImportSpecifier; 5999 }()); 6000 exports.ImportSpecifier = ImportSpecifier; 6001 var LabeledStatement = (function () { 6002 function LabeledStatement(label, body) { 6003 this.type = syntax_1.Syntax.LabeledStatement; 6004 this.label = label; 6005 this.body = body; 6006 } 6007 return LabeledStatement; 6008 }()); 6009 exports.LabeledStatement = LabeledStatement; 6010 var Literal = (function () { 6011 function Literal(value, raw) { 6012 this.type = syntax_1.Syntax.Literal; 6013 this.value = value; 6014 this.raw = raw; 6015 } 6016 return Literal; 6017 }()); 6018 exports.Literal = Literal; 6019 var MetaProperty = (function () { 6020 function MetaProperty(meta, property) { 6021 this.type = syntax_1.Syntax.MetaProperty; 6022 this.meta = meta; 6023 this.property = property; 6024 } 6025 return MetaProperty; 6026 }()); 6027 exports.MetaProperty = MetaProperty; 6028 var MethodDefinition = (function () { 6029 function MethodDefinition(key, computed, value, kind, isStatic) { 6030 this.type = syntax_1.Syntax.MethodDefinition; 6031 this.key = key; 6032 this.computed = computed; 6033 this.value = value; 6034 this.kind = kind; 6035 this.static = isStatic; 6036 } 6037 return MethodDefinition; 6038 }()); 6039 exports.MethodDefinition = MethodDefinition; 6040 var Module = (function () { 6041 function Module(body) { 6042 this.type = syntax_1.Syntax.Program; 6043 this.body = body; 6044 this.sourceType = 'module';
6045 } 6046 return Module; 6047 }()); 6048 exports.Module = Module; 6049 var NewExpression = (function () { 6050 function NewExpression(callee, args) { 6051 this.type = syntax_1.Syntax.NewExpression; 6052 this.callee = callee; 6053 this.arguments = args; 6054 } 6055 return NewExpression; 6056 }()); 6057 exports.NewExpression = NewExpression; 6058 var ObjectExpression = (function () { 6059 function ObjectExpression(properties) { 6060 this.type = syntax_1.Syntax.ObjectExpression; 6061 this.properties = properties; 6062 } 6063 return ObjectExpression; 6064 }()); 6065 exports.ObjectExpression = ObjectExpression; 6066 var ObjectPattern = (function () { 6067 function ObjectPattern(properties) { 6068 this.type = syntax_1.Syntax.ObjectPattern; 6069 this.properties = properties; 6070 } 6071 return ObjectPattern; 6072 }()); 6073 exports.ObjectPattern = ObjectPattern; 6074 var Property = (function () { 6075 function Property(kind, key, computed, value, method, shorthand) { 6076 this.type = syntax_1.Syntax.Property; 6077 this.key = key; 6078 this.computed = computed; 6079 this.value = value; 6080 this.kind = kind; 6081 this.method = method; 6082 this.shorthand = shorthand; 6083 } 6084 return Property; 6085 }()); 6086 exports.Property = Property; 6087 var RegexLiteral = (function () { 6088 function RegexLiteral(value, raw, pattern, flags) { 6089 this.type = syntax_1.Syntax.Literal; 6090 this.value = value; 6091 this.raw = raw; 6092 this.regex = { pattern: pattern, flags: flags }; 6093 } 6094 return RegexLiteral; 6095 }()); 6096 exports.RegexLiteral = RegexLiteral; 6097 var RestElement = (function () { 6098 function RestElement(argument) { 6099 this.type = syntax_1.Syntax.RestElement; 6100 this.argument = argument; 6101 } 6102 return RestElement; 6103 }()); 6104 exports.RestElement = RestElement; 6105 var ReturnStatement = (function () {
6106 function ReturnStatement(argument) { 6107 this.type = syntax_1.Syntax.ReturnStatement; 6108 this.argument = argument; 6109 } 6110 return ReturnStatement; 6111 }()); 6112 exports.ReturnStatement = ReturnStatement; 6113 var Script = (function () { 6114 function Script(body) { 6115 this.type = syntax_1.Syntax.Program; 6116 this.body = body; 6117 this.sourceType = 'script'; 6118 } 6119 return Script; 6120 }()); 6121 exports.Script = Script; 6122 var SequenceExpression = (function () { 6123 function SequenceExpression(expressions) { 6124 this.type = syntax_1.Syntax.SequenceExpression; 6125 this.expressions = expressions; 6126 } 6127 return SequenceExpression; 6128 }()); 6129 exports.SequenceExpression = SequenceExpression; 6130 var SpreadElement = (function () { 6131 function SpreadElement(argument) { 6132 this.type = syntax_1.Syntax.SpreadElement; 6133 this.argument = argument; 6134 } 6135 return SpreadElement; 6136 }()); 6137 exports.SpreadElement = SpreadElement; 6138 var StaticMemberExpression = (function () { 6139 function StaticMemberExpression(object, property) { 6140 this.type = syntax_1.Syntax.MemberExpression; 6141 this.computed = false; 6142 this.object = object; 6143 this.property = property; 6144 } 6145 return StaticMemberExpression; 6146 }()); 6147 exports.StaticMemberExpression = StaticMemberExpression; 6148 var Super = (function () { 6149 function Super() { 6150 this.type = syntax_1.Syntax.Super; 6151 } 6152 return Super; 6153 }()); 6154 exports.Super = Super; 6155 var SwitchCase = (function () { 6156 function SwitchCase(test, consequent) { 6157 this.type = syntax_1.Syntax.SwitchCase; 6158 this.test = test; 6159 this.consequent = consequent; 6160 } 6161 return SwitchCase; 6162 }()); 6163 exports.SwitchCase = SwitchCase; 6164 var SwitchStatement = (function () { 6165 function SwitchStatement(discriminant, cases) { 6166 this.type = syntax_1.Syntax.SwitchStatement; 6167 this.discriminant = discriminant; 6168 this.cases = cases; 6169 } 6170 return SwitchStatement; 6171 }()); 6172 exports.SwitchStatement = SwitchStatement; 6173 var TaggedTemplateExpression = (function () { 6174 function TaggedTemplateExpression(tag, quasi) { 6175 this.type = syntax_1.Syntax.TaggedTemplateExpression; 6176 this.tag = tag; 6177 this.quasi = quasi; 6178 } 6179 return TaggedTemplateExpression; 6180 }()); 6181 exports.TaggedTemplateExpression = TaggedTemplateExpression; 6182 var TemplateElement = (function () { 6183 function TemplateElement(value, tail) { 6184 this.type = syntax_1.Syntax.TemplateElement; 6185 this.value = value; 6186 this.tail = tail; 6187 } 6188 return TemplateElement; 6189 }()); 6190 exports.TemplateElement = TemplateElement; 6191 var TemplateLiteral = (function () { 6192 function TemplateLiteral(quasis, expressions) { 6193 this.type = syntax_1.Syntax.TemplateLiteral; 6194 this.quasis = quasis; 6195 this.expressions = expressions; 6196 } 6197 return TemplateLiteral; 6198 }()); 6199 exports.TemplateLiteral = TemplateLiteral; 6200 var ThisExpression = (function () { 6201 function ThisExpression() { 6202 this.type = syntax_1.Syntax.ThisExpression; 6203 } 6204 return ThisExpression; 6205 }()); 6206 exports.ThisExpression = ThisExpression; 6207 var ThrowStatement = (function () {
vendor: 28,960 bytes, lines 6208-6683
6208 function ThrowStatement(argument) { 6209 this.type = syntax_1.Syntax.ThrowStatement; 6210 this.argument = argument; 6211 } 6212 return ThrowStatement; 6213 }()); 6214 exports.ThrowStatement = ThrowStatement; 6215 var TryStatement = (function () { 6216 function TryStatement(block, handler, finalizer) { 6217 this.type = syntax_1.Syntax.TryStatement; 6218 this.block = block; 6219 this.handler = handler; 6220 this.finalizer = finalizer; 6221 } 6222 return TryStatement; 6223 }()); 6224 exports.TryStatement = TryStatement; 6225 var UnaryExpression = (function () { 6226 function UnaryExpression(operator, argument) { 6227 this.type = syntax_1.Syntax.UnaryExpression; 6228 this.operator = operator; 6229 this.argument = argument; 6230 this.prefix = true; 6231 } 6232 return UnaryExpression; 6233 }()); 6234 exports.UnaryExpression = UnaryExpression; 6235 var UpdateExpression = (function () { 6236 function UpdateExpression(operator, argument, prefix) { 6237 this.type = syntax_1.Syntax.UpdateExpression; 6238 this.operator = operator; 6239 this.argument = argument; 6240 this.prefix = prefix; 6241 } 6242 return UpdateExpression; 6243 }()); 6244 exports.UpdateExpression = UpdateExpression; 6245 var VariableDeclaration = (function () { 6246 function VariableDeclaration(declarations, kind) { 6247 this.type = syntax_1.Syntax.VariableDeclaration; 6248 this.declarations = declarations; 6249 this.kind = kind; 6250 } 6251 return VariableDeclaration; 6252 }()); 6253 exports.VariableDeclaration = VariableDeclaration; 6254 var VariableDeclarator = (function () { 6255 function VariableDeclarator(id, init) { 6256 this.type = syntax_1.Syntax.VariableDeclarator; 6257 this.id = id; 6258 this.init = init; 6259 } 6260 return VariableDeclarator; 6261 }()); 6262 exports.VariableDeclarator = VariableDeclarator; 6263 var WhileStatement = (function () { 6264 function WhileStatement(test, body) { 6265 this.type = syntax_1.Syntax.WhileStatement; 6266 this.test = test; 6267 this.body = body; 6268 } 6269 return WhileStatement; 6270 }()); 6271 exports.WhileStatement = WhileStatement; 6272 var WithStatement = (function () { 6273 function WithStatement(object, body) { 6274 this.type = syntax_1.Syntax.WithStatement; 6275 this.object = object; 6276 this.body = body; 6277 } 6278 return WithStatement; 6279 }()); 6280 exports.WithStatement = WithStatement; 6281 var YieldExpression = (function () { 6282 function YieldExpression(argument, delegate) { 6283 this.type = syntax_1.Syntax.YieldExpression; 6284 this.argument = argument; 6285 this.delegate = delegate; 6286 } 6287 return YieldExpression; 6288 }()); 6289 exports.YieldExpression = YieldExpression; 6290 6291 6292 /***/ }, 6293 /* 8 */ 6294 /***/ function(module, exports, __webpack_require__) { 6295 6296 "use strict"; 6297 Object.defineProperty(exports, "__esModule", { value: true }); 6298 var assert_1 = __webpack_require__(9); 6299 var error_handler_1 = __webpack_require__(10); 6300 var messages_1 = __webpack_require__(11); 6301 var Node = __webpack_require__(7); 6302 var scanner_1 = __webpack_require__(12); 6303 var syntax_1 = __webpack_require__(2); 6304 var token_1 = __webpack_require__(13); 6305 var ArrowParameterPlaceHolder = 'ArrowParameterPlaceHolder'; 6306 var Parser = (function () { 6307 function Parser(code, options, delegate) { 6308 if (options === void 0) { options = {}; } 6309 this.config = { 6310 range: (typeof options.range === 'boolean') && options.range, 6311 loc: (typeof options.loc === 'boolean') && options.loc, 6312 source: null, 6313 tokens: (typeof options.tokens === 'boolean') && options.tokens, 6314 comment: (typeof options.comment === 'boolean') && options.comment, 6315 tolerant: (typeof options.tolerant === 'boolean') && options.tolerant 6316 }; 6317 if (this.config.loc && options.source && options.source !== null) { 6318 this.config.source = String(options.source); 6319 } 6320 this.delegate = delegate; 6321 this.errorHandler = new error_handler_1.ErrorHandler(); 6322 this.errorHandler.tolerant = this.config.tolerant; 6323 this.scanner = new scanner_1.Scanner(code, this.errorHandler); 6324 this.scanner.trackComment = this.config.comment; 6325 this.operatorPrecedence = { 6326 ')': 0, 6327 ';': 0, 6328 ',': 0, 6329 '=': 0, 6330 ']': 0, 6331 '||': 1, 6332 '&&': 2, 6333 '|': 3, 6334 '^': 4, 6335 '&': 5, 6336 '==': 6, 6337 '!=': 6, 6338 '===': 6, 6339 '!==': 6, 6340 '<': 7, 6341 '>': 7, 6342 '<=': 7, 6343 '>=': 7, 6344 '<<': 8, 6345 '>>': 8, 6346 '>>>': 8, 6347 '+': 9, 6348 '-': 9, 6349 '*': 11, 6350 '/': 11, 6351 '%': 11 6352 }; 6353 this.lookahead = { 6354 type: 2 /* EOF */, 6355 value: '', 6356 lineNumber: this.scanner.lineNumber, 6357 lineStart: 0, 6358 start: 0, 6359 end: 0 6360 }; 6361 this.hasLineTerminator = false; 6362 this.context = { 6363 isModule: false, 6364 await: false, 6365 allowIn: true, 6366 allowStrictDirective: true, 6367 allowYield: true, 6368 firstCoverInitializedNameError: null, 6369 isAssignmentTarget: false, 6370 isBindingElement: false, 6371 inFunctionBody: false, 6372 inIteration: false, 6373 inSwitch: false, 6374 labelSet: {}, 6375 strict: false 6376 }; 6377 this.tokens = []; 6378 this.startMarker = { 6379 index: 0, 6380 line: this.scanner.lineNumber, 6381 column: 0 6382 }; 6383 this.lastMarker = { 6384 index: 0, 6385 line: this.scanner.lineNumber, 6386 column: 0 6387 }; 6388 this.nextToken(); 6389 this.lastMarker = { 6390 index: this.scanner.index, 6391 line: this.scanner.lineNumber, 6392 column: this.scanner.index - this.scanner.lineStart 6393 }; 6394 } 6395 Parser.prototype.throwError = function (messageFormat) { 6396 var values = []; 6397 for (var _i = 1; _i < arguments.length; _i++) { 6398 values[_i - 1] = arguments[_i]; 6399 } 6400 var args = Array.prototype.slice.call(arguments, 1); 6401 var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { 6402 assert_1.assert(idx < args.length, 'Message reference must be in range'); 6403 return args[idx]; 6404 }); 6405 var index = this.lastMarker.index; 6406 var line = this.lastMarker.line; 6407 var column = this.lastMarker.column + 1; 6408 throw this.errorHandler.createError(index, line, column, msg); 6409 }; 6410 Parser.prototype.tolerateError = function (messageFormat) { 6411 var values = []; 6412 for (var _i = 1; _i < arguments.length; _i++) { 6413 values[_i - 1] = arguments[_i]; 6414 } 6415 var args = Array.prototype.slice.call(arguments, 1); 6416 var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { 6417 assert_1.assert(idx < args.length, 'Message reference must be in range'); 6418 return args[idx]; 6419 }); 6420 var index = this.lastMarker.index; 6421 var line = this.scanner.lineNumber; 6422 var column = this.lastMarker.column + 1; 6423 this.errorHandler.tolerateError(index, line, column, msg); 6424 }; 6425 // Throw an exception because of the token. 6426 Parser.prototype.unexpectedTokenError = function (token, message) { 6427 var msg = message || messages_1.Messages.UnexpectedToken; 6428 var value; 6429 if (token) { 6430 if (!message) { 6431 msg = (token.type === 2 /* EOF */) ? messages_1.Messages.UnexpectedEOS : 6432 (token.type === 3 /* Identifier */) ? messages_1.Messages.UnexpectedIdentifier : 6433 (token.type === 6 /* NumericLiteral */) ? messages_1.Messages.UnexpectedNumber : 6434 (token.type === 8 /* StringLiteral */) ? messages_1.Messages.UnexpectedString : 6435 (token.type === 10 /* Template */) ? messages_1.Messages.UnexpectedTemplate : 6436 messages_1.Messages.UnexpectedToken; 6437 if (token.type === 4 /* Keyword */) { 6438 if (this.scanner.isFutureReservedWord(token.value)) { 6439 msg = messages_1.Messages.UnexpectedReserved; 6440 } 6441 else if (this.context.strict && this.scanner.isStrictModeReservedWord(token.value)) { 6442 msg = messages_1.Messages.StrictReservedWord; 6443 } 6444 } 6445 } 6446 value = token.value; 6447 } 6448 else { 6449 value = 'ILLEGAL'; 6450 } 6451 msg = msg.replace('%0', value); 6452 if (token && typeof token.lineNumber === 'number') { 6453 var index = token.start; 6454 var line = token.lineNumber; 6455 var lastMarkerLineStart = this.lastMarker.index - this.lastMarker.column; 6456 var column = token.start - lastMarkerLineStart + 1; 6457 return this.errorHandler.createError(index, line, column, msg); 6458 } 6459 else { 6460 var index = this.lastMarker.index; 6461 var line = this.lastMarker.line; 6462 var column = this.lastMarker.column + 1; 6463 return this.errorHandler.createError(index, line, column, msg); 6464 } 6465 }; 6466 Parser.prototype.throwUnexpectedToken = function (token, message) { 6467 throw this.unexpectedTokenError(token, message); 6468 }; 6469 Parser.prototype.tolerateUnexpectedToken = function (token, message) { 6470 this.errorHandler.tolerate(this.unexpectedTokenError(token, message)); 6471 }; 6472 Parser.prototype.collectComments = function () { 6473 if (!this.config.comment) { 6474 this.scanner.scanComments(); 6475 } 6476 else { 6477 var comments = this.scanner.scanComments(); 6478 if (comments.length > 0 && this.delegate) { 6479 for (var i = 0; i < comments.length; ++i) { 6480 var e = comments[i]; 6481 var node = void 0; 6482 node = { 6483 type: e.multiLine ? 'BlockComment' : 'LineComment', 6484 value: this.scanner.source.slice(e.slice[0], e.slice[1]) 6485 }; 6486 if (this.config.range) { 6487 node.range = e.range; 6488 } 6489 if (this.config.loc) { 6490 node.loc = e.loc; 6491 } 6492 var metadata = { 6493 start: { 6494 line: e.loc.start.line, 6495 column: e.loc.start.column, 6496 offset: e.range[0] 6497 }, 6498 end: { 6499 line: e.loc.end.line, 6500 column: e.loc.end.column, 6501 offset: e.range[1] 6502 } 6503 }; 6504 this.delegate(node, metadata); 6505 } 6506 } 6507 } 6508 }; 6509 // From internal representation to an external structure 6510 Parser.prototype.getTokenRaw = function (token) { 6511 return this.scanner.source.slice(token.start, token.end); 6512 }; 6513 Parser.prototype.convertToken = function (token) { 6514 var t = { 6515 type: token_1.TokenName[token.type], 6516 value: this.getTokenRaw(token) 6517 }; 6518 if (this.config.range) { 6519 t.range = [token.start, token.end]; 6520 } 6521 if (this.config.loc) { 6522 t.loc = { 6523 start: { 6524 line: this.startMarker.line, 6525 column: this.startMarker.column 6526 }, 6527 end: { 6528 line: this.scanner.lineNumber, 6529 column: this.scanner.index - this.scanner.lineStart 6530 } 6531 }; 6532 } 6533 if (token.type === 9 /* RegularExpression */) { 6534 var pattern = token.pattern; 6535 var flags = token.flags; 6536 t.regex = { pattern: pattern, flags: flags }; 6537 } 6538 return t; 6539 }; 6540 Parser.prototype.nextToken = function () { 6541 var token = this.lookahead; 6542 this.lastMarker.index = this.scanner.index; 6543 this.lastMarker.line = this.scanner.lineNumber; 6544 this.lastMarker.column = this.scanner.index - this.scanner.lineStart; 6545 this.collectComments(); 6546 if (this.scanner.index !== this.startMarker.index) { 6547 this.startMarker.index = this.scanner.index; 6548 this.startMarker.line = this.scanner.lineNumber; 6549 this.startMarker.column = this.scanner.index - this.scanner.lineStart; 6550 } 6551 var next = this.scanner.lex(); 6552 this.hasLineTerminator = (token.lineNumber !== next.lineNumber); 6553 if (next && this.context.strict && next.type === 3 /* Identifier */) { 6554 if (this.scanner.isStrictModeReservedWord(next.value)) { 6555 next.type = 4 /* Keyword */; 6556 } 6557 } 6558 this.lookahead = next; 6559 if (this.config.tokens && next.type !== 2 /* EOF */) { 6560 this.tokens.push(this.convertToken(next)); 6561 } 6562 return token; 6563 }; 6564 Parser.prototype.nextRegexToken = function () { 6565 this.collectComments(); 6566 var token = this.scanner.scanRegExp(); 6567 if (this.config.tokens) { 6568 // Pop the previous token, '/' or '/=' 6569 // This is added from the lookahead token. 6570 this.tokens.pop(); 6571 this.tokens.push(this.convertToken(token)); 6572 } 6573 // Prime the next lookahead. 6574 this.lookahead = token; 6575 this.nextToken(); 6576 return token; 6577 }; 6578 Parser.prototype.createNode = function () { 6579 return { 6580 index: this.startMarker.index, 6581 line: this.startMarker.line, 6582 column: this.startMarker.column 6583 }; 6584 }; 6585 Parser.prototype.startNode = function (token, lastLineStart) { 6586 if (lastLineStart === void 0) { lastLineStart = 0; } 6587 var column = token.start - token.lineStart; 6588 var line = token.lineNumber; 6589 if (column < 0) { 6590 column += lastLineStart; 6591 line--; 6592 } 6593 return { 6594 index: token.start, 6595 line: line, 6596 column: column 6597 }; 6598 }; 6599 Parser.prototype.finalize = function (marker, node) { 6600 if (this.config.range) { 6601 node.range = [marker.index, this.lastMarker.index]; 6602 } 6603 if (this.config.loc) { 6604 node.loc = { 6605 start: { 6606 line: marker.line, 6607 column: marker.column, 6608 }, 6609 end: { 6610 line: this.lastMarker.line, 6611 column: this.lastMarker.column 6612 } 6613 }; 6614 if (this.config.source) { 6615 node.loc.source = this.config.source; 6616 } 6617 } 6618 if (this.delegate) { 6619 var metadata = { 6620 start: { 6621 line: marker.line, 6622 column: marker.column, 6623 offset: marker.index 6624 }, 6625 end: { 6626 line: this.lastMarker.line, 6627 column: this.lastMarker.column, 6628 offset: this.lastMarker.index 6629 } 6630 }; 6631 this.delegate(node, metadata); 6632 } 6633 return node; 6634 }; 6635 // Expect the next token to match the specified punctuator. 6636 // If not, an exception will be thrown. 6637 Parser.prototype.expect = function (value) { 6638 var token = this.nextToken(); 6639 if (token.type !== 7 /* Punctuator */ || token.value !== value) { 6640 this.throwUnexpectedToken(token); 6641 } 6642 }; 6643 // Quietly expect a comma when in tolerant mode, otherwise delegates to expect(). 6644 Parser.prototype.expectCommaSeparator = function () { 6645 if (this.config.tolerant) { 6646 var token = this.lookahead; 6647 if (token.type === 7 /* Punctuator */ && token.value === ',') { 6648 this.nextToken(); 6649 } 6650 else if (token.type === 7 /* Punctuator */ && token.value === ';') { 6651 this.nextToken(); 6652 this.tolerateUnexpectedToken(token); 6653 } 6654 else { 6655 this.tolerateUnexpectedToken(token, messages_1.Messages.UnexpectedToken); 6656 } 6657 } 6658 else { 6659 this.expect(','); 6660 } 6661 }; 6662 // Expect the next token to match the specified keyword. 6663 // If not, an exception will be thrown. 6664 Parser.prototype.expectKeyword = function (keyword) { 6665 var token = this.nextToken(); 6666 if (token.type !== 4 /* Keyword */ || token.value !== keyword) { 6667 this.throwUnexpectedToken(token); 6668 } 6669 }; 6670 // Return true if the next token matches the specified punctuator. 6671 Parser.prototype.match = function (value) { 6672 return this.lookahead.type === 7 /* Punctuator */ && this.lookahead.value === value; 6673 }; 6674 // Return true if the next token matches the specified keyword 6675 Parser.prototype.matchKeyword = function (keyword) { 6676 return this.lookahead.type === 4 /* Keyword */ && this.lookahead.value === keyword; 6677 }; 6678 // Return true if the next token matches the specified contextual keyword 6679 // (where an identifier is sometimes a keyword depending on the context) 6680 Parser.prototype.matchContextualKeyword = function (keyword) { 6681 return this.lookahead.type === 3 /* Identifier */ && this.lookahead.value === keyword; 6682 }; 6683 // Return true if the next token is an assignment operator
6684 Parser.prototype.matchAssign = function () { 6685 if (this.lookahead.type !== 7 /* Punctuator */) { 6686 return false; 6687 } 6688 var op = this.lookahead.value; 6689 return op === '=' || 6690 op === '*=' || 6691 op === '**=' || 6692 op === '/=' || 6693 op === '%=' || 6694 op === '+=' || 6695 op === '-=' || 6696 op === '<<=' || 6697 op === '>>=' || 6698 op === '>>>=' || 6699 op === '&=' || 6700 op === '^=' || 6701 op === '|='; 6702 }; 6703 // Cover grammar support. 6704 // 6705 // When an assignment expression position starts with an left parenthesis, the determination of the type 6706 // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) 6707 // or the first comma. This situation also defers the determination of all the expressions nested in the pair. 6708 // 6709 // There are three productions that can be parsed in a parentheses pair that needs to be determined 6710 // after the outermost pair is closed. They are: 6711 // 6712 // 1. AssignmentExpression 6713 // 2. BindingElements 6714 // 3. AssignmentTargets 6715 // 6716 // In order to avoid exponential backtracking, we use two flags to denote if the production can be 6717 // binding element or assignment target. 6718 // 6719 // The three productions have the relationship: 6720 // 6721 // BindingElements â AssignmentTargets â AssignmentExpression 6722 // 6723 // with a single exception that CoverInitializedName when used directly in an Expression, generates 6724 // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the 6725 // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. 6726 // 6727 // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not 6728 // effect the current flags. This means the production the parser parses is only used as an expression. Therefore 6729 // the CoverInitializedName check is conducted. 6730 // 6731 // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates 6732 // the flags outside of the parser. This means the production the parser parses is used as a part of a potential 6733 // pattern. The CoverInitializedName check is deferred. 6734 Parser.prototype.isolateCoverGrammar = function (parseFunction) { 6735 var previousIsBindingElement = this.context.isBindingElement; 6736 var previousIsAssignmentTarget = this.context.isAssignmentTarget; 6737 var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; 6738 this.context.isBindingElement = true;
vendor: 4,187 bytes, lines 6739-6792
6739 this.context.isAssignmentTarget = true; 6740 this.context.firstCoverInitializedNameError = null; 6741 var result = parseFunction.call(this); 6742 if (this.context.firstCoverInitializedNameError !== null) { 6743 this.throwUnexpectedToken(this.context.firstCoverInitializedNameError); 6744 } 6745 this.context.isBindingElement = previousIsBindingElement; 6746 this.context.isAssignmentTarget = previousIsAssignmentTarget; 6747 this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError; 6748 return result; 6749 }; 6750 Parser.prototype.inheritCoverGrammar = function (parseFunction) { 6751 var previousIsBindingElement = this.context.isBindingElement; 6752 var previousIsAssignmentTarget = this.context.isAssignmentTarget; 6753 var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; 6754 this.context.isBindingElement = true; 6755 this.context.isAssignmentTarget = true; 6756 this.context.firstCoverInitializedNameError = null; 6757 var result = parseFunction.call(this); 6758 this.context.isBindingElement = this.context.isBindingElement && previousIsBindingElement; 6759 this.context.isAssignmentTarget = this.context.isAssignmentTarget && previousIsAssignmentTarget; 6760 this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.context.firstCoverInitializedNameError; 6761 return result; 6762 }; 6763 Parser.prototype.consumeSemicolon = function () { 6764 if (this.match(';')) { 6765 this.nextToken(); 6766 } 6767 else if (!this.hasLineTerminator) { 6768 if (this.lookahead.type !== 2 /* EOF */ && !this.match('}')) { 6769 this.throwUnexpectedToken(this.lookahead); 6770 } 6771 this.lastMarker.index = this.startMarker.index; 6772 this.lastMarker.line = this.startMarker.line; 6773 this.lastMarker.column = this.startMarker.column; 6774 } 6775 }; 6776 // https://tc39.github.io/ecma262/#sec-primary-expression 6777 Parser.prototype.parsePrimaryExpression = function () { 6778 var node = this.createNode(); 6779 var expr; 6780 var token, raw; 6781 switch (this.lookahead.type) { 6782 case 3 /* Identifier */: 6783 if ((this.context.isModule || this.context.await) && this.lookahead.value === 'await') { 6784 this.tolerateUnexpectedToken(this.lookahead); 6785 } 6786 expr = this.matchAsyncFunction() ? this.parseFunctionExpression() : this.finalize(node, new Node.Identifier(this.nextToken().value)); 6787 break; 6788 case 6 /* NumericLiteral */: 6789 case 8 /* StringLiteral */: 6790 if (this.context.strict && this.lookahead.octal) { 6791 this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.StrictOctalLiteral); 6792 }
6793 this.context.isAssignmentTarget = false; 6794 this.context.isBindingElement = false; 6795 token = this.nextToken(); 6796 raw = this.getTokenRaw(token); 6797 expr = this.finalize(node, new Node.Literal(token.value, raw)); 6798 break; 6799 case 1 /* BooleanLiteral */: 6800 this.context.isAssignmentTarget = false; 6801 this.context.isBindingElement = false; 6802 token = this.nextToken(); 6803 raw = this.getTokenRaw(token); 6804 expr = this.finalize(node, new Node.Literal(token.value === 'true', raw)); 6805 break; 6806 case 5 /* NullLiteral */: 6807 this.context.isAssignmentTarget = false;
vendor: 5,747 bytes, lines 6808-6890
6808 this.context.isBindingElement = false; 6809 token = this.nextToken(); 6810 raw = this.getTokenRaw(token); 6811 expr = this.finalize(node, new Node.Literal(null, raw)); 6812 break; 6813 case 10 /* Template */: 6814 expr = this.parseTemplateLiteral(); 6815 break; 6816 case 7 /* Punctuator */: 6817 switch (this.lookahead.value) { 6818 case '(': 6819 this.context.isBindingElement = false; 6820 expr = this.inheritCoverGrammar(this.parseGroupExpression); 6821 break; 6822 case '[': 6823 expr = this.inheritCoverGrammar(this.parseArrayInitializer); 6824 break; 6825 case '{': 6826 expr = this.inheritCoverGrammar(this.parseObjectInitializer); 6827 break; 6828 case '/': 6829 case '/=': 6830 this.context.isAssignmentTarget = false; 6831 this.context.isBindingElement = false; 6832 this.scanner.index = this.startMarker.index; 6833 token = this.nextRegexToken(); 6834 raw = this.getTokenRaw(token); 6835 expr = this.finalize(node, new Node.RegexLiteral(token.regex, raw, token.pattern, token.flags)); 6836 break; 6837 default: 6838 expr = this.throwUnexpectedToken(this.nextToken()); 6839 } 6840 break; 6841 case 4 /* Keyword */: 6842 if (!this.context.strict && this.context.allowYield && this.matchKeyword('yield')) { 6843 expr = this.parseIdentifierName(); 6844 } 6845 else if (!this.context.strict && this.matchKeyword('let')) { 6846 expr = this.finalize(node, new Node.Identifier(this.nextToken().value)); 6847 } 6848 else { 6849 this.context.isAssignmentTarget = false; 6850 this.context.isBindingElement = false; 6851 if (this.matchKeyword('function')) { 6852 expr = this.parseFunctionExpression(); 6853 } 6854 else if (this.matchKeyword('this')) { 6855 this.nextToken(); 6856 expr = this.finalize(node, new Node.ThisExpression()); 6857 } 6858 else if (this.matchKeyword('class')) { 6859 expr = this.parseClassExpression(); 6860 } 6861 else { 6862 expr = this.throwUnexpectedToken(this.nextToken()); 6863 } 6864 } 6865 break; 6866 default: 6867 expr = this.throwUnexpectedToken(this.nextToken()); 6868 } 6869 return expr; 6870 }; 6871 // https://tc39.github.io/ecma262/#sec-array-initializer 6872 Parser.prototype.parseSpreadElement = function () { 6873 var node = this.createNode(); 6874 this.expect('...'); 6875 var arg = this.inheritCoverGrammar(this.parseAssignmentExpression); 6876 return this.finalize(node, new Node.SpreadElement(arg)); 6877 }; 6878 Parser.prototype.parseArrayInitializer = function () { 6879 var node = this.createNode(); 6880 var elements = []; 6881 this.expect('['); 6882 while (!this.match(']')) { 6883 if (this.match(',')) { 6884 this.nextToken(); 6885 elements.push(null); 6886 } 6887 else if (this.match('...')) { 6888 var element = this.parseSpreadElement(); 6889 if (!this.match(']')) { 6890 this.context.isAssignmentTarget = false;
6891 this.context.isBindingElement = false; 6892 this.expect(','); 6893 } 6894 elements.push(element); 6895 } 6896 else { 6897 elements.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); 6898 if (!this.match(']')) { 6899 this.expect(','); 6900 } 6901 } 6902 } 6903 this.expect(']'); 6904 return this.finalize(node, new Node.ArrayExpression(elements)); 6905 }; 6906 // https://tc39.github.io/ecma262/#sec-object-initializer 6907 Parser.prototype.parsePropertyMethod = function (params) { 6908 this.context.isAssignmentTarget = false;
vendor: 174,089 bytes, lines 6909-9498
6909 this.context.isBindingElement = false; 6910 var previousStrict = this.context.strict; 6911 var previousAllowStrictDirective = this.context.allowStrictDirective; 6912 this.context.allowStrictDirective = params.simple; 6913 var body = this.isolateCoverGrammar(this.parseFunctionSourceElements); 6914 if (this.context.strict && params.firstRestricted) { 6915 this.tolerateUnexpectedToken(params.firstRestricted, params.message); 6916 } 6917 if (this.context.strict && params.stricted) { 6918 this.tolerateUnexpectedToken(params.stricted, params.message); 6919 } 6920 this.context.strict = previousStrict; 6921 this.context.allowStrictDirective = previousAllowStrictDirective; 6922 return body; 6923 }; 6924 Parser.prototype.parsePropertyMethodFunction = function () { 6925 var isGenerator = false; 6926 var node = this.createNode(); 6927 var previousAllowYield = this.context.allowYield; 6928 this.context.allowYield = true; 6929 var params = this.parseFormalParameters(); 6930 var method = this.parsePropertyMethod(params); 6931 this.context.allowYield = previousAllowYield; 6932 return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); 6933 }; 6934 Parser.prototype.parsePropertyMethodAsyncFunction = function () { 6935 var node = this.createNode(); 6936 var previousAllowYield = this.context.allowYield; 6937 var previousAwait = this.context.await; 6938 this.context.allowYield = false; 6939 this.context.await = true; 6940 var params = this.parseFormalParameters(); 6941 var method = this.parsePropertyMethod(params); 6942 this.context.allowYield = previousAllowYield; 6943 this.context.await = previousAwait; 6944 return this.finalize(node, new Node.AsyncFunctionExpression(null, params.params, method)); 6945 }; 6946 Parser.prototype.parseObjectPropertyKey = function () { 6947 var node = this.createNode(); 6948 var token = this.nextToken(); 6949 var key; 6950 switch (token.type) { 6951 case 8 /* StringLiteral */: 6952 case 6 /* NumericLiteral */: 6953 if (this.context.strict && token.octal) { 6954 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictOctalLiteral); 6955 } 6956 var raw = this.getTokenRaw(token); 6957 key = this.finalize(node, new Node.Literal(token.value, raw)); 6958 break; 6959 case 3 /* Identifier */: 6960 case 1 /* BooleanLiteral */: 6961 case 5 /* NullLiteral */: 6962 case 4 /* Keyword */: 6963 key = this.finalize(node, new Node.Identifier(token.value)); 6964 break; 6965 case 7 /* Punctuator */: 6966 if (token.value === '[') { 6967 key = this.isolateCoverGrammar(this.parseAssignmentExpression); 6968 this.expect(']'); 6969 } 6970 else { 6971 key = this.throwUnexpectedToken(token); 6972 } 6973 break; 6974 default: 6975 key = this.throwUnexpectedToken(token); 6976 } 6977 return key; 6978 }; 6979 Parser.prototype.isPropertyKey = function (key, value) { 6980 return (key.type === syntax_1.Syntax.Identifier && key.name === value) || 6981 (key.type === syntax_1.Syntax.Literal && key.value === value); 6982 }; 6983 Parser.prototype.parseObjectProperty = function (hasProto) { 6984 var node = this.createNode(); 6985 var token = this.lookahead; 6986 var kind; 6987 var key = null; 6988 var value = null; 6989 var computed = false; 6990 var method = false; 6991 var shorthand = false; 6992 var isAsync = false; 6993 if (token.type === 3 /* Identifier */) { 6994 var id = token.value; 6995 this.nextToken(); 6996 computed = this.match('['); 6997 isAsync = !this.hasLineTerminator && (id === 'async') && 6998 !this.match(':') && !this.match('(') && !this.match('*') && !this.match(','); 6999 key = isAsync ? this.parseObjectPropertyKey() : this.finalize(node, new Node.Identifier(id)); 7000 } 7001 else if (this.match('*')) { 7002 this.nextToken(); 7003 } 7004 else { 7005 computed = this.match('['); 7006 key = this.parseObjectPropertyKey(); 7007 } 7008 var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); 7009 if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'get' && lookaheadPropertyKey) { 7010 kind = 'get'; 7011 computed = this.match('['); 7012 key = this.parseObjectPropertyKey(); 7013 this.context.allowYield = false; 7014 value = this.parseGetterMethod(); 7015 } 7016 else if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'set' && lookaheadPropertyKey) { 7017 kind = 'set'; 7018 computed = this.match('['); 7019 key = this.parseObjectPropertyKey(); 7020 value = this.parseSetterMethod(); 7021 } 7022 else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { 7023 kind = 'init'; 7024 computed = this.match('['); 7025 key = this.parseObjectPropertyKey(); 7026 value = this.parseGeneratorMethod(); 7027 method = true; 7028 } 7029 else { 7030 if (!key) { 7031 this.throwUnexpectedToken(this.lookahead); 7032 } 7033 kind = 'init'; 7034 if (this.match(':') && !isAsync) { 7035 if (!computed && this.isPropertyKey(key, '__proto__')) { 7036 if (hasProto.value) { 7037 this.tolerateError(messages_1.Messages.DuplicateProtoProperty); 7038 } 7039 hasProto.value = true; 7040 } 7041 this.nextToken(); 7042 value = this.inheritCoverGrammar(this.parseAssignmentExpression); 7043 } 7044 else if (this.match('(')) { 7045 value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); 7046 method = true; 7047 } 7048 else if (token.type === 3 /* Identifier */) { 7049 var id = this.finalize(node, new Node.Identifier(token.value)); 7050 if (this.match('=')) { 7051 this.context.firstCoverInitializedNameError = this.lookahead; 7052 this.nextToken(); 7053 shorthand = true; 7054 var init = this.isolateCoverGrammar(this.parseAssignmentExpression); 7055 value = this.finalize(node, new Node.AssignmentPattern(id, init)); 7056 } 7057 else { 7058 shorthand = true; 7059 value = id; 7060 } 7061 } 7062 else { 7063 this.throwUnexpectedToken(this.nextToken()); 7064 } 7065 } 7066 return this.finalize(node, new Node.Property(kind, key, computed, value, method, shorthand)); 7067 }; 7068 Parser.prototype.parseObjectInitializer = function () { 7069 var node = this.createNode(); 7070 this.expect('{'); 7071 var properties = []; 7072 var hasProto = { value: false }; 7073 while (!this.match('}')) { 7074 properties.push(this.parseObjectProperty(hasProto)); 7075 if (!this.match('}')) { 7076 this.expectCommaSeparator(); 7077 } 7078 } 7079 this.expect('}'); 7080 return this.finalize(node, new Node.ObjectExpression(properties)); 7081 }; 7082 // https://tc39.github.io/ecma262/#sec-template-literals 7083 Parser.prototype.parseTemplateHead = function () { 7084 assert_1.assert(this.lookahead.head, 'Template literal must start with a template head'); 7085 var node = this.createNode(); 7086 var token = this.nextToken(); 7087 var raw = token.value; 7088 var cooked = token.cooked; 7089 return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); 7090 }; 7091 Parser.prototype.parseTemplateElement = function () { 7092 if (this.lookahead.type !== 10 /* Template */) { 7093 this.throwUnexpectedToken(); 7094 } 7095 var node = this.createNode(); 7096 var token = this.nextToken(); 7097 var raw = token.value; 7098 var cooked = token.cooked; 7099 return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); 7100 }; 7101 Parser.prototype.parseTemplateLiteral = function () { 7102 var node = this.createNode(); 7103 var expressions = []; 7104 var quasis = []; 7105 var quasi = this.parseTemplateHead(); 7106 quasis.push(quasi); 7107 while (!quasi.tail) { 7108 expressions.push(this.parseExpression()); 7109 quasi = this.parseTemplateElement(); 7110 quasis.push(quasi); 7111 } 7112 return this.finalize(node, new Node.TemplateLiteral(quasis, expressions)); 7113 }; 7114 // https://tc39.github.io/ecma262/#sec-grouping-operator 7115 Parser.prototype.reinterpretExpressionAsPattern = function (expr) { 7116 switch (expr.type) { 7117 case syntax_1.Syntax.Identifier: 7118 case syntax_1.Syntax.MemberExpression: 7119 case syntax_1.Syntax.RestElement: 7120 case syntax_1.Syntax.AssignmentPattern: 7121 break; 7122 case syntax_1.Syntax.SpreadElement: 7123 expr.type = syntax_1.Syntax.RestElement; 7124 this.reinterpretExpressionAsPattern(expr.argument); 7125 break; 7126 case syntax_1.Syntax.ArrayExpression: 7127 expr.type = syntax_1.Syntax.ArrayPattern; 7128 for (var i = 0; i < expr.elements.length; i++) { 7129 if (expr.elements[i] !== null) { 7130 this.reinterpretExpressionAsPattern(expr.elements[i]); 7131 } 7132 } 7133 break; 7134 case syntax_1.Syntax.ObjectExpression: 7135 expr.type = syntax_1.Syntax.ObjectPattern; 7136 for (var i = 0; i < expr.properties.length; i++) { 7137 this.reinterpretExpressionAsPattern(expr.properties[i].value); 7138 } 7139 break; 7140 case syntax_1.Syntax.AssignmentExpression: 7141 expr.type = syntax_1.Syntax.AssignmentPattern; 7142 delete expr.operator; 7143 this.reinterpretExpressionAsPattern(expr.left); 7144 break; 7145 default: 7146 // Allow other node type for tolerant parsing. 7147 break; 7148 } 7149 }; 7150 Parser.prototype.parseGroupExpression = function () { 7151 var expr; 7152 this.expect('('); 7153 if (this.match(')')) { 7154 this.nextToken(); 7155 if (!this.match('=>')) { 7156 this.expect('=>'); 7157 } 7158 expr = { 7159 type: ArrowParameterPlaceHolder, 7160 params: [], 7161 async: false 7162 }; 7163 } 7164 else { 7165 var startToken = this.lookahead; 7166 var params = []; 7167 if (this.match('...')) { 7168 expr = this.parseRestElement(params); 7169 this.expect(')'); 7170 if (!this.match('=>')) { 7171 this.expect('=>'); 7172 } 7173 expr = { 7174 type: ArrowParameterPlaceHolder, 7175 params: [expr], 7176 async: false 7177 }; 7178 } 7179 else { 7180 var arrow = false; 7181 this.context.isBindingElement = true; 7182 expr = this.inheritCoverGrammar(this.parseAssignmentExpression); 7183 if (this.match(',')) { 7184 var expressions = []; 7185 this.context.isAssignmentTarget = false; 7186 expressions.push(expr); 7187 while (this.lookahead.type !== 2 /* EOF */) { 7188 if (!this.match(',')) { 7189 break; 7190 } 7191 this.nextToken(); 7192 if (this.match(')')) { 7193 this.nextToken(); 7194 for (var i = 0; i < expressions.length; i++) { 7195 this.reinterpretExpressionAsPattern(expressions[i]); 7196 } 7197 arrow = true; 7198 expr = { 7199 type: ArrowParameterPlaceHolder, 7200 params: expressions, 7201 async: false 7202 }; 7203 } 7204 else if (this.match('...')) { 7205 if (!this.context.isBindingElement) { 7206 this.throwUnexpectedToken(this.lookahead); 7207 } 7208 expressions.push(this.parseRestElement(params)); 7209 this.expect(')'); 7210 if (!this.match('=>')) { 7211 this.expect('=>'); 7212 } 7213 this.context.isBindingElement = false; 7214 for (var i = 0; i < expressions.length; i++) { 7215 this.reinterpretExpressionAsPattern(expressions[i]); 7216 } 7217 arrow = true; 7218 expr = { 7219 type: ArrowParameterPlaceHolder, 7220 params: expressions, 7221 async: false 7222 }; 7223 } 7224 else { 7225 expressions.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); 7226 } 7227 if (arrow) { 7228 break; 7229 } 7230 } 7231 if (!arrow) { 7232 expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); 7233 } 7234 } 7235 if (!arrow) { 7236 this.expect(')'); 7237 if (this.match('=>')) { 7238 if (expr.type === syntax_1.Syntax.Identifier && expr.name === 'yield') { 7239 arrow = true; 7240 expr = { 7241 type: ArrowParameterPlaceHolder, 7242 params: [expr], 7243 async: false 7244 }; 7245 } 7246 if (!arrow) { 7247 if (!this.context.isBindingElement) { 7248 this.throwUnexpectedToken(this.lookahead); 7249 } 7250 if (expr.type === syntax_1.Syntax.SequenceExpression) { 7251 for (var i = 0; i < expr.expressions.length; i++) { 7252 this.reinterpretExpressionAsPattern(expr.expressions[i]); 7253 } 7254 } 7255 else { 7256 this.reinterpretExpressionAsPattern(expr); 7257 } 7258 var parameters = (expr.type === syntax_1.Syntax.SequenceExpression ? expr.expressions : [expr]); 7259 expr = { 7260 type: ArrowParameterPlaceHolder, 7261 params: parameters, 7262 async: false 7263 }; 7264 } 7265 } 7266 this.context.isBindingElement = false; 7267 } 7268 } 7269 } 7270 return expr; 7271 }; 7272 // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions 7273 Parser.prototype.parseArguments = function () { 7274 this.expect('('); 7275 var args = []; 7276 if (!this.match(')')) { 7277 while (true) { 7278 var expr = this.match('...') ? this.parseSpreadElement() : 7279 this.isolateCoverGrammar(this.parseAssignmentExpression); 7280 args.push(expr); 7281 if (this.match(')')) { 7282 break; 7283 } 7284 this.expectCommaSeparator(); 7285 if (this.match(')')) { 7286 break; 7287 } 7288 } 7289 } 7290 this.expect(')'); 7291 return args; 7292 }; 7293 Parser.prototype.isIdentifierName = function (token) { 7294 return token.type === 3 /* Identifier */ || 7295 token.type === 4 /* Keyword */ || 7296 token.type === 1 /* BooleanLiteral */ || 7297 token.type === 5 /* NullLiteral */; 7298 }; 7299 Parser.prototype.parseIdentifierName = function () { 7300 var node = this.createNode(); 7301 var token = this.nextToken(); 7302 if (!this.isIdentifierName(token)) { 7303 this.throwUnexpectedToken(token); 7304 } 7305 return this.finalize(node, new Node.Identifier(token.value)); 7306 }; 7307 Parser.prototype.parseNewExpression = function () { 7308 var node = this.createNode(); 7309 var id = this.parseIdentifierName(); 7310 assert_1.assert(id.name === 'new', 'New expression must start with `new`'); 7311 var expr; 7312 if (this.match('.')) { 7313 this.nextToken(); 7314 if (this.lookahead.type === 3 /* Identifier */ && this.context.inFunctionBody && this.lookahead.value === 'target') { 7315 var property = this.parseIdentifierName(); 7316 expr = new Node.MetaProperty(id, property); 7317 } 7318 else { 7319 this.throwUnexpectedToken(this.lookahead); 7320 } 7321 } 7322 else { 7323 var callee = this.isolateCoverGrammar(this.parseLeftHandSideExpression); 7324 var args = this.match('(') ? this.parseArguments() : []; 7325 expr = new Node.NewExpression(callee, args); 7326 this.context.isAssignmentTarget = false; 7327 this.context.isBindingElement = false; 7328 } 7329 return this.finalize(node, expr); 7330 }; 7331 Parser.prototype.parseAsyncArgument = function () { 7332 var arg = this.parseAssignmentExpression(); 7333 this.context.firstCoverInitializedNameError = null; 7334 return arg; 7335 }; 7336 Parser.prototype.parseAsyncArguments = function () { 7337 this.expect('('); 7338 var args = []; 7339 if (!this.match(')')) { 7340 while (true) { 7341 var expr = this.match('...') ? this.parseSpreadElement() : 7342 this.isolateCoverGrammar(this.parseAsyncArgument); 7343 args.push(expr); 7344 if (this.match(')')) { 7345 break; 7346 } 7347 this.expectCommaSeparator(); 7348 if (this.match(')')) { 7349 break; 7350 } 7351 } 7352 } 7353 this.expect(')'); 7354 return args; 7355 }; 7356 Parser.prototype.parseLeftHandSideExpressionAllowCall = function () { 7357 var startToken = this.lookahead; 7358 var maybeAsync = this.matchContextualKeyword('async'); 7359 var previousAllowIn = this.context.allowIn; 7360 this.context.allowIn = true; 7361 var expr; 7362 if (this.matchKeyword('super') && this.context.inFunctionBody) { 7363 expr = this.createNode(); 7364 this.nextToken(); 7365 expr = this.finalize(expr, new Node.Super()); 7366 if (!this.match('(') && !this.match('.') && !this.match('[')) { 7367 this.throwUnexpectedToken(this.lookahead); 7368 } 7369 } 7370 else { 7371 expr = this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); 7372 } 7373 while (true) { 7374 if (this.match('.')) { 7375 this.context.isBindingElement = false; 7376 this.context.isAssignmentTarget = true; 7377 this.expect('.'); 7378 var property = this.parseIdentifierName(); 7379 expr = this.finalize(this.startNode(startToken), new Node.StaticMemberExpression(expr, property)); 7380 } 7381 else if (this.match('(')) { 7382 var asyncArrow = maybeAsync && (startToken.lineNumber === this.lookahead.lineNumber); 7383 this.context.isBindingElement = false; 7384 this.context.isAssignmentTarget = false; 7385 var args = asyncArrow ? this.parseAsyncArguments() : this.parseArguments(); 7386 expr = this.finalize(this.startNode(startToken), new Node.CallExpression(expr, args)); 7387 if (asyncArrow && this.match('=>')) { 7388 for (var i = 0; i < args.length; ++i) { 7389 this.reinterpretExpressionAsPattern(args[i]); 7390 } 7391 expr = { 7392 type: ArrowParameterPlaceHolder, 7393 params: args, 7394 async: true 7395 }; 7396 } 7397 } 7398 else if (this.match('[')) { 7399 this.context.isBindingElement = false; 7400 this.context.isAssignmentTarget = true; 7401 this.expect('['); 7402 var property = this.isolateCoverGrammar(this.parseExpression); 7403 this.expect(']'); 7404 expr = this.finalize(this.startNode(startToken), new Node.ComputedMemberExpression(expr, property)); 7405 } 7406 else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { 7407 var quasi = this.parseTemplateLiteral(); 7408 expr = this.finalize(this.startNode(startToken), new Node.TaggedTemplateExpression(expr, quasi)); 7409 } 7410 else { 7411 break; 7412 } 7413 } 7414 this.context.allowIn = previousAllowIn; 7415 return expr; 7416 }; 7417 Parser.prototype.parseSuper = function () { 7418 var node = this.createNode(); 7419 this.expectKeyword('super'); 7420 if (!this.match('[') && !this.match('.')) { 7421 this.throwUnexpectedToken(this.lookahead); 7422 } 7423 return this.finalize(node, new Node.Super()); 7424 }; 7425 Parser.prototype.parseLeftHandSideExpression = function () { 7426 assert_1.assert(this.context.allowIn, 'callee of new expression always allow in keyword.'); 7427 var node = this.startNode(this.lookahead); 7428 var expr = (this.matchKeyword('super') && this.context.inFunctionBody) ? this.parseSuper() : 7429 this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); 7430 while (true) { 7431 if (this.match('[')) { 7432 this.context.isBindingElement = false; 7433 this.context.isAssignmentTarget = true; 7434 this.expect('['); 7435 var property = this.isolateCoverGrammar(this.parseExpression); 7436 this.expect(']'); 7437 expr = this.finalize(node, new Node.ComputedMemberExpression(expr, property)); 7438 } 7439 else if (this.match('.')) { 7440 this.context.isBindingElement = false; 7441 this.context.isAssignmentTarget = true; 7442 this.expect('.'); 7443 var property = this.parseIdentifierName(); 7444 expr = this.finalize(node, new Node.StaticMemberExpression(expr, property)); 7445 } 7446 else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { 7447 var quasi = this.parseTemplateLiteral(); 7448 expr = this.finalize(node, new Node.TaggedTemplateExpression(expr, quasi)); 7449 } 7450 else { 7451 break; 7452 } 7453 } 7454 return expr; 7455 }; 7456 // https://tc39.github.io/ecma262/#sec-update-expressions 7457 Parser.prototype.parseUpdateExpression = function () { 7458 var expr; 7459 var startToken = this.lookahead; 7460 if (this.match('++') || this.match('--')) { 7461 var node = this.startNode(startToken); 7462 var token = this.nextToken(); 7463 expr = this.inheritCoverGrammar(this.parseUnaryExpression); 7464 if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { 7465 this.tolerateError(messages_1.Messages.StrictLHSPrefix); 7466 } 7467 if (!this.context.isAssignmentTarget) { 7468 this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); 7469 } 7470 var prefix = true; 7471 expr = this.finalize(node, new Node.UpdateExpression(token.value, expr, prefix)); 7472 this.context.isAssignmentTarget = false; 7473 this.context.isBindingElement = false; 7474 } 7475 else { 7476 expr = this.inheritCoverGrammar(this.parseLeftHandSideExpressionAllowCall); 7477 if (!this.hasLineTerminator && this.lookahead.type === 7 /* Punctuator */) { 7478 if (this.match('++') || this.match('--')) { 7479 if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { 7480 this.tolerateError(messages_1.Messages.StrictLHSPostfix); 7481 } 7482 if (!this.context.isAssignmentTarget) { 7483 this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); 7484 } 7485 this.context.isAssignmentTarget = false; 7486 this.context.isBindingElement = false; 7487 var operator = this.nextToken().value; 7488 var prefix = false; 7489 expr = this.finalize(this.startNode(startToken), new Node.UpdateExpression(operator, expr, prefix)); 7490 } 7491 } 7492 } 7493 return expr; 7494 }; 7495 // https://tc39.github.io/ecma262/#sec-unary-operators 7496 Parser.prototype.parseAwaitExpression = function () { 7497 var node = this.createNode(); 7498 this.nextToken(); 7499 var argument = this.parseUnaryExpression(); 7500 return this.finalize(node, new Node.AwaitExpression(argument)); 7501 }; 7502 Parser.prototype.parseUnaryExpression = function () { 7503 var expr; 7504 if (this.match('+') || this.match('-') || this.match('~') || this.match('!') || 7505 this.matchKeyword('delete') || this.matchKeyword('void') || this.matchKeyword('typeof')) { 7506 var node = this.startNode(this.lookahead); 7507 var token = this.nextToken(); 7508 expr = this.inheritCoverGrammar(this.parseUnaryExpression); 7509 expr = this.finalize(node, new Node.UnaryExpression(token.value, expr)); 7510 if (this.context.strict && expr.operator === 'delete' && expr.argument.type === syntax_1.Syntax.Identifier) { 7511 this.tolerateError(messages_1.Messages.StrictDelete); 7512 } 7513 this.context.isAssignmentTarget = false; 7514 this.context.isBindingElement = false; 7515 } 7516 else if (this.context.await && this.matchContextualKeyword('await')) { 7517 expr = this.parseAwaitExpression(); 7518 } 7519 else { 7520 expr = this.parseUpdateExpression(); 7521 } 7522 return expr; 7523 }; 7524 Parser.prototype.parseExponentiationExpression = function () { 7525 var startToken = this.lookahead; 7526 var expr = this.inheritCoverGrammar(this.parseUnaryExpression); 7527 if (expr.type !== syntax_1.Syntax.UnaryExpression && this.match('**')) { 7528 this.nextToken(); 7529 this.context.isAssignmentTarget = false; 7530 this.context.isBindingElement = false; 7531 var left = expr; 7532 var right = this.isolateCoverGrammar(this.parseExponentiationExpression); 7533 expr = this.finalize(this.startNode(startToken), new Node.BinaryExpression('**', left, right)); 7534 } 7535 return expr; 7536 }; 7537 // https://tc39.github.io/ecma262/#sec-exp-operator 7538 // https://tc39.github.io/ecma262/#sec-multiplicative-operators 7539 // https://tc39.github.io/ecma262/#sec-additive-operators 7540 // https://tc39.github.io/ecma262/#sec-bitwise-shift-operators 7541 // https://tc39.github.io/ecma262/#sec-relational-operators 7542 // https://tc39.github.io/ecma262/#sec-equality-operators 7543 // https://tc39.github.io/ecma262/#sec-binary-bitwise-operators 7544 // https://tc39.github.io/ecma262/#sec-binary-logical-operators 7545 Parser.prototype.binaryPrecedence = function (token) { 7546 var op = token.value; 7547 var precedence; 7548 if (token.type === 7 /* Punctuator */) { 7549 precedence = this.operatorPrecedence[op] || 0; 7550 } 7551 else if (token.type === 4 /* Keyword */) { 7552 precedence = (op === 'instanceof' || (this.context.allowIn && op === 'in')) ? 7 : 0; 7553 } 7554 else { 7555 precedence = 0; 7556 } 7557 return precedence; 7558 }; 7559 Parser.prototype.parseBinaryExpression = function () { 7560 var startToken = this.lookahead; 7561 var expr = this.inheritCoverGrammar(this.parseExponentiationExpression); 7562 var token = this.lookahead; 7563 var prec = this.binaryPrecedence(token); 7564 if (prec > 0) { 7565 this.nextToken(); 7566 this.context.isAssignmentTarget = false; 7567 this.context.isBindingElement = false; 7568 var markers = [startToken, this.lookahead]; 7569 var left = expr; 7570 var right = this.isolateCoverGrammar(this.parseExponentiationExpression); 7571 var stack = [left, token.value, right]; 7572 var precedences = [prec]; 7573 while (true) { 7574 prec = this.binaryPrecedence(this.lookahead); 7575 if (prec <= 0) { 7576 break; 7577 } 7578 // Reduce: make a binary expression from the three topmost entries. 7579 while ((stack.length > 2) && (prec <= precedences[precedences.length - 1])) { 7580 right = stack.pop(); 7581 var operator = stack.pop(); 7582 precedences.pop(); 7583 left = stack.pop(); 7584 markers.pop(); 7585 var node = this.startNode(markers[markers.length - 1]); 7586 stack.push(this.finalize(node, new Node.BinaryExpression(operator, left, right))); 7587 } 7588 // Shift. 7589 stack.push(this.nextToken().value); 7590 precedences.push(prec); 7591 markers.push(this.lookahead); 7592 stack.push(this.isolateCoverGrammar(this.parseExponentiationExpression)); 7593 } 7594 // Final reduce to clean-up the stack. 7595 var i = stack.length - 1; 7596 expr = stack[i]; 7597 var lastMarker = markers.pop(); 7598 while (i > 1) { 7599 var marker = markers.pop(); 7600 var lastLineStart = lastMarker && lastMarker.lineStart; 7601 var node = this.startNode(marker, lastLineStart); 7602 var operator = stack[i - 1]; 7603 expr = this.finalize(node, new Node.BinaryExpression(operator, stack[i - 2], expr)); 7604 i -= 2; 7605 lastMarker = marker; 7606 } 7607 } 7608 return expr; 7609 }; 7610 // https://tc39.github.io/ecma262/#sec-conditional-operator 7611 Parser.prototype.parseConditionalExpression = function () { 7612 var startToken = this.lookahead; 7613 var expr = this.inheritCoverGrammar(this.parseBinaryExpression); 7614 if (this.match('?')) { 7615 this.nextToken(); 7616 var previousAllowIn = this.context.allowIn; 7617 this.context.allowIn = true; 7618 var consequent = this.isolateCoverGrammar(this.parseAssignmentExpression); 7619 this.context.allowIn = previousAllowIn; 7620 this.expect(':'); 7621 var alternate = this.isolateCoverGrammar(this.parseAssignmentExpression); 7622 expr = this.finalize(this.startNode(startToken), new Node.ConditionalExpression(expr, consequent, alternate)); 7623 this.context.isAssignmentTarget = false; 7624 this.context.isBindingElement = false; 7625 } 7626 return expr; 7627 }; 7628 // https://tc39.github.io/ecma262/#sec-assignment-operators 7629 Parser.prototype.checkPatternParam = function (options, param) { 7630 switch (param.type) { 7631 case syntax_1.Syntax.Identifier: 7632 this.validateParam(options, param, param.name); 7633 break; 7634 case syntax_1.Syntax.RestElement: 7635 this.checkPatternParam(options, param.argument); 7636 break; 7637 case syntax_1.Syntax.AssignmentPattern: 7638 this.checkPatternParam(options, param.left); 7639 break; 7640 case syntax_1.Syntax.ArrayPattern: 7641 for (var i = 0; i < param.elements.length; i++) { 7642 if (param.elements[i] !== null) { 7643 this.checkPatternParam(options, param.elements[i]); 7644 } 7645 } 7646 break; 7647 case syntax_1.Syntax.ObjectPattern: 7648 for (var i = 0; i < param.properties.length; i++) { 7649 this.checkPatternParam(options, param.properties[i].value); 7650 } 7651 break; 7652 default: 7653 break; 7654 } 7655 options.simple = options.simple && (param instanceof Node.Identifier); 7656 }; 7657 Parser.prototype.reinterpretAsCoverFormalsList = function (expr) { 7658 var params = [expr]; 7659 var options; 7660 var asyncArrow = false; 7661 switch (expr.type) { 7662 case syntax_1.Syntax.Identifier: 7663 break; 7664 case ArrowParameterPlaceHolder: 7665 params = expr.params; 7666 asyncArrow = expr.async; 7667 break; 7668 default: 7669 return null; 7670 } 7671 options = { 7672 simple: true, 7673 paramSet: {} 7674 }; 7675 for (var i = 0; i < params.length; ++i) { 7676 var param = params[i]; 7677 if (param.type === syntax_1.Syntax.AssignmentPattern) { 7678 if (param.right.type === syntax_1.Syntax.YieldExpression) { 7679 if (param.right.argument) { 7680 this.throwUnexpectedToken(this.lookahead); 7681 } 7682 param.right.type = syntax_1.Syntax.Identifier; 7683 param.right.name = 'yield'; 7684 delete param.right.argument; 7685 delete param.right.delegate; 7686 } 7687 } 7688 else if (asyncArrow && param.type === syntax_1.Syntax.Identifier && param.name === 'await') { 7689 this.throwUnexpectedToken(this.lookahead); 7690 } 7691 this.checkPatternParam(options, param); 7692 params[i] = param; 7693 } 7694 if (this.context.strict || !this.context.allowYield) { 7695 for (var i = 0; i < params.length; ++i) { 7696 var param = params[i]; 7697 if (param.type === syntax_1.Syntax.YieldExpression) { 7698 this.throwUnexpectedToken(this.lookahead); 7699 } 7700 } 7701 } 7702 if (options.message === messages_1.Messages.StrictParamDupe) { 7703 var token = this.context.strict ? options.stricted : options.firstRestricted; 7704 this.throwUnexpectedToken(token, options.message); 7705 } 7706 return { 7707 simple: options.simple, 7708 params: params, 7709 stricted: options.stricted, 7710 firstRestricted: options.firstRestricted, 7711 message: options.message 7712 }; 7713 }; 7714 Parser.prototype.parseAssignmentExpression = function () { 7715 var expr; 7716 if (!this.context.allowYield && this.matchKeyword('yield')) { 7717 expr = this.parseYieldExpression(); 7718 } 7719 else { 7720 var startToken = this.lookahead; 7721 var token = startToken; 7722 expr = this.parseConditionalExpression(); 7723 if (token.type === 3 /* Identifier */ && (token.lineNumber === this.lookahead.lineNumber) && token.value === 'async') { 7724 if (this.lookahead.type === 3 /* Identifier */ || this.matchKeyword('yield')) { 7725 var arg = this.parsePrimaryExpression(); 7726 this.reinterpretExpressionAsPattern(arg); 7727 expr = { 7728 type: ArrowParameterPlaceHolder, 7729 params: [arg], 7730 async: true 7731 }; 7732 } 7733 } 7734 if (expr.type === ArrowParameterPlaceHolder || this.match('=>')) { 7735 // https://tc39.github.io/ecma262/#sec-arrow-function-definitions 7736 this.context.isAssignmentTarget = false; 7737 this.context.isBindingElement = false; 7738 var isAsync = expr.async; 7739 var list = this.reinterpretAsCoverFormalsList(expr); 7740 if (list) { 7741 if (this.hasLineTerminator) { 7742 this.tolerateUnexpectedToken(this.lookahead); 7743 } 7744 this.context.firstCoverInitializedNameError = null; 7745 var previousStrict = this.context.strict; 7746 var previousAllowStrictDirective = this.context.allowStrictDirective; 7747 this.context.allowStrictDirective = list.simple; 7748 var previousAllowYield = this.context.allowYield; 7749 var previousAwait = this.context.await; 7750 this.context.allowYield = true; 7751 this.context.await = isAsync; 7752 var node = this.startNode(startToken); 7753 this.expect('=>'); 7754 var body = void 0; 7755 if (this.match('{')) { 7756 var previousAllowIn = this.context.allowIn; 7757 this.context.allowIn = true; 7758 body = this.parseFunctionSourceElements(); 7759 this.context.allowIn = previousAllowIn; 7760 } 7761 else { 7762 body = this.isolateCoverGrammar(this.parseAssignmentExpression); 7763 } 7764 var expression = body.type !== syntax_1.Syntax.BlockStatement; 7765 if (this.context.strict && list.firstRestricted) { 7766 this.throwUnexpectedToken(list.firstRestricted, list.message); 7767 } 7768 if (this.context.strict && list.stricted) { 7769 this.tolerateUnexpectedToken(list.stricted, list.message); 7770 } 7771 expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression)) : 7772 this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression)); 7773 this.context.strict = previousStrict; 7774 this.context.allowStrictDirective = previousAllowStrictDirective; 7775 this.context.allowYield = previousAllowYield; 7776 this.context.await = previousAwait; 7777 } 7778 } 7779 else { 7780 if (this.matchAssign()) { 7781 if (!this.context.isAssignmentTarget) { 7782 this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); 7783 } 7784 if (this.context.strict && expr.type === syntax_1.Syntax.Identifier) { 7785 var id = expr; 7786 if (this.scanner.isRestrictedWord(id.name)) { 7787 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictLHSAssignment); 7788 } 7789 if (this.scanner.isStrictModeReservedWord(id.name)) { 7790 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); 7791 } 7792 } 7793 if (!this.match('=')) { 7794 this.context.isAssignmentTarget = false; 7795 this.context.isBindingElement = false; 7796 } 7797 else { 7798 this.reinterpretExpressionAsPattern(expr); 7799 } 7800 token = this.nextToken(); 7801 var operator = token.value; 7802 var right = this.isolateCoverGrammar(this.parseAssignmentExpression); 7803 expr = this.finalize(this.startNode(startToken), new Node.AssignmentExpression(operator, expr, right)); 7804 this.context.firstCoverInitializedNameError = null; 7805 } 7806 } 7807 } 7808 return expr; 7809 }; 7810 // https://tc39.github.io/ecma262/#sec-comma-operator 7811 Parser.prototype.parseExpression = function () { 7812 var startToken = this.lookahead; 7813 var expr = this.isolateCoverGrammar(this.parseAssignmentExpression); 7814 if (this.match(',')) { 7815 var expressions = []; 7816 expressions.push(expr); 7817 while (this.lookahead.type !== 2 /* EOF */) { 7818 if (!this.match(',')) { 7819 break; 7820 } 7821 this.nextToken(); 7822 expressions.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); 7823 } 7824 expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); 7825 } 7826 return expr; 7827 }; 7828 // https://tc39.github.io/ecma262/#sec-block 7829 Parser.prototype.parseStatementListItem = function () { 7830 var statement; 7831 this.context.isAssignmentTarget = true; 7832 this.context.isBindingElement = true; 7833 if (this.lookahead.type === 4 /* Keyword */) { 7834 switch (this.lookahead.value) { 7835 case 'export': 7836 if (!this.context.isModule) { 7837 this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalExportDeclaration); 7838 } 7839 statement = this.parseExportDeclaration(); 7840 break; 7841 case 'import': 7842 if (!this.context.isModule) { 7843 this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalImportDeclaration); 7844 } 7845 statement = this.parseImportDeclaration(); 7846 break; 7847 case 'const': 7848 statement = this.parseLexicalDeclaration({ inFor: false }); 7849 break; 7850 case 'function': 7851 statement = this.parseFunctionDeclaration(); 7852 break; 7853 case 'class': 7854 statement = this.parseClassDeclaration(); 7855 break; 7856 case 'let': 7857 statement = this.isLexicalDeclaration() ? this.parseLexicalDeclaration({ inFor: false }) : this.parseStatement(); 7858 break; 7859 default: 7860 statement = this.parseStatement(); 7861 break; 7862 } 7863 } 7864 else { 7865 statement = this.parseStatement(); 7866 } 7867 return statement; 7868 }; 7869 Parser.prototype.parseBlock = function () { 7870 var node = this.createNode(); 7871 this.expect('{'); 7872 var block = []; 7873 while (true) { 7874 if (this.match('}')) { 7875 break; 7876 } 7877 block.push(this.parseStatementListItem()); 7878 } 7879 this.expect('}'); 7880 return this.finalize(node, new Node.BlockStatement(block)); 7881 }; 7882 // https://tc39.github.io/ecma262/#sec-let-and-const-declarations 7883 Parser.prototype.parseLexicalBinding = function (kind, options) { 7884 var node = this.createNode(); 7885 var params = []; 7886 var id = this.parsePattern(params, kind); 7887 if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { 7888 if (this.scanner.isRestrictedWord(id.name)) { 7889 this.tolerateError(messages_1.Messages.StrictVarName); 7890 } 7891 } 7892 var init = null; 7893 if (kind === 'const') { 7894 if (!this.matchKeyword('in') && !this.matchContextualKeyword('of')) { 7895 if (this.match('=')) { 7896 this.nextToken(); 7897 init = this.isolateCoverGrammar(this.parseAssignmentExpression); 7898 } 7899 else { 7900 this.throwError(messages_1.Messages.DeclarationMissingInitializer, 'const'); 7901 } 7902 } 7903 } 7904 else if ((!options.inFor && id.type !== syntax_1.Syntax.Identifier) || this.match('=')) { 7905 this.expect('='); 7906 init = this.isolateCoverGrammar(this.parseAssignmentExpression); 7907 } 7908 return this.finalize(node, new Node.VariableDeclarator(id, init)); 7909 }; 7910 Parser.prototype.parseBindingList = function (kind, options) { 7911 var list = [this.parseLexicalBinding(kind, options)]; 7912 while (this.match(',')) { 7913 this.nextToken(); 7914 list.push(this.parseLexicalBinding(kind, options)); 7915 } 7916 return list; 7917 }; 7918 Parser.prototype.isLexicalDeclaration = function () { 7919 var state = this.scanner.saveState(); 7920 this.scanner.scanComments(); 7921 var next = this.scanner.lex(); 7922 this.scanner.restoreState(state); 7923 return (next.type === 3 /* Identifier */) || 7924 (next.type === 7 /* Punctuator */ && next.value === '[') || 7925 (next.type === 7 /* Punctuator */ && next.value === '{') || 7926 (next.type === 4 /* Keyword */ && next.value === 'let') || 7927 (next.type === 4 /* Keyword */ && next.value === 'yield'); 7928 }; 7929 Parser.prototype.parseLexicalDeclaration = function (options) { 7930 var node = this.createNode(); 7931 var kind = this.nextToken().value; 7932 assert_1.assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const'); 7933 var declarations = this.parseBindingList(kind, options); 7934 this.consumeSemicolon(); 7935 return this.finalize(node, new Node.VariableDeclaration(declarations, kind)); 7936 }; 7937 // https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns 7938 Parser.prototype.parseBindingRestElement = function (params, kind) { 7939 var node = this.createNode(); 7940 this.expect('...'); 7941 var arg = this.parsePattern(params, kind); 7942 return this.finalize(node, new Node.RestElement(arg)); 7943 }; 7944 Parser.prototype.parseArrayPattern = function (params, kind) { 7945 var node = this.createNode(); 7946 this.expect('['); 7947 var elements = []; 7948 while (!this.match(']')) { 7949 if (this.match(',')) { 7950 this.nextToken(); 7951 elements.push(null); 7952 } 7953 else { 7954 if (this.match('...')) { 7955 elements.push(this.parseBindingRestElement(params, kind)); 7956 break; 7957 } 7958 else { 7959 elements.push(this.parsePatternWithDefault(params, kind)); 7960 } 7961 if (!this.match(']')) { 7962 this.expect(','); 7963 } 7964 } 7965 } 7966 this.expect(']'); 7967 return this.finalize(node, new Node.ArrayPattern(elements)); 7968 }; 7969 Parser.prototype.parsePropertyPattern = function (params, kind) { 7970 var node = this.createNode(); 7971 var computed = false; 7972 var shorthand = false; 7973 var method = false; 7974 var key; 7975 var value; 7976 if (this.lookahead.type === 3 /* Identifier */) { 7977 var keyToken = this.lookahead; 7978 key = this.parseVariableIdentifier(); 7979 var init = this.finalize(node, new Node.Identifier(keyToken.value)); 7980 if (this.match('=')) { 7981 params.push(keyToken); 7982 shorthand = true; 7983 this.nextToken(); 7984 var expr = this.parseAssignmentExpression(); 7985 value = this.finalize(this.startNode(keyToken), new Node.AssignmentPattern(init, expr)); 7986 } 7987 else if (!this.match(':')) { 7988 params.push(keyToken); 7989 shorthand = true; 7990 value = init; 7991 } 7992 else { 7993 this.expect(':'); 7994 value = this.parsePatternWithDefault(params, kind); 7995 } 7996 } 7997 else { 7998 computed = this.match('['); 7999 key = this.parseObjectPropertyKey(); 8000 this.expect(':'); 8001 value = this.parsePatternWithDefault(params, kind); 8002 } 8003 return this.finalize(node, new Node.Property('init', key, computed, value, method, shorthand)); 8004 }; 8005 Parser.prototype.parseObjectPattern = function (params, kind) { 8006 var node = this.createNode(); 8007 var properties = []; 8008 this.expect('{'); 8009 while (!this.match('}')) { 8010 properties.push(this.parsePropertyPattern(params, kind)); 8011 if (!this.match('}')) { 8012 this.expect(','); 8013 } 8014 } 8015 this.expect('}'); 8016 return this.finalize(node, new Node.ObjectPattern(properties)); 8017 }; 8018 Parser.prototype.parsePattern = function (params, kind) { 8019 var pattern; 8020 if (this.match('[')) { 8021 pattern = this.parseArrayPattern(params, kind); 8022 } 8023 else if (this.match('{')) { 8024 pattern = this.parseObjectPattern(params, kind); 8025 } 8026 else { 8027 if (this.matchKeyword('let') && (kind === 'const' || kind === 'let')) { 8028 this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.LetInLexicalBinding); 8029 } 8030 params.push(this.lookahead); 8031 pattern = this.parseVariableIdentifier(kind); 8032 } 8033 return pattern; 8034 }; 8035 Parser.prototype.parsePatternWithDefault = function (params, kind) { 8036 var startToken = this.lookahead; 8037 var pattern = this.parsePattern(params, kind); 8038 if (this.match('=')) { 8039 this.nextToken(); 8040 var previousAllowYield = this.context.allowYield; 8041 this.context.allowYield = true; 8042 var right = this.isolateCoverGrammar(this.parseAssignmentExpression); 8043 this.context.allowYield = previousAllowYield; 8044 pattern = this.finalize(this.startNode(startToken), new Node.AssignmentPattern(pattern, right)); 8045 } 8046 return pattern; 8047 }; 8048 // https://tc39.github.io/ecma262/#sec-variable-statement 8049 Parser.prototype.parseVariableIdentifier = function (kind) { 8050 var node = this.createNode(); 8051 var token = this.nextToken(); 8052 if (token.type === 4 /* Keyword */ && token.value === 'yield') { 8053 if (this.context.strict) { 8054 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); 8055 } 8056 else if (!this.context.allowYield) { 8057 this.throwUnexpectedToken(token); 8058 } 8059 } 8060 else if (token.type !== 3 /* Identifier */) { 8061 if (this.context.strict && token.type === 4 /* Keyword */ && this.scanner.isStrictModeReservedWord(token.value)) { 8062 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); 8063 } 8064 else { 8065 if (this.context.strict || token.value !== 'let' || kind !== 'var') { 8066 this.throwUnexpectedToken(token); 8067 } 8068 } 8069 } 8070 else if ((this.context.isModule || this.context.await) && token.type === 3 /* Identifier */ && token.value === 'await') { 8071 this.tolerateUnexpectedToken(token); 8072 } 8073 return this.finalize(node, new Node.Identifier(token.value)); 8074 }; 8075 Parser.prototype.parseVariableDeclaration = function (options) { 8076 var node = this.createNode(); 8077 var params = []; 8078 var id = this.parsePattern(params, 'var'); 8079 if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { 8080 if (this.scanner.isRestrictedWord(id.name)) { 8081 this.tolerateError(messages_1.Messages.StrictVarName); 8082 } 8083 } 8084 var init = null; 8085 if (this.match('=')) { 8086 this.nextToken(); 8087 init = this.isolateCoverGrammar(this.parseAssignmentExpression); 8088 } 8089 else if (id.type !== syntax_1.Syntax.Identifier && !options.inFor) { 8090 this.expect('='); 8091 } 8092 return this.finalize(node, new Node.VariableDeclarator(id, init)); 8093 }; 8094 Parser.prototype.parseVariableDeclarationList = function (options) { 8095 var opt = { inFor: options.inFor }; 8096 var list = []; 8097 list.push(this.parseVariableDeclaration(opt)); 8098 while (this.match(',')) { 8099 this.nextToken(); 8100 list.push(this.parseVariableDeclaration(opt)); 8101 } 8102 return list; 8103 }; 8104 Parser.prototype.parseVariableStatement = function () { 8105 var node = this.createNode(); 8106 this.expectKeyword('var'); 8107 var declarations = this.parseVariableDeclarationList({ inFor: false }); 8108 this.consumeSemicolon(); 8109 return this.finalize(node, new Node.VariableDeclaration(declarations, 'var')); 8110 }; 8111 // https://tc39.github.io/ecma262/#sec-empty-statement 8112 Parser.prototype.parseEmptyStatement = function () { 8113 var node = this.createNode(); 8114 this.expect(';'); 8115 return this.finalize(node, new Node.EmptyStatement()); 8116 }; 8117 // https://tc39.github.io/ecma262/#sec-expression-statement 8118 Parser.prototype.parseExpressionStatement = function () { 8119 var node = this.createNode(); 8120 var expr = this.parseExpression(); 8121 this.consumeSemicolon(); 8122 return this.finalize(node, new Node.ExpressionStatement(expr)); 8123 }; 8124 // https://tc39.github.io/ecma262/#sec-if-statement 8125 Parser.prototype.parseIfClause = function () { 8126 if (this.context.strict && this.matchKeyword('function')) { 8127 this.tolerateError(messages_1.Messages.StrictFunction); 8128 } 8129 return this.parseStatement(); 8130 }; 8131 Parser.prototype.parseIfStatement = function () { 8132 var node = this.createNode(); 8133 var consequent; 8134 var alternate = null; 8135 this.expectKeyword('if'); 8136 this.expect('('); 8137 var test = this.parseExpression(); 8138 if (!this.match(')') && this.config.tolerant) { 8139 this.tolerateUnexpectedToken(this.nextToken()); 8140 consequent = this.finalize(this.createNode(), new Node.EmptyStatement()); 8141 } 8142 else { 8143 this.expect(')'); 8144 consequent = this.parseIfClause(); 8145 if (this.matchKeyword('else')) { 8146 this.nextToken(); 8147 alternate = this.parseIfClause(); 8148 } 8149 } 8150 return this.finalize(node, new Node.IfStatement(test, consequent, alternate)); 8151 }; 8152 // https://tc39.github.io/ecma262/#sec-do-while-statement 8153 Parser.prototype.parseDoWhileStatement = function () { 8154 var node = this.createNode(); 8155 this.expectKeyword('do'); 8156 var previousInIteration = this.context.inIteration; 8157 this.context.inIteration = true; 8158 var body = this.parseStatement(); 8159 this.context.inIteration = previousInIteration; 8160 this.expectKeyword('while'); 8161 this.expect('('); 8162 var test = this.parseExpression(); 8163 if (!this.match(')') && this.config.tolerant) { 8164 this.tolerateUnexpectedToken(this.nextToken()); 8165 } 8166 else { 8167 this.expect(')'); 8168 if (this.match(';')) { 8169 this.nextToken(); 8170 } 8171 } 8172 return this.finalize(node, new Node.DoWhileStatement(body, test)); 8173 }; 8174 // https://tc39.github.io/ecma262/#sec-while-statement 8175 Parser.prototype.parseWhileStatement = function () { 8176 var node = this.createNode(); 8177 var body; 8178 this.expectKeyword('while'); 8179 this.expect('('); 8180 var test = this.parseExpression(); 8181 if (!this.match(')') && this.config.tolerant) { 8182 this.tolerateUnexpectedToken(this.nextToken()); 8183 body = this.finalize(this.createNode(), new Node.EmptyStatement()); 8184 } 8185 else { 8186 this.expect(')'); 8187 var previousInIteration = this.context.inIteration; 8188 this.context.inIteration = true; 8189 body = this.parseStatement(); 8190 this.context.inIteration = previousInIteration; 8191 } 8192 return this.finalize(node, new Node.WhileStatement(test, body)); 8193 }; 8194 // https://tc39.github.io/ecma262/#sec-for-statement 8195 // https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements 8196 Parser.prototype.parseForStatement = function () { 8197 var init = null; 8198 var test = null; 8199 var update = null; 8200 var forIn = true; 8201 var left, right; 8202 var node = this.createNode(); 8203 this.expectKeyword('for'); 8204 this.expect('('); 8205 if (this.match(';')) { 8206 this.nextToken(); 8207 } 8208 else { 8209 if (this.matchKeyword('var')) { 8210 init = this.createNode(); 8211 this.nextToken(); 8212 var previousAllowIn = this.context.allowIn; 8213 this.context.allowIn = false; 8214 var declarations = this.parseVariableDeclarationList({ inFor: true }); 8215 this.context.allowIn = previousAllowIn; 8216 if (declarations.length === 1 && this.matchKeyword('in')) { 8217 var decl = declarations[0]; 8218 if (decl.init && (decl.id.type === syntax_1.Syntax.ArrayPattern || decl.id.type === syntax_1.Syntax.ObjectPattern || this.context.strict)) { 8219 this.tolerateError(messages_1.Messages.ForInOfLoopInitializer, 'for-in'); 8220 } 8221 init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); 8222 this.nextToken(); 8223 left = init; 8224 right = this.parseExpression(); 8225 init = null; 8226 } 8227 else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { 8228 init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); 8229 this.nextToken(); 8230 left = init; 8231 right = this.parseAssignmentExpression(); 8232 init = null; 8233 forIn = false; 8234 } 8235 else { 8236 init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); 8237 this.expect(';'); 8238 } 8239 } 8240 else if (this.matchKeyword('const') || this.matchKeyword('let')) { 8241 init = this.createNode(); 8242 var kind = this.nextToken().value; 8243 if (!this.context.strict && this.lookahead.value === 'in') { 8244 init = this.finalize(init, new Node.Identifier(kind)); 8245 this.nextToken(); 8246 left = init; 8247 right = this.parseExpression(); 8248 init = null; 8249 } 8250 else { 8251 var previousAllowIn = this.context.allowIn; 8252 this.context.allowIn = false; 8253 var declarations = this.parseBindingList(kind, { inFor: true }); 8254 this.context.allowIn = previousAllowIn; 8255 if (declarations.length === 1 && declarations[0].init === null && this.matchKeyword('in')) { 8256 init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); 8257 this.nextToken(); 8258 left = init; 8259 right = this.parseExpression(); 8260 init = null; 8261 } 8262 else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { 8263 init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); 8264 this.nextToken(); 8265 left = init; 8266 right = this.parseAssignmentExpression(); 8267 init = null; 8268 forIn = false; 8269 } 8270 else { 8271 this.consumeSemicolon(); 8272 init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); 8273 } 8274 } 8275 } 8276 else { 8277 var initStartToken = this.lookahead; 8278 var previousAllowIn = this.context.allowIn; 8279 this.context.allowIn = false; 8280 init = this.inheritCoverGrammar(this.parseAssignmentExpression); 8281 this.context.allowIn = previousAllowIn; 8282 if (this.matchKeyword('in')) { 8283 if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { 8284 this.tolerateError(messages_1.Messages.InvalidLHSInForIn); 8285 } 8286 this.nextToken(); 8287 this.reinterpretExpressionAsPattern(init); 8288 left = init; 8289 right = this.parseExpression(); 8290 init = null; 8291 } 8292 else if (this.matchContextualKeyword('of')) { 8293 if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { 8294 this.tolerateError(messages_1.Messages.InvalidLHSInForLoop); 8295 } 8296 this.nextToken(); 8297 this.reinterpretExpressionAsPattern(init); 8298 left = init; 8299 right = this.parseAssignmentExpression(); 8300 init = null; 8301 forIn = false; 8302 } 8303 else { 8304 if (this.match(',')) { 8305 var initSeq = [init]; 8306 while (this.match(',')) { 8307 this.nextToken(); 8308 initSeq.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); 8309 } 8310 init = this.finalize(this.startNode(initStartToken), new Node.SequenceExpression(initSeq)); 8311 } 8312 this.expect(';'); 8313 } 8314 } 8315 } 8316 if (typeof left === 'undefined') { 8317 if (!this.match(';')) { 8318 test = this.parseExpression(); 8319 } 8320 this.expect(';'); 8321 if (!this.match(')')) { 8322 update = this.parseExpression(); 8323 } 8324 } 8325 var body; 8326 if (!this.match(')') && this.config.tolerant) { 8327 this.tolerateUnexpectedToken(this.nextToken()); 8328 body = this.finalize(this.createNode(), new Node.EmptyStatement()); 8329 } 8330 else { 8331 this.expect(')'); 8332 var previousInIteration = this.context.inIteration; 8333 this.context.inIteration = true; 8334 body = this.isolateCoverGrammar(this.parseStatement); 8335 this.context.inIteration = previousInIteration; 8336 } 8337 return (typeof left === 'undefined') ? 8338 this.finalize(node, new Node.ForStatement(init, test, update, body)) : 8339 forIn ? this.finalize(node, new Node.ForInStatement(left, right, body)) : 8340 this.finalize(node, new Node.ForOfStatement(left, right, body)); 8341 }; 8342 // https://tc39.github.io/ecma262/#sec-continue-statement 8343 Parser.prototype.parseContinueStatement = function () { 8344 var node = this.createNode(); 8345 this.expectKeyword('continue'); 8346 var label = null; 8347 if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { 8348 var id = this.parseVariableIdentifier(); 8349 label = id; 8350 var key = '$' + id.name; 8351 if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { 8352 this.throwError(messages_1.Messages.UnknownLabel, id.name); 8353 } 8354 } 8355 this.consumeSemicolon(); 8356 if (label === null && !this.context.inIteration) { 8357 this.throwError(messages_1.Messages.IllegalContinue); 8358 } 8359 return this.finalize(node, new Node.ContinueStatement(label)); 8360 }; 8361 // https://tc39.github.io/ecma262/#sec-break-statement 8362 Parser.prototype.parseBreakStatement = function () { 8363 var node = this.createNode(); 8364 this.expectKeyword('break'); 8365 var label = null; 8366 if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { 8367 var id = this.parseVariableIdentifier(); 8368 var key = '$' + id.name; 8369 if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { 8370 this.throwError(messages_1.Messages.UnknownLabel, id.name); 8371 } 8372 label = id; 8373 } 8374 this.consumeSemicolon(); 8375 if (label === null && !this.context.inIteration && !this.context.inSwitch) { 8376 this.throwError(messages_1.Messages.IllegalBreak); 8377 } 8378 return this.finalize(node, new Node.BreakStatement(label)); 8379 }; 8380 // https://tc39.github.io/ecma262/#sec-return-statement 8381 Parser.prototype.parseReturnStatement = function () { 8382 if (!this.context.inFunctionBody) { 8383 this.tolerateError(messages_1.Messages.IllegalReturn); 8384 } 8385 var node = this.createNode(); 8386 this.expectKeyword('return'); 8387 var hasArgument = (!this.match(';') && !this.match('}') && 8388 !this.hasLineTerminator && this.lookahead.type !== 2 /* EOF */) || 8389 this.lookahead.type === 8 /* StringLiteral */ || 8390 this.lookahead.type === 10 /* Template */; 8391 var argument = hasArgument ? this.parseExpression() : null; 8392 this.consumeSemicolon(); 8393 return this.finalize(node, new Node.ReturnStatement(argument)); 8394 }; 8395 // https://tc39.github.io/ecma262/#sec-with-statement 8396 Parser.prototype.parseWithStatement = function () { 8397 if (this.context.strict) { 8398 this.tolerateError(messages_1.Messages.StrictModeWith); 8399 } 8400 var node = this.createNode(); 8401 var body; 8402 this.expectKeyword('with'); 8403 this.expect('('); 8404 var object = this.parseExpression(); 8405 if (!this.match(')') && this.config.tolerant) { 8406 this.tolerateUnexpectedToken(this.nextToken()); 8407 body = this.finalize(this.createNode(), new Node.EmptyStatement()); 8408 } 8409 else { 8410 this.expect(')'); 8411 body = this.parseStatement(); 8412 } 8413 return this.finalize(node, new Node.WithStatement(object, body)); 8414 }; 8415 // https://tc39.github.io/ecma262/#sec-switch-statement 8416 Parser.prototype.parseSwitchCase = function () { 8417 var node = this.createNode(); 8418 var test; 8419 if (this.matchKeyword('default')) { 8420 this.nextToken(); 8421 test = null; 8422 } 8423 else { 8424 this.expectKeyword('case'); 8425 test = this.parseExpression(); 8426 } 8427 this.expect(':'); 8428 var consequent = []; 8429 while (true) { 8430 if (this.match('}') || this.matchKeyword('default') || this.matchKeyword('case')) { 8431 break; 8432 } 8433 consequent.push(this.parseStatementListItem()); 8434 } 8435 return this.finalize(node, new Node.SwitchCase(test, consequent)); 8436 }; 8437 Parser.prototype.parseSwitchStatement = function () { 8438 var node = this.createNode(); 8439 this.expectKeyword('switch'); 8440 this.expect('('); 8441 var discriminant = this.parseExpression(); 8442 this.expect(')'); 8443 var previousInSwitch = this.context.inSwitch; 8444 this.context.inSwitch = true; 8445 var cases = []; 8446 var defaultFound = false; 8447 this.expect('{'); 8448 while (true) { 8449 if (this.match('}')) { 8450 break; 8451 } 8452 var clause = this.parseSwitchCase(); 8453 if (clause.test === null) { 8454 if (defaultFound) { 8455 this.throwError(messages_1.Messages.MultipleDefaultsInSwitch); 8456 } 8457 defaultFound = true; 8458 } 8459 cases.push(clause); 8460 } 8461 this.expect('}'); 8462 this.context.inSwitch = previousInSwitch; 8463 return this.finalize(node, new Node.SwitchStatement(discriminant, cases)); 8464 }; 8465 // https://tc39.github.io/ecma262/#sec-labelled-statements 8466 Parser.prototype.parseLabelledStatement = function () { 8467 var node = this.createNode(); 8468 var expr = this.parseExpression(); 8469 var statement; 8470 if ((expr.type === syntax_1.Syntax.Identifier) && this.match(':')) { 8471 this.nextToken(); 8472 var id = expr; 8473 var key = '$' + id.name; 8474 if (Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { 8475 this.throwError(messages_1.Messages.Redeclaration, 'Label', id.name); 8476 } 8477 this.context.labelSet[key] = true; 8478 var body = void 0; 8479 if (this.matchKeyword('class')) { 8480 this.tolerateUnexpectedToken(this.lookahead); 8481 body = this.parseClassDeclaration(); 8482 } 8483 else if (this.matchKeyword('function')) { 8484 var token = this.lookahead; 8485 var declaration = this.parseFunctionDeclaration(); 8486 if (this.context.strict) { 8487 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunction); 8488 } 8489 else if (declaration.generator) { 8490 this.tolerateUnexpectedToken(token, messages_1.Messages.GeneratorInLegacyContext); 8491 } 8492 body = declaration; 8493 } 8494 else { 8495 body = this.parseStatement(); 8496 } 8497 delete this.context.labelSet[key]; 8498 statement = new Node.LabeledStatement(id, body); 8499 } 8500 else { 8501 this.consumeSemicolon(); 8502 statement = new Node.ExpressionStatement(expr); 8503 } 8504 return this.finalize(node, statement); 8505 }; 8506 // https://tc39.github.io/ecma262/#sec-throw-statement 8507 Parser.prototype.parseThrowStatement = function () { 8508 var node = this.createNode(); 8509 this.expectKeyword('throw'); 8510 if (this.hasLineTerminator) { 8511 this.throwError(messages_1.Messages.NewlineAfterThrow); 8512 } 8513 var argument = this.parseExpression(); 8514 this.consumeSemicolon(); 8515 return this.finalize(node, new Node.ThrowStatement(argument)); 8516 }; 8517 // https://tc39.github.io/ecma262/#sec-try-statement 8518 Parser.prototype.parseCatchClause = function () { 8519 var node = this.createNode(); 8520 this.expectKeyword('catch'); 8521 this.expect('('); 8522 if (this.match(')')) { 8523 this.throwUnexpectedToken(this.lookahead); 8524 } 8525 var params = []; 8526 var param = this.parsePattern(params); 8527 var paramMap = {}; 8528 for (var i = 0; i < params.length; i++) { 8529 var key = '$' + params[i].value; 8530 if (Object.prototype.hasOwnProperty.call(paramMap, key)) { 8531 this.tolerateError(messages_1.Messages.DuplicateBinding, params[i].value); 8532 } 8533 paramMap[key] = true; 8534 } 8535 if (this.context.strict && param.type === syntax_1.Syntax.Identifier) { 8536 if (this.scanner.isRestrictedWord(param.name)) { 8537 this.tolerateError(messages_1.Messages.StrictCatchVariable); 8538 } 8539 } 8540 this.expect(')'); 8541 var body = this.parseBlock(); 8542 return this.finalize(node, new Node.CatchClause(param, body)); 8543 }; 8544 Parser.prototype.parseFinallyClause = function () { 8545 this.expectKeyword('finally'); 8546 return this.parseBlock(); 8547 }; 8548 Parser.prototype.parseTryStatement = function () { 8549 var node = this.createNode(); 8550 this.expectKeyword('try'); 8551 var block = this.parseBlock(); 8552 var handler = this.matchKeyword('catch') ? this.parseCatchClause() : null; 8553 var finalizer = this.matchKeyword('finally') ? this.parseFinallyClause() : null; 8554 if (!handler && !finalizer) { 8555 this.throwError(messages_1.Messages.NoCatchOrFinally); 8556 } 8557 return this.finalize(node, new Node.TryStatement(block, handler, finalizer)); 8558 }; 8559 // https://tc39.github.io/ecma262/#sec-debugger-statement 8560 Parser.prototype.parseDebuggerStatement = function () { 8561 var node = this.createNode(); 8562 this.expectKeyword('debugger'); 8563 this.consumeSemicolon(); 8564 return this.finalize(node, new Node.DebuggerStatement()); 8565 }; 8566 // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations 8567 Parser.prototype.parseStatement = function () { 8568 var statement; 8569 switch (this.lookahead.type) { 8570 case 1 /* BooleanLiteral */: 8571 case 5 /* NullLiteral */: 8572 case 6 /* NumericLiteral */: 8573 case 8 /* StringLiteral */: 8574 case 10 /* Template */: 8575 case 9 /* RegularExpression */: 8576 statement = this.parseExpressionStatement(); 8577 break; 8578 case 7 /* Punctuator */: 8579 var value = this.lookahead.value; 8580 if (value === '{') { 8581 statement = this.parseBlock(); 8582 } 8583 else if (value === '(') { 8584 statement = this.parseExpressionStatement(); 8585 } 8586 else if (value === ';') { 8587 statement = this.parseEmptyStatement(); 8588 } 8589 else { 8590 statement = this.parseExpressionStatement(); 8591 } 8592 break; 8593 case 3 /* Identifier */: 8594 statement = this.matchAsyncFunction() ? this.parseFunctionDeclaration() : this.parseLabelledStatement(); 8595 break; 8596 case 4 /* Keyword */: 8597 switch (this.lookahead.value) { 8598 case 'break': 8599 statement = this.parseBreakStatement(); 8600 break; 8601 case 'continue': 8602 statement = this.parseContinueStatement(); 8603 break; 8604 case 'debugger': 8605 statement = this.parseDebuggerStatement(); 8606 break; 8607 case 'do': 8608 statement = this.parseDoWhileStatement(); 8609 break; 8610 case 'for': 8611 statement = this.parseForStatement(); 8612 break; 8613 case 'function': 8614 statement = this.parseFunctionDeclaration(); 8615 break; 8616 case 'if': 8617 statement = this.parseIfStatement(); 8618 break; 8619 case 'return': 8620 statement = this.parseReturnStatement(); 8621 break; 8622 case 'switch': 8623 statement = this.parseSwitchStatement(); 8624 break; 8625 case 'throw': 8626 statement = this.parseThrowStatement(); 8627 break; 8628 case 'try': 8629 statement = this.parseTryStatement(); 8630 break; 8631 case 'var': 8632 statement = this.parseVariableStatement(); 8633 break; 8634 case 'while': 8635 statement = this.parseWhileStatement(); 8636 break; 8637 case 'with': 8638 statement = this.parseWithStatement(); 8639 break; 8640 default: 8641 statement = this.parseExpressionStatement(); 8642 break; 8643 } 8644 break; 8645 default: 8646 statement = this.throwUnexpectedToken(this.lookahead); 8647 } 8648 return statement; 8649 }; 8650 // https://tc39.github.io/ecma262/#sec-function-definitions 8651 Parser.prototype.parseFunctionSourceElements = function () { 8652 var node = this.createNode(); 8653 this.expect('{'); 8654 var body = this.parseDirectivePrologues(); 8655 var previousLabelSet = this.context.labelSet; 8656 var previousInIteration = this.context.inIteration; 8657 var previousInSwitch = this.context.inSwitch; 8658 var previousInFunctionBody = this.context.inFunctionBody; 8659 this.context.labelSet = {}; 8660 this.context.inIteration = false; 8661 this.context.inSwitch = false; 8662 this.context.inFunctionBody = true; 8663 while (this.lookahead.type !== 2 /* EOF */) { 8664 if (this.match('}')) { 8665 break; 8666 } 8667 body.push(this.parseStatementListItem()); 8668 } 8669 this.expect('}'); 8670 this.context.labelSet = previousLabelSet; 8671 this.context.inIteration = previousInIteration; 8672 this.context.inSwitch = previousInSwitch; 8673 this.context.inFunctionBody = previousInFunctionBody; 8674 return this.finalize(node, new Node.BlockStatement(body)); 8675 }; 8676 Parser.prototype.validateParam = function (options, param, name) { 8677 var key = '$' + name; 8678 if (this.context.strict) { 8679 if (this.scanner.isRestrictedWord(name)) { 8680 options.stricted = param; 8681 options.message = messages_1.Messages.StrictParamName; 8682 } 8683 if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { 8684 options.stricted = param; 8685 options.message = messages_1.Messages.StrictParamDupe; 8686 } 8687 } 8688 else if (!options.firstRestricted) { 8689 if (this.scanner.isRestrictedWord(name)) { 8690 options.firstRestricted = param; 8691 options.message = messages_1.Messages.StrictParamName; 8692 } 8693 else if (this.scanner.isStrictModeReservedWord(name)) { 8694 options.firstRestricted = param; 8695 options.message = messages_1.Messages.StrictReservedWord; 8696 } 8697 else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { 8698 options.stricted = param; 8699 options.message = messages_1.Messages.StrictParamDupe; 8700 } 8701 } 8702 /* istanbul ignore next */ 8703 if (typeof Object.defineProperty === 'function') { 8704 Object.defineProperty(options.paramSet, key, { value: true, enumerable: true, writable: true, configurable: true }); 8705 } 8706 else { 8707 options.paramSet[key] = true; 8708 } 8709 }; 8710 Parser.prototype.parseRestElement = function (params) { 8711 var node = this.createNode(); 8712 this.expect('...'); 8713 var arg = this.parsePattern(params); 8714 if (this.match('=')) { 8715 this.throwError(messages_1.Messages.DefaultRestParameter); 8716 } 8717 if (!this.match(')')) { 8718 this.throwError(messages_1.Messages.ParameterAfterRestParameter); 8719 } 8720 return this.finalize(node, new Node.RestElement(arg)); 8721 }; 8722 Parser.prototype.parseFormalParameter = function (options) { 8723 var params = []; 8724 var param = this.match('...') ? this.parseRestElement(params) : this.parsePatternWithDefault(params); 8725 for (var i = 0; i < params.length; i++) { 8726 this.validateParam(options, params[i], params[i].value); 8727 } 8728 options.simple = options.simple && (param instanceof Node.Identifier); 8729 options.params.push(param); 8730 }; 8731 Parser.prototype.parseFormalParameters = function (firstRestricted) { 8732 var options; 8733 options = { 8734 simple: true, 8735 params: [], 8736 firstRestricted: firstRestricted 8737 }; 8738 this.expect('('); 8739 if (!this.match(')')) { 8740 options.paramSet = {}; 8741 while (this.lookahead.type !== 2 /* EOF */) { 8742 this.parseFormalParameter(options); 8743 if (this.match(')')) { 8744 break; 8745 } 8746 this.expect(','); 8747 if (this.match(')')) { 8748 break; 8749 } 8750 } 8751 } 8752 this.expect(')'); 8753 return { 8754 simple: options.simple, 8755 params: options.params, 8756 stricted: options.stricted, 8757 firstRestricted: options.firstRestricted, 8758 message: options.message 8759 }; 8760 }; 8761 Parser.prototype.matchAsyncFunction = function () { 8762 var match = this.matchContextualKeyword('async'); 8763 if (match) { 8764 var state = this.scanner.saveState(); 8765 this.scanner.scanComments(); 8766 var next = this.scanner.lex(); 8767 this.scanner.restoreState(state); 8768 match = (state.lineNumber === next.lineNumber) && (next.type === 4 /* Keyword */) && (next.value === 'function'); 8769 } 8770 return match; 8771 }; 8772 Parser.prototype.parseFunctionDeclaration = function (identifierIsOptional) { 8773 var node = this.createNode(); 8774 var isAsync = this.matchContextualKeyword('async'); 8775 if (isAsync) { 8776 this.nextToken(); 8777 } 8778 this.expectKeyword('function'); 8779 var isGenerator = isAsync ? false : this.match('*'); 8780 if (isGenerator) { 8781 this.nextToken(); 8782 } 8783 var message; 8784 var id = null; 8785 var firstRestricted = null; 8786 if (!identifierIsOptional || !this.match('(')) { 8787 var token = this.lookahead; 8788 id = this.parseVariableIdentifier(); 8789 if (this.context.strict) { 8790 if (this.scanner.isRestrictedWord(token.value)) { 8791 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); 8792 } 8793 } 8794 else { 8795 if (this.scanner.isRestrictedWord(token.value)) { 8796 firstRestricted = token; 8797 message = messages_1.Messages.StrictFunctionName; 8798 } 8799 else if (this.scanner.isStrictModeReservedWord(token.value)) { 8800 firstRestricted = token; 8801 message = messages_1.Messages.StrictReservedWord; 8802 } 8803 } 8804 } 8805 var previousAllowAwait = this.context.await; 8806 var previousAllowYield = this.context.allowYield; 8807 this.context.await = isAsync; 8808 this.context.allowYield = !isGenerator; 8809 var formalParameters = this.parseFormalParameters(firstRestricted); 8810 var params = formalParameters.params; 8811 var stricted = formalParameters.stricted; 8812 firstRestricted = formalParameters.firstRestricted; 8813 if (formalParameters.message) { 8814 message = formalParameters.message; 8815 } 8816 var previousStrict = this.context.strict; 8817 var previousAllowStrictDirective = this.context.allowStrictDirective; 8818 this.context.allowStrictDirective = formalParameters.simple; 8819 var body = this.parseFunctionSourceElements(); 8820 if (this.context.strict && firstRestricted) { 8821 this.throwUnexpectedToken(firstRestricted, message); 8822 } 8823 if (this.context.strict && stricted) { 8824 this.tolerateUnexpectedToken(stricted, message); 8825 } 8826 this.context.strict = previousStrict; 8827 this.context.allowStrictDirective = previousAllowStrictDirective; 8828 this.context.await = previousAllowAwait; 8829 this.context.allowYield = previousAllowYield; 8830 return isAsync ? this.finalize(node, new Node.AsyncFunctionDeclaration(id, params, body)) : 8831 this.finalize(node, new Node.FunctionDeclaration(id, params, body, isGenerator)); 8832 }; 8833 Parser.prototype.parseFunctionExpression = function () { 8834 var node = this.createNode(); 8835 var isAsync = this.matchContextualKeyword('async'); 8836 if (isAsync) { 8837 this.nextToken(); 8838 } 8839 this.expectKeyword('function'); 8840 var isGenerator = isAsync ? false : this.match('*'); 8841 if (isGenerator) { 8842 this.nextToken(); 8843 } 8844 var message; 8845 var id = null; 8846 var firstRestricted; 8847 var previousAllowAwait = this.context.await; 8848 var previousAllowYield = this.context.allowYield; 8849 this.context.await = isAsync; 8850 this.context.allowYield = !isGenerator; 8851 if (!this.match('(')) { 8852 var token = this.lookahead; 8853 id = (!this.context.strict && !isGenerator && this.matchKeyword('yield')) ? this.parseIdentifierName() : this.parseVariableIdentifier(); 8854 if (this.context.strict) { 8855 if (this.scanner.isRestrictedWord(token.value)) { 8856 this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); 8857 } 8858 } 8859 else { 8860 if (this.scanner.isRestrictedWord(token.value)) { 8861 firstRestricted = token; 8862 message = messages_1.Messages.StrictFunctionName; 8863 } 8864 else if (this.scanner.isStrictModeReservedWord(token.value)) { 8865 firstRestricted = token; 8866 message = messages_1.Messages.StrictReservedWord; 8867 } 8868 } 8869 } 8870 var formalParameters = this.parseFormalParameters(firstRestricted); 8871 var params = formalParameters.params; 8872 var stricted = formalParameters.stricted; 8873 firstRestricted = formalParameters.firstRestricted; 8874 if (formalParameters.message) { 8875 message = formalParameters.message; 8876 } 8877 var previousStrict = this.context.strict; 8878 var previousAllowStrictDirective = this.context.allowStrictDirective; 8879 this.context.allowStrictDirective = formalParameters.simple; 8880 var body = this.parseFunctionSourceElements(); 8881 if (this.context.strict && firstRestricted) { 8882 this.throwUnexpectedToken(firstRestricted, message); 8883 } 8884 if (this.context.strict && stricted) { 8885 this.tolerateUnexpectedToken(stricted, message); 8886 } 8887 this.context.strict = previousStrict; 8888 this.context.allowStrictDirective = previousAllowStrictDirective; 8889 this.context.await = previousAllowAwait; 8890 this.context.allowYield = previousAllowYield; 8891 return isAsync ? this.finalize(node, new Node.AsyncFunctionExpression(id, params, body)) : 8892 this.finalize(node, new Node.FunctionExpression(id, params, body, isGenerator)); 8893 }; 8894 // https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive 8895 Parser.prototype.parseDirective = function () { 8896 var token = this.lookahead; 8897 var node = this.createNode(); 8898 var expr = this.parseExpression(); 8899 var directive = (expr.type === syntax_1.Syntax.Literal) ? this.getTokenRaw(token).slice(1, -1) : null; 8900 this.consumeSemicolon(); 8901 return this.finalize(node, directive ? new Node.Directive(expr, directive) : new Node.ExpressionStatement(expr)); 8902 }; 8903 Parser.prototype.parseDirectivePrologues = function () { 8904 var firstRestricted = null; 8905 var body = []; 8906 while (true) { 8907 var token = this.lookahead; 8908 if (token.type !== 8 /* StringLiteral */) { 8909 break; 8910 } 8911 var statement = this.parseDirective(); 8912 body.push(statement); 8913 var directive = statement.directive; 8914 if (typeof directive !== 'string') { 8915 break; 8916 } 8917 if (directive === 'use strict') { 8918 this.context.strict = true; 8919 if (firstRestricted) { 8920 this.tolerateUnexpectedToken(firstRestricted, messages_1.Messages.StrictOctalLiteral); 8921 } 8922 if (!this.context.allowStrictDirective) { 8923 this.tolerateUnexpectedToken(token, messages_1.Messages.IllegalLanguageModeDirective); 8924 } 8925 } 8926 else { 8927 if (!firstRestricted && token.octal) { 8928 firstRestricted = token; 8929 } 8930 } 8931 } 8932 return body; 8933 }; 8934 // https://tc39.github.io/ecma262/#sec-method-definitions 8935 Parser.prototype.qualifiedPropertyName = function (token) { 8936 switch (token.type) { 8937 case 3 /* Identifier */: 8938 case 8 /* StringLiteral */: 8939 case 1 /* BooleanLiteral */: 8940 case 5 /* NullLiteral */: 8941 case 6 /* NumericLiteral */: 8942 case 4 /* Keyword */: 8943 return true; 8944 case 7 /* Punctuator */: 8945 return token.value === '['; 8946 default: 8947 break; 8948 } 8949 return false; 8950 }; 8951 Parser.prototype.parseGetterMethod = function () { 8952 var node = this.createNode(); 8953 var isGenerator = false; 8954 var previousAllowYield = this.context.allowYield; 8955 this.context.allowYield = !isGenerator; 8956 var formalParameters = this.parseFormalParameters(); 8957 if (formalParameters.params.length > 0) { 8958 this.tolerateError(messages_1.Messages.BadGetterArity); 8959 } 8960 var method = this.parsePropertyMethod(formalParameters); 8961 this.context.allowYield = previousAllowYield; 8962 return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); 8963 }; 8964 Parser.prototype.parseSetterMethod = function () { 8965 var node = this.createNode(); 8966 var isGenerator = false; 8967 var previousAllowYield = this.context.allowYield; 8968 this.context.allowYield = !isGenerator; 8969 var formalParameters = this.parseFormalParameters(); 8970 if (formalParameters.params.length !== 1) { 8971 this.tolerateError(messages_1.Messages.BadSetterArity); 8972 } 8973 else if (formalParameters.params[0] instanceof Node.RestElement) { 8974 this.tolerateError(messages_1.Messages.BadSetterRestParameter); 8975 } 8976 var method = this.parsePropertyMethod(formalParameters); 8977 this.context.allowYield = previousAllowYield; 8978 return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); 8979 }; 8980 Parser.prototype.parseGeneratorMethod = function () { 8981 var node = this.createNode(); 8982 var isGenerator = true; 8983 var previousAllowYield = this.context.allowYield; 8984 this.context.allowYield = true; 8985 var params = this.parseFormalParameters(); 8986 this.context.allowYield = false; 8987 var method = this.parsePropertyMethod(params); 8988 this.context.allowYield = previousAllowYield; 8989 return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); 8990 }; 8991 // https://tc39.github.io/ecma262/#sec-generator-function-definitions 8992 Parser.prototype.isStartOfExpression = function () { 8993 var start = true; 8994 var value = this.lookahead.value; 8995 switch (this.lookahead.type) { 8996 case 7 /* Punctuator */: 8997 start = (value === '[') || (value === '(') || (value === '{') || 8998 (value === '+') || (value === '-') || 8999 (value === '!') || (value === '~') || 9000 (value === '++') || (value === '--') || 9001 (value === '/') || (value === '/='); // regular expression literal 9002 break; 9003 case 4 /* Keyword */: 9004 start = (value === 'class') || (value === 'delete') || 9005 (value === 'function') || (value === 'let') || (value === 'new') || 9006 (value === 'super') || (value === 'this') || (value === 'typeof') || 9007 (value === 'void') || (value === 'yield'); 9008 break; 9009 default: 9010 break; 9011 } 9012 return start; 9013 }; 9014 Parser.prototype.parseYieldExpression = function () { 9015 var node = this.createNode(); 9016 this.expectKeyword('yield'); 9017 var argument = null; 9018 var delegate = false; 9019 if (!this.hasLineTerminator) { 9020 var previousAllowYield = this.context.allowYield; 9021 this.context.allowYield = false; 9022 delegate = this.match('*'); 9023 if (delegate) { 9024 this.nextToken(); 9025 argument = this.parseAssignmentExpression(); 9026 } 9027 else if (this.isStartOfExpression()) { 9028 argument = this.parseAssignmentExpression(); 9029 } 9030 this.context.allowYield = previousAllowYield; 9031 } 9032 return this.finalize(node, new Node.YieldExpression(argument, delegate)); 9033 }; 9034 // https://tc39.github.io/ecma262/#sec-class-definitions 9035 Parser.prototype.parseClassElement = function (hasConstructor) { 9036 var token = this.lookahead; 9037 var node = this.createNode(); 9038 var kind = ''; 9039 var key = null; 9040 var value = null; 9041 var computed = false; 9042 var method = false; 9043 var isStatic = false; 9044 var isAsync = false; 9045 if (this.match('*')) { 9046 this.nextToken(); 9047 } 9048 else { 9049 computed = this.match('['); 9050 key = this.parseObjectPropertyKey(); 9051 var id = key; 9052 if (id.name === 'static' && (this.qualifiedPropertyName(this.lookahead) || this.match('*'))) { 9053 token = this.lookahead; 9054 isStatic = true; 9055 computed = this.match('['); 9056 if (this.match('*')) { 9057 this.nextToken(); 9058 } 9059 else { 9060 key = this.parseObjectPropertyKey(); 9061 } 9062 } 9063 if ((token.type === 3 /* Identifier */) && !this.hasLineTerminator && (token.value === 'async')) { 9064 var punctuator = this.lookahead.value; 9065 if (punctuator !== ':' && punctuator !== '(' && punctuator !== '*') { 9066 isAsync = true; 9067 token = this.lookahead; 9068 key = this.parseObjectPropertyKey(); 9069 if (token.type === 3 /* Identifier */ && token.value === 'constructor') { 9070 this.tolerateUnexpectedToken(token, messages_1.Messages.ConstructorIsAsync); 9071 } 9072 } 9073 } 9074 } 9075 var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); 9076 if (token.type === 3 /* Identifier */) { 9077 if (token.value === 'get' && lookaheadPropertyKey) { 9078 kind = 'get'; 9079 computed = this.match('['); 9080 key = this.parseObjectPropertyKey(); 9081 this.context.allowYield = false; 9082 value = this.parseGetterMethod(); 9083 } 9084 else if (token.value === 'set' && lookaheadPropertyKey) { 9085 kind = 'set'; 9086 computed = this.match('['); 9087 key = this.parseObjectPropertyKey(); 9088 value = this.parseSetterMethod(); 9089 } 9090 } 9091 else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { 9092 kind = 'init'; 9093 computed = this.match('['); 9094 key = this.parseObjectPropertyKey(); 9095 value = this.parseGeneratorMethod(); 9096 method = true; 9097 } 9098 if (!kind && key && this.match('(')) { 9099 kind = 'init'; 9100 value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); 9101 method = true; 9102 } 9103 if (!kind) { 9104 this.throwUnexpectedToken(this.lookahead); 9105 } 9106 if (kind === 'init') { 9107 kind = 'method'; 9108 } 9109 if (!computed) { 9110 if (isStatic && this.isPropertyKey(key, 'prototype')) { 9111 this.throwUnexpectedToken(token, messages_1.Messages.StaticPrototype); 9112 } 9113 if (!isStatic && this.isPropertyKey(key, 'constructor')) { 9114 if (kind !== 'method' || !method || (value && value.generator)) { 9115 this.throwUnexpectedToken(token, messages_1.Messages.ConstructorSpecialMethod); 9116 } 9117 if (hasConstructor.value) { 9118 this.throwUnexpectedToken(token, messages_1.Messages.DuplicateConstructor); 9119 } 9120 else { 9121 hasConstructor.value = true; 9122 } 9123 kind = 'constructor'; 9124 } 9125 } 9126 return this.finalize(node, new Node.MethodDefinition(key, computed, value, kind, isStatic)); 9127 }; 9128 Parser.prototype.parseClassElementList = function () { 9129 var body = []; 9130 var hasConstructor = { value: false }; 9131 this.expect('{'); 9132 while (!this.match('}')) { 9133 if (this.match(';')) { 9134 this.nextToken(); 9135 } 9136 else { 9137 body.push(this.parseClassElement(hasConstructor)); 9138 } 9139 } 9140 this.expect('}'); 9141 return body; 9142 }; 9143 Parser.prototype.parseClassBody = function () { 9144 var node = this.createNode(); 9145 var elementList = this.parseClassElementList(); 9146 return this.finalize(node, new Node.ClassBody(elementList)); 9147 }; 9148 Parser.prototype.parseClassDeclaration = function (identifierIsOptional) { 9149 var node = this.createNode(); 9150 var previousStrict = this.context.strict; 9151 this.context.strict = true; 9152 this.expectKeyword('class'); 9153 var id = (identifierIsOptional && (this.lookahead.type !== 3 /* Identifier */)) ? null : this.parseVariableIdentifier(); 9154 var superClass = null; 9155 if (this.matchKeyword('extends')) { 9156 this.nextToken(); 9157 superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); 9158 } 9159 var classBody = this.parseClassBody(); 9160 this.context.strict = previousStrict; 9161 return this.finalize(node, new Node.ClassDeclaration(id, superClass, classBody)); 9162 }; 9163 Parser.prototype.parseClassExpression = function () { 9164 var node = this.createNode(); 9165 var previousStrict = this.context.strict; 9166 this.context.strict = true; 9167 this.expectKeyword('class'); 9168 var id = (this.lookahead.type === 3 /* Identifier */) ? this.parseVariableIdentifier() : null; 9169 var superClass = null; 9170 if (this.matchKeyword('extends')) { 9171 this.nextToken(); 9172 superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); 9173 } 9174 var classBody = this.parseClassBody(); 9175 this.context.strict = previousStrict; 9176 return this.finalize(node, new Node.ClassExpression(id, superClass, classBody)); 9177 }; 9178 // https://tc39.github.io/ecma262/#sec-scripts 9179 // https://tc39.github.io/ecma262/#sec-modules 9180 Parser.prototype.parseModule = function () { 9181 this.context.strict = true; 9182 this.context.isModule = true; 9183 this.scanner.isModule = true; 9184 var node = this.createNode(); 9185 var body = this.parseDirectivePrologues(); 9186 while (this.lookahead.type !== 2 /* EOF */) { 9187 body.push(this.parseStatementListItem()); 9188 } 9189 return this.finalize(node, new Node.Module(body)); 9190 }; 9191 Parser.prototype.parseScript = function () { 9192 var node = this.createNode(); 9193 var body = this.parseDirectivePrologues(); 9194 while (this.lookahead.type !== 2 /* EOF */) { 9195 body.push(this.parseStatementListItem()); 9196 } 9197 return this.finalize(node, new Node.Script(body)); 9198 }; 9199 // https://tc39.github.io/ecma262/#sec-imports 9200 Parser.prototype.parseModuleSpecifier = function () { 9201 var node = this.createNode(); 9202 if (this.lookahead.type !== 8 /* StringLiteral */) { 9203 this.throwError(messages_1.Messages.InvalidModuleSpecifier); 9204 } 9205 var token = this.nextToken(); 9206 var raw = this.getTokenRaw(token); 9207 return this.finalize(node, new Node.Literal(token.value, raw)); 9208 }; 9209 // import {<foo as bar>} ...; 9210 Parser.prototype.parseImportSpecifier = function () { 9211 var node = this.createNode(); 9212 var imported; 9213 var local; 9214 if (this.lookahead.type === 3 /* Identifier */) { 9215 imported = this.parseVariableIdentifier(); 9216 local = imported; 9217 if (this.matchContextualKeyword('as')) { 9218 this.nextToken(); 9219 local = this.parseVariableIdentifier(); 9220 } 9221 } 9222 else { 9223 imported = this.parseIdentifierName(); 9224 local = imported; 9225 if (this.matchContextualKeyword('as')) { 9226 this.nextToken(); 9227 local = this.parseVariableIdentifier(); 9228 } 9229 else { 9230 this.throwUnexpectedToken(this.nextToken()); 9231 } 9232 } 9233 return this.finalize(node, new Node.ImportSpecifier(local, imported)); 9234 }; 9235 // {foo, bar as bas} 9236 Parser.prototype.parseNamedImports = function () { 9237 this.expect('{'); 9238 var specifiers = []; 9239 while (!this.match('}')) { 9240 specifiers.push(this.parseImportSpecifier()); 9241 if (!this.match('}')) { 9242 this.expect(','); 9243 } 9244 } 9245 this.expect('}'); 9246 return specifiers; 9247 }; 9248 // import <foo> ...; 9249 Parser.prototype.parseImportDefaultSpecifier = function () { 9250 var node = this.createNode(); 9251 var local = this.parseIdentifierName(); 9252 return this.finalize(node, new Node.ImportDefaultSpecifier(local)); 9253 }; 9254 // import <* as foo> ...; 9255 Parser.prototype.parseImportNamespaceSpecifier = function () { 9256 var node = this.createNode(); 9257 this.expect('*'); 9258 if (!this.matchContextualKeyword('as')) { 9259 this.throwError(messages_1.Messages.NoAsAfterImportNamespace); 9260 } 9261 this.nextToken(); 9262 var local = this.parseIdentifierName(); 9263 return this.finalize(node, new Node.ImportNamespaceSpecifier(local)); 9264 }; 9265 Parser.prototype.parseImportDeclaration = function () { 9266 if (this.context.inFunctionBody) { 9267 this.throwError(messages_1.Messages.IllegalImportDeclaration); 9268 } 9269 var node = this.createNode(); 9270 this.expectKeyword('import'); 9271 var src; 9272 var specifiers = []; 9273 if (this.lookahead.type === 8 /* StringLiteral */) { 9274 // import 'foo'; 9275 src = this.parseModuleSpecifier(); 9276 } 9277 else { 9278 if (this.match('{')) { 9279 // import {bar} 9280 specifiers = specifiers.concat(this.parseNamedImports()); 9281 } 9282 else if (this.match('*')) { 9283 // import * as foo 9284 specifiers.push(this.parseImportNamespaceSpecifier()); 9285 } 9286 else if (this.isIdentifierName(this.lookahead) && !this.matchKeyword('default')) { 9287 // import foo 9288 specifiers.push(this.parseImportDefaultSpecifier()); 9289 if (this.match(',')) { 9290 this.nextToken(); 9291 if (this.match('*')) { 9292 // import foo, * as foo 9293 specifiers.push(this.parseImportNamespaceSpecifier()); 9294 } 9295 else if (this.match('{')) { 9296 // import foo, {bar} 9297 specifiers = specifiers.concat(this.parseNamedImports()); 9298 } 9299 else { 9300 this.throwUnexpectedToken(this.lookahead); 9301 } 9302 } 9303 } 9304 else { 9305 this.throwUnexpectedToken(this.nextToken()); 9306 } 9307 if (!this.matchContextualKeyword('from')) { 9308 var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; 9309 this.throwError(message, this.lookahead.value); 9310 } 9311 this.nextToken(); 9312 src = this.parseModuleSpecifier(); 9313 } 9314 this.consumeSemicolon(); 9315 return this.finalize(node, new Node.ImportDeclaration(specifiers, src)); 9316 }; 9317 // https://tc39.github.io/ecma262/#sec-exports 9318 Parser.prototype.parseExportSpecifier = function () { 9319 var node = this.createNode(); 9320 var local = this.parseIdentifierName(); 9321 var exported = local; 9322 if (this.matchContextualKeyword('as')) { 9323 this.nextToken(); 9324 exported = this.parseIdentifierName(); 9325 } 9326 return this.finalize(node, new Node.ExportSpecifier(local, exported)); 9327 }; 9328 Parser.prototype.parseExportDeclaration = function () { 9329 if (this.context.inFunctionBody) { 9330 this.throwError(messages_1.Messages.IllegalExportDeclaration); 9331 } 9332 var node = this.createNode(); 9333 this.expectKeyword('export'); 9334 var exportDeclaration; 9335 if (this.matchKeyword('default')) { 9336 // export default ... 9337 this.nextToken(); 9338 if (this.matchKeyword('function')) { 9339 // export default function foo () {} 9340 // export default function () {} 9341 var declaration = this.parseFunctionDeclaration(true); 9342 exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); 9343 } 9344 else if (this.matchKeyword('class')) { 9345 // export default class foo {} 9346 var declaration = this.parseClassDeclaration(true); 9347 exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); 9348 } 9349 else if (this.matchContextualKeyword('async')) { 9350 // export default async function f () {} 9351 // export default async function () {} 9352 // export default async x => x 9353 var declaration = this.matchAsyncFunction() ? this.parseFunctionDeclaration(true) : this.parseAssignmentExpression(); 9354 exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); 9355 } 9356 else { 9357 if (this.matchContextualKeyword('from')) { 9358 this.throwError(messages_1.Messages.UnexpectedToken, this.lookahead.value); 9359 } 9360 // export default {}; 9361 // export default []; 9362 // export default (1 + 2); 9363 var declaration = this.match('{') ? this.parseObjectInitializer() : 9364 this.match('[') ? this.parseArrayInitializer() : this.parseAssignmentExpression(); 9365 this.consumeSemicolon(); 9366 exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); 9367 } 9368 } 9369 else if (this.match('*')) { 9370 // export * from 'foo'; 9371 this.nextToken(); 9372 if (!this.matchContextualKeyword('from')) { 9373 var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; 9374 this.throwError(message, this.lookahead.value); 9375 } 9376 this.nextToken(); 9377 var src = this.parseModuleSpecifier(); 9378 this.consumeSemicolon(); 9379 exportDeclaration = this.finalize(node, new Node.ExportAllDeclaration(src)); 9380 } 9381 else if (this.lookahead.type === 4 /* Keyword */) { 9382 // export var f = 1; 9383 var declaration = void 0; 9384 switch (this.lookahead.value) { 9385 case 'let': 9386 case 'const': 9387 declaration = this.parseLexicalDeclaration({ inFor: false }); 9388 break; 9389 case 'var': 9390 case 'class': 9391 case 'function': 9392 declaration = this.parseStatementListItem(); 9393 break; 9394 default: 9395 this.throwUnexpectedToken(this.lookahead); 9396 } 9397 exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); 9398 } 9399 else if (this.matchAsyncFunction()) { 9400 var declaration = this.parseFunctionDeclaration(); 9401 exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); 9402 } 9403 else { 9404 var specifiers = []; 9405 var source = null; 9406 var isExportFromIdentifier = false; 9407 this.expect('{'); 9408 while (!this.match('}')) { 9409 isExportFromIdentifier = isExportFromIdentifier || this.matchKeyword('default'); 9410 specifiers.push(this.parseExportSpecifier()); 9411 if (!this.match('}')) { 9412 this.expect(','); 9413 } 9414 } 9415 this.expect('}'); 9416 if (this.matchContextualKeyword('from')) { 9417 // export {default} from 'foo'; 9418 // export {foo} from 'foo'; 9419 this.nextToken(); 9420 source = this.parseModuleSpecifier(); 9421 this.consumeSemicolon(); 9422 } 9423 else if (isExportFromIdentifier) { 9424 // export {default}; // missing fromClause 9425 var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; 9426 this.throwError(message, this.lookahead.value); 9427 } 9428 else { 9429 // export {foo}; 9430 this.consumeSemicolon(); 9431 } 9432 exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(null, specifiers, source)); 9433 } 9434 return exportDeclaration; 9435 }; 9436 return Parser; 9437 }()); 9438 exports.Parser = Parser; 9439 9440 9441 /***/ }, 9442 /* 9 */ 9443 /***/ function(module, exports) { 9444 9445 "use strict"; 9446 // Ensure the condition is true, otherwise throw an error. 9447 // This is only to have a better contract semantic, i.e. another safety net 9448 // to catch a logic error. The condition shall be fulfilled in normal case. 9449 // Do NOT use this to enforce a certain condition on any user input. 9450 Object.defineProperty(exports, "__esModule", { value: true }); 9451 function assert(condition, message) { 9452 /* istanbul ignore if */ 9453 if (!condition) { 9454 throw new Error('ASSERT: ' + message); 9455 } 9456 } 9457 exports.assert = assert; 9458 9459 9460 /***/ }, 9461 /* 10 */ 9462 /***/ function(module, exports) { 9463 9464 "use strict"; 9465 /* tslint:disable:max-classes-per-file */ 9466 Object.defineProperty(exports, "__esModule", { value: true }); 9467 var ErrorHandler = (function () { 9468 function ErrorHandler() { 9469 this.errors = []; 9470 this.tolerant = false; 9471 } 9472 ErrorHandler.prototype.recordError = function (error) { 9473 this.errors.push(error); 9474 }; 9475 ErrorHandler.prototype.tolerate = function (error) { 9476 if (this.tolerant) { 9477 this.recordError(error); 9478 } 9479 else { 9480 throw error; 9481 } 9482 }; 9483 ErrorHandler.prototype.constructError = function (msg, column) { 9484 var error = new Error(msg); 9485 try { 9486 throw error; 9487 } 9488 catch (base) { 9489 /* istanbul ignore else */ 9490 if (Object.create && Object.defineProperty) { 9491 error = Object.create(base); 9492 Object.defineProperty(error, 'column', { value: column }); 9493 } 9494 } 9495 /* istanbul ignore next */ 9496 return error; 9497 }; 9498 ErrorHandler.prototype.createError = function (index, line, col, description) {
9499 var msg = 'Line ' + line + ': ' + description; 9500 var error = this.constructError(msg, col); 9501 error.index = index; 9502 error.lineNumber = line; 9503 error.description = description; 9504 return error; 9505 }; 9506 ErrorHandler.prototype.throwError = function (index, line, col, description) { 9507 throw this.createError(index, line, col, description); 9508 }; 9509 ErrorHandler.prototype.tolerateError = function (index, line, col, description) { 9510 var error = this.createError(index, line, col, description); 9511 if (this.tolerant) { 9512 this.recordError(error); 9513 } 9514 else { 9515 throw error; 9516 } 9517 }; 9518 return ErrorHandler; 9519 }()); 9520 exports.ErrorHandler = ErrorHandler; 9521 9522 9523 /***/ }, 9524 /* 11 */ 9525 /***/ function(module, exports) { 9526 9527 "use strict"; 9528 Object.defineProperty(exports, "__esModule", { value: true }); 9529 // Error messages should be identical to V8. 9530 exports.Messages = { 9531 BadGetterArity: 'Getter must not have any formal parameters', 9532 BadSetterArity: 'Setter must have exactly one formal parameter', 9533 BadSetterRestParameter: 'Setter function argument must not be a rest parameter', 9534 ConstructorIsAsync: 'Class constructor may not be an async method', 9535 ConstructorSpecialMethod: 'Class constructor may not be an accessor', 9536 DeclarationMissingInitializer: 'Missing initializer in %0 declaration', 9537 DefaultRestParameter: 'Unexpected token =', 9538 DuplicateBinding: 'Duplicate binding %0', 9539 DuplicateConstructor: 'A class may only have one constructor', 9540 DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals', 9541 ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer', 9542 GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts', 9543 IllegalBreak: 'Illegal break statement', 9544 IllegalContinue: 'Illegal continue statement', 9545 IllegalExportDeclaration: 'Unexpected token', 9546 IllegalImportDeclaration: 'Unexpected token', 9547 IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list', 9548 IllegalReturn: 'Illegal return statement', 9549 InvalidEscapedReservedWord: 'Keyword must not contain escaped characters', 9550 InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence', 9551 InvalidLHSInAssignment: 'Invalid left-hand side in assignment', 9552 InvalidLHSInForIn: 'Invalid left-hand side in for-in', 9553 InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', 9554 InvalidModuleSpecifier: 'Unexpected token', 9555 InvalidRegExp: 'Invalid regular expression', 9556 LetInLexicalBinding: 'let is disallowed as a lexically bound name', 9557 MissingFromClause: 'Unexpected token', 9558 MultipleDefaultsInSwitch: 'More than one default clause in switch statement', 9559 NewlineAfterThrow: 'Illegal newline after throw', 9560 NoAsAfterImportNamespace: 'Unexpected token', 9561 NoCatchOrFinally: 'Missing catch or finally after try', 9562 ParameterAfterRestParameter: 'Rest parameter must be last formal parameter', 9563 Redeclaration: '%0 \'%1\' has already been declared', 9564 StaticPrototype: 'Classes may not have static property named prototype', 9565 StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', 9566 StrictDelete: 'Delete of an unqualified identifier in strict mode.',
vendor: 64,095 bytes, lines 9567-10597
9567 StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block', 9568 StrictFunctionName: 'Function name may not be eval or arguments in strict mode', 9569 StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', 9570 StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', 9571 StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', 9572 StrictModeWith: 'Strict mode code may not include a with statement', 9573 StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', 9574 StrictParamDupe: 'Strict mode function may not have duplicate parameter names', 9575 StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', 9576 StrictReservedWord: 'Use of future reserved word in strict mode', 9577 StrictVarName: 'Variable name may not be eval or arguments in strict mode', 9578 TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', 9579 UnexpectedEOS: 'Unexpected end of input', 9580 UnexpectedIdentifier: 'Unexpected identifier', 9581 UnexpectedNumber: 'Unexpected number', 9582 UnexpectedReserved: 'Unexpected reserved word', 9583 UnexpectedString: 'Unexpected string', 9584 UnexpectedTemplate: 'Unexpected quasi %0', 9585 UnexpectedToken: 'Unexpected token %0', 9586 UnexpectedTokenIllegal: 'Unexpected token ILLEGAL', 9587 UnknownLabel: 'Undefined label \'%0\'', 9588 UnterminatedRegExp: 'Invalid regular expression: missing /' 9589 }; 9590 9591 9592 /***/ }, 9593 /* 12 */ 9594 /***/ function(module, exports, __webpack_require__) { 9595 9596 "use strict"; 9597 Object.defineProperty(exports, "__esModule", { value: true }); 9598 var assert_1 = __webpack_require__(9); 9599 var character_1 = __webpack_require__(4); 9600 var messages_1 = __webpack_require__(11); 9601 function hexValue(ch) { 9602 return '0123456789abcdef'.indexOf(ch.toLowerCase()); 9603 } 9604 function octalValue(ch) { 9605 return '01234567'.indexOf(ch); 9606 } 9607 var Scanner = (function () { 9608 function Scanner(code, handler) { 9609 this.source = code; 9610 this.errorHandler = handler; 9611 this.trackComment = false; 9612 this.isModule = false; 9613 this.length = code.length; 9614 this.index = 0; 9615 this.lineNumber = (code.length > 0) ? 1 : 0; 9616 this.lineStart = 0; 9617 this.curlyStack = []; 9618 } 9619 Scanner.prototype.saveState = function () { 9620 return { 9621 index: this.index, 9622 lineNumber: this.lineNumber, 9623 lineStart: this.lineStart 9624 }; 9625 }; 9626 Scanner.prototype.restoreState = function (state) { 9627 this.index = state.index; 9628 this.lineNumber = state.lineNumber; 9629 this.lineStart = state.lineStart; 9630 }; 9631 Scanner.prototype.eof = function () { 9632 return this.index >= this.length; 9633 }; 9634 Scanner.prototype.throwUnexpectedToken = function (message) { 9635 if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } 9636 return this.errorHandler.throwError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); 9637 }; 9638 Scanner.prototype.tolerateUnexpectedToken = function (message) { 9639 if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } 9640 this.errorHandler.tolerateError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); 9641 }; 9642 // https://tc39.github.io/ecma262/#sec-comments 9643 Scanner.prototype.skipSingleLineComment = function (offset) { 9644 var comments = []; 9645 var start, loc; 9646 if (this.trackComment) { 9647 comments = []; 9648 start = this.index - offset; 9649 loc = { 9650 start: { 9651 line: this.lineNumber, 9652 column: this.index - this.lineStart - offset 9653 }, 9654 end: {} 9655 }; 9656 } 9657 while (!this.eof()) { 9658 var ch = this.source.charCodeAt(this.index); 9659 ++this.index; 9660 if (character_1.Character.isLineTerminator(ch)) { 9661 if (this.trackComment) { 9662 loc.end = { 9663 line: this.lineNumber, 9664 column: this.index - this.lineStart - 1 9665 }; 9666 var entry = { 9667 multiLine: false, 9668 slice: [start + offset, this.index - 1], 9669 range: [start, this.index - 1], 9670 loc: loc 9671 }; 9672 comments.push(entry); 9673 } 9674 if (ch === 13 && this.source.charCodeAt(this.index) === 10) { 9675 ++this.index; 9676 } 9677 ++this.lineNumber; 9678 this.lineStart = this.index; 9679 return comments; 9680 } 9681 } 9682 if (this.trackComment) { 9683 loc.end = { 9684 line: this.lineNumber, 9685 column: this.index - this.lineStart 9686 }; 9687 var entry = { 9688 multiLine: false, 9689 slice: [start + offset, this.index], 9690 range: [start, this.index], 9691 loc: loc 9692 }; 9693 comments.push(entry); 9694 } 9695 return comments; 9696 }; 9697 Scanner.prototype.skipMultiLineComment = function () { 9698 var comments = []; 9699 var start, loc; 9700 if (this.trackComment) { 9701 comments = []; 9702 start = this.index - 2; 9703 loc = { 9704 start: { 9705 line: this.lineNumber, 9706 column: this.index - this.lineStart - 2 9707 }, 9708 end: {} 9709 }; 9710 } 9711 while (!this.eof()) { 9712 var ch = this.source.charCodeAt(this.index); 9713 if (character_1.Character.isLineTerminator(ch)) { 9714 if (ch === 0x0D && this.source.charCodeAt(this.index + 1) === 0x0A) { 9715 ++this.index; 9716 } 9717 ++this.lineNumber; 9718 ++this.index; 9719 this.lineStart = this.index; 9720 } 9721 else if (ch === 0x2A) { 9722 // Block comment ends with '*/'. 9723 if (this.source.charCodeAt(this.index + 1) === 0x2F) { 9724 this.index += 2; 9725 if (this.trackComment) { 9726 loc.end = { 9727 line: this.lineNumber, 9728 column: this.index - this.lineStart 9729 }; 9730 var entry = { 9731 multiLine: true, 9732 slice: [start + 2, this.index - 2], 9733 range: [start, this.index], 9734 loc: loc 9735 }; 9736 comments.push(entry); 9737 } 9738 return comments; 9739 } 9740 ++this.index; 9741 } 9742 else { 9743 ++this.index; 9744 } 9745 } 9746 // Ran off the end of the file - the whole thing is a comment 9747 if (this.trackComment) { 9748 loc.end = { 9749 line: this.lineNumber, 9750 column: this.index - this.lineStart 9751 }; 9752 var entry = { 9753 multiLine: true, 9754 slice: [start + 2, this.index], 9755 range: [start, this.index], 9756 loc: loc 9757 }; 9758 comments.push(entry); 9759 } 9760 this.tolerateUnexpectedToken(); 9761 return comments; 9762 }; 9763 Scanner.prototype.scanComments = function () { 9764 var comments; 9765 if (this.trackComment) { 9766 comments = []; 9767 } 9768 var start = (this.index === 0); 9769 while (!this.eof()) { 9770 var ch = this.source.charCodeAt(this.index); 9771 if (character_1.Character.isWhiteSpace(ch)) { 9772 ++this.index; 9773 } 9774 else if (character_1.Character.isLineTerminator(ch)) { 9775 ++this.index; 9776 if (ch === 0x0D && this.source.charCodeAt(this.index) === 0x0A) { 9777 ++this.index; 9778 } 9779 ++this.lineNumber; 9780 this.lineStart = this.index; 9781 start = true; 9782 } 9783 else if (ch === 0x2F) { 9784 ch = this.source.charCodeAt(this.index + 1); 9785 if (ch === 0x2F) { 9786 this.index += 2; 9787 var comment = this.skipSingleLineComment(2); 9788 if (this.trackComment) { 9789 comments = comments.concat(comment); 9790 } 9791 start = true; 9792 } 9793 else if (ch === 0x2A) { 9794 this.index += 2; 9795 var comment = this.skipMultiLineComment(); 9796 if (this.trackComment) { 9797 comments = comments.concat(comment); 9798 } 9799 } 9800 else { 9801 break; 9802 } 9803 } 9804 else if (start && ch === 0x2D) { 9805 // U+003E is '>' 9806 if ((this.source.charCodeAt(this.index + 1) === 0x2D) && (this.source.charCodeAt(this.index + 2) === 0x3E)) { 9807 // '-->' is a single-line comment 9808 this.index += 3; 9809 var comment = this.skipSingleLineComment(3); 9810 if (this.trackComment) { 9811 comments = comments.concat(comment); 9812 } 9813 } 9814 else { 9815 break; 9816 } 9817 } 9818 else if (ch === 0x3C && !this.isModule) { 9819 if (this.source.slice(this.index + 1, this.index + 4) === '!--') { 9820 this.index += 4; // `<!--` 9821 var comment = this.skipSingleLineComment(4); 9822 if (this.trackComment) { 9823 comments = comments.concat(comment); 9824 } 9825 } 9826 else { 9827 break; 9828 } 9829 } 9830 else { 9831 break; 9832 } 9833 } 9834 return comments; 9835 }; 9836 // https://tc39.github.io/ecma262/#sec-future-reserved-words 9837 Scanner.prototype.isFutureReservedWord = function (id) { 9838 switch (id) { 9839 case 'enum': 9840 case 'export': 9841 case 'import': 9842 case 'super': 9843 return true; 9844 default: 9845 return false; 9846 } 9847 }; 9848 Scanner.prototype.isStrictModeReservedWord = function (id) { 9849 switch (id) { 9850 case 'implements': 9851 case 'interface': 9852 case 'package': 9853 case 'private': 9854 case 'protected': 9855 case 'public': 9856 case 'static': 9857 case 'yield': 9858 case 'let': 9859 return true; 9860 default: 9861 return false; 9862 } 9863 }; 9864 Scanner.prototype.isRestrictedWord = function (id) { 9865 return id === 'eval' || id === 'arguments'; 9866 }; 9867 // https://tc39.github.io/ecma262/#sec-keywords 9868 Scanner.prototype.isKeyword = function (id) { 9869 switch (id.length) { 9870 case 2: 9871 return (id === 'if') || (id === 'in') || (id === 'do'); 9872 case 3: 9873 return (id === 'var') || (id === 'for') || (id === 'new') || 9874 (id === 'try') || (id === 'let'); 9875 case 4: 9876 return (id === 'this') || (id === 'else') || (id === 'case') || 9877 (id === 'void') || (id === 'with') || (id === 'enum'); 9878 case 5: 9879 return (id === 'while') || (id === 'break') || (id === 'catch') || 9880 (id === 'throw') || (id === 'const') || (id === 'yield') || 9881 (id === 'class') || (id === 'super'); 9882 case 6: 9883 return (id === 'return') || (id === 'typeof') || (id === 'delete') || 9884 (id === 'switch') || (id === 'export') || (id === 'import'); 9885 case 7: 9886 return (id === 'default') || (id === 'finally') || (id === 'extends'); 9887 case 8: 9888 return (id === 'function') || (id === 'continue') || (id === 'debugger'); 9889 case 10: 9890 return (id === 'instanceof'); 9891 default: 9892 return false; 9893 } 9894 }; 9895 Scanner.prototype.codePointAt = function (i) { 9896 var cp = this.source.charCodeAt(i); 9897 if (cp >= 0xD800 && cp <= 0xDBFF) { 9898 var second = this.source.charCodeAt(i + 1); 9899 if (second >= 0xDC00 && second <= 0xDFFF) { 9900 var first = cp; 9901 cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; 9902 } 9903 } 9904 return cp; 9905 }; 9906 Scanner.prototype.scanHexEscape = function (prefix) { 9907 var len = (prefix === 'u') ? 4 : 2; 9908 var code = 0; 9909 for (var i = 0; i < len; ++i) { 9910 if (!this.eof() && character_1.Character.isHexDigit(this.source.charCodeAt(this.index))) { 9911 code = code * 16 + hexValue(this.source[this.index++]); 9912 } 9913 else { 9914 return null; 9915 } 9916 } 9917 return String.fromCharCode(code); 9918 }; 9919 Scanner.prototype.scanUnicodeCodePointEscape = function () { 9920 var ch = this.source[this.index]; 9921 var code = 0; 9922 // At least, one hex digit is required. 9923 if (ch === '}') { 9924 this.throwUnexpectedToken(); 9925 } 9926 while (!this.eof()) { 9927 ch = this.source[this.index++]; 9928 if (!character_1.Character.isHexDigit(ch.charCodeAt(0))) { 9929 break; 9930 } 9931 code = code * 16 + hexValue(ch); 9932 } 9933 if (code > 0x10FFFF || ch !== '}') { 9934 this.throwUnexpectedToken(); 9935 } 9936 return character_1.Character.fromCodePoint(code); 9937 }; 9938 Scanner.prototype.getIdentifier = function () { 9939 var start = this.index++; 9940 while (!this.eof()) { 9941 var ch = this.source.charCodeAt(this.index); 9942 if (ch === 0x5C) { 9943 // Blackslash (U+005C) marks Unicode escape sequence. 9944 this.index = start; 9945 return this.getComplexIdentifier(); 9946 } 9947 else if (ch >= 0xD800 && ch < 0xDFFF) { 9948 // Need to handle surrogate pairs. 9949 this.index = start; 9950 return this.getComplexIdentifier(); 9951 } 9952 if (character_1.Character.isIdentifierPart(ch)) { 9953 ++this.index; 9954 } 9955 else { 9956 break; 9957 } 9958 } 9959 return this.source.slice(start, this.index); 9960 }; 9961 Scanner.prototype.getComplexIdentifier = function () { 9962 var cp = this.codePointAt(this.index); 9963 var id = character_1.Character.fromCodePoint(cp); 9964 this.index += id.length; 9965 // '\u' (U+005C, U+0075) denotes an escaped character. 9966 var ch; 9967 if (cp === 0x5C) { 9968 if (this.source.charCodeAt(this.index) !== 0x75) { 9969 this.throwUnexpectedToken(); 9970 } 9971 ++this.index; 9972 if (this.source[this.index] === '{') { 9973 ++this.index; 9974 ch = this.scanUnicodeCodePointEscape(); 9975 } 9976 else { 9977 ch = this.scanHexEscape('u'); 9978 if (ch === null || ch === '\\' || !character_1.Character.isIdentifierStart(ch.charCodeAt(0))) { 9979 this.throwUnexpectedToken(); 9980 } 9981 } 9982 id = ch; 9983 } 9984 while (!this.eof()) { 9985 cp = this.codePointAt(this.index); 9986 if (!character_1.Character.isIdentifierPart(cp)) { 9987 break; 9988 } 9989 ch = character_1.Character.fromCodePoint(cp); 9990 id += ch; 9991 this.index += ch.length; 9992 // '\u' (U+005C, U+0075) denotes an escaped character. 9993 if (cp === 0x5C) { 9994 id = id.substr(0, id.length - 1); 9995 if (this.source.charCodeAt(this.index) !== 0x75) { 9996 this.throwUnexpectedToken(); 9997 } 9998 ++this.index; 9999 if (this.source[this.index] === '{') { 10000 ++this.index; 10001 ch = this.scanUnicodeCodePointEscape(); 10002 } 10003 else { 10004 ch = this.scanHexEscape('u'); 10005 if (ch === null || ch === '\\' || !character_1.Character.isIdentifierPart(ch.charCodeAt(0))) { 10006 this.throwUnexpectedToken(); 10007 } 10008 } 10009 id += ch; 10010 } 10011 } 10012 return id; 10013 }; 10014 Scanner.prototype.octalToDecimal = function (ch) { 10015 // \0 is not octal escape sequence 10016 var octal = (ch !== '0'); 10017 var code = octalValue(ch); 10018 if (!this.eof() && character_1.Character.isOctalDigit(this.source.charCodeAt(this.index))) { 10019 octal = true; 10020 code = code * 8 + octalValue(this.source[this.index++]); 10021 // 3 digits are only allowed when string starts 10022 // with 0, 1, 2, 3 10023 if ('0123'.indexOf(ch) >= 0 && !this.eof() && character_1.Character.isOctalDigit(this.source.charCodeAt(this.index))) { 10024 code = code * 8 + octalValue(this.source[this.index++]); 10025 } 10026 } 10027 return { 10028 code: code, 10029 octal: octal 10030 }; 10031 }; 10032 // https://tc39.github.io/ecma262/#sec-names-and-keywords 10033 Scanner.prototype.scanIdentifier = function () { 10034 var type; 10035 var start = this.index; 10036 // Backslash (U+005C) starts an escaped character. 10037 var id = (this.source.charCodeAt(start) === 0x5C) ? this.getComplexIdentifier() : this.getIdentifier(); 10038 // There is no keyword or literal with only one character. 10039 // Thus, it must be an identifier. 10040 if (id.length === 1) { 10041 type = 3 /* Identifier */; 10042 } 10043 else if (this.isKeyword(id)) { 10044 type = 4 /* Keyword */; 10045 } 10046 else if (id === 'null') { 10047 type = 5 /* NullLiteral */; 10048 } 10049 else if (id === 'true' || id === 'false') { 10050 type = 1 /* BooleanLiteral */; 10051 } 10052 else { 10053 type = 3 /* Identifier */; 10054 } 10055 if (type !== 3 /* Identifier */ && (start + id.length !== this.index)) { 10056 var restore = this.index; 10057 this.index = start; 10058 this.tolerateUnexpectedToken(messages_1.Messages.InvalidEscapedReservedWord); 10059 this.index = restore; 10060 } 10061 return { 10062 type: type, 10063 value: id, 10064 lineNumber: this.lineNumber, 10065 lineStart: this.lineStart, 10066 start: start, 10067 end: this.index 10068 }; 10069 }; 10070 // https://tc39.github.io/ecma262/#sec-punctuators 10071 Scanner.prototype.scanPunctuator = function () { 10072 var start = this.index; 10073 // Check for most common single-character punctuators. 10074 var str = this.source[this.index]; 10075 switch (str) { 10076 case '(': 10077 case '{': 10078 if (str === '{') { 10079 this.curlyStack.push('{'); 10080 } 10081 ++this.index; 10082 break; 10083 case '.': 10084 ++this.index; 10085 if (this.source[this.index] === '.' && this.source[this.index + 1] === '.') { 10086 // Spread operator: ... 10087 this.index += 2; 10088 str = '...'; 10089 } 10090 break; 10091 case '}': 10092 ++this.index; 10093 this.curlyStack.pop(); 10094 break; 10095 case ')': 10096 case ';': 10097 case ',': 10098 case '[': 10099 case ']': 10100 case ':': 10101 case '?': 10102 case '~': 10103 ++this.index; 10104 break; 10105 default: 10106 // 4-character punctuator. 10107 str = this.source.substr(this.index, 4); 10108 if (str === '>>>=') { 10109 this.index += 4; 10110 } 10111 else { 10112 // 3-character punctuators. 10113 str = str.substr(0, 3); 10114 if (str === '===' || str === '!==' || str === '>>>' || 10115 str === '<<=' || str === '>>=' || str === '**=') { 10116 this.index += 3; 10117 } 10118 else { 10119 // 2-character punctuators. 10120 str = str.substr(0, 2); 10121 if (str === '&&' || str === '||' || str === '==' || str === '!=' || 10122 str === '+=' || str === '-=' || str === '*=' || str === '/=' || 10123 str === '++' || str === '--' || str === '<<' || str === '>>' || 10124 str === '&=' || str === '|=' || str === '^=' || str === '%=' || 10125 str === '<=' || str === '>=' || str === '=>' || str === '**') { 10126 this.index += 2; 10127 } 10128 else { 10129 // 1-character punctuators. 10130 str = this.source[this.index]; 10131 if ('<>=!+-*%&|^/'.indexOf(str) >= 0) { 10132 ++this.index; 10133 } 10134 } 10135 } 10136 } 10137 } 10138 if (this.index === start) { 10139 this.throwUnexpectedToken(); 10140 } 10141 return { 10142 type: 7 /* Punctuator */, 10143 value: str, 10144 lineNumber: this.lineNumber, 10145 lineStart: this.lineStart, 10146 start: start, 10147 end: this.index 10148 }; 10149 }; 10150 // https://tc39.github.io/ecma262/#sec-literals-numeric-literals 10151 Scanner.prototype.scanHexLiteral = function (start) { 10152 var num = ''; 10153 while (!this.eof()) { 10154 if (!character_1.Character.isHexDigit(this.source.charCodeAt(this.index))) { 10155 break; 10156 } 10157 num += this.source[this.index++]; 10158 } 10159 if (num.length === 0) { 10160 this.throwUnexpectedToken(); 10161 } 10162 if (character_1.Character.isIdentifierStart(this.source.charCodeAt(this.index))) { 10163 this.throwUnexpectedToken(); 10164 } 10165 return { 10166 type: 6 /* NumericLiteral */, 10167 value: parseInt('0x' + num, 16), 10168 lineNumber: this.lineNumber, 10169 lineStart: this.lineStart, 10170 start: start, 10171 end: this.index 10172 }; 10173 }; 10174 Scanner.prototype.scanBinaryLiteral = function (start) { 10175 var num = ''; 10176 var ch; 10177 while (!this.eof()) { 10178 ch = this.source[this.index]; 10179 if (ch !== '0' && ch !== '1') { 10180 break; 10181 } 10182 num += this.source[this.index++]; 10183 } 10184 if (num.length === 0) { 10185 // only 0b or 0B 10186 this.throwUnexpectedToken(); 10187 } 10188 if (!this.eof()) { 10189 ch = this.source.charCodeAt(this.index); 10190 /* istanbul ignore else */ 10191 if (character_1.Character.isIdentifierStart(ch) || character_1.Character.isDecimalDigit(ch)) { 10192 this.throwUnexpectedToken(); 10193 } 10194 } 10195 return { 10196 type: 6 /* NumericLiteral */, 10197 value: parseInt(num, 2), 10198 lineNumber: this.lineNumber, 10199 lineStart: this.lineStart, 10200 start: start, 10201 end: this.index 10202 }; 10203 }; 10204 Scanner.prototype.scanOctalLiteral = function (prefix, start) { 10205 var num = ''; 10206 var octal = false; 10207 if (character_1.Character.isOctalDigit(prefix.charCodeAt(0))) { 10208 octal = true; 10209 num = '0' + this.source[this.index++]; 10210 } 10211 else { 10212 ++this.index; 10213 } 10214 while (!this.eof()) { 10215 if (!character_1.Character.isOctalDigit(this.source.charCodeAt(this.index))) { 10216 break; 10217 } 10218 num += this.source[this.index++]; 10219 } 10220 if (!octal && num.length === 0) { 10221 // only 0o or 0O 10222 this.throwUnexpectedToken(); 10223 } 10224 if (character_1.Character.isIdentifierStart(this.source.charCodeAt(this.index)) || character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) { 10225 this.throwUnexpectedToken(); 10226 } 10227 return { 10228 type: 6 /* NumericLiteral */, 10229 value: parseInt(num, 8), 10230 octal: octal, 10231 lineNumber: this.lineNumber, 10232 lineStart: this.lineStart, 10233 start: start, 10234 end: this.index 10235 }; 10236 }; 10237 Scanner.prototype.isImplicitOctalLiteral = function () { 10238 // Implicit octal, unless there is a non-octal digit. 10239 // (Annex B.1.1 on Numeric Literals) 10240 for (var i = this.index + 1; i < this.length; ++i) { 10241 var ch = this.source[i]; 10242 if (ch === '8' || ch === '9') { 10243 return false; 10244 } 10245 if (!character_1.Character.isOctalDigit(ch.charCodeAt(0))) { 10246 return true; 10247 } 10248 } 10249 return true; 10250 }; 10251 Scanner.prototype.scanNumericLiteral = function () { 10252 var start = this.index; 10253 var ch = this.source[start]; 10254 assert_1.assert(character_1.Character.isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), 'Numeric literal must start with a decimal digit or a decimal point'); 10255 var num = ''; 10256 if (ch !== '.') { 10257 num = this.source[this.index++]; 10258 ch = this.source[this.index]; 10259 // Hex number starts with '0x'. 10260 // Octal number starts with '0'. 10261 // Octal number in ES6 starts with '0o'. 10262 // Binary number in ES6 starts with '0b'. 10263 if (num === '0') { 10264 if (ch === 'x' || ch === 'X') { 10265 ++this.index; 10266 return this.scanHexLiteral(start); 10267 } 10268 if (ch === 'b' || ch === 'B') { 10269 ++this.index; 10270 return this.scanBinaryLiteral(start); 10271 } 10272 if (ch === 'o' || ch === 'O') { 10273 return this.scanOctalLiteral(ch, start); 10274 } 10275 if (ch && character_1.Character.isOctalDigit(ch.charCodeAt(0))) { 10276 if (this.isImplicitOctalLiteral()) { 10277 return this.scanOctalLiteral(ch, start); 10278 } 10279 } 10280 } 10281 while (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) { 10282 num += this.source[this.index++]; 10283 } 10284 ch = this.source[this.index]; 10285 } 10286 if (ch === '.') { 10287 num += this.source[this.index++]; 10288 while (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) { 10289 num += this.source[this.index++]; 10290 } 10291 ch = this.source[this.index]; 10292 } 10293 if (ch === 'e' || ch === 'E') { 10294 num += this.source[this.index++]; 10295 ch = this.source[this.index]; 10296 if (ch === '+' || ch === '-') { 10297 num += this.source[this.index++]; 10298 } 10299 if (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) { 10300 while (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) { 10301 num += this.source[this.index++]; 10302 } 10303 } 10304 else { 10305 this.throwUnexpectedToken(); 10306 } 10307 } 10308 if (character_1.Character.isIdentifierStart(this.source.charCodeAt(this.index))) { 10309 this.throwUnexpectedToken(); 10310 } 10311 return { 10312 type: 6 /* NumericLiteral */, 10313 value: parseFloat(num), 10314 lineNumber: this.lineNumber, 10315 lineStart: this.lineStart, 10316 start: start, 10317 end: this.index 10318 }; 10319 }; 10320 // https://tc39.github.io/ecma262/#sec-literals-string-literals 10321 Scanner.prototype.scanStringLiteral = function () { 10322 var start = this.index; 10323 var quote = this.source[start]; 10324 assert_1.assert((quote === '\'' || quote === '"'), 'String literal must starts with a quote'); 10325 ++this.index; 10326 var octal = false; 10327 var str = ''; 10328 while (!this.eof()) { 10329 var ch = this.source[this.index++]; 10330 if (ch === quote) { 10331 quote = ''; 10332 break; 10333 } 10334 else if (ch === '\\') { 10335 ch = this.source[this.index++]; 10336 if (!ch || !character_1.Character.isLineTerminator(ch.charCodeAt(0))) { 10337 switch (ch) { 10338 case 'u': 10339 if (this.source[this.index] === '{') { 10340 ++this.index; 10341 str += this.scanUnicodeCodePointEscape(); 10342 } 10343 else { 10344 var unescaped_1 = this.scanHexEscape(ch); 10345 if (unescaped_1 === null) { 10346 this.throwUnexpectedToken(); 10347 } 10348 str += unescaped_1; 10349 } 10350 break; 10351 case 'x': 10352 var unescaped = this.scanHexEscape(ch); 10353 if (unescaped === null) { 10354 this.throwUnexpectedToken(messages_1.Messages.InvalidHexEscapeSequence); 10355 } 10356 str += unescaped; 10357 break; 10358 case 'n': 10359 str += '\n'; 10360 break; 10361 case 'r': 10362 str += '\r'; 10363 break; 10364 case 't': 10365 str += '\t'; 10366 break; 10367 case 'b': 10368 str += '\b'; 10369 break; 10370 case 'f': 10371 str += '\f'; 10372 break; 10373 case 'v': 10374 str += '\x0B'; 10375 break; 10376 case '8': 10377 case '9': 10378 str += ch; 10379 this.tolerateUnexpectedToken(); 10380 break; 10381 default: 10382 if (ch && character_1.Character.isOctalDigit(ch.charCodeAt(0))) { 10383 var octToDec = this.octalToDecimal(ch); 10384 octal = octToDec.octal || octal; 10385 str += String.fromCharCode(octToDec.code); 10386 } 10387 else { 10388 str += ch; 10389 } 10390 break; 10391 } 10392 } 10393 else { 10394 ++this.lineNumber; 10395 if (ch === '\r' && this.source[this.index] === '\n') { 10396 ++this.index; 10397 } 10398 this.lineStart = this.index; 10399 } 10400 } 10401 else if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { 10402 break; 10403 } 10404 else { 10405 str += ch; 10406 } 10407 } 10408 if (quote !== '') { 10409 this.index = start; 10410 this.throwUnexpectedToken(); 10411 } 10412 return { 10413 type: 8 /* StringLiteral */, 10414 value: str, 10415 octal: octal, 10416 lineNumber: this.lineNumber, 10417 lineStart: this.lineStart, 10418 start: start, 10419 end: this.index 10420 }; 10421 }; 10422 // https://tc39.github.io/ecma262/#sec-template-literal-lexical-components 10423 Scanner.prototype.scanTemplate = function () { 10424 var cooked = ''; 10425 var terminated = false; 10426 var start = this.index; 10427 var head = (this.source[start] === '`'); 10428 var tail = false; 10429 var rawOffset = 2; 10430 ++this.index; 10431 while (!this.eof()) { 10432 var ch = this.source[this.index++]; 10433 if (ch === '`') { 10434 rawOffset = 1; 10435 tail = true; 10436 terminated = true; 10437 break; 10438 } 10439 else if (ch === '$') { 10440 if (this.source[this.index] === '{') { 10441 this.curlyStack.push('${'); 10442 ++this.index; 10443 terminated = true; 10444 break; 10445 } 10446 cooked += ch; 10447 } 10448 else if (ch === '\\') { 10449 ch = this.source[this.index++]; 10450 if (!character_1.Character.isLineTerminator(ch.charCodeAt(0))) { 10451 switch (ch) { 10452 case 'n': 10453 cooked += '\n'; 10454 break; 10455 case 'r': 10456 cooked += '\r'; 10457 break; 10458 case 't': 10459 cooked += '\t'; 10460 break; 10461 case 'u': 10462 if (this.source[this.index] === '{') { 10463 ++this.index; 10464 cooked += this.scanUnicodeCodePointEscape(); 10465 } 10466 else { 10467 var restore = this.index; 10468 var unescaped_2 = this.scanHexEscape(ch); 10469 if (unescaped_2 !== null) { 10470 cooked += unescaped_2; 10471 } 10472 else { 10473 this.index = restore; 10474 cooked += ch; 10475 } 10476 } 10477 break; 10478 case 'x': 10479 var unescaped = this.scanHexEscape(ch); 10480 if (unescaped === null) { 10481 this.throwUnexpectedToken(messages_1.Messages.InvalidHexEscapeSequence); 10482 } 10483 cooked += unescaped; 10484 break; 10485 case 'b': 10486 cooked += '\b'; 10487 break; 10488 case 'f': 10489 cooked += '\f'; 10490 break; 10491 case 'v': 10492 cooked += '\v'; 10493 break; 10494 default: 10495 if (ch === '0') { 10496 if (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index))) { 10497 // Illegal: \01 \02 and so on 10498 this.throwUnexpectedToken(messages_1.Messages.TemplateOctalLiteral); 10499 } 10500 cooked += '\0'; 10501 } 10502 else if (character_1.Character.isOctalDigit(ch.charCodeAt(0))) { 10503 // Illegal: \1 \2 10504 this.throwUnexpectedToken(messages_1.Messages.TemplateOctalLiteral); 10505 } 10506 else { 10507 cooked += ch; 10508 } 10509 break; 10510 } 10511 } 10512 else { 10513 ++this.lineNumber; 10514 if (ch === '\r' && this.source[this.index] === '\n') { 10515 ++this.index; 10516 } 10517 this.lineStart = this.index; 10518 } 10519 } 10520 else if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { 10521 ++this.lineNumber; 10522 if (ch === '\r' && this.source[this.index] === '\n') { 10523 ++this.index; 10524 } 10525 this.lineStart = this.index; 10526 cooked += '\n'; 10527 } 10528 else { 10529 cooked += ch; 10530 } 10531 } 10532 if (!terminated) { 10533 this.throwUnexpectedToken(); 10534 } 10535 if (!head) { 10536 this.curlyStack.pop(); 10537 } 10538 return { 10539 type: 10 /* Template */, 10540 value: this.source.slice(start + 1, this.index - rawOffset), 10541 cooked: cooked, 10542 head: head, 10543 tail: tail, 10544 lineNumber: this.lineNumber, 10545 lineStart: this.lineStart, 10546 start: start, 10547 end: this.index 10548 }; 10549 }; 10550 // https://tc39.github.io/ecma262/#sec-literals-regular-expression-literals 10551 Scanner.prototype.testRegExp = function (pattern, flags) { 10552 // The BMP character to use as a replacement for astral symbols when 10553 // translating an ES6 "u"-flagged pattern to an ES5-compatible 10554 // approximation. 10555 // Note: replacing with '\uFFFF' enables false positives in unlikely 10556 // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid 10557 // pattern that would not be detected by this substitution. 10558 var astralSubstitute = '\uFFFF'; 10559 var tmp = pattern; 10560 var self = this; 10561 if (flags.indexOf('u') >= 0) { 10562 tmp = tmp 10563 .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) { 10564 var codePoint = parseInt($1 || $2, 16); 10565 if (codePoint > 0x10FFFF) { 10566 self.throwUnexpectedToken(messages_1.Messages.InvalidRegExp); 10567 } 10568 if (codePoint <= 0xFFFF) { 10569 return String.fromCharCode(codePoint); 10570 } 10571 return astralSubstitute; 10572 }) 10573 .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, astralSubstitute); 10574 } 10575 // First, detect invalid regular expressions. 10576 try { 10577 RegExp(tmp); 10578 } 10579 catch (e) { 10580 this.throwUnexpectedToken(messages_1.Messages.InvalidRegExp); 10581 } 10582 // Return a regular expression object for this pattern-flag pair, or 10583 // `null` in case the current environment doesn't support the flags it 10584 // uses. 10585 try { 10586 return new RegExp(pattern, flags); 10587 } 10588 catch (exception) { 10589 /* istanbul ignore next */ 10590 return null; 10591 } 10592 }; 10593 Scanner.prototype.scanRegExpBody = function () { 10594 var ch = this.source[this.index]; 10595 assert_1.assert(ch === '/', 'Regular expression literal must start with a slash'); 10596 var str = this.source[this.index++]; 10597 var classMarker = false;
10598 var terminated = false; 10599 while (!this.eof()) { 10600 ch = this.source[this.index++]; 10601 str += ch; 10602 if (ch === '\\') { 10603 ch = this.source[this.index++]; 10604 // https://tc39.github.io/ecma262/#sec-literals-regular-expression-literals 10605 if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { 10606 this.throwUnexpectedToken(messages_1.Messages.UnterminatedRegExp); 10607 } 10608 str += ch; 10609 } 10610 else if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { 10611 this.throwUnexpectedToken(messages_1.Messages.UnterminatedRegExp); 10612 } 10613 else if (classMarker) { 10614 if (ch === ']') { 10615 classMarker = false;
vendor: 7,399 bytes, lines 10616-10744
10616 } 10617 } 10618 else { 10619 if (ch === '/') { 10620 terminated = true; 10621 break; 10622 } 10623 else if (ch === '[') { 10624 classMarker = true; 10625 } 10626 } 10627 } 10628 if (!terminated) { 10629 this.throwUnexpectedToken(messages_1.Messages.UnterminatedRegExp); 10630 } 10631 // Exclude leading and trailing slash. 10632 return str.substr(1, str.length - 2); 10633 }; 10634 Scanner.prototype.scanRegExpFlags = function () { 10635 var str = ''; 10636 var flags = ''; 10637 while (!this.eof()) { 10638 var ch = this.source[this.index]; 10639 if (!character_1.Character.isIdentifierPart(ch.charCodeAt(0))) { 10640 break; 10641 } 10642 ++this.index; 10643 if (ch === '\\' && !this.eof()) { 10644 ch = this.source[this.index]; 10645 if (ch === 'u') { 10646 ++this.index; 10647 var restore = this.index; 10648 var char = this.scanHexEscape('u'); 10649 if (char !== null) { 10650 flags += char; 10651 for (str += '\\u'; restore < this.index; ++restore) { 10652 str += this.source[restore]; 10653 } 10654 } 10655 else { 10656 this.index = restore; 10657 flags += 'u'; 10658 str += '\\u'; 10659 } 10660 this.tolerateUnexpectedToken(); 10661 } 10662 else { 10663 str += '\\'; 10664 this.tolerateUnexpectedToken(); 10665 } 10666 } 10667 else { 10668 flags += ch; 10669 str += ch; 10670 } 10671 } 10672 return flags; 10673 }; 10674 Scanner.prototype.scanRegExp = function () { 10675 var start = this.index; 10676 var pattern = this.scanRegExpBody(); 10677 var flags = this.scanRegExpFlags(); 10678 var value = this.testRegExp(pattern, flags); 10679 return { 10680 type: 9 /* RegularExpression */, 10681 value: '', 10682 pattern: pattern, 10683 flags: flags, 10684 regex: value, 10685 lineNumber: this.lineNumber, 10686 lineStart: this.lineStart, 10687 start: start, 10688 end: this.index 10689 }; 10690 }; 10691 Scanner.prototype.lex = function () { 10692 if (this.eof()) { 10693 return { 10694 type: 2 /* EOF */, 10695 value: '', 10696 lineNumber: this.lineNumber, 10697 lineStart: this.lineStart, 10698 start: this.index, 10699 end: this.index 10700 }; 10701 } 10702 var cp = this.source.charCodeAt(this.index); 10703 if (character_1.Character.isIdentifierStart(cp)) { 10704 return this.scanIdentifier(); 10705 } 10706 // Very common: ( and ) and ; 10707 if (cp === 0x28 || cp === 0x29 || cp === 0x3B) { 10708 return this.scanPunctuator(); 10709 } 10710 // String literal starts with single quote (U+0027) or double quote (U+0022). 10711 if (cp === 0x27 || cp === 0x22) { 10712 return this.scanStringLiteral(); 10713 } 10714 // Dot (.) U+002E can also start a floating-point number, hence the need 10715 // to check the next character. 10716 if (cp === 0x2E) { 10717 if (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index + 1))) { 10718 return this.scanNumericLiteral(); 10719 } 10720 return this.scanPunctuator(); 10721 } 10722 if (character_1.Character.isDecimalDigit(cp)) { 10723 return this.scanNumericLiteral(); 10724 } 10725 // Template literals start with ` (U+0060) for template head 10726 // or } (U+007D) for template middle or template tail. 10727 if (cp === 0x60 || (cp === 0x7D && this.curlyStack[this.curlyStack.length - 1] === '${')) { 10728 return this.scanTemplate(); 10729 } 10730 // Possible identifier start in a surrogate pair. 10731 if (cp >= 0xD800 && cp < 0xDFFF) { 10732 if (character_1.Character.isIdentifierStart(this.codePointAt(this.index))) { 10733 return this.scanIdentifier(); 10734 } 10735 } 10736 return this.scanPunctuator(); 10737 }; 10738 return Scanner; 10739 }()); 10740 exports.Scanner = Scanner; 10741 10742 10743 /***/ }, 10744 /* 13 */
10745 /***/ function(module, exports) { 10746 10747 "use strict"; 10748 Object.defineProperty(exports, "__esModule", { value: true }); 10749 exports.TokenName = {}; 10750 exports.TokenName[1 /* BooleanLiteral */] = 'Boolean'; 10751 exports.TokenName[2 /* EOF */] = '<end>'; 10752 exports.TokenName[3 /* Identifier */] = 'Identifier'; 10753 exports.TokenName[4 /* Keyword */] = 'Keyword'; 10754 exports.TokenName[5 /* NullLiteral */] = 'Null'; 10755 exports.TokenName[6 /* NumericLiteral */] = 'Numeric'; 10756 exports.TokenName[7 /* Punctuator */] = 'Punctuator'; 10757 exports.TokenName[8 /* StringLiteral */] = 'String'; 10758 exports.TokenName[9 /* RegularExpression */] = 'RegularExpression'; 10759 exports.TokenName[10 /* Template */] = 'Template'; 10760 10761 10762 /***/ }, 10763 /* 14 */ 10764 /***/ function(module, exports) { 10765 10766 "use strict"; 10767 // Generated by generate-xhtml-entities.js. DO NOT MODIFY! 10768 Object.defineProperty(exports, "__esModule", { value: true }); 10769 exports.XHTMLEntities = { 10770 quot: '\u0022', 10771 amp: '\u0026', 10772 apos: '\u0027', 10773 gt: '\u003E', 10774 nbsp: '\u00A0', 10775 iexcl: '\u00A1', 10776 cent: '\u00A2', 10777 pound: '\u00A3', 10778 curren: '\u00A4', 10779 yen: '\u00A5', 10780 brvbar: '\u00A6', 10781 sect: '\u00A7', 10782 uml: '\u00A8', 10783 copy: '\u00A9', 10784 ordf: '\u00AA', 10785 laquo: '\u00AB', 10786 not: '\u00AC', 10787 shy: '\u00AD', 10788 reg: '\u00AE', 10789 macr: '\u00AF', 10790 deg: '\u00B0', 10791 plusmn: '\u00B1', 10792 sup2: '\u00B2', 10793 sup3: '\u00B3', 10794 acute: '\u00B4', 10795 micro: '\u00B5', 10796 para: '\u00B6', 10797 middot: '\u00B7', 10798 cedil: '\u00B8', 10799 sup1: '\u00B9', 10800 ordm: '\u00BA', 10801 raquo: '\u00BB', 10802 frac14: '\u00BC', 10803 frac12: '\u00BD', 10804 frac34: '\u00BE', 10805 iquest: '\u00BF', 10806 Agrave: '\u00C0', 10807 Aacute: '\u00C1', 10808 Acirc: '\u00C2', 10809 Atilde: '\u00C3', 10810 Auml: '\u00C4', 10811 Aring: '\u00C5', 10812 AElig: '\u00C6', 10813 Ccedil: '\u00C7', 10814 Egrave: '\u00C8', 10815 Eacute: '\u00C9', 10816 Ecirc: '\u00CA', 10817 Euml: '\u00CB', 10818 Igrave: '\u00CC', 10819 Iacute: '\u00CD', 10820 Icirc: '\u00CE', 10821 Iuml: '\u00CF', 10822 ETH: '\u00D0', 10823 Ntilde: '\u00D1', 10824 Ograve: '\u00D2', 10825 Oacute: '\u00D3', 10826 Ocirc: '\u00D4', 10827 Otilde: '\u00D5', 10828 Ouml: '\u00D6', 10829 times: '\u00D7', 10830 Oslash: '\u00D8', 10831 Ugrave: '\u00D9', 10832 Uacute: '\u00DA', 10833 Ucirc: '\u00DB', 10834 Uuml: '\u00DC', 10835 Yacute: '\u00DD', 10836 THORN: '\u00DE', 10837 szlig: '\u00DF', 10838 agrave: '\u00E0', 10839 aacute: '\u00E1', 10840 acirc: '\u00E2', 10841 atilde: '\u00E3', 10842 auml: '\u00E4', 10843 aring: '\u00E5', 10844 aelig: '\u00E6', 10845 ccedil: '\u00E7', 10846 egrave: '\u00E8', 10847 eacute: '\u00E9', 10848 ecirc: '\u00EA', 10849 euml: '\u00EB', 10850 igrave: '\u00EC', 10851 iacute: '\u00ED', 10852 icirc: '\u00EE', 10853 iuml: '\u00EF', 10854 eth: '\u00F0', 10855 ntilde: '\u00F1', 10856 ograve: '\u00F2', 10857 oacute: '\u00F3', 10858 ocirc: '\u00F4', 10859 otilde: '\u00F5', 10860 ouml: '\u00F6', 10861 divide: '\u00F7', 10862 oslash: '\u00F8', 10863 ugrave: '\u00F9', 10864 uacute: '\u00FA', 10865 ucirc: '\u00FB', 10866 uuml: '\u00FC', 10867 yacute: '\u00FD', 10868 thorn: '\u00FE', 10869 yuml: '\u00FF', 10870 OElig: '\u0152', 10871 oelig: '\u0153', 10872 Scaron: '\u0160', 10873 scaron: '\u0161', 10874 Yuml: '\u0178', 10875 fnof: '\u0192', 10876 circ: '\u02C6', 10877 tilde: '\u02DC', 10878 Alpha: '\u0391', 10879 Beta: '\u0392', 10880 Gamma: '\u0393', 10881 Delta: '\u0394', 10882 Epsilon: '\u0395', 10883 Zeta: '\u0396', 10884 Eta: '\u0397', 10885 Theta: '\u0398', 10886 Iota: '\u0399', 10887 Kappa: '\u039A', 10888 Lambda: '\u039B', 10889 Mu: '\u039C', 10890 Nu: '\u039D', 10891 Xi: '\u039E', 10892 Omicron: '\u039F', 10893 Pi: '\u03A0', 10894 Rho: '\u03A1', 10895 Sigma: '\u03A3', 10896 Tau: '\u03A4', 10897 Upsilon: '\u03A5', 10898 Phi: '\u03A6', 10899 Chi: '\u03A7', 10900 Psi: '\u03A8', 10901 Omega: '\u03A9', 10902 alpha: '\u03B1', 10903 beta: '\u03B2', 10904 gamma: '\u03B3', 10905 delta: '\u03B4', 10906 epsilon: '\u03B5', 10907 zeta: '\u03B6', 10908 eta: '\u03B7', 10909 theta: '\u03B8', 10910 iota: '\u03B9', 10911 kappa: '\u03BA', 10912 lambda: '\u03BB', 10913 mu: '\u03BC', 10914 nu: '\u03BD', 10915 xi: '\u03BE', 10916 omicron: '\u03BF', 10917 pi: '\u03C0', 10918 rho: '\u03C1', 10919 sigmaf: '\u03C2', 10920 sigma: '\u03C3', 10921 tau: '\u03C4', 10922 upsilon: '\u03C5', 10923 phi: '\u03C6', 10924 chi: '\u03C7', 10925 psi: '\u03C8', 10926 omega: '\u03C9', 10927 thetasym: '\u03D1', 10928 upsih: '\u03D2', 10929 piv: '\u03D6', 10930 ensp: '\u2002', 10931 emsp: '\u2003', 10932 thinsp: '\u2009', 10933 zwnj: '\u200C', 10934 zwj: '\u200D', 10935 lrm: '\u200E', 10936 rlm: '\u200F', 10937 ndash: '\u2013', 10938 mdash: '\u2014', 10939 lsquo: '\u2018', 10940 rsquo: '\u2019', 10941 sbquo: '\u201A', 10942 ldquo: '\u201C', 10943 rdquo: '\u201D', 10944 bdquo: '\u201E', 10945 dagger: '\u2020', 10946 Dagger: '\u2021', 10947 bull: '\u2022', 10948 hellip: '\u2026', 10949 permil: '\u2030', 10950 prime: '\u2032', 10951 Prime: '\u2033', 10952 lsaquo: '\u2039', 10953 rsaquo: '\u203A', 10954 oline: '\u203E',
vendor: 16,600 bytes, lines 10955-11261
10955 frasl: '\u2044', 10956 euro: '\u20AC', 10957 image: '\u2111', 10958 weierp: '\u2118', 10959 real: '\u211C', 10960 trade: '\u2122', 10961 alefsym: '\u2135', 10962 larr: '\u2190', 10963 uarr: '\u2191', 10964 rarr: '\u2192', 10965 darr: '\u2193', 10966 harr: '\u2194', 10967 crarr: '\u21B5', 10968 lArr: '\u21D0', 10969 uArr: '\u21D1', 10970 rArr: '\u21D2', 10971 dArr: '\u21D3', 10972 hArr: '\u21D4', 10973 forall: '\u2200', 10974 part: '\u2202', 10975 exist: '\u2203', 10976 empty: '\u2205', 10977 nabla: '\u2207', 10978 isin: '\u2208', 10979 notin: '\u2209', 10980 ni: '\u220B', 10981 prod: '\u220F', 10982 sum: '\u2211', 10983 minus: '\u2212', 10984 lowast: '\u2217', 10985 radic: '\u221A', 10986 prop: '\u221D', 10987 infin: '\u221E', 10988 ang: '\u2220', 10989 and: '\u2227', 10990 or: '\u2228', 10991 cap: '\u2229', 10992 cup: '\u222A', 10993 int: '\u222B', 10994 there4: '\u2234', 10995 sim: '\u223C', 10996 cong: '\u2245', 10997 asymp: '\u2248', 10998 ne: '\u2260', 10999 equiv: '\u2261', 11000 le: '\u2264', 11001 ge: '\u2265', 11002 sub: '\u2282', 11003 sup: '\u2283', 11004 nsub: '\u2284', 11005 sube: '\u2286', 11006 supe: '\u2287', 11007 oplus: '\u2295', 11008 otimes: '\u2297', 11009 perp: '\u22A5', 11010 sdot: '\u22C5', 11011 lceil: '\u2308', 11012 rceil: '\u2309', 11013 lfloor: '\u230A', 11014 rfloor: '\u230B', 11015 loz: '\u25CA', 11016 spades: '\u2660', 11017 clubs: '\u2663', 11018 hearts: '\u2665', 11019 diams: '\u2666', 11020 lang: '\u27E8', 11021 rang: '\u27E9' 11022 }; 11023 11024 11025 /***/ }, 11026 /* 15 */ 11027 /***/ function(module, exports, __webpack_require__) { 11028 11029 "use strict"; 11030 Object.defineProperty(exports, "__esModule", { value: true }); 11031 var error_handler_1 = __webpack_require__(10); 11032 var scanner_1 = __webpack_require__(12); 11033 var token_1 = __webpack_require__(13); 11034 var Reader = (function () { 11035 function Reader() { 11036 this.values = []; 11037 this.curly = this.paren = -1; 11038 } 11039 // A function following one of those tokens is an expression. 11040 Reader.prototype.beforeFunctionExpression = function (t) { 11041 return ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new', 11042 'return', 'case', 'delete', 'throw', 'void', 11043 // assignment operators 11044 '=', '+=', '-=', '*=', '**=', '/=', '%=', '<<=', '>>=', '>>>=', 11045 '&=', '|=', '^=', ',', 11046 // binary/unary operators 11047 '+', '-', '*', '**', '/', '%', '++', '--', '<<', '>>', '>>>', '&', 11048 '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=', 11049 '<=', '<', '>', '!=', '!=='].indexOf(t) >= 0; 11050 }; 11051 // Determine if forward slash (/) is an operator or part of a regular expression 11052 // https://github.com/mozilla/sweet.js/wiki/design 11053 Reader.prototype.isRegexStart = function () { 11054 var previous = this.values[this.values.length - 1]; 11055 var regex = (previous !== null); 11056 switch (previous) { 11057 case 'this': 11058 case ']': 11059 regex = false; 11060 break; 11061 case ')': 11062 var keyword = this.values[this.paren - 1]; 11063 regex = (keyword === 'if' || keyword === 'while' || keyword === 'for' || keyword === 'with'); 11064 break; 11065 case '}': 11066 // Dividing a function by anything makes little sense, 11067 // but we have to check for that. 11068 regex = false; 11069 if (this.values[this.curly - 3] === 'function') { 11070 // Anonymous function, e.g. function(){} /42 11071 var check = this.values[this.curly - 4]; 11072 regex = check ? !this.beforeFunctionExpression(check) : false; 11073 } 11074 else if (this.values[this.curly - 4] === 'function') { 11075 // Named function, e.g. function f(){} /42/ 11076 var check = this.values[this.curly - 5]; 11077 regex = check ? !this.beforeFunctionExpression(check) : true; 11078 } 11079 break; 11080 default: 11081 break; 11082 } 11083 return regex; 11084 }; 11085 Reader.prototype.push = function (token) { 11086 if (token.type === 7 /* Punctuator */ || token.type === 4 /* Keyword */) { 11087 if (token.value === '{') { 11088 this.curly = this.values.length; 11089 } 11090 else if (token.value === '(') { 11091 this.paren = this.values.length; 11092 } 11093 this.values.push(token.value); 11094 } 11095 else { 11096 this.values.push(null); 11097 } 11098 }; 11099 return Reader; 11100 }()); 11101 var Tokenizer = (function () { 11102 function Tokenizer(code, config) { 11103 this.errorHandler = new error_handler_1.ErrorHandler(); 11104 this.errorHandler.tolerant = config ? (typeof config.tolerant === 'boolean' && config.tolerant) : false; 11105 this.scanner = new scanner_1.Scanner(code, this.errorHandler); 11106 this.scanner.trackComment = config ? (typeof config.comment === 'boolean' && config.comment) : false; 11107 this.trackRange = config ? (typeof config.range === 'boolean' && config.range) : false; 11108 this.trackLoc = config ? (typeof config.loc === 'boolean' && config.loc) : false; 11109 this.buffer = []; 11110 this.reader = new Reader(); 11111 } 11112 Tokenizer.prototype.errors = function () { 11113 return this.errorHandler.errors; 11114 }; 11115 Tokenizer.prototype.getNextToken = function () { 11116 if (this.buffer.length === 0) { 11117 var comments = this.scanner.scanComments(); 11118 if (this.scanner.trackComment) { 11119 for (var i = 0; i < comments.length; ++i) { 11120 var e = comments[i]; 11121 var value = this.scanner.source.slice(e.slice[0], e.slice[1]); 11122 var comment = { 11123 type: e.multiLine ? 'BlockComment' : 'LineComment', 11124 value: value 11125 }; 11126 if (this.trackRange) { 11127 comment.range = e.range; 11128 } 11129 if (this.trackLoc) { 11130 comment.loc = e.loc; 11131 } 11132 this.buffer.push(comment); 11133 } 11134 } 11135 if (!this.scanner.eof()) { 11136 var loc = void 0; 11137 if (this.trackLoc) { 11138 loc = { 11139 start: { 11140 line: this.scanner.lineNumber, 11141 column: this.scanner.index - this.scanner.lineStart 11142 }, 11143 end: {} 11144 }; 11145 } 11146 var startRegex = (this.scanner.source[this.scanner.index] === '/') && this.reader.isRegexStart(); 11147 var token = startRegex ? this.scanner.scanRegExp() : this.scanner.lex(); 11148 this.reader.push(token); 11149 var entry = { 11150 type: token_1.TokenName[token.type], 11151 value: this.scanner.source.slice(token.start, token.end) 11152 }; 11153 if (this.trackRange) { 11154 entry.range = [token.start, token.end]; 11155 } 11156 if (this.trackLoc) { 11157 loc.end = { 11158 line: this.scanner.lineNumber, 11159 column: this.scanner.index - this.scanner.lineStart 11160 }; 11161 entry.loc = loc; 11162 } 11163 if (token.type === 9 /* RegularExpression */) { 11164 var pattern = token.pattern; 11165 var flags = token.flags; 11166 entry.regex = { pattern: pattern, flags: flags }; 11167 } 11168 this.buffer.push(entry); 11169 } 11170 } 11171 return this.buffer.shift(); 11172 }; 11173 return Tokenizer; 11174 }()); 11175 exports.Tokenizer = Tokenizer; 11176 11177 11178 /***/ } 11179 /******/ ]) 11180 }); 11181 ; 11182 /*global define, Reflect */ 11183 11184 /* 11185 * xpcshell has a smaller stack on linux and windows (1MB vs 9MB on mac), 11186 * and the recursive nature of esprima can cause it to overflow pretty 11187 * quickly. So favor it built in Reflect parser: 11188 * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API 11189 */ 11190 define('esprimaAdapter', ['./esprima', 'env'], function (esprima, env) { 11191 if (env.get() === 'xpconnect' && typeof Reflect !== 'undefined') { 11192 return Reflect; 11193 } else { 11194 return esprima; 11195 } 11196 }); 11197 (function webpackUniversalModuleDefinition(root, factory) { 11198 var exports, module; 11199 if(typeof exports === 'object' && typeof module === 'object') 11200 module.exports = factory(); 11201 else if(typeof define === 'function' && define.amd) 11202 define('source-map', [], factory); 11203 else if(typeof exports === 'object') 11204 exports["sourceMap"] = factory(); 11205 else 11206 root["sourceMap"] = factory(); 11207 })(this, function() { 11208 return /******/ (function(modules) { // webpackBootstrap 11209 /******/ // The module cache 11210 /******/ var installedModules = {}; 11211 11212 /******/ // The require function 11213 /******/ function __webpack_require__(moduleId) { 11214 11215 /******/ // Check if module is in cache 11216 /******/ if(installedModules[moduleId]) 11217 /******/ return installedModules[moduleId].exports; 11218 11219 /******/ // Create a new module (and put it into the cache) 11220 /******/ var module = installedModules[moduleId] = { 11221 /******/ exports: {}, 11222 /******/ id: moduleId, 11223 /******/ loaded: false 11224 /******/ }; 11225 11226 /******/ // Execute the module function 11227 /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 11228 11229 /******/ // Flag the module as loaded 11230 /******/ module.loaded = true; 11231 11232 /******/ // Return the exports of the module 11233 /******/ return module.exports; 11234 /******/ } 11235 11236 11237 /******/ // expose the modules object (__webpack_modules__) 11238 /******/ __webpack_require__.m = modules; 11239 11240 /******/ // expose the module cache 11241 /******/ __webpack_require__.c = installedModules; 11242 11243 /******/ // __webpack_public_path__ 11244 /******/ __webpack_require__.p = ""; 11245 11246 /******/ // Load entry module and return exports 11247 /******/ return __webpack_require__(0); 11248 /******/ }) 11249 /************************************************************************/ 11250 /******/ ([ 11251 /* 0 */ 11252 /***/ function(module, exports, __webpack_require__) { 11253 11254 /* 11255 * Copyright 2009-2011 Mozilla Foundation and contributors 11256 * Licensed under the New BSD license. See LICENSE.txt or: 11257 * http://opensource.org/licenses/BSD-3-Clause 11258 */ 11259 exports.SourceMapGenerator = __webpack_require__(1).SourceMapGenerator; 11260 exports.SourceMapConsumer = __webpack_require__(7).SourceMapConsumer; 11261 exports.SourceNode = __webpack_require__(10).SourceNode;
vendor: 5,680 bytes, lines 11262-11365
11262 11263 11264 /***/ }, 11265 /* 1 */ 11266 /***/ function(module, exports, __webpack_require__) { 11267 11268 /* -*- Mode: js; js-indent-level: 2; -*- */ 11269 /* 11270 * Copyright 2011 Mozilla Foundation and contributors 11271 * Licensed under the New BSD license. See LICENSE or: 11272 * http://opensource.org/licenses/BSD-3-Clause 11273 */ 11274 11275 var base64VLQ = __webpack_require__(2); 11276 var util = __webpack_require__(4); 11277 var ArraySet = __webpack_require__(5).ArraySet; 11278 var MappingList = __webpack_require__(6).MappingList; 11279 11280 /** 11281 * An instance of the SourceMapGenerator represents a source map which is 11282 * being built incrementally. You may pass an object with the following 11283 * properties: 11284 * 11285 * - file: The filename of the generated source. 11286 * - sourceRoot: A root for all relative URLs in this source map. 11287 */ 11288 function SourceMapGenerator(aArgs) { 11289 if (!aArgs) { 11290 aArgs = {}; 11291 } 11292 this._file = util.getArg(aArgs, 'file', null); 11293 this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); 11294 this._skipValidation = util.getArg(aArgs, 'skipValidation', false); 11295 this._sources = new ArraySet(); 11296 this._names = new ArraySet(); 11297 this._mappings = new MappingList(); 11298 this._sourcesContents = null; 11299 } 11300 11301 SourceMapGenerator.prototype._version = 3; 11302 11303 /** 11304 * Creates a new SourceMapGenerator based on a SourceMapConsumer 11305 * 11306 * @param aSourceMapConsumer The SourceMap. 11307 */ 11308 SourceMapGenerator.fromSourceMap = 11309 function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { 11310 var sourceRoot = aSourceMapConsumer.sourceRoot; 11311 var generator = new SourceMapGenerator({ 11312 file: aSourceMapConsumer.file, 11313 sourceRoot: sourceRoot 11314 }); 11315 aSourceMapConsumer.eachMapping(function (mapping) { 11316 var newMapping = { 11317 generated: { 11318 line: mapping.generatedLine, 11319 column: mapping.generatedColumn 11320 } 11321 }; 11322 11323 if (mapping.source != null) { 11324 newMapping.source = mapping.source; 11325 if (sourceRoot != null) { 11326 newMapping.source = util.relative(sourceRoot, newMapping.source); 11327 } 11328 11329 newMapping.original = { 11330 line: mapping.originalLine, 11331 column: mapping.originalColumn 11332 }; 11333 11334 if (mapping.name != null) { 11335 newMapping.name = mapping.name; 11336 } 11337 } 11338 11339 generator.addMapping(newMapping); 11340 }); 11341 aSourceMapConsumer.sources.forEach(function (sourceFile) { 11342 var content = aSourceMapConsumer.sourceContentFor(sourceFile); 11343 if (content != null) { 11344 generator.setSourceContent(sourceFile, content); 11345 } 11346 }); 11347 return generator; 11348 }; 11349 11350 /** 11351 * Add a single mapping from original source line and column to the generated 11352 * source's line and column for this source map being created. The mapping 11353 * object should have the following properties: 11354 * 11355 * - generated: An object with the generated line and column positions. 11356 * - original: An object with the original line and column positions. 11357 * - source: The original source file (relative to the sourceRoot). 11358 * - name: An optional original token name for this mapping. 11359 */ 11360 SourceMapGenerator.prototype.addMapping = 11361 function SourceMapGenerator_addMapping(aArgs) { 11362 var generated = util.getArg(aArgs, 'generated'); 11363 var original = util.getArg(aArgs, 'original', null); 11364 var source = util.getArg(aArgs, 'source', null); 11365 var name = util.getArg(aArgs, 'n
vendor: 17,711 bytes, lines 11365-11663
11365ame', null); 11366 11367 if (!this._skipValidation) { 11368 this._validateMapping(generated, original, source, name); 11369 } 11370 11371 if (source != null) { 11372 source = String(source); 11373 if (!this._sources.has(source)) { 11374 this._sources.add(source); 11375 } 11376 } 11377 11378 if (name != null) { 11379 name = String(name); 11380 if (!this._names.has(name)) { 11381 this._names.add(name); 11382 } 11383 } 11384 11385 this._mappings.add({ 11386 generatedLine: generated.line, 11387 generatedColumn: generated.column, 11388 originalLine: original != null && original.line, 11389 originalColumn: original != null && original.column, 11390 source: source, 11391 name: name 11392 }); 11393 }; 11394 11395 /** 11396 * Set the source content for a source file. 11397 */ 11398 SourceMapGenerator.prototype.setSourceContent = 11399 function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { 11400 var source = aSourceFile; 11401 if (this._sourceRoot != null) { 11402 source = util.relative(this._sourceRoot, source); 11403 } 11404 11405 if (aSourceContent != null) { 11406 // Add the source content to the _sourcesContents map. 11407 // Create a new _sourcesContents map if the property is null. 11408 if (!this._sourcesContents) { 11409 this._sourcesContents = Object.create(null); 11410 } 11411 this._sourcesContents[util.toSetString(source)] = aSourceContent; 11412 } else if (this._sourcesContents) { 11413 // Remove the source file from the _sourcesContents map. 11414 // If the _sourcesContents map is empty, set the property to null. 11415 delete this._sourcesContents[util.toSetString(source)]; 11416 if (Object.keys(this._sourcesContents).length === 0) { 11417 this._sourcesContents = null; 11418 } 11419 } 11420 }; 11421 11422 /** 11423 * Applies the mappings of a sub-source-map for a specific source file to the 11424 * source map being generated. Each mapping to the supplied source file is 11425 * rewritten using the supplied source map. Note: The resolution for the 11426 * resulting mappings is the minimium of this map and the supplied map. 11427 * 11428 * @param aSourceMapConsumer The source map to be applied. 11429 * @param aSourceFile Optional. The filename of the source file. 11430 * If omitted, SourceMapConsumer's file property will be used. 11431 * @param aSourceMapPath Optional. The dirname of the path to the source map 11432 * to be applied. If relative, it is relative to the SourceMapConsumer. 11433 * This parameter is needed when the two source maps aren't in the same 11434 * directory, and the source map to be applied contains relative source 11435 * paths. If so, those relative source paths need to be rewritten 11436 * relative to the SourceMapGenerator. 11437 */ 11438 SourceMapGenerator.prototype.applySourceMap = 11439 function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { 11440 var sourceFile = aSourceFile; 11441 // If aSourceFile is omitted, we will use the file property of the SourceMap 11442 if (aSourceFile == null) { 11443 if (aSourceMapConsumer.file == null) { 11444 throw new Error( 11445 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + 11446 'or the source map\'s "file" property. Both were omitted.' 11447 ); 11448 } 11449 sourceFile = aSourceMapConsumer.file; 11450 } 11451 var sourceRoot = this._sourceRoot; 11452 // Make "sourceFile" relative if an absolute Url is passed. 11453 if (sourceRoot != null) { 11454 sourceFile = util.relative(sourceRoot, sourceFile); 11455 } 11456 // Applying the SourceMap can add and remove items from the sources and 11457 // the names array. 11458 var newSources = new ArraySet(); 11459 var newNames = new ArraySet(); 11460 11461 // Find mappings for the "sourceFile" 11462 this._mappings.unsortedForEach(function (mapping) { 11463 if (mapping.source === sourceFile && mapping.originalLine != null) { 11464 // Check if it can be mapped by the source map, then update the mapping. 11465 var original = aSourceMapConsumer.originalPositionFor({ 11466 line: mapping.originalLine, 11467 column: mapping.originalColumn 11468 }); 11469 if (original.source != null) { 11470 // Copy mapping 11471 mapping.source = original.source; 11472 if (aSourceMapPath != null) { 11473 mapping.source = util.join(aSourceMapPath, mapping.source) 11474 } 11475 if (sourceRoot != null) { 11476 mapping.source = util.relative(sourceRoot, mapping.source); 11477 } 11478 mapping.originalLine = original.line; 11479 mapping.originalColumn = original.column; 11480 if (original.name != null) { 11481 mapping.name = original.name; 11482 } 11483 } 11484 } 11485 11486 var source = mapping.source; 11487 if (source != null && !newSources.has(source)) { 11488 newSources.add(source); 11489 } 11490 11491 var name = mapping.name; 11492 if (name != null && !newNames.has(name)) { 11493 newNames.add(name); 11494 } 11495 11496 }, this); 11497 this._sources = newSources; 11498 this._names = newNames; 11499 11500 // Copy sourcesContents of applied map. 11501 aSourceMapConsumer.sources.forEach(function (sourceFile) { 11502 var content = aSourceMapConsumer.sourceContentFor(sourceFile); 11503 if (content != null) { 11504 if (aSourceMapPath != null) { 11505 sourceFile = util.join(aSourceMapPath, sourceFile); 11506 } 11507 if (sourceRoot != null) { 11508 sourceFile = util.relative(sourceRoot, sourceFile); 11509 } 11510 this.setSourceContent(sourceFile, content); 11511 } 11512 }, this); 11513 }; 11514 11515 /** 11516 * A mapping can have one of the three levels of data: 11517 * 11518 * 1. Just the generated position. 11519 * 2. The Generated position, original position, and original source. 11520 * 3. Generated and original position, original source, as well as a name 11521 * token. 11522 * 11523 * To maintain consistency, we validate that any new mapping being added falls 11524 * in to one of these categories. 11525 */ 11526 SourceMapGenerator.prototype._validateMapping = 11527 function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, 11528 aName) { 11529 if (aGenerated && 'line' in aGenerated && 'column' in aGenerated 11530 && aGenerated.line > 0 && aGenerated.column >= 0 11531 && !aOriginal && !aSource && !aName) { 11532 // Case 1. 11533 return; 11534 } 11535 else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated 11536 && aOriginal && 'line' in aOriginal && 'column' in aOriginal 11537 && aGenerated.line > 0 && aGenerated.column >= 0 11538 && aOriginal.line > 0 && aOriginal.column >= 0 11539 && aSource) { 11540 // Cases 2 and 3. 11541 return; 11542 } 11543 else { 11544 throw new Error('Invalid mapping: ' + JSON.stringify({ 11545 generated: aGenerated, 11546 source: aSource, 11547 original: aOriginal, 11548 name: aName 11549 })); 11550 } 11551 }; 11552 11553 /** 11554 * Serialize the accumulated mappings in to the stream of base 64 VLQs 11555 * specified by the source map format. 11556 */ 11557 SourceMapGenerator.prototype._serializeMappings = 11558 function SourceMapGenerator_serializeMappings() { 11559 var previousGeneratedColumn = 0; 11560 var previousGeneratedLine = 1; 11561 var previousOriginalColumn = 0; 11562 var previousOriginalLine = 0; 11563 var previousName = 0; 11564 var previousSource = 0; 11565 var result = ''; 11566 var next; 11567 var mapping; 11568 var nameIdx; 11569 var sourceIdx; 11570 11571 var mappings = this._mappings.toArray(); 11572 for (var i = 0, len = mappings.length; i < len; i++) { 11573 mapping = mappings[i]; 11574 next = '' 11575 11576 if (mapping.generatedLine !== previousGeneratedLine) { 11577 previousGeneratedColumn = 0; 11578 while (mapping.generatedLine !== previousGeneratedLine) { 11579 next += ';'; 11580 previousGeneratedLine++; 11581 } 11582 } 11583 else { 11584 if (i > 0) { 11585 if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { 11586 continue; 11587 } 11588 next += ','; 11589 } 11590 } 11591 11592 next += base64VLQ.encode(mapping.generatedColumn 11593 - previousGeneratedColumn); 11594 previousGeneratedColumn = mapping.generatedColumn; 11595 11596 if (mapping.source != null) { 11597 sourceIdx = this._sources.indexOf(mapping.source); 11598 next += base64VLQ.encode(sourceIdx - previousSource); 11599 previousSource = sourceIdx; 11600 11601 // lines are stored 0-based in SourceMap spec version 3 11602 next += base64VLQ.encode(mapping.originalLine - 1 11603 - previousOriginalLine); 11604 previousOriginalLine = mapping.originalLine - 1; 11605 11606 next += base64VLQ.encode(mapping.originalColumn 11607 - previousOriginalColumn); 11608 previousOriginalColumn = mapping.originalColumn; 11609 11610 if (mapping.name != null) { 11611 nameIdx = this._names.indexOf(mapping.name); 11612 next += base64VLQ.encode(nameIdx - previousName); 11613 previousName = nameIdx; 11614 } 11615 } 11616 11617 result += next; 11618 } 11619 11620 return result; 11621 }; 11622 11623 SourceMapGenerator.prototype._generateSourcesContent = 11624 function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { 11625 return aSources.map(function (source) { 11626 if (!this._sourcesContents) { 11627 return null; 11628 } 11629 if (aSourceRoot != null) { 11630 source = util.relative(aSourceRoot, source); 11631 } 11632 var key = util.toSetString(source); 11633 return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) 11634 ? this._sourcesContents[key] 11635 : null; 11636 }, this); 11637 }; 11638 11639 /** 11640 * Externalize the source map. 11641 */ 11642 SourceMapGenerator.prototype.toJSON = 11643 function SourceMapGenerator_toJSON() { 11644 var map = { 11645 version: this._version, 11646 sources: this._sources.toArray(), 11647 names: this._names.toArray(), 11648 mappings: this._serializeMappings() 11649 }; 11650 if (this._file != null) { 11651 map.file = this._file; 11652 } 11653 if (this._sourceRoot != null) { 11654 map.sourceRoot = this._sourceRoot; 11655 } 11656 if (this._sourcesContents) { 11657 map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); 11658 } 11659 11660 return map; 11661 }; 11662 11663 /**
vendor: 4,923 bytes, lines 11664-11760
11664 * Render the source map being generated to a string. 11665 */ 11666 SourceMapGenerator.prototype.toString = 11667 function SourceMapGenerator_toString() { 11668 return JSON.stringify(this.toJSON()); 11669 }; 11670 11671 exports.SourceMapGenerator = SourceMapGenerator; 11672 11673 11674 /***/ }, 11675 /* 2 */ 11676 /***/ function(module, exports, __webpack_require__) { 11677 11678 /* -*- Mode: js; js-indent-level: 2; -*- */ 11679 /* 11680 * Copyright 2011 Mozilla Foundation and contributors 11681 * Licensed under the New BSD license. See LICENSE or: 11682 * http://opensource.org/licenses/BSD-3-Clause 11683 * 11684 * Based on the Base 64 VLQ implementation in Closure Compiler: 11685 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java 11686 * 11687 * Copyright 2011 The Closure Compiler Authors. All rights reserved. 11688 * Redistribution and use in source and binary forms, with or without 11689 * modification, are permitted provided that the following conditions are 11690 * met: 11691 * 11692 * * Redistributions of source code must retain the above copyright 11693 * notice, this list of conditions and the following disclaimer. 11694 * * Redistributions in binary form must reproduce the above 11695 * copyright notice, this list of conditions and the following 11696 * disclaimer in the documentation and/or other materials provided 11697 * with the distribution. 11698 * * Neither the name of Google Inc. nor the names of its 11699 * contributors may be used to endorse or promote products derived 11700 * from this software without specific prior written permission. 11701 * 11702 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 11703 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 11704 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 11705 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 11706 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11707 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 11708 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 11709 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 11710 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 11711 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 11712 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11713 */ 11714 11715 var base64 = __webpack_require__(3); 11716 11717 // A single base 64 digit can contain 6 bits of data. For the base 64 variable 11718 // length quantities we use in the source map spec, the first bit is the sign, 11719 // the next four bits are the actual value, and the 6th bit is the 11720 // continuation bit. The continuation bit tells us whether there are more 11721 // digits in this value following this digit. 11722 // 11723 // Continuation 11724 // | Sign 11725 // | | 11726 // V V 11727 // 101011 11728 11729 var VLQ_BASE_SHIFT = 5; 11730 11731 // binary: 100000 11732 var VLQ_BASE = 1 << VLQ_BASE_SHIFT; 11733 11734 // binary: 011111 11735 var VLQ_BASE_MASK = VLQ_BASE - 1; 11736 11737 // binary: 100000 11738 var VLQ_CONTINUATION_BIT = VLQ_BASE; 11739 11740 /** 11741 * Converts from a two-complement value to a value where the sign bit is 11742 * placed in the least significant bit. For example, as decimals: 11743 * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) 11744 * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) 11745 */ 11746 function toVLQSigned(aValue) { 11747 return aValue < 0 11748 ? ((-aValue) << 1) + 1 11749 : (aValue << 1) + 0; 11750 } 11751 11752 /** 11753 * Converts to a two-complement value from a value where the sign bit is 11754 * placed in the least significant bit. For example, as decimals: 11755 * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 11756 * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 11757 */ 11758 function fromVLQSigned(aValue) { 11759 var isNegative = (aValue & 1) === 1; 11760 var shifted = aValue >>
vendor: 4,073 bytes, lines 11760-11851
11760 1; 11761 return isNegative 11762 ? -shifted 11763 : shifted; 11764 } 11765 11766 /** 11767 * Returns the base 64 VLQ encoded value. 11768 */ 11769 exports.encode = function base64VLQ_encode(aValue) { 11770 var encoded = ""; 11771 var digit; 11772 11773 var vlq = toVLQSigned(aValue); 11774 11775 do { 11776 digit = vlq & VLQ_BASE_MASK; 11777 vlq >>>= VLQ_BASE_SHIFT; 11778 if (vlq > 0) { 11779 // There are still more digits in this value, so we must make sure the 11780 // continuation bit is marked. 11781 digit |= VLQ_CONTINUATION_BIT; 11782 } 11783 encoded += base64.encode(digit); 11784 } while (vlq > 0); 11785 11786 return encoded; 11787 }; 11788 11789 /** 11790 * Decodes the next base 64 VLQ value from the given string and returns the 11791 * value and the rest of the string via the out parameter. 11792 */ 11793 exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { 11794 var strLen = aStr.length; 11795 var result = 0; 11796 var shift = 0; 11797 var continuation, digit; 11798 11799 do { 11800 if (aIndex >= strLen) { 11801 throw new Error("Expected more digits in base 64 VLQ value."); 11802 } 11803 11804 digit = base64.decode(aStr.charCodeAt(aIndex++)); 11805 if (digit === -1) { 11806 throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); 11807 } 11808 11809 continuation = !!(digit & VLQ_CONTINUATION_BIT); 11810 digit &= VLQ_BASE_MASK; 11811 result = result + (digit << shift); 11812 shift += VLQ_BASE_SHIFT; 11813 } while (continuation); 11814 11815 aOutParam.value = fromVLQSigned(result); 11816 aOutParam.rest = aIndex; 11817 }; 11818 11819 11820 /***/ }, 11821 /* 3 */ 11822 /***/ function(module, exports) { 11823 11824 /* -*- Mode: js; js-indent-level: 2; -*- */ 11825 /* 11826 * Copyright 2011 Mozilla Foundation and contributors 11827 * Licensed under the New BSD license. See LICENSE or: 11828 * http://opensource.org/licenses/BSD-3-Clause 11829 */ 11830 11831 var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); 11832 11833 /** 11834 * Encode an integer in the range of 0 to 63 to a single base 64 digit. 11835 */ 11836 exports.encode = function (number) { 11837 if (0 <= number && number < intToCharMap.length) { 11838 return intToCharMap[number]; 11839 } 11840 throw new TypeError("Must be between 0 and 63: " + number); 11841 }; 11842 11843 /** 11844 * Decode a single base 64 character code digit to an integer. Returns -1 on 11845 * failure. 11846 */ 11847 exports.decode = function (charCode) { 11848 var bigA = 65; // 'A' 11849 var bigZ = 90; // 'Z' 11850 11851 var littleA = 97; // 'a'
vendor: 14,425 bytes, lines 11852-12162
11852 var littleZ = 122; // 'z' 11853 11854 var zero = 48; // '0' 11855 var nine = 57; // '9' 11856 11857 var plus = 43; // '+' 11858 var slash = 47; // '/' 11859 11860 var littleOffset = 26; 11861 var numberOffset = 52; 11862 11863 // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ 11864 if (bigA <= charCode && charCode <= bigZ) { 11865 return (charCode - bigA); 11866 } 11867 11868 // 26 - 51: abcdefghijklmnopqrstuvwxyz 11869 if (littleA <= charCode && charCode <= littleZ) { 11870 return (charCode - littleA + littleOffset); 11871 } 11872 11873 // 52 - 61: 0123456789 11874 if (zero <= charCode && charCode <= nine) { 11875 return (charCode - zero + numberOffset); 11876 } 11877 11878 // 62: + 11879 if (charCode == plus) { 11880 return 62; 11881 } 11882 11883 // 63: / 11884 if (charCode == slash) { 11885 return 63; 11886 } 11887 11888 // Invalid base64 digit. 11889 return -1; 11890 }; 11891 11892 11893 /***/ }, 11894 /* 4 */ 11895 /***/ function(module, exports) { 11896 11897 /* -*- Mode: js; js-indent-level: 2; -*- */ 11898 /* 11899 * Copyright 2011 Mozilla Foundation and contributors 11900 * Licensed under the New BSD license. See LICENSE or: 11901 * http://opensource.org/licenses/BSD-3-Clause 11902 */ 11903 11904 /** 11905 * This is a helper function for getting values from parameter/options 11906 * objects. 11907 * 11908 * @param args The object we are extracting values from 11909 * @param name The name of the property we are getting. 11910 * @param defaultValue An optional value to return if the property is missing 11911 * from the object. If this is not specified and the property is missing, an 11912 * error will be thrown. 11913 */ 11914 function getArg(aArgs, aName, aDefaultValue) { 11915 if (aName in aArgs) { 11916 return aArgs[aName]; 11917 } else if (arguments.length === 3) { 11918 return aDefaultValue; 11919 } else { 11920 throw new Error('"' + aName + '" is a required argument.'); 11921 } 11922 } 11923 exports.getArg = getArg; 11924 11925 var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; 11926 var dataUrlRegexp = /^data:.+\,.+$/; 11927 11928 function urlParse(aUrl) { 11929 var match = aUrl.match(urlRegexp); 11930 if (!match) { 11931 return null; 11932 } 11933 return { 11934 scheme: match[1], 11935 auth: match[2], 11936 host: match[3], 11937 port: match[4], 11938 path: match[5] 11939 }; 11940 } 11941 exports.urlParse = urlParse; 11942 11943 function urlGenerate(aParsedUrl) { 11944 var url = ''; 11945 if (aParsedUrl.scheme) { 11946 url += aParsedUrl.scheme + ':'; 11947 } 11948 url += '//'; 11949 if (aParsedUrl.auth) { 11950 url += aParsedUrl.auth + '@'; 11951 } 11952 if (aParsedUrl.host) { 11953 url += aParsedUrl.host; 11954 } 11955 if (aParsedUrl.port) { 11956 url += ":" + aParsedUrl.port 11957 } 11958 if (aParsedUrl.path) { 11959 url += aParsedUrl.path; 11960 } 11961 return url; 11962 } 11963 exports.urlGenerate = urlGenerate; 11964 11965 /** 11966 * Normalizes a path, or the path portion of a URL: 11967 * 11968 * - Replaces consequtive slashes with one slash. 11969 * - Removes unnecessary '.' parts. 11970 * - Removes unnecessary '<dir>/..' parts. 11971 * 11972 * Based on code in the Node.js 'path' core module. 11973 * 11974 * @param aPath The path or url to normalize. 11975 */ 11976 function normalize(aPath) { 11977 var path = aPath; 11978 var url = urlParse(aPath); 11979 if (url) { 11980 if (!url.path) { 11981 return aPath; 11982 } 11983 path = url.path; 11984 } 11985 var isAbsolute = exports.isAbsolute(path); 11986 11987 var parts = path.split(/\/+/); 11988 for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { 11989 part = parts[i]; 11990 if (part === '.') { 11991 parts.splice(i, 1); 11992 } else if (part === '..') { 11993 up++; 11994 } else if (up > 0) { 11995 if (part === '') { 11996 // The first part is blank if the path is absolute. Trying to go 11997 // above the root is a no-op. Therefore we can remove all '..' parts 11998 // directly after the root. 11999 parts.splice(i + 1, up); 12000 up = 0; 12001 } else { 12002 parts.splice(i, 2); 12003 up--; 12004 } 12005 } 12006 } 12007 path = parts.join('/'); 12008 12009 if (path === '') { 12010 path = isAbsolute ? '/' : '.'; 12011 } 12012 12013 if (url) { 12014 url.path = path; 12015 return urlGenerate(url); 12016 } 12017 return path; 12018 } 12019 exports.normalize = normalize; 12020 12021 /** 12022 * Joins two paths/URLs. 12023 * 12024 * @param aRoot The root path or URL. 12025 * @param aPath The path or URL to be joined with the root. 12026 * 12027 * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a 12028 * scheme-relative URL: Then the scheme of aRoot, if any, is prepended 12029 * first. 12030 * - Otherwise aPath is a path. If aRoot is a URL, then its path portion 12031 * is updated with the result and aRoot is returned. Otherwise the result 12032 * is returned. 12033 * - If aPath is absolute, the result is aPath. 12034 * - Otherwise the two paths are joined with a slash. 12035 * - Joining for example 'http://' and 'www.example.com' is also supported. 12036 */ 12037 function join(aRoot, aPath) { 12038 if (aRoot === "") { 12039 aRoot = "."; 12040 } 12041 if (aPath === "") { 12042 aPath = "."; 12043 } 12044 var aPathUrl = urlParse(aPath); 12045 var aRootUrl = urlParse(aRoot); 12046 if (aRootUrl) { 12047 aRoot = aRootUrl.path || '/'; 12048 } 12049 12050 // `join(foo, '//www.example.org')` 12051 if (aPathUrl && !aPathUrl.scheme) { 12052 if (aRootUrl) { 12053 aPathUrl.scheme = aRootUrl.scheme; 12054 } 12055 return urlGenerate(aPathUrl); 12056 } 12057 12058 if (aPathUrl || aPath.match(dataUrlRegexp)) { 12059 return aPath; 12060 } 12061 12062 // `join('http://', 'www.example.com')` 12063 if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { 12064 aRootUrl.host = aPath; 12065 return urlGenerate(aRootUrl); 12066 } 12067 12068 var joined = aPath.charAt(0) === '/' 12069 ? aPath 12070 : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); 12071 12072 if (aRootUrl) { 12073 aRootUrl.path = joined; 12074 return urlGenerate(aRootUrl); 12075 } 12076 return joined; 12077 } 12078 exports.join = join; 12079 12080 exports.isAbsolute = function (aPath) { 12081 return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); 12082 }; 12083 12084 /** 12085 * Make a path relative to a URL or another path. 12086 * 12087 * @param aRoot The root path or URL. 12088 * @param aPath The path or URL to be made relative to aRoot. 12089 */ 12090 function relative(aRoot, aPath) { 12091 if (aRoot === "") { 12092 aRoot = "."; 12093 } 12094 12095 aRoot = aRoot.replace(/\/$/, ''); 12096 12097 // It is possible for the path to be above the root. In this case, simply 12098 // checking whether the root is a prefix of the path won't work. Instead, we 12099 // need to remove components from the root one by one, until either we find 12100 // a prefix that fits, or we run out of components to remove. 12101 var level = 0; 12102 while (aPath.indexOf(aRoot + '/') !== 0) { 12103 var index = aRoot.lastIndexOf("/"); 12104 if (index < 0) { 12105 return aPath; 12106 } 12107 12108 // If the only part of the root that is left is the scheme (i.e. http://, 12109 // file:///, etc.), one or more slashes (/), or simply nothing at all, we 12110 // have exhausted all components, so the path is not relative to the root. 12111 aRoot = aRoot.slice(0, index); 12112 if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { 12113 return aPath; 12114 } 12115 12116 ++level; 12117 } 12118 12119 // Make sure we add a "../" for each component we removed from the root. 12120 return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); 12121 } 12122 exports.relative = relative; 12123 12124 var supportsNullProto = (function () { 12125 var obj = Object.create(null); 12126 return !('__proto__' in obj); 12127 }()); 12128 12129 function identity (s) { 12130 return s; 12131 } 12132 12133 /** 12134 * Because behavior goes wacky when you set `__proto__` on objects, we 12135 * have to prefix all the strings in our set with an arbitrary character. 12136 * 12137 * See https://github.com/mozilla/source-map/pull/31 and 12138 * https://github.com/mozilla/source-map/issues/30 12139 * 12140 * @param String aStr 12141 */ 12142 function toSetString(aStr) { 12143 if (isProtoString(aStr)) { 12144 return '$' + aStr; 12145 } 12146 12147 return aStr; 12148 } 12149 exports.toSetString = supportsNullProto ? identity : toSetString; 12150 12151 function fromSetString(aStr) { 12152 if (isProtoString(aStr)) { 12153 return aStr.slice(1); 12154 } 12155 12156 return aStr; 12157 } 12158 exports.fromSetString = supportsNullProto ? identity : fromSetString; 12159 12160 function isProtoString(s) { 12161 if (!s) { 12162 return false;
vendor: 38,426 bytes, lines 12163-12868
12163 } 12164 12165 var length = s.length; 12166 12167 if (length < 9 /* "__proto__".length */) { 12168 return false; 12169 } 12170 12171 if (s.charCodeAt(length - 1) !== 95 /* '_' */ || 12172 s.charCodeAt(length - 2) !== 95 /* '_' */ || 12173 s.charCodeAt(length - 3) !== 111 /* 'o' */ || 12174 s.charCodeAt(length - 4) !== 116 /* 't' */ || 12175 s.charCodeAt(length - 5) !== 111 /* 'o' */ || 12176 s.charCodeAt(length - 6) !== 114 /* 'r' */ || 12177 s.charCodeAt(length - 7) !== 112 /* 'p' */ || 12178 s.charCodeAt(length - 8) !== 95 /* '_' */ || 12179 s.charCodeAt(length - 9) !== 95 /* '_' */) { 12180 return false; 12181 } 12182 12183 for (var i = length - 10; i >= 0; i--) { 12184 if (s.charCodeAt(i) !== 36 /* '$' */) { 12185 return false; 12186 } 12187 } 12188 12189 return true; 12190 } 12191 12192 /** 12193 * Comparator between two mappings where the original positions are compared. 12194 * 12195 * Optionally pass in `true` as `onlyCompareGenerated` to consider two 12196 * mappings with the same original source/line/column, but different generated 12197 * line and column the same. Useful when searching for a mapping with a 12198 * stubbed out mapping. 12199 */ 12200 function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { 12201 var cmp = mappingA.source - mappingB.source; 12202 if (cmp !== 0) { 12203 return cmp; 12204 } 12205 12206 cmp = mappingA.originalLine - mappingB.originalLine; 12207 if (cmp !== 0) { 12208 return cmp; 12209 } 12210 12211 cmp = mappingA.originalColumn - mappingB.originalColumn; 12212 if (cmp !== 0 || onlyCompareOriginal) { 12213 return cmp; 12214 } 12215 12216 cmp = mappingA.generatedColumn - mappingB.generatedColumn; 12217 if (cmp !== 0) { 12218 return cmp; 12219 } 12220 12221 cmp = mappingA.generatedLine - mappingB.generatedLine; 12222 if (cmp !== 0) { 12223 return cmp; 12224 } 12225 12226 return mappingA.name - mappingB.name; 12227 } 12228 exports.compareByOriginalPositions = compareByOriginalPositions; 12229 12230 /** 12231 * Comparator between two mappings with deflated source and name indices where 12232 * the generated positions are compared. 12233 * 12234 * Optionally pass in `true` as `onlyCompareGenerated` to consider two 12235 * mappings with the same generated line and column, but different 12236 * source/name/original line and column the same. Useful when searching for a 12237 * mapping with a stubbed out mapping. 12238 */ 12239 function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { 12240 var cmp = mappingA.generatedLine - mappingB.generatedLine; 12241 if (cmp !== 0) { 12242 return cmp; 12243 } 12244 12245 cmp = mappingA.generatedColumn - mappingB.generatedColumn; 12246 if (cmp !== 0 || onlyCompareGenerated) { 12247 return cmp; 12248 } 12249 12250 cmp = mappingA.source - mappingB.source; 12251 if (cmp !== 0) { 12252 return cmp; 12253 } 12254 12255 cmp = mappingA.originalLine - mappingB.originalLine; 12256 if (cmp !== 0) { 12257 return cmp; 12258 } 12259 12260 cmp = mappingA.originalColumn - mappingB.originalColumn; 12261 if (cmp !== 0) { 12262 return cmp; 12263 } 12264 12265 return mappingA.name - mappingB.name; 12266 } 12267 exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; 12268 12269 function strcmp(aStr1, aStr2) { 12270 if (aStr1 === aStr2) { 12271 return 0; 12272 } 12273 12274 if (aStr1 > aStr2) { 12275 return 1; 12276 } 12277 12278 return -1; 12279 } 12280 12281 /** 12282 * Comparator between two mappings with inflated source and name strings where 12283 * the generated positions are compared. 12284 */ 12285 function compareByGeneratedPositionsInflated(mappingA, mappingB) { 12286 var cmp = mappingA.generatedLine - mappingB.generatedLine; 12287 if (cmp !== 0) { 12288 return cmp; 12289 } 12290 12291 cmp = mappingA.generatedColumn - mappingB.generatedColumn; 12292 if (cmp !== 0) { 12293 return cmp; 12294 } 12295 12296 cmp = strcmp(mappingA.source, mappingB.source); 12297 if (cmp !== 0) { 12298 return cmp; 12299 } 12300 12301 cmp = mappingA.originalLine - mappingB.originalLine; 12302 if (cmp !== 0) { 12303 return cmp; 12304 } 12305 12306 cmp = mappingA.originalColumn - mappingB.originalColumn; 12307 if (cmp !== 0) { 12308 return cmp; 12309 } 12310 12311 return strcmp(mappingA.name, mappingB.name); 12312 } 12313 exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; 12314 12315 12316 /***/ }, 12317 /* 5 */ 12318 /***/ function(module, exports, __webpack_require__) { 12319 12320 /* -*- Mode: js; js-indent-level: 2; -*- */ 12321 /* 12322 * Copyright 2011 Mozilla Foundation and contributors 12323 * Licensed under the New BSD license. See LICENSE or: 12324 * http://opensource.org/licenses/BSD-3-Clause 12325 */ 12326 12327 var util = __webpack_require__(4); 12328 var has = Object.prototype.hasOwnProperty; 12329 12330 /** 12331 * A data structure which is a combination of an array and a set. Adding a new 12332 * member is O(1), testing for membership is O(1), and finding the index of an 12333 * element is O(1). Removing elements from the set is not supported. Only 12334 * strings are supported for membership. 12335 */ 12336 function ArraySet() { 12337 this._array = []; 12338 this._set = Object.create(null); 12339 } 12340 12341 /** 12342 * Static method for creating ArraySet instances from an existing array. 12343 */ 12344 ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { 12345 var set = new ArraySet(); 12346 for (var i = 0, len = aArray.length; i < len; i++) { 12347 set.add(aArray[i], aAllowDuplicates); 12348 } 12349 return set; 12350 }; 12351 12352 /** 12353 * Return how many unique items are in this ArraySet. If duplicates have been 12354 * added, than those do not count towards the size. 12355 * 12356 * @returns Number 12357 */ 12358 ArraySet.prototype.size = function ArraySet_size() { 12359 return Object.getOwnPropertyNames(this._set).length; 12360 }; 12361 12362 /** 12363 * Add the given string to this set. 12364 * 12365 * @param String aStr 12366 */ 12367 ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { 12368 var sStr = util.toSetString(aStr); 12369 var isDuplicate = has.call(this._set, sStr); 12370 var idx = this._array.length; 12371 if (!isDuplicate || aAllowDuplicates) { 12372 this._array.push(aStr); 12373 } 12374 if (!isDuplicate) { 12375 this._set[sStr] = idx; 12376 } 12377 }; 12378 12379 /** 12380 * Is the given string a member of this set? 12381 * 12382 * @param String aStr 12383 */ 12384 ArraySet.prototype.has = function ArraySet_has(aStr) { 12385 var sStr = util.toSetString(aStr); 12386 return has.call(this._set, sStr); 12387 }; 12388 12389 /** 12390 * What is the index of the given string in the array? 12391 * 12392 * @param String aStr 12393 */ 12394 ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { 12395 var sStr = util.toSetString(aStr); 12396 if (has.call(this._set, sStr)) { 12397 return this._set[sStr]; 12398 } 12399 throw new Error('"' + aStr + '" is not in the set.'); 12400 }; 12401 12402 /** 12403 * What is the element at the given index? 12404 * 12405 * @param Number aIdx 12406 */ 12407 ArraySet.prototype.at = function ArraySet_at(aIdx) { 12408 if (aIdx >= 0 && aIdx < this._array.length) { 12409 return this._array[aIdx]; 12410 } 12411 throw new Error('No element indexed by ' + aIdx); 12412 }; 12413 12414 /** 12415 * Returns the array representation of this set (which has the proper indices 12416 * indicated by indexOf). Note that this is a copy of the internal array used 12417 * for storing the members so that no one can mess with internal state. 12418 */ 12419 ArraySet.prototype.toArray = function ArraySet_toArray() { 12420 return this._array.slice(); 12421 }; 12422 12423 exports.ArraySet = ArraySet; 12424 12425 12426 /***/ }, 12427 /* 6 */ 12428 /***/ function(module, exports, __webpack_require__) { 12429 12430 /* -*- Mode: js; js-indent-level: 2; -*- */ 12431 /* 12432 * Copyright 2014 Mozilla Foundation and contributors 12433 * Licensed under the New BSD license. See LICENSE or: 12434 * http://opensource.org/licenses/BSD-3-Clause 12435 */ 12436 12437 var util = __webpack_require__(4); 12438 12439 /** 12440 * Determine whether mappingB is after mappingA with respect to generated 12441 * position. 12442 */ 12443 function generatedPositionAfter(mappingA, mappingB) { 12444 // Optimized for most common case 12445 var lineA = mappingA.generatedLine; 12446 var lineB = mappingB.generatedLine; 12447 var columnA = mappingA.generatedColumn; 12448 var columnB = mappingB.generatedColumn; 12449 return lineB > lineA || lineB == lineA && columnB >= columnA || 12450 util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; 12451 } 12452 12453 /** 12454 * A data structure to provide a sorted view of accumulated mappings in a 12455 * performance conscious manner. It trades a neglibable overhead in general 12456 * case for a large speedup in case of mappings being added in order. 12457 */ 12458 function MappingList() { 12459 this._array = []; 12460 this._sorted = true; 12461 // Serves as infimum 12462 this._last = {generatedLine: -1, generatedColumn: 0}; 12463 } 12464 12465 /** 12466 * Iterate through internal items. This method takes the same arguments that 12467 * `Array.prototype.forEach` takes. 12468 * 12469 * NOTE: The order of the mappings is NOT guaranteed. 12470 */ 12471 MappingList.prototype.unsortedForEach = 12472 function MappingList_forEach(aCallback, aThisArg) { 12473 this._array.forEach(aCallback, aThisArg); 12474 }; 12475 12476 /** 12477 * Add the given source mapping. 12478 * 12479 * @param Object aMapping 12480 */ 12481 MappingList.prototype.add = function MappingList_add(aMapping) { 12482 if (generatedPositionAfter(this._last, aMapping)) { 12483 this._last = aMapping; 12484 this._array.push(aMapping); 12485 } else { 12486 this._sorted = false; 12487 this._array.push(aMapping); 12488 } 12489 }; 12490 12491 /** 12492 * Returns the flat, sorted array of mappings. The mappings are sorted by 12493 * generated position. 12494 * 12495 * WARNING: This method returns internal data without copying, for 12496 * performance. The return value must NOT be mutated, and should be treated as 12497 * an immutable borrow. If you want to take ownership, you must make your own 12498 * copy. 12499 */ 12500 MappingList.prototype.toArray = function MappingList_toArray() { 12501 if (!this._sorted) { 12502 this._array.sort(util.compareByGeneratedPositionsInflated); 12503 this._sorted = true; 12504 } 12505 return this._array; 12506 }; 12507 12508 exports.MappingList = MappingList; 12509 12510 12511 /***/ }, 12512 /* 7 */ 12513 /***/ function(module, exports, __webpack_require__) { 12514 12515 /* -*- Mode: js; js-indent-level: 2; -*- */ 12516 /* 12517 * Copyright 2011 Mozilla Foundation and contributors 12518 * Licensed under the New BSD license. See LICENSE or: 12519 * http://opensource.org/licenses/BSD-3-Clause 12520 */ 12521 12522 var util = __webpack_require__(4); 12523 var binarySearch = __webpack_require__(8); 12524 var ArraySet = __webpack_require__(5).ArraySet; 12525 var base64VLQ = __webpack_require__(2); 12526 var quickSort = __webpack_require__(9).quickSort; 12527 12528 function SourceMapConsumer(aSourceMap) { 12529 var sourceMap = aSourceMap; 12530 if (typeof aSourceMap === 'string') { 12531 sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); 12532 } 12533 12534 return sourceMap.sections != null 12535 ? new IndexedSourceMapConsumer(sourceMap) 12536 : new BasicSourceMapConsumer(sourceMap); 12537 } 12538 12539 SourceMapConsumer.fromSourceMap = function(aSourceMap) { 12540 return BasicSourceMapConsumer.fromSourceMap(aSourceMap); 12541 } 12542 12543 /** 12544 * The version of the source mapping spec that we are consuming. 12545 */ 12546 SourceMapConsumer.prototype._version = 3; 12547 12548 // `__generatedMappings` and `__originalMappings` are arrays that hold the 12549 // parsed mapping coordinates from the source map's "mappings" attribute. They 12550 // are lazily instantiated, accessed via the `_generatedMappings` and 12551 // `_originalMappings` getters respectively, and we only parse the mappings 12552 // and create these arrays once queried for a source location. We jump through 12553 // these hoops because there can be many thousands of mappings, and parsing 12554 // them is expensive, so we only want to do it if we must. 12555 // 12556 // Each object in the arrays is of the form: 12557 // 12558 // { 12559 // generatedLine: The line number in the generated code, 12560 // generatedColumn: The column number in the generated code, 12561 // source: The path to the original source file that generated this 12562 // chunk of code, 12563 // originalLine: The line number in the original source that 12564 // corresponds to this chunk of generated code, 12565 // originalColumn: The column number in the original source that 12566 // corresponds to this chunk of generated code, 12567 // name: The name of the original symbol which generated this chunk of 12568 // code. 12569 // } 12570 // 12571 // All properties except for `generatedLine` and `generatedColumn` can be 12572 // `null`. 12573 // 12574 // `_generatedMappings` is ordered by the generated positions. 12575 // 12576 // `_originalMappings` is ordered by the original positions. 12577 12578 SourceMapConsumer.prototype.__generatedMappings = null; 12579 Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { 12580 get: function () { 12581 if (!this.__generatedMappings) { 12582 this._parseMappings(this._mappings, this.sourceRoot); 12583 } 12584 12585 return this.__generatedMappings; 12586 } 12587 }); 12588 12589 SourceMapConsumer.prototype.__originalMappings = null; 12590 Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { 12591 get: function () { 12592 if (!this.__originalMappings) { 12593 this._parseMappings(this._mappings, this.sourceRoot); 12594 } 12595 12596 return this.__originalMappings; 12597 } 12598 }); 12599 12600 SourceMapConsumer.prototype._charIsMappingSeparator = 12601 function SourceMapConsumer_charIsMappingSeparator(aStr, index) { 12602 var c = aStr.charAt(index); 12603 return c === ";" || c === ","; 12604 }; 12605 12606 /** 12607 * Parse the mappings in a string in to a data structure which we can easily 12608 * query (the ordered arrays in the `this.__generatedMappings` and 12609 * `this.__originalMappings` properties). 12610 */ 12611 SourceMapConsumer.prototype._parseMappings = 12612 function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { 12613 throw new Error("Subclasses must implement _parseMappings"); 12614 }; 12615 12616 SourceMapConsumer.GENERATED_ORDER = 1; 12617 SourceMapConsumer.ORIGINAL_ORDER = 2; 12618 12619 SourceMapConsumer.GREATEST_LOWER_BOUND = 1; 12620 SourceMapConsumer.LEAST_UPPER_BOUND = 2; 12621 12622 /** 12623 * Iterate over each mapping between an original source/line/column and a 12624 * generated line/column in this source map. 12625 * 12626 * @param Function aCallback 12627 * The function that is called with each mapping. 12628 * @param Object aContext 12629 * Optional. If specified, this object will be the value of `this` every 12630 * time that `aCallback` is called. 12631 * @param aOrder 12632 * Either `SourceMapConsumer.GENERATED_ORDER` or 12633 * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to 12634 * iterate over the mappings sorted by the generated file's line/column 12635 * order or the original's source/line/column order, respectively. Defaults to 12636 * `SourceMapConsumer.GENERATED_ORDER`. 12637 */ 12638 SourceMapConsumer.prototype.eachMapping = 12639 function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { 12640 var context = aContext || null; 12641 var order = aOrder || SourceMapConsumer.GENERATED_ORDER; 12642 12643 var mappings; 12644 switch (order) { 12645 case SourceMapConsumer.GENERATED_ORDER: 12646 mappings = this._generatedMappings; 12647 break; 12648 case SourceMapConsumer.ORIGINAL_ORDER: 12649 mappings = this._originalMappings; 12650 break; 12651 default: 12652 throw new Error("Unknown order of iteration."); 12653 } 12654 12655 var sourceRoot = this.sourceRoot; 12656 mappings.map(function (mapping) { 12657 var source = mapping.source === null ? null : this._sources.at(mapping.source); 12658 if (source != null && sourceRoot != null) { 12659 source = util.join(sourceRoot, source); 12660 } 12661 return { 12662 source: source, 12663 generatedLine: mapping.generatedLine, 12664 generatedColumn: mapping.generatedColumn, 12665 originalLine: mapping.originalLine, 12666 originalColumn: mapping.originalColumn, 12667 name: mapping.name === null ? null : this._names.at(mapping.name) 12668 }; 12669 }, this).forEach(aCallback, context); 12670 }; 12671 12672 /** 12673 * Returns all generated line and column information for the original source, 12674 * line, and column provided. If no column is provided, returns all mappings 12675 * corresponding to a either the line we are searching for or the next 12676 * closest line that has any mappings. Otherwise, returns all mappings 12677 * corresponding to the given line and either the column we are searching for 12678 * or the next closest column that has any offsets. 12679 * 12680 * The only argument is an object with the following properties: 12681 * 12682 * - source: The filename of the original source. 12683 * - line: The line number in the original source. 12684 * - column: Optional. the column number in the original source. 12685 * 12686 * and an array of objects is returned, each with the following properties: 12687 * 12688 * - line: The line number in the generated source, or null. 12689 * - column: The column number in the generated source, or null. 12690 */ 12691 SourceMapConsumer.prototype.allGeneratedPositionsFor = 12692 function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { 12693 var line = util.getArg(aArgs, 'line'); 12694 12695 // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping 12696 // returns the index of the closest mapping less than the needle. By 12697 // setting needle.originalColumn to 0, we thus find the last mapping for 12698 // the given line, provided such a mapping exists. 12699 var needle = { 12700 source: util.getArg(aArgs, 'source'), 12701 originalLine: line, 12702 originalColumn: util.getArg(aArgs, 'column', 0) 12703 }; 12704 12705 if (this.sourceRoot != null) { 12706 needle.source = util.relative(this.sourceRoot, needle.source); 12707 } 12708 if (!this._sources.has(needle.source)) { 12709 return []; 12710 } 12711 needle.source = this._sources.indexOf(needle.source); 12712 12713 var mappings = []; 12714 12715 var index = this._findMapping(needle, 12716 this._originalMappings, 12717 "originalLine", 12718 "originalColumn", 12719 util.compareByOriginalPositions, 12720 binarySearch.LEAST_UPPER_BOUND); 12721 if (index >= 0) { 12722 var mapping = this._originalMappings[index]; 12723 12724 if (aArgs.column === undefined) { 12725 var originalLine = mapping.originalLine; 12726 12727 // Iterate until either we run out of mappings, or we run into 12728 // a mapping for a different line than the one we found. Since 12729 // mappings are sorted, this is guaranteed to find all mappings for 12730 // the line we found. 12731 while (mapping && mapping.originalLine === originalLine) { 12732 mappings.push({ 12733 line: util.getArg(mapping, 'generatedLine', null), 12734 column: util.getArg(mapping, 'generatedColumn', null), 12735 lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) 12736 }); 12737 12738 mapping = this._originalMappings[++index]; 12739 } 12740 } else { 12741 var originalColumn = mapping.originalColumn; 12742 12743 // Iterate until either we run out of mappings, or we run into 12744 // a mapping for a different line than the one we were searching for. 12745 // Since mappings are sorted, this is guaranteed to find all mappings for 12746 // the line we are searching for. 12747 while (mapping && 12748 mapping.originalLine === line && 12749 mapping.originalColumn == originalColumn) { 12750 mappings.push({ 12751 line: util.getArg(mapping, 'generatedLine', null), 12752 column: util.getArg(mapping, 'generatedColumn', null), 12753 lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) 12754 }); 12755 12756 mapping = this._originalMappings[++index]; 12757 } 12758 } 12759 } 12760 12761 return mappings; 12762 }; 12763 12764 exports.SourceMapConsumer = SourceMapConsumer; 12765 12766 /** 12767 * A BasicSourceMapConsumer instance represents a parsed source map which we can 12768 * query for information about the original file positions by giving it a file 12769 * position in the generated source. 12770 * 12771 * The only parameter is the raw source map (either as a JSON string, or 12772 * already parsed to an object). According to the spec, source maps have the 12773 * following attributes: 12774 * 12775 * - version: Which version of the source map spec this map is following. 12776 * - sources: An array of URLs to the original source files. 12777 * - names: An array of identifiers which can be referrenced by individual mappings. 12778 * - sourceRoot: Optional. The URL root from which all sources are relative. 12779 * - sourcesContent: Optional. An array of contents of the original source files. 12780 * - mappings: A string of base64 VLQs which contain the actual mappings. 12781 * - file: Optional. The generated file this source map is associated with. 12782 * 12783 * Here is an example source map, taken from the source map spec[0]: 12784 * 12785 * { 12786 * version : 3, 12787 * file: "out.js", 12788 * sourceRoot : "", 12789 * sources: ["foo.js", "bar.js"], 12790 * names: ["src", "maps", "are", "fun"], 12791 * mappings: "AA,AB;;ABCDE;" 12792 * } 12793 * 12794 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# 12795 */ 12796 function BasicSourceMapConsumer(aSourceMap) { 12797 var sourceMap = aSourceMap; 12798 if (typeof aSourceMap === 'string') { 12799 sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); 12800 } 12801 12802 var version = util.getArg(sourceMap, 'version'); 12803 var sources = util.getArg(sourceMap, 'sources'); 12804 // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which 12805 // requires the array) to play nice here. 12806 var names = util.getArg(sourceMap, 'names', []); 12807 var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); 12808 var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); 12809 var mappings = util.getArg(sourceMap, 'mappings'); 12810 var file = util.getArg(sourceMap, 'file', null); 12811 12812 // Once again, Sass deviates from the spec and supplies the version as a 12813 // string rather than a number, so we use loose equality checking here. 12814 if (version != this._version) { 12815 throw new Error('Unsupported version: ' + version); 12816 } 12817 12818 sources = sources 12819 .map(String) 12820 // Some source maps produce relative source paths like "./foo.js" instead of 12821 // "foo.js". Normalize these first so that future comparisons will succeed. 12822 // See bugzil.la/1090768. 12823 .map(util.normalize) 12824 // Always ensure that absolute sources are internally stored relative to 12825 // the source root, if the source root is absolute. Not doing this would 12826 // be particularly problematic when the source root is a prefix of the 12827 // source (valid, but why??). See github issue #199 and bugzil.la/1188982. 12828 .map(function (source) { 12829 return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) 12830 ? util.relative(sourceRoot, source) 12831 : source; 12832 }); 12833 12834 // Pass `true` below to allow duplicate names and sources. While source maps 12835 // are intended to be compressed and deduplicated, the TypeScript compiler 12836 // sometimes generates source maps with duplicates in them. See Github issue 12837 // #72 and bugzil.la/889492. 12838 this._names = ArraySet.fromArray(names.map(String), true); 12839 this._sources = ArraySet.fromArray(sources, true); 12840 12841 this.sourceRoot = sourceRoot; 12842 this.sourcesContent = sourcesContent; 12843 this._mappings = mappings; 12844 this.file = file; 12845 } 12846 12847 BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); 12848 BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; 12849 12850 /** 12851 * Create a BasicSourceMapConsumer from a SourceMapGenerator. 12852 * 12853 * @param SourceMapGenerator aSourceMap 12854 * The source map that will be consumed. 12855 * @returns BasicSourceMapConsumer 12856 */ 12857 BasicSourceMapConsumer.fromSourceMap = 12858 function SourceMapConsumer_fromSourceMap(aSourceMap) { 12859 var smc = Object.create(BasicSourceMapConsumer.prototype); 12860 12861 var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); 12862 var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); 12863 smc.sourceRoot = aSourceMap._sourceRoot; 12864 smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), 12865 smc.sourceRoot); 12866 smc.file = aSourceMap._file; 12867 12868 // Because we are modifying the entries (by convert
vendor: 5,374 bytes, lines 12868-12966
12868ing string sources and 12869 // names to indices into the sources and names ArraySets), we have to make 12870 // a copy of the entry or else bad things happen. Shared mutable state 12871 // strikes again! See github issue #191. 12872 12873 var generatedMappings = aSourceMap._mappings.toArray().slice(); 12874 var destGeneratedMappings = smc.__generatedMappings = []; 12875 var destOriginalMappings = smc.__originalMappings = []; 12876 12877 for (var i = 0, length = generatedMappings.length; i < length; i++) { 12878 var srcMapping = generatedMappings[i]; 12879 var destMapping = new Mapping; 12880 destMapping.generatedLine = srcMapping.generatedLine; 12881 destMapping.generatedColumn = srcMapping.generatedColumn; 12882 12883 if (srcMapping.source) { 12884 destMapping.source = sources.indexOf(srcMapping.source); 12885 destMapping.originalLine = srcMapping.originalLine; 12886 destMapping.originalColumn = srcMapping.originalColumn; 12887 12888 if (srcMapping.name) { 12889 destMapping.name = names.indexOf(srcMapping.name); 12890 } 12891 12892 destOriginalMappings.push(destMapping); 12893 } 12894 12895 destGeneratedMappings.push(destMapping); 12896 } 12897 12898 quickSort(smc.__originalMappings, util.compareByOriginalPositions); 12899 12900 return smc; 12901 }; 12902 12903 /** 12904 * The version of the source mapping spec that we are consuming. 12905 */ 12906 BasicSourceMapConsumer.prototype._version = 3; 12907 12908 /** 12909 * The list of original sources. 12910 */ 12911 Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { 12912 get: function () { 12913 return this._sources.toArray().map(function (s) { 12914 return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; 12915 }, this); 12916 } 12917 }); 12918 12919 /** 12920 * Provide the JIT with a nice shape / hidden class. 12921 */ 12922 function Mapping() { 12923 this.generatedLine = 0; 12924 this.generatedColumn = 0; 12925 this.source = null; 12926 this.originalLine = null; 12927 this.originalColumn = null; 12928 this.name = null; 12929 } 12930 12931 /** 12932 * Parse the mappings in a string in to a data structure which we can easily 12933 * query (the ordered arrays in the `this.__generatedMappings` and 12934 * `this.__originalMappings` properties). 12935 */ 12936 BasicSourceMapConsumer.prototype._parseMappings = 12937 function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { 12938 var generatedLine = 1; 12939 var previousGeneratedColumn = 0; 12940 var previousOriginalLine = 0; 12941 var previousOriginalColumn = 0; 12942 var previousSource = 0; 12943 var previousName = 0; 12944 var length = aStr.length; 12945 var index = 0; 12946 var cachedSegments = {}; 12947 var temp = {}; 12948 var originalMappings = []; 12949 var generatedMappings = []; 12950 var mapping, str, segment, end, value; 12951 12952 while (index < length) { 12953 if (aStr.charAt(index) === ';') { 12954 generatedLine++; 12955 index++; 12956 previousGeneratedColumn = 0; 12957 } 12958 else if (aStr.charAt(index) === ',') { 12959 index++; 12960 } 12961 else { 12962 mapping = new Mapping(); 12963 mapping.generatedLine = generatedLine; 12964 12965 // Because each offset is encoded relative to the previous one, 12966 // many segments often have the same encoding. We can exploit this
vendor: 9,113 bytes, lines 12967-13112
12967 // fact by caching the parsed variable length fields of each segment, 12968 // allowing us to avoid a second parse if we encounter the same 12969 // segment again. 12970 for (end = index; end < length; end++) { 12971 if (this._charIsMappingSeparator(aStr, end)) { 12972 break; 12973 } 12974 } 12975 str = aStr.slice(index, end); 12976 12977 segment = cachedSegments[str]; 12978 if (segment) { 12979 index += str.length; 12980 } else { 12981 segment = []; 12982 while (index < end) { 12983 base64VLQ.decode(aStr, index, temp); 12984 value = temp.value; 12985 index = temp.rest; 12986 segment.push(value); 12987 } 12988 12989 if (segment.length === 2) { 12990 throw new Error('Found a source, but no line and column'); 12991 } 12992 12993 if (segment.length === 3) { 12994 throw new Error('Found a source and line, but no column'); 12995 } 12996 12997 cachedSegments[str] = segment; 12998 } 12999 13000 // Generated column. 13001 mapping.generatedColumn = previousGeneratedColumn + segment[0]; 13002 previousGeneratedColumn = mapping.generatedColumn; 13003 13004 if (segment.length > 1) { 13005 // Original source. 13006 mapping.source = previousSource + segment[1]; 13007 previousSource += segment[1]; 13008 13009 // Original line. 13010 mapping.originalLine = previousOriginalLine + segment[2]; 13011 previousOriginalLine = mapping.originalLine; 13012 // Lines are stored 0-based 13013 mapping.originalLine += 1; 13014 13015 // Original column. 13016 mapping.originalColumn = previousOriginalColumn + segment[3]; 13017 previousOriginalColumn = mapping.originalColumn; 13018 13019 if (segment.length > 4) { 13020 // Original name. 13021 mapping.name = previousName + segment[4]; 13022 previousName += segment[4]; 13023 } 13024 } 13025 13026 generatedMappings.push(mapping); 13027 if (typeof mapping.originalLine === 'number') { 13028 originalMappings.push(mapping); 13029 } 13030 } 13031 } 13032 13033 quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); 13034 this.__generatedMappings = generatedMappings; 13035 13036 quickSort(originalMappings, util.compareByOriginalPositions); 13037 this.__originalMappings = originalMappings; 13038 }; 13039 13040 /** 13041 * Find the mapping that best matches the hypothetical "needle" mapping that 13042 * we are searching for in the given "haystack" of mappings. 13043 */ 13044 BasicSourceMapConsumer.prototype._findMapping = 13045 function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, 13046 aColumnName, aComparator, aBias) { 13047 // To return the position we are searching for, we must first find the 13048 // mapping for the given position and then return the opposite position it 13049 // points to. Because the mappings are sorted, we can use binary search to 13050 // find the best mapping. 13051 13052 if (aNeedle[aLineName] <= 0) { 13053 throw new TypeError('Line must be greater than or equal to 1, got ' 13054 + aNeedle[aLineName]); 13055 } 13056 if (aNeedle[aColumnName] < 0) { 13057 throw new TypeError('Column must be greater than or equal to 0, got ' 13058 + aNeedle[aColumnName]); 13059 } 13060 13061 return binarySearch.search(aNeedle, aMappings, aComparator, aBias); 13062 }; 13063 13064 /** 13065 * Compute the last column for each generated mapping. The last column is 13066 * inclusive. 13067 */ 13068 BasicSourceMapConsumer.prototype.computeColumnSpans = 13069 function SourceMapConsumer_computeColumnSpans() { 13070 for (var index = 0; index < this._generatedMappings.length; ++index) { 13071 var mapping = this._generatedMappings[index]; 13072 13073 // Mappings do not contain a field for the last generated columnt. We 13074 // can come up with an optimistic estimate, however, by assuming that 13075 // mappings are contiguous (i.e. given two consecutive mappings, the 13076 // first mapping ends where the second one starts). 13077 if (index + 1 < this._generatedMappings.length) { 13078 var nextMapping = this._generatedMappings[index + 1]; 13079 13080 if (mapping.generatedLine === nextMapping.generatedLine) { 13081 mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; 13082 continue; 13083 } 13084 } 13085 13086 // The last mapping for each line spans the entire line. 13087 mapping.lastGeneratedColumn = Infinity; 13088 } 13089 }; 13090 13091 /** 13092 * Returns the original source, line, and column information for the generated 13093 * source's line and column positions provided. The only argument is an object 13094 * with the following properties: 13095 * 13096 * - line: The line number in the generated source. 13097 * - column: The column number in the generated source. 13098 * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or 13099 * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the 13100 * closest element that is smaller than or greater than the one we are 13101 * searching for, respectively, if the exact element cannot be found. 13102 * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. 13103 * 13104 * and an object is returned with the following properties: 13105 * 13106 * - source: The original source file, or null. 13107 * - line: The line number in the original source, or null. 13108 * - column: The column number in the original source, or null. 13109 * - name: The original identifier, or null. 13110 */ 13111 BasicSourceMapConsumer.prototype.originalPositionFor = 13112 function SourceMapConsumer_originalPositionFor(
vendor: 17,966 bytes, lines 13112-13424
13112aArgs) { 13113 var needle = { 13114 generatedLine: util.getArg(aArgs, 'line'), 13115 generatedColumn: util.getArg(aArgs, 'column') 13116 }; 13117 13118 var index = this._findMapping( 13119 needle, 13120 this._generatedMappings, 13121 "generatedLine", 13122 "generatedColumn", 13123 util.compareByGeneratedPositionsDeflated, 13124 util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) 13125 ); 13126 13127 if (index >= 0) { 13128 var mapping = this._generatedMappings[index]; 13129 13130 if (mapping.generatedLine === needle.generatedLine) { 13131 var source = util.getArg(mapping, 'source', null); 13132 if (source !== null) { 13133 source = this._sources.at(source); 13134 if (this.sourceRoot != null) { 13135 source = util.join(this.sourceRoot, source); 13136 } 13137 } 13138 var name = util.getArg(mapping, 'name', null); 13139 if (name !== null) { 13140 name = this._names.at(name); 13141 } 13142 return { 13143 source: source, 13144 line: util.getArg(mapping, 'originalLine', null), 13145 column: util.getArg(mapping, 'originalColumn', null), 13146 name: name 13147 }; 13148 } 13149 } 13150 13151 return { 13152 source: null, 13153 line: null, 13154 column: null, 13155 name: null 13156 }; 13157 }; 13158 13159 /** 13160 * Return true if we have the source content for every source in the source 13161 * map, false otherwise. 13162 */ 13163 BasicSourceMapConsumer.prototype.hasContentsOfAllSources = 13164 function BasicSourceMapConsumer_hasContentsOfAllSources() { 13165 if (!this.sourcesContent) { 13166 return false; 13167 } 13168 return this.sourcesContent.length >= this._sources.size() && 13169 !this.sourcesContent.some(function (sc) { return sc == null; }); 13170 }; 13171 13172 /** 13173 * Returns the original source content. The only argument is the url of the 13174 * original source file. Returns null if no original source content is 13175 * available. 13176 */ 13177 BasicSourceMapConsumer.prototype.sourceContentFor = 13178 function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { 13179 if (!this.sourcesContent) { 13180 return null; 13181 } 13182 13183 if (this.sourceRoot != null) { 13184 aSource = util.relative(this.sourceRoot, aSource); 13185 } 13186 13187 if (this._sources.has(aSource)) { 13188 return this.sourcesContent[this._sources.indexOf(aSource)]; 13189 } 13190 13191 var url; 13192 if (this.sourceRoot != null 13193 && (url = util.urlParse(this.sourceRoot))) { 13194 // XXX: file:// URIs and absolute paths lead to unexpected behavior for 13195 // many users. We can help them out when they expect file:// URIs to 13196 // behave like it would if they were running a local HTTP server. See 13197 // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. 13198 var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); 13199 if (url.scheme == "file" 13200 && this._sources.has(fileUriAbsPath)) { 13201 return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] 13202 } 13203 13204 if ((!url.path || url.path == "/") 13205 && this._sources.has("/" + aSource)) { 13206 return this.sourcesContent[this._sources.indexOf("/" + aSource)]; 13207 } 13208 } 13209 13210 // This function is used recursively from 13211 // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we 13212 // don't want to throw if we can't find the source - we just want to 13213 // return null, so we provide a flag to exit gracefully. 13214 if (nullOnMissing) { 13215 return null; 13216 } 13217 else { 13218 throw new Error('"' + aSource + '" is not in the SourceMap.'); 13219 } 13220 }; 13221 13222 /** 13223 * Returns the generated line and column information for the original source, 13224 * line, and column positions provided. The only argument is an object with 13225 * the following properties: 13226 * 13227 * - source: The filename of the original source. 13228 * - line: The line number in the original source. 13229 * - column: The column number in the original source. 13230 * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or 13231 * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the 13232 * closest element that is smaller than or greater than the one we are 13233 * searching for, respectively, if the exact element cannot be found. 13234 * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. 13235 * 13236 * and an object is returned with the following properties: 13237 * 13238 * - line: The line number in the generated source, or null. 13239 * - column: The column number in the generated source, or null. 13240 */ 13241 BasicSourceMapConsumer.prototype.generatedPositionFor = 13242 function SourceMapConsumer_generatedPositionFor(aArgs) { 13243 var source = util.getArg(aArgs, 'source'); 13244 if (this.sourceRoot != null) { 13245 source = util.relative(this.sourceRoot, source); 13246 } 13247 if (!this._sources.has(source)) { 13248 return { 13249 line: null, 13250 column: null, 13251 lastColumn: null 13252 }; 13253 } 13254 source = this._sources.indexOf(source); 13255 13256 var needle = { 13257 source: source, 13258 originalLine: util.getArg(aArgs, 'line'), 13259 originalColumn: util.getArg(aArgs, 'column') 13260 }; 13261 13262 var index = this._findMapping( 13263 needle, 13264 this._originalMappings, 13265 "originalLine", 13266 "originalColumn", 13267 util.compareByOriginalPositions, 13268 util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) 13269 ); 13270 13271 if (index >= 0) { 13272 var mapping = this._originalMappings[index]; 13273 13274 if (mapping.source === needle.source) { 13275 return { 13276 line: util.getArg(mapping, 'generatedLine', null), 13277 column: util.getArg(mapping, 'generatedColumn', null), 13278 lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) 13279 }; 13280 } 13281 } 13282 13283 return { 13284 line: null, 13285 column: null, 13286 lastColumn: null 13287 }; 13288 }; 13289 13290 exports.BasicSourceMapConsumer = BasicSourceMapConsumer; 13291 13292 /** 13293 * An IndexedSourceMapConsumer instance represents a parsed source map which 13294 * we can query for information. It differs from BasicSourceMapConsumer in 13295 * that it takes "indexed" source maps (i.e. ones with a "sections" field) as 13296 * input. 13297 * 13298 * The only parameter is a raw source map (either as a JSON string, or already 13299 * parsed to an object). According to the spec for indexed source maps, they 13300 * have the following attributes: 13301 * 13302 * - version: Which version of the source map spec this map is following. 13303 * - file: Optional. The generated file this source map is associated with. 13304 * - sections: A list of section definitions. 13305 * 13306 * Each value under the "sections" field has two fields: 13307 * - offset: The offset into the original specified at which this section 13308 * begins to apply, defined as an object with a "line" and "column" 13309 * field. 13310 * - map: A source map definition. This source map could also be indexed, 13311 * but doesn't have to be. 13312 * 13313 * Instead of the "map" field, it's also possible to have a "url" field 13314 * specifying a URL to retrieve a source map from, but that's currently 13315 * unsupported. 13316 * 13317 * Here's an example source map, taken from the source map spec[0], but 13318 * modified to omit a section which uses the "url" field. 13319 * 13320 * { 13321 * version : 3, 13322 * file: "app.js", 13323 * sections: [{ 13324 * offset: {line:100, column:10}, 13325 * map: { 13326 * version : 3, 13327 * file: "section.js", 13328 * sources: ["foo.js", "bar.js"], 13329 * names: ["src", "maps", "are", "fun"], 13330 * mappings: "AAAA,E;;ABCDE;" 13331 * } 13332 * }], 13333 * } 13334 * 13335 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt 13336 */ 13337 function IndexedSourceMapConsumer(aSourceMap) { 13338 var sourceMap = aSourceMap; 13339 if (typeof aSourceMap === 'string') { 13340 sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); 13341 } 13342 13343 var version = util.getArg(sourceMap, 'version'); 13344 var sections = util.getArg(sourceMap, 'sections'); 13345 13346 if (version != this._version) { 13347 throw new Error('Unsupported version: ' + version); 13348 } 13349 13350 this._sources = new ArraySet(); 13351 this._names = new ArraySet(); 13352 13353 var lastOffset = { 13354 line: -1, 13355 column: 0 13356 }; 13357 this._sections = sections.map(function (s) { 13358 if (s.url) { 13359 // The url field will require support for asynchronicity. 13360 // See https://github.com/mozilla/source-map/issues/16 13361 throw new Error('Support for url field in sections not implemented.'); 13362 } 13363 var offset = util.getArg(s, 'offset'); 13364 var offsetLine = util.getArg(offset, 'line'); 13365 var offsetColumn = util.getArg(offset, 'column'); 13366 13367 if (offsetLine < lastOffset.line || 13368 (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { 13369 throw new Error('Section offsets must be ordered and non-overlapping.'); 13370 } 13371 lastOffset = offset; 13372 13373 return { 13374 generatedOffset: { 13375 // The offset fields are 0-based, but we use 1-based indices when 13376 // encoding/decoding from VLQ. 13377 generatedLine: offsetLine + 1, 13378 generatedColumn: offsetColumn + 1 13379 }, 13380 consumer: new SourceMapConsumer(util.getArg(s, 'map')) 13381 } 13382 }); 13383 } 13384 13385 IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); 13386 IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; 13387 13388 /** 13389 * The version of the source mapping spec that we are consuming. 13390 */ 13391 IndexedSourceMapConsumer.prototype._version = 3; 13392 13393 /** 13394 * The list of original sources. 13395 */ 13396 Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { 13397 get: function () { 13398 var sources = []; 13399 for (var i = 0; i < this._sections.length; i++) { 13400 for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { 13401 sources.push(this._sections[i].consumer.sources[j]); 13402 } 13403 } 13404 return sources; 13405 } 13406 }); 13407 13408 /** 13409 * Returns the original source, line, and column information for the generated 13410 * source's line and column positions provided. The only argument is an object 13411 * with the following properties: 13412 * 13413 * - line: The line number in the generated source. 13414 * - column: The column number in the generated source. 13415 * 13416 * and an object is returned with the following properties: 13417 * 13418 * - source: The original source file, or null. 13419 * - line: The line number in the original source, or null. 13420 * - column: The column number in the original source, or null. 13421 * - name: The original identifier, or null. 13422 */ 13423 IndexedSourceMapConsumer.prototype.originalPositionFor = 13424 function IndexedSourceMapConsumer_originalPositionFor(
vendor: 5,056 bytes, lines 13424-13513
13424aArgs) { 13425 var needle = { 13426 generatedLine: util.getArg(aArgs, 'line'), 13427 generatedColumn: util.getArg(aArgs, 'column') 13428 }; 13429 13430 // Find the section containing the generated position we're trying to map 13431 // to an original position. 13432 var sectionIndex = binarySearch.search(needle, this._sections, 13433 function(needle, section) { 13434 var cmp = needle.generatedLine - section.generatedOffset.generatedLine; 13435 if (cmp) { 13436 return cmp; 13437 } 13438 13439 return (needle.generatedColumn - 13440 section.generatedOffset.generatedColumn); 13441 }); 13442 var section = this._sections[sectionIndex]; 13443 13444 if (!section) { 13445 return { 13446 source: null, 13447 line: null, 13448 column: null, 13449 name: null 13450 }; 13451 } 13452 13453 return section.consumer.originalPositionFor({ 13454 line: needle.generatedLine - 13455 (section.generatedOffset.generatedLine - 1), 13456 column: needle.generatedColumn - 13457 (section.generatedOffset.generatedLine === needle.generatedLine 13458 ? section.generatedOffset.generatedColumn - 1 13459 : 0), 13460 bias: aArgs.bias 13461 }); 13462 }; 13463 13464 /** 13465 * Return true if we have the source content for every source in the source 13466 * map, false otherwise. 13467 */ 13468 IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = 13469 function IndexedSourceMapConsumer_hasContentsOfAllSources() { 13470 return this._sections.every(function (s) { 13471 return s.consumer.hasContentsOfAllSources(); 13472 }); 13473 }; 13474 13475 /** 13476 * Returns the original source content. The only argument is the url of the 13477 * original source file. Returns null if no original source content is 13478 * available. 13479 */ 13480 IndexedSourceMapConsumer.prototype.sourceContentFor = 13481 function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { 13482 for (var i = 0; i < this._sections.length; i++) { 13483 var section = this._sections[i]; 13484 13485 var content = section.consumer.sourceContentFor(aSource, true); 13486 if (content) { 13487 return content; 13488 } 13489 } 13490 if (nullOnMissing) { 13491 return null; 13492 } 13493 else { 13494 throw new Error('"' + aSource + '" is not in the SourceMap.'); 13495 } 13496 }; 13497 13498 /** 13499 * Returns the generated line and column information for the original source, 13500 * line, and column positions provided. The only argument is an object with 13501 * the following properties: 13502 * 13503 * - source: The filename of the original source. 13504 * - line: The line number in the original source. 13505 * - column: The column number in the original source. 13506 * 13507 * and an object is returned with the following properties: 13508 * 13509 * - line: The line number in the generated source, or null. 13510 * - column: The column number in the generated source, or null. 13511 */ 13512 IndexedSourceMapConsumer.prototype.generatedPositionFor = 13513 function IndexedSourceMapConsumer_generatedPositionFor(
vendor: 5,447 bytes, lines 13513-13600
13513aArgs) { 13514 for (var i = 0; i < this._sections.length; i++) { 13515 var section = this._sections[i]; 13516 13517 // Only consider this section if the requested source is in the list of 13518 // sources of the consumer. 13519 if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { 13520 continue; 13521 } 13522 var generatedPosition = section.consumer.generatedPositionFor(aArgs); 13523 if (generatedPosition) { 13524 var ret = { 13525 line: generatedPosition.line + 13526 (section.generatedOffset.generatedLine - 1), 13527 column: generatedPosition.column + 13528 (section.generatedOffset.generatedLine === generatedPosition.line 13529 ? section.generatedOffset.generatedColumn - 1 13530 : 0) 13531 }; 13532 return ret; 13533 } 13534 } 13535 13536 return { 13537 line: null, 13538 column: null 13539 }; 13540 }; 13541 13542 /** 13543 * Parse the mappings in a string in to a data structure which we can easily 13544 * query (the ordered arrays in the `this.__generatedMappings` and 13545 * `this.__originalMappings` properties). 13546 */ 13547 IndexedSourceMapConsumer.prototype._parseMappings = 13548 function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { 13549 this.__generatedMappings = []; 13550 this.__originalMappings = []; 13551 for (var i = 0; i < this._sections.length; i++) { 13552 var section = this._sections[i]; 13553 var sectionMappings = section.consumer._generatedMappings; 13554 for (var j = 0; j < sectionMappings.length; j++) { 13555 var mapping = sectionMappings[j]; 13556 13557 var source = section.consumer._sources.at(mapping.source); 13558 if (section.consumer.sourceRoot !== null) { 13559 source = util.join(section.consumer.sourceRoot, source); 13560 } 13561 this._sources.add(source); 13562 source = this._sources.indexOf(source); 13563 13564 var name = section.consumer._names.at(mapping.name); 13565 this._names.add(name); 13566 name = this._names.indexOf(name); 13567 13568 // The mappings coming from the consumer for the section have 13569 // generated positions relative to the start of the section, so we 13570 // need to offset them to be relative to the start of the concatenated 13571 // generated file. 13572 var adjustedMapping = { 13573 source: source, 13574 generatedLine: mapping.generatedLine + 13575 (section.generatedOffset.generatedLine - 1), 13576 generatedColumn: mapping.generatedColumn + 13577 (section.generatedOffset.generatedLine === mapping.generatedLine 13578 ? section.generatedOffset.generatedColumn - 1 13579 : 0), 13580 originalLine: mapping.originalLine, 13581 originalColumn: mapping.originalColumn, 13582 name: name 13583 }; 13584 13585 this.__generatedMappings.push(adjustedMapping); 13586 if (typeof adjustedMapping.originalLine === 'number') { 13587 this.__originalMappings.push(adjustedMapping); 13588 } 13589 } 13590 } 13591 13592 quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); 13593 quickSort(this.__originalMappings, util.compareByOriginalPositions); 13594 }; 13595 13596 exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; 13597 13598 13599 /***/ }, 13600 /* 8 */
vendor: 4,704 bytes, lines 13601-13678
13601 /***/ function(module, exports) { 13602 13603 /* -*- Mode: js; js-indent-level: 2; -*- */ 13604 /* 13605 * Copyright 2011 Mozilla Foundation and contributors 13606 * Licensed under the New BSD license. See LICENSE or: 13607 * http://opensource.org/licenses/BSD-3-Clause 13608 */ 13609 13610 exports.GREATEST_LOWER_BOUND = 1; 13611 exports.LEAST_UPPER_BOUND = 2; 13612 13613 /** 13614 * Recursive implementation of binary search. 13615 * 13616 * @param aLow Indices here and lower do not contain the needle. 13617 * @param aHigh Indices here and higher do not contain the needle. 13618 * @param aNeedle The element being searched for. 13619 * @param aHaystack The non-empty array being searched. 13620 * @param aCompare Function which takes two elements and returns -1, 0, or 1. 13621 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or 13622 * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the 13623 * closest element that is smaller than or greater than the one we are 13624 * searching for, respectively, if the exact element cannot be found. 13625 */ 13626 function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { 13627 // This function terminates when one of the following is true: 13628 // 13629 // 1. We find the exact element we are looking for. 13630 // 13631 // 2. We did not find the exact element, but we can return the index of 13632 // the next-closest element. 13633 // 13634 // 3. We did not find the exact element, and there is no next-closest 13635 // element than the one we are searching for, so we return -1. 13636 var mid = Math.floor((aHigh - aLow) / 2) + aLow; 13637 var cmp = aCompare(aNeedle, aHaystack[mid], true); 13638 if (cmp === 0) { 13639 // Found the element we are looking for. 13640 return mid; 13641 } 13642 else if (cmp > 0) { 13643 // Our needle is greater than aHaystack[mid]. 13644 if (aHigh - mid > 1) { 13645 // The element is in the upper half. 13646 return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); 13647 } 13648 13649 // The exact needle element was not found in this haystack. Determine if 13650 // we are in termination case (3) or (2) and return the appropriate thing. 13651 if (aBias == exports.LEAST_UPPER_BOUND) { 13652 return aHigh < aHaystack.length ? aHigh : -1; 13653 } else { 13654 return mid; 13655 } 13656 } 13657 else { 13658 // Our needle is less than aHaystack[mid]. 13659 if (mid - aLow > 1) { 13660 // The element is in the lower half. 13661 return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); 13662 } 13663 13664 // we are in termination case (3) or (2) and return the appropriate thing. 13665 if (aBias == exports.LEAST_UPPER_BOUND) { 13666 return mid; 13667 } else { 13668 return aLow < 0 ? -1 : aLow; 13669 } 13670 } 13671 } 13672 13673 /** 13674 * This is an implementation of binary search which will always try and return 13675 * the index of the closest element if there is no exact hit. This is because 13676 * mappings between original and generated line/col pairs are single points, 13677 * and there is an implicit region between each of them, so a miss just means 13678 * that you aren't on the very start of a regi
vendor: 9,192 bytes, lines 13678-13853
13678on. 13679 * 13680 * @param aNeedle The element you are looking for. 13681 * @param aHaystack The array that is being searched. 13682 * @param aCompare A function which takes the needle and an element in the 13683 * array and returns -1, 0, or 1 depending on whether the needle is less 13684 * than, equal to, or greater than the element, respectively. 13685 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or 13686 * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the 13687 * closest element that is smaller than or greater than the one we are 13688 * searching for, respectively, if the exact element cannot be found. 13689 * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. 13690 */ 13691 exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { 13692 if (aHaystack.length === 0) { 13693 return -1; 13694 } 13695 13696 var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, 13697 aCompare, aBias || exports.GREATEST_LOWER_BOUND); 13698 if (index < 0) { 13699 return -1; 13700 } 13701 13702 // We have found either the exact element, or the next-closest element than 13703 // the one we are searching for. However, there may be more than one such 13704 // element. Make sure we always return the smallest of these. 13705 while (index - 1 >= 0) { 13706 if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { 13707 break; 13708 } 13709 --index; 13710 } 13711 13712 return index; 13713 }; 13714 13715 13716 /***/ }, 13717 /* 9 */ 13718 /***/ function(module, exports) { 13719 13720 /* -*- Mode: js; js-indent-level: 2; -*- */ 13721 /* 13722 * Copyright 2011 Mozilla Foundation and contributors 13723 * Licensed under the New BSD license. See LICENSE or: 13724 * http://opensource.org/licenses/BSD-3-Clause 13725 */ 13726 13727 // It turns out that some (most?) JavaScript engines don't self-host 13728 // `Array.prototype.sort`. This makes sense because C++ will likely remain 13729 // faster than JS when doing raw CPU-intensive sorting. However, when using a 13730 // custom comparator function, calling back and forth between the VM's C++ and 13731 // JIT'd JS is rather slow *and* loses JIT type information, resulting in 13732 // worse generated code for the comparator function than would be optimal. In 13733 // fact, when sorting with a comparator, these costs outweigh the benefits of 13734 // sorting in C++. By using our own JS-implemented Quick Sort (below), we get 13735 // a ~3500ms mean speed-up in `bench/bench.html`. 13736 13737 /** 13738 * Swap the elements indexed by `x` and `y` in the array `ary`. 13739 * 13740 * @param {Array} ary 13741 * The array. 13742 * @param {Number} x 13743 * The index of the first item. 13744 * @param {Number} y 13745 * The index of the second item. 13746 */ 13747 function swap(ary, x, y) { 13748 var temp = ary[x]; 13749 ary[x] = ary[y]; 13750 ary[y] = temp; 13751 } 13752 13753 /** 13754 * Returns a random integer within the range `low .. high` inclusive. 13755 * 13756 * @param {Number} low 13757 * The lower bound on the range. 13758 * @param {Number} high 13759 * The upper bound on the range. 13760 */ 13761 function randomIntInRange(low, high) { 13762 return Math.round(low + (Math.random() * (high - low))); 13763 } 13764 13765 /** 13766 * The Quick Sort algorithm. 13767 * 13768 * @param {Array} ary 13769 * An array to sort. 13770 * @param {function} comparator 13771 * Function to use to compare two items. 13772 * @param {Number} p 13773 * Start index of the array 13774 * @param {Number} r 13775 * End index of the array 13776 */ 13777 function doQuickSort(ary, comparator, p, r) { 13778 // If our lower bound is less than our upper bound, we (1) partition the 13779 // array into two pieces and (2) recurse on each half. If it is not, this is 13780 // the empty array and our base case. 13781 13782 if (p < r) { 13783 // (1) Partitioning. 13784 // 13785 // The partitioning chooses a pivot between `p` and `r` and moves all 13786 // elements that are less than or equal to the pivot to the before it, and 13787 // all the elements that are greater than it after it. The effect is that 13788 // once partition is done, the pivot is in the exact place it will be when 13789 // the array is put in sorted order, and it will not need to be moved 13790 // again. This runs in O(n) time. 13791 13792 // Always choose a random pivot so that an input array which is reverse 13793 // sorted does not cause O(n^2) running time. 13794 var pivotIndex = randomIntInRange(p, r); 13795 var i = p - 1; 13796 13797 swap(ary, pivotIndex, r); 13798 var pivot = ary[r]; 13799 13800 // Immediately after `j` is incremented in this loop, the following hold 13801 // true: 13802 // 13803 // * Every element in `ary[p .. i]` is less than or equal to the pivot. 13804 // 13805 // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. 13806 for (var j = p; j < r; j++) { 13807 if (comparator(ary[j], pivot) <= 0) { 13808 i += 1; 13809 swap(ary, i, j); 13810 } 13811 } 13812 13813 swap(ary, i + 1, j); 13814 var q = i + 1; 13815 13816 // (2) Recurse on each half. 13817 13818 doQuickSort(ary, comparator, p, q - 1); 13819 doQuickSort(ary, comparator, q + 1, r); 13820 } 13821 } 13822 13823 /** 13824 * Sort the given array in-place with the given comparator function. 13825 * 13826 * @param {Array} ary 13827 * An array to sort. 13828 * @param {function} comparator 13829 * Function to use to compare two items. 13830 */ 13831 exports.quickSort = function (ary, comparator) { 13832 doQuickSort(ary, comparator, 0, ary.length - 1); 13833 }; 13834 13835 13836 /***/ }, 13837 /* 10 */ 13838 /***/ function(module, exports, __webpack_require__) { 13839 13840 /* -*- Mode: js; js-indent-level: 2; -*- */ 13841 /* 13842 * Copyright 2011 Mozilla Foundation and contributors 13843 * Licensed under the New BSD license. See LICENSE or: 13844 * http://opensource.org/licenses/BSD-3-Clause 13845 */ 13846 13847 var SourceMapGenerator = __webpack_require__(1).SourceMapGenerator; 13848 var util = __webpack_require__(4); 13849 13850 // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other 13851 // operating systems these days (capturing the result). 13852 var REGEX_NEWLINE = /(\r?\n)/; 13853
vendor: 4,715 bytes, lines 13854-13925
13854 // Newline character code for charCodeAt() comparisons 13855 var NEWLINE_CODE = 10; 13856 13857 // Private symbol for identifying `SourceNode`s when multiple versions of 13858 // the source-map library are loaded. This MUST NOT CHANGE across 13859 // versions! 13860 var isSourceNode = "$$$isSourceNode$$$"; 13861 13862 /** 13863 * SourceNodes provide a way to abstract over interpolating/concatenating 13864 * snippets of generated JavaScript source code while maintaining the line and 13865 * column information associated with the original source code. 13866 * 13867 * @param aLine The original line number. 13868 * @param aColumn The original column number. 13869 * @param aSource The original source's filename. 13870 * @param aChunks Optional. An array of strings which are snippets of 13871 * generated JS, or other SourceNodes. 13872 * @param aName The original identifier. 13873 */ 13874 function SourceNode(aLine, aColumn, aSource, aChunks, aName) { 13875 this.children = []; 13876 this.sourceContents = {}; 13877 this.line = aLine == null ? null : aLine; 13878 this.column = aColumn == null ? null : aColumn; 13879 this.source = aSource == null ? null : aSource; 13880 this.name = aName == null ? null : aName; 13881 this[isSourceNode] = true; 13882 if (aChunks != null) this.add(aChunks); 13883 } 13884 13885 /** 13886 * Creates a SourceNode from generated code and a SourceMapConsumer. 13887 * 13888 * @param aGeneratedCode The generated code 13889 * @param aSourceMapConsumer The SourceMap for the generated code 13890 * @param aRelativePath Optional. The path that relative sources in the 13891 * SourceMapConsumer should be relative to. 13892 */ 13893 SourceNode.fromStringWithSourceMap = 13894 function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { 13895 // The SourceNode we want to fill with the generated code 13896 // and the SourceMap 13897 var node = new SourceNode(); 13898 13899 // All even indices of this array are one line of the generated code, 13900 // while all odd indices are the newlines between two adjacent lines 13901 // (since `REGEX_NEWLINE` captures its match). 13902 // Processed fragments are removed from this array, by calling `shiftNextLine`. 13903 var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); 13904 var shiftNextLine = function() { 13905 var lineContents = remainingLines.shift(); 13906 // The last line of a file might not have a newline. 13907 var newLine = remainingLines.shift() || ""; 13908 return lineContents + newLine; 13909 }; 13910 13911 // We need to remember the position of "remainingLines" 13912 var lastGeneratedLine = 1, lastGeneratedColumn = 0; 13913 13914 // The generate SourceNodes we need a code range. 13915 // To extract it current and last mapping is used. 13916 // Here we store the last mapping. 13917 var lastMapping = null; 13918 13919 aSourceMapConsumer.eachMapping(function (mapping) { 13920 if (lastMapping !== null) { 13921 // We add the code from "lastMapping" to "mapping": 13922 // First check if there is a new line in between. 13923 if (lastGeneratedLine < mapping.generatedLine) { 13924 // Associate first line with "lastMapping" 13925 addMappingWithCode(lastMapping, shiftNextLine()
vendor: 11,277 bytes, lines 13925-14119
13925); 13926 lastGeneratedLine++; 13927 lastGeneratedColumn = 0; 13928 // The remaining code is added without mapping 13929 } else { 13930 // There is no new line in between. 13931 // Associate the code between "lastGeneratedColumn" and 13932 // "mapping.generatedColumn" with "lastMapping" 13933 var nextLine = remainingLines[0]; 13934 var code = nextLine.substr(0, mapping.generatedColumn - 13935 lastGeneratedColumn); 13936 remainingLines[0] = nextLine.substr(mapping.generatedColumn - 13937 lastGeneratedColumn); 13938 lastGeneratedColumn = mapping.generatedColumn; 13939 addMappingWithCode(lastMapping, code); 13940 // No more remaining code, continue 13941 lastMapping = mapping; 13942 return; 13943 } 13944 } 13945 // We add the generated code until the first mapping 13946 // to the SourceNode without any mapping. 13947 // Each line is added as separate string. 13948 while (lastGeneratedLine < mapping.generatedLine) { 13949 node.add(shiftNextLine()); 13950 lastGeneratedLine++; 13951 } 13952 if (lastGeneratedColumn < mapping.generatedColumn) { 13953 var nextLine = remainingLines[0]; 13954 node.add(nextLine.substr(0, mapping.generatedColumn)); 13955 remainingLines[0] = nextLine.substr(mapping.generatedColumn); 13956 lastGeneratedColumn = mapping.generatedColumn; 13957 } 13958 lastMapping = mapping; 13959 }, this); 13960 // We have processed all mappings. 13961 if (remainingLines.length > 0) { 13962 if (lastMapping) { 13963 // Associate the remaining code in the current line with "lastMapping" 13964 addMappingWithCode(lastMapping, shiftNextLine()); 13965 } 13966 // and add the remaining lines without any mapping 13967 node.add(remainingLines.join("")); 13968 } 13969 13970 // Copy sourcesContent into SourceNode 13971 aSourceMapConsumer.sources.forEach(function (sourceFile) { 13972 var content = aSourceMapConsumer.sourceContentFor(sourceFile); 13973 if (content != null) { 13974 if (aRelativePath != null) { 13975 sourceFile = util.join(aRelativePath, sourceFile); 13976 } 13977 node.setSourceContent(sourceFile, content); 13978 } 13979 }); 13980 13981 return node; 13982 13983 function addMappingWithCode(mapping, code) { 13984 if (mapping === null || mapping.source === undefined) { 13985 node.add(code); 13986 } else { 13987 var source = aRelativePath 13988 ? util.join(aRelativePath, mapping.source) 13989 : mapping.source; 13990 node.add(new SourceNode(mapping.originalLine, 13991 mapping.originalColumn, 13992 source, 13993 code, 13994 mapping.name)); 13995 } 13996 } 13997 }; 13998 13999 /** 14000 * Add a chunk of generated JS to this source node. 14001 * 14002 * @param aChunk A string snippet of generated JS code, another instance of 14003 * SourceNode, or an array where each member is one of those things. 14004 */ 14005 SourceNode.prototype.add = function SourceNode_add(aChunk) { 14006 if (Array.isArray(aChunk)) { 14007 aChunk.forEach(function (chunk) { 14008 this.add(chunk); 14009 }, this); 14010 } 14011 else if (aChunk[isSourceNode] || typeof aChunk === "string") { 14012 if (aChunk) { 14013 this.children.push(aChunk); 14014 } 14015 } 14016 else { 14017 throw new TypeError( 14018 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk 14019 ); 14020 } 14021 return this; 14022 }; 14023 14024 /** 14025 * Add a chunk of generated JS to the beginning of this source node. 14026 * 14027 * @param aChunk A string snippet of generated JS code, another instance of 14028 * SourceNode, or an array where each member is one of those things. 14029 */ 14030 SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { 14031 if (Array.isArray(aChunk)) { 14032 for (var i = aChunk.length-1; i >= 0; i--) { 14033 this.prepend(aChunk[i]); 14034 } 14035 } 14036 else if (aChunk[isSourceNode] || typeof aChunk === "string") { 14037 this.children.unshift(aChunk); 14038 } 14039 else { 14040 throw new TypeError( 14041 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk 14042 ); 14043 } 14044 return this; 14045 }; 14046 14047 /** 14048 * Walk over the tree of JS snippets in this node and its children. The 14049 * walking function is called once for each snippet of JS and is passed that 14050 * snippet and the its original associated source's line/column location. 14051 * 14052 * @param aFn The traversal function. 14053 */ 14054 SourceNode.prototype.walk = function SourceNode_walk(aFn) { 14055 var chunk; 14056 for (var i = 0, len = this.children.length; i < len; i++) { 14057 chunk = this.children[i]; 14058 if (chunk[isSourceNode]) { 14059 chunk.walk(aFn); 14060 } 14061 else { 14062 if (chunk !== '') { 14063 aFn(chunk, { source: this.source, 14064 line: this.line, 14065 column: this.column, 14066 name: this.name }); 14067 } 14068 } 14069 } 14070 }; 14071 14072 /** 14073 * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between 14074 * each of `this.children`. 14075 * 14076 * @param aSep The separator. 14077 */ 14078 SourceNode.prototype.join = function SourceNode_join(aSep) { 14079 var newChildren; 14080 var i; 14081 var len = this.children.length; 14082 if (len > 0) { 14083 newChildren = []; 14084 for (i = 0; i < len-1; i++) { 14085 newChildren.push(this.children[i]); 14086 newChildren.push(aSep); 14087 } 14088 newChildren.push(this.children[i]); 14089 this.children = newChildren; 14090 } 14091 return this; 14092 }; 14093 14094 /** 14095 * Call String.prototype.replace on the very right-most source snippet. Useful 14096 * for trimming whitespace from the end of a source node, etc. 14097 * 14098 * @param aPattern The pattern to replace. 14099 * @param aReplacement The thing to replace the pattern with. 14100 */ 14101 SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { 14102 var lastChild = this.children[this.children.length - 1]; 14103 if (lastChild[isSourceNode]) { 14104 lastChild.replaceRight(aPattern, aReplacement); 14105 } 14106 else if (typeof lastChild === 'string') { 14107 this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); 14108 } 14109 else { 14110 this.children.push(''.replace(aPattern, aReplacement)); 14111 } 14112 return this; 14113 }; 14114 14115 /** 14116 * Set the source content for a source file. This will be added to the SourceMapGenerator 14117 * in the sourcesContent field. 14118 * 14119 * @param aSourceFile The filename of the source file
vendor: 4,248 bytes, lines 14120-14193
14120 * @param aSourceContent The content of the source file 14121 */ 14122 SourceNode.prototype.setSourceContent = 14123 function SourceNode_setSourceContent(aSourceFile, aSourceContent) { 14124 this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; 14125 }; 14126 14127 /** 14128 * Walk over the tree of SourceNodes. The walking function is called for each 14129 * source file content and is passed the filename and source content. 14130 * 14131 * @param aFn The traversal function. 14132 */ 14133 SourceNode.prototype.walkSourceContents = 14134 function SourceNode_walkSourceContents(aFn) { 14135 for (var i = 0, len = this.children.length; i < len; i++) { 14136 if (this.children[i][isSourceNode]) { 14137 this.children[i].walkSourceContents(aFn); 14138 } 14139 } 14140 14141 var sources = Object.keys(this.sourceContents); 14142 for (var i = 0, len = sources.length; i < len; i++) { 14143 aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); 14144 } 14145 }; 14146 14147 /** 14148 * Return the string representation of this source node. Walks over the tree 14149 * and concatenates all the various snippets together to one string. 14150 */ 14151 SourceNode.prototype.toString = function SourceNode_toString() { 14152 var str = ""; 14153 this.walk(function (chunk) { 14154 str += chunk; 14155 }); 14156 return str; 14157 }; 14158 14159 /** 14160 * Returns the string representation of this source node along with a source 14161 * map. 14162 */ 14163 SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { 14164 var generated = { 14165 code: "", 14166 line: 1, 14167 column: 0 14168 }; 14169 var map = new SourceMapGenerator(aArgs); 14170 var sourceMappingActive = false; 14171 var lastOriginalSource = null; 14172 var lastOriginalLine = null; 14173 var lastOriginalColumn = null; 14174 var lastOriginalName = null; 14175 this.walk(function (chunk, original) { 14176 generated.code += chunk; 14177 if (original.source !== null 14178 && original.line !== null 14179 && original.column !== null) { 14180 if(lastOriginalSource !== original.source 14181 || lastOriginalLine !== original.line 14182 || lastOriginalColumn !== original.column 14183 || lastOriginalName !== original.name) { 14184 map.addMapping({ 14185 source: original.source, 14186 original: { 14187 line: original.line, 14188 column: original.column 14189 }, 14190 generated: { 14191 line: generated.line, 14192 column: generated.column 14193 },
vendor: 4,924 bytes, lines 14194-14288
14194 name: original.name 14195 }); 14196 } 14197 lastOriginalSource = original.source; 14198 lastOriginalLine = original.line; 14199 lastOriginalColumn = original.column; 14200 lastOriginalName = original.name; 14201 sourceMappingActive = true; 14202 } else if (sourceMappingActive) { 14203 map.addMapping({ 14204 generated: { 14205 line: generated.line, 14206 column: generated.column 14207 } 14208 }); 14209 lastOriginalSource = null; 14210 sourceMappingActive = false; 14211 } 14212 for (var idx = 0, length = chunk.length; idx < length; idx++) { 14213 if (chunk.charCodeAt(idx) === NEWLINE_CODE) { 14214 generated.line++; 14215 generated.column = 0; 14216 // Mappings end at eol 14217 if (idx + 1 === length) { 14218 lastOriginalSource = null; 14219 sourceMappingActive = false; 14220 } else if (sourceMappingActive) { 14221 map.addMapping({ 14222 source: original.source, 14223 original: { 14224 line: original.line, 14225 column: original.column 14226 }, 14227 generated: { 14228 line: generated.line, 14229 column: generated.column 14230 }, 14231 name: original.name 14232 }); 14233 } 14234 } else { 14235 generated.column++; 14236 } 14237 } 14238 }); 14239 this.walkSourceContents(function (sourceFile, sourceContent) { 14240 map.setSourceContent(sourceFile, sourceContent); 14241 }); 14242 14243 return { code: generated.code, map: map }; 14244 }; 14245 14246 exports.SourceNode = SourceNode; 14247 14248 14249 /***/ } 14250 /******/ ]) 14251 }); 14252 ;//Distributed under the BSD license: 14253//Copyright 2012 (c) Mihai Bazon <[email protected]> 14254 define('uglifyjs', ['exports', 'source-map', 'logger', 'env!env/file'], function (exports, MOZ_SourceMap, logger, rjsFile) { 14255 14256 /*********************************************************************** 14257 14258 A JavaScript tokenizer / parser / beautifier / compressor. 14259 https://github.com/mishoo/UglifyJS2 14260 14261 -------------------------------- (C) --------------------------------- 14262 14263 Author: Mihai Bazon 14264 <[email protected]> 14265 http://mihai.bazon.net/blog 14266 14267 Distributed under the BSD license: 14268 14269 Copyright 2012 (c) Mihai Bazon <[email protected]> 14270 14271 Redistribution and use in source and binary forms, with or without 14272 modification, are permitted provided that the following conditions 14273 are met: 14274 14275 * Redistributions of source code must retain the above 14276 copyright notice, this list of conditions and the following 14277 disclaimer. 14278 14279 * Redistributions in binary form must reproduce the above 14280 copyright notice, this list of conditions and the following 14281 disclaimer in the documentation and/or other materials 14282 provided with the distribution. 14283 14284 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 14285 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14286 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 14287 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 14288 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
14289 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 14290 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 14291 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 14292 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 14293 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 14294 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 14295 SUCH DAMAGE. 14296 14297 ***********************************************************************/ 14298 14299 "use strict"; 14300 14301 function array_to_hash(a) { 14302 var ret = Object.create(null); 14303 for (var i = 0; i < a.length; ++i) 14304 ret[a[i]] = true; 14305 return ret; 14306 }; 14307 14308 function slice(a, start) { 14309 return Array.prototype.slice.call(a, start || 0); 14310 }; 14311 14312 function characters(str) { 14313 return str.split(""); 14314 }; 14315 14316 function member(name, array) { 14317 return array.indexOf(name) >= 0; 14318 }; 14319 14320 function find_if(func, array) { 14321 for (var i = 0, n = array.length; i < n; ++i) { 14322 if (func(array[i])) 14323 return array[i]; 14324 } 14325 }; 14326 14327 function repeat_string(str, i) { 14328 if (i <= 0) return ""; 14329 if (i == 1) return str; 14330 var d = repeat_string(str, i >> 1); 14331 d += d; 14332 if (i & 1) d += str; 14333 return d; 14334 }; 14335 14336 function configure_error_stack(fn) { 14337 Object.defineProperty(fn.prototype, "stack", { 14338 get: function() { 14339 var err = new Error(this.message); 14340 err.name = this.name; 14341 try { 14342 throw err; 14343 } catch(e) { 14344 return e.stack; 14345 } 14346 } 14347 }); 14348 } 14349 14350 function DefaultsError(msg, defs) { 14351 this.message = msg; 14352 this.defs = defs; 14353 }; 14354 DefaultsError.prototype = Object.create(Error.prototype); 14355 DefaultsError.prototype.constructor = DefaultsError; 14356 DefaultsError.prototype.name = "DefaultsError"; 14357 configure_error_stack(DefaultsError); 14358 14359 DefaultsError.croak = function(msg, defs) { 14360 throw new DefaultsError(msg, defs); 14361 }; 14362 14363 function defaults(args, defs, croak) { 14364 if (args === true) 14365 args = {}; 14366 var ret = args || {}; 14367 if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) 14368 DefaultsError.croak("`" + i + "` is not a supported option", defs); 14369 for (var i in defs) if (HOP(defs, i)) { 14370 ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; 14371 } 14372 return ret; 14373 }; 14374 14375 function merge(obj, ext) { 14376 var count = 0; 14377 for (var i in ext) if (HOP(ext, i)) { 14378 obj[i] = ext[i]; 14379 count++; 14380 } 14381 return count; 14382 }; 14383 14384 function noop() {} 14385 function return_false() { return false; } 14386 function return_true() { return true; } 14387 function return_this() { return this; } 14388 function return_null() { return null; } 14389 14390 var MAP = (function(){ 14391 function MAP(a, f, backwards) { 14392 var ret = [], top = [], i; 14393 function doit() { 14394 var val = f(a[i], i); 14395 var is_last = val instanceof Last; 14396 if (is_last) val = val.v; 14397 if (val instanceof AtTop) { 14398 val = val.v; 14399 if (val instanceof Splice) { 14400 top.push.apply(top, backwards ? val.v.slice().reverse() : val.v); 14401 } else { 14402 top.push(val); 14403 } 14404 } 14405 else if (val !== skip) { 14406 if (val instanceof Splice) {
14407 ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); 14408 } else { 14409 ret.push(val); 14410 } 14411 } 14412 return is_last; 14413 }; 14414 if (a instanceof Array) { 14415 if (backwards) { 14416 for (i = a.length; --i >= 0;) if (doit()) break; 14417 ret.reverse(); 14418 top.reverse(); 14419 } else { 14420 for (i = 0; i < a.length; ++i) if (doit()) break; 14421 } 14422 } 14423 else { 14424 for (i in a) if (HOP(a, i)) if (doit()) break; 14425 } 14426 return top.concat(ret); 14427 }; 14428 MAP.at_top = function(val) { return new AtTop(val) }; 14429 MAP.splice = function(val) { return new Splice(val) }; 14430 MAP.last = function(val) { return new Last(val) }; 14431 var skip = MAP.skip = {}; 14432 function AtTop(val) { this.v = val }; 14433 function Splice(val) { this.v = val }; 14434 function Last(val) { this.v = val }; 14435 return MAP; 14436 })(); 14437 14438 function push_uniq(array, el) { 14439 if (array.indexOf(el) < 0) 14440 array.push(el); 14441 }; 14442 14443 function string_template(text, props) { 14444 return text.replace(/\{(.+?)\}/g, function(str, p){ 14445 return props && props[p]; 14446 }); 14447 }; 14448 14449 function remove(array, el) { 14450 for (var i = array.length; --i >= 0;) { 14451 if (array[i] === el) array.splice(i, 1); 14452 } 14453 }; 14454 14455 function mergeSort(array, cmp) { 14456 if (array.length < 2) return array.slice(); 14457 function merge(a, b) { 14458 var r = [], ai = 0, bi = 0, i = 0; 14459 while (ai < a.length && bi < b.length) { 14460 cmp(a[ai], b[bi]) <= 0 14461 ? r[i++] = a[ai++] 14462 : r[i++] = b[bi++]; 14463 }
14464 if (ai < a.length) r.push.apply(r, a.slice(ai)); 14465 if (bi < b.length) r.push.apply(r, b.slice(bi)); 14466 return r; 14467 }; 14468 function _ms(a) { 14469 if (a.length <= 1) 14470 return a; 14471 var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m); 14472 left = _ms(left); 14473 right = _ms(right); 14474 return merge(left, right); 14475 }; 14476 return _ms(array); 14477 }; 14478 14479 function set_difference(a, b) { 14480 return a.filter(function(el){ 14481 return b.indexOf(el) < 0; 14482 }); 14483 }; 14484 14485 function set_intersection(a, b) { 14486 return a.filter(function(el){ 14487 return b.indexOf(el) >= 0; 14488 }); 14489 }; 14490 14491// this function is taken from Acorn [1], written by Marijn Haverbeke 14492// [1] https://github.com/marijnh/acorn 14493 function makePredicate(words) { 14494 if (!(words instanceof Array)) words = words.split(" "); 14495 var f = "", cats = []; 14496 out: for (var i = 0; i < words.length; ++i) { 14497 for (var j = 0; j < cats.length; ++j) 14498 if (cats[j][0].length == words[i].length) { 14499 cats[j].push(words[i]); 14500 continue out; 14501 } 14502 cats.push([words[i]]); 14503 } 14504 function quote(word) { 14505 return JSON.stringify(word).replace(/[\u2028\u2029]/g, function(s) { 14506 switch (s) { 14507 case "\u2028": return "\\u2028"; 14508 case "\u2029": return "\\u2029"; 14509 } 14510 return s; 14511 }); 14512 } 14513 function compareTo(arr) { 14514 if (arr.length == 1) return f += "return str === " + quote(arr[0]) + ";"; 14515 f += "switch(str){"; 14516 for (var i = 0; i < arr.length; ++i) f += "case " + quote(arr[i]) + ":"; 14517 f += "return true}return false;"; 14518 } 14519 // When there are more than three length categories, an outer 14520 // switch first dispatches on the lengths, to save on comparisons. 14521 if (cats.length > 3) { 14522 cats.sort(function(a, b) {return b.length - a.length;}); 14523 f += "switch(str.length){"; 14524 for (var i = 0; i < cats.length; ++i) { 14525 var cat = cats[i]; 14526 f += "case " + cat[0].length + ":"; 14527 compareTo(cat); 14528 } 14529 f += "}"; 14530 // Otherwise, simply generate a flat `switch` statement. 14531 } else { 14532 compareTo(words); 14533 } 14534 return new Function("str", f); 14535 }; 14536 14537 function all(array, predicate) { 14538 for (var i = array.length; --i >= 0;) 14539 if (!predicate(array[i])) 14540 return false; 14541 return true; 14542 }; 14543 14544 function Dictionary() { 14545 this._values = Object.create(null); 14546 this._size = 0; 14547 }; 14548 Dictionary.prototype = { 14549 set: function(key, val) { 14550 if (!this.has(key)) ++this._size; 14551 this._values["$" + key] = val; 14552 return this; 14553 }, 14554 add: function(key, val) { 14555 if (this.has(key)) { 14556 this.get(key).push(val); 14557 } else { 14558 this.set(key, [ val ]); 14559 } 14560 return this; 14561 }, 14562 get: function(key) { return this._values["$" + key] }, 14563 del: function(key) { 14564 if (this.has(key)) { 14565 --this._size; 14566 delete this._values["$" + key]; 14567 } 14568 return this; 14569 }, 14570 has: function(key) { return ("$" + key) in this._values }, 14571 each: function(f) { 14572 for (var i in this._values) 14573 f(this._values[i], i.substr(1)); 14574 }, 14575 size: function() { 14576 return this._size; 14577 }, 14578 map: function(f) { 14579 var ret = []; 14580 for (var i in this._values)
14581 ret.push(f(this._values[i], i.substr(1))); 14582 return ret; 14583 }, 14584 toObject: function() { return this._values } 14585 }; 14586 Dictionary.fromObject = function(obj) { 14587 var dict = new Dictionary(); 14588 dict._size = merge(dict._values, obj); 14589 return dict; 14590 }; 14591 14592 function HOP(obj, prop) { 14593 return Object.prototype.hasOwnProperty.call(obj, prop); 14594 } 14595 14596// return true if the node at the top of the stack (that means the 14597// innermost node in the current output) is lexically the first in 14598// a statement. 14599 function first_in_statement(stack) { 14600 var node = stack.parent(-1); 14601 for (var i = 0, p; p = stack.parent(i); i++) { 14602 if (p instanceof AST_Statement && p.body === node) 14603 return true; 14604 if ((p instanceof AST_Seq && p.car === node ) || 14605 (p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) || 14606 (p instanceof AST_Dot && p.expression === node ) || 14607 (p instanceof AST_Sub && p.expression === node ) || 14608 (p instanceof AST_Conditional && p.condition === node ) || 14609 (p instanceof AST_Binary && p.left === node ) || 14610 (p instanceof AST_UnaryPostfix && p.expression === node )) 14611 { 14612 node = p; 14613 } else { 14614 return false; 14615 } 14616 } 14617 } 14618 14619 /*********************************************************************** 14620 14621 A JavaScript tokenizer / parser / beautifier / compressor. 14622 https://github.com/mishoo/UglifyJS2 14623 14624 -------------------------------- (C) --------------------------------- 14625 14626 Author: Mihai Bazon 14627 <[email protected]> 14628 http://mihai.bazon.net/blog 14629 14630 Distributed under the BSD license: 14631 14632 Copyright 2012 (c) Mihai Bazon <[email protected]> 14633 14634 Redistribution and use in source and binary forms, with or without 14635 modification, are permitted provided that the following conditions 14636 are met: 14637 14638 * Redistributions of source code must retain the above 14639 copyright notice, this list of conditions and the following 14640 disclaimer. 14641 14642 * Redistributions in binary form must reproduce the above 14643 copyright notice, this list of conditions and the following 14644 disclaimer in the documentation and/or other materials 14645 provided with the distribution. 14646 14647 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 14648 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14649 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 14650 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 14651 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 14652 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 14653 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 14654 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 14655 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 14656 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 14657 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 14658 SUCH DAMAGE. 14659 14660 ***********************************************************************/ 14661 14662 "use strict"; 14663 14664 function DEFNODE(type, props, methods, base) { 14665 if (arguments.length < 4) base = AST_Node; 14666 if (!props) props = []; 14667 else props = props.split(/\s+/); 14668 var self_props = props; 14669 if (base && base.PROPS) 14670 props = props.concat(base.PROPS); 14671 var code = "return function AST_" + type + "(props){ if (props) { "; 14672 for (var i = props.length; --i >= 0;) { 14673 code += "this." + props[i] + " = props." + props[i] + ";"; 14674 } 14675 var proto = base && new base; 14676 if (proto && proto.initialize || (methods && methods.initialize)) 14677 code += "this.initialize();"; 14678 code += "}}"; 14679 var ctor = new Function(code)(); 14680 if (proto) { 14681 ctor.prototype = proto; 14682 ctor.BASE = base; 14683 } 14684 if (base) base.SUBCLASSES.push(ctor); 14685 ctor.prototype.CTOR = ctor;
14686 ctor.PROPS = props || null; 14687 ctor.SELF_PROPS = self_props; 14688 ctor.SUBCLASSES = []; 14689 if (type) { 14690 ctor.prototype.TYPE = ctor.TYPE = type; 14691 } 14692 if (methods) for (i in methods) if (HOP(methods, i)) { 14693 if (/^\$/.test(i)) { 14694 ctor[i.substr(1)] = methods[i]; 14695 } else { 14696 ctor.prototype[i] = methods[i]; 14697 } 14698 } 14699 ctor.DEFMETHOD = function(name, method) { 14700 this.prototype[name] = method; 14701 }; 14702 if (typeof exports !== "undefined") { 14703 exports["AST_" + type] = ctor; 14704 } 14705 return ctor; 14706 }; 14707 14708 var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", { 14709 }, null); 14710 14711 var AST_Node = DEFNODE("Node", "start end", { 14712 _clone: function(deep) { 14713 if (deep) { 14714 var self = this.clone(); 14715 return self.transform(new TreeTransformer(function(node) { 14716 if (node !== self) { 14717 return node.clone(true); 14718 } 14719 })); 14720 } 14721 return new this.CTOR(this); 14722 }, 14723 clone: function(deep) { 14724 return this._clone(deep); 14725 }, 14726 $documentation: "Base class of all AST nodes", 14727 $propdoc: { 14728 start: "[AST_Token] The first token of this node", 14729 end: "[AST_Token] The last token of this node" 14730 }, 14731 _walk: function(visitor) { 14732 return visitor._visit(this); 14733 }, 14734 walk: function(visitor) { 14735 return this._walk(visitor); // not sure the indirection will be any help 14736 } 14737 }, null); 14738 14739 AST_Node.warn_function = null; 14740 AST_Node.warn = function(txt, props) { 14741 if (AST_Node.warn_function) 14742 AST_Node.warn_function(string_template(txt, props)); 14743 }; 14744 14745 /* -----[ statements ]----- */ 14746 14747 var AST_Statement = DEFNODE("Statement", null, { 14748 $documentation: "Base class of all statements", 14749 }); 14750 14751 var AST_Debugger = DEFNODE("Debugger", null, { 14752 $documentation: "Represents a debugger statement", 14753 }, AST_Statement); 14754 14755 var AST_Directive = DEFNODE("Directive", "value scope quote", { 14756 $documentation: "Represents a directive, like \"use strict\";", 14757 $propdoc: { 14758 value: "[string] The value of this directive as a plain string (it's not an AST_String!)", 14759 scope: "[AST_Scope/S] The scope that this directive affects", 14760 quote: "[string] the original quote character" 14761 }, 14762 }, AST_Statement); 14763 14764 var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { 14765 $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", 14766 $propdoc: { 14767 body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" 14768 }, 14769 _walk: function(visitor) { 14770 return visitor._visit(this, function(){ 14771 this.body._walk(visitor); 14772 }); 14773 } 14774 }, AST_Statement); 14775 14776 function walk_body(node, visitor) { 14777 var body = node.body; 14778 if (body instanceof AST_Statement) { 14779 body._walk(visitor); 14780 } 14781 else for (var i = 0, len = body.length; i < len; i++) { 14782 body[i]._walk(visitor); 14783 } 14784 }; 14785 14786 var AST_Block = DEFNODE("Block", "body", { 14787 $documentation: "A body of statements (usually bracketed)", 14788 $propdoc: { 14789 body: "[AST_Statement*] an array of statements" 14790 }, 14791 _walk: function(visitor) { 14792 return visitor._visit(this, function(){ 14793 walk_body(this, visitor); 14794 }); 14795 } 14796 }, AST_Statement); 14797 14798 var AST_BlockStatement = DEFNODE("BlockStatement", null, { 14799 $documentation: "A block statement", 14800 }, AST_Block); 14801 14802 var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { 14803 $documentation: "The empty statement (empty block or simply a semicolon)", 14804 _walk: function(visitor) { 14805 return visitor._visit(this); 14806 } 14807 }, AST_Statement); 14808 14809 var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { 14810 $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", 14811 $propdoc: { 14812 body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" 14813 }, 14814 _walk: function(visitor) { 14815 return visitor._visit(this, function(){ 14816 this.body._walk(visitor); 14817 }); 14818 } 14819 }, AST_Statement); 14820 14821 var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { 14822 $documentation: "Statement with a label", 14823 $propdoc: { 14824 label: "[AST_Label] a label definition" 14825 }, 14826 _walk: function(visitor) { 14827 return visitor._visit(this, function(){ 14828 this.label._walk(visitor); 14829 this.body._walk(visitor); 14830 }); 14831 }, 14832 clone: function(deep) { 14833 var node = this._clone(deep); 14834 if (deep) { 14835 var label = node.label; 14836 var def = this.label; 14837 node.walk(new TreeWalker(function(node) {
14838 if (node instanceof AST_LoopControl 14839 && node.label && node.label.thedef === def) { 14840 node.label.thedef = label; 14841 label.references.push(node); 14842 } 14843 })); 14844 } 14845 return node; 14846 } 14847 }, AST_StatementWithBody); 14848 14849 var AST_IterationStatement = DEFNODE("IterationStatement", null, { 14850 $documentation: "Internal class. All loops inherit from it." 14851 }, AST_StatementWithBody); 14852 14853 var AST_DWLoop = DEFNODE("DWLoop", "condition", { 14854 $documentation: "Base class for do/while statements", 14855 $propdoc: { 14856 condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" 14857 } 14858 }, AST_IterationStatement); 14859 14860 var AST_Do = DEFNODE("Do", null, { 14861 $documentation: "A `do` statement", 14862 _walk: function(visitor) { 14863 return visitor._visit(this, function(){ 14864 this.body._walk(visitor); 14865 this.condition._walk(visitor); 14866 }); 14867 } 14868 }, AST_DWLoop); 14869 14870 var AST_While = DEFNODE("While", null, { 14871 $documentation: "A `while` statement", 14872 _walk: function(visitor) { 14873 return visitor._visit(this, function(){ 14874 this.condition._walk(visitor); 14875 this.body._walk(visitor); 14876 }); 14877 } 14878 }, AST_DWLoop); 14879 14880 var AST_For = DEFNODE("For", "init condition step", { 14881 $documentation: "A `for` statement", 14882 $propdoc: { 14883 init: "[AST_Node?] the `for` initialization code, or null if empty", 14884 condition: "[AST_Node?] the `for` termination clause, or null if empty", 14885 step: "[AST_Node?] the `for` update clause, or null if empty" 14886 }, 14887 _walk: function(visitor) { 14888 return visitor._visit(this, function(){ 14889 if (this.init) this.init._walk(visitor); 14890 if (this.condition) this.condition._walk(visitor); 14891 if (this.step) this.step._walk(visitor); 14892 this.body._walk(visitor); 14893 }); 14894 } 14895 }, AST_IterationStatement); 14896 14897 var AST_ForIn = DEFNODE("ForIn", "init name object", { 14898 $documentation: "A `for ... in` statement", 14899 $propdoc: { 14900 init: "[AST_Node] the `for/in` initialization code", 14901 name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var", 14902 object: "[AST_Node] the object that we're looping through" 14903 }, 14904 _walk: function(visitor) { 14905 return visitor._visit(this, function(){ 14906 this.init._walk(visitor); 14907 this.object._walk(visitor); 14908 this.body._walk(visitor); 14909 }); 14910 } 14911 }, AST_IterationStatement); 14912 14913 var AST_With = DEFNODE("With", "expression", { 14914 $documentation: "A `with` statement", 14915 $propdoc: { 14916 expression: "[AST_Node] the `with` expression" 14917 }, 14918 _walk: function(visitor) { 14919 return visitor._visit(this, function(){ 14920 this.expression._walk(visitor); 14921 this.body._walk(visitor); 14922 }); 14923 } 14924 }, AST_StatementWithBody); 14925 14926 /* -----[ scope and functions ]----- */ 14927 14928 var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { 14929 $documentation: "Base class for all statements introducing a lexical scope", 14930 $propdoc: { 14931 directives: "[string*/S] an array of directives declared in this scope", 14932 variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope", 14933 functions: "[Object/S] like `variables`, but only lists function declarations", 14934 uses_with: "[boolean/S] tells whether this scope uses the `with` statement", 14935 uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`", 14936 parent_scope: "[AST_Scope?/S] link to the parent scope", 14937 enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", 14938 cname: "[integer/S] current index for mangling variables (used internally by the mangler)", 14939 }, 14940 }, AST_Block); 14941 14942 var AST_Toplevel = DEFNODE("Toplevel", "globals", { 14943 $documentation: "The toplevel scope", 14944 $propdoc: { 14945 globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", 14946 }, 14947 wrap_enclose: function(arg_parameter_pairs) { 14948 var self = this; 14949 var args = []; 14950 var parameters = []; 14951
14952 arg_parameter_pairs.forEach(function(pair) { 14953 var splitAt = pair.lastIndexOf(":"); 14954 14955 args.push(pair.substr(0, splitAt)); 14956 parameters.push(pair.substr(splitAt + 1)); 14957 }); 14958 14959 var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")"; 14960 wrapped_tl = parse(wrapped_tl); 14961 wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ 14962 if (node instanceof AST_Directive && node.value == "$ORIG") { 14963 return MAP.splice(self.body); 14964 } 14965 })); 14966 return wrapped_tl; 14967 }, 14968 wrap_commonjs: function(name, export_all) { 14969 var self = this; 14970 var to_export = []; 14971 if (export_all) { 14972 self.figure_out_scope(); 14973 self.walk(new TreeWalker(function(node){ 14974 if (node instanceof AST_SymbolDeclaration && node.definition().global) { 14975 if (!find_if(function(n){ return n.name == node.name }, to_export)) 14976 to_export.push(node); 14977 } 14978 })); 14979 } 14980 var wrapped_tl = "(function(exports, global){ '$ORIG'; '$EXPORTS'; global['" + name + "'] = exports; }({}, (function(){return this}())))"; 14981 wrapped_tl = parse(wrapped_tl); 14982 wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ 14983 if (node instanceof AST_Directive) { 14984 switch (node.value) { 14985 case "$ORIG": 14986 return MAP.splice(self.body); 14987 case "$EXPORTS": 14988 var body = []; 14989 to_export.forEach(function(sym){ 14990 body.push(new AST_SimpleStatement({ 14991 body: new AST_Assign({ 14992 left: new AST_Sub({ 14993 expression: new AST_SymbolRef({ name: "exports" }), 14994 property: new AST_String({ value: sym.name }), 14995 }), 14996 operator: "=", 14997 right: new AST_SymbolRef(sym), 14998 }), 14999 })); 15000 }); 15001 return MAP.splice(body); 15002 } 15003 } 15004 })); 15005 return wrapped_tl; 15006 } 15007 }, AST_Scope); 15008 15009 var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { 15010 $documentation: "Base class for functions", 15011 $propdoc: { 15012 name: "[AST_SymbolDeclaration?] the name of this function", 15013 argnames: "[AST_SymbolFunarg*] array of function arguments", 15014 uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" 15015 }, 15016 _walk: function(visitor) { 15017 return visitor._visit(this, function(){ 15018 if (this.name) this.name._walk(visitor); 15019 var argnames = this.argnames; 15020 for (var i = 0, len = argnames.length; i < len; i++) { 15021 argnames[i]._walk(visitor); 15022 } 15023 walk_body(this, visitor); 15024 }); 15025 } 15026 }, AST_Scope); 15027 15028 var AST_Accessor = DEFNODE("Accessor", null, { 15029 $documentation: "A setter/getter function. The `name` property is always null." 15030 }, AST_Lambda); 15031 15032 var AST_Function = DEFNODE("Function", null, { 15033 $documentation: "A function expression" 15034 }, AST_Lambda); 15035 15036 var AST_Defun = DEFNODE("Defun", null, { 15037 $documentation: "A function definition" 15038 }, AST_Lambda); 15039 15040 /* -----[ JUMPS ]----- */ 15041 15042 var AST_Jump = DEFNODE("Jump", null, { 15043 $documentation: "Base class for âjumpsâ (for now that's `return`, `throw`, `break` and `continue`)" 15044 }, AST_Statement); 15045 15046 var AST_Exit = DEFNODE("Exit", "value", { 15047 $documentation: "Base class for âexitsâ (`return` and `throw`)", 15048 $propdoc: { 15049 value: "[AST_Node?] the value returned or thrown by this
15049statement; could be null for AST_Return" 15050 }, 15051 _walk: function(visitor) { 15052 return visitor._visit(this, this.value && function(){ 15053 this.value._walk(visitor); 15054 }); 15055 } 15056 }, AST_Jump); 15057 15058 var AST_Return = DEFNODE("Return", null, { 15059 $documentation: "A `return` statement" 15060 }, AST_Exit); 15061 15062 var AST_Throw = DEFNODE("Throw", null, { 15063 $documentation: "A `throw` statement" 15064 }, AST_Exit); 15065 15066 var AST_LoopControl = DEFNODE("LoopControl", "label", { 15067 $documentation: "Base class for loop control statements (`break` and `continue`)", 15068 $propdoc: { 15069 label: "[AST_LabelRef?] the label, or null if none", 15070 }, 15071 _walk: function(visitor) { 15072 return visitor._visit(this, this.label && function(){ 15073 this.label._walk(visitor); 15074 }); 15075 } 15076 }, AST_Jump); 15077 15078 var AST_Break = DEFNODE("Break", null, { 15079 $documentation: "A `break` statement" 15080 }, AST_LoopControl); 15081 15082 var AST_Continue = DEFNODE("Continue", null, { 15083 $documentation: "A `continue` statement" 15084 }, AST_LoopControl); 15085 15086 /* -----[ IF ]----- */ 15087 15088 var AST_If = DEFNODE("If", "condition alternative", { 15089 $documentation: "A `if` statement", 15090 $propdoc: { 15091 condition: "[AST_Node] the `if` condition", 15092 alternative: "[AST_Statement?] the `else` part, or null if not present" 15093 }, 15094 _walk: function(visitor) { 15095 return visitor._visit(this, function(){ 15096 this.condition._walk(visitor); 15097 this.body._walk(visitor); 15098 if (this.alternative) this.alternative._walk(visitor); 15099 }); 15100 } 15101 }, AST_StatementWithBody); 15102 15103 /* -----[ SWITCH ]----- */ 15104 15105 var AST_Switch = DEFNODE("Switch", "expression", { 15106 $documentation: "A `switch` statement", 15107 $propdoc: { 15108 expression: "[AST_Node] the `switch` âdiscriminantâ" 15109 }, 15110 _walk: function(visitor) { 15111 return visitor._visit(this, function(){ 15112 this.expression._walk(visitor); 15113 walk_body(this, visitor); 15114 }); 15115 } 15116 }, AST_Block); 15117 15118 var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { 15119 $documentation: "Base class for `switch` branches", 15120 }, AST_Block); 15121 15122 var AST_Default = DEFNODE("Default", null, { 15123 $documentation: "A `default` switch branch", 15124 }, AST_SwitchBranch); 15125 15126 var AST_Case = DEFNODE("Case", "expression", { 15127 $documentation: "A `case` switch branch", 15128 $propdoc: { 15129 expression: "[AST_Node] the `case` expression" 15130 }, 15131 _walk: function(visitor) { 15132 return visitor._visit(this, function(){ 15133 this.expression._walk(visitor); 15134 walk_body(this, visitor); 15135 }); 15136 } 15137 }, AST_SwitchBranch); 15138 15139 /* -----[ EXCEPTIONS ]----- */ 15140 15141 var AST_Try = DEFNODE("Try", "bcatch bfinally", { 15142 $documentation: "A `try` statement", 15143 $propdoc: { 15144 bcatch: "[AST_Catch?] the catch block, or null if not present", 15145 bfinally: "[AST_Finally?] the finally block, or null if not present" 15146 }, 15147 _walk: function(visitor) { 15148 return visitor._visit(this, function(){ 15149 walk_body(this, visitor); 15150 if (this.bcatch) this.bcatch._walk(visitor); 15151 if (this.bfinally) this.bfinally._walk(visitor); 15152 }); 15153 } 15154 }, AST_Block); 15155 15156 var AST_Catch = DEFNODE("Catch", "argname", { 15157 $documentation: "A `catch` node; only makes sense as part of a `try` statement", 15158 $propdoc: { 15159 argname: "[AST_SymbolCatch] symbol for the exception" 15160 }, 15161 _walk: function(visitor) { 15162 return visitor._visit(this, function(){ 15163 this.argname._walk(visitor); 15164 walk_body(this, visitor); 15165 }); 15166 } 15167 }, AST_Block); 15168 15169 var AST_Finally = DEFNODE("Finally", null, { 15170 $documentation: "A `finally` node; only makes sense as part of a `try` statement" 15171 }, AST_Block); 15172 15173 /* -----[ VAR/CONST ]----- */ 15174 15175 var AST_Definitions = DEFNODE("Definitions", "definitions", { 15176 $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", 15177 $propdoc: { 15178 definitions: "[AST_VarDef*] array of variable definitions" 15179 }, 15180 _walk: function(visitor) { 15181 return visitor._visit(this, function(){ 15182 var definitions = this.definitions; 15183 for (var i = 0, len = definitions.length; i < len; i++) { 15184 definitions[i]._walk(visitor); 15185 } 15186 }); 15187 } 15188 }, AST_Statement); 15189 15190 var AST_Var = DEFNODE("Var", null, { 15191 $documentation: "A `var` statement" 15192 }, AST_Definitions); 15193 15194 var AST_Const = DEFNODE("Const", null, { 15195 $documentation: "A `const` statement" 15196 }, AST_Definitions); 15197 15198 var AST_VarDef = DEFNODE("VarDef", "name value", { 15199 $documentation: "A variable declaration; only appears in a AST_Definitions node", 15200 $propdoc: { 15201 name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", 15202 value: "[AST_Node?] initializer, or null of there's no initializer" 15203 }, 15204 _walk: function(visitor) { 15205 return visitor._visit(this, function(){ 15206 this.name._walk(visitor); 15207 if (this.value) this.value._walk(visitor); 15208 }); 15209 } 15210 }); 15211 15212 /* -----[ OTHER ]----- */ 15213 15214 var AST_Call = DEFNODE("Call", "expression args", { 15215 $documentation: "A function call expression", 15216 $propdoc: { 15217 expression: "[AST_Node] expression to invoke as function", 15218 args: "[AST_Node*] array of arguments" 15219 }, 15220 _walk: function(visitor) { 15221 return visitor._visit(this, function(){ 15222 this.expression._walk(visitor); 15223 var args = this.args; 15224 for (var i = 0, len = args.length; i < len; i++) { 15225 args[i]._walk(visitor); 15226 } 15227 }); 15228 } 15229 }); 15230 15231 var AST_New = DEFNODE("New", null, { 15232 $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" 15233 }, AST_Call); 15234 15235 var AST_Seq = DEFNODE("Seq", "car cdr", { 15236 $documentation: "A sequence expression (two comma-separated expressions)", 15237 $propdoc: { 15238 car: "[AST_Node] first element in sequence", 15239 cdr: "[AST_Node] second element in sequence" 15240 }, 15241 $cons: function(x, y) { 15242 var seq = new AST_Seq(x); 15243 seq.car = x; 15244 seq.cdr = y; 15245 return seq; 15246 }, 15247 $from_array: function(array) { 15248 if (array.length == 0) return null; 15249 if (array.length == 1) return array[0].clone(); 15250 var list = null; 15251 for (var i = array.length; --i >= 0;) { 15252 list = AST_Seq.cons(array[i], list); 15253 } 15254 var p = list; 15255 while (p) { 15256 if (p.cdr && !p.cdr.cdr) {
15257 p.cdr = p.cdr.car; 15258 break; 15259 } 15260 p = p.cdr; 15261 } 15262 return list; 15263 }, 15264 to_array: function() { 15265 var p = this, a = []; 15266 while (p) { 15267 a.push(p.car); 15268 if (p.cdr && !(p.cdr instanceof AST_Seq)) { 15269 a.push(p.cdr); 15270 break; 15271 } 15272 p = p.cdr; 15273 } 15274 return a; 15275 }, 15276 add: function(node) { 15277 var p = this; 15278 while (p) { 15279 if (!(p.cdr instanceof AST_Seq)) { 15280 var cell = AST_Seq.cons(p.cdr, node); 15281 return p.cdr = cell; 15282 } 15283 p = p.cdr; 15284 } 15285 }, 15286 len: function() { 15287 if (this.cdr instanceof AST_Seq) { 15288 return this.cdr.len() + 1; 15289 } else { 15290 return 2; 15291 } 15292 }, 15293 _walk: function(visitor) { 15294 return visitor._visit(this, function(){ 15295 this.car._walk(visitor); 15296 if (this.cdr) this.cdr._walk(visitor); 15297 }); 15298 } 15299 }); 15300 15301 var AST_PropAccess = DEFNODE("PropAccess", "expression property", { 15302 $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", 15303 $propdoc: { 15304 expression: "[AST_Node] the âcontainerâ expression", 15305 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" 15306 } 15307 }); 15308 15309 var AST_Dot = DEFNODE("Dot", null, { 15310 $documentation: "A dotted property access expression", 15311 _walk: function(visitor) { 15312 return visitor._visit(this, function(){ 15313 this.expression._walk(visitor); 15314 }); 15315 } 15316 }, AST_PropAccess); 15317 15318 var AST_Sub = DEFNODE("Sub", null, { 15319 $documentation: "Index-style property access, i.e. `a[\"foo\"]`", 15320 _walk: function(visitor) { 15321 return visitor._visit(this, function(){ 15322 this.expression._walk(visitor); 15323 this.property._walk(visitor); 15324 }); 15325 } 15326 }, AST_PropAccess); 15327 15328 var AST_Unary = DEFNODE("Unary", "operator expression", { 15329 $documentation: "Base class for unary expressions", 15330 $propdoc: { 15331 operator: "[string] the operator", 15332 expression: "[AST_Node] expression that this unary operator applies to" 15333 }, 15334 _walk: function(visitor) { 15335 return visitor._visit(this, function(){ 15336 this.expression._walk(visitor); 15337 }); 15338 } 15339 }); 15340 15341 var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { 15342 $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" 15343 }, AST_Unary); 15344 15345 var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { 15346 $documentation: "Unary postfix expression, i.e. `i++`" 15347 }, AST_Unary); 15348 15349 var AST_Binary = DEFNODE("Binary", "left operator right", { 15350 $documentation: "Binary expression, i.e. `a + b`", 15351 $propdoc: { 15352 left: "[AST_Node] left-hand side expression", 15353 operator: "[string] the operator", 15354 right: "[AST_Node] right-hand side expression" 15355 }, 15356 _walk: function(visitor) { 15357 return visitor._visit(this, function(){ 15358 this.left._walk(visitor); 15359 this.right._walk(visitor); 15360 }); 15361 } 15362 }); 15363 15364 var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { 15365 $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", 15366 $propdoc: { 15367 condition: "[AST_Node]", 15368 consequent: "[AST_Node]", 15369 alternative: "[AST_Node]" 15370 }, 15371 _walk: function(visitor) { 15372 return visitor._visit(this, function(){ 15373 this.condition._walk(visitor); 15374 this.consequent._walk(visitor); 15375 this.alternative._walk(visitor); 15376 }); 15377 } 15378 }); 15379 15380 var AST_Assign = DEFNODE("Assign", null, { 15381 $documentation: "An assignment expression â `a = b + 5`", 15382 }, AST_Binary); 15383 15384 /* -----[ LITERALS ]----- */ 15385 15386 var AST_Array = DEFNODE("Array", "elements", { 15387 $documentation: "An array literal", 15388 $propdoc: { 15389 elements: "[AST_Node*] array of elements" 15390 }, 15391 _walk: function(visitor) { 15392 return visitor._visit(this, function(){ 15393 var elements = this.elements; 15394 for (var i = 0, len = elements.length; i < len; i++) { 15395 elements[i]._walk(visitor); 15396 } 15397 }); 15398 } 15399 }); 15400 15401 var AST_Object = DEFNODE("Object", "properties", { 15402 $documentation: "An object literal", 15403 $propdoc: { 15404 properties: "[AST_ObjectProperty*] array of properties" 15405 }, 15406 _walk: function(visitor) { 15407 return visitor._visit(this, function(){ 15408 var properties = this.properties; 15409 for (var i = 0, len = properties.length; i < len; i++) { 15410 properties[i]._walk(visitor); 15411 } 15412 }); 15413 } 15414 }); 15415 15416 var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { 15417 $documentation: "Base class for literal object properties", 15418 $propdoc: { 15419 key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an AST_SymbolAccessor.", 15420 value: "[AST_Node] property value. For setters and getters this is an AST_Acce
15420ssor." 15421 }, 15422 _walk: function(visitor) { 15423 return visitor._visit(this, function(){ 15424 this.value._walk(visitor); 15425 }); 15426 } 15427 }); 15428 15429 var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", { 15430 $documentation: "A key: value object property", 15431 $propdoc: { 15432 quote: "[string] the original quote character" 15433 } 15434 }, AST_ObjectProperty); 15435 15436 var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { 15437 $documentation: "An object setter property", 15438 }, AST_ObjectProperty); 15439 15440 var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { 15441 $documentation: "An object getter property", 15442 }, AST_ObjectProperty); 15443 15444 var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { 15445 $propdoc: { 15446 name: "[string] name of this symbol", 15447 scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", 15448 thedef: "[SymbolDef/S] the definition of this symbol" 15449 }, 15450 $documentation: "Base class for all symbols", 15451 }); 15452 15453 var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { 15454 $documentation: "The name of a property accessor (setter/getter function)" 15455 }, AST_Symbol); 15456 15457 var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { 15458 $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", 15459 }, AST_Symbol); 15460 15461 var AST_SymbolVar = DEFNODE("SymbolVar", null, { 15462 $documentation: "Symbol defining a variable", 15463 }, AST_SymbolDeclaration); 15464 15465 var AST_SymbolConst = DEFNODE("SymbolConst", null, { 15466 $documentation: "A constant declaration" 15467 }, AST_SymbolDeclaration); 15468 15469 var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { 15470 $documentation: "Symbol naming a function argument", 15471 }, AST_SymbolVar); 15472 15473 var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { 15474 $documentation: "Symbol defining a function", 15475 }, AST_SymbolDeclaration); 15476 15477 var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { 15478 $documentation: "Symbol naming a function expression", 15479 }, AST_SymbolDeclaration); 15480 15481 var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { 15482 $documentation: "Symbol naming the exception in catch", 15483 }, AST_SymbolDeclaration); 15484 15485 var AST_Label = DEFNODE("Label", "references", { 15486 $documentation: "Symbol naming a label (declaration)", 15487 $propdoc: { 15488 references: "[AST_LoopControl*] a list of nodes referring to this label" 15489 }, 15490 initialize: function() { 15491 this.references = []; 15492 this.thedef = this; 15493 } 15494 }, AST_Symbol); 15495 15496 var AST_SymbolRef = DEFNODE("SymbolRef", null, { 15497 $documentation: "Reference to some symbol (not definition/declaration)", 15498 }, AST_Symbol); 15499 15500 var AST_LabelRef = DEFNODE("LabelRef", null, { 15501 $documentation: "Reference to a label symbol", 15502 }, AST_Symbol); 15503 15504 var AST_This = DEFNODE("This", null, { 15505 $documentation: "The `this` symbol", 15506 }, AST_Symbol); 15507 15508 var AST_Constant = DEFNODE("Constant", null, { 15509 $documentation: "Base class for all constants", 15510 getValue: function() { 15511 return this.value; 15512 } 15513 }); 15514 15515 var AST_String = DEFNODE("String", "value quote", { 15516 $documentation: "A string literal", 15517 $propdoc: { 15518 value: "[string] the contents of this string", 15519 quote: "[string] the original quote character" 15520 } 15521 }, AST_Constant); 15522 15523 var AST_Number = DEFNODE("Number", "value literal", { 15524 $documentation: "A number literal", 15525 $propdoc: { 15526 value: "[number] the numeric value",
15527 literal: "[string] numeric value as string (optional)" 15528 } 15529 }, AST_Constant); 15530 15531 var AST_RegExp = DEFNODE("RegExp", "value", { 15532 $documentation: "A regexp literal", 15533 $propdoc: { 15534 value: "[RegExp] the actual regexp" 15535 } 15536 }, AST_Constant); 15537 15538 var AST_Atom = DEFNODE("Atom", null, { 15539 $documentation: "Base class for atoms", 15540 }, AST_Constant); 15541 15542 var AST_Null = DEFNODE("Null", null, { 15543 $documentation: "The `null` atom", 15544 value: null 15545 }, AST_Atom); 15546 15547 var AST_NaN = DEFNODE("NaN", null, { 15548 $documentation: "The impossible value", 15549 value: 0/0 15550 }, AST_Atom); 15551 15552 var AST_Undefined = DEFNODE("Undefined", null, { 15553 $documentation: "The `undefined` value", 15554 value: (function(){}()) 15555 }, AST_Atom); 15556 15557 var AST_Hole = DEFNODE("Hole", null, { 15558 $documentation: "A hole in an array", 15559 value: (function(){}()) 15560 }, AST_Atom); 15561 15562 var AST_Infinity = DEFNODE("Infinity", null, { 15563 $documentation: "The `Infinity` value", 15564 value: 1/0 15565 }, AST_Atom); 15566 15567 var AST_Boolean = DEFNODE("Boolean", null, { 15568 $documentation: "Base class for booleans", 15569 }, AST_Atom); 15570 15571 var AST_False = DEFNODE("False", null, { 15572 $documentation: "The `false` atom", 15573 value: false 15574 }, AST_Boolean); 15575 15576 var AST_True = DEFNODE("True", null, { 15577 $documentation: "The `true` atom", 15578 value: true 15579 }, AST_Boolean); 15580 15581 /* -----[ TreeWalker ]----- */ 15582 15583 function TreeWalker(callback) { 15584 this.visit = callback; 15585 this.stack = []; 15586 this.directives = Object.create(null); 15587 }; 15588 TreeWalker.prototype = { 15589 _visit: function(node, descend) { 15590 this.push(node); 15591 var ret = this.visit(node, descend ? function(){ 15592 descend.call(node); 15593 } : noop); 15594 if (!ret && descend) { 15595 descend.call(node); 15596 } 15597 this.pop(node); 15598 return ret; 15599 }, 15600 parent: function(n) { 15601 return this.stack[this.stack.length - 2 - (n || 0)]; 15602 }, 15603 push: function (node) { 15604 if (node instanceof AST_Lambda) { 15605 this.directives = Object.create(this.directives); 15606 } else if (node instanceof AST_Directive && !this.directives[node.value]) { 15607 this.directives[node.value] = node; 15608 } 15609 this.stack.push(node); 15610 }, 15611 pop: function(node) { 15612 this.stack.pop(); 15613 if (node instanceof AST_Lambda) { 15614 this.directives = Object.getPrototypeOf(this.directives); 15615 } 15616 }, 15617 self: function() { 15618 return this.stack[this.stack.length - 1]; 15619 }, 15620 find_parent: function(type) { 15621 var stack = this.stack; 15622 for (var i = stack.length; --i >= 0;) { 15623 var x = stack[i]; 15624 if (x instanceof type) return x; 15625 } 15626 }, 15627 has_directive: function(type) { 15628 var dir = this.directives[type]; 15629 if (dir) return dir; 15630 var node = this.stack[this.stack.length - 1]; 15631 if (node instanceof AST_Scope) { 15632 for (var i = 0; i < node.body.length; ++i) { 15633 var st = node.body[i]; 15634 if (!(st instanceof AST_Directive)) break; 15635 if (st.value == type) return st; 15636 } 15637 } 15638 }, 15639 in_boolean_context: function() { 15640 var stack = this.stack; 15641 var i = stack.length, self = stack[--i]; 15642 while (i > 0) { 15643 var p = stack[--i]; 15644 if ((p instanceof AST_If && p.condition === self) || 15645 (p instanceof AST_Conditional && p.condition === self) || 15646 (p instanceof AST_DWLoop && p.condition === self) || 15647 (p instanceof AST_For && p.condition === self) || 15648 (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self)) 15649 { 15650 return true; 15651 } 15652 if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) 15653 return false;
vendor: 5,721 bytes, lines 15654-15794
15654 self = p; 15655 } 15656 }, 15657 loopcontrol_target: function(node) { 15658 var stack = this.stack; 15659 if (node.label) for (var i = stack.length; --i >= 0;) { 15660 var x = stack[i]; 15661 if (x instanceof AST_LabeledStatement && x.label.name == node.label.name) 15662 return x.body; 15663 } else for (var i = stack.length; --i >= 0;) { 15664 var x = stack[i]; 15665 if (x instanceof AST_IterationStatement 15666 || node instanceof AST_Break && x instanceof AST_Switch) 15667 return x; 15668 } 15669 } 15670 }; 15671 15672 /*********************************************************************** 15673 15674 A JavaScript tokenizer / parser / beautifier / compressor. 15675 https://github.com/mishoo/UglifyJS2 15676 15677 -------------------------------- (C) --------------------------------- 15678 15679 Author: Mihai Bazon 15680 <[email protected]> 15681 http://mihai.bazon.net/blog 15682 15683 Distributed under the BSD license: 15684 15685 Copyright 2012 (c) Mihai Bazon <[email protected]> 15686 Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/). 15687 15688 Redistribution and use in source and binary forms, with or without 15689 modification, are permitted provided that the following conditions 15690 are met: 15691 15692 * Redistributions of source code must retain the above 15693 copyright notice, this list of conditions and the following 15694 disclaimer. 15695 15696 * Redistributions in binary form must reproduce the above 15697 copyright notice, this list of conditions and the following 15698 disclaimer in the documentation and/or other materials 15699 provided with the distribution. 15700 15701 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 15702 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15703 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15704 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 15705 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 15706 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 15707 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 15708 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 15709 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 15710 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15711 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 15712 SUCH DAMAGE. 15713 15714 ***********************************************************************/ 15715 15716 "use strict"; 15717 15718 var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; 15719 var KEYWORDS_ATOM = 'false null true'; 15720 var 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' 15721 + " " + KEYWORDS_ATOM + " " + KEYWORDS; 15722 var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case'; 15723 15724 KEYWORDS = makePredicate(KEYWORDS); 15725 RESERVED_WORDS = makePredicate(RESERVED_WORDS); 15726 KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); 15727 KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); 15728 15729 var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); 15730 15731 var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; 15732 var RE_OCT_NUMBER = /^0[0-7]+$/; 15733 15734 var OPERATORS = makePredicate([ 15735 "in", 15736 "instanceof", 15737 "typeof", 15738 "new", 15739 "void", 15740 "delete", 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 "%=", 15771 ">>=", 15772 "<<=", 15773 ">>>=", 15774 "|=", 15775 "^=", 15776 "&=", 15777 "&&", 15778 "||" 15779 ]); 15780 15781 var 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")); 15782 15783 var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029")); 15784 15785 var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:")); 15786 15787 var PUNC_CHARS = makePredicate(characters("[]{}(),;:")); 15788 15789 var REGEXP_MODIFIERS = makePredicate(characters("gmsiy")); 15790 15791 /* -----[ Tokenizer ]----- */ 15792 15793// regexps adapted from http://xregexp.com/plugins/#unicode 15794 var UNICODE = {
15795 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\\u
157950AE1\\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]"), 15796 digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u
157960BEF\\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]"), 15797 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]"), 15798 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]"), 15799 connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") 15800 }; 15801 15802 function is_letter(code) { 15803 return (code >= 97 && code <= 122) 15804 || (code >= 65 && code <= 90) 15805 || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); 15806 }; 15807 15808 function is_digit(code) { 15809 return code >= 48 && code <= 57; 15810 }; 15811 15812 function is_alphanumeric_char(code) { 15813 return is_digit(code) || is_letter(code); 15814 }; 15815 15816 function is_unicode_digit(code) { 15817 return UNICODE.digit.test(String.fromCharCode(code)); 15818 } 15819 15820 function is_unicode_combining_mark(ch) { 15821 return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); 15822 }; 15823 15824 function is_unicode_connector_punctuation(ch) { 15825 return UNICODE.connector_punctuation.test(ch); 15826 }; 15827 15828 function is_identifier(name) { 15829 return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); 15830 }; 15831 15832 function is_identifier_start(code) { 15833 return code == 36 || code == 95 || is_letter(code); 15834 }; 15835 15836 function is_identifier_char(ch) {
15837 var code = ch.charCodeAt(0); 15838 return is_identifier_start(code) 15839 || is_digit(code) 15840 || code == 8204 // \u200c: zero-width non-joiner <ZWNJ> 15841 || code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c) 15842 || is_unicode_combining_mark(ch) 15843 || is_unicode_connector_punctuation(ch) 15844 || is_unicode_digit(code) 15845 ; 15846 }; 15847 15848 function is_identifier_string(str){ 15849 return /^[a-z_$][a-z0-9_$]*$/i.test(str); 15850 }; 15851 15852 function parse_js_number(num) { 15853 if (RE_HEX_NUMBER.test(num)) { 15854 return parseInt(num.substr(2), 16); 15855 } else if (RE_OCT_NUMBER.test(num)) { 15856 return parseInt(num.substr(1), 8); 15857 } else { 15858 var val = parseFloat(num); 15859 if (val == num) return val; 15860 } 15861 }; 15862 15863 function JS_Parse_Error(message, filename, line, col, pos) { 15864 this.message = message; 15865 this.filename = filename; 15866 this.line = line; 15867 this.col = col; 15868 this.pos = pos; 15869 }; 15870 JS_Parse_Error.prototype = Object.create(Error.prototype); 15871 JS_Parse_Error.prototype.constructor = JS_Parse_Error; 15872 JS_Parse_Error.prototype.name = "SyntaxError"; 15873 configure_error_stack(JS_Parse_Error); 15874 15875 function js_error(message, filename, line, col, pos) { 15876 throw new JS_Parse_Error(message, filename, line, col, pos); 15877 }; 15878 15879 function is_token(token, type, val) { 15880 return token.type == type && (val == null || token.value == val); 15881 }; 15882 15883 var EX_EOF = {}; 15884 15885 function tokenizer($TEXT, filename, html5_comments, shebang) { 15886 15887 var S = { 15888 text : $TEXT, 15889 filename : filename, 15890 pos : 0, 15891 tokpos : 0, 15892 line : 1, 15893 tokline : 0, 15894 col : 0, 15895 tokcol : 0, 15896 newline_before : false, 15897 regex_allowed : false, 15898 comments_before : [], 15899 directives : {}, 15900 directive_stack : [] 15901 }; 15902 15903 function peek() { return S.text.charAt(S.pos); }; 15904 15905 function next(signal_eof, in_string) { 15906 var ch = S.text.charAt(S.pos++); 15907 if (signal_eof && !ch) 15908 throw EX_EOF; 15909 if (NEWLINE_CHARS(ch)) { 15910 S.newline_before = S.newline_before || !in_string; 15911 ++S.line; 15912 S.col = 0; 15913 if (!in_string && ch == "\r" && peek() == "\n") { 15914 // treat a \r\n sequence as a single \n 15915 ++S.pos; 15916 ch = "\n"; 15917 } 15918 } else { 15919 ++S.col; 15920 } 15921 return ch; 15922 }; 15923 15924 function forward(i) { 15925 while (i-- > 0) next(); 15926 }; 15927 15928 function looking_at(str) { 15929 return S.text.substr(S.pos, str.length) == str; 15930 }; 15931 15932 function find_eol() { 15933 var text = S.text; 15934 for (var i = S.pos, n = S.text.length; i < n; ++i) { 15935 var ch = text[i]; 15936 if (NEWLINE_CHARS(ch)) 15937 return i; 15938 } 15939 return -1; 15940 }; 15941 15942 function find(what, signal_eof) { 15943 var pos = S.text.indexOf(what, S.pos); 15944 if (signal_eof && pos == -1) throw EX_EOF; 15945 return pos; 15946 }; 15947 15948 function start_token() { 15949 S.tokline = S.line; 15950 S.tokcol = S.col; 15951 S.tokpos = S.pos; 15952 }; 15953 15954 var prev_was_dot = false;
15955 function token(type, value, is_comment) { 15956 S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) || 15957 (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) || 15958 (type == "punc" && PUNC_BEFORE_EXPRESSION(value))); 15959 if (type == "punc" && value == ".") { 15960 prev_was_dot = true; 15961 } else if (!is_comment) { 15962 prev_was_dot = false; 15963 } 15964 var ret = { 15965 type : type, 15966 value : value, 15967 line : S.tokline, 15968 col : S.tokcol, 15969 pos : S.tokpos, 15970 endline : S.line, 15971 endcol : S.col, 15972 endpos : S.pos, 15973 nlb : S.newline_before, 15974 file : filename 15975 }; 15976 if (/^(?:num|string|regexp)$/i.test(type)) { 15977 ret.raw = $TEXT.substring(ret.pos, ret.endpos); 15978 } 15979 if (!is_comment) { 15980 ret.comments_before = S.comments_before; 15981 S.comments_before = []; 15982 // make note of any newlines in the comments that came before 15983 for (var i = 0, len = ret.comments_before.length; i < len; i++) { 15984 ret.nlb = ret.nlb || ret.comments_before[i].nlb; 15985 } 15986 } 15987 S.newline_before = false; 15988 return new AST_Token(ret); 15989 }; 15990 15991 function skip_whitespace() { 15992 while (WHITESPACE_CHARS(peek())) 15993 next(); 15994 }; 15995 15996 function read_while(pred) { 15997 var ret = "", ch, i = 0; 15998 while ((ch = peek()) && pred(ch, i++)) 15999 ret += next(); 16000 return ret; 16001 }; 16002 16003 function parse_error(err) { 16004 js_error(err, filename, S.tokline, S.tokcol, S.tokpos); 16005 }; 16006 16007 function read_num(prefix) { 16008 var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; 16009 var num = read_while(function(ch, i){ 16010 var code = ch.charCodeAt(0); 16011 switch (code) { 16012 case 120: case 88: // xX 16013 return has_x ? false : (has_x = true); 16014 case 101: case 69: // eE 16015 return has_x ? true : has_e ? false : (has_e = after_e = true); 16016 case 45: // - 16017 return after_e || (i == 0 && !prefix); 16018 case 43: // + 16019 return after_e; 16020 case (after_e = false, 46): // . 16021 return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false; 16022 } 16023 return is_alphanumeric_char(code); 16024 }); 16025 if (prefix) num = prefix + num; 16026 if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) { 16027 parse_error("Legacy octal literals are not allowed in strict mode"); 16028 } 16029 var valid = parse_js_number(num); 16030 if (!isNaN(valid)) { 16031 return token("num", valid); 16032 } else { 16033 parse_error("Invalid syntax: " + num); 16034 } 16035 }; 16036 16037 function read_escaped_char(in_string) { 16038 var ch = next(true, in_string); 16039 switch (ch.charCodeAt(0)) { 16040 case 110 : return "\n"; 16041 case 114 : return "\r"; 16042 case 116 : return "\t"; 16043 case 98 : return "\b"; 16044 case 118 : return "\u000b"; // \v 16045 case 102 : return "\f"; 16046 case 120 : return String.fromCharCode(hex_bytes(2)); // \x 16047 case 117 : return String.fromCharCode(hex_bytes(4)); // \u 16048 case 10 : return ""; // newline 16049 case 13 : // \r 16050 if (peek() == "\n") { // DOS newline 16051 next(true, in_string); 16052 return ""; 16053 } 16054 } 16055 if (ch >= "0" && ch <= "7") 16056 return read_octal_escape_sequence(ch); 16057 return ch; 16058 }; 16059 16060 function read_octal_escape_sequence(ch) { 16061 // Read 16062 var p = peek(); 16063 if (p >= "0" && p <= "7") { 16064 ch += next(true); 16065 if (ch[0] <= "3" && (p = peek()) >= "0" && p <= "7") 16066 ch += next(true); 16067 } 16068 16069 // Parse 16070 if (ch === "0") return "\0"; 16071 if (ch.length > 0 && next_token.has_directive("use strict")) 16072 parse_error("Legacy octal escape sequences are not allowed in strict mode"); 16073 return String.fromCharCode(parseInt(ch, 8)); 16074 } 16075 16076 function hex_bytes(n) { 16077 var num = 0; 16078 for (; n > 0; --n) { 16079 var digit = parseInt(next(true), 16); 16080 if (isNaN(digit)) 16081 parse_error("Invalid hex-character pattern in string"); 16082 num = (num << 4) | digit; 16083 } 16084 return num; 16085 }; 16086 16087 var read_string = with_eof_error("Unterminated string constant", function(quote_char){ 16088 var quote = next(), ret = ""; 16089 for (;;) { 16090 var ch = next(true, true); 16091 if (ch == "\\") ch = read_escaped_char(true); 16092 else if (NEWLINE_CHARS(ch)) parse_error("Unterminated string constant"); 16093 else if (ch == quote) break; 16094 ret += ch; 16095 } 16096 var tok = token("string", ret); 16097 tok.quote = quote_char; 16098 return tok; 16099 }); 16100 16101 function skip_line_comment(type) { 16102 var regex_allowed = S.regex_allowed; 16103 var i = find_eol(), ret; 16104 if (i == -1) { 16105 ret = S.text.substr(S.pos); 16106 S.pos = S.text.length; 16107 } else { 16108 ret = S.text.substring(S.pos, i); 16109 S.pos = i; 16110 } 16111 S.col = S.tokcol + (S.pos - S.tokpos); 16112 S.comments_before.push(token(type, ret, true)); 16113 S.regex_allowed = regex_allowed; 16114 return next_token; 16115 }; 16116 16117 var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ 16118 var regex_allowed = S.regex_allowed; 16119 var i = find("*/", true); 16120 var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n'); 16121 // update stream position 16122 forward(text.length /* doesn't count \r\n as 2 char while S.pos - i does */ + 2); 16123 S.comments_before.push(token("comment2", text, true)); 16124 S.regex_allowed = regex_allowed; 16125 return next_token; 16126 }); 16127 16128 function read_name() { 16129 var backslash = false, name = "", ch, escaped = false, hex; 16130 while ((ch = peek()) != null) { 16131 if (!backslash) { 16132 if (ch == "\\") escaped = backslash = true, next(); 16133 else if (is_identifier_char(ch)) name += next(); 16134 else break; 16135 } 16136 else { 16137 if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); 16138 ch = read_escaped_char(); 16139 if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCo
16139deAt(0) + " is not valid in identifier"); 16140 name += ch; 16141 backslash = false; 16142 } 16143 } 16144 if (KEYWORDS(name) && escaped) { 16145 hex = name.charCodeAt(0).toString(16).toUpperCase(); 16146 name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); 16147 } 16148 return name; 16149 }; 16150 16151 var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){ 16152 var prev_backslash = false, ch, in_class = false; 16153 while ((ch = next(true))) if (NEWLINE_CHARS(ch)) { 16154 parse_error("Unexpected line terminator"); 16155 } else if (prev_backslash) { 16156 regexp += "\\" + ch; 16157 prev_backslash = false; 16158 } else if (ch == "[") { 16159 in_class = true; 16160 regexp += ch; 16161 } else if (ch == "]" && in_class) { 16162 in_class = false; 16163 regexp += ch; 16164 } else if (ch == "/" && !in_class) { 16165 break; 16166 } else if (ch == "\\") { 16167 prev_backslash = true; 16168 } else { 16169 regexp += ch; 16170 } 16171 var mods = read_name(); 16172 try { 16173 return token("regexp", new RegExp(regexp, mods)); 16174 } catch(e) { 16175 parse_error(e.message); 16176 } 16177 }); 16178 16179 function read_operator(prefix) { 16180 function grow(op) { 16181 if (!peek()) return op; 16182 var bigger = op + peek(); 16183 if (OPERATORS(bigger)) { 16184 next(); 16185 return grow(bigger); 16186 } else { 16187 return op; 16188 } 16189 }; 16190 return token("operator", grow(prefix || next())); 16191 }; 16192 16193 function handle_slash() { 16194 next(); 16195 switch (peek()) { 16196 case "/": 16197 next(); 16198 return skip_line_comment("comment1"); 16199 case "*": 16200 next(); 16201 return skip_multiline_comment(); 16202 } 16203 return S.regex_allowed ? read_regexp("") : read_operator("/"); 16204 }; 16205 16206 function handle_dot() { 16207 next(); 16208 return is_digit(peek().charCodeAt(0)) 16209 ? read_num(".") 16210 : token("punc", "."); 16211 }; 16212 16213 function read_word() { 16214 var word = read_name(); 16215 if (prev_was_dot) return token("name", word); 16216 return KEYWORDS_ATOM(word) ? token("atom", word) 16217 : !KEYWORDS(word) ? token("name", word) 16218 : OPERATORS(word) ? token("operator", word) 16219 : token("keyword", word); 16220 }; 16221 16222 function with_eof_error(eof_error, cont) { 16223 return function(x) { 16224 try { 16225 return cont(x); 16226 } catch(ex) { 16227 if (ex === EX_EOF) parse_error(eof_error); 16228 else throw ex; 16229 } 16230 }; 16231 }; 16232 16233 function next_token(force_regexp) { 16234 if (force_regexp != null) 16235 return read_regexp(force_regexp); 16236 if (shebang && S.pos == 0 && looking_at("#!")) { 16237 start_token(); 16238 forward(2); 16239 skip_line_comment("comment5"); 16240 } 16241 for (;;) { 16242 skip_whitespace(); 16243 start_token(); 16244 if (html5_comments) { 16245 if (looking_at("<!--")) { 16246 forward(4); 16247 skip_line_comment("comment3"); 16248 continue; 16249 } 16250 if (looking_at("-->") && S.newline_before) { 16251 forward(3); 16252 skip_line_comment("comment4"); 16253 continue; 16254 } 16255 } 16256 var ch = peek(); 16257 if (!ch) return token("eof");
16258 var code = ch.charCodeAt(0); 16259 switch (code) { 16260 case 34: case 39: return read_string(ch); 16261 case 46: return handle_dot(); 16262 case 47: { 16263 var tok = handle_slash(); 16264 if (tok === next_token) continue; 16265 return tok; 16266 } 16267 } 16268 if (is_digit(code)) return read_num(); 16269 if (PUNC_CHARS(ch)) return token("punc", next()); 16270 if (OPERATOR_CHARS(ch)) return read_operator(); 16271 if (code == 92 || is_identifier_start(code)) return read_word(); 16272 break; 16273 } 16274 parse_error("Unexpected character '" + ch + "'"); 16275 }; 16276 16277 next_token.context = function(nc) { 16278 if (nc) S = nc; 16279 return S; 16280 }; 16281 16282 next_token.add_directive = function(directive) { 16283 S.directive_stack[S.directive_stack.length - 1].push(directive); 16284 16285 if (S.directives[directive] === undefined) { 16286 S.directives[directive] = 1; 16287 } else { 16288 S.directives[directive]++; 16289 } 16290 } 16291 16292 next_token.push_directives_stack = function() { 16293 S.directive_stack.push([]); 16294 } 16295 16296 next_token.pop_directives_stack = function() { 16297 var directives = S.directive_stack[S.directive_stack.length - 1]; 16298 16299 for (var i = 0; i < directives.length; i++) { 16300 S.directives[directives[i]]--; 16301 } 16302 16303 S.directive_stack.pop(); 16304 } 16305 16306 next_token.has_directive = function(directive) { 16307 return S.directives[directive] !== undefined && 16308 S.directives[directive] > 0; 16309 } 16310 16311 return next_token; 16312 16313 }; 16314 16315 /* -----[ Parser (constants) ]----- */ 16316 16317 var UNARY_PREFIX = makePredicate([ 16318 "typeof", 16319 "void", 16320 "delete", 16321 "--", 16322 "++", 16323 "!", 16324 "~", 16325 "-", 16326 "+" 16327 ]); 16328 16329 var UNARY_POSTFIX = makePredicate([ "--", "++" ]); 16330 16331 var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); 16332 16333 var PRECEDENCE = (function(a, ret){ 16334 for (var i = 0; i < a.length; ++i) { 16335 var b = a[i]; 16336 for (var j = 0; j < b.length; ++j) { 16337 ret[b[j]] = i + 1; 16338 } 16339 } 16340 return ret; 16341 })( 16342 [ 16343 ["||"], 16344 ["&&"], 16345 ["|"], 16346 ["^"], 16347 ["&"], 16348 ["==", "===", "!=", "!=="], 16349 ["<", ">", "<=", ">=", "in", "instanceof"], 16350 [">>", "<<", ">>>"], 16351 ["+", "-"], 16352 ["*", "/", "%"] 16353 ], 16354 {} 16355 ); 16356 16357 var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); 16358 16359 var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); 16360 16361 /* -----[ Parser ]----- */ 16362 16363 function parse($TEXT, options) { 16364 16365 options = defaults(options, { 16366 bare_returns : false, 16367 cli : false, 16368 expression : false, 16369 filename : null, 16370 html5_comments : true, 16371 shebang : true, 16372 strict : false, 16373 toplevel : null, 16374 }); 16375 16376 var S = { 16377 input : (typeof $TEXT == "string" 16378 ? tokenizer($TEXT, options.filename, 16379 options.html5_comments, options.shebang) 16380 : $TEXT), 16381 token : null, 16382 prev : null, 16383 peeked : null, 16384 in_function : 0, 16385 in_directives : true, 16386 in_loop : 0, 16387 labels : [] 16388 }; 16389 16390 S.token = next(); 16391 16392 function is(type, value) { 16393 return is_token(S.token, type, value); 16394 }; 16395 16396 function peek() { return S.peeked || (S.peeked = S.input()); }; 16397 16398 function next() { 16399 S.prev = S.token; 16400 if (S.peeked) { 16401 S.token = S.peeked; 16402 S.peeked = null; 16403 } else { 16404 S.token = S.input(); 16405 } 16406 S.in_directives = S.in_directives && ( 16407 S.token.type == "string" || is("punc", ";") 16408 ); 16409 return S.token; 16410 }; 16411 16412 function prev() { 16413 return S.prev; 16414 }; 16415 16416 function croak(msg, line, col, pos) { 16417 var ctx = S.input.context(); 16418 js_error(msg, 16419 ctx.filename, 16420 line != null ? line : ctx.tokline, 16421 col != null ? col : ctx.tokcol, 16422 pos != null ? pos : ctx.tokpos); 16423 }; 16424 16425 function token_error(token, msg) { 16426 croak(msg, token.line, token.col); 16427 }; 16428 16429 function unexpected(token) { 16430 if (token == null) 16431 token = S.token; 16432 token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); 16433 }; 16434 16435 function expect_token(type, val) { 16436 if (is(type, val)) { 16437 return next(); 16438 } 16439 token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); 16440 }; 16441 16442 function expect(punc) { return expect_token("punc", punc); }; 16443 16444 function can_insert_semicolon() { 16445 return !options.strict && ( 16446 S.token.nlb || is("eof") || is("punc", "}") 16447 ); 16448 }; 16449 16450 function semicolon(optional) { 16451 if (is("punc", ";")) next(); 16452 else if (!optional && !can_insert_semicolon()) unexpected(); 16453 }; 16454 16455 function parenthesised() { 16456 expect("("); 16457 var exp = expression(true); 16458 expect(")"); 16459 return exp; 16460 }; 16461 16462 function embed_tokens(parser) { 16463 return function() { 16464 var start = S.token; 16465 var expr = parser(); 16466 var end = prev(); 16467 expr.start = start; 16468 expr.end = end; 16469 return expr; 16470 }; 16471 }; 16472 16473 function handle_regexp() { 16474 if (is("operator", "/") || is("operator", "/=")) { 16475 S.peeked = null; 16476 S.token = S.input(S.token.value.substr(1)); // force regexp 16477 } 16478 }; 16479 16480 var statement = embed_tokens(function() { 16481 handle_regexp(); 16482 switch (S.token.type) { 16483 case "string": 16484 if (S.in_directives) { 16485 var token = peek(); 16486 if (S.token.raw.indexOf("\\") == -1 16487 && (token.nlb 16488 || is_token(token, "eof") 16489 || is_token(token, "punc", ";") 16490 || is_token(token, "punc", "}"))) { 16491 S.input.add_directive(S.token.value); 16492 } else { 16493 S.in_directives = false;
vendor: 5,869 bytes, lines 16494-16622
16494 } 16495 } 16496 var dir = S.in_directives, stat = simple_statement(); 16497 return dir ? new AST_Directive(stat.body) : stat; 16498 case "num": 16499 case "regexp": 16500 case "operator": 16501 case "atom": 16502 return simple_statement(); 16503 16504 case "name": 16505 return is_token(peek(), "punc", ":") 16506 ? labeled_statement() 16507 : simple_statement(); 16508 16509 case "punc": 16510 switch (S.token.value) { 16511 case "{": 16512 return new AST_BlockStatement({ 16513 start : S.token, 16514 body : block_(), 16515 end : prev() 16516 }); 16517 case "[": 16518 case "(": 16519 return simple_statement(); 16520 case ";": 16521 S.in_directives = false; 16522 next(); 16523 return new AST_EmptyStatement(); 16524 default: 16525 unexpected(); 16526 } 16527 16528 case "keyword": 16529 switch (S.token.value) { 16530 case "break": 16531 next(); 16532 return break_cont(AST_Break); 16533 16534 case "continue": 16535 next(); 16536 return break_cont(AST_Continue); 16537 16538 case "debugger": 16539 next(); 16540 semicolon(); 16541 return new AST_Debugger(); 16542 16543 case "do": 16544 next(); 16545 var body = in_loop(statement); 16546 expect_token("keyword", "while"); 16547 var condition = parenthesised(); 16548 semicolon(true); 16549 return new AST_Do({ 16550 body : body, 16551 condition : condition 16552 }); 16553 16554 case "while": 16555 next(); 16556 return new AST_While({ 16557 condition : parenthesised(), 16558 body : in_loop(statement) 16559 }); 16560 16561 case "for": 16562 next(); 16563 return for_(); 16564 16565 case "function": 16566 next(); 16567 return function_(AST_Defun); 16568 16569 case "if": 16570 next(); 16571 return if_(); 16572 16573 case "return": 16574 if (S.in_function == 0 && !options.bare_returns) 16575 croak("'return' outside of function"); 16576 next(); 16577 var value = null; 16578 if (is("punc", ";")) { 16579 next(); 16580 } else if (!can_insert_semicolon()) { 16581 value = expression(true); 16582 semicolon(); 16583 } 16584 return new AST_Return({ 16585 value: value 16586 }); 16587 16588 case "switch": 16589 next(); 16590 return new AST_Switch({ 16591 expression : parenthesised(), 16592 body : in_loop(switch_body_) 16593 }); 16594 16595 case "throw": 16596 next(); 16597 if (S.token.nlb) 16598 croak("Illegal newline after 'throw'"); 16599 var value = expression(true); 16600 semicolon(); 16601 return new AST_Throw({ 16602 value: value 16603 }); 16604 16605 case "try": 16606 next(); 16607 return try_(); 16608 16609 case "var": 16610 next(); 16611 var node = var_(); 16612 semicolon(); 16613 return node; 16614 16615 case "const": 16616 next(); 16617 var node = const_(); 16618 semicolon(); 16619 return node; 16620 16621 case "with": 16622 if (S.input.has_directive("use strict")) {
16623 croak("Strict mode may not include a with statement"); 16624 } 16625 next(); 16626 return new AST_With({ 16627 expression : parenthesised(), 16628 body : statement() 16629 }); 16630 } 16631 } 16632 unexpected(); 16633 }); 16634 16635 function labeled_statement() { 16636 var label = as_symbol(AST_Label); 16637 if (find_if(function(l){ return l.name == label.name }, S.labels)) { 16638 // ECMA-262, 12.12: An ECMAScript program is considered 16639 // syntactically incorrect if it contains a 16640 // LabelledStatement that is enclosed by a 16641 // LabelledStatement with the same Identifier as label. 16642 croak("Label " + label.name + " defined twice"); 16643 } 16644 expect(":"); 16645 S.labels.push(label); 16646 var stat = statement(); 16647 S.labels.pop(); 16648 if (!(stat instanceof AST_IterationStatement)) { 16649 // check for `continue` that refers to this label. 16650 // those should be reported as syntax errors. 16651 // https://github.com/mishoo/UglifyJS2/issues/287 16652 label.references.forEach(function(ref){ 16653 if (ref instanceof AST_Continue) { 16654 ref = ref.label.start; 16655 croak("Continue label `" + label.name + "` refers to non-IterationStatement.", 16656 ref.line, ref.col, ref.pos); 16657 } 16658 }); 16659 } 16660 return new AST_LabeledStatement({ body: stat, label: label }); 16661 }; 16662 16663 function simple_statement(tmp) { 16664 return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); 16665 }; 16666 16667 function break_cont(type) { 16668 var label = null, ldef; 16669 if (!can_insert_semicolon()) { 16670 label = as_symbol(AST_LabelRef, true); 16671 } 16672 if (label != null) { 16673 ldef = find_if(function(l){ return l.name == label.name }, S.labels); 16674 if (!ldef) 16675 croak("Undefined label " + label.name); 16676 label.thedef = ldef; 16677 } 16678 else if (S.in_loop == 0) 16679 croak(type.TYPE + " not inside a loop or switch"); 16680 semicolon(); 16681 var stat = new type({ label: label }); 16682 if (ldef) ldef.references.push(stat); 16683 return stat; 16684 }; 16685 16686 function for_() { 16687 expect("("); 16688 var init = null; 16689 if (!is("punc", ";")) { 16690 init = is("keyword", "var") 16691 ? (next(), var_(true)) 16692 : expression(true, true); 16693 if (is("operator", "in")) { 16694 if (init instanceof AST_Var && init.definitions.length > 1) 16695 croak("Only one variable declaration allowed in for..in loop"); 16696 next(); 16697 return for_in(init); 16698 } 16699 } 16700 return regular_for(init); 16701 }; 16702 16703 function regular_for(init) { 16704 expect(";"); 16705 var test = is("punc", ";") ? null : expression(true); 16706 expect(";"); 16707 var step = is("punc", ")") ? null : expression(true); 16708 expect(")"); 16709 return new AST_For({ 16710 init : init, 16711 condition : test, 16712 step : step, 16713 body : in_loop(statement) 16714 }); 16715 }; 16716 16717 function for_in(init) { 16718 var lhs = init instanceof AST_Var ? init.definitions[0].name : null; 16719 var obj = expression(true); 16720 expect(")"); 16721 return new AST_ForIn({ 16722 init : init, 16723 name : lhs, 16724 object : obj, 16725 body : in_loop(statement) 16726 }); 16727 }; 16728 16729 var function_ = function(ctor) { 16730 var in_statement = ctor === AST_Defun; 16731 var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null; 16732 if (in_statement && !name) 16733 unexpected(); 16734 expect("("); 16735 return new ctor({ 16736 name: name, 16737 argnames: (function(first, a){ 16738 while (!is("punc", ")")) { 16739 if (first) first = false; else expect(","); 16740 a.push(as_symbol(AST_SymbolFunarg)); 16741 } 16742 next(); 16743 return a; 16744 })(true, []), 16745 body: (function(loop, labels){ 16746 ++S.in_function; 16747 S.in_directives = true; 16748 S.input.push_directives_stack(); 16749 S.in_loop = 0; 16750 S.labels = []; 16751 var a = block_(); 16752 S.input.pop_directives_stack(); 16753 --S.in_function; 16754 S.in_loop = loop; 16755 S.labels = labels; 16756 return a; 16757 })(S.in_loop, S.labels) 16758 }); 16759 }; 16760 16761 function if_() { 16762 var cond = parenthesised(), body = statement
16762(), belse = null; 16763 if (is("keyword", "else")) { 16764 next(); 16765 belse = statement(); 16766 } 16767 return new AST_If({ 16768 condition : cond, 16769 body : body, 16770 alternative : belse 16771 }); 16772 }; 16773 16774 function block_() { 16775 expect("{"); 16776 var a = []; 16777 while (!is("punc", "}")) { 16778 if (is("eof")) unexpected(); 16779 a.push(statement()); 16780 } 16781 next(); 16782 return a; 16783 }; 16784 16785 function switch_body_() { 16786 expect("{"); 16787 var a = [], cur = null, branch = null, tmp; 16788 while (!is("punc", "}")) { 16789 if (is("eof")) unexpected(); 16790 if (is("keyword", "case")) { 16791 if (branch) branch.end = prev(); 16792 cur = []; 16793 branch = new AST_Case({ 16794 start : (tmp = S.token, next(), tmp), 16795 expression : expression(true), 16796 body : cur 16797 }); 16798 a.push(branch); 16799 expect(":"); 16800 } 16801 else if (is("keyword", "default")) { 16802 if (branch) branch.end = prev(); 16803 cur = []; 16804 branch = new AST_Default({ 16805 start : (tmp = S.token, next(), expect(":"), tmp), 16806 body : cur 16807 }); 16808 a.push(branch); 16809 } 16810 else { 16811 if (!cur) unexpected(); 16812 cur.push(statement()); 16813 } 16814 } 16815 if (branch) branch.end = prev(); 16816 next(); 16817 return a; 16818 }; 16819 16820 function try_() { 16821 var body = block_(), bcatch = null, bfinally = null; 16822 if (is("keyword", "catch")) { 16823 var start = S.token; 16824 next(); 16825 expect("("); 16826 var name = as_symbol(AST_SymbolCatch); 16827 expect(")"); 16828 bcatch = new AST_Catch({ 16829 start : start, 16830 argname : name, 16831 body : block_(), 16832 end : prev() 16833 }); 16834 } 16835 if (is("keyword", "finally")) { 16836 var start = S.token; 16837 next(); 16838 bfinally = new AST_Finally({ 16839 start : start, 16840 body : block_(), 16841 end : prev() 16842 }); 16843 } 16844 if (!bcatch && !bfinally) 16845 croak("Missing catch/finally blocks"); 16846 return new AST_Try({ 16847 body : body, 16848 bcatch : bcatch, 16849 bfinally : bfinally 16850 }); 16851 }; 16852 16853 function vardefs(no_in, in_const) { 16854 var a = []; 16855 for (;;) { 16856 a.push(new AST_VarDef({ 16857 start : S.token, 16858 name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), 16859 value : is("operator", "=") ? (next(), expression(false, no_in)) : null, 16860 end : prev() 16861 })); 16862 if (!is("punc", ",")) 16863 break; 16864 next(); 16865 } 16866 return a; 16867 }; 16868 16869 var var_ = function(no_in) { 16870 return new AST_Var({ 16871 start : prev(), 16872 definitions : vardefs(no_in, false), 16873 end : prev() 16874 }); 16875 }; 16876 16877 var const_ = function() { 16878 return new AST_Const({ 16879 start : prev(), 16880 definitions : vardefs(false, true), 16881 end : prev() 16882 }); 16883 }; 16884 16885 var new_ = function(allow_calls) { 16886 var start = S.token; 16887 expect_token("operator", "new"); 16888 var newexp = expr_atom(false), args; 16889 if (is("punc", "(")) { 16890 next(); 16891 args = expr_list(")"); 16892 } else { 16893 args = []; 16894 } 16895 return subscripts(new AST_New({ 16896 start : start, 16897 expression : newexp, 16898 args : args, 16899 end : prev() 16900 }), allow_calls); 16901 }; 16902 16903 function as_atom_node() { 16904 var tok = S.token, ret; 16905 switch (tok.type) { 16906 case "name": 16907 case "keyword": 16908 ret = _make_symbol(AST_SymbolRef); 16909 break; 16910 case "num": 16911 ret = new AST_Number({ start: tok, end: tok, value: tok.value }); 16912 break; 16913 case "string": 16914 ret = new AST_String({ 16915 start : tok, 16916 end : tok, 16917 value : tok.value, 16918 quote : tok.quote 16919 }); 16920 break; 16921 case "regexp": 16922 ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); 16923 break; 16924 case "atom": 16925 switch (tok.value) { 16926 case "false": 16927 ret = new AST_False({ start: tok, end: tok }); 16928 break; 16929 case "true": 16930 ret = new AST_True({ start: tok, end: tok }); 16931 break; 16932 case "null": 16933 ret = new AST_Null({ start: tok, end: tok }); 16934 break; 16935 } 16936 break; 16937 case "operator": 16938 if (!is_identifier_string(tok.value)) { 16939 croak("Invalid getter/setter name: " + tok.value, 16940 tok.line, tok.col, tok.pos); 16941 } 16942 ret = _make_symbol(AST_SymbolRef); 16943 break; 16944 } 16945 next(); 16946 return ret; 16947 }; 16948 16949 var expr_atom = function(allow_calls) { 16950 if (is("operator", "new")) { 16951 return new_(allow_calls); 16952 } 16953 var start = S.token; 16954 if (is("punc")) { 16955 switch (start.value) { 16956 case "(": 16957 next(); 16958 var ex = expression(true); 16959 ex.start = start; 16960 ex.end = S.token; 16961 expect(")"); 16962 return subscripts(ex, allow_calls); 16963 case "[": 16964 return subscripts(array_(), allow_calls); 16965 case "{": 16966 return subscripts(object_(), allow_calls); 16967 } 16968 unexpected(); 16969 } 16970 if (is("keyword", "function")) { 16971 next(); 16972 var func = function_(AST_Function); 16973 func.start = start; 16974 func.end = prev(); 16975 return subscripts(func, allow_calls); 16976 } 16977 if (ATOMIC_START_TOKEN[S.token.type]) { 16978 return subscripts(as_atom_node(), allow_calls); 16979 } 16980 unexpected(); 16981 }; 16982 16983 function expr_list(closing, allow_trailing_comma, allow_empty) { 16984 var first = true, a = []; 16985 while (!is("punc", closing)) { 16986 if (first) first = false; else expect(","); 16987 if (allow_trailing_comma && is("punc", closing)) break; 16988 if (is("punc", ",") && allow_empty) { 16989 a.push(new AST_Hole({ start: S.token, end: S.token })); 16990 } else { 16991 a.push(expression(false)); 16992 } 16993 } 16994 next(); 16995 return a; 16996 }; 16997 16998 var array_ = embed_tokens(function() { 16999 expect("["); 17000 return new AST_Array({ 17001 elements: expr_list("]", !options.strict, true) 17002 }); 17003 }); 17004 17005 var create_accessor = embed_tokens(function() { 17006 return function_(AST_Accessor); 17007 }); 17008 17009 var object_ = embed_tokens(function() { 17010 expect("{"); 17011 var first = true, a = []; 17012 while (!is("punc", "}")) { 17013 if (first) first = false; else expect(","); 17014 if (!options.strict && is("punc", "}")) 17015 // allow trailing comma 17016 break; 17017 var start = S.token; 17018 var type = start.type; 17019 var name = as_property_name(); 17020 if (type == "name" && !is("punc", ":")) { 17021 var key = new AST_SymbolAccessor({ 17022 start: S.token, 17023 name: as_property_name(), 17024 end: prev() 17025 }); 17026 if (name == "get") { 17027 a.push(new AST_ObjectGetter({ 17028 start : start, 17029 key : key, 17030 value : create_accessor(), 17031 end : prev() 17032 })); 17033 continue; 17034 } 17035 if (name == "set") { 17036 a.push(new AST_ObjectSetter({ 17037 start : start, 17038 key : key, 17039 value : create_accessor(), 17040 end : prev() 17041 })); 17042 continue; 17043 } 17044 } 17045 expect(":"); 17046 a.push(new AST_ObjectKeyVal({ 17047 start : start, 17048 quote : start.quote, 17049 key : name, 17050 value : expression(false), 17051 end : prev() 17052 })); 17053 } 17054 next(); 17055 return new AST_Object({ properties: a }); 17056 }); 17057 17058 function as_property_name() { 17059 var tmp = S.token;
17060 switch (tmp.type) { 17061 case "operator": 17062 if (!KEYWORDS(tmp.value)) unexpected(); 17063 case "num": 17064 case "string": 17065 case "name": 17066 case "keyword": 17067 case "atom": 17068 next(); 17069 return tmp.value; 17070 default: 17071 unexpected(); 17072 } 17073 }; 17074 17075 function as_name() { 17076 var tmp = S.token; 17077 if (tmp.type != "name") unexpected(); 17078 next(); 17079 return tmp.value; 17080 }; 17081 17082 function _make_symbol(type) { 17083 var name = S.token.value; 17084 return new (name == "this" ? AST_This : type)({ 17085 name : String(name), 17086 start : S.token, 17087 end : S.token 17088 }); 17089 }; 17090 17091 function as_symbol(type, noerror) { 17092 if (!is("name")) { 17093 if (!noerror) croak("Name expected"); 17094 return null; 17095 } 17096 var sym = _make_symbol(type); 17097 next(); 17098 return sym; 17099 }; 17100 17101 var subscripts = function(expr, allow_calls) { 17102 var start = expr.start; 17103 if (is("punc", ".")) { 17104 next(); 17105 return subscripts(new AST_Dot({ 17106 start : start, 17107 expression : expr, 17108 property : as_name(), 17109 end : prev() 17110 }), allow_calls); 17111 } 17112 if (is("punc", "[")) { 17113 next(); 17114 var prop = expression(true); 17115 expect("]"); 17116 return subscripts(new AST_Sub({ 17117 start : start, 17118 expression : expr, 17119 property : prop, 17120 end : prev() 17121 }), allow_calls); 17122 } 17123 if (allow_calls && is("punc", "(")) { 17124 next(); 17125 return subscripts(new AST_Call({ 17126 start : start, 17127 expression : expr, 17128 args : expr_list(")"), 17129 end : prev() 17130 }), true); 17131 } 17132 return expr; 17133 }; 17134 17135 var maybe_unary = function(allow_calls) { 17136 var start = S.token; 17137 if (is("operator") && UNARY_PREFIX(start.value)) { 17138 next(); 17139 handle_regexp(); 17140 var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls)); 17141 ex.start = start; 17142 ex.end = prev(); 17143 return ex; 17144 } 17145 var val = expr_atom(allow_calls); 17146 while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { 17147 val = make_unary(AST_UnaryPostfix, S.token, val); 17148 val.start = start; 17149 val.end = S.token; 17150 next(); 17151 } 17152 return val; 17153 }; 17154 17155 function make_unary(ctor, token, expr) { 17156 var op = token.value; 17157 if ((op == "++" || op == "--") && !is_assignable(expr)) 17158 croak("Invalid use of " + op + " operator", token.line, token.col, token.pos); 17159 return new ctor({ operator: op, expression: expr }); 17160 }; 17161 17162 var expr_op = function(left, min_prec, no_in) { 17163 var op = is("operator") ? S.token.value : null; 17164 if (op == "in" && no_in) op = null; 17165 var prec = op != null ? PRECEDENCE[op] : null; 17166 if (prec != null && prec > min_prec) { 17167 next(); 17168 var right = expr_op(maybe_unary(true), prec, no_in); 17169 return expr_op(new AST_Binary({ 17170 start : left.start, 17171 left : left, 17172 operator : op, 17173 right : right, 17174 end : right.end 17175 }), min_prec, no_in); 17176 } 17177 return left; 17178 }; 17179 17180 function expr_ops(no_in) { 17181 return expr_op(maybe_unary(true), 0, no_in); 17182 }; 17183 17184 var maybe_conditional = function(no_in) { 17185 var start = S.token; 17186 var expr = expr_ops(no_in); 17187 if (is("operator", "?")) { 17188 next(); 17189 var yes = expression(false); 17190 expect(":"); 17191 return new AST_Conditional({ 17192 start : start, 17193 condition : expr, 17194 consequent : yes, 17195 alternative : expression(false, no_in), 17196 end : prev() 17197 }); 17198 } 17199 return expr; 17200 }; 17201 17202 function is_assignable(expr) { 17203 if (options.cli) return true; 17204 return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef; 17205 }; 17206 17207 var maybe_assign = function(no_in) { 17208 var start = S.token; 17209 var left = maybe_conditional(no_in), val = S.token.value; 17210 if (is("operator") && ASSIGNMENT(val)) { 17211 if (is_assignable(left)) { 17212 next(); 17213 return new AST_Assign({ 17214 start : start, 17215 left : left, 17216 operator : val, 17217 right : maybe_assign(no_in), 17218 end : prev() 17219 }); 17220 } 17221 croak("Invalid assignment"); 17222 } 17223 return left; 17224 }; 17225 17226 var expression = function(commas, no_in) { 17227 var start = S.token; 17228 var expr = maybe_assign(no_in); 17229 if (commas && is("punc", ",")) { 17230 next(); 17231 return new AST_Seq({ 17232 start : start, 17233 car : expr, 17234 cdr : expression(true, no_in), 17235 end : peek() 17236 }); 17237 } 17238 return expr; 17239 }; 17240 17241 function in_loop(cont) { 17242 ++S.in_loop; 17243 var ret = cont(); 17244 --S.in_loop; 17245 return ret; 17246 }; 17247 17248 if (options.expression) { 17249 return expression(true); 17250 } 17251 17252 return (function(){ 17253 var start = S.token; 17254 var body = []; 17255 S.input.push_directives_stack(); 17256 while (!is("eof"))
17257 body.push(statement()); 17258 S.input.pop_directives_stack(); 17259 var end = prev(); 17260 var toplevel = options.toplevel; 17261 if (toplevel) { 17262 toplevel.body = toplevel.body.concat(body); 17263 toplevel.end = end; 17264 } else { 17265 toplevel = new AST_Toplevel({ start: start, body: body, end: end }); 17266 } 17267 return toplevel; 17268 })(); 17269 17270 }; 17271 17272 /*********************************************************************** 17273 17274 A JavaScript tokenizer / parser / beautifier / compressor. 17275 https://github.com/mishoo/UglifyJS2 17276 17277 -------------------------------- (C) --------------------------------- 17278 17279 Author: Mihai Bazon 17280 <[email protected]> 17281 http://mihai.bazon.net/blog 17282 17283 Distributed under the BSD license: 17284 17285 Copyright 2012 (c) Mihai Bazon <[email protected]> 17286 17287 Redistribution and use in source and binary forms, with or without 17288 modification, are permitted provided that the following conditions 17289 are met: 17290 17291 * Redistributions of source code must retain the above 17292 copyright notice, this list of conditions and the following 17293 disclaimer. 17294 17295 * Redistributions in binary form must reproduce the above 17296 copyright notice, this list of conditions and the following 17297 disclaimer in the documentation and/or other materials 17298 provided with the distribution. 17299 17300 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 17301 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17302 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17303 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 17304 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 17305 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17306 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 17307 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 17308 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 17309 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 17310 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 17311 SUCH DAMAGE. 17312 17313 ***********************************************************************/ 17314 17315 "use strict"; 17316 17317// Tree transformer helpers. 17318 17319 function TreeTransformer(before, after) { 17320 TreeWalker.call(this); 17321 this.before = before; 17322 this.after = after; 17323 } 17324 TreeTransformer.prototype = new TreeWalker; 17325 17326 (function(undefined){ 17327 17328 function _(node, descend) { 17329 node.DEFMETHOD("transform", function(tw, in_list){ 17330 var x, y; 17331 tw.push(this); 17332 if (tw.before) x = tw.before(this, descend, in_list); 17333 if (x === undefined) { 17334 if (!tw.after) { 17335 x = this; 17336 descend(x, tw); 17337 } else { 17338 tw.stack[tw.stack.length - 1] = x = this; 17339 descend(x, tw); 17340 y = tw.after(x, in_list); 17341 if (y !== undefined) x = y; 17342 } 17343 } 17344 tw.pop(this); 17345 return x; 17346 }); 17347 }; 17348 17349 function do_list(list, tw) { 17350 return MAP(list, function(node){ 17351 return node.transform(tw, true); 17352 }); 17353 }; 17354 17355 _(AST_Node, noop); 17356 17357 _(AST_LabeledStatement, function(self, tw){ 17358 self.label = self.label.transform(tw); 17359 self.body = self.body.transform(tw); 17360 }); 17361 17362 _(AST_SimpleStatement, function(self, tw){ 17363 self.body = self.body.transform(tw); 17364 }); 17365 17366 _(AST_Block, function(self, tw){ 17367 self.body = do_list(self.body, tw); 17368 }); 17369 17370 _(AST_DWLoop, function(self, tw){ 17371 self.condition = self.condition.transform(tw); 17372 self.body = self.body.transform(tw); 17373 }); 17374 17375 _(AST_For, function(self, tw){ 17376 if (self.init) self.init = self.init.transform(tw); 17377 if (self.condition) self.condition = self.condition.transform(tw); 17378 if (self.step) self.step = self.step.transform(tw); 17379 self.body = self.body.transform(tw); 17380 }); 17381 17382 _(AST_ForIn, function(self, tw){ 17383 self.init = self.init.transform(tw); 17384 self.object = self.object.transform(tw); 17385 self.body = self.body.transform(tw); 17386 }); 17387 17388 _(AST_With, function(self, tw){ 17389 self.expression = self.expression.transform(tw); 17390 self.body = self.body.transform(tw); 17391 }); 17392 17393 _(AST_Exit, function(self, tw){ 17394 if (self.value) self.value = self.value.transform(tw); 17395 }); 17396 17397 _(AST_LoopControl, function(self, tw){ 17398 if (self.label) self.label = self.label.transform(tw); 17399 }); 17400 17401 _(AST_If, function(self, tw){ 17402 self.condition = self.condition.transform(tw); 17403 self.body = self.body.transform(tw); 17404 if (self.alternative) self.alternative = self.alternative.transform(tw); 17405 }); 17406 17407 _(AST_Switch, function(self, tw){ 17408 self.expression = self.expression.transform(tw); 17409 self.body = do_list(self.body, tw); 17410 }); 17411 17412 _(AST_Case, function(self, tw){ 17413 self.expression = self.expression.transform(tw); 17414 self.body = do_list(self.body, tw); 17415 }); 17416 17417 _(AST_Try, function(self, tw){ 17418 self.body = do_list(self.body, tw); 17419 if (self.bcatch) self.bcatch = self.bcatch.transform(tw); 17420 if (self.bfinally) self.bfinally = self.bfinally.transform(tw); 17421 }); 17422 17423 _(AST_Catch, function(self, tw){ 17424 self.argname = self.argname.transform(tw); 17425 self.body = do_list(self.body, tw); 17426 }); 17427 17428 _(AST_Definitions, function(self, tw){ 17429 self.definitions = do_list(self.definitions, tw); 17430 }); 17431 17432 _(AST_VarDef, function(self, tw){ 17433 self.name = self.name.transform(tw); 17434 if (self.value) self.value = self.value.transform(tw); 17435 }); 17436 17437 _(AST_Lambda, function(self, tw){ 17438 if (self.name) self.name = self.name.transform(tw); 17439 self.argnames = do_list(self.argnames, tw); 17440 self.body = do_list(self.body, tw); 17441 }); 17442 17443 _(AST_Call, function(self, tw){ 17444 self.expression = self.expression.transform(tw); 17445 self.args = do_list(self.args, tw); 17446 }); 17447 17448 _(AST_Seq, function(self, tw){ 17449 self.car = self.car.transform(tw); 17450 self.cdr = self.cdr.transform(tw); 17451 }); 17452 17453 _(AST_Dot, function(self, tw){ 17454 self.expression = self.expression.transform(tw); 17455 }); 17456 17457 _(AST_Sub, function(self, tw){ 17458 self.expression = self.expression.transform(tw); 17459 self.property = self.property.transform(tw); 17460 }); 17461 17462 _(AST_Unary, function(self, tw){ 17463 self.expression = self.expression.transform(tw); 17464 }); 17465 17466 _(AST_Binary, function(self, tw){ 17467 self.left = self.left.transform(tw); 17468 self.right = self.right.transform(tw); 17469 }); 17470 17471 _(AST_Conditional, function(self, tw){ 17472 self.condition = self.condition.transform(tw); 17473 self.consequent = self.consequent.transform(tw); 17474 self.alternative = self.alternative.transform(tw); 17475 }); 17476 17477 _(AST_Array, function(self, tw){ 17478 self.elements = do_list(self.elements, tw); 17479 }); 17480 17481 _(AST_Object, function(self, tw){ 17482 self.properties = do_list(self.properties, tw); 17483 }); 17484 17485 _(AST_ObjectProperty, function(self, tw){ 17486 self.value = self.value.transform(tw); 17487 }); 17488 17489 })(); 17490 17491 /*********************************************************************** 17492 17493 A JavaScript tokenizer / parser / beautifier / compressor. 17494 https://github.com/mishoo/UglifyJS2 17495 17496 -------------------------------- (C) --------------------------------- 17497 17498 Author: Mihai Bazon 17499 <[email protected]> 17500 http://mihai.bazon.net/blog 17501 17502 Distributed under the BSD license: 17503 17504 Copyright 2012 (c) Mihai Bazon <[email protected]> 17505 17506 Redistribution and use in source and binary forms, with or without 17507 modification, are permitted provided that the following conditions 17508 are met: 17509 17510 * Redistributions of source code must retain the above 17511 copyright notice, this list of conditions and the following 17512 disclaimer. 17513 17514 * Redistributions in binary form must reproduce the above 17515 copyright notice, this list of conditions and the following 17516 disclaimer in the documentation and/or other materials 17517 provided with the distribution. 17518 17519 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 17520 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17521 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17522 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 17523 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
17524 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17525 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 17526 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 17527 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 17528 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 17529 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 17530 SUCH DAMAGE. 17531 17532 ***********************************************************************/ 17533 17534 "use strict"; 17535 17536 function SymbolDef(scope, index, orig) { 17537 this.name = orig.name; 17538 this.orig = [ orig ]; 17539 this.scope = scope; 17540 this.references = []; 17541 this.global = false; 17542 this.mangled_name = null; 17543 this.undeclared = false; 17544 this.index = index; 17545 this.id = SymbolDef.next_id++; 17546 }; 17547 17548 SymbolDef.next_id = 1; 17549 17550 SymbolDef.prototype = { 17551 unmangleable: function(options) { 17552 if (!options) options = {}; 17553 17554 return (this.global && !options.toplevel) 17555 || this.undeclared 17556 || (!options.eval && (this.scope.uses_eval || this.scope.uses_with)) 17557 || (options.keep_fnames 17558 && (this.orig[0] instanceof AST_SymbolLambda 17559 || this.orig[0] instanceof AST_SymbolDefun)); 17560 }, 17561 mangle: function(options) { 17562 var cache = options.cache && options.cache.props; 17563 if (this.global && cache && cache.has(this.name)) { 17564 this.mangled_name = cache.get(this.name); 17565 } 17566 else if (!this.mangled_name && !this.unmangleable(options)) { 17567 var s = this.scope; 17568 var sym = this.orig[0]; 17569 if (!options.screw_ie8 && sym instanceof AST_SymbolLambda) 17570 s = s.parent_scope; 17571 var def; 17572 if (this.defun && (def = this.defun.variables.get(this.name))) { 17573 this.mangled_name = def.mangled_name || def.name; 17574 } else 17575 this.mangled_name = s.next_mangled(options, this); 17576 if (this.global && cache) { 17577 cache.set(this.name, this.mangled_name); 17578 } 17579 } 17580 } 17581 }; 17582 17583 AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ 17584 options = defaults(options, { 17585 cache: null, 17586 screw_ie8: true, 17587 }); 17588 17589 // pass 1: setup scope chaining and handle definitions 17590 var self = this; 17591 var scope = self.parent_scope = null; 17592 var labels = new Dictionary(); 17593 var defun = null; 17594 var tw = new TreeWalker(function(node, descend){ 17595 if (node instanceof AST_Catch) { 17596 var save_scope = scope; 17597 scope = new AST_Scope(node); 17598 scope.init_scope_vars(save_scope); 17599 descend(); 17600 scope = save_scope; 17601 return true; 17602 } 17603 if (node instanceof AST_Scope) { 17604 node.init_scope_vars(scope); 17605 var save_scope = scope; 17606 var save_defun = defun; 17607 var save_labels = labels; 17608 defun = scope = node; 17609 labels = new Dictionary(); 17610 descend(); 17611 scope = save_scope; 17612 defun = save_defun; 17613 labels = save_labels; 17614 return true; // don't descend again in TreeWalker 17615 } 17616 if (node instanceof AST_LabeledStatement) { 17617 var l = node.label; 17618 if (labels.has(l.name)) { 17619 throw new Error(string_template("Label {name} defined twice", l)); 17620 } 17621 labels.set(l.name, l); 17622 descend(); 17623 labels.del(l.name); 17624 return true; // no descend again 17625 } 17626 if (node instanceof AST_With) { 17627 for (var s = scope; s; s = s.parent_scope) 17628 s.uses_with = true; 17629 return; 17630 } 17631 if (node instanceof AST_Symbol) { 17632 node.scope = scope; 17633 } 17634 if (node instanceof AST_Label) { 17635 node.thedef = node; 17636 node.references = []; 17637 } 17638 if (node instanceof AST_SymbolLambda) { 17639 defun.def_function(node); 17640 } 17641 else if (node instanceof AST_SymbolDefun) { 17642 // Careful here, the scope where this should be defined is 17643 // the parent scope. The reason is that we enter a new 17644 // scope when we encounter the AST_Defun node (which is 17645 // instanceof AST_Scope) but we get to the symbol a bit 17646 // later. 17647 (node.scope = defun.parent_scope).def_function(node); 17648 } 17649 else if (node instanceof AST_SymbolVar 17650 || node instanceof AST_SymbolConst) { 17651 defun.def_variable(node); 17652 if (defun !== scope) { 17653 node.mark_enclosed(options); 17654 var def = scope.find_variable(node); 17655 if (node.thedef !== def) { 17656 node.thedef = def; 17657 node.reference(options); 17658 } 17659 } 17660 } 17661 else if (node instanceof AST_SymbolCatch) { 17662 scope.def_variable(node).defun = defun; 17663 } 17664 else if (node instanceof AST_LabelRef) { 17665 var sym = labels.get(node.name); 17666 if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", { 17667 name: node.name, 17668 line: node.start.line, 17669 col: node.start.col 17670 })); 17671 node.thedef = sym; 17672 } 17673 }); 17674 self.walk(tw); 17675 17676 // pass 2: find back references and eval 17677 var func = null; 17678 var globals = self.globals = new Dictionary(); 17679 var tw = new TreeWalker(function(node, descend){ 17680 if (node instanceof AST_Lambda) { 17681 var prev_func = func; 17682 func = node; 17683 descend(); 17684 func = prev_func; 17685 return true; 17686 }
17687 if (node instanceof AST_LoopControl && node.label) { 17688 node.label.thedef.references.push(node); 17689 return true; 17690 } 17691 if (node instanceof AST_SymbolRef) { 17692 var name = node.name; 17693 if (name == "eval" && tw.parent() instanceof AST_Call) { 17694 for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) { 17695 s.uses_eval = true; 17696 } 17697 } 17698 var sym = node.scope.find_variable(name); 17699 if (node.scope instanceof AST_Lambda && name == "arguments") { 17700 node.scope.uses_arguments = true; 17701 } 17702 if (!sym) { 17703 sym = self.def_global(node); 17704 } 17705 node.thedef = sym; 17706 node.reference(options); 17707 return true; 17708 } 17709 }); 17710 self.walk(tw); 17711 17712 // pass 3: fix up any scoping issue with IE8 17713 if (!options.screw_ie8) { 17714 self.walk(new TreeWalker(function(node, descend) { 17715 if (node instanceof AST_SymbolCatch) { 17716 var name = node.name; 17717 var refs = node.thedef.references; 17718 var scope = node.thedef.defun; 17719 var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node); 17720 refs.forEach(function(ref) { 17721 ref.thedef = def; 17722 ref.reference(options); 17723 }); 17724 node.thedef = def; 17725 return true; 17726 } 17727 })); 17728 } 17729 17730 if (options.cache) { 17731 this.cname = options.cache.cname; 17732 } 17733 }); 17734 17735 AST_Toplevel.DEFMETHOD("def_global", function(node){ 17736 var globals = this.globals, name = node.name; 17737 if (globals.has(name)) { 17738 return globals.get(name); 17739 } else { 17740 var g = new SymbolDef(this, globals.size(), node); 17741 g.undeclared = true; 17742 g.global = true; 17743 globals.set(name, g); 17744 return g; 17745 } 17746 }); 17747 17748 AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){ 17749 this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) 17750 this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) 17751 this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement 17752 this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` 17753 this.parent_scope = parent_scope; // the parent scope 17754 this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes 17755 this.cname = -1; // the current index for mangling functions/variables 17756 }); 17757 17758 AST_Lambda.DEFMETHOD("init_scope_vars", function(){ 17759 AST_Scope.prototype.init_scope_vars.apply(this, arguments); 17760 this.uses_arguments = false; 17761 this.def_variable(new AST_SymbolVar({ 17762 name: "arguments", 17763 start: this.start, 17764 end: this.end 17765 })); 17766 }); 17767 17768 AST_Symbol.DEFMETHOD("mark_enclosed", function(options) { 17769 var def = this.definition(); 17770 var s = this.scope; 17771 while (s) { 17772 push_uniq(s.enclosed, def); 17773 if (options.keep_fnames) { 17774 s.functions.each(function(d) { 17775 push_uniq(def.scope.enclosed, d); 17776 }); 17777 } 17778 if (s === def.scope) break; 17779 s = s.parent_scope; 17780 } 17781 }); 17782 17783 AST_Symbol.DEFMETHOD("reference", function(options) { 17784 this.definition().references.push(this); 17785 this.mark_enclosed(options); 17786 }); 17787 17788 AST_Scope.DEFMETHOD("find_variable", function(name){ 17789 if (name instanceof AST_Symbol) name = name.name; 17790 return this.variables.get(name) 17791 || (this.parent_scope && this.parent_scope.find_variable(name)); 17792 }); 17793 17794 AST_Scope.DEFMETHOD("def_function", function(symbol){ 17795 this.functions.set(symbol.name, this.def_variable(symbol)); 17796 }); 17797 17798 AST_Scope.DEFMETHOD("def_variable", function(symbol){ 17799 var def; 17800 if (!this.variables.has(symbol.name)) { 17801 def = new SymbolDef(this, this.variables.size(), symbol); 17802 this.variables.set(symbol.name, def); 17803 def.global = !this.parent_scope; 17804 } else { 17805 def = this.variables.get(symbol.name); 17806 def.orig.push(symbol); 17807 } 17808 return symbol.thedef = def; 17809 }); 17810 17811 AST_Scope.DEFMETHOD("next_mangled", function(options){ 17812 var ext = this.enclosed; 17813 out: while (true) { 17814 var m = base54(++this.cname); 17815 if (!is_identifier(m)) continue; // skip over "do" 17816 17817 // https://github.com/mishoo/UglifyJS2/issues/242 -- do n
17817ot 17818 // shadow a name excepted from mangling. 17819 if (options.except.indexOf(m) >= 0) continue; 17820 17821 // we must ensure that the mangled name does not shadow a name 17822 // from some parent scope that is referenced in this or in 17823 // inner scopes. 17824 for (var i = ext.length; --i >= 0;) { 17825 var sym = ext[i]; 17826 var name = sym.mangled_name || (sym.unmangleable(options) && sym.name); 17827 if (m == name) continue out; 17828 } 17829 return m; 17830 } 17831 }); 17832 17833 AST_Function.DEFMETHOD("next_mangled", function(options, def){ 17834 // #179, #326 17835 // in Safari strict mode, something like (function x(x){...}) is a syntax error; 17836 // a function expression's argument cannot shadow the function expression's name 17837 17838 var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition(); 17839 17840 // the function's mangled_name is null when keep_fnames is true 17841 var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null; 17842 17843 while (true) { 17844 var name = AST_Lambda.prototype.next_mangled.call(this, options, def); 17845 if (!tricky_name || tricky_name != name) 17846 return name; 17847 } 17848 }); 17849 17850 AST_Symbol.DEFMETHOD("unmangleable", function(options){ 17851 return this.definition().unmangleable(options); 17852 }); 17853 17854// labels are always mangleable 17855 AST_Label.DEFMETHOD("unmangleable", function(){ 17856 return false; 17857 }); 17858 17859 AST_Symbol.DEFMETHOD("unreferenced", function(){ 17860 return this.definition().references.length == 0 17861 && !(this.scope.uses_eval || this.scope.uses_with); 17862 }); 17863 17864 AST_Symbol.DEFMETHOD("undeclared", function(){ 17865 return this.definition().undeclared; 17866 }); 17867 17868 AST_LabelRef.DEFMETHOD("undeclared", function(){ 17869 return false; 17870 }); 17871 17872 AST_Label.DEFMETHOD("undeclared", function(){ 17873 return false; 17874 }); 17875 17876 AST_Symbol.DEFMETHOD("definition", function(){ 17877 return this.thedef; 17878 }); 17879 17880 AST_Symbol.DEFMETHOD("global", function(){ 17881 return this.definition().global; 17882 }); 17883 17884 AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ 17885 return defaults(options, { 17886 eval : false, 17887 except : [], 17888 keep_fnames : false, 17889 screw_ie8 : true, 17890 sort : false, // Ignored. Flag retained for backwards compatibility. 17891 toplevel : false, 17892 }); 17893 }); 17894 17895 AST_Toplevel.DEFMETHOD("mangle_names", function(options){ 17896 options = this._default_mangler_options(options); 17897 17898 // Never mangle arguments 17899 options.except.push('arguments'); 17900 17901 // We only need to mangle declaration nodes. Special logic wired 17902 // into the code generator will display the mangled name if it's 17903 // present (and for AST_SymbolRef-s it'll use the mangled name of 17904 // the AST_SymbolDeclaration that it points to). 17905 var lname = -1; 17906 var to_mangle = []; 17907 17908 if (options.cache) { 17909 this.globals.each(function(symbol){ 17910 if (options.except.indexOf(symbol.name) < 0) { 17911 to_mangle.push(symbol); 17912 } 17913 }); 17914 } 17915 17916 var tw = new TreeWalker(function(node, descend){ 17917 if (node instanceof AST_LabeledStatement) { 17918 // lname is incremented when we get to the AST_Label 17919 var save_nesting = lname; 17920 descend(); 17921 lname = save_nesting; 17922 return true; // don't descend again in TreeWalker 17923 } 17924 if (node instanceof AST_Scope) { 17925 var p = tw.parent(), a = []; 17926 node.variables.each(function(symbol){ 17927 if (options.except.indexOf(symbol.name) < 0) { 17928 a.push(symbol); 17929 } 17930 }); 17931 to_mangle.push.apply(to_mangle, a); 17932 return; 17933 } 17934 if (node instanceof AST_Label) { 17935 var name; 17936 do name = base54(++lname); while (!is_identifier(name)); 17937 node.mangled_name = name; 17938 return true; 17939 } 17940 if (options.screw_ie8 && node instanceof AST_SymbolCatch) { 17941 to_mangle.push(node.definition()); 17942 return; 17943 } 17944 }); 17945 this.walk(tw); 17946 to_mangle.forEach(function(def){ def.mangle(options) }); 17947 17948 if (options.cache) { 17949 options.cache.cname = this.cname; 17950 } 17951 }); 17952 17953 AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ 17954 options = this._default_mangler_options(options); 17955 var tw = new TreeWalker(function(node){ 17956 if (node instanceof AST_Constant) 17957 base54.consider(node.print_to_string()); 17958 else if (node instanceof AST_Return) 17959 base54.consider("return"); 17960 else if (node instanceof AST_Throw) 17961 base54.consider("throw"); 17962 else if (node instanceof AST_Continue) 17963 base54.consider("continue"); 17964 else if (node instanceof AST_Break) 17965 base54.consider("break"); 17966 else if (node instanceof AST_Debugger) 17967 base54.consider("debugger"); 17968 else if (node instanceof AST_Directive) 17969 base54.consider(node.value); 17970 else if (node instanceof AST_While) 17971 base54.consider("while"); 17972 else if (node instanceof AST_Do) 17973 base54.consider("do while"); 17974 else if (node instanceof AST_If) { 17975 base54.consider("if"); 17976 if (node.alternative) base54.consider("else"); 17977 } 17978 else if (node instanceof AST_Var) 17979 base54.consider("var"); 17980 else if (node instanceof AST_Const) 17981 base54.consider("const"); 17982 else if (node instanceof AST_Lambda) 17983 base54.consider("function"); 17984 else if (node instanceof AST_For) 17985 base54.consider("for"); 17986 else if (node instanceof AST_ForIn) 17987 base54.consider("for in"); 17988 else if (node instanceof AST_Switch) 17989 base54.consider("switch"); 17990 else if (node instanceof AST_Case) 17991 base54.consider("case"); 17992 else if (node instanceof AST_Default) 17993 base54.consider("default"); 17994 else if (node instanceof AST_With) 17995 base54.consider("with"); 17996 else if (node instanceof AST_ObjectSetter) 17997 base54.consider("set" + node.key); 17998 else if (node instanceof AST_ObjectGetter) 17999 base54.consider("get" + node.key); 18000 else if (node instanceof AST_ObjectKeyVal) 18001 base54.consider(node.key); 18002 else if (node instanceof AST_New) 18003 base54.consider("new"); 18004 else if (node instanceof AST_This) 18005 base54.consider("this"); 18006 else if (node instanceof AST_Try) 18007 base54.consider("try"); 18008 else if (node instanceof AST_Catch) 18009 base54.consider("catch"); 18010 else if (node instanceof AST_Finally) 18011 base54.consider("finally"); 18012 else if (node instanceof AST_Symbol && node.unmangleable(options)) 18013 base54.consider(node.name); 18014 else if (node instanceof AST_Unary || node instanceof AST_Binary) 18015 base54.consider(node.operator); 18016 else if (node instanceof AST_Dot) 18017 base54.consider(node.property); 18018 }); 18019 this.walk(tw); 18020 base54.sort(); 18021 }); 18022 18023 var base54 = (function() { 18024 var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; 18025 var chars, frequency; 18026 function reset() { 18027 frequency = Object.create(null); 18028 chars = string.split("").map(function(ch){ return ch.charCo
18028deAt(0) }); 18029 chars.forEach(function(ch){ frequency[ch] = 0 }); 18030 } 18031 base54.consider = function(str){ 18032 for (var i = str.length; --i >= 0;) { 18033 var code = str.charCodeAt(i); 18034 if (code in frequency) ++frequency[code]; 18035 } 18036 }; 18037 base54.sort = function() { 18038 chars = mergeSort(chars, function(a, b){ 18039 if (is_digit(a) && !is_digit(b)) return 1; 18040 if (is_digit(b) && !is_digit(a)) return -1; 18041 return frequency[b] - frequency[a]; 18042 }); 18043 }; 18044 base54.reset = reset; 18045 reset(); 18046 base54.get = function(){ return chars }; 18047 base54.freq = function(){ return frequency }; 18048 function base54(num) { 18049 var ret = "", base = 54; 18050 num++; 18051 do { 18052 num--; 18053 ret += String.fromCharCode(chars[num % base]); 18054 num = Math.floor(num / base); 18055 base = 64; 18056 } while (num > 0); 18057 return ret; 18058 }; 18059 return base54; 18060 })(); 18061 18062 AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ 18063 options = defaults(options, { 18064 assign_to_global : true, 18065 eval : true, 18066 func_arguments : true, 18067 nested_defuns : true, 18068 undeclared : false, // this makes a lot of noise 18069 unreferenced : true, 18070 }); 18071 var tw = new TreeWalker(function(node){ 18072 if (options.undeclared 18073 && node instanceof AST_SymbolRef 18074 && node.undeclared()) 18075 { 18076 // XXX: this also warns about JS standard names, 18077 // i.e. Object, Array, parseInt etc. Should add a list of 18078 // exceptions. 18079 AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { 18080 name: node.name, 18081 file: node.start.file, 18082 line: node.start.line, 18083 col: node.start.col 18084 }); 18085 } 18086 if (options.assign_to_global) 18087 { 18088 var sym = null; 18089 if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) 18090 sym = node.left; 18091 else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) 18092 sym = node.init; 18093 if (sym 18094 && (sym.undeclared() 18095 || (sym.global() && sym.scope !== sym.definition().scope))) { 18096 AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { 18097 msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", 18098 name: sym.name, 18099 file: sym.start.file, 18100 line: sym.start.line, 18101 col: sym.start.col 18102 }); 18103 } 18104 } 18105 if (options.eval 18106 && node instanceof AST_SymbolRef 18107 && node.undeclared() 18108 && node.name == "eval") { 18109 AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); 18110 } 18111 if (options.unreferenced 18112 && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) 18113 && !(node instanceof AST_SymbolCatch) 18114 && node.unreferenced()) { 18115 AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { 18116 type: node instanceof AST_Label ? "Label" : "Symbol", 18117 name: node.name, 18118 file: node.start.file, 18119 line: node.start.line, 18120 col: node.start.col 18121 }); 18122 } 18123 if (options.func_arguments 18124 && node instanceof AST_Lambda 18125 && node.uses_arguments) { 18126 AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { 18127 name: node.name ? node.name.name : "anonymous", 18128 file: node.start.file, 18129 line: node.start.line, 18130 col: node.start.col 18131 }); 18132 } 18133 if (options.nested_defuns 18134 && node instanceof AST_Defun 18135 && !(tw.parent() instanceof AST_Scope)) { 18136 AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { 18137 name: node.name.name, 18138 type: tw.parent().TYPE, 18139 file: node.start.file, 18140 line: node.start.line, 18141 col: node.start.col 18142 }); 18143 } 18144 }); 18145 this.walk(tw); 18146 }); 18147 18148 /*********************************************************************** 18149 18150 A JavaScript tokenizer / parser / beautifier / compressor. 18151 https://github.com/mishoo/UglifyJS2 18152 18153 -------------------------------- (C) --------------------------------- 18154 18155 Author: Mihai Bazon 18156 <[email protected]> 18157 http://mihai.bazon.net/blog 18158 18159 Distributed under the BSD license: 18160 18161 Copyright 2012 (c) Mihai Bazon <[email protected]> 18162 18163 Redistribution and use in source and binary forms, with or without 18164 modification, are permitted provided that the following conditions 18165 are met: 18166 18167 * Redistributions of source code must retain the above 18168 copyright notice, this list of conditions and the following 18169 disclaimer. 18170 18171 * Redistributions in binary form must reproduce the above 18172 copyright notice, this list of conditions and the following 18173 disclaimer in the documentation and/or other materials 18174 provided with the distribution. 18175 18176 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 18177 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18178 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18179 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 18180 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
18181 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18182 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18183 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 18184 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 18185 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 18186 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18187 SUCH DAMAGE. 18188 18189 ***********************************************************************/ 18190 18191 "use strict"; 18192 18193 var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/; 18194 18195 function is_some_comments(comment) { 18196 // multiline comment 18197 return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value); 18198 } 18199 18200 function OutputStream(options) { 18201 18202 options = defaults(options, { 18203 ascii_only : false, 18204 beautify : false, 18205 bracketize : false, 18206 comments : false, 18207 indent_level : 4, 18208 indent_start : 0, 18209 inline_script : true, 18210 keep_quoted_props: false, 18211 max_line_len : false, 18212 preamble : null, 18213 preserve_line : false, 18214 quote_keys : false, 18215 quote_style : 0, 18216 screw_ie8 : true, 18217 semicolons : true, 18218 shebang : true, 18219 source_map : null, 18220 space_colon : true, 18221 unescape_regexps : false, 18222 width : 80, 18223 wrap_iife : false, 18224 }, true); 18225 18226 // Convert comment option to RegExp if neccessary and set up comments filter 18227 var comment_filter = return_false; // Default case, throw all comments away 18228 if (options.comments) { 18229 var comments = options.comments; 18230 if (typeof options.comments === "string" && /^\/.*\/[a-zA-Z]*$/.test(options.comments)) { 18231 var regex_pos = options.comments.lastIndexOf("/"); 18232 comments = new RegExp( 18233 options.comments.substr(1, regex_pos - 1), 18234 options.comments.substr(regex_pos + 1) 18235 ); 18236 } 18237 if (comments instanceof RegExp) { 18238 comment_filter = function(comment) { 18239 return comment.type != "comment5" && comments.test(comment.value); 18240 }; 18241 } 18242 else if (typeof comments === "function") { 18243 comment_filter = function(comment) { 18244 return comment.type != "comment5" && comments(this, comment); 18245 }; 18246 } 18247 else if (comments === "some") { 18248 comment_filter = is_some_comments; 18249 } else { // NOTE includes "all" option 18250 comment_filter = return_true; 18251 } 18252 } 18253 18254 var indentation = 0; 18255 var current_col = 0; 18256 var current_line = 1; 18257 var current_pos = 0; 18258 var OUTPUT = ""; 18259 18260 function to_ascii(str, identifier) { 18261 return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) { 18262 var code = ch.charCodeAt(0).toString(16); 18263 if (code.length <= 2 && !identifier) { 18264 while (code.length < 2) code = "0" + code; 18265 return "\\x" + code; 18266 } else { 18267 while (code.length < 4) code = "0" + code; 18268 return "\\u" + code; 18269 } 18270 }); 18271 }; 18272 18273 function make_string(str, quote) { 18274 var dq = 0, sq = 0; 18275 str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, 18276 function(s, i){ 18277 switch (s) { 18278 case '"': ++dq; return '"';
18279 case "'": ++sq; return "'"; 18280 case "\\": return "\\\\"; 18281 case "\n": return "\\n"; 18282 case "\r": return "\\r"; 18283 case "\t": return "\\t"; 18284 case "\b": return "\\b"; 18285 case "\f": return "\\f"; 18286 case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B"; 18287 case "\u2028": return "\\u2028"; 18288 case "\u2029": return "\\u2029"; 18289 case "\ufeff": return "\\ufeff"; 18290 case "\0": 18291 return /[0-7]/.test(str.charAt(i+1)) ? "\\x00" : "\\0"; 18292 } 18293 return s; 18294 }); 18295 function quote_single() { 18296 return "'" + str.replace(/\x27/g, "\\'") + "'"; 18297 } 18298 function quote_double() { 18299 return '"' + str.replace(/\x22/g, '\\"') + '"'; 18300 } 18301 if (options.ascii_only) str = to_ascii(str); 18302 switch (options.quote_style) { 18303 case 1: 18304 return quote_single(); 18305 case 2: 18306 return quote_double(); 18307 case 3: 18308 return quote == "'" ? quote_single() : quote_double(); 18309 default: 18310 return dq > sq ? quote_single() : quote_double(); 18311 } 18312 }; 18313 18314 function encode_string(str, quote) { 18315 var ret = make_string(str, quote); 18316 if (options.inline_script) { 18317 ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); 18318 ret = ret.replace(/\x3c!--/g, "\\x3c!--"); 18319 ret = ret.replace(/--\x3e/g, "--\\x3e"); 18320 } 18321 return ret; 18322 }; 18323 18324 function make_name(name) { 18325 name = name.toString(); 18326 if (options.ascii_only) 18327 name = to_ascii(name, true); 18328 return name; 18329 }; 18330 18331 function make_indent(back) { 18332 return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); 18333 }; 18334 18335 /* -----[ beautification/minification ]----- */ 18336 18337 var might_need_space = false; 18338 var might_need_semicolon = false; 18339 var might_add_newline = 0; 18340 var last = ""; 18341 18342 var ensure_line_len = options.max_line_len ? function() { 18343 if (current_col > options.max_line_len) { 18344 if (might_add_newline) { 18345 var left = OUTPUT.slice(0, might_add_newline); 18346 var right = OUTPUT.slice(might_add_newline); 18347 OUTPUT = left + "\n" + right; 18348 current_line++; 18349 current_pos++; 18350 current_col = right.length; 18351 } 18352 if (current_col > options.max_line_len) { 18353 AST_Node.warn("Output exceeds {max_line_len} characters", options); 18354 } 18355 } 18356 might_add_newline = 0; 18357 } : noop; 18358 18359 var requireSemicolonChars = makePredicate("( [ + * / - , ."); 18360 18361 function print(str) { 18362 str = String(str); 18363 var ch = str.charAt(0); 18364 var prev = last.charAt(last.length - 1); 18365 if (might_need_semicolon) { 18366 might_need_semicolon = false; 18367 18368 if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") { 18369 if (options.semicolons || requireSemicolonChars(ch)) { 18370 OUTPUT += ";";
18371 current_col++; 18372 current_pos++; 18373 } else { 18374 ensure_line_len(); 18375 OUTPUT += "\n"; 18376 current_pos++; 18377 current_line++; 18378 current_col = 0; 18379 18380 if (/^\s+$/.test(str)) { 18381 // reset the semicolon flag, since we didn't print one 18382 // now and might still have to later 18383 might_need_semicolon = true; 18384 } 18385 } 18386 18387 if (!options.beautify) 18388 might_need_space = false; 18389 } 18390 } 18391 18392 if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { 18393 var target_line = stack[stack.length - 1].start.line; 18394 while (current_line < target_line) { 18395 ensure_line_len(); 18396 OUTPUT += "\n"; 18397 current_pos++; 18398 current_line++; 18399 current_col = 0; 18400 might_need_space = false; 18401 } 18402 } 18403 18404 if (might_need_space) { 18405 if ((is_identifier_char(prev) 18406 && (is_identifier_char(ch) || ch == "\\")) 18407 || (ch == "/" && ch == prev) 18408 || ((ch == "+" || ch == "-") && ch == last)) 18409 { 18410 OUTPUT += " "; 18411 current_col++; 18412 current_pos++; 18413 } 18414 might_need_space = false; 18415 } 18416 OUTPUT += str; 18417 current_pos += str.length; 18418 var a = str.split(/\r?\n/), n = a.length - 1; 18419 current_line += n; 18420 current_col += a[0].length; 18421 if (n > 0) { 18422 ensure_line_len(); 18423 current_col = a[n].length; 18424 } 18425 last = str; 18426 }; 18427 18428 var space = options.beautify ? function() { 18429 print(" "); 18430 } : function() { 18431 might_need_space = true; 18432 }; 18433 18434 var indent = options.beautify ? function(half) { 18435 if (options.beautify) { 18436 print(make_indent(half ? 0.5 : 0)); 18437 } 18438 } : noop; 18439 18440 var with_indent = options.beautify ? function(col, cont) { 18441 if (col === true) col = next_indent(); 18442 var save_indentation = indentation; 18443 indentation = col; 18444 var ret = cont(); 18445 indentation = save_indentation; 18446 return ret; 18447 } : function(col, cont) { return cont() }; 18448 18449 var newline = options.beautify ? function() { 18450 print("\n"); 18451 } : options.max_line_len ? function() { 18452 ensure_line_len(); 18453 might_add_newline = OUTPUT.length; 18454 } : noop; 18455 18456 var semicolon = options.beautify ? function() { 18457 print(";"); 18458 } : function() { 18459 might_need_semicolon = true; 18460 }; 18461 18462 function force_semicolon() { 18463 might_need_semicolon = false; 18464 print(";"); 18465 }; 18466 18467 function next_indent() { 18468 return indentation + options.indent_level; 18469 }; 18470 18471 function with_block(cont) { 18472 var ret; 18473 print("{"); 18474 newline(); 18475 with_indent(next_indent(), function(){ 18476 ret = cont(); 18477 }); 18478 indent(); 18479 print("}"); 18480 return ret; 18481 }; 18482 18483 function with_parens(cont) { 18484 print("("); 18485 //XXX: still nice to have that for argument lists 18486 //var ret = with_indent(current_col, cont); 18487 var ret = cont(); 18488 print(")"); 18489 return ret; 18490 }; 18491
18492 function with_square(cont) { 18493 print("["); 18494 //var ret = with_indent(current_col, cont); 18495 var ret = cont(); 18496 print("]"); 18497 return ret; 18498 }; 18499 18500 function comma() { 18501 print(","); 18502 space(); 18503 }; 18504 18505 function colon() { 18506 print(":"); 18507 if (options.space_colon) space(); 18508 }; 18509 18510 var add_mapping = options.source_map ? function(token, name) { 18511 try { 18512 if (token) options.source_map.add( 18513 token.file || "?", 18514 current_line, current_col, 18515 token.line, token.col, 18516 (!name && token.type == "name") ? token.value : name 18517 ); 18518 } catch(ex) { 18519 AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} â {cline},{ccol} [{name}]", { 18520 file: token.file, 18521 line: token.line, 18522 col: token.col, 18523 cline: current_line, 18524 ccol: current_col, 18525 name: name || "" 18526 }) 18527 } 18528 } : noop; 18529 18530 function get() { 18531 if (might_add_newline) { 18532 ensure_line_len(); 18533 } 18534 return OUTPUT; 18535 }; 18536 18537 var stack = []; 18538 return { 18539 get : get, 18540 toString : get, 18541 indent : indent, 18542 indentation : function() { return indentation }, 18543 current_width : function() { return current_col - indentation }, 18544 should_break : function() { return options.width && this.current_width() >= options.width }, 18545 newline : newline, 18546 print : print, 18547 space : space, 18548 comma : comma, 18549 colon : colon, 18550 last : function() { return last }, 18551 semicolon : semicolon, 18552 force_semicolon : force_semicolon, 18553 to_ascii : to_ascii, 18554 print_name : function(name) { print(make_name(name)) }, 18555 print_string : function(str, quote, escape_directive) { 18556 var encoded = encode_string(str, quote); 18557 if (escape_directive === true && encoded.indexOf("\\") === -1) { 18558 // Insert semicolons to break directive prologue 18559 if (!EXPECT_DIRECTIVE.test(OUTPUT)) { 18560 force_semicolon(); 18561 } 18562 force_semicolon(); 18563 } 18564 print(encoded); 18565 }, 18566 encode_string : encode_string, 18567 next_indent : next_indent, 18568 with_indent : with_indent, 18569 with_block : with_block, 18570 with_parens : with_parens, 18571 with_square : with_square, 18572 add_mapping : add_mapping, 18573 option : function(opt) { return options[opt] }, 18574 comment_filter : comment_filter, 18575 line : function() { return current_line }, 18576 col : function() { return current_col }, 18577 pos : function() { return current_pos }, 18578 push_node : function(node) { stack.push(node) }, 18579 pop_node : function() { return stack.pop() }, 18580 parent : function(n) { 18581 return stack[stack.length - 2 - (n || 0)]; 18582 } 18583 }; 18584 18585 }; 18586 18587 /* -----[ code generators ]----- */ 18588 18589 (function(){ 18590 18591 /* -----[ utils ]----- */ 18592 18593 function DEFPRINT(nodetype, generator) { 18594 nodetype.DEFMETHOD("_codegen", generator); 18595 }; 18596 18597 var use_asm = false;
18598 var in_directive = false; 18599 18600 AST_Node.DEFMETHOD("print", function(stream, force_parens){ 18601 var self = this, generator = self._codegen, prev_use_asm = use_asm; 18602 if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) { 18603 use_asm = true; 18604 } 18605 function doit() { 18606 self.add_comments(stream); 18607 self.add_source_map(stream); 18608 generator(self, stream); 18609 } 18610 stream.push_node(self); 18611 if (force_parens || self.needs_parens(stream)) { 18612 stream.with_parens(doit); 18613 } else { 18614 doit(); 18615 } 18616 stream.pop_node(); 18617 if (self instanceof AST_Scope) { 18618 use_asm = prev_use_asm; 18619 } 18620 }); 18621 18622 AST_Node.DEFMETHOD("print_to_string", function(options){ 18623 var s = OutputStream(options); 18624 if (!options) s._readonly = true; 18625 this.print(s); 18626 return s.get(); 18627 }); 18628 18629 /* -----[ comments ]----- */ 18630 18631 AST_Node.DEFMETHOD("add_comments", function(output){ 18632 if (output._readonly) return; 18633 var self = this; 18634 var start = self.start; 18635 if (start && !start._comments_dumped) { 18636 start._comments_dumped = true; 18637 var comments = start.comments_before || []; 18638 18639 // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 18640 // and https://github.com/mishoo/UglifyJS2/issues/372 18641 if (self instanceof AST_Exit && self.value) { 18642 self.value.walk(new TreeWalker(function(node){ 18643 if (node.start && node.start.comments_before) { 18644 comments = comments.concat(node.start.comments_before); 18645 node.start.comments_before = []; 18646 } 18647 if (node instanceof AST_Function || 18648 node instanceof AST_Array || 18649 node instanceof AST_Object) 18650 { 18651 return true; // don't go inside. 18652 } 18653 })); 18654 } 18655 18656 if (output.pos() == 0) { 18657 if (comments.length > 0 && output.option("shebang") && comments[0].type == "comment5") { 18658 output.print("#!" + comments.shift().value + "\n"); 18659 output.indent(); 18660 } 18661 var preamble = output.option("preamble"); 18662 if (preamble) { 18663 output.print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n")); 18664 } 18665 } 18666 18667 comments = comments.filter(output.comment_filter, self); 18668 18669 // Keep single line comments after nlb, after nlb 18670 if (!output.option("beautify") && comments.length > 0 && 18671 /comment[134]/.test(comments[0].type) && 18672 output.col() !== 0 && comments[0].nlb) 18673 { 18674 output.print("\n"); 18675 } 18676 18677 comments.forEach(function(c){ 18678 if (/comment[134]/.test(c.type)) { 18679 output.print("//" + c.value + "\n"); 18680 output.indent(); 18681 }
18682 else if (c.type == "comment2") { 18683 output.print("/*" + c.value + "*/"); 18684 if (start.nlb) { 18685 output.print("\n"); 18686 output.indent(); 18687 } else { 18688 output.space(); 18689 } 18690 } 18691 }); 18692 } 18693 }); 18694 18695 /* -----[ PARENTHESES ]----- */ 18696 18697 function PARENS(nodetype, func) { 18698 if (Array.isArray(nodetype)) { 18699 nodetype.forEach(function(nodetype){ 18700 PARENS(nodetype, func); 18701 }); 18702 } else { 18703 nodetype.DEFMETHOD("needs_parens", func); 18704 } 18705 }; 18706 18707 PARENS(AST_Node, function(){ 18708 return false; 18709 }); 18710 18711 // a function expression needs parens around it when it's provably 18712 // the first token to appear in a statement. 18713 PARENS(AST_Function, function(output){ 18714 if (first_in_statement(output)) { 18715 return true; 18716 } 18717 18718 if (output.option('wrap_iife')) { 18719 var p = output.parent(); 18720 return p instanceof AST_Call && p.expression === this; 18721 } 18722 18723 return false; 18724 }); 18725 18726 // same goes for an object literal, because otherwise it would be 18727 // interpreted as a block of code. 18728 PARENS(AST_Object, function(output){ 18729 return first_in_statement(output); 18730 }); 18731 18732 PARENS(AST_Unary, function(output){ 18733 var p = output.parent(); 18734 return p instanceof AST_PropAccess && p.expression === this 18735 || p instanceof AST_Call && p.expression === this; 18736 }); 18737 18738 PARENS(AST_Seq, function(output){ 18739 var p = output.parent(); 18740 return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) 18741 || p instanceof AST_Unary // !(foo, bar, baz) 18742 || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 18743 || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 18744 || p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2 18745 || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] 18746 || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 18747 || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) 18748 * ==> 20 (side effect, set a := 10 and b := 20) */ 18749 ; 18750 }); 18751 18752 PARENS(AST_Binary, function(output){ 18753 var p = output.parent(); 18754 // (foo && bar)() 18755 if (p instanceof AST_Call && p.expression === this) 18756 return true; 18757 // typeof (foo && bar) 18758 if (p instanceof AST_Unary) 18759 return true; 18760 // (foo && bar)["prop"], (foo && bar).prop 18761 if (p instanceof AST_PropAccess && p.expression === this) 18762 return true; 18763 // this deals with precedence: 3 * (2 + 1) 18764 if (p instanceof AST_Binary) { 18765 var po = p.operator, pp = PRECEDENCE[po]; 18766 var so = this.operator, sp = PRECEDENCE[so]; 18767 if (pp > sp 18768 || (pp == sp 18769 && this === p.right)) { 18770 return true; 18771 } 18772 } 18773 }); 18774 18775 PARENS(AST_PropAccess, function(output){ 18776 var p = output.parent(); 18777 if (p instanceof AST_New && p.expression === this) { 18778 // i.e. new (foo.bar().baz) 18779 // 18780 // if there's one call into this subtree, then we need 18781 // parens around it too, otherwise the call will be 18782 // interpreted as passing the arguments to the upper New 18783 // expression. 18784 try { 18785 this.walk(new TreeWalker(function(node){ 18786 if (node instanceof AST_Call) throw p; 18787 })); 18788 } catch(ex) { 18789 if (ex !== p) throw ex; 18790 return true; 18791 } 18792 } 18793 }); 18794 18795 PARENS(AST_Call, function(output){ 18796 var p = output.parent(), p1; 18797 if (p instanceof AST_New && p.expression === this) 18798 return true; 18799 18800 // workaround for Safari bug. 18801 // https://bugs.webkit.org/show_bug.cgi?id=123506 18802 return this.expression instanceof AST_Function 18803 && p instanceof AST_PropAccess 18804 && p.expression === this 18805 && (p1 = output.parent(1)) instanceof AST_Assign 18806 && p1.left === p; 18807 }); 18808 18809 PARENS(AST_New, function(output){ 18810 var p = output.parent(); 18811 if (!need_constructor_parens(this, output) 18812 && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() 18813 || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) 18814 return true; 18815 }); 18816 18817 PARENS(AST_Number, function(output){ 18818 var p = output.parent(); 18819 if (p instanceof AST_PropAccess && p.expression === this) { 18820 var value = this.getValue(); 18821 if (value < 0 || /^0/.test(make_num(value))) { 18822 return true; 18823 } 18824 } 18825 }); 18826 18827 PARENS([ AST_Assign, AST_Conditional ], function (output){ 18828 var p = output.parent(); 18829 // !(a = false) â true 18830 if (p instanceof AST_Unary) 18831 return true; 18832 // 1 + (a = 2) + 3 â 6, side effect setting a = 2 18833 if (p instanceof AST_Binary && !(p instanceof AST_Assign)
18833) 18834 return true; 18835 // (a = func)() âorâ new (a = Object)() 18836 if (p instanceof AST_Call && p.expression === this) 18837 return true; 18838 // (a = foo) ? bar : baz 18839 if (p instanceof AST_Conditional && p.condition === this) 18840 return true; 18841 // (a = foo)["prop"] âorâ (a = foo).prop 18842 if (p instanceof AST_PropAccess && p.expression === this) 18843 return true; 18844 }); 18845 18846 /* -----[ PRINTERS ]----- */ 18847 18848 DEFPRINT(AST_Directive, function(self, output){ 18849 output.print_string(self.value, self.quote); 18850 output.semicolon(); 18851 }); 18852 DEFPRINT(AST_Debugger, function(self, output){ 18853 output.print("debugger"); 18854 output.semicolon(); 18855 }); 18856 18857 /* -----[ statements ]----- */ 18858 18859 function display_body(body, is_toplevel, output, allow_directives) { 18860 var last = body.length - 1; 18861 in_directive = allow_directives; 18862 body.forEach(function(stmt, i){ 18863 if (in_directive === true && !(stmt instanceof AST_Directive || 18864 stmt instanceof AST_EmptyStatement || 18865 (stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String) 18866 )) { 18867 in_directive = false; 18868 } 18869 if (!(stmt instanceof AST_EmptyStatement)) { 18870 output.indent(); 18871 stmt.print(output); 18872 if (!(i == last && is_toplevel)) { 18873 output.newline(); 18874 if (is_toplevel) output.newline(); 18875 } 18876 } 18877 if (in_directive === true && 18878 stmt instanceof AST_SimpleStatement && 18879 stmt.body instanceof AST_String 18880 ) { 18881 in_directive = false; 18882 } 18883 }); 18884 in_directive = false; 18885 }; 18886 18887 AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ 18888 force_statement(this.body, output); 18889 }); 18890 18891 DEFPRINT(AST_Statement, function(self, output){ 18892 self.body.print(output); 18893 output.semicolon(); 18894 }); 18895 DEFPRINT(AST_Toplevel, function(self, output){ 18896 display_body(self.body, true, output, true); 18897 output.print(""); 18898 }); 18899 DEFPRINT(AST_LabeledStatement, function(self, output){ 18900 self.label.print(output); 18901 output.colon(); 18902 self.body.print(output); 18903 }); 18904 DEFPRINT(AST_SimpleStatement, function(self, output){ 18905 self.body.print(output); 18906 output.semicolon(); 18907 }); 18908 function print_bracketed(body, output, allow_directives) { 18909 if (body.length > 0) output.with_block(function(){ 18910 display_body(body, false, output, allow_directives); 18911 }); 18912 else output.print("{}"); 18913 }; 18914 DEFPRINT(AST_BlockStatement, function(self, output){ 18915 print_bracketed(self.body, output); 18916 }); 18917 DEFPRINT(AST_EmptyStatement, function(self, output){ 18918 output.semicolon(); 18919 }); 18920 DEFPRINT(AST_Do, function(self, output){ 18921 output.print("do"); 18922 output.space(); 18923 make_block(self.body, output); 18924 output.space(); 18925 output.print("while"); 18926 output.space(); 18927 output.with_parens(function(){
vendor: 8,809 bytes, lines 18928-19131
18928 self.condition.print(output); 18929 }); 18930 output.semicolon(); 18931 }); 18932 DEFPRINT(AST_While, function(self, output){ 18933 output.print("while"); 18934 output.space(); 18935 output.with_parens(function(){ 18936 self.condition.print(output); 18937 }); 18938 output.space(); 18939 self._do_print_body(output); 18940 }); 18941 DEFPRINT(AST_For, function(self, output){ 18942 output.print("for"); 18943 output.space(); 18944 output.with_parens(function(){ 18945 if (self.init) { 18946 if (self.init instanceof AST_Definitions) { 18947 self.init.print(output); 18948 } else { 18949 parenthesize_for_noin(self.init, output, true); 18950 } 18951 output.print(";"); 18952 output.space(); 18953 } else { 18954 output.print(";"); 18955 } 18956 if (self.condition) { 18957 self.condition.print(output); 18958 output.print(";"); 18959 output.space(); 18960 } else { 18961 output.print(";"); 18962 } 18963 if (self.step) { 18964 self.step.print(output); 18965 } 18966 }); 18967 output.space(); 18968 self._do_print_body(output); 18969 }); 18970 DEFPRINT(AST_ForIn, function(self, output){ 18971 output.print("for"); 18972 output.space(); 18973 output.with_parens(function(){ 18974 self.init.print(output); 18975 output.space(); 18976 output.print("in"); 18977 output.space(); 18978 self.object.print(output); 18979 }); 18980 output.space(); 18981 self._do_print_body(output); 18982 }); 18983 DEFPRINT(AST_With, function(self, output){ 18984 output.print("with"); 18985 output.space(); 18986 output.with_parens(function(){ 18987 self.expression.print(output); 18988 }); 18989 output.space(); 18990 self._do_print_body(output); 18991 }); 18992 18993 /* -----[ functions ]----- */ 18994 AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ 18995 var self = this; 18996 if (!nokeyword) { 18997 output.print("function"); 18998 } 18999 if (self.name) { 19000 output.space(); 19001 self.name.print(output); 19002 } 19003 output.with_parens(function(){ 19004 self.argnames.forEach(function(arg, i){ 19005 if (i) output.comma(); 19006 arg.print(output); 19007 }); 19008 }); 19009 output.space(); 19010 print_bracketed(self.body, output, true); 19011 }); 19012 DEFPRINT(AST_Lambda, function(self, output){ 19013 self._do_print(output); 19014 }); 19015 19016 /* -----[ exits ]----- */ 19017 AST_Exit.DEFMETHOD("_do_print", function(output, kind){ 19018 output.print(kind); 19019 if (this.value) { 19020 output.space(); 19021 this.value.print(output); 19022 } 19023 output.semicolon(); 19024 }); 19025 DEFPRINT(AST_Return, function(self, output){ 19026 self._do_print(output, "return"); 19027 }); 19028 DEFPRINT(AST_Throw, function(self, output){ 19029 self._do_print(output, "throw"); 19030 }); 19031 19032 /* -----[ loop control ]----- */ 19033 AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ 19034 output.print(kind); 19035 if (this.label) { 19036 output.space(); 19037 this.label.print(output); 19038 } 19039 output.semicolon(); 19040 }); 19041 DEFPRINT(AST_Break, function(self, output){ 19042 self._do_print(output, "break"); 19043 }); 19044 DEFPRINT(AST_Continue, function(self, output){ 19045 self._do_print(output, "continue"); 19046 }); 19047 19048 /* -----[ if ]----- */ 19049 function make_then(self, output) { 19050 var b = self.body; 19051 if (output.option("bracketize") 19052 || !output.option("screw_ie8") && b instanceof AST_Do) 19053 return make_block(b, output); 19054 // The squeezer replaces "block"-s that contain only a single 19055 // statement with the statement itself; technically, the AST 19056 // is correct, but this can create problems when we output an 19057 // IF having an ELSE clause where the THEN clause ends in an 19058 // IF *without* an ELSE block (then the outer ELSE would refer 19059 // to the inner IF). This function checks for this case and 19060 // adds the block brackets if needed. 19061 if (!b) return output.force_semicolon(); 19062 while (true) { 19063 if (b instanceof AST_If) { 19064 if (!b.alternative) { 19065 make_block(self.body, output); 19066 return; 19067 } 19068 b = b.alternative; 19069 } 19070 else if (b instanceof AST_StatementWithBody) { 19071 b = b.body; 19072 } 19073 else break; 19074 } 19075 force_statement(self.body, output); 19076 }; 19077 DEFPRINT(AST_If, function(self, output){ 19078 output.print("if"); 19079 output.space(); 19080 output.with_parens(function(){ 19081 self.condition.print(output); 19082 }); 19083 output.space(); 19084 if (self.alternative) { 19085 make_then(self, output); 19086 output.space(); 19087 output.print("else"); 19088 output.space(); 19089 if (self.alternative instanceof AST_If) 19090 self.alternative.print(output); 19091 else 19092 force_statement(self.alternative, output); 19093 } else { 19094 self._do_print_body(output); 19095 } 19096 }); 19097 19098 /* -----[ switch ]----- */ 19099 DEFPRINT(AST_Switch, function(self, output){ 19100 output.print("switch"); 19101 output.space(); 19102 output.with_parens(function(){ 19103 self.expression.print(output); 19104 }); 19105 output.space(); 19106 var last = self.body.length - 1; 19107 if (last < 0) output.print("{}"); 19108 else output.with_block(function(){ 19109 self.body.forEach(function(branch, i){ 19110 output.indent(true); 19111 branch.print(output); 19112 if (i < last && branch.body.length > 0) 19113 output.newline(); 19114 }); 19115 }); 19116 }); 19117 AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ 19118 output.newline(); 19119 this.body.forEach(function(stmt){ 19120 output.indent(); 19121 stmt.print(output); 19122 output.newline(); 19123 }); 19124 }); 19125 DEFPRINT(AST_Default, function(self, output){ 19126 output.print("default:"); 19127 self._do_print_body(output); 19128 }); 19129 DEFPRINT(AST_Case, function(self, output){ 19130 output.print("case"); 19131 output.space();
19132 self.expression.print(output); 19133 output.print(":"); 19134 self._do_print_body(output); 19135 }); 19136 19137 /* -----[ exceptions ]----- */ 19138 DEFPRINT(AST_Try, function(self, output){ 19139 output.print("try"); 19140 output.space(); 19141 print_bracketed(self.body, output); 19142 if (self.bcatch) { 19143 output.space(); 19144 self.bcatch.print(output); 19145 } 19146 if (self.bfinally) { 19147 output.space(); 19148 self.bfinally.print(output); 19149 } 19150 }); 19151 DEFPRINT(AST_Catch, function(self, output){ 19152 output.print("catch"); 19153 output.space(); 19154 output.with_parens(function(){ 19155 self.argname.print(output); 19156 }); 19157 output.space(); 19158 print_bracketed(self.body, output); 19159 }); 19160 DEFPRINT(AST_Finally, function(self, output){ 19161 output.print("finally"); 19162 output.space(); 19163 print_bracketed(self.body, output); 19164 }); 19165 19166 /* -----[ var/const ]----- */ 19167 AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ 19168 output.print(kind); 19169 output.space(); 19170 this.definitions.forEach(function(def, i){ 19171 if (i) output.comma(); 19172 def.print(output); 19173 }); 19174 var p = output.parent(); 19175 var in_for = p instanceof AST_For || p instanceof AST_ForIn; 19176 var avoid_semicolon = in_for && p.init === this; 19177 if (!avoid_semicolon) 19178 output.semicolon(); 19179 }); 19180 DEFPRINT(AST_Var, function(self, output){ 19181 self._do_print(output, "var"); 19182 }); 19183 DEFPRINT(AST_Const, function(self, output){ 19184 self._do_print(output, "const"); 19185 }); 19186 19187 function parenthesize_for_noin(node, output, noin) { 19188 if (!noin) node.print(output); 19189 else try { 19190 // need to take some precautions here: 19191 // https://github.com/mishoo/UglifyJS2/issues/60 19192 node.walk(new TreeWalker(function(node){ 19193 if (node instanceof AST_Binary && node.operator == "in") 19194 throw output; 19195 })); 19196 node.print(output); 19197 } catch(ex) { 19198 if (ex !== output) throw ex; 19199 node.print(output, true); 19200 } 19201 }; 19202 19203 DEFPRINT(AST_VarDef, function(self, output){ 19204 self.name.print(output); 19205 if (self.value) { 19206 output.space(); 19207 output.print("="); 19208 output.space(); 19209 var p = output.parent(1); 19210 var noin = p instanceof AST_For || p instanceof AST_ForIn; 19211 parenthesize_for_noin(self.value, output, noin); 19212 } 19213 }); 19214 19215 /* -----[ other expressions ]----- */ 19216 DEFPRINT(AST_Call, function(self, output){ 19217 self.expression.print(output); 19218 if (self instanceof AST_New && !need_constructor_parens(self, output)) 19219 return; 19220 output.with_parens(function(){ 19221 self.args.forEach(function(expr, i){ 19222 if (i) output.comma(); 19223 expr.print(output); 19224 }); 19225 }); 19226 }); 19227 DEFPRINT(AST_New, function(self, output){ 19228 output.print("new"); 19229 output.space(); 19230 AST_Call.prototype._codegen(self, output); 19231 }); 19232 19233 AST_Seq.DEFMETHOD("_do_print", function(output){ 19234 this.car.print(output); 19235 if (this.cdr) { 19236 output.comma(); 19237 if (output.should_break()) { 19238 output.newline(); 19239 output.indent(); 19240 } 19241 this.cdr.print(output); 19242 } 19243 }); 19244 DEFPRINT(AST_Seq, function(self, output){ 19245 self._do_print(output); 19246 // var p = output.parent(); 19247 // if (p instanceof AST_Statement) { 19248 // output.with_indent(output.next_indent(), function(){ 19249 // self._do_print(output); 19250 // }); 19251 // } else { 19252 // self._do_print(output); 19253 // } 19254 }); 19255 DEFPRINT(AST_Dot, function(self, output){ 19256 var expr = self.expression; 19257 expr.print(output); 19258 if (expr instanceof AST_Number && expr.getValue() >= 0) { 19259 if (!/[xa-f.)]/i.test(output.last())) { 19260 output.print("."); 19261 } 19262 } 19263 output.print("."); 19264 // the name after dot would be mapped about here. 19265 output.add_mapping(self.end); 19266 output.print_name(self.property); 19267 }); 19268 DEFPRINT(AST_Sub, function(self, output){
19269 self.expression.print(output); 19270 output.print("["); 19271 self.property.print(output); 19272 output.print("]"); 19273 }); 19274 DEFPRINT(AST_UnaryPrefix, function(self, output){ 19275 var op = self.operator; 19276 output.print(op); 19277 if (/^[a-z]/i.test(op) 19278 || (/[+-]$/.test(op) 19279 && self.expression instanceof AST_UnaryPrefix 19280 && /^[+-]/.test(self.expression.operator))) { 19281 output.space(); 19282 } 19283 self.expression.print(output); 19284 }); 19285 DEFPRINT(AST_UnaryPostfix, function(self, output){ 19286 self.expression.print(output); 19287 output.print(self.operator); 19288 }); 19289 DEFPRINT(AST_Binary, function(self, output){ 19290 var op = self.operator; 19291 self.left.print(output); 19292 if (op[0] == ">" /* ">>" ">>>" ">" ">=" */ 19293 && self.left instanceof AST_UnaryPostfix 19294 && self.left.operator == "--") { 19295 // space is mandatory to avoid outputting --> 19296 output.print(" "); 19297 } else { 19298 // the space is optional depending on "beautify" 19299 output.space(); 19300 } 19301 output.print(op); 19302 if ((op == "<" || op == "<<") 19303 && self.right instanceof AST_UnaryPrefix 19304 && self.right.operator == "!" 19305 && self.right.expression instanceof AST_UnaryPrefix 19306 && self.right.expression.operator == "--") { 19307 // space is mandatory to avoid outputting <!-- 19308 output.print(" "); 19309 } else { 19310 // the space is optional depending on "beautify" 19311 output.space(); 19312 } 19313 self.right.print(output); 19314 }); 19315 DEFPRINT(AST_Conditional, function(self, output){ 19316 self.condition.print(output); 19317 output.space(); 19318 output.print("?"); 19319 output.space(); 19320 self.consequent.print(output); 19321 output.space(); 19322 output.colon(); 19323 self.alternative.print(output); 19324 }); 19325 19326 /* -----[ literals ]----- */ 19327 DEFPRINT(AST_Array, function(self, output){ 19328 output.with_square(function(){ 19329 var a = self.elements, len = a.length; 19330 if (len > 0) output.space(); 19331 a.forEach(function(exp, i){ 19332 if (i) output.comma(); 19333 exp.print(output); 19334 // If the final element is a hole, we need to make sure it 19335 // doesn't look like a trailing comma, by inserting an actual 19336 // trailing comma. 19337 if (i === len - 1 && exp instanceof AST_Hole) 19338 output.comma(); 19339 }); 19340 if (len > 0) output.space(); 19341 }); 19342 }); 19343 DEFPRINT(AST_Object, function(self, output){ 19344 if (self.properties.length > 0) output.with_block(function(){ 19345 self.properties.forEach(function(prop, i){ 19346 if (i) { 19347 output.print(","); 19348 output.newline(); 19349 } 19350 output.indent(); 19351 prop.print(output); 19352 }); 19353 output.newline(); 19354 }); 19355 else output.print("{}"); 19356 }); 19357 19358 function print_property_name(key, quote, output) { 19359 if (output.option("quote_keys")) { 19360 output.print_string(key + ""); 19361 } else if ((typeof key == "number" 19362 || !output.option("beautify") 19363 && +key + "" == key) 19364 && parseFloat(key) >= 0) { 19365 output.print(make_num(key)); 19366 } else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) { 19367 if (quote && output.option("keep_quoted_props")) { 19368 output.print_string(key, quote); 19369 } else { 19370 output.print_name(key); 19371 } 19372 } else { 19373 output.print_string(key, quote); 19374 } 19375 } 19376 19377 DEFPRINT(AST_ObjectKeyVal, function(self, output){ 19378 print_property_name(self.key, self.quote, output); 19379 output.colon(); 19380 self.value.print(output); 19381 }); 19382 AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) { 19383 output.print(type); 19384 output.space(); 19385 print_property_name(this.key.name, this.quote, output); 19386 this.value._do_print(output, true); 19387 }); 19388 DEFPRINT(AST_ObjectSetter, function(self, output){ 19389 self._print_getter_setter("set", output); 19390 }); 19391 DEFPRINT(AST_ObjectGetter, function(self, output){ 19392 self._print_getter_setter("get", output); 19393 }); 19394 DEFPRINT(AST_Symbol, function(self, output){ 19395 var def = self.definition(); 19396 output.print_name(def ? def.mangled_name || def.name : self.name); 19397 }); 19398 DEFPRINT(AST_Hole, noop); 19399 DEFPRINT(AST_This, function(self, output){ 19400 output.print("this"); 19401 }); 19402 DEFPRINT(AST_Constant, function(self, output){ 19403 output.print(self.getValue()); 19404 }); 19405 DEFPRINT(AST_String, function(self, output){ 19406 output.print_string(self.getValue(), self.quote, in_directive); 19407 }); 19408 DEFPRINT(AST_Number, function(self, output){ 19409 if (use_asm && self.start && self.start.raw != null) { 19410 output.print(self.start.raw); 19411 } else { 19412 output.print(make_num(self.getValue())); 19413 } 19414 }); 19415 19416 function regexp_safe_literal(code) { 19417 return [ 19418 0x5c , // \ 19419 0x2f , // / 19420 0x2e , // . 19421 0x2b , // + 19422 0x2a , // * 19423 0x3f , // ? 19424 0x28 , // ( 19425 0x29 , // ) 19426 0x5b , // [ 19427 0x5d , // ] 19428 0x7b , // { 19429 0x7d , // } 19430 0x24 , // $ 19431 0x5e , // ^ 19432 0x3a , // : 19433 0x7c , // | 19434 0x21 , // ! 19435 0x0a , // \n 19436 0x0d , // \r 19437 0x00 , // \0 19438 0xfeff , // Unicode BOM 19439 0x2028 , // unicode "line separator" 19440 0x2029 , // unicode "paragraph separator" 19441 ].indexOf(code) < 0; 19442 }; 19443 19444 DEFPRINT(AST_RegExp, function(self, output){ 19445 var str = self.getValue().toString(); 19446 if (output.option("ascii_only")) { 19447 str = output.to_ascii(str); 19448 } else if (output.option("unescape_regexps")) { 19449 str = str.split("\\\\").map(function(str){ 19450 return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s){ 19451 var code = parseInt(s.substr(2), 16); 19452 return regexp_safe_literal(code) ? String.fromCharCode(code) : s; 19453 }); 19454 }).join("\\\\"); 19455 } 19456 output.print(str); 19457 var p = output.parent(); 19458 if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) 19459 output.print(" "); 19460 }); 19461
19462 function force_statement(stat, output) { 19463 if (output.option("bracketize")) { 19464 make_block(stat, output); 19465 } else { 19466 if (!stat || stat instanceof AST_EmptyStatement) 19467 output.force_semicolon(); 19468 else 19469 stat.print(output); 19470 } 19471 }; 19472 19473 // self should be AST_New. decide if we want to show parens or not. 19474 function need_constructor_parens(self, output) { 19475 // Always print parentheses with arguments 19476 if (self.args.length > 0) return true; 19477 19478 return output.option("beautify"); 19479 }; 19480 19481 function best_of(a) { 19482 var best = a[0], len = best.length; 19483 for (var i = 1; i < a.length; ++i) { 19484 if (a[i].length < len) { 19485 best = a[i]; 19486 len = best.length; 19487 } 19488 } 19489 return best; 19490 }; 19491 19492 function make_num(num) { 19493 var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; 19494 if (Math.floor(num) === num) { 19495 if (num >= 0) { 19496 a.push("0x" + num.toString(16).toLowerCase(), // probably pointless 19497 "0" + num.toString(8)); // same. 19498 } else { 19499 a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless 19500 "-0" + (-num).toString(8)); // same. 19501 } 19502 if ((m = /^(.*?)(0+)$/.exec(num))) { 19503 a.push(m[1] + "e" + m[2].length); 19504 } 19505 } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { 19506 a.push(m[2] + "e-" + (m[1].length + m[2].length), 19507 str.substr(str.indexOf("."))); 19508 } 19509 return best_of(a); 19510 }; 19511 19512 function make_block(stmt, output) { 19513 if (!stmt || stmt instanceof AST_EmptyStatement) 19514 output.print("{}"); 19515 else if (stmt instanceof AST_BlockStatement) 19516 stmt.print(output); 19517 else output.with_block(function(){ 19518 output.indent(); 19519 stmt.print(output); 19520 output.newline(); 19521 }); 19522 }; 19523 19524 /* -----[ source map generators ]----- */ 19525 19526 function DEFMAP(nodetype, generator) { 19527 nodetype.DEFMETHOD("add_source_map", function(stream){ 19528 generator(this, stream); 19529 }); 19530 }; 19531 19532 // We could easily add info for ALL nodes, but it seems to me that 19533 // would be quite wasteful, hence this noop in the base class. 19534 DEFMAP(AST_Node, noop); 19535 19536 function basic_sourcemap_gen(self, output) { 19537 output.add_mapping(self.start); 19538 }; 19539 19540 // XXX: I'm not exactly sure if we need it for all of these nodes, 19541 // or if we should add even more. 19542 19543 DEFMAP(AST_Directive, basic_sourcemap_gen); 19544 DEFMAP(AST_Debugger, basic_sourcemap_gen); 19545 DEFMAP(AST_Symbol, basic_sourcemap_gen); 19546 DEFMAP(AST_Jump, basic_sourcemap_gen); 19547 DEFMAP(AST_StatementWithBody, basic_sourcemap_gen); 19548 DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it 19549 DEFMAP(AST_Lambda, basic_sourcemap_gen); 19550 DEFMAP(AST_Switch, basic_sourcemap_gen); 19551 DEFMAP(AST_SwitchBranch, basic_sourcemap_gen); 19552 DEFMAP(AST_BlockStatement, basic_sourcemap_gen); 19553 DEFMAP(AST_Toplevel, noop); 19554 DEFMAP(AST_New, basic_sourcemap_gen); 19555 DEFMAP(AST_Try, basic_sourcemap_gen); 19556 DEFMAP(AST_Catch, basic_sourcemap_gen); 19557 DEFMAP(AST_Finally, basic_sourcemap_gen); 19558 DEFMAP(AST_Definitions, basic_sourcemap_gen); 19559 DEFMAP(AST_Constant, basic_sourcemap_gen); 19560 DEFMAP(AST_ObjectSetter, function(self, output){ 19561 output.add_mapping(self.start, self.key.name); 19562 }); 19563 DEFMAP(AST_ObjectGetter, function(self, output){ 19564 output.add_mapping(self.start, self.key.name); 19565 }); 19566 DEFMAP(AST_ObjectProperty, function(self, output){ 19567 output.add_mapping(self.start, self.key); 19568 }); 19569 19570 })(); 19571 19572 /*********************************************************************** 19573 19574 A JavaScript tokenizer / parser / beautifier / compressor. 19575 https://github.com/mishoo/UglifyJS2 19576 19577 -------------------------------- (C) --------------------------------- 19578 19579 Author: Mihai Bazon 19580 <[email protected]> 19581 http://mihai.bazon.net/blog 19582 19583 Distributed under the BSD license: 19584 19585 Copyright 2012 (c) Mihai Bazon <[email protected]> 19586 19587 Redistribution and use in source and binary forms, with or without 19588 modification, are permitted provided that the following conditions 19589 are met: 19590 19591 * Redistributions of source code must retain the above 19592 copyright notice, this list of conditions and the following 19593 disclaimer. 19594 19595 * Redistributions in binary form must reproduce the above 19596 copyright notice, this list of conditions and the following 19597 disclaimer in the documentation and/or other materials 19598 provided with the distribution. 19599 19600 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 19601 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19602 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19603 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 19604 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
19605 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19606 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19607 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 19608 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 19609 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 19610 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 19611 SUCH DAMAGE. 19612 19613 ***********************************************************************/ 19614 19615 "use strict"; 19616 19617 function Compressor(options, false_by_default) { 19618 if (!(this instanceof Compressor)) 19619 return new Compressor(options, false_by_default); 19620 TreeTransformer.call(this, this.before, this.after); 19621 this.options = defaults(options, { 19622 angular : false, 19623 booleans : !false_by_default, 19624 cascade : !false_by_default, 19625 collapse_vars : !false_by_default, 19626 comparisons : !false_by_default, 19627 conditionals : !false_by_default, 19628 dead_code : !false_by_default, 19629 drop_console : false, 19630 drop_debugger : !false_by_default, 19631 evaluate : !false_by_default, 19632 expression : false, 19633 global_defs : {}, 19634 hoist_funs : !false_by_default, 19635 hoist_vars : false, 19636 if_return : !false_by_default, 19637 join_vars : !false_by_default, 19638 keep_fargs : true, 19639 keep_fnames : false, 19640 keep_infinity : false, 19641 loops : !false_by_default, 19642 negate_iife : !false_by_default, 19643 passes : 1, 19644 properties : !false_by_default, 19645 pure_getters : !false_by_default && "strict", 19646 pure_funcs : null, 19647 reduce_vars : !false_by_default, 19648 screw_ie8 : true, 19649 sequences : !false_by_default, 19650 side_effects : !false_by_default, 19651 switches : !false_by_default, 19652 top_retain : null, 19653 toplevel : !!(options && options["top_retain"]), 19654 unsafe : false, 19655 unsafe_comps : false, 19656 unsafe_math : false, 19657 unsafe_proto : false, 19658 unsafe_regexp : false, 19659 unused : !false_by_default, 19660 warnings : true, 19661 }, true); 19662 var pure_funcs = this.options["pure_funcs"]; 19663 if (typeof pure_funcs == "function") { 19664 this.pure_funcs = pure_funcs; 19665 } else { 19666 this.pure_funcs = pure_funcs ? function(node) { 19667 return pure_funcs.indexOf(node.expression.print_to_string()) < 0; 19668 } : return_true; 19669 } 19670 var top_retain = this.options["top_retain"]; 19671 if (top_retain instanceof RegExp) { 19672 this.top_retain = function(def) { 19673 return top_retain.test(def.name); 19674 }; 19675 } else if (typeof top_retain == "function") { 19676 this.top_retain = top_retain; 19677 } else if (top_retain) { 19678 if (typeof top_retain == "string") { 19679 top_retain = top_retain.split(/,/); 19680 } 19681 this.top_retain = function(def) { 19682 return top_retain.indexOf(def.name) >= 0; 19683 }; 19684 } 19685 var sequences = this.options["sequences"]; 19686 this.sequences_limit = sequences == 1 ? 200 : sequences | 0; 19687 this.warnings_produced = {}; 19688 }; 19689 19690 Compressor.prototype = new TreeTransformer; 19691 merge(Compressor.prototype, { 19692 option: function(key) { return this.options[key] }, 19693 compress: function(node) { 19694 if (this.option("expression")) { 19695 node = node.process_expression(true); 19696 } 19697 var passes = +this.options.passes || 1; 19698 for (var pass = 0; pass < passes && pass < 3; ++pass) { 19699 if (pass > 0 || this.option("reduce_vars")) 19700 node.reset_opt_flags(this, true); 19701 node = node.transform(this); 19702 } 19703 if (this.option("expression")) { 19704 node = node.process_expression(false); 19705 } 19706 return node; 19707 }, 19708 info: function() { 19709 if (this.options.warnings == "verbose") { 19710 AST_Node.warn.apply(AST_Node, arguments); 19711 } 19712 }, 19713 warn: function(text, props) { 19714 if (this.options.warnings) { 19715 // only emit unique warnings 19716 var message = string_template(text, props); 19717 if (!(message in this.warnings_produced)) { 19718 this.warnings_produced[message] = true; 19719 AST_Node.warn.apply(AST_Node, arguments); 19720 } 19721 } 19722 }, 19723 clear_warnings: function() { 19724 this.warnings_produced = {}; 19725 }, 19726 before: function(node, descend, in_list) { 19727 if (node._squeezed) return node; 19728 var was_scope = false;
19729 if (node instanceof AST_Scope) { 19730 node = node.hoist_declarations(this); 19731 was_scope = true; 19732 } 19733 // Before https://github.com/mishoo/UglifyJS2/pull/1602 AST_Node.optimize() 19734 // would call AST_Node.transform() if a different instance of AST_Node is 19735 // produced after OPT(). 19736 // This corrupts TreeWalker.stack, which cause AST look-ups to malfunction. 19737 // Migrate and defer all children's AST_Node.transform() to below, which 19738 // will now happen after this parent AST_Node has been properly substituted 19739 // thus gives a consistent AST snapshot. 19740 descend(node, this); 19741 // Existing code relies on how AST_Node.optimize() worked, and omitting the 19742 // following replacement call would result in degraded efficiency of both 19743 // output and performance. 19744 descend(node, this); 19745 var opt = node.optimize(this); 19746 if (was_scope && opt instanceof AST_Scope) { 19747 opt.drop_unused(this); 19748 descend(opt, this); 19749 } 19750 if (opt === node) opt._squeezed = true; 19751 return opt; 19752 } 19753 }); 19754 19755 (function(){ 19756 19757 function OPT(node, optimizer) { 19758 node.DEFMETHOD("optimize", function(compressor){ 19759 var self = this; 19760 if (self._optimized) return self; 19761 if (compressor.has_directive("use asm")) return self; 19762 var opt = optimizer(self, compressor); 19763 opt._optimized = true; 19764 return opt; 19765 }); 19766 }; 19767 19768 OPT(AST_Node, function(self, compressor){ 19769 return self; 19770 }); 19771 19772 AST_Node.DEFMETHOD("equivalent_to", function(node){ 19773 return this.TYPE == node.TYPE && this.print_to_string() == node.print_to_string(); 19774 }); 19775 19776 AST_Node.DEFMETHOD("process_expression", function(insert, compressor) { 19777 var self = this; 19778 var tt = new TreeTransformer(function(node) { 19779 if (insert && node instanceof AST_SimpleStatement) { 19780 return make_node(AST_Return, node, { 19781 value: node.body 19782 }); 19783 } 19784 if (!insert && node instanceof AST_Return) { 19785 if (compressor) { 19786 var value = node.value && node.value.drop_side_effect_free(compressor, true); 19787 return value ? make_node(AST_SimpleStatement, node, { 19788 body: value 19789 }) : make_node(AST_EmptyStatement, node); 19790 } 19791 return make_node(AST_SimpleStatement, node, { 19792 body: node.value || make_node(AST_UnaryPrefix, node, { 19793 operator: "void", 19794 expression: make_node(AST_Number, node, { 19795 value: 0 19796 }) 19797 }) 19798 }); 19799 } 19800 if (node instanceof AST_Lambda && node !== self) { 19801 return node; 19802 } 19803 if (node instanceof AST_Block) { 19804 var index = node.body.length - 1; 19805 if (index >= 0) { 19806 node.body[index] = node.body[index].transform(tt); 19807 } 19808 } 19809 if (node instanceof AST_If) { 19810 node.body = node.body.transform(tt); 19811 if (node.alternative) { 19812 node.alternative = node.alternative.transform(tt); 19813 } 19814 } 19815 if (node instanceof AST_With) { 19816 node.body = node.body.transform(tt); 19817 } 19818 return node; 19819 }); 19820 return self.transform(tt); 19821 }); 19822 19823 AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){ 19824 var reduce_vars = rescan && compressor.option("reduce_vars"); 19825 var toplevel = compressor.option("toplevel"); 19826 var safe_ids = Object.create(null); 19827 var suppressor = new TreeWalker(function(node) { 19828 if (node instanceof AST_Symbol) { 19829 var d = node.definition(); 19830 if (node instanceof AST_SymbolRef) d.references.push(node); 19831 d.fixed = false;
19832 } 19833 }); 19834 var tw = new TreeWalker(function(node, descend){ 19835 node._squeezed = false; 19836 node._optimized = false; 19837 if (reduce_vars) { 19838 if (node instanceof AST_Toplevel) node.globals.each(reset_def); 19839 if (node instanceof AST_Scope) node.variables.each(reset_def); 19840 if (node instanceof AST_SymbolRef) { 19841 var d = node.definition(); 19842 d.references.push(node); 19843 if (d.fixed === undefined || !is_safe(d) 19844 || is_modified(node, 0, node.fixed_value() instanceof AST_Lambda)) { 19845 d.fixed = false; 19846 } else { 19847 var parent = tw.parent(); 19848 if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right 19849 || parent instanceof AST_Call && node !== parent.expression 19850 || parent instanceof AST_Return && node === parent.value && node.scope !== d.scope 19851 || parent instanceof AST_VarDef && node === parent.value) { 19852 d.escaped = true; 19853 } 19854 } 19855 } 19856 if (node instanceof AST_SymbolCatch) { 19857 node.definition().fixed = false; 19858 } 19859 if (node instanceof AST_VarDef) { 19860 var d = node.name.definition(); 19861 if (d.fixed == null) { 19862 if (node.value) { 19863 d.fixed = function() { 19864 return node.value; 19865 }; 19866 mark(d, false); 19867 descend(); 19868 } else { 19869 d.fixed = null; 19870 } 19871 mark(d, true); 19872 return true; 19873 } else if (node.value) { 19874 d.fixed = false; 19875 } 19876 } 19877 if (node instanceof AST_Defun) { 19878 var d = node.name.definition(); 19879 if (!toplevel && d.global || is_safe(d)) { 19880 d.fixed = false; 19881 } else { 19882 d.fixed = node; 19883 mark(d, true); 19884 } 19885 var save_ids = safe_ids; 19886 safe_ids = Object.create(null); 19887 descend(); 19888 safe_ids = save_ids; 19889 return true; 19890 } 19891 if (node instanceof AST_Function) { 19892 push(); 19893 var iife; 19894 if (!node.name 19895 && (iife = tw.parent()) instanceof AST_Call 19896 && iife.expression === node) { 19897 // Virtually turn IIFE parameters into variable definitions: 19898 // (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})() 19899 // So existing transformation rules can work on them. 19900 node.argnames.forEach(function(arg, i) { 19901 var d = arg.definition(); 19902 if (!node.uses_arguments && d.fixed === undefined) { 19903 d.fixed = function() { 19904 return iife.args[i] || make_node(AST_Undefined, iife); 19905 }; 19906 mark(d, true); 19907 } else { 19908 d.fixed = false;
19909 } 19910 }); 19911 } 19912 descend(); 19913 pop(); 19914 return true; 19915 } 19916 if (node instanceof AST_Accessor) { 19917 var save_ids = safe_ids; 19918 safe_ids = Object.create(null); 19919 descend(); 19920 safe_ids = save_ids; 19921 return true; 19922 } 19923 if (node instanceof AST_Binary 19924 && (node.operator == "&&" || node.operator == "||")) { 19925 node.left.walk(tw); 19926 push(); 19927 node.right.walk(tw); 19928 pop(); 19929 return true; 19930 } 19931 if (node instanceof AST_Conditional) { 19932 node.condition.walk(tw); 19933 push(); 19934 node.consequent.walk(tw); 19935 pop(); 19936 push(); 19937 node.alternative.walk(tw); 19938 pop(); 19939 return true; 19940 } 19941 if (node instanceof AST_If || node instanceof AST_DWLoop) { 19942 node.condition.walk(tw); 19943 push(); 19944 node.body.walk(tw); 19945 pop(); 19946 if (node.alternative) { 19947 push(); 19948 node.alternative.walk(tw); 19949 pop(); 19950 } 19951 return true; 19952 } 19953 if (node instanceof AST_LabeledStatement) { 19954 push(); 19955 node.body.walk(tw); 19956 pop(); 19957 return true; 19958 } 19959 if (node instanceof AST_For) { 19960 if (node.init) node.init.walk(tw); 19961 push(); 19962 if (node.condition) node.condition.walk(tw); 19963 node.body.walk(tw); 19964 if (node.step) node.step.walk(tw); 19965 pop(); 19966 return true; 19967 } 19968 if (node instanceof AST_ForIn) { 19969 node.init.walk(suppressor); 19970 node.object.walk(tw); 19971 push(); 19972 node.body.walk(tw); 19973 pop(); 19974 return true; 19975 } 19976 if (node instanceof AST_Try) { 19977 push(); 19978 walk_body(node, tw); 19979 pop(); 19980 if (node.bcatch) { 19981 push(); 19982 node.bcatch.walk(tw); 19983 pop(); 19984 } 19985 if (node.bfinally) node.bfinally.walk(tw); 19986 return true; 19987 } 19988 if (node instanceof AST_SwitchBranch) { 19989 push(); 19990 descend(); 19991 pop(); 19992 return true; 19993 } 19994 } 19995 }); 19996 this.walk(tw); 19997 19998 function mark(def, safe) { 19999 safe_ids[def.id] = safe; 20000 } 20001 20002 function is_safe(def) { 20003 if (safe_ids[def.id]) {
20004 if (def.fixed == null) { 20005 var orig = def.orig[0]; 20006 if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false; 20007 def.fixed = make_node(AST_Undefined, orig); 20008 } 20009 return true; 20010 } 20011 } 20012 20013 function push() { 20014 safe_ids = Object.create(safe_ids); 20015 } 20016 20017 function pop() { 20018 safe_ids = Object.getPrototypeOf(safe_ids); 20019 } 20020 20021 function reset_def(def) { 20022 def.escaped = false; 20023 if (def.scope.uses_eval) { 20024 def.fixed = false; 20025 } else if (toplevel || !def.global || def.orig[0] instanceof AST_SymbolConst) { 20026 def.fixed = undefined; 20027 } else { 20028 def.fixed = false; 20029 } 20030 def.references = []; 20031 def.should_replace = undefined; 20032 } 20033 20034 function is_modified(node, level, func) { 20035 var parent = tw.parent(level); 20036 if (is_lhs(node, parent) 20037 || !func && parent instanceof AST_Call && parent.expression === node) { 20038 return true; 20039 } else if (parent instanceof AST_PropAccess && parent.expression === node) { 20040 return !func && is_modified(parent, level + 1); 20041 } 20042 } 20043 }); 20044 20045 AST_SymbolRef.DEFMETHOD("fixed_value", function() { 20046 var fixed = this.definition().fixed; 20047 if (!fixed || fixed instanceof AST_Node) return fixed; 20048 return fixed(); 20049 }); 20050 20051 function is_reference_const(ref) { 20052 if (!(ref instanceof AST_SymbolRef)) return false; 20053 var orig = ref.definition().orig; 20054 for (var i = orig.length; --i >= 0;) { 20055 if (orig[i] instanceof AST_SymbolConst) return true; 20056 } 20057 } 20058 20059 function find_variable(compressor, name) { 20060 var scope, i = 0; 20061 while (scope = compressor.parent(i++)) { 20062 if (scope instanceof AST_Scope) break; 20063 if (scope instanceof AST_Catch) { 20064 scope = scope.argname.definition().scope; 20065 break; 20066 } 20067 } 20068 return scope.find_variable(name); 20069 } 20070 20071 function make_node(ctor, orig, props) { 20072 if (!props) props = {}; 20073 if (orig) { 20074 if (!props.start) props.start = orig.start; 20075 if (!props.end) props.end = orig.end; 20076 } 20077 return new ctor(props); 20078 }; 20079 20080 function make_node_from_constant(val, orig) { 20081 switch (typeof val) { 20082 case "string": 20083 return make_node(AST_String, orig, { 20084 value: val 20085 }); 20086 case "number": 20087 if (isNaN(val)) return make_node(AST_NaN, orig); 20088 if (isFinite(val)) { 20089 return 1 / val < 0 ? make_node(AST_UnaryPrefix, orig, { 20090 operator: "-", 20091 expression: make_node(AST_Number, orig, { value: -val }) 20092 }) : make_node(AST_Number, orig, { value: val }); 20093 } 20094 return val < 0 ? make_node(AST_UnaryPrefix, orig, { 20095 operator: "-", 20096 expression: make_node(AST_Infinity, orig) 20097 }) : make_node(AST_Infinity, orig); 20098 case "boolean": 20099 return make_node(val ? AST_True : AST_False, orig); 20100 case "undefined": 20101 return make_node(AST_Undefined, orig); 20102 default: 20103 if (val === null) { 20104 return make_node(AST_Null, orig, { value: null }); 20105 } 20106 if (val instanceof RegExp) { 20107 return make_node(AST_RegExp, orig, { value: val }); 20108 } 20109 throw new Error(string_template("Can't handle constant of type: {type}", { 20110 type: typeof val 20111 })); 20112 } 20113 }; 20114 20115 // we shouldn't compress (1,func)(something) to 20116 // func(something) because that changes the meaning of 20117 // the func (becomes lexical instead of global). 20118 function maintain_this_binding(parent, orig, val) { 20119 if (parent instanceof AST_UnaryPrefix && parent.operator == "delete" 20120 || parent instanceof AST_Call && parent.expression === orig 20121 && (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) { 20122 return make_node(AST_Seq, orig, { 20123 car: make_node(AST_Number, orig, { 20124 value: 0 20125 }), 20126 cdr: val 20127 }); 20128 } 20129 return val; 20130 } 20131 20132 function as_statement_array(thing) { 20133 if (thing === null) return []; 20134 if (thing instanceof AST_BlockStatement) return thing.body; 20135 if (thing instanceof AST_EmptyStatement) return []; 20136 if (thing instanceof AST_Statement) return [ thing ]; 20137 throw new Error("Can't convert thing to statement array"); 20138 }; 20139 20140 function is_empty(thing) { 20141 if (thing === null) return true; 20142 if (thing instanceof AST_EmptyStatement) return true; 20143 if (thing instanceof AST_BlockStatement) return thing.body.length == 0; 20144 return false;
20145 }; 20146 20147 function loop_body(x) { 20148 if (x instanceof AST_Switch) return x; 20149 if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { 20150 return (x.body instanceof AST_BlockStatement ? x.body : x); 20151 } 20152 return x; 20153 }; 20154 20155 function is_iife_call(node) { 20156 if (node instanceof AST_Call && !(node instanceof AST_New)) { 20157 return node.expression instanceof AST_Function || is_iife_call(node.expression); 20158 } 20159 return false; 20160 } 20161 20162 function tighten_body(statements, compressor) { 20163 var CHANGED, max_iter = 10; 20164 do { 20165 CHANGED = false; 20166 if (compressor.option("angular")) { 20167 statements = process_for_angular(statements); 20168 } 20169 statements = eliminate_spurious_blocks(statements); 20170 if (compressor.option("dead_code")) { 20171 statements = eliminate_dead_code(statements, compressor); 20172 } 20173 if (compressor.option("if_return")) { 20174 statements = handle_if_return(statements, compressor); 20175 } 20176 if (compressor.sequences_limit > 0) { 20177 statements = sequencesize(statements, compressor); 20178 } 20179 if (compressor.option("join_vars")) { 20180 statements = join_consecutive_vars(statements, compressor); 20181 } 20182 if (compressor.option("collapse_vars")) { 20183 statements = collapse_single_use_vars(statements, compressor); 20184 } 20185 } while (CHANGED && max_iter-- > 0); 20186 20187 return statements; 20188 20189 function collapse_single_use_vars(statements, compressor) { 20190 // Iterate statements backwards looking for a statement with a var/const 20191 // declaration immediately preceding it. Grab the rightmost var definition 20192 // and if it has exactly one reference then attempt to replace its reference 20193 // in the statement with the var value and then erase the var definition. 20194 20195 var self = compressor.self(); 20196 var var_defs_removed = false; 20197 var toplevel = compressor.option("toplevel"); 20198 for (var stat_index = statements.length; --stat_index >= 0;) { 20199 var stat = statements[stat_index]; 20200 if (stat instanceof AST_Definitions) continue; 20201 20202 // Process child blocks of statement if present. 20203 [stat, stat.body, stat.alternative, stat.bcatch, stat.bfinally].forEach(function(node) { 20204 node && node.body && collapse_single_use_vars(node.body, compressor); 20205 }); 20206 20207 // The variable definition must precede a statement. 20208 if (stat_index <= 0) break; 20209 var prev_stat_index = stat_index - 1; 20210 var prev_stat = statements[prev_stat_index]; 20211 if (!(prev_stat instanceof AST_Definitions)) continue; 20212 var var_defs = prev_stat.definitions; 20213 if (var_defs == null) continue; 20214 20215 var var_names_seen = {}; 20216 var side_effects_encountered = false; 20217 var lvalues_encountered = false; 20218 var lvalues = {}; 20219 20220 // Scan variable definitions from right to left. 20221 for (var var_defs_index = var_defs.length; --var_defs_index >= 0;) { 20222 20223 // Obtain var declaration and var name with basic sanity check. 20224 var var_decl = var_defs[var_defs_index]; 20225 if (var_decl.value == null) break; 20226 var var_name = var_decl.name.name; 20227 if (!var_name || !var_name.length) break; 20228 20229 // Bail if we've seen a var definition of same name before. 20230 if (var_name in var_names_seen) break; 20231 var_names_seen[var_name] = true; 20232 20233 // Only interested in cases with just one reference to the variable. 20234 var def = self.find_variable && self.find_variable(var_name); 20235 if (!def || !def.references || def.references.length !== 1 20236 || var_name == "arguments" || (!toplevel && def.global)) { 20237 side_effects_encountered = true; 20238 continue; 20239 } 20240 var ref = def.references[0]; 20241 20242 // Don't replace ref if eval() or with statement in scope. 20243 if (ref.scope.uses_eval || ref.scope.uses_with) break; 20244 20245 // Constant single use vars can be replaced in any scope. 20246 if (var_decl.value.is_constant()) { 20247 var ctt = new TreeTransformer(function(node) { 20248 var parent = ctt.parent(); 20249 if (parent instanceof AST_IterationStatement 20250 && (parent.condition === no
20250de || parent.init === node)) { 20251 return node; 20252 } 20253 if (node === ref) 20254 return replace_var(node, parent, true); 20255 }); 20256 stat.transform(ctt); 20257 continue; 20258 } 20259 20260 // Restrict var replacement to constants if side effects encountered. 20261 if (side_effects_encountered |= lvalues_encountered) continue; 20262 20263 var value_has_side_effects = var_decl.value.has_side_effects(compressor); 20264 // Non-constant single use vars can only be replaced in same scope. 20265 if (ref.scope !== self) { 20266 side_effects_encountered |= value_has_side_effects; 20267 continue; 20268 } 20269 20270 // Detect lvalues in var value. 20271 var tw = new TreeWalker(function(node){ 20272 if (node instanceof AST_SymbolRef && is_lvalue(node, tw.parent())) { 20273 lvalues[node.name] = lvalues_encountered = true; 20274 } 20275 }); 20276 var_decl.value.walk(tw); 20277 20278 // Replace the non-constant single use var in statement if side effect free. 20279 var unwind = false; 20280 var tt = new TreeTransformer( 20281 function preorder(node) { 20282 if (unwind) return node; 20283 var parent = tt.parent(); 20284 if (node instanceof AST_Lambda 20285 || node instanceof AST_Try 20286 || node instanceof AST_With 20287 || node instanceof AST_Case 20288 || node instanceof AST_IterationStatement 20289 || (parent instanceof AST_If && node !== parent.condition) 20290 || (parent instanceof AST_Conditional && node !== parent.condition) 20291 || (node instanceof AST_SymbolRef 20292 && value_has_side_effects 20293 && !are_references_in_scope(node.definition(), self)) 20294 || (parent instanceof AST_Binary 20295 && (parent.operator == "&&" || parent.operator == "||") 20296 && node === parent.right) 20297 || (parent instanceof AST_Switch && node !== parent.expression)) { 20298 return side_effects_encountered = unwind = true, node; 20299 } 20300 function are_references_in_scope(def, scope) { 20301 if (def.orig.length === 1 20302 && def.orig[0] instanceof AST_SymbolDefun) return true; 20303 if (def.scope !== scope) return false; 20304 var refs = def.references; 20305 for (var i = 0, len = refs.length; i < len; i++) { 20306 if (refs[i].scope !== scope) return false; 20307 } 20308 return true; 20309 } 20310 }, 20311 function postorder(node) { 20312 if (unwind) return node; 20313 if (node === ref) 20314 return unwind = true, replace_var(node, tt.parent(), false); 20315 if (side_effects_encountered |= node.has_side_effects(compressor)) 20316 return unwind = true, node; 20317 if (lvalues_encountered && node instanceof AST_SymbolRef && node.name in lvalues) { 20318 side_effects_encountered = true; 20319 return unwind = true, node; 20320 } 20321 } 20322 ); 20323 stat.transform(tt); 20324 } 20325 } 20326 20327 // Remove extraneous empty statments in block after remov
20327ing var definitions. 20328 // Leave at least one statement in `statements`. 20329 if (var_defs_removed) for (var i = statements.length; --i >= 0;) { 20330 if (statements.length > 1 && statements[i] instanceof AST_EmptyStatement) 20331 statements.splice(i, 1); 20332 } 20333 20334 return statements; 20335 20336 function is_lvalue(node, parent) { 20337 return node instanceof AST_SymbolRef && is_lhs(node, parent); 20338 } 20339 function replace_var(node, parent, is_constant) { 20340 if (is_lvalue(node, parent)) return node; 20341 20342 // Remove var definition and return its value to the TreeTransformer to replace. 20343 var value = maintain_this_binding(parent, node, var_decl.value); 20344 var_decl.value = null; 20345 20346 var_defs.splice(var_defs_index, 1); 20347 if (var_defs.length === 0) { 20348 statements[prev_stat_index] = make_node(AST_EmptyStatement, self); 20349 var_defs_removed = true; 20350 } 20351 // Further optimize statement after substitution. 20352 stat.reset_opt_flags(compressor); 20353 20354 compressor.info("Collapsing " + (is_constant ? "constant" : "variable") + 20355 " " + var_name + " [{file}:{line},{col}]", node.start); 20356 CHANGED = true; 20357 return value; 20358 } 20359 } 20360 20361 function process_for_angular(statements) { 20362 function has_inject(comment) { 20363 return /@ngInject/.test(comment.value); 20364 } 20365 function make_arguments_names_list(func) { 20366 return func.argnames.map(function(sym){ 20367 return make_node(AST_String, sym, { value: sym.name }); 20368 }); 20369 } 20370 function make_array(orig, elements) { 20371 return make_node(AST_Array, orig, { elements: elements }); 20372 } 20373 function make_injector(func, name) { 20374 return make_node(AST_SimpleStatement, func, { 20375 body: make_node(AST_Assign, func, { 20376 operator: "=", 20377 left: make_node(AST_Dot, name, { 20378 expression: make_node(AST_SymbolRef, name, name), 20379 property: "$inject" 20380 }), 20381 right: make_array(func, make_arguments_names_list(func)) 20382 }) 20383 }); 20384 } 20385 function check_expression(body) { 20386 if (body && body.args) { 20387 // if this is a function call check all of arguments passed 20388 body.args.forEach(function(argument, index, array) { 20389 var comments = argument.start.comments_before; 20390 // if the argument is function preceded by @ngInject 20391 if (argument instanceof AST_Lambda && comments.length && has_inject(comments[0])) { 20392 // replace the function with an array of names of its parameters and function at the end 20393 array[index] = make_array(argument, make_arguments_names_list(argument).concat(argument)); 20394 } 20395 }); 20396 // if this is chained call check previous one recursively 20397 if (body.expression && body.expression.expression) { 20398 check_expression(body.expression.expression); 20399 } 20400 } 20401 } 20402 return statements.reduce(function(a, stat){ 20403 a.push(stat); 20404
20405 if (stat.body && stat.body.args) { 20406 check_expression(stat.body); 20407 } else { 20408 var token = stat.start; 20409 var comments = token.comments_before; 20410 if (comments && comments.length > 0) { 20411 var last = comments.pop(); 20412 if (has_inject(last)) { 20413 // case 1: defun 20414 if (stat instanceof AST_Defun) { 20415 a.push(make_injector(stat, stat.name)); 20416 } 20417 else if (stat instanceof AST_Definitions) { 20418 stat.definitions.forEach(function(def) { 20419 if (def.value && def.value instanceof AST_Lambda) { 20420 a.push(make_injector(def.value, def.name)); 20421 } 20422 }); 20423 } 20424 else { 20425 compressor.warn("Unknown statement marked with @ngInject [{file}:{line},{col}]", token); 20426 } 20427 } 20428 } 20429 } 20430 20431 return a; 20432 }, []); 20433 } 20434 20435 function eliminate_spurious_blocks(statements) { 20436 var seen_dirs = []; 20437 return statements.reduce(function(a, stat){ 20438 if (stat instanceof AST_BlockStatement) { 20439 CHANGED = true; 20440 a.push.apply(a, eliminate_spurious_blocks(stat.body)); 20441 } else if (stat instanceof AST_EmptyStatement) { 20442 CHANGED = true; 20443 } else if (stat instanceof AST_Directive) { 20444 if (seen_dirs.indexOf(stat.value) < 0) { 20445 a.push(stat); 20446 seen_dirs.push(stat.value); 20447 } else { 20448 CHANGED = true; 20449 } 20450 } else { 20451 a.push(stat); 20452 } 20453 return a; 20454 }, []); 20455 }; 20456 20457 function handle_if_return(statements, compressor) { 20458 var self = compressor.self(); 20459 var multiple_if_returns = has_multiple_if_returns(statements); 20460 var in_lambda = self instanceof AST_Lambda; 20461 var ret = []; // Optimized statements, build from tail to front 20462 loop: for (var i = statements.length; --i >= 0;) { 20463 var stat = statements[i]; 20464 switch (true) { 20465 case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0): 20466 CHANGED = true; 20467 // note, ret.length is probably always zero 20468 // because we drop unreachable code before this 20469 // step. nevertheless, it's good to check. 20470 continue loop; 20471 case stat instanceof AST_If: 20472 if (stat.body instanceof AST_Return) { 20473 //--- 20474 // pretty silly case, but: 20475 // if (foo()) return; return; ==> foo(); return; 20476 if (((in_lambda && ret.length == 0) 20477 || (ret[0] instanceof AST_Return && !ret[0].value)) 20478 && !stat.body.value && !stat.alternative) { 20479 CHANGED = true; 20480 var cond = make_node(AST_SimpleStatement, stat.condition, { 20481 body: stat.condition 20482 }); 20483 ret.unshift(cond); 20484 continue loop; 20485 } 20486 //--- 20487 // if (foo()) return x; return y; ==> return foo() ? x : y; 20488 if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { 20489 CHANGED = true; 20490 stat = stat.clone(); 20491 stat.alternative = ret[0]; 20492 ret[0] = stat.transform(compressor); 20493 continue loop; 20494 } 20495 //--- 20496 // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; 20497 if (multiple_if_returns && (ret.length == 0 || ret[0] instanceof AST_Return) 20498 && stat.body.value && !stat.alternative && in_lambda) { 20499 CHANGED = true; 20500 stat = stat.clone(); 20501 stat.alternative = ret[0] || make_node(AST_Return, stat, { 20502 value: null 20503 }); 20504 ret[0] = stat.transform(compressor); 20505 continue loop; 20506 } 20507 //--- 20508 // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... } 20509 if (!stat.body.value && in_lambda) { 20510 CHANGED = true; 20511 stat = stat.clone(); 20512 stat.condition = stat.condition.negate(compressor); 20513 var body = as_statement_array(stat.alternative).concat(ret); 20514 var funs = extract_functions_from_statement_array(body); 20515 stat.body = make_node(AST_BlockStatement, stat, { 20516 body: body 20517 }); 20518 stat.alternative = null; 20519 ret = funs.concat([ stat.transform(compressor) ]); 20520 continue loop; 20521 } 20522 20523 //--- 20524 // if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e; 20525 // 20526 // if sequences is not enabled, this can lead to an endless loop (issue #866). 20527 // however, with sequences on this helps producing slightly better output for 20528 // the example code. 20529 if (compressor.option("sequences") 20530 && i > 0 && statements[i - 1] instanceof AST_If && statements[i - 1].body instanceof AST_Return 20531 && ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement 20532 && !stat.alternative) { 20533 CHANGED = true;
20534 ret.push(make_node(AST_Return, ret[0], { 20535 value: null 20536 }).transform(compressor)); 20537 ret.unshift(stat); 20538 continue loop; 20539 } 20540 } 20541 20542 var ab = aborts(stat.body); 20543 var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null; 20544 if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) 20545 || (ab instanceof AST_Continue && self === loop_body(lct)) 20546 || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { 20547 if (ab.label) { 20548 remove(ab.label.thedef.references, ab); 20549 } 20550 CHANGED = true; 20551 var body = as_statement_array(stat.body).slice(0, -1); 20552 stat = stat.clone(); 20553 stat.condition = stat.condition.negate(compressor); 20554 stat.body = make_node(AST_BlockStatement, stat, { 20555 body: as_statement_array(stat.alternative).concat(ret) 20556 }); 20557 stat.alternative = make_node(AST_BlockStatement, stat, { 20558 body: body 20559 }); 20560 ret = [ stat.transform(compressor) ]; 20561 continue loop; 20562 } 20563 20564 var ab = aborts(stat.alternative); 20565 var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null; 20566 if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) 20567 || (ab instanceof AST_Continue && self === loop_body(lct)) 20568 || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { 20569 if (ab.label) { 20570 remove(ab.label.thedef.references, ab); 20571 } 20572 CHANGED = true; 20573 stat = stat.clone(); 20574 stat.body = make_node(AST_BlockStatement, stat.body, { 20575 body: as_statement_array(stat.body).concat(ret) 20576 }); 20577 stat.alternative = make_node(AST_BlockStatement, stat.alternative, { 20578 body: as_statement_array(stat.alternative).slice(0, -1) 20579 }); 20580 ret = [ stat.transform(compressor) ]; 20581 continue loop; 20582 } 20583 20584 ret.unshift(stat); 20585 break; 20586 default: 20587 ret.unshift(stat); 20588 break; 20589 } 20590 } 20591 return ret; 20592 20593 function has_multiple_if_returns(statements) { 20594 var n = 0; 20595 for (var i = statements.length; --i >= 0;) { 20596 var stat = statements[i]; 20597 if (stat instanceof AST_If && stat.body instanceof AST_Return) { 20598 if (++n > 1) return true; 20599 } 20600 } 20601 return false;
20602 } 20603 }; 20604 20605 function eliminate_dead_code(statements, compressor) { 20606 var has_quit = false; 20607 var orig = statements.length; 20608 var self = compressor.self(); 20609 statements = statements.reduce(function(a, stat){ 20610 if (has_quit) { 20611 extract_declarations_from_unreachable_code(compressor, stat, a); 20612 } else { 20613 if (stat instanceof AST_LoopControl) { 20614 var lct = compressor.loopcontrol_target(stat); 20615 if ((stat instanceof AST_Break 20616 && !(lct instanceof AST_IterationStatement) 20617 && loop_body(lct) === self) || (stat instanceof AST_Continue 20618 && loop_body(lct) === self)) { 20619 if (stat.label) { 20620 remove(stat.label.thedef.references, stat); 20621 } 20622 } else { 20623 a.push(stat); 20624 } 20625 } else { 20626 a.push(stat); 20627 } 20628 if (aborts(stat)) has_quit = true; 20629 } 20630 return a; 20631 }, []); 20632 CHANGED = statements.length != orig; 20633 return statements; 20634 }; 20635 20636 function sequencesize(statements, compressor) { 20637 if (statements.length < 2) return statements; 20638 var seq = [], ret = []; 20639 function push_seq() { 20640 seq = AST_Seq.from_array(seq); 20641 if (seq) ret.push(make_node(AST_SimpleStatement, seq, { 20642 body: seq 20643 })); 20644 seq = []; 20645 }; 20646 statements.forEach(function(stat){ 20647 if (stat instanceof AST_SimpleStatement) { 20648 if (seqLength(seq) >= compressor.sequences_limit) push_seq(); 20649 var body = stat.body; 20650 if (seq.length > 0) body = body.drop_side_effect_free(compressor); 20651 if (body) seq.push(body); 20652 } else { 20653 push_seq(); 20654 ret.push(stat); 20655 } 20656 }); 20657 push_seq(); 20658 ret = sequencesize_2(ret, compressor); 20659 CHANGED = ret.length != statements.length; 20660 return ret; 20661 }; 20662 20663 function seqLength(a) { 20664 for (var len = 0, i = 0; i < a.length; ++i) { 20665 var stat = a[i]; 20666 if (stat instanceof AST_Seq) { 20667 len += stat.len(); 20668 } else { 20669 len++; 20670 } 20671 } 20672 return len; 20673 }; 20674 20675 function sequencesize_2(statements, compressor) { 20676 function cons_seq(right) { 20677 ret.pop(); 20678 var left = prev.body; 20679 if (left instanceof AST_Seq) { 20680 left.add(right); 20681 } else { 20682 left = AST_Seq.cons(left, right); 20683 } 20684 return left.transform(compressor); 20685 }; 20686 var ret = [], prev = null;
20687 statements.forEach(function(stat){ 20688 if (prev) { 20689 if (stat instanceof AST_For) { 20690 var opera = {}; 20691 try { 20692 prev.body.walk(new TreeWalker(function(node){ 20693 if (node instanceof AST_Binary && node.operator == "in") 20694 throw opera; 20695 })); 20696 if (stat.init && !(stat.init instanceof AST_Definitions)) { 20697 stat.init = cons_seq(stat.init); 20698 } 20699 else if (!stat.init) { 20700 stat.init = prev.body.drop_side_effect_free(compressor); 20701 ret.pop(); 20702 } 20703 } catch(ex) { 20704 if (ex !== opera) throw ex; 20705 } 20706 } 20707 else if (stat instanceof AST_If) { 20708 stat.condition = cons_seq(stat.condition); 20709 } 20710 else if (stat instanceof AST_With) { 20711 stat.expression = cons_seq(stat.expression); 20712 } 20713 else if (stat instanceof AST_Exit && stat.value) { 20714 stat.value = cons_seq(stat.value); 20715 } 20716 else if (stat instanceof AST_Exit) { 20717 stat.value = cons_seq(make_node(AST_Undefined, stat).transform(compressor)); 20718 } 20719 else if (stat instanceof AST_Switch) { 20720 stat.expression = cons_seq(stat.expression); 20721 } 20722 } 20723 ret.push(stat); 20724 prev = stat instanceof AST_SimpleStatement ? stat : null; 20725 }); 20726 return ret; 20727 }; 20728 20729 function join_consecutive_vars(statements, compressor) { 20730 var prev = null; 20731 return statements.reduce(function(a, stat){ 20732 if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { 20733 prev.definitions = prev.definitions.concat(stat.definitions); 20734 CHANGED = true; 20735 } 20736 else if (stat instanceof AST_For 20737 && prev instanceof AST_Var 20738 && (!stat.init || stat.init.TYPE == prev.TYPE)) { 20739 CHANGED = true; 20740 a.pop(); 20741 if (stat.init) { 20742 stat.init.definitions = prev.definitions.concat(stat.init.definitions); 20743 } else { 20744 stat.init = prev; 20745 } 20746 a.push(stat); 20747 prev = stat; 20748 } 20749 else { 20750 prev = stat; 20751 a.push(stat); 20752 } 20753 return a; 20754 }, []); 20755 }; 20756 20757 }; 20758 20759 function extract_functions_from_statement_array(statements) { 20760 var funs = []; 20761 for (var i = statements.length - 1; i >= 0; --i) { 20762 var stat = statements[i]; 20763 if (stat instanceof AST_Defun) { 20764 statements.splice(i, 1); 20765 funs.unshift(stat); 20766 } 20767 } 20768 return funs; 20769 } 20770 20771 function extract_declarations_from_unreachable_code(compressor, stat, target) { 20772 if (!(stat instanceof AST_Defun)) { 20773 compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); 20774 } 20775 stat.walk(new TreeWalker(function(node){ 20776 if (node instanceof AST_Definitions) { 20777 compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
20778 node.remove_initializers(); 20779 target.push(node); 20780 return true; 20781 } 20782 if (node instanceof AST_Defun) { 20783 target.push(node); 20784 return true; 20785 } 20786 if (node instanceof AST_Scope) { 20787 return true; 20788 } 20789 })); 20790 }; 20791 20792 function is_undefined(node, compressor) { 20793 return node.is_undefined 20794 || node instanceof AST_Undefined 20795 || node instanceof AST_UnaryPrefix 20796 && node.operator == "void" 20797 && !node.expression.has_side_effects(compressor); 20798 } 20799 20800 // may_throw_on_access() 20801 // returns true if this node may be null, undefined or contain `AST_Accessor` 20802 (function(def) { 20803 AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) { 20804 var pure_getters = compressor.option("pure_getters"); 20805 return !pure_getters || this._throw_on_access(pure_getters); 20806 }); 20807 20808 function is_strict(pure_getters) { 20809 return /strict/.test(pure_getters); 20810 } 20811 20812 def(AST_Node, is_strict); 20813 def(AST_Null, return_true); 20814 def(AST_Undefined, return_true); 20815 def(AST_Constant, return_false); 20816 def(AST_Array, return_false); 20817 def(AST_Object, function(pure_getters) { 20818 if (!is_strict(pure_getters)) return false; 20819 for (var i = this.properties.length; --i >=0;) 20820 if (this.properties[i].value instanceof AST_Accessor) return true; 20821 return false; 20822 }); 20823 def(AST_Function, return_false); 20824 def(AST_UnaryPostfix, return_false); 20825 def(AST_UnaryPrefix, function() { 20826 return this.operator == "void"; 20827 }); 20828 def(AST_Binary, function(pure_getters) { 20829 switch (this.operator) { 20830 case "&&": 20831 return this.left._throw_on_access(pure_getters); 20832 case "||": 20833 return this.left._throw_on_access(pure_getters) 20834 && this.right._throw_on_access(pure_getters); 20835 default: 20836 return false; 20837 } 20838 }) 20839 def(AST_Assign, function(pure_getters) { 20840 return this.operator == "=" 20841 && this.right._throw_on_access(pure_getters); 20842 }) 20843 def(AST_Conditional, function(pure_getters) { 20844 return this.consequent._throw_on_access(pure_getters) 20845 || this.alternative._throw_on_access(pure_getters); 20846 }) 20847 def(AST_Seq, function(pure_getters) { 20848 return this.cdr._throw_on_access(pure_getters); 20849 }); 20850 def(AST_SymbolRef, function(pure_getters) { 20851 if (this.is_undefined) return true; 20852 if (!is_strict(pure_getters)) return false; 20853 var fixed = this.fixed_value(); 20854 return !fixed || fixed._throw_on_access(pure_getters); 20855 }); 20856 })(function(node, func) { 20857 node.DEFMETHOD("_throw_on_access", func); 20858 }); 20859 20860 /* -----[ boolean/negation helpers ]----- */ 20861 20862 // methods to determine whether an expression has a boolean result type 20863 (function (def){ 20864 var unary_bool = [ "!", "delete" ]; 20865 var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; 20866 def(AST_Node, return_false); 20867 def(AST_UnaryPrefix, function(){ 20868 return member(this.operator, unary_bool); 20869 }); 20870 def(AST_Binary, function(){ 20871 return member(this.operator, binary_bool) || 20872 ( (this.operator == "&&" || this.operator == "||") && 20873 this.left.is_boolean() && this.right.is_boolean() ); 20874 }); 20875 def(AST_Conditional, function(){ 20876 return this.consequent.is_boolean() && this.alternative.is_boolean(); 20877 }); 20878 def(AST_Assign, function(){ 20879 return this.operator == "=" && this.right.is_boolean(); 20880 }); 20881 def(AST_Seq, function(){ 20882 return this.cdr.is_boolean(); 20883 }); 20884 def(AST_True, return_true); 20885 def(AST_False, return_true); 20886 })(function(node, func){ 20887 node.DEFMETHOD("is_boolean", func); 20888 }); 20889 20890 // methods to determine if an expression has a numeric result type 20891 (function (def){ 20892 def(AST_Node, return_false); 20893 def(AST_Number, return_true); 20894 var unary = makePredicate("+ - ~ ++ --"); 20895 def(AST_Unary, function(){ 20896 return unary(this.operator); 20897 }); 20898 var binary = makePredicate("- * / % & | ^ << >> >>>"); 20899 def(AST_Binary, function(compressor){ 20900 return binary(this.operator) || this.operator == "+" 20901 && this.left.is_number(compressor) 20902 && this.right.is_number(compressor); 20903 }); 20904 def(AST_Assign, function(compressor){ 20905 return binary(this.operator.slice(0, -1)) 20906 || this.operator == "=" && this.right.is_number(compressor); 20907 }); 20908 def(AST_Seq, function(compressor){ 20909 return this.cdr.is_number(compressor); 20910 }); 20911 def(AST_Conditional, function(compressor){ 20912 return this.consequent.is_number(compressor) && this.alternative.is_number(compressor); 20913 }); 20914 })(function(node, func){ 20915 node.DEFMETHOD("is_number", func); 20916 }); 20917 20918 // methods to determine if an expression has a string result type 20919 (function (def){ 20920 def(AST_Node, return_false); 20921 def(AST_String, return_true); 20922 def(AST_UnaryPrefix, function(){ 20923 return this.operator == "typeof"; 20924 }); 20925 def(AST_Binary, function(compressor){ 20926 return this.operator == "+" && 20927 (this.left.is_string(compressor) || this.right.is_string(compressor)); 20928 }); 20929 def(AST_Assign, function(compressor){ 20930 return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); 20931 }); 20932 def(AST_Seq, function(compressor){ 20933 return this.cdr.is_string(compressor); 20934 }); 20935 def(AST_Conditional, function(compressor){ 20936 return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); 20937 }); 20938 })(function(node, func){ 20939 node.DEFMETHOD("is_string", func); 20940 }); 20941 20942 var unary_side_effects = makePredicate("delete ++ --"); 20943 20944 function is_lhs(node, parent) { 20945 if (parent instanceof AST_Unary && unary_side_effects(parent.operator)) return parent.expression; 20946 if (parent instanceof AST_Assign && parent.left === node) return node; 20947 } 20948 20949 (function (def){ 20950 AST_Node.DEFMETHOD("resolve_defines", function(compressor) { 20951 if (!compressor.option("global_defs")) return; 20952 var def = this._find_defs(compressor, ""); 20953 if (def) { 20954 var node, parent = this, level = 0; 20955 do { 20956 node = parent; 20957 parent = compressor.parent(level++); 20958 } while (parent instanceof AST_PropAccess && parent.expression === no
20958de); 20959 if (is_lhs(node, parent)) { 20960 compressor.warn('global_defs ' + this.print_to_string() + ' redefined [{file}:{line},{col}]', this.start); 20961 } else { 20962 return def; 20963 } 20964 } 20965 }); 20966 function to_node(value, orig) { 20967 if (value instanceof AST_Node) return make_node(value.CTOR, orig, value); 20968 if (Array.isArray(value)) return make_node(AST_Array, orig, { 20969 elements: value.map(function(value) { 20970 return to_node(value, orig); 20971 }) 20972 }); 20973 if (value && typeof value == "object") { 20974 var props = []; 20975 for (var key in value) { 20976 props.push(make_node(AST_ObjectKeyVal, orig, { 20977 key: key, 20978 value: to_node(value[key], orig) 20979 })); 20980 } 20981 return make_node(AST_Object, orig, { 20982 properties: props 20983 }); 20984 } 20985 return make_node_from_constant(value, orig); 20986 } 20987 def(AST_Node, noop); 20988 def(AST_Dot, function(compressor, suffix){ 20989 return this.expression._find_defs(compressor, "." + this.property + suffix); 20990 }); 20991 def(AST_SymbolRef, function(compressor, suffix){ 20992 if (!this.global()) return; 20993 var name; 20994 var defines = compressor.option("global_defs"); 20995 if (defines && HOP(defines, (name = this.name + suffix))) { 20996 var node = to_node(defines[name], this); 20997 var top = compressor.find_parent(AST_Toplevel); 20998 node.walk(new TreeWalker(function(node) { 20999 if (node instanceof AST_SymbolRef) { 21000 node.scope = top; 21001 node.thedef = top.def_global(node); 21002 } 21003 })); 21004 return node; 21005 } 21006 }); 21007 })(function(node, func){ 21008 node.DEFMETHOD("_find_defs", func); 21009 }); 21010 21011 function best_of_expression(ast1, ast2) { 21012 return ast1.print_to_string().length > 21013 ast2.print_to_string().length 21014 ? ast2 : ast1; 21015 } 21016 21017 function best_of_statement(ast1, ast2) { 21018 return best_of_expression(make_node(AST_SimpleStatement, ast1, { 21019 body: ast1 21020 }), make_node(AST_SimpleStatement, ast2, { 21021 body: ast2 21022 })).body; 21023 } 21024 21025 function best_of(compressor, ast1, ast2) { 21026 return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2); 21027 } 21028 21029 // methods to evaluate a constant expression 21030 (function (def){ 21031 // If the node has been successfully reduced to a constant, 21032 // then its value is returned; otherwise the element itself 21033 // is returned. 21034 // They can be distinguished as constant value is never a 21035 // descendant of AST_Node. 21036 AST_Node.DEFMETHOD("evaluate", function(compressor){ 21037 if (!compressor.option("evaluate")) return this; 21038 try { 21039 var val = this._eval(compressor); 21040 return !val || val instanceof RegExp || typeof val != "object" ? val : this; 21041 } catch(ex) { 21042 if (ex !== def) throw ex; 21043 return this; 21044 } 21045 }); 21046 var unaryPrefix = makePredicate("! ~ - + void"); 21047 AST_Node.DEFMETHOD("is_constant", function(){ 21048 // Accomodate when compress option evaluate=false 21049 // as well as the common constant expressions !0 and -1 21050 if (this instanceof AST_Constant) { 21051 return !(this instanceof AST_RegExp); 21052 } else { 21053 return this instanceof AST_UnaryPrefix 21054 && this.expression instanceof AST_Constant 21055 && unaryPrefix(this.operator); 21056 } 21057 }); 21058 // Obtain the constant value of an expression already known to be constant. 21059 // Result only valid iff this.is_constant() is true. 21060 AST_Node.DEFMETHOD("constant_value", function(compressor){ 21061 // Accomodate when option evaluate=false. 21062 if (this instanceof AST_Constant && !(this instanceof AST_RegExp)) { 21063 return this.value; 21064 } 21065 // Accomodate the common constant expressions !0 and -1 when option evaluate=false. 21066 if (this instanceof AST_UnaryPrefix 21067 && this.expression instanceof AST_Constant) switch (this.operator) { 21068 case "!": 21069 return !this.expression.value; 21070 case "~": 21071 return ~this.expression.value; 21072 case "-": 21073 return -this.expression.value; 21074 case "+": 21075 return +this.expression.value; 21076 default: 21077 throw new Error(string_template("Cannot evaluate unary expression {value}", { 21078 value: this.print_to_string() 21079 })); 21080 } 21081 var result = this.evaluate(compressor); 21082 if (result !== this) { 21083 return result; 21084 } 21085 throw new Error(string_template("Cannot evaluate constant [{file}:{line},{col}]", this.start)); 21086 }); 21087 def(AST_Statement, function(){ 21088 throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); 21089 }); 21090 def(AST_Lambda, function(){ 21091 throw def; 21092 }); 21093 function ev(node, compressor) { 21094 if (!compressor) throw new Error("Compressor must be passed"); 21095 21096 return node._eval(compressor); 21097 }; 21098 def(AST_Node, function(){ 21099 throw def; // not constant 21100 }); 21101 def(AST_Constant, function(){ 21102 return this.getValue(); 21103 }); 21104 def(AST_Array, function(compressor){ 21105 if (compressor.option("unsafe")) { 21106 return this.elements.map(function(element) { 21107 return ev(element, compressor); 21108 }); 21109 } 21110 throw def; 21111 }); 21112 def(AST_Object, function(compressor){ 21113 if (compressor.option("unsafe")) { 21114 var val = {}; 21115 for (var i = 0, len = this.properties.length; i < len; i++) { 21116 var prop = this.properties[i]; 21117 var key = prop.key; 21118 if (key instanceof AST_Symbol) { 21119 key = key.name; 21120 } else if (key instanceof AST_Node) { 21121 key = ev(key, compressor); 21122 } 21123 if (typeof Object.prototype[key] === 'function') { 21124 throw def; 21125 } 21126 val[key] = ev(prop.value, compressor); 21127 } 21128 return val; 21129 } 21130 throw def; 21131 }); 21132 def(AST_UnaryPrefix, function(compressor){ 21133 var e = this.expression; 21134 switch (this.operator) { 21135 case "!": return !ev(e, compressor); 21136 case "typeof": 21137 // Function would be evaluated to an array and so typeof would 21138 // incorrectly return 'object'. Hence making is a special case. 21139 if (e instanceof AST_Function) return typeof function(){}; 21140 21141 e = ev(e, compressor); 21142 21143 // typeof <RegExp> returns "object" or "function" on different platforms 21144 // so cannot evaluate reliably 21145 if (e instanceof RegExp) throw def; 21146 21147 return typeof e; 21148 case "void": return void ev(e, compressor); 21149 case "~": return ~ev(e, compressor); 21150 case "-": return -ev(e, compressor); 21151 case "+": return +ev(e, compressor); 21152 } 21153 throw def; 21154 }); 21155 def(AST_Binary, function(c){ 21156 var left = this.left, right = this.right, result; 21157 switch (this.operator) { 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 case ">>" : result = ev(left, c) >> ev(right, c); break; 21170 case ">>>" : result = ev(left, c) >>> ev(right, c); break; 21171 case "==" : result = ev(left, c) == ev(right, c); break; 21172 case "===" : result = ev(left, c) === ev(right, c); break; 21173 case "!=" : result = ev(left, c) != ev(right, c); break; 21174 case "!==" : result = ev(left, c) !== ev(right, c); break; 21175 case "<" : result = ev(left, c) < ev(right, c); break; 21176 case "<=" : result = ev(left, c) <= ev(right, c); break; 21177 case ">" : result = ev(left, c) > ev(right, c); break; 21178 case ">=" : result = ev(left, c) >= ev(right, c); break; 21179 default: 21180 throw def; 21181 } 21182 if (isNaN(result) && c.find_parent(AST_With)) { 21183 // leave original expression as is 21184 throw def; 21185 } 21186 return result; 21187 }); 21188 def(AST_Conditional, function(compressor){ 21189 return ev(this.condition, compressor) 21190 ? ev(this.consequent, compressor) 21191 : ev(this.alternative, compressor); 21192 }); 21193 def(AST_SymbolRef, function(compressor){ 21194 if (!compressor.option("reduce_vars") || this._evaluating) throw def; 21195 this._evaluating = true; 21196 try { 21197 var fixed = this.fixed_value(); 21198 if (!fixed) throw def; 21199 var value = ev(fixed, compressor); 21200 if (!HOP(fixed, "_eval")) fixed._eval = function() { 21201 return value; 21202 }; 21203 if (value && typeof value == "object" && this.definition().escaped) throw def; 21204 return value; 21205 } finally { 21206 this._evaluating = false;
vendor: 5,047 bytes, lines 21207-21304
21207 } 21208 }); 21209 def(AST_PropAccess, function(compressor){ 21210 if (compressor.option("unsafe")) { 21211 var key = this.property; 21212 if (key instanceof AST_Node) { 21213 key = ev(key, compressor); 21214 } 21215 var val = ev(this.expression, compressor); 21216 if (val && HOP(val, key)) { 21217 return val[key]; 21218 } 21219 } 21220 throw def; 21221 }); 21222 })(function(node, func){ 21223 node.DEFMETHOD("_eval", func); 21224 }); 21225 21226 // method to negate an expression 21227 (function(def){ 21228 function basic_negation(exp) { 21229 return make_node(AST_UnaryPrefix, exp, { 21230 operator: "!", 21231 expression: exp 21232 }); 21233 } 21234 function best(orig, alt, first_in_statement) { 21235 var negated = basic_negation(orig); 21236 if (first_in_statement) { 21237 var stat = make_node(AST_SimpleStatement, alt, { 21238 body: alt 21239 }); 21240 return best_of_expression(negated, stat) === stat ? alt : negated; 21241 } 21242 return best_of_expression(negated, alt); 21243 } 21244 def(AST_Node, function(){ 21245 return basic_negation(this); 21246 }); 21247 def(AST_Statement, function(){ 21248 throw new Error("Cannot negate a statement"); 21249 }); 21250 def(AST_Function, function(){ 21251 return basic_negation(this); 21252 }); 21253 def(AST_UnaryPrefix, function(){ 21254 if (this.operator == "!") 21255 return this.expression; 21256 return basic_negation(this); 21257 }); 21258 def(AST_Seq, function(compressor){ 21259 var self = this.clone(); 21260 self.cdr = self.cdr.negate(compressor); 21261 return self; 21262 }); 21263 def(AST_Conditional, function(compressor, first_in_statement){ 21264 var self = this.clone(); 21265 self.consequent = self.consequent.negate(compressor); 21266 self.alternative = self.alternative.negate(compressor); 21267 return best(this, self, first_in_statement); 21268 }); 21269 def(AST_Binary, function(compressor, first_in_statement){ 21270 var self = this.clone(), op = this.operator; 21271 if (compressor.option("unsafe_comps")) { 21272 switch (op) { 21273 case "<=" : self.operator = ">" ; return self; 21274 case "<" : self.operator = ">=" ; return self; 21275 case ">=" : self.operator = "<" ; return self; 21276 case ">" : self.operator = "<=" ; return self; 21277 } 21278 } 21279 switch (op) { 21280 case "==" : self.operator = "!="; return self; 21281 case "!=" : self.operator = "=="; return self; 21282 case "===": self.operator = "!=="; return self; 21283 case "!==": self.operator = "==="; return self; 21284 case "&&": 21285 self.operator = "||"; 21286 self.left = self.left.negate(compressor, first_in_statement); 21287 self.right = self.right.negate(compressor); 21288 return best(this, self, first_in_statement); 21289 case "||": 21290 self.operator = "&&"; 21291 self.left = self.left.negate(compressor, first_in_statement); 21292 self.right = self.right.negate(compressor); 21293 return best(this, self, first_in_statement); 21294 } 21295 return basic_negation(this); 21296 }); 21297 })(function(node, func){ 21298 node.DEFMETHOD("negate", function(compressor, first_in_statement){ 21299 return func.call(this, compressor, first_in_statement); 21300 }); 21301 }); 21302 21303 AST_Call.DEFMETHOD("has_pure_annotation", function(compressor) { 21304 if (!compressor.option("side_effects")) return false;
21305 if (this.pure !== undefined) return this.pure; 21306 var pure = false; 21307 var comments, last_comment; 21308 if (this.start 21309 && (comments = this.start.comments_before) 21310 && comments.length 21311 && /[@#]__PURE__/.test((last_comment = comments[comments.length - 1]).value)) { 21312 pure = last_comment; 21313 } 21314 return this.pure = pure; 21315 }); 21316 21317 // determine if expression has side effects 21318 (function(def){ 21319 def(AST_Node, return_true); 21320 21321 def(AST_EmptyStatement, return_false); 21322 def(AST_Constant, return_false); 21323 def(AST_This, return_false); 21324 21325 def(AST_Call, function(compressor){ 21326 if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return true; 21327 for (var i = this.args.length; --i >= 0;) { 21328 if (this.args[i].has_side_effects(compressor)) 21329 return true; 21330 } 21331 return false; 21332 }); 21333 21334 function any(list, compressor) { 21335 for (var i = list.length; --i >= 0;) 21336 if (list[i].has_side_effects(compressor)) 21337 return true; 21338 return false; 21339 } 21340 21341 def(AST_Block, function(compressor){ 21342 return any(this.body, compressor); 21343 }); 21344 def(AST_Switch, function(compressor){ 21345 return this.expression.has_side_effects(compressor) 21346 || any(this.body, compressor); 21347 }); 21348 def(AST_Case, function(compressor){ 21349 return this.expression.has_side_effects(compressor) 21350 || any(this.body, compressor); 21351 }); 21352 def(AST_Try, function(compressor){ 21353 return any(this.body, compressor) 21354 || this.bcatch && this.bcatch.has_side_effects(compressor) 21355 || this.bfinally && this.bfinally.has_side_effects(compressor); 21356 }); 21357 def(AST_If, function(compressor){ 21358 return this.condition.has_side_effects(compressor) 21359 || this.body && this.body.has_side_effects(compressor) 21360 || this.alternative && this.alternative.has_side_effects(compressor); 21361 }); 21362 def(AST_LabeledStatement, function(compressor){ 21363 return this.body.has_side_effects(compressor); 21364 }); 21365 def(AST_SimpleStatement, function(compressor){ 21366 return this.body.has_side_effects(compressor); 21367 }); 21368 def(AST_Defun, return_true); 21369 def(AST_Function, return_false); 21370 def(AST_Binary, function(compressor){ 21371 return this.left.has_side_effects(compressor) 21372 || this.right.has_side_effects(compressor); 21373 }); 21374 def(AST_Assign, return_true); 21375 def(AST_Conditional, function(compressor){ 21376 return this.condition.has_side_effects(compressor) 21377 || this.consequent.has_side_effects(compressor) 21378 || this.alternative.has_side_effects(compressor); 21379 }); 21380 def(AST_Unary, function(compressor){ 21381 return unary_side_effects(this.operator) 21382 || this.expression.has_side_effects(compressor); 21383 }); 21384 def(AST_SymbolRef, function(compressor){ 21385 return this.undeclared(); 21386 }); 21387 def(AST_Object, function(compressor){ 21388 return any(this.properties, compressor); 21389 }); 21390 def(AST_ObjectProperty, function(compressor){ 21391 return this.value.has_side_effects(compressor); 21392 }); 21393 def(AST_Array, function(compressor){ 21394 return any(this.elements, compressor); 21395 }); 21396 def(AST_Dot, function(compressor){ 21397 return this.expression.may_throw_on_access(compressor) 21398 || this.expression.has_side_effects(compressor); 21399 }); 21400 def(AST_Sub, function(compressor){ 21401 return this.expression.may_throw_on_access(compressor) 21402 || this.expression.has_side_effects(compressor) 21403 || this.property.has_side_effects(compressor); 21404 }); 21405 def(AST_Seq, function(compressor){ 21406 return this.car.has_side_effects(compressor) 21407 || this.cdr.has_side_effects(compressor); 21408 }); 21409 })(function(node, func){ 21410 node.DEFMETHOD("has_side_effects", func); 21411 }); 21412 21413 // tell me if a statement aborts 21414 function aborts(thing) { 21415 return thing && thing.aborts(); 21416 }; 21417 (function(def){ 21418 def(AST_Statement, return_null); 21419 def(AST_Jump, return_this); 21420 function block_aborts(){ 21421 var n = this.body.length; 21422 return n > 0 && aborts(this.body[n - 1]); 21423 }; 21424 def(AST_BlockStatement, block_aborts); 21425 def(AST_SwitchBranch, block_aborts); 21426 def(AST_If, function(){ 21427 return this.alternative && aborts(this.body) && aborts(this.alternative) && this; 21428 }); 21429 })(function(node, func){ 21430 node.DEFMETHOD("aborts", func); 21431 }); 21432 21433 /* -----[ optimizers ]----- */ 21434 21435 OPT(AST_Directive, function(self, compressor){ 21436 if (compressor.has_directive(self.value) !== self) { 21437 return make_node(AST_EmptyStatement, self); 21438 } 21439 return self; 21440 }); 21441 21442 OPT(AST_Debugger, function(self, compressor){ 21443 if (compressor.option("drop_debugger")) 21444 return make_node(AST_EmptyStatement, self); 21445 return self; 21446 }); 21447 21448 OPT(AST_LabeledStatement, function(self, compressor){ 21449 if (self.body instanceof AST_Break 21450 && compressor.loopcontrol_target(self.body) === self.body) { 21451 return make_node(AST_EmptyStatement, self); 21452 } 21453 return self.label.references.length == 0 ? self.body : self; 21454 }); 21455 21456 OPT(AST_Block, function(self, compressor){ 21457 self.body = tighten_body(self.body, compressor); 21458 return self; 21459 }); 21460 21461 OPT(AST_BlockStatement, function(self, compressor){ 21462 self.body = tighten_body(self.body, compressor); 21463 switch (self.body.length) { 21464 case 1: return self.body[0]; 21465 case 0: return make_node(AST_EmptyStatement, self); 21466 } 21467 return self; 21468 }); 21469 21470 AST_Scope.DEFMETHOD("drop_unused", function(compressor){ 21471 var self = this; 21472 if (compressor.has_directive("use asm")) return self; 21473 var toplevel = compressor.option("toplevel"); 21474 if (compressor.option("unused") 21475 && (!(self instanceof AST_Toplevel) || toplevel) 21476 && !self.uses_eval 21477 && !self.uses_with) { 21478 var assign_as_unused = !/keep_assign/.test(compressor.option("unused"));
21479 var drop_funcs = /funcs/.test(toplevel); 21480 var drop_vars = /vars/.test(toplevel); 21481 if (!(self instanceof AST_Toplevel) || toplevel == true) { 21482 drop_funcs = drop_vars = true; 21483 } 21484 var in_use = []; 21485 var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use 21486 if (self instanceof AST_Toplevel && compressor.top_retain) { 21487 self.variables.each(function(def) { 21488 if (compressor.top_retain(def) && !(def.id in in_use_ids)) { 21489 in_use_ids[def.id] = true; 21490 in_use.push(def); 21491 } 21492 }); 21493 } 21494 var initializations = new Dictionary(); 21495 // pass 1: find out which symbols are directly used in 21496 // this scope (not in nested scopes). 21497 var scope = this; 21498 var tw = new TreeWalker(function(node, descend){ 21499 if (node !== self) { 21500 if (node instanceof AST_Defun) { 21501 if (!drop_funcs && scope === self) { 21502 var node_def = node.name.definition(); 21503 if (!(node_def.id in in_use_ids)) { 21504 in_use_ids[node_def.id] = true; 21505 in_use.push(node_def); 21506 } 21507 } 21508 initializations.add(node.name.name, node); 21509 return true; // don't go in nested scopes 21510 } 21511 if (node instanceof AST_Definitions && scope === self) { 21512 node.definitions.forEach(function(def){ 21513 if (!drop_vars) { 21514 var node_def = def.name.definition(); 21515 if (!(node_def.id in in_use_ids)) { 21516 in_use_ids[node_def.id] = true; 21517 in_use.push(node_def); 21518 } 21519 } 21520 if (def.value) { 21521 initializations.add(def.name.name, def.value); 21522 if (def.value.has_side_effects(compressor)) { 21523 def.value.walk(tw); 21524 } 21525 } 21526 }); 21527 return true; 21528 } 21529 if (assign_as_unused 21530 && node instanceof AST_Assign 21531 && node.operator == "=" 21532 && node.left instanceof AST_SymbolRef 21533 && !is_reference_const(node.left) 21534 && scope === self) { 21535 node.right.walk(tw); 21536 return true; 21537 } 21538 if (node instanceof AST_SymbolRef) { 21539 var node_def = node.definition(); 21540 if (!(node_def.id in in_use_ids)) { 21541 in_use_ids[node_def.id] = true; 21542 in_use.push(node_def); 21543 } 21544 return true; 21545 } 21546 if (node instanceof AST_Scope) { 21547 var save_scope = scope; 21548 scope = node; 21549 descend(); 21550 scope = save_scope; 21551 return true; 21552 } 21553 } 21554 }); 21555 self.walk(tw); 21556 // pass 2: for every used symbol we need to walk its 21557 // initialization code to figure out if it uses other 21558 // symbols (that may not be in_use). 21559 for (var i = 0; i < in_use.length; ++i) { 21560 in_use[i].orig.forEach(function(decl){ 21561 // undeclared globals will be instanceof AST_SymbolRef 21562 var init = initializations.get(decl.name); 21563 if (init) init.forEach(function(init){ 21564 var tw = new TreeWalker(function(node){ 21565 if (node instanceof AST_SymbolRef) { 21566 var node_def = node.definition(); 21567 if (!(node_def.id in in_use_ids)) { 21568 in_use_ids[node_def.id] = true; 21569 in_use.push(node_def); 21570 } 21571 } 21572 }); 21573 init.walk(tw); 21574 }); 21575 }); 21576 } 21577 // pass 3: we should drop declarations not in_use 21578 var tt = new TreeTransformer( 21579 function before(node, descend, in_list) { 21580 if (node instanceof AST_Function 21581 && node.name 21582 && !compressor.option("keep_fnames")) { 21583 var def = node.name.definition(); 21584 // any declarations with same name will overshadow 21585 // name of this anonymous function and can therefore 21586 // never be used anywhere 21587 if (!(def.id in in_use_ids) || def.orig.length > 1) 21588 node.name = null; 21589 } 21590 if (node instanceof AST_Lambda && !(node instanceof AST_Acce
21590ssor)) { 21591 var trim = !compressor.option("keep_fargs"); 21592 for (var a = node.argnames, i = a.length; --i >= 0;) { 21593 var sym = a[i]; 21594 if (!(sym.definition().id in in_use_ids)) { 21595 sym.__unused = true; 21596 if (trim) { 21597 a.pop(); 21598 compressor[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", { 21599 name : sym.name, 21600 file : sym.start.file, 21601 line : sym.start.line, 21602 col : sym.start.col 21603 }); 21604 } 21605 } 21606 else { 21607 trim = false;
21608 } 21609 } 21610 } 21611 if (drop_funcs && node instanceof AST_Defun && node !== self) { 21612 if (!(node.name.definition().id in in_use_ids)) { 21613 compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", { 21614 name : node.name.name, 21615 file : node.name.start.file, 21616 line : node.name.start.line, 21617 col : node.name.start.col 21618 }); 21619 return make_node(AST_EmptyStatement, node); 21620 } 21621 return node; 21622 } 21623 if (drop_vars && node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn && tt.parent().init === node)) { 21624 var def = node.definitions.filter(function(def){ 21625 if (def.value) def.value = def.value.transform(tt); 21626 var sym = def.name.definition(); 21627 if (sym.id in in_use_ids) return true; 21628 if (sym.orig[0] instanceof AST_SymbolCatch) { 21629 def.value = def.value && def.value.drop_side_effect_free(compressor); 21630 return true; 21631 } 21632 var w = { 21633 name : def.name.name, 21634 file : def.name.start.file, 21635 line : def.name.start.line, 21636 col : def.name.start.col 21637 }; 21638 if (def.value && (def._unused_side_effects = def.value.drop_side_effect_free(compressor))) { 21639 compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); 21640 return true; 21641 } 21642 compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", w); 21643 return false; 21644 }); 21645 // place uninitialized names at the start 21646 def = mergeSort(def, function(a, b){ 21647 if (!a.value && b.value) return -1; 21648 if (!b.value && a.value) return 1; 21649 return 0; 21650 }); 21651 // for unused names whose initialization has 21652 // side effects, we can cascade the init. code 21653 // into the next one, or next statement. 21654 var side_effects = []; 21655 for (var i = 0; i < def.length;) { 21656 var x = def[i]; 21657 if (x._unused_side_effects) { 21658 side_effects.push(x._unused_side_effects); 21659 def.splice(i, 1); 21660 } else { 21661 if (side_effects.length > 0) { 21662 side_effects.push(x.value); 21663 x.value = AST_Seq.from_array(side_effects); 21664 side_effects = []; 21665 } 21666 ++i; 21667 } 21668 } 21669 if (side_effects.length > 0) { 21670 side_effects = make_node(AST_BlockStatement, node, { 21671 body: [ make_node(AST_SimpleStatement, node, { 21672 body: AST_Seq.from_array(side_effects) 21673 }) ] 21674 }); 21675 } else { 21676 side_effects = null; 21677 } 21678 if (def.length == 0 && !side_effects) { 21679 return make_node(AST_EmptyStatement, node); 21680 } 21681 if (def.length == 0) { 21682 return in_list ? MAP.splice(side_effects.body) : side_effects; 21683 } 21684 node.definitions = def; 21685 if (side_effects) { 21686 side_effects.body.unshift(node); 21687 return in_list ? MAP.splice(side_effects.body) : side_effects; 21688 } 21689 return node; 21690 } 21691 if (drop_vars && assign_as_unused 21692 && node instanceof AST_Assign 21693 && node.operator == "=" 21694 && node.left instanceof AST_SymbolRef) { 21695 var def = node.left.definition(); 21696 if (!(def.id in in_use_ids) 21697 && self.variables.get(def.name) === def) { 21698 return maintain_this_binding(tt.parent(), node, node.right.transform(tt)); 21699 } 21700 } 21701 // certain combination of unused name + side effect leads to: 21702 // https://github.com/mishoo/UglifyJS2/issues/44 21703 // https://github.com/mishoo/UglifyJS2/issues/1830
vendor: 5,228 bytes, lines 21704-21790
21704 // that's an invalid AST. 21705 // We fix it at this stage by moving the `var` outside the `for`. 21706 if (node instanceof AST_For) { 21707 descend(node, this); 21708 if (node.init instanceof AST_BlockStatement) { 21709 var block = node.init; 21710 node.init = block.body.pop(); 21711 block.body.push(node); 21712 return in_list ? MAP.splice(block.body) : block; 21713 } else if (is_empty(node.init)) { 21714 node.init = null; 21715 } 21716 return node; 21717 } 21718 if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) { 21719 descend(node, this); 21720 if (node.body instanceof AST_BlockStatement) { 21721 var block = node.body; 21722 node.body = block.body.pop(); 21723 block.body.push(node); 21724 return in_list ? MAP.splice(block.body) : block; 21725 } 21726 return node; 21727 } 21728 if (node instanceof AST_Scope && node !== self) 21729 return node; 21730 } 21731 ); 21732 self.transform(tt); 21733 } 21734 }); 21735 21736 AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ 21737 var self = this; 21738 if (compressor.has_directive("use asm")) return self; 21739 var hoist_funs = compressor.option("hoist_funs"); 21740 var hoist_vars = compressor.option("hoist_vars"); 21741 if (hoist_funs || hoist_vars) { 21742 var dirs = []; 21743 var hoisted = []; 21744 var vars = new Dictionary(), vars_found = 0, var_decl = 0; 21745 // let's count var_decl first, we seem to waste a lot of 21746 // space if we hoist `var` when there's only one. 21747 self.walk(new TreeWalker(function(node){ 21748 if (node instanceof AST_Scope && node !== self) 21749 return true; 21750 if (node instanceof AST_Var) { 21751 ++var_decl; 21752 return true; 21753 } 21754 })); 21755 hoist_vars = hoist_vars && var_decl > 1; 21756 var tt = new TreeTransformer( 21757 function before(node) { 21758 if (node !== self) { 21759 if (node instanceof AST_Directive) { 21760 dirs.push(node); 21761 return make_node(AST_EmptyStatement, node); 21762 } 21763 if (node instanceof AST_Defun && hoist_funs) { 21764 hoisted.push(node); 21765 return make_node(AST_EmptyStatement, node); 21766 } 21767 if (node instanceof AST_Var && hoist_vars) { 21768 node.definitions.forEach(function(def){ 21769 vars.set(def.name.name, def); 21770 ++vars_found; 21771 }); 21772 var seq = node.to_assignments(compressor); 21773 var p = tt.parent(); 21774 if (p instanceof AST_ForIn && p.init === node) { 21775 if (seq == null) { 21776 var def = node.definitions[0].name; 21777 return make_node(AST_SymbolRef, def, def); 21778 } 21779 return seq; 21780 } 21781 if (p instanceof AST_For && p.init === node) { 21782 return seq; 21783 } 21784 if (!seq) return make_node(AST_EmptyStatement, node); 21785 return make_node(AST_SimpleStatement, node, { 21786 body: seq 21787 }); 21788 } 21789 if (node instanceof AST_Scope) 21790 return node;
vendor: 4,235 bytes, lines 21790-21864
21790 // to avoid descending in nested scopes 21791 } 21792 } 21793 ); 21794 self = self.transform(tt); 21795 if (vars_found > 0) { 21796 // collect only vars which don't show up in self's arguments list 21797 var defs = []; 21798 vars.each(function(def, name){ 21799 if (self instanceof AST_Lambda 21800 && find_if(function(x){ return x.name == def.name.name }, 21801 self.argnames)) { 21802 vars.del(name); 21803 } else { 21804 def = def.clone(); 21805 def.value = null; 21806 defs.push(def); 21807 vars.set(name, def); 21808 } 21809 }); 21810 if (defs.length > 0) { 21811 // try to merge in assignments 21812 for (var i = 0; i < self.body.length;) { 21813 if (self.body[i] instanceof AST_SimpleStatement) { 21814 var expr = self.body[i].body, sym, assign; 21815 if (expr instanceof AST_Assign 21816 && expr.operator == "=" 21817 && (sym = expr.left) instanceof AST_Symbol 21818 && vars.has(sym.name)) 21819 { 21820 var def = vars.get(sym.name); 21821 if (def.value) break; 21822 def.value = expr.right; 21823 remove(defs, def); 21824 defs.push(def); 21825 self.body.splice(i, 1); 21826 continue; 21827 } 21828 if (expr instanceof AST_Seq 21829 && (assign = expr.car) instanceof AST_Assign 21830 && assign.operator == "=" 21831 && (sym = assign.left) instanceof AST_Symbol 21832 && vars.has(sym.name)) 21833 { 21834 var def = vars.get(sym.name); 21835 if (def.value) break; 21836 def.value = assign.right; 21837 remove(defs, def); 21838 defs.push(def); 21839 self.body[i].body = expr.cdr; 21840 continue; 21841 } 21842 } 21843 if (self.body[i] instanceof AST_EmptyStatement) { 21844 self.body.splice(i, 1); 21845 continue; 21846 } 21847 if (self.body[i] instanceof AST_BlockStatement) { 21848 var tmp = [ i, 1 ].concat(self.body[i].body); 21849 self.body.splice.apply(self.body, tmp); 21850 continue; 21851 } 21852 break; 21853 } 21854 defs = make_node(AST_Var, self, { 21855 definitions: defs 21856 }); 21857 hoisted.push(defs); 21858 }; 21859 } 21860 self.body = dirs.concat(hoisted, self.body); 21861 } 21862 return self; 21863 }); 21864
21865 // drop_side_effect_free() 21866 // remove side-effect-free parts which only affects return value 21867 (function(def){ 21868 // Drop side-effect-free elements from an array of expressions. 21869 // Returns an array of expressions with side-effects or null 21870 // if all elements were dropped. Note: original array may be 21871 // returned if nothing changed. 21872 function trim(nodes, compressor, first_in_statement) { 21873 var ret = [], changed = false; 21874 for (var i = 0, len = nodes.length; i < len; i++) { 21875 var node = nodes[i].drop_side_effect_free(compressor, first_in_statement); 21876 changed |= node !== nodes[i]; 21877 if (node) { 21878 ret.push(node); 21879 first_in_statement = false; 21880 } 21881 } 21882 return changed ? ret.length ? ret : null : nodes; 21883 } 21884 21885 def(AST_Node, return_this); 21886 def(AST_Constant, return_null); 21887 def(AST_This, return_null); 21888 def(AST_Call, function(compressor, first_in_statement){ 21889 if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) { 21890 if (this.expression instanceof AST_Function 21891 && (!this.expression.name || !this.expression.name.definition().references.length)) { 21892 var node = this.clone(); 21893 node.expression = node.expression.process_expression(false, compressor); 21894 return node; 21895 } 21896 return this; 21897 } 21898 if (this.pure) { 21899 compressor.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start); 21900 this.pure.value = this.pure.value.replace(/[@#]__PURE__/g, ' '); 21901 } 21902 var args = trim(this.args, compressor, first_in_statement); 21903 return args && AST_Seq.from_array(args); 21904 }); 21905 def(AST_Accessor, return_null); 21906 def(AST_Function, return_null); 21907 def(AST_Binary, function(compressor, first_in_statement){ 21908 var right = this.right.drop_side_effect_free(compressor); 21909 if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement); 21910 switch (this.operator) { 21911 case "&&": 21912 case "||": 21913 if (right === this.right) return this; 21914 var node = this.clone(); 21915 node.right = right; 21916 return node; 21917 default: 21918 var left = this.left.drop_side_effect_free(compressor, first_in_statement); 21919 if (!left) return this.right.drop_side_effect_free(compressor, first_in_statement); 21920 return make_node(AST_Seq, this, { 21921 car: left, 21922 cdr: right 21923 }); 21924 } 21925 }); 21926 def(AST_Assign, return_this); 21927 def(AST_Conditional, function(compressor){ 21928 var consequent = this.consequent.drop_side_effect_free(compressor); 21929 var alternative = this.alternative.drop_side_effect_free(compressor); 21930 if (consequent === this.consequent && alternative === this.alternative) return this; 21931 if (!consequent) return alternative ? make_node(AST_Binary, this, { 21932 operator: "||", 21933 left: this.condition, 21934 right: alternative 21935 }) : this.condition.drop_side_effect_free(compressor); 21936 if (!alternative) return make_node(AST_Binary, this, { 21937 operator: "&&", 21938 left: this.condition, 21939 right: consequent 21940 }); 21941 var node = this.clone(); 21942 node.consequent = consequent; 21943 node.alternative = alternative; 21944 return node; 21945 }); 21946 def(AST_Unary, function(compressor, first_in_statement){ 21947 if (unary_side_effects(this.operator)) return this; 21948 if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) return null; 21949 var expression = this.expression.drop_side_effect_free(compressor, first_in_statement); 21950 if (first_in_statement 21951 && this instanceof AST_UnaryPrefix 21952 && is_iife_call(expression)) { 21953 if (expression === this.expression && this.operator.length === 1) return this; 21954 return make_node(AST_UnaryPrefix, this, { 21955 operator: this.operator.length === 1 ? this.operator : "!", 21956 expression: expression 21957 }); 21958 } 21959 return expression; 21960 }); 21961 def(AST_SymbolRef, function() {
21962 return this.undeclared() ? this : null; 21963 }); 21964 def(AST_Object, function(compressor, first_in_statement){ 21965 var values = trim(this.properties, compressor, first_in_statement); 21966 return values && AST_Seq.from_array(values); 21967 }); 21968 def(AST_ObjectProperty, function(compressor, first_in_statement){ 21969 return this.value.drop_side_effect_free(compressor, first_in_statement); 21970 }); 21971 def(AST_Array, function(compressor, first_in_statement){ 21972 var values = trim(this.elements, compressor, first_in_statement); 21973 return values && AST_Seq.from_array(values); 21974 }); 21975 def(AST_Dot, function(compressor, first_in_statement){ 21976 if (this.expression.may_throw_on_access(compressor)) return this; 21977 return this.expression.drop_side_effect_free(compressor, first_in_statement); 21978 }); 21979 def(AST_Sub, function(compressor, first_in_statement){ 21980 if (this.expression.may_throw_on_access(compressor)) return this; 21981 var expression = this.expression.drop_side_effect_free(compressor, first_in_statement); 21982 if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement); 21983 var property = this.property.drop_side_effect_free(compressor); 21984 if (!property) return expression; 21985 return make_node(AST_Seq, this, { 21986 car: expression, 21987 cdr: property 21988 }); 21989 }); 21990 def(AST_Seq, function(compressor){ 21991 var cdr = this.cdr.drop_side_effect_free(compressor); 21992 if (cdr === this.cdr) return this; 21993 if (!cdr) return this.car; 21994 return make_node(AST_Seq, this, { 21995 car: this.car, 21996 cdr: cdr 21997 }); 21998 }); 21999 })(function(node, func){ 22000 node.DEFMETHOD("drop_side_effect_free", func); 22001 }); 22002 22003 OPT(AST_SimpleStatement, function(self, compressor){ 22004 if (compressor.option("side_effects")) { 22005 var body = self.body; 22006 var node = body.drop_side_effect_free(compressor, true); 22007 if (!node) { 22008 compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); 22009 return make_node(AST_EmptyStatement, self); 22010 } 22011 if (node !== body) { 22012 return make_node(AST_SimpleStatement, self, { body: node }); 22013 } 22014 } 22015 return self; 22016 }); 22017 22018 OPT(AST_DWLoop, function(self, compressor){ 22019 if (!compressor.option("loops")) return self; 22020 var cond = self.condition.evaluate(compressor); 22021 if (cond !== self.condition) { 22022 if (cond) { 22023 return make_node(AST_For, self, { 22024 body: self.body 22025 }); 22026 } 22027 if (compressor.option("dead_code") && self instanceof AST_While) { 22028 var a = []; 22029 extract_declarations_from_unreachable_code(compressor, self.body, a); 22030 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor); 22031 } 22032 if (self instanceof AST_Do) { 22033 var has_loop_control = false; 22034 var tw = new TreeWalker(function(node) { 22035 if (node instanceof AST_Scope || has_loop_control) return true;
22036 if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self) 22037 return has_loop_control = true; 22038 }); 22039 var parent = compressor.parent(); 22040 (parent instanceof AST_LabeledStatement ? parent : self).walk(tw); 22041 if (!has_loop_control) return self.body; 22042 } 22043 } 22044 if (self instanceof AST_While) { 22045 return make_node(AST_For, self, self).optimize(compressor); 22046 } 22047 return self; 22048 }); 22049 22050 function if_break_in_loop(self, compressor) { 22051 function drop_it(rest) { 22052 rest = as_statement_array(rest); 22053 if (self.body instanceof AST_BlockStatement) { 22054 self.body = self.body.clone(); 22055 self.body.body = rest.concat(self.body.body.slice(1)); 22056 self.body = self.body.transform(compressor); 22057 } else { 22058 self.body = make_node(AST_BlockStatement, self.body, { 22059 body: rest 22060 }).transform(compressor); 22061 } 22062 if_break_in_loop(self, compressor); 22063 } 22064 var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; 22065 if (first instanceof AST_If) { 22066 if (first.body instanceof AST_Break 22067 && compressor.loopcontrol_target(first.body) === compressor.self()) { 22068 if (self.condition) { 22069 self.condition = make_node(AST_Binary, self.condition, { 22070 left: self.condition, 22071 operator: "&&", 22072 right: first.condition.negate(compressor), 22073 }); 22074 } else { 22075 self.condition = first.condition.negate(compressor); 22076 } 22077 drop_it(first.alternative); 22078 } 22079 else if (first.alternative instanceof AST_Break 22080 && compressor.loopcontrol_target(first.alternative) === compressor.self()) { 22081 if (self.condition) { 22082 self.condition = make_node(AST_Binary, self.condition, { 22083 left: self.condition, 22084 operator: "&&", 22085 right: first.condition, 22086 }); 22087 } else { 22088 self.condition = first.condition; 22089 } 22090 drop_it(first.body); 22091 } 22092 } 22093 }; 22094 22095 OPT(AST_For, function(self, compressor){ 22096 if (!compressor.option("loops")) return self; 22097 if (self.condition) { 22098 var cond = self.condition.evaluate(compressor); 22099 if (compressor.option("dead_code") && !cond) { 22100 var a = []; 22101 if (self.init instanceof AST_Statement) { 22102 a.push(self.init); 22103 } 22104 else if (self.init) { 22105 a.push(make_node(AST_SimpleStatement, self.init, { 22106 body: self.init 22107 })); 22108 } 22109 extract_declarations_from_unreachable_code(compressor, self.body, a); 22110 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor); 22111 } 22112 if (cond !== self.condition) { 22113 cond = make_node_from_constant(cond, self.condition).transform(compressor); 22114 self.condition = best_of_expression(cond, self.condition); 22115 } 22116 } 22117 if_break_in_loop(self, compressor); 22118 return self; 22119 }); 22120 22121 OPT(AST_If, function(self, compressor){ 22122 if (is_empty(self.alternative)) self.alternative = null; 22123 22124 if (!compressor.option("conditionals")) return self; 22125 // if condition can be statically determined, warn and drop 22126 // one of the blocks. note, statically determined implies 22127 // âhas no side effectsâ; also it doesn't work for cases like 22128 // `x && true`, though it probably should. 22129 var cond = self.condition.evaluate(compressor); 22130 if (cond !== self.condition) { 22131 if (cond) { 22132 compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); 22133 if (compressor.option("dead_code")) { 22134 var a = []; 22135 if (self.alternative) { 22136 extract_declarations_from_unreachable_code(compressor, self.alternative, a); 22137 } 22138 a.push(self.body); 22139 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor); 22140 } 22141 } else { 22142 compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); 22143 if (compressor.option("dead_code")) { 22144 var a = []; 22145 extract_declarations_from_unreachable_code(compressor, self.body, a); 22146 if (self.alternative) a.push(self.alternative); 22147 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor); 22148 } 22149 } 22150 cond = make_node_from_constant(cond, self.condition).transform(compressor); 22151 self.condition = best_of_expression(cond, self.condition); 22152 } 22153 var negated = self.condition.negate(compressor); 22154 var self_condition_length = self.condition.print_to_string().length; 22155 var negated_length = negated.print_to_string().length;
vendor: 5,467 bytes, lines 22156-22249
22156 var negated_is_best = negated_length < self_condition_length; 22157 if (self.alternative && negated_is_best) { 22158 negated_is_best = false; // because we already do the switch here. 22159 // no need to swap values of self_condition_length and negated_length 22160 // here because they are only used in an equality comparison later on. 22161 self.condition = negated; 22162 var tmp = self.body; 22163 self.body = self.alternative || make_node(AST_EmptyStatement, self); 22164 self.alternative = tmp; 22165 } 22166 if (is_empty(self.body) && is_empty(self.alternative)) { 22167 return make_node(AST_SimpleStatement, self.condition, { 22168 body: self.condition.clone() 22169 }).optimize(compressor); 22170 } 22171 if (self.body instanceof AST_SimpleStatement 22172 && self.alternative instanceof AST_SimpleStatement) { 22173 return make_node(AST_SimpleStatement, self, { 22174 body: make_node(AST_Conditional, self, { 22175 condition : self.condition, 22176 consequent : self.body.body, 22177 alternative : self.alternative.body 22178 }) 22179 }).optimize(compressor); 22180 } 22181 if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { 22182 if (self_condition_length === negated_length && !negated_is_best 22183 && self.condition instanceof AST_Binary && self.condition.operator == "||") { 22184 // although the code length of self.condition and negated are the same, 22185 // negated does not require additional surrounding parentheses. 22186 // see https://github.com/mishoo/UglifyJS2/issues/979 22187 negated_is_best = true; 22188 } 22189 if (negated_is_best) return make_node(AST_SimpleStatement, self, { 22190 body: make_node(AST_Binary, self, { 22191 operator : "||", 22192 left : negated, 22193 right : self.body.body 22194 }) 22195 }).optimize(compressor); 22196 return make_node(AST_SimpleStatement, self, { 22197 body: make_node(AST_Binary, self, { 22198 operator : "&&", 22199 left : self.condition, 22200 right : self.body.body 22201 }) 22202 }).optimize(compressor); 22203 } 22204 if (self.body instanceof AST_EmptyStatement 22205 && self.alternative instanceof AST_SimpleStatement) { 22206 return make_node(AST_SimpleStatement, self, { 22207 body: make_node(AST_Binary, self, { 22208 operator : "||", 22209 left : self.condition, 22210 right : self.alternative.body 22211 }) 22212 }).optimize(compressor); 22213 } 22214 if (self.body instanceof AST_Exit 22215 && self.alternative instanceof AST_Exit 22216 && self.body.TYPE == self.alternative.TYPE) { 22217 return make_node(self.body.CTOR, self, { 22218 value: make_node(AST_Conditional, self, { 22219 condition : self.condition, 22220 consequent : self.body.value || make_node(AST_Undefined, self.body), 22221 alternative : self.alternative.value || make_node(AST_Undefined, self.alternative) 22222 }).transform(compressor) 22223 }).optimize(compressor); 22224 } 22225 if (self.body instanceof AST_If 22226 && !self.body.alternative 22227 && !self.alternative) { 22228 self = make_node(AST_If, self, { 22229 condition: make_node(AST_Binary, self.condition, { 22230 operator: "&&", 22231 left: self.condition, 22232 right: self.body.condition 22233 }), 22234 body: self.body.body, 22235 alternative: null 22236 }); 22237 } 22238 if (aborts(self.body)) { 22239 if (self.alternative) { 22240 var alt = self.alternative; 22241 self.alternative = null; 22242 return make_node(AST_BlockStatement, self, { 22243 body: [ self, alt ] 22244 }).optimize(compressor); 22245 } 22246 } 22247 if (aborts(self.alternative)) { 22248 var body = self.body; 22249 self.body = self.alternative;
22250 self.condition = negated_is_best ? negated : self.condition.negate(compressor); 22251 self.alternative = null; 22252 return make_node(AST_BlockStatement, self, { 22253 body: [ self, body ] 22254 }).optimize(compressor); 22255 } 22256 return self; 22257 }); 22258 22259 OPT(AST_Switch, function(self, compressor){ 22260 if (!compressor.option("switches")) return self; 22261 var branch; 22262 var value = self.expression.evaluate(compressor); 22263 if (value !== self.expression) { 22264 var expression = make_node_from_constant(value, self.expression).transform(compressor); 22265 self.expression = best_of_expression(expression, self.expression); 22266 } 22267 if (!compressor.option("dead_code")) return self; 22268 var decl = []; 22269 var body = []; 22270 var default_branch; 22271 var exact_match; 22272 for (var i = 0, len = self.body.length; i < len && !exact_match; i++) { 22273 branch = self.body[i]; 22274 if (branch instanceof AST_Default) { 22275 if (!default_branch) { 22276 default_branch = branch; 22277 } else { 22278 eliminate_branch(branch, body[body.length - 1]); 22279 } 22280 } else if (value !== self.expression) { 22281 var exp = branch.expression.evaluate(compressor); 22282 if (exp === value) { 22283 exact_match = branch; 22284 if (default_branch) { 22285 var default_index = body.indexOf(default_branch); 22286 body.splice(default_index, 1); 22287 eliminate_branch(default_branch, body[default_index - 1]); 22288 default_branch = null; 22289 } 22290 } else if (exp !== branch.expression) { 22291 eliminate_branch(branch, body[body.length - 1]); 22292 continue; 22293 } 22294 } 22295 if (aborts(branch)) { 22296 var prev = body[body.length - 1]; 22297 if (aborts(prev) && prev.body.length == branch.body.length 22298 && make_node(AST_BlockStatement, prev, prev).equivalent_to(make_node(AST_BlockStatement, branch, branch))) { 22299 prev.body = []; 22300 } 22301 } 22302 body.push(branch); 22303 } 22304 while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]); 22305 if (body.length > 0) { 22306 body[0].body = decl.concat(body[0].body); 22307 } 22308 self.body = body; 22309 while (branch = body[body.length - 1]) { 22310 var stat = branch.body[branch.body.length - 1]; 22311 if (stat instanceof AST_Break && compressor.loopcontrol_target(stat) === self) 22312 branch.body.pop(); 22313 if (branch.body.length || branch instanceof AST_Case 22314 && (default_branch || branch.expression.has_side_effects(compressor))) break; 22315 if (body.pop() === default_branch) default_branch = null; 22316 } 22317 if (body.length == 0) { 22318 return make_node(AST_BlockStatement, self, { 22319 body: decl.concat(make_node(AST_SimpleStatement, self.expression, { 22320 body: self.expression 22321 })) 22322 }).optimize(compressor); 22323 } 22324 if (body.length == 1 && (body[0] === exact_match || body[0] === default_branch)) { 22325 var has_break = false;
22326 var tw = new TreeWalker(function(node) { 22327 if (has_break 22328 || node instanceof AST_Lambda 22329 || node instanceof AST_SimpleStatement) return true; 22330 if (node instanceof AST_Break && tw.loopcontrol_target(node) === self) 22331 has_break = true; 22332 }); 22333 self.walk(tw); 22334 if (!has_break) { 22335 body = body[0].body.slice(); 22336 body.unshift(make_node(AST_SimpleStatement, self.expression, { 22337 body: self.expression 22338 })); 22339 return make_node(AST_BlockStatement, self, { 22340 body: body 22341 }).optimize(compressor); 22342 } 22343 } 22344 return self; 22345 22346 function eliminate_branch(branch, prev) { 22347 if (prev && !aborts(prev)) { 22348 prev.body = prev.body.concat(branch.body); 22349 } else { 22350 extract_declarations_from_unreachable_code(compressor, branch, decl); 22351 } 22352 } 22353 }); 22354 22355 OPT(AST_Try, function(self, compressor){ 22356 self.body = tighten_body(self.body, compressor); 22357 if (self.bcatch && self.bfinally && all(self.bfinally.body, is_empty)) self.bfinally = null; 22358 if (all(self.body, is_empty)) { 22359 var body = []; 22360 if (self.bcatch) extract_declarations_from_unreachable_code(compressor, self.bcatch, body); 22361 if (self.bfinally) body = body.concat(self.bfinally.body); 22362 return make_node(AST_BlockStatement, self, { 22363 body: body 22364 }).optimize(compressor); 22365 } 22366 return self; 22367 }); 22368 22369 AST_Definitions.DEFMETHOD("remove_initializers", function(){ 22370 this.definitions.forEach(function(def){ def.value = null }); 22371 }); 22372 22373 AST_Definitions.DEFMETHOD("to_assignments", function(compressor){ 22374 var reduce_vars = compressor.option("reduce_vars"); 22375 var assignments = this.definitions.reduce(function(a, def){ 22376 if (def.value) { 22377 var name = make_node(AST_SymbolRef, def.name, def.name); 22378 a.push(make_node(AST_Assign, def, { 22379 operator : "=", 22380 left : name, 22381 right : def.value 22382 })); 22383 if (reduce_vars) name.definition().fixed = false; 22384 } 22385 return a; 22386 }, []); 22387 if (assignments.length == 0) return null; 22388 return AST_Seq.from_array(assignments); 22389 }); 22390 22391 OPT(AST_Definitions, function(self, compressor){ 22392 if (self.definitions.length == 0) 22393 return make_node(AST_EmptyStatement, self); 22394 return self; 22395 }); 22396 22397 OPT(AST_Call, function(self, compressor){ 22398 var exp = self.expression; 22399 if (compressor.option("reduce_vars") 22400 && exp instanceof AST_SymbolRef) { 22401 var def = exp.definition(); 22402 var fixed = exp.fixed_value(); 22403 if (fixed instanceof AST_Defun) { 22404 def.fixed = fixed = make_node(AST_Function, fixed, fixed).clone(true); 22405 } 22406 if (fixed instanceof AST_Function) { 22407 exp = fixed; 22408 if (compressor.option("unused") 22409 && def.references.length == 1 22410 && !(def.scope.uses_arguments 22411 && def.orig[0] instanceof AST_SymbolFunarg) 22412 && !def.scope.uses_eval 22413 && compressor.find_parent(AST_Scope) === def.scope) { 22414 self.expression = exp; 22415 } 22416 } 22417 } 22418 if (compressor.option("unused") 22419 && exp instanceof AST_Function 22420 && !exp.uses_arguments 22421 && !exp.uses_eval) { 22422 var pos = 0, last = 0; 22423 for (var i = 0, len = self.args.length; i < len; i++) { 22424 var trim = i >= exp.argnames.length; 22425 if (trim || exp.argnames[i].__unused) { 22426 var node = self.args[i].drop_side_effect_free(compressor); 22427 if (node) { 22428 self.args[pos++] = node; 22429 } else if (!trim) { 22430 self.args[pos++] = make_node(AST_Number, self.args[i], { 22431 value: 0 22432 }); 22433 continue; 22434 } 22435 } else { 22436 self.args[pos++] = self.args[i]; 22437 } 22438 last = pos; 22439 } 22440 self.args.length = last; 22441 } 22442 if (compressor.option("unsafe")) { 22443 if (exp instanceof AST_SymbolRef && exp.undeclared()) { 22444 switch (exp.name) { 22445 case "Array": 22446 if (self.args.length != 1) { 22447 return make_node(AST_Array, self, { 22448 elements: self.args 22449 }).optimize(compressor); 22450 } 22451 break; 22452 case "Object": 22453 if (self.args.length == 0) { 22454 return make_node(AST_Object, self, { 22455 properties: [] 22456 }); 22457 } 22458 break; 22459 case "String": 22460 if (self.args.length == 0) return make_node(AST_String, self, { 22461 value: "" 22462 }); 22463 if (self.args.length <= 1) return make_node(AST_Binary, self, { 22464 left: self.args[0], 22465 operator: "+", 22466 right: make_node(AST_String, self, { value: "" }) 22467 }).optimize(compressor); 22468 break; 22469 case "Number": 22470 if (self.args.length == 0) return make_node(AST_Number, self, { 22471 value: 0 22472 }); 22473 if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, { 22474 expression: self.args[0], 22475 operator: "+" 22476 }).optimize(compressor); 22477 case "Boolean": 22478 if (self.args.length == 0) return make_node(AST_False, self); 22479 if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, { 22480 expression: make_node(AST_UnaryPrefix, self, { 22481 expression: self.args[0], 22482 operator: "!" 22483 }), 22484 operator: "!" 22485 }).optimize(compressor); 22486 break; 22487 case "Function": 22488 // new Function() => function(){} 22489 if (self.args.length == 0) return make_node(AST_Function, self, { 22490 argnames: [], 22491 body: [] 22492 }); 22493 if (all(self.args, function(x){ return x instanceof AST_String })) { 22494 // quite a corner-case, but we can handle it: 22495 // https://github.com/mishoo/UglifyJS2/issues/203 22496 // if the code argument is a constant, then we can minify it. 22497 try { 22498 var code = "(function(" + self.args.slice(0, -1).map(function(arg){ 22499 return arg.value; 22500 }).join(",") + "){" + self.args[self.args.length - 1].value + "})()"; 22501 var ast = parse(code); 22502 ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") }); 22503 var comp = new Compressor(compressor.options); 22504 ast = ast.transform(comp); 22505 ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") }); 22506 ast.mangle_names(); 22507 var fun; 22508 try { 22509 ast.walk(new TreeWalker(function(node){ 22510 if (node instanceof AST_Lambda) { 22511 fun = node; 22512 throw ast; 22513 } 22514 })); 22515 } catch(ex) { 22516 if (ex !== ast) throw ex; 22517 }; 22518 if (!fun) return self; 22519 var args = fun.argnames.map(function(arg, i){ 22520 return make_node(AST_String, self.args[i], { 22521 value: arg.print_to_string() 22522 }); 22523 }); 22524 var code = OutputStream(); 22525 AST_BlockStatement.prototype._codegen.call(fun, fun, code); 22526 code = code.toString().replace(/^\{|\}$/g, ""); 22527 args.push(make_node(AST_String, self.args[self.args.length - 1], { 22528 value: code 22529 })); 22530 self.args = args; 22531 return self; 22532 } catch(ex) { 22533 if (ex instanceof JS_Parse_Error) { 22534 compressor.warn("Error parsing code passed to
vendor: 8,141 bytes, lines 22534-22679
22534new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start); 22535 compressor.warn(ex.toString()); 22536 } else { 22537 console.log(ex); 22538 throw ex; 22539 } 22540 } 22541 } 22542 break; 22543 } 22544 } 22545 else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { 22546 return make_node(AST_Binary, self, { 22547 left: make_node(AST_String, self, { value: "" }), 22548 operator: "+", 22549 right: exp.expression 22550 }).optimize(compressor); 22551 } 22552 else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: { 22553 var separator; 22554 if (self.args.length > 0) { 22555 separator = self.args[0].evaluate(compressor); 22556 if (separator === self.args[0]) break EXIT; // not a constant 22557 } 22558 var elements = []; 22559 var consts = []; 22560 exp.expression.elements.forEach(function(el) { 22561 var value = el.evaluate(compressor); 22562 if (value !== el) { 22563 consts.push(value); 22564 } else { 22565 if (consts.length > 0) { 22566 elements.push(make_node(AST_String, self, { 22567 value: consts.join(separator) 22568 })); 22569 consts.length = 0; 22570 } 22571 elements.push(el); 22572 } 22573 }); 22574 if (consts.length > 0) { 22575 elements.push(make_node(AST_String, self, { 22576 value: consts.join(separator) 22577 })); 22578 } 22579 if (elements.length == 0) return make_node(AST_String, self, { value: "" }); 22580 if (elements.length == 1) { 22581 if (elements[0].is_string(compressor)) { 22582 return elements[0]; 22583 } 22584 return make_node(AST_Binary, elements[0], { 22585 operator : "+", 22586 left : make_node(AST_String, self, { value: "" }), 22587 right : elements[0] 22588 }); 22589 } 22590 if (separator == "") { 22591 var first; 22592 if (elements[0].is_string(compressor) 22593 || elements[1].is_string(compressor)) { 22594 first = elements.shift(); 22595 } else { 22596 first = make_node(AST_String, self, { value: "" }); 22597 } 22598 return elements.reduce(function(prev, el){ 22599 return make_node(AST_Binary, el, { 22600 operator : "+", 22601 left : prev, 22602 right : el 22603 }); 22604 }, first).optimize(compressor); 22605 } 22606 // need this awkward cloning to not affect original element 22607 // best_of will decide which one to get through. 22608 var node = self.clone(); 22609 node.expression = node.expression.clone(); 22610 node.expression.expression = node.expression.expression.clone(); 22611 node.expression.expression.elements = elements; 22612 return best_of(compressor, self, node); 22613 } 22614 else if (exp instanceof AST_Dot && exp.expression.is_string(compressor) && exp.property == "charAt") { 22615 var arg = self.args[0]; 22616 var index = arg ? arg.evaluate(compressor) : 0; 22617 if (index !== arg) { 22618 return make_node(AST_Sub, exp, { 22619 expression: exp.expression, 22620 property: make_node_from_constant(index | 0, arg || exp) 22621 }).optimize(compressor); 22622 } 22623 } 22624 } 22625 if (exp instanceof AST_Function) { 22626 if (exp.body[0] instanceof AST_Return) { 22627 var value = exp.body[0].value; 22628 if (!value || value.is_constant()) { 22629 var args = self.args.concat(value || make_node(AST_Undefined, self)); 22630 return AST_Seq.from_array(args).transform(compressor); 22631 } 22632 } 22633 if (compressor.option("side_effects") && all(exp.body, is_empty)) { 22634 var args = self.args.concat(make_node(AST_Undefined, self)); 22635 return AST_Seq.from_array(args).transform(compressor); 22636 } 22637 } 22638 if (compressor.option("drop_console")) { 22639 if (exp instanceof AST_PropAccess) { 22640 var name = exp.expression; 22641 while (name.expression) { 22642 name = name.expression; 22643 } 22644 if (name instanceof AST_SymbolRef 22645 && name.name == "console" 22646 && name.undeclared()) { 22647 return make_node(AST_Undefined, self).optimize(compressor); 22648 } 22649 } 22650 } 22651 if (compressor.option("negate_iife") 22652 && compressor.parent() instanceof AST_SimpleStatement 22653 && is_iife_call(self)) { 22654 return self.negate(compressor, true); 22655 } 22656 return self; 22657 }); 22658 22659 OPT(AST_New, function(self, compressor){ 22660 if (compressor.option("unsafe")) { 22661 var exp = self.expression; 22662 if (exp instanceof AST_SymbolRef && exp.undeclared()) { 22663 switch (exp.name) { 22664 case "Object": 22665 case "RegExp": 22666 case "Function": 22667 case "Error": 22668 case "Array": 22669 return make_node(AST_Call, self, self).transform(compressor); 22670 } 22671 } 22672 } 22673 return self; 22674 }); 22675 22676 OPT(AST_Seq, function(self, compressor){ 22677 if (!compressor.option("side_effects")) 22678 return self; 22679 self.car = self.car.drop_side_effect_free(compressor, first_in_statement
22679(compressor)); 22680 if (!self.car) return maintain_this_binding(compressor.parent(), self, self.cdr); 22681 if (compressor.option("cascade")) { 22682 var left; 22683 if (self.car instanceof AST_Assign 22684 && !self.car.left.has_side_effects(compressor)) { 22685 left = self.car.left; 22686 } else if (self.car instanceof AST_Unary 22687 && (self.car.operator == "++" || self.car.operator == "--")) { 22688 left = self.car.expression; 22689 } 22690 if (left 22691 && !(left instanceof AST_SymbolRef 22692 && (left.definition().orig[0] instanceof AST_SymbolLambda 22693 || is_reference_const(left)))) { 22694 var parent, field; 22695 var cdr = self.cdr; 22696 while (true) { 22697 if (cdr.equivalent_to(left)) { 22698 var car = self.car instanceof AST_UnaryPostfix ? make_node(AST_UnaryPrefix, self.car, { 22699 operator: self.car.operator, 22700 expression: left 22701 }) : self.car; 22702 if (parent) { 22703 parent[field] = car; 22704 return self.cdr; 22705 } 22706 return car; 22707 } 22708 if (cdr instanceof AST_Binary && !(cdr instanceof AST_Assign)) { 22709 if (cdr.left.is_constant()) { 22710 if (cdr.operator == "||" || cdr.operator == "&&") break; 22711 field = "right"; 22712 } else { 22713 field = "left"; 22714 } 22715 } else if (cdr instanceof AST_Call 22716 || cdr instanceof AST_Unary && !unary_side_effects(cdr.operator)) { 22717 field = "expression"; 22718 } else break; 22719 parent = cdr; 22720 cdr = cdr[field]; 22721 } 22722 } 22723 } 22724 if (is_undefined(self.cdr, compressor)) { 22725 return make_node(AST_UnaryPrefix, self, { 22726 operator : "void", 22727 expression : self.car 22728 }); 22729 } 22730 return self; 22731 }); 22732 22733 AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ 22734 if (compressor.option("sequences")) { 22735 if (this.expression instanceof AST_Seq) { 22736 var seq = this.expression; 22737 var x = seq.to_array(); 22738 var e = this.clone(); 22739 e.expression = x.pop(); 22740 x.push(e); 22741 seq = AST_Seq.from_array(x).transform(compressor); 22742 return seq; 22743 } 22744 } 22745 return this; 22746 }); 22747 22748 OPT(AST_UnaryPostfix, function(self, compressor){ 22749 return self.lift_sequences(compressor); 22750 }); 22751 22752 OPT(AST_UnaryPrefix, function(self, compressor){ 22753 var e = self.expression; 22754 if (self.operator == "delete" 22755 && !(e instanceof AST_SymbolRef 22756 || e instanceof AST_PropAccess 22757 || e instanceof AST_NaN 22758 || e instanceof AST_Infinity 22759 || e instanceof AST_Undefined)) { 22760 if (e instanceof AST_Seq) { 22761 e = e.to_array(); 22762 e.push(make_node(AST_True, self)); 22763 return AST_Seq.from_array(e).optimize(compressor); 22764 } 22765 return make_node(AST_Seq, self, { 22766 car: e, 22767 cdr: make_node(AST_True, self) 22768 }).optimize(compressor); 22769 } 22770 var seq = self.lift_sequences(compressor); 22771 if (seq !== self) { 22772 return seq; 22773 } 22774 if (compressor.option("side_effects") && self.operator == "void") { 22775 e = e.drop_side_effect_free(compressor); 22776 if (e) { 22777 self.expression = e; 22778 return self; 22779 } else { 22780 return make_node(AST_Undefined, self).optimize(compressor); 22781 } 22782 } 22783 if (compressor.option("booleans") && compressor.in_boolean_context()) { 22784 switch (self.operator) { 22785 case "!": 22786 if (e instanceof AST_UnaryPrefix && e.o
22786perator == "!") { 22787 // !!foo ==> foo, if we're in boolean context 22788 return e.expression; 22789 } 22790 if (e instanceof AST_Binary) { 22791 self = best_of(compressor, self, e.negate(compressor, first_in_statement(compressor))); 22792 } 22793 break; 22794 case "typeof": 22795 // typeof always returns a non-empty string, thus it's 22796 // always true in booleans 22797 compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); 22798 return (e instanceof AST_SymbolRef ? make_node(AST_True, self) : make_node(AST_Seq, self, { 22799 car: e, 22800 cdr: make_node(AST_True, self) 22801 })).optimize(compressor); 22802 } 22803 } 22804 if (self.operator == "-" && e instanceof AST_Infinity) { 22805 e = e.transform(compressor); 22806 } 22807 if (e instanceof AST_Binary 22808 && (self.operator == "+" || self.operator == "-") 22809 && (e.operator == "*" || e.operator == "/" || e.operator == "%")) { 22810 return make_node(AST_Binary, self, { 22811 operator: e.operator, 22812 left: make_node(AST_UnaryPrefix, e.left, { 22813 operator: self.operator, 22814 expression: e.left 22815 }), 22816 right: e.right 22817 }); 22818 } 22819 // avoids infinite recursion of numerals 22820 if (self.operator != "-" 22821 || !(e instanceof AST_Number || e instanceof AST_Infinity)) { 22822 var ev = self.evaluate(compressor); 22823 if (ev !== self) { 22824 ev = make_node_from_constant(ev, self).optimize(compressor); 22825 return best_of(compressor, ev, self); 22826 } 22827 } 22828 return self; 22829 }); 22830 22831 AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ 22832 if (compressor.option("sequences")) { 22833 if (this.left instanceof AST_Seq) { 22834 var seq = this.left; 22835 var x = seq.to_array(); 22836 var e = this.clone(); 22837 e.left = x.pop(); 22838 x.push(e); 22839 return AST_Seq.from_array(x).optimize(compressor); 22840 } 22841 if (this.right instanceof AST_Seq && !this.left.has_side_effects(compressor)) { 22842 var assign = this.operator == "=" && this.left instanceof AST_SymbolRef; 22843 var root = this.right.clone(); 22844 var cursor, seq = root; 22845 while (assign || !seq.car.has_side_effects(compressor)) { 22846 cursor = seq; 22847 if (seq.cdr instanceof AST_Seq) { 22848 seq = seq.cdr = seq.cdr.clone(); 22849 } else break; 22850 } 22851 if (cursor) { 22852 var e = this.clone(); 22853 e.right = cursor.cdr; 22854 cursor.cdr = e; 22855 return root.optimize(compressor); 22856 } 22857 } 22858 } 22859 return this; 22860 }); 22861 22862 var commutativeOperators = makePredicate("== === != !== * & | ^"); 22863 22864 OPT(AST_Binary, function(self, compressor){ 22865 function reversible() { 22866 return self.left.is_constant() 22867 || self.right.is_constant() 22868 || !self.left.has_side_effects(compressor) 22869 && !self.right.has_side_effects(compressor); 22870 } 22871 function reverse(op) { 22872 if (reversible()) { 22873 if (op) self.operator = op; 22874 var tmp = self.left; 22875 self.left = self.right; 22876 self.right = tmp; 22877 } 22878 } 22879 if (commutativeOperators(self.operator)) { 22880 if (self.right.is_constant() 22881 && !self.left.is_constant()) { 22882 // if right is a constant, whatever side effects the 22883 // left side might have could not influence the 22884 // result. hence, force switch. 22885 22886 if (!(self.left instanceof AST_Binary 22887 && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) { 22888 reverse(); 22889 } 22890 } 22891 } 22892 self = self.lift_sequences(compressor); 22893 if (compressor.option("comparisons")) switch (self.operator) { 22894 case "===": 22895 case "!==": 22896 if ((self.left.is_string(compressor) && self.right.is_string(compressor)) || 22897 (self.left.is_number(compressor) && self.right.is_number(compressor)) || 22898 (self.left.is_boolean() && self.right.is_boolean())) { 22899 self.operator = self.operator.substr(0, 2); 22900 } 22901 // XXX: intentionally falling down to the next case 22902 case "==": 22903 case "!=": 22904 // "undefined" == typeof x => undefined === x 22905 if (self.left instanceof AST_String 22906 && self.left.value == "undefined" 22907 && self.right instanceof AST_UnaryPrefix 22908 && self.right.operator == "typeof") { 22909 var expr = self.right.expression; 22910 if (expr instanceof AST_SymbolRef ? !expr.undeclared() 22911 : !(expr instanceof AST_PropAccess) || compressor.option("screw_ie8")) { 22912 self.right = expr; 22913 self.left = make_node(AST_Undefined, self.left).optimize(compressor); 22914 if (self.operator.length == 2) self.operator += "="; 22915 } 22916 } 22917 break; 22918 } 22919 if (compressor.option("booleans") && self.operator == "+" && compressor.in_boolean_context()) { 22920 var ll = self.left.evaluate(compressor); 22921 var rr = self.right.evaluate(compressor); 22922 if (ll && typeof ll == "string") { 22923 compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); 22924 return make_node(AST_Seq, self, { 22925 car: self.right, 22926 cdr: make_node(AST_True, self) 22927 }).optimize(compressor); 22928 } 22929 if (rr && typeof rr == "string") { 22930 compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); 22931 return make_node(AST_Seq, self, { 22932 car: self.left, 22933 cdr: make_node(AST_True, self) 22934 }).optimize(compressor); 22935 } 22936 } 22937 if (compressor.option("comparisons") && self.is_boolean()) { 22938 if (!(compressor.parent() instanceof AST_Binary) 22939 || compressor.parent() instanceof AST_Assign) { 22940 var negated = make_node(AST_UnaryPrefix, self, { 22941 operator: "!", 22942 expression: self.negate(compressor, first_in_statement
22942(compressor)) 22943 }); 22944 self = best_of(compressor, self, negated); 22945 } 22946 if (compressor.option("unsafe_comps")) { 22947 switch (self.operator) { 22948 case "<": reverse(">"); break; 22949 case "<=": reverse(">="); break; 22950 } 22951 } 22952 } 22953 if (self.operator == "+") { 22954 if (self.right instanceof AST_String 22955 && self.right.getValue() == "" 22956 && self.left.is_string(compressor)) { 22957 return self.left; 22958 } 22959 if (self.left instanceof AST_String 22960 && self.left.getValue() == "" 22961 && self.right.is_string(compressor)) { 22962 return self.right; 22963 } 22964 if (self.left instanceof AST_Binary 22965 && self.left.operator == "+" 22966 && self.left.left instanceof AST_String 22967 && self.left.left.getValue() == "" 22968 && self.right.is_string(compressor)) { 22969 self.left = self.left.right; 22970 return self.transform(compressor); 22971 } 22972 } 22973 if (compressor.option("evaluate")) { 22974 switch (self.operator) { 22975 case "&&": 22976 var ll = self.left.evaluate(compressor); 22977 if (!ll) { 22978 compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start); 22979 return maintain_this_binding(compressor.parent(), self, self.left).optimize(compressor); 22980 } else if (ll !== self.left) { 22981 compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start); 22982 return maintain_this_binding(compressor.parent(), self, self.right).optimize(compressor); 22983 } 22984 if (compressor.option("booleans") && compressor.in_boolean_context()) { 22985 var rr = self.right.evaluate(compressor); 22986 if (!rr) { 22987 compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); 22988 return make_node(AST_Seq, self, { 22989 car: self.left, 22990 cdr: make_node(AST_False, self) 22991 }).optimize(compressor); 22992 } else if (rr !== self.right) { 22993 compressor.warn("Dropping side-effect-free && in boolean context [{file}:{line},{col}]", self.start); 22994 return self.left.optimize(compressor); 22995 } 22996 } 22997 break; 22998 case "||": 22999 var ll = self.left.evaluate(compressor); 23000 if (!ll) { 23001 compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start); 23002 return maintain_this_binding(compressor.parent(), self, self.right).optimize(compressor); 23003 } else if (ll !== self.left) { 23004 compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start); 23005 return maintain_this_binding(compressor.parent(), self, self.left).optimize(compressor); 23006 } 23007 if (compressor.option("booleans") && compressor.in_boolean_context()) { 23008 var rr = self.right.evaluate(compressor); 23009 if (!rr) { 23010 compressor.warn("Dropping side-effect-free || in boolean context [{file}:{line},{col}]", self.start); 23011 return self.left.optimize(compressor); 23012 } else if (rr !== self.right) { 23013 compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); 23014 return make_node(AST_Seq, self, { 23015 car: self.left, 23016 cdr: make_node(AST_True, self) 23017 }).optimize(compressor); 23018 } 23019 } 23020 break; 23021 } 23022 var associative = true; 23023 switch (self.operator) { 23024 case "+": 23025 // "foo" + ("bar" + x) => "foobar" + x 23026 if (self.left instanceof AST_Constant 23027 && self.right instanceof AST_Binary 23028 && self.right.operator == "+" 23029 && self.right.left instanceof AST_Constant 23030 && self.right.is_string(compressor)) { 23031 self = make_node(AST_Binary, self, { 23032 operator: "+", 23033 left: make_node(AST_String, self.left, { 23034 value: "" + self.left.getValue() + self.right.left.getValue(), 23035 start: self.left.start, 23036 end: self.right.left.end 23037 }), 23038 right: self.right.right 23039 }); 23040 } 23041 // (x + "foo") + "bar" => x + "foobar" 23042 if (self.right instanceof AST_Constant 23043 && self.left instanceof AST_Binary 23044 && self.left.operator == "+" 23045 && self.left.right instanceof AST_Constant 23046 && self.left.is_string(compressor)) { 23047 self = make_node(AST_Binary, self, { 23048 operator: "+", 23049 left: self.left.left, 23050 right: make_node(AST_String, self.right, { 23051 value: "" + self.left.right.getValue() + self.right.getValue(), 23052 start: self.left.right.start, 23053 end: self.right.end 23054 }) 23055 }); 23056 } 23057 // (x + "foo") + ("bar" + y) => (x + "foobar") + y 23058 if (self.left instanceof AST_Binary 23059 && self.left.operator == "+" 23060 && self.left.is_string(compressor) 23061 && self.left.right instanceof AST_Constant 23062 && self.right instanceof AST_Binary 23063 && self.right.operator == "+" 23064 && self.right.left instanceof AST_Constant 23065 && self.right.is_string(compressor)) { 23066 self = make_node(AST_Binary, self, { 23067 operator: "+", 23068 left: make_node(AST_Binary, self.left, { 23069 operator: "+", 23070 left: self.left.left, 23071 right: make_node(AST_String, self.left.right, { 23072 value: "" + self.left.right.getValue() + self.right.left.getValue(), 23073 start: self.left.right.start, 23074 end: self.right.left.end 23075 }) 23076 }), 23077 right: self.right.right 23078 }); 23079 } 23080 // a + -b => a - b 23081 if (self.right instanceof AST_UnaryPrefix 23082 && self.right.operator == "-" 23083 && self.left.is_number(compressor)) { 23084 self = make_node(AST_Binary, self, { 23085 operator: "-", 23086 left: self.left, 23087 right: self.right.expression 23088 }); 23089 break; 23090 } 23091 // -a + b => b - a 23092 if (self.left instanceof AST_UnaryPrefix 23093 && self.left.operator == "-" 23094 && reversible() 23095 && self.right.is_number(compressor)) { 23096 self = make_node(AST_Binary, self, { 23097 operator: "-", 23098 left: self.right, 23099 right: self.left.expression 23100 }); 23101 break; 23102 } 23103 case "*": 23104 associative = compressor.option("unsafe_math"); 23105 case "&": 23106 case "|": 23107 case "^": 23108 // a + +b => +b + a 23109 if (self.left.is_number(compressor) 23110 && self.right.is_number(compressor) 23111 && reversible() 23112 && !(self.left instanceof AST_Binary 23113 && self.left.operator != self.operator
vendor: 4,352 bytes, lines 23114-23176
23114 && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) { 23115 var reversed = make_node(AST_Binary, self, { 23116 operator: self.operator, 23117 left: self.right, 23118 right: self.left 23119 }); 23120 if (self.right instanceof AST_Constant 23121 && !(self.left instanceof AST_Constant)) { 23122 self = best_of(compressor, reversed, self); 23123 } else { 23124 self = best_of(compressor, self, reversed); 23125 } 23126 } 23127 if (associative && self.is_number(compressor)) { 23128 // a + (b + c) => (a + b) + c 23129 if (self.right instanceof AST_Binary 23130 && self.right.operator == self.operator) { 23131 self = make_node(AST_Binary, self, { 23132 operator: self.operator, 23133 left: make_node(AST_Binary, self.left, { 23134 operator: self.operator, 23135 left: self.left, 23136 right: self.right.left, 23137 start: self.left.start, 23138 end: self.right.left.end 23139 }), 23140 right: self.right.right 23141 }); 23142 } 23143 // (n + 2) + 3 => 5 + n 23144 // (2 * n) * 3 => 6 + n 23145 if (self.right instanceof AST_Constant 23146 && self.left instanceof AST_Binary 23147 && self.left.operator == self.operator) { 23148 if (self.left.left instanceof AST_Constant) { 23149 self = make_node(AST_Binary, self, { 23150 operator: self.operator, 23151 left: make_node(AST_Binary, self.left, { 23152 operator: self.operator, 23153 left: self.left.left, 23154 right: self.right, 23155 start: self.left.left.start, 23156 end: self.right.end 23157 }), 23158 right: self.left.right 23159 }); 23160 } else if (self.left.right instanceof AST_Constant) { 23161 self = make_node(AST_Binary, self, { 23162 operator: self.operator, 23163 left: make_node(AST_Binary, self.left, { 23164 operator: self.operator, 23165 left: self.left.right, 23166 right: self.right, 23167 start: self.left.right.start, 23168 end: self.right.end 23169 }), 23170 right: self.left.left 23171 }); 23172 } 23173 } 23174 // (a | 1) | (2 | d) => (3 | a) | b 23175 if (self.left instanceof AST_Binary 23176 && self.left.operator == self.operator
23177 && self.left.right instanceof AST_Constant 23178 && self.right instanceof AST_Binary 23179 && self.right.operator == self.operator 23180 && self.right.left instanceof AST_Constant) { 23181 self = make_node(AST_Binary, self, { 23182 operator: self.operator, 23183 left: make_node(AST_Binary, self.left, { 23184 operator: self.operator, 23185 left: make_node(AST_Binary, self.left.left, { 23186 operator: self.operator, 23187 left: self.left.right, 23188 right: self.right.left, 23189 start: self.left.right.start, 23190 end: self.right.left.end 23191 }), 23192 right: self.left.left 23193 }), 23194 right: self.right.right 23195 }); 23196 } 23197 } 23198 } 23199 } 23200 // x && (y && z) ==> x && y && z 23201 // x || (y || z) ==> x || y || z 23202 // x + ("y" + z) ==> x + "y" + z 23203 // "x" + (y + "z")==> "x" + y + "z" 23204 if (self.right instanceof AST_Binary 23205 && self.right.operator == self.operator
23206 && (self.operator == "&&" 23207 || self.operator == "||" 23208 || (self.operator == "+" 23209 && (self.right.left.is_string(compressor) 23210 || (self.left.is_string(compressor) 23211 && self.right.right.is_string(compressor)))))) 23212 { 23213 self.left = make_node(AST_Binary, self.left, { 23214 operator : self.operator, 23215 left : self.left, 23216 right : self.right.left 23217 }); 23218 self.right = self.right.right; 23219 return self.transform(compressor); 23220 } 23221 var ev = self.evaluate(compressor); 23222 if (ev !== self) { 23223 ev = make_node_from_constant(ev, self).optimize(compressor); 23224 return best_of(compressor, ev, self); 23225 } 23226 return self; 23227 }); 23228 23229 OPT(AST_SymbolRef, function(self, compressor){ 23230 var def = self.resolve_defines(compressor); 23231 if (def) { 23232 return def.optimize(compressor); 23233 } 23234 // testing against !self.scope.uses_with first is an optimization 23235 if (compressor.option("screw_ie8") 23236 && self.undeclared() 23237 && (!self.scope.uses_with || !compressor.find_parent(AST_With))) { 23238 switch (self.name) { 23239 case "undefined": 23240 return make_node(AST_Undefined, self).optimize(compressor); 23241 case "NaN": 23242 return make_node(AST_NaN, self).optimize(compressor); 23243 case "Infinity": 23244 return make_node(AST_Infinity, self).optimize(compressor); 23245 } 23246 } 23247 if (compressor.option("evaluate") 23248 && compressor.option("reduce_vars") 23249 && is_lhs(self, compressor.parent()) !== self) { 23250 var d = self.definition(); 23251 var fixed = self.fixed_value(); 23252 if (fixed) { 23253 if (d.should_replace === undefined) { 23254 var init = fixed.evaluate(compressor); 23255 if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) { 23256 init = make_node_from_constant(init, fixed); 23257 var value = init.optimize(compressor).print_to_string().length; 23258 var fn; 23259 if (has_symbol_ref(fixed)) { 23260 fn = function() { 23261 var result = init.optimize(compressor); 23262 return result === init ? result.clone(true) : result; 23263 }; 23264 } else { 23265 value = Math.min(value, fixed.print_to_string().length); 23266 fn = function() { 23267 var result = best_of_expression(init.optimize(compressor), fixed); 23268 return result === init || result === fixed ? result.clone(true) : result; 23269 }; 23270 } 23271 var name = d.name.length; 23272 var overhead = 0; 23273 if (compressor.option("unused") && (!d.global || compressor.option("toplevel"))) { 23274 overhead = (name + 2 + value) / d.references.length; 23275 } 23276 d.should_replace = value <= name + overhead ? fn : false;
23277 } else { 23278 d.should_replace = false; 23279 } 23280 } 23281 if (d.should_replace) { 23282 return d.should_replace(); 23283 } 23284 } 23285 } 23286 return self; 23287 23288 function has_symbol_ref(value) { 23289 var found; 23290 value.walk(new TreeWalker(function(node) { 23291 if (node instanceof AST_SymbolRef) found = true; 23292 if (found) return true; 23293 })); 23294 return found; 23295 } 23296 }); 23297 23298 function is_atomic(lhs, self) { 23299 return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE; 23300 } 23301 23302 OPT(AST_Undefined, function(self, compressor){ 23303 if (compressor.option("unsafe")) { 23304 var undef = find_variable(compressor, "undefined"); 23305 if (undef) { 23306 var ref = make_node(AST_SymbolRef, self, { 23307 name : "undefined", 23308 scope : undef.scope, 23309 thedef : undef 23310 }); 23311 ref.is_undefined = true; 23312 return ref; 23313 } 23314 } 23315 var lhs = is_lhs(compressor.self(), compressor.parent()); 23316 if (lhs && is_atomic(lhs, self)) return self; 23317 return make_node(AST_UnaryPrefix, self, { 23318 operator: "void", 23319 expression: make_node(AST_Number, self, { 23320 value: 0 23321 }) 23322 }); 23323 }); 23324 23325 OPT(AST_Infinity, function(self, compressor){ 23326 var lhs = is_lhs(compressor.self(), compressor.parent()); 23327 if (lhs && is_atomic(lhs, self)) return self; 23328 if (compressor.option("keep_infinity") 23329 && !(lhs && !is_atomic(lhs, self)) 23330 && !find_variable(compressor, "Infinity")) 23331 return self; 23332 return make_node(AST_Binary, self, { 23333 operator: "/", 23334 left: make_node(AST_Number, self, { 23335 value: 1 23336 }), 23337 right: make_node(AST_Number, self, { 23338 value: 0 23339 }) 23340 }); 23341 }); 23342 23343 OPT(AST_NaN, function(self, compressor){ 23344 var lhs = is_lhs(compressor.self(), compressor.parent()); 23345 if (lhs && !is_atomic(lhs, self) 23346 || find_variable(compressor, "NaN")) { 23347 return make_node(AST_Binary, self, { 23348 operator: "/", 23349 left: make_node(AST_Number, self, { 23350 value: 0 23351 }), 23352 right: make_node(AST_Number, self, { 23353 value: 0 23354 }) 23355 }); 23356 } 23357 return self; 23358 }); 23359 23360 var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; 23361 var ASSIGN_OPS_COMMUTATIVE = [ '*', '|', '^', '&' ]; 23362 OPT(AST_Assign, function(self, compressor){ 23363 self = self.lift_sequences(compressor); 23364 if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) { 23365 // x = expr1 OP expr2 23366 if (self.right.left instanceof AST_SymbolRef 23367 && self.right.left.name == self.left.name 23368 && member(self.right.operator, ASSIGN_OPS)) { 23369 // x = x - 2 ---> x -= 2 23370 self.operator = self.right.operator + "="; 23371 self.right = self.right.right; 23372 } 23373 else if (self.right.right instanceof AST_SymbolRef 23374 && self.right.right.name == self.left.name 23375 && member(self.right.operator, ASSIGN_OPS_COMMUTATIVE) 23376 && !self.right.left.has_side_effects(compressor)) { 23377 // x = 2 & x ---> x &= 2 23378 self.operator = self.right.operator + "="; 23379 self.right = self.right.left; 23380 } 23381 } 23382 return self; 23383 }); 23384 23385 OPT(AST_Conditional, function(self, compressor){ 23386 if (!compressor.option("conditionals")) return self; 23387 if (self.condition instanceof AST_Seq) { 23388 var car = self.condition.car; 23389 self.condition = self.condition.cdr; 23390 return AST_Seq.cons(car, self); 23391 } 23392 var cond = self.condition.evaluate(compressor); 23393 if (cond !== self.condition) { 23394 if (cond) { 23395 compressor.warn("Condition always true [{file}:{line},{col}]", self.start); 23396 return maintain_this_binding(compressor.parent(), self, self.consequent); 23397 } else { 23398 compressor.warn("Condition always false [{file}:{line},{col}]", self.start); 23399 return maintain_this_binding(compressor.parent(), self, self.alternative); 23400 } 23401 } 23402 var negated = cond.negate(compressor, first_in_statement
vendor: 14,833 bytes, lines 23402-23706
23402(compressor)); 23403 if (best_of(compressor, cond, negated) === negated) { 23404 self = make_node(AST_Conditional, self, { 23405 condition: negated, 23406 consequent: self.alternative, 23407 alternative: self.consequent 23408 }); 23409 } 23410 var condition = self.condition; 23411 var consequent = self.consequent; 23412 var alternative = self.alternative; 23413 // x?x:y --> x||y 23414 if (condition instanceof AST_SymbolRef 23415 && consequent instanceof AST_SymbolRef 23416 && condition.definition() === consequent.definition()) { 23417 return make_node(AST_Binary, self, { 23418 operator: "||", 23419 left: condition, 23420 right: alternative 23421 }); 23422 } 23423 // if (foo) exp = something; else exp = something_else; 23424 // | 23425 // v 23426 // exp = foo ? something : something_else; 23427 if (consequent instanceof AST_Assign 23428 && alternative instanceof AST_Assign 23429 && consequent.operator == alternative.operator 23430 && consequent.left.equivalent_to(alternative.left) 23431 && (!self.condition.has_side_effects(compressor) 23432 || consequent.operator == "=" 23433 && !consequent.left.has_side_effects(compressor))) { 23434 return make_node(AST_Assign, self, { 23435 operator: consequent.operator, 23436 left: consequent.left, 23437 right: make_node(AST_Conditional, self, { 23438 condition: self.condition, 23439 consequent: consequent.right, 23440 alternative: alternative.right 23441 }) 23442 }); 23443 } 23444 // x ? y(a) : y(b) --> y(x ? a : b) 23445 if (consequent instanceof AST_Call 23446 && alternative.TYPE === consequent.TYPE 23447 && consequent.args.length == 1 23448 && alternative.args.length == 1 23449 && consequent.expression.equivalent_to(alternative.expression) 23450 && !consequent.expression.has_side_effects(compressor)) { 23451 consequent.args[0] = make_node(AST_Conditional, self, { 23452 condition: self.condition, 23453 consequent: consequent.args[0], 23454 alternative: alternative.args[0] 23455 }); 23456 return consequent; 23457 } 23458 // x?y?z:a:a --> x&&y?z:a 23459 if (consequent instanceof AST_Conditional 23460 && consequent.alternative.equivalent_to(alternative)) { 23461 return make_node(AST_Conditional, self, { 23462 condition: make_node(AST_Binary, self, { 23463 left: self.condition, 23464 operator: "&&", 23465 right: consequent.condition 23466 }), 23467 consequent: consequent.consequent, 23468 alternative: alternative 23469 }); 23470 } 23471 // x ? y : y --> x, y 23472 if (consequent.equivalent_to(alternative)) { 23473 return make_node(AST_Seq, self, { 23474 car: self.condition, 23475 cdr: consequent 23476 }).optimize(compressor); 23477 } 23478 23479 if (is_true(self.consequent)) { 23480 if (is_false(self.alternative)) { 23481 // c ? true : false ---> !!c 23482 return booleanize(self.condition); 23483 } 23484 // c ? true : x ---> !!c || x 23485 return make_node(AST_Binary, self, { 23486 operator: "||", 23487 left: booleanize(self.condition), 23488 right: self.alternative 23489 }); 23490 } 23491 if (is_false(self.consequent)) { 23492 if (is_true(self.alternative)) { 23493 // c ? false : true ---> !c 23494 return booleanize(self.condition.negate(compressor)); 23495 } 23496 // c ? false : x ---> !c && x 23497 return make_node(AST_Binary, self, { 23498 operator: "&&", 23499 left: booleanize(self.condition.negate(compressor)), 23500 right: self.alternative 23501 }); 23502 } 23503 if (is_true(self.alternative)) { 23504 // c ? x : true ---> !c || x 23505 return make_node(AST_Binary, self, { 23506 operator: "||", 23507 left: booleanize(self.condition.negate(compressor)), 23508 right: self.consequent 23509 }); 23510 } 23511 if (is_false(self.alternative)) { 23512 // c ? x : false ---> !!c && x 23513 return make_node(AST_Binary, self, { 23514 operator: "&&", 23515 left: booleanize(self.condition), 23516 right: self.consequent 23517 }); 23518 } 23519 23520 return self; 23521 23522 function booleanize(node) { 23523 if (node.is_boolean()) return node; 23524 // !!expression 23525 return make_node(AST_UnaryPrefix, node, { 23526 operator: "!", 23527 expression: node.negate(compressor) 23528 }); 23529 } 23530 23531 // AST_True or !0 23532 function is_true(node) { 23533 return node instanceof AST_True 23534 || (node instanceof AST_UnaryPrefix 23535 && node.operator == "!" 23536 && node.expression instanceof AST_Constant 23537 && !node.expression.value); 23538 } 23539 // AST_False or !1 23540 function is_false(node) { 23541 return node instanceof AST_False 23542 || (node instanceof AST_UnaryPrefix 23543 && node.operator == "!" 23544 && node.expression instanceof AST_Constant 23545 && !!node.expression.value); 23546 } 23547 }); 23548 23549 OPT(AST_Boolean, function(self, compressor){ 23550 if (compressor.option("booleans")) { 23551 var p = compressor.parent(); 23552 if (p instanceof AST_Binary && (p.operator == "==" 23553 || p.operator == "!=")) { 23554 compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { 23555 operator : p.operator, 23556 value : self.value, 23557 file : p.start.file, 23558 line : p.start.line, 23559 col : p.start.col, 23560 }); 23561 return make_node(AST_Number, self, { 23562 value: +self.value 23563 }); 23564 } 23565 return make_node(AST_UnaryPrefix, self, { 23566 operator: "!", 23567 expression: make_node(AST_Number, self, { 23568 value: 1 - self.value 23569 }) 23570 }); 23571 } 23572 return self; 23573 }); 23574 23575 OPT(AST_Sub, function(self, compressor){ 23576 var prop = self.property; 23577 if (prop instanceof AST_String && compressor.option("properties")) { 23578 prop = prop.getValue(); 23579 if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) { 23580 return make_node(AST_Dot, self, { 23581 expression : self.expression, 23582 property : prop 23583 }).optimize(compressor); 23584 } 23585 var v = parseFloat(prop); 23586 if (!isNaN(v) && v.toString() == prop) { 23587 self.property = make_node(AST_Number, self.property, { 23588 value: v 23589 }); 23590 } 23591 } 23592 var ev = self.evaluate(compressor); 23593 if (ev !== self) { 23594 ev = make_node_from_constant(ev, self).optimize(compressor); 23595 return best_of(compressor, ev, self); 23596 } 23597 return self; 23598 }); 23599 23600 OPT(AST_Dot, function(self, compressor){ 23601 var def = self.resolve_defines(compressor); 23602 if (def) { 23603 return def.optimize(compressor); 23604 } 23605 var prop = self.property; 23606 if (RESERVED_WORDS(prop) && !compressor.option("screw_ie8")) { 23607 return make_node(AST_Sub, self, { 23608 expression : self.expression, 23609 property : make_node(AST_String, self, { 23610 value: prop 23611 }) 23612 }).optimize(compressor); 23613 } 23614 if (compressor.option("unsafe_proto") 23615 && self.expression instanceof AST_Dot 23616 && self.expression.property == "prototype") { 23617 var exp = self.expression.expression; 23618 if (exp instanceof AST_SymbolRef && exp.undeclared()) switch (exp.name) { 23619 case "Array": 23620 self.expression = make_node(AST_Array, self.expression, { 23621 elements: [] 23622 }); 23623 break; 23624 case "Object": 23625 self.expression = make_node(AST_Object, self.expression, { 23626 properties: [] 23627 }); 23628 break; 23629 case "String": 23630 self.expression = make_node(AST_String, self.expression, { 23631 value: "" 23632 }); 23633 break; 23634 } 23635 } 23636 var ev = self.evaluate(compressor); 23637 if (ev !== self) { 23638 ev = make_node_from_constant(ev, self).optimize(compressor); 23639 return best_of(compressor, ev, self); 23640 } 23641 return self; 23642 }); 23643 23644 function literals_in_boolean_context(self, compressor) { 23645 if (compressor.option("booleans") && compressor.in_boolean_context()) { 23646 return best_of(compressor, self, make_node(AST_Seq, self, { 23647 car: self, 23648 cdr: make_node(AST_True, self) 23649 }).optimize(compressor)); 23650 } 23651 return self; 23652 }; 23653 OPT(AST_Array, literals_in_boolean_context); 23654 OPT(AST_Object, literals_in_boolean_context); 23655 OPT(AST_RegExp, literals_in_boolean_context); 23656 23657 OPT(AST_Return, function(self, compressor){ 23658 if (self.value && is_undefined(self.value, compressor)) { 23659 self.value = null; 23660 } 23661 return self; 23662 }); 23663 23664 OPT(AST_VarDef, function(self, compressor){ 23665 var defines = compressor.option("global_defs"); 23666 if (defines && HOP(defines, self.name.name)) { 23667 compressor.warn('global_defs ' + self.name.name + ' redefined [{file}:{line},{col}]', self.start); 23668 } 23669 return self; 23670 }); 23671 23672 })(); 23673 23674 /*********************************************************************** 23675 23676 A JavaScript tokenizer / parser / beautifier / compressor. 23677 https://github.com/mishoo/UglifyJS2 23678 23679 -------------------------------- (C) --------------------------------- 23680 23681 Author: Mihai Bazon 23682 <[email protected]> 23683 http://mihai.bazon.net/blog 23684 23685 Distributed under the BSD license: 23686 23687 Copyright 2012 (c) Mihai Bazon <[email protected]> 23688 23689 Redistribution and use in source and binary forms, with or without 23690 modification, are permitted provided that the following conditions 23691 are met: 23692 23693 * Redistributions of source code must retain the above 23694 copyright notice, this list of conditions and the following 23695 disclaimer. 23696 23697 * Redistributions in binary form must reproduce the above 23698 copyright notice, this list of conditions and the following 23699 disclaimer in the documentation and/or other materials 23700 provided with the distribution. 23701 23702 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 23703 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23704 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23705 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 23706 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23707 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23708 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23709 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23710 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 23711 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 23712 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23713 SUCH DAMAGE. 23714 23715 ***********************************************************************/ 23716 23717 "use strict"; 23718 23719// a small wrapper around fitzgen's source-map library 23720 function SourceMap(options) { 23721 options = defaults(options, { 23722 file : null, 23723 root : null, 23724 orig : null, 23725 23726 orig_line_diff : 0, 23727 dest_line_diff : 0, 23728 }); 23729 var generator = new MOZ_SourceMap.SourceMapGenerator({ 23730 file : options.file, 23731 sourceRoot : options.root 23732 }); 23733 var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); 23734 23735 if (orig_map && Array.isArray(options.orig.sources)) { 23736 orig_map._sources.toArray().forEach(function(source) { 23737 var sourceContent = orig_map.sourceContentFor(source, true); 23738 if (sourceContent) { 23739 generator.setSourceContent(source, sourceContent); 23740 } 23741 }); 23742 } 23743 23744 function add(source, gen_line, gen_col, orig_line, orig_col, name) { 23745 if (orig_map) { 23746 var info = orig_map.originalPositionFor({ 23747 line: orig_line, 23748 column: orig_col 23749 }); 23750 if (info.source === null) { 23751 return; 23752 } 23753 source = info.source; 23754 orig_line = info.line; 23755 orig_col = info.column; 23756 name = info.name || name; 23757 } 23758 generator.addMapping({ 23759 generated : { line: gen_line + options.dest_line_diff, column: gen_col }, 23760 original : { line: orig_line + options.orig_line_diff, column: orig_col }, 23761 source : source, 23762 name : name 23763 }); 23764 }; 23765 return { 23766 add : add, 23767 get : function() { return generator }, 23768 toString : function() { return JSON.stringify(generator.toJSON()); } 23769 }; 23770 }; 23771 23772 /*********************************************************************** 23773 23774 A JavaScript tokenizer / parser / beautifier / compressor. 23775 https://github.com/mishoo/UglifyJS2 23776 23777 -------------------------------- (C) --------------------------------- 23778 23779 Author: Mihai Bazon 23780 <[email protected]> 23781 http://mihai.bazon.net/blog 23782 23783 Distributed under the BSD license: 23784 23785 Copyright 2012 (c) Mihai Bazon <[email protected]> 23786 23787 Redistribution and use in source and binary forms, with or without 23788 modification, are permitted provided that the following conditions 23789 are met: 23790 23791 * Redistributions of source code must retain the above 23792 copyright notice, this list of conditions and the following 23793 disclaimer. 23794 23795 * Redistributions in binary form must reproduce the above 23796 copyright notice, this list of conditions and the following 23797 disclaimer in the documentation and/or other materials 23798 provided with the distribution. 23799 23800 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 23801 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23802 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23803 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 23804 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23805 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23806 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23807 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23808 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 23809 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 23810 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23811 SUCH DAMAGE. 23812 23813 ***********************************************************************/ 23814 23815 "use strict"; 23816 23817 (function(){ 23818 23819 var normalize_directives = function(body) { 23820 var in_directive = true; 23821 23822 for (var i = 0; i < body.length; i++) { 23823 if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) { 23824 body[i] = new AST_Directive({ 23825 start: body[i].start, 23826 end: body[i].end, 23827 value: body[i].body.value 23828 }); 23829 } else if (in_directive && !(body[i] instanceof AST_Statement && body[i].body instanceof AST_String)) { 23830 in_directive = false; 23831 } 23832 } 23833 23834 return body; 23835 }; 23836 23837 var MOZ_TO_ME = { 23838 Program: function(M) { 23839 return new AST_Toplevel({ 23840 start: my_start_token(M), 23841 end: my_end_token(M), 23842 body: normalize_directives(M.body.map(from_moz)) 23843 }); 23844 }, 23845 FunctionDeclaration: function(M) { 23846 return new AST_Defun({ 23847 start: my_start_token(M), 23848 end: my_end_token(M), 23849 name: from_moz(M.id), 23850 argnames: M.params.map(from_moz), 23851 body: normalize_directives(from_moz(M.body).body) 23852 }); 23853 }, 23854 FunctionExpression: function(M) { 23855 return new AST_Function({ 23856 start: my_start_token(M), 23857 end: my_end_token(M), 23858 name: from_moz(M.id), 23859 argnames: M.params.map(from_moz), 23860 body: normalize_directives(from_moz(M.body).body) 23861 }); 23862 }, 23863 ExpressionStatement: function(M) { 23864 return new AST_SimpleStatement({ 23865 start: my_start_token(M), 23866 end: my_end_token(M), 23867 body: from_moz(M.expression) 23868 }); 23869 }, 23870 TryStatement: function(M) { 23871 var handlers = M.handlers || [M.handler]; 23872 if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) { 23873 throw new Error("Multiple catch clauses are not supported."); 23874 } 23875 return new AST_Try({ 23876 start : my_start_token(M), 23877 end : my_end_token(M), 23878 body : from_moz(M.block).body, 23879 bcatch : from_moz(handlers[0]), 23880 bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null 23881 }); 23882 }, 23883 Property: function(M) { 23884 var key = M.key; 23885 var args = { 23886 start : my_start_token(key), 23887 end : my_end_token(M.value), 23888 key : key.type == "Identifier" ? key.name : key.value, 23889 value : from_moz(M.value) 23890 }; 23891 if (M.kind == "init") return new AST_ObjectKeyVal(args); 23892 args.key = new AST_SymbolAccessor({ 23893 name: args.key 23894 });
23895 args.value = new AST_Accessor(args.value); 23896 if (M.kind == "get") return new AST_ObjectGetter(args); 23897 if (M.kind == "set") return new AST_ObjectSetter(args); 23898 }, 23899 ArrayExpression: function(M) { 23900 return new AST_Array({ 23901 start : my_start_token(M), 23902 end : my_end_token(M), 23903 elements : M.elements.map(function(elem){ 23904 return elem === null ? new AST_Hole() : from_moz(elem); 23905 }) 23906 }); 23907 }, 23908 ObjectExpression: function(M) { 23909 return new AST_Object({ 23910 start : my_start_token(M), 23911 end : my_end_token(M), 23912 properties : M.properties.map(function(prop){ 23913 prop.type = "Property"; 23914 return from_moz(prop) 23915 }) 23916 }); 23917 }, 23918 SequenceExpression: function(M) { 23919 return AST_Seq.from_array(M.expressions.map(from_moz)); 23920 }, 23921 MemberExpression: function(M) { 23922 return new (M.computed ? AST_Sub : AST_Dot)({ 23923 start : my_start_token(M), 23924 end : my_end_token(M), 23925 property : M.computed ? from_moz(M.property) : M.property.name, 23926 expression : from_moz(M.object) 23927 }); 23928 }, 23929 SwitchCase: function(M) { 23930 return new (M.test ? AST_Case : AST_Default)({ 23931 start : my_start_token(M), 23932 end : my_end_token(M), 23933 expression : from_moz(M.test), 23934 body : M.consequent.map(from_moz) 23935 }); 23936 }, 23937 VariableDeclaration: function(M) { 23938 return new (M.kind === "const" ? AST_Const : AST_Var)({ 23939 start : my_start_token(M), 23940 end : my_end_token(M), 23941 definitions : M.declarations.map(from_moz) 23942 }); 23943 }, 23944 Literal: function(M) { 23945 var val = M.value, args = { 23946 start : my_start_token(M), 23947 end : my_end_token(M) 23948 }; 23949 if (val === null) return new AST_Null(args); 23950 switch (typeof val) { 23951 case "string": 23952 args.value = val; 23953 return new AST_String(args); 23954 case "number": 23955 args.value = val; 23956 return new AST_Number(args); 23957 case "boolean": 23958 return new (val ? AST_True : AST_False)(args); 23959 default: 23960 var rx = M.regex; 23961 if (rx && rx.pattern) { 23962 // RegExpLiteral as per ESTree AST spec 23963 args.value = new RegExp(rx.pattern, rx.flags).toString(); 23964 } else { 23965 // support legacy RegExp 23966 args.value = M.regex && M.raw ? M.raw : val; 23967 } 23968 return new AST_RegExp(args); 23969 } 23970 }, 23971 Identifier: function(M) { 23972 var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; 23973 return new ( p.type == "LabeledStatement" ? AST_Label 23974 : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) 23975 : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) 23976 : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) 23977 : p.type == "CatchClause" ? AST_SymbolCatch 23978 : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef 23979 : AST_SymbolRef)({ 23980 start : my_start_token(M), 23981 end : my_end_token(M), 23982 name : M.name 23983 }); 23984 } 23985 }; 23986 23987 MOZ_TO_ME.UpdateExpression = 23988 MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) { 23989 var prefix = "prefix" in M ? M.prefix 23990 : M.type == "UnaryExpression" ? true : false;
23991 return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ 23992 start : my_start_token(M), 23993 end : my_end_token(M), 23994 operator : M.operator, 23995 expression : from_moz(M.argument) 23996 }); 23997 }; 23998 23999 map("EmptyStatement", AST_EmptyStatement); 24000 map("BlockStatement", AST_BlockStatement, "body@body"); 24001 map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); 24002 map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); 24003 map("BreakStatement", AST_Break, "label>label"); 24004 map("ContinueStatement", AST_Continue, "label>label"); 24005 map("WithStatement", AST_With, "object>expression, body>body"); 24006 map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); 24007 map("ReturnStatement", AST_Return, "argument>value"); 24008 map("ThrowStatement", AST_Throw, "argument>value"); 24009 map("WhileStatement", AST_While, "test>condition, body>body"); 24010 map("DoWhileStatement", AST_Do, "test>condition, body>body"); 24011 map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); 24012 map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); 24013 map("DebuggerStatement", AST_Debugger); 24014 map("VariableDeclarator", AST_VarDef, "id>name, init>value"); 24015 map("CatchClause", AST_Catch, "param>argname, body%body"); 24016 24017 map("ThisExpression", AST_This); 24018 map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); 24019 map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); 24020 map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); 24021 map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); 24022 map("NewExpression", AST_New, "callee>expression, arguments@args"); 24023 map("CallExpression", AST_Call, "callee>expression, arguments@args"); 24024 24025 def_to_moz(AST_Toplevel, function To_Moz_Program(M) { 24026 return to_moz_scope("Program", M); 24027 }); 24028 24029 def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) { 24030 return { 24031 type: "FunctionDeclaration", 24032 id: to_moz(M.name), 24033 params: M.argnames.map(to_moz), 24034 body: to_moz_scope("BlockStatement", M) 24035 } 24036 }); 24037 24038 def_to_moz(AST_Function, function To_Moz_FunctionExpression(M) { 24039 return { 24040 type: "FunctionExpression", 24041 id: to_moz(M.name), 24042 params: M.argnames.map(to_moz), 24043 body: to_moz_scope("BlockStatement", M) 24044 } 24045 }); 24046 24047 def_to_moz(AST_Directive, function To_Moz_Directive(M) { 24048 return { 24049 type: "ExpressionStatement", 24050 expression: { 24051 type: "Literal", 24052 value: M.value 24053 } 24054 }; 24055 }); 24056 24057 def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) { 24058 return { 24059 type: "ExpressionStatement", 24060 expression: to_moz(M.body) 24061 }; 24062 }); 24063 24064 def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) { 24065 return { 24066 type: "SwitchCase", 24067 test: to_moz(M.expression), 24068 consequent: M.body.map(to_moz) 24069 }; 24070 }); 24071 24072 def_to_moz(AST_Try, function To_Moz_TryStatement
24072(M) { 24073 return { 24074 type: "TryStatement", 24075 block: to_moz_block(M), 24076 handler: to_moz(M.bcatch), 24077 guardedHandlers: [], 24078 finalizer: to_moz(M.bfinally) 24079 }; 24080 }); 24081 24082 def_to_moz(AST_Catch, function To_Moz_CatchClause(M) { 24083 return { 24084 type: "CatchClause", 24085 param: to_moz(M.argname), 24086 guard: null, 24087 body: to_moz_block(M) 24088 }; 24089 }); 24090 24091 def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) { 24092 return { 24093 type: "VariableDeclaration", 24094 kind: M instanceof AST_Const ? "const" : "var", 24095 declarations: M.definitions.map(to_moz) 24096 }; 24097 }); 24098 24099 def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) { 24100 return { 24101 type: "SequenceExpression", 24102 expressions: M.to_array().map(to_moz) 24103 }; 24104 }); 24105 24106 def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) { 24107 var isComputed = M instanceof AST_Sub; 24108 return { 24109 type: "MemberExpression", 24110 object: to_moz(M.expression), 24111 computed: isComputed, 24112 property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property} 24113 }; 24114 }); 24115 24116 def_to_moz(AST_Unary, function To_Moz_Unary(M) { 24117 return { 24118 type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression", 24119 operator: M.operator, 24120 prefix: M instanceof AST_UnaryPrefix, 24121 argument: to_moz(M.expression) 24122 }; 24123 }); 24124 24125 def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) { 24126 return { 24127 type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression", 24128 left: to_moz(M.left), 24129 operator: M.operator, 24130 right: to_moz(M.right) 24131 }; 24132 }); 24133 24134 def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) { 24135 return { 24136 type: "ArrayExpression", 24137 elements: M.elements.map(to_moz) 24138 }; 24139 }); 24140 24141 def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) { 24142 return { 24143 type: "ObjectExpression", 24144 properties: M.properties.map(to_moz) 24145 }; 24146 }); 24147 24148 def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) { 24149 var key = { 24150 type: "Literal", 24151 value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key 24152 }; 24153 var kind; 24154 if (M instanceof AST_ObjectKeyVal) { 24155 kind = "init"; 24156 } else 24157 if (M instanceof AST_ObjectGetter) { 24158 kind = "get"; 24159 } else 24160 if (M instanceof AST_ObjectSetter) { 24161 kind = "set"; 24162 } 24163 return { 24164 type: "Property", 24165 kind: kind, 24166 key: key, 24167 value: to_moz(M.value) 24168 }; 24169 }); 24170 24171 def_to_moz(AST_Symbol, function To_Moz_Identifier(M) { 24172 var def = M.definition(); 24173 return { 24174 type: "Identifier", 24175 name: def ? def.mangled_name || def.name : M.name 24176 }; 24177 }); 24178 24179 def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) { 24180 var value = M.value; 24181 return { 24182 type: "Literal", 24183 value: value, 24184 raw: value.toString(), 24185 regex: { 24186 pattern: value.source, 24187 flags: value.toString().match(/[gimuy]*$/)[0] 24188 } 24189 }; 24190 }); 24191 24192 def_to_moz(AST_Constant, function To_Moz_Literal(M) { 24193 var value = M.value; 24194 if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) { 24195 return { 24196 type: "UnaryExpression", 24197 operator: "-", 24198 prefix: true, 24199 argument: { 24200 type: "Literal", 24201 value: -value, 24202 raw: M.start.raw 24203 } 24204 }; 24205 } 24206 return { 24207 type: "Literal", 24208 value: value, 24209 raw: M.start.raw 24210 }; 24211 }); 24212 24213 def_to_moz(AST_Atom, function To_Moz_Atom(M) { 24214 return { 24215 type: "Identifier", 24216 name: String(M.value) 24217 }; 24218 }); 24219 24220 AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast); 24221 AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast); 24222 AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null }); 24223 24224 AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast); 24225 AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast); 24226 24227 /* -----[ tools ]----- */ 24228 24229 function raw_token(moznode) { 24230 if (moznode.type == "Literal") { 24231 return moznode.raw != null ? moznode.raw : moznode.value + ""; 24232 } 24233 } 24234 24235 function my_start_token(moznode) { 24236 var loc = moznode.loc, start = loc && loc.start; 24237 var range = moznode.range; 24238 return new AST_Token({ 24239 file : loc && loc.source, 24240 line : start && start.line, 24241 col : start && start.column, 24242 pos : range ? range[0] : moznode.start, 24243 endline : start && start.line, 24244 endcol : start && start.column, 24245 endpos : range ? range[0] : moznode.start, 24246 raw : raw_token(moznode), 24247 }); 24248 }; 24249 24250 function my_end_token(moznode) { 24251 var loc = moznode.loc, end = loc && loc.end; 24252 var range = moznode.range; 24253 return new AST_Token({ 24254 file : loc && loc.source, 24255 line : end && end.line, 24256 col : end && end.column, 24257 pos : range ? range[1] : moznode.end, 24258 endline : end && end.line, 24259 endcol : end && end.column, 24260 endpos : range ? range[1] : moznode.end, 24261 raw : raw_token(moznode), 24262 }); 24263 }; 24264 24265 function map(moztype, mytype, propmap) { 24266 var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; 24267 moz_to_me += "return new U2." + mytype.name + "({\n" + 24268 "start: my_start_token(M),\n" + 24269 "end: my_end_token(M)"; 24270 24271 var me_to_moz = "function To_Moz_" + moztype + "(M){\n"; 24272 me_to_moz += "return {\n" + 24273 "type: " + JSON.stringify(moztype); 24274 24275 if (propmap) propmap.split(/\s*,\s*/).forEac
24275h(function(prop){ 24276 var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); 24277 if (!m) throw new Error("Can't understand property map: " + prop); 24278 var moz = m[1], how = m[2], my = m[3]; 24279 moz_to_me += ",\n" + my + ": "; 24280 me_to_moz += ",\n" + moz + ": "; 24281 switch (how) { 24282 case "@": 24283 moz_to_me += "M." + moz + ".map(from_moz)"; 24284 me_to_moz += "M." + my + ".map(to_moz)"; 24285 break; 24286 case ">": 24287 moz_to_me += "from_moz(M." + moz + ")"; 24288 me_to_moz += "to_moz(M." + my + ")"; 24289 break; 24290 case "=": 24291 moz_to_me += "M." + moz; 24292 me_to_moz += "M." + my; 24293 break; 24294 case "%": 24295 moz_to_me += "from_moz(M." + moz + ").body"; 24296 me_to_moz += "to_moz_block(M)"; 24297 break; 24298 default: 24299 throw new Error("Can't understand operator in propmap: " + prop); 24300 } 24301 }); 24302 24303 moz_to_me += "\n})\n}"; 24304 me_to_moz += "\n}\n}"; 24305 24306 //moz_to_me = parse(moz_to_me).print_to_string({ beautify: true }); 24307 //me_to_moz = parse(me_to_moz).print_to_string({ beautify: true }); 24308 //console.log(moz_to_me); 24309 24310 moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( 24311 exports, my_start_token, my_end_token, from_moz 24312 ); 24313 me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")( 24314 to_moz, to_moz_block, to_moz_scope 24315 ); 24316 MOZ_TO_ME[moztype] = moz_to_me; 24317 def_to_moz(mytype, me_to_moz); 24318 }; 24319 24320 var FROM_MOZ_STACK = null; 24321 24322 function from_moz(node) { 24323 FROM_MOZ_STACK.push(node); 24324 var ret = node != null ? MOZ_TO_ME[node.type](node) : null; 24325 FROM_MOZ_STACK.pop(); 24326 return ret; 24327 }; 24328 24329 AST_Node.from_mozilla_ast = function(node){ 24330 var save_stack = FROM_MOZ_STACK; 24331 FROM_MOZ_STACK = []; 24332 var ast = from_moz(node); 24333 FROM_MOZ_STACK = save_stack; 24334 return ast; 24335 }; 24336 24337 function set_moz_loc(mynode, moznode, myparent) { 24338 var start = mynode.start; 24339 var end = mynode.end; 24340 if (start.pos != null && end.endpos != null) { 24341 moznode.range = [start.pos, end.endpos]; 24342 } 24343 if (start.line) { 24344 moznode.loc = { 24345 start: {line: start.line, column: start.col}, 24346 end: end.endline ? {line: end.endline, column: end.endcol} : null 24347 }; 24348 if (start.file) { 24349 moznode.loc.source = start.file; 24350 } 24351 } 24352 return moznode; 24353 }; 24354 24355 function def_to_moz(mytype, handler) { 24356 mytype.DEFMETHOD("to_mozilla_ast", function() { 24357 return set_moz_loc(this, handler(this)); 24358 }); 24359 }; 24360 24361 function to_moz(node) { 24362 return node != null ? node.to_mozilla_ast() : null; 24363 }; 24364 24365 function to_moz_block(node) { 24366 return { 24367 type: "BlockStatement",
24368 body: node.body.map(to_moz) 24369 }; 24370 }; 24371 24372 function to_moz_scope(type, node) { 24373 var body = node.body.map(to_moz); 24374 if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) { 24375 body.unshift(to_moz(new AST_EmptyStatement(node.body[0]))); 24376 } 24377 return { 24378 type: type, 24379 body: body 24380 }; 24381 }; 24382 })(); 24383 24384 /*********************************************************************** 24385 24386 A JavaScript tokenizer / parser / beautifier / compressor. 24387 https://github.com/mishoo/UglifyJS2 24388 24389 -------------------------------- (C) --------------------------------- 24390 24391 Author: Mihai Bazon 24392 <[email protected]> 24393 http://mihai.bazon.net/blog 24394 24395 Distributed under the BSD license: 24396 24397 Copyright 2012 (c) Mihai Bazon <[email protected]> 24398 24399 Redistribution and use in source and binary forms, with or without 24400 modification, are permitted provided that the following conditions 24401 are met: 24402 24403 * Redistributions of source code must retain the above 24404 copyright notice, this list of conditions and the following 24405 disclaimer. 24406 24407 * Redistributions in binary form must reproduce the above 24408 copyright notice, this list of conditions and the following 24409 disclaimer in the documentation and/or other materials 24410 provided with the distribution. 24411 24412 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER âAS ISâ AND ANY 24413 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24414 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24415 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 24416 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 24417 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24418 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24419 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24420 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24421 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 24422 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24423 SUCH DAMAGE. 24424 24425 ***********************************************************************/ 24426 24427 "use strict"; 24428 24429 function find_builtins() { 24430 // NaN will be included due to Number.NaN 24431 var a = [ 24432 "null", 24433 "true", 24434 "false", 24435 "Infinity", 24436 "-Infinity", 24437 "undefined", 24438 ]; 24439 [ Object, Array, Function, Number, 24440 String, Boolean, Error, Math, 24441 Date, RegExp 24442 ].forEach(function(ctor){ 24443 Object.getOwnPropertyNames(ctor).map(add); 24444 if (ctor.prototype) { 24445 Object.getOwnPropertyNames(ctor.prototype).map(add); 24446 } 24447 }); 24448 function add(name) { 24449 push_uniq(a, name); 24450 } 24451 return a; 24452 } 24453 24454 function mangle_properties(ast, options) { 24455 options = defaults(options, { 24456 cache: null, 24457 debug: false, 24458 ignore_quoted: false, 24459 only_cache: false, 24460 regex: null, 24461 reserved: null, 24462 }); 24463 24464 var reserved = options.reserved; 24465 if (reserved == null) 24466 reserved = find_builtins(); 24467 24468 var cache = options.cache; 24469 if (cache == null) { 24470 cache = { 24471 cname: -1, 24472 props: new Dictionary() 24473 }; 24474 } 24475 24476 var regex = options.regex; 24477 var ignore_quoted = options.ignore_quoted; 24478 24479 // note debug is either false (disabled), or a string of the debug suffix to use (enabled). 24480 // note debug may be enabled as an empty string, which is falsey. Also treat passing 'true' 24481 // the same as passing an empty string. 24482 var debug = (options.debug !== false); 24483 var debug_name_suffix; 24484 if (debug) { 24485 debug_name_suffix = (options.debug === true ? "" : options.debug); 24486 } 24487 24488 var names_to_mangle = []; 24489 var unmangleable = []; 24490 var ignored = {}; 24491 24492 // step 1: find candidates to mangle 24493 ast.walk(new TreeWalker(function(node){ 24494 if (node instanceof AST_ObjectKeyVal) { 24495 add(node.key, ignore_quoted && node.quote); 24496 } 24497 else if (node instanceof AST_ObjectProperty) { 24498 // setter or getter, since KeyVal is handled above 24499 add(node.key.name); 24500 } 24501 else if (node instanceof AST_Dot) { 24502 add(node.property); 24503 } 24504 else if (node instanceof AST_Sub) { 24505 addStrings(node.property, ignore_quoted); 24506 } 24507 })); 24508 24509 // step 2: transform the tree, renaming properties 24510 return ast.transform(new TreeTransformer(function(node){ 24511 if (node instanceof AST_ObjectKeyVal) { 24512 if (!(ignore_quoted && node.quote)) 24513 node.key = mangle(node.key); 24514 } 24515 else if (node instanceof AST_ObjectProperty) { 24516 // setter or getter 24517 node.key.name = mangle(node.key.name); 24518 } 24519 else if (node instanceof AST_Dot) { 24520 node.property = mangle(node.property); 24521 } 24522 else if (node instanceof AST_Sub) { 24523 if (!ignore_quoted) 24524 node.property = mangleStrings(node.property); 24525 } 24526 // else if (node instanceof AST_String) { 24527 // if (should_mangle(node.value)) { 24528 // AST_Node.warn( 24529 // "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
24530 // file : node.start.file, 24531 // line : node.start.line, 24532 // col : node.start.col, 24533 // prop : node.value 24534 // } 24535 // ); 24536 // } 24537 // } 24538 })); 24539 24540 // only function declarations after this line 24541 24542 function can_mangle(name) { 24543 if (unmangleable.indexOf(name) >= 0) return false; 24544 if (reserved.indexOf(name) >= 0) return false; 24545 if (options.only_cache) { 24546 return cache.props.has(name); 24547 } 24548 if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false; 24549 return true; 24550 } 24551 24552 function should_mangle(name) { 24553 if (ignore_quoted && name in ignored) return false; 24554 if (regex && !regex.test(name)) return false; 24555 if (reserved.indexOf(name) >= 0) return false; 24556 return cache.props.has(name) 24557 || names_to_mangle.indexOf(name) >= 0; 24558 } 24559 24560 function add(name, ignore) { 24561 if (ignore) { 24562 ignored[name] = true; 24563 return; 24564 } 24565 24566 if (can_mangle(name)) 24567 push_uniq(names_to_mangle, name); 24568 24569 if (!should_mangle(name)) { 24570 push_uniq(unmangleable, name); 24571 } 24572 } 24573 24574 function mangle(name) { 24575 if (!should_mangle(name)) { 24576 return name; 24577 } 24578 24579 var mangled = cache.props.get(name); 24580 if (!mangled) { 24581 if (debug) { 24582 // debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_. 24583 var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_"; 24584 24585 if (can_mangle(debug_mangled) && !(ignore_quoted && debug_mangled in ignored)) { 24586 mangled = debug_mangled; 24587 } 24588 } 24589 24590 // either debug mode is off, or it is on and we could not use the mangled name 24591 if (!mangled) { 24592 // note can_mangle() does not check if the name collides with the 'ignored' set 24593 // (filled with quoted properties when ignore_quoted set). Make sure we add this 24594 // check so we don't collide with a quoted name. 24595 do { 24596 mangled = base54(++cache.cname); 24597 } while (!can_mangle(mangled) || (ignore_quoted && mangled in ignored)); 24598 } 24599 24600 cache.props.set(name, mangled); 24601 } 24602 return mangled; 24603 } 24604 24605 function addStrings(node, ignore) { 24606 var out = {}; 24607 try { 24608 (function walk(node){ 24609 node.walk(new TreeWalker(function(node){ 24610 if (node instanceof AST_Seq) { 24611 walk(node.cdr); 24612 return true; 24613 } 24614 if (node instanceof AST_String) { 24615 add(node.value, ignore); 24616 return true; 24617 } 24618 if (node instanceof AST_Conditional) { 24619 walk(node.consequent); 24620 walk(node.alternative); 24621 return true; 24622 } 24623 throw out; 24624 })); 24625 })(node); 24626 } catch(ex) { 24627 if (ex !== out) throw ex; 24628 } 24629 } 24630 24631 function mangleStrings(node) { 24632 return node.transform(new TreeTransformer(function(node){ 24633 if (node instanceof AST_Seq) { 24634 node.cdr = mangleStrings(node.cdr); 24635 } 24636 else if (node instanceof AST_String) { 24637 node.value = mangle(node.value); 24638 } 24639 else if (node instanceof AST_Conditional) { 24640 node.consequent = mangleStrings(node.consequent); 24641 node.alternative = mangleStrings(node.alternative); 24642 } 24643 return node; 24644 })); 24645 } 24646 24647 } 24648 24649 exports["Compressor"] = Compressor; 24650 exports["DefaultsError"] = DefaultsError; 24651 exports["Dictionary"] = Dictionary; 24652 exports["JS_Parse_Error"] = JS_Parse_Error; 24653 exports["MAP"] = MAP; 24654 exports["OutputStream"] = OutputStream; 24655 exports["SourceMap"] = SourceMap; 24656 exports["TreeTransformer"] = TreeTransformer; 24657 exports["TreeWalker"] = TreeWalker; 24658 exports["base54"] = base54; 24659 exports["defaults"] = defaults; 24660 exports["mangle_properties"] = mangle_properties; 24661 exports["merge"] = merge; 24662 exports["parse"] = parse; 24663 exports["push_uniq"] = push_uniq; 24664 exports["string_template"] = string_template; 24665 exports["tokenizer"] = tokenizer; 24666 exports["is_identifier"] = is_identifier; 24667 exports["SymbolDef"] = SymbolDef; 24668 24669 AST_Node.warn_function = function(txt) { logger.error("uglifyjs WARN: " + txt); }; 24670 24671 exports.AST_Node.warn_function = function(txt) { 24672 console.error("WARN: %s", txt); 24673 }; 24674 24675 function read_source_map(code) { 24676 var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code); 24677 if (!match) { 24678 exports.AST_Node.warn("inline source map not found"); 24679 return null; 24680 } 24681 return JSON.parse(new Buffer(match[2], "base64")); 24682 } 24683 24684 exports.minify = function(files, options, name) { 24685 options = exports.defaults(options, { 24686 compress : {}, 24687 fromString : false, 24688 inSourceMap : null, 24689 mangle : {}, 24690 mangleProperties : false, 24691 nameCache : null, 24692 outFileName : null, 24693 output : null, 24694 outSourceMap : null, 24695 parse : {}, 24696 sourceMapInline : false, 24697 sourceMapUrl : null, 24698 sourceRoot : null, 24699 spidermonkey : false, 24700 warnings : false, 24701 }); 24702 exports.base54.reset(); 24703 24704 var inMap = options.inSourceMap; 24705 if (typeof inMap == "string" && inMap != "inline") { 24706 inMap = JSON.parse(rjsFile.readFile(inMap, "utf8")); 24707 } 24708 24709 // 1. parse 24710 var toplevel = null, 24711 sourcesContent = {}; 24712 24713 if (options.spidermonkey) { 24714 if (inMap == "inline") { 24715 throw new Error("inline source map only w
24715orks with built-in parser"); 24716 } 24717 toplevel = exports.AST_Node.from_mozilla_ast(files); 24718 } else { 24719 var addFile = function(file, fileUrl) { 24720 var code = options.fromString 24721 ? file 24722 : rjsFile.readFile(file, "utf8"); 24723 if (inMap == "inline") { 24724 inMap = read_source_map(code); 24725 } 24726 sourcesContent[fileUrl] = code; 24727 toplevel = exports.parse(code, { 24728 filename: fileUrl, 24729 toplevel: toplevel, 24730 bare_returns: options.parse ? options.parse.bare_returns : undefined 24731 }); 24732 } 24733 if (!options.fromString) { 24734 files = exports.simple_glob(files); 24735 if (inMap == "inline" && files.length > 1) { 24736 throw new Error("inline source map only works with singular input"); 24737 } 24738 } 24739 [].concat(files).forEach(function (files, i) { 24740 if (typeof files === 'string') { 24741 addFile(files, options.fromString ? i : files); 24742 } else { 24743 for (var fileUrl in files) { 24744 addFile(files[fileUrl], fileUrl); 24745 } 24746 } 24747 }); 24748 } 24749 if (options.wrap) { 24750 toplevel = toplevel.wrap_commonjs(options.wrap, options.exportAll); 24751 } 24752 24753 // 2. compress 24754 if (options.compress) { 24755 var compress = { warnings: options.warnings }; 24756 exports.merge(compress, options.compress); 24757 toplevel.figure_out_scope(options.mangle); 24758 var sq = exports.Compressor(compress); 24759 toplevel = sq.compress(toplevel); 24760 } 24761 24762 // 3. mangle properties 24763 if (options.mangleProperties || options.nameCache) { 24764 options.mangleProperties.cache = exports.readNameCache(options.nameCache, "props"); 24765 toplevel = exports.mangle_properties(toplevel, options.mangleProperties); 24766 exports.writeNameCache(options.nameCache, "props", options.mangleProperties.cache); 24767 } 24768 24769 // 4. mangle 24770 if (options.mangle) { 24771 toplevel.figure_out_scope(options.mangle); 24772 toplevel.compute_char_frequency(options.mangle); 24773 toplevel.mangle_names(options.mangle); 24774 } 24775 24776 // 5. output 24777 var output = { max_line_len: 32000 }; 24778 if (options.outSourceMap || options.sourceMapInline) { 24779 output.source_map = exports.SourceMap({ 24780 // prefer outFileName, otherwise use outSourceMap without .map suffix 24781 file: options.outFileName || (typeof options.outSourceMap === 'string' ? options.outSourceMap.replace(/\.map$/i, '') : null), 24782 orig: inMap, 24783 root: options.sourceRoot 24784 }); 24785 if (options.sourceMapIncludeSources) { 24786 for (var file in sourcesContent) { 24787 if (sourcesContent.hasOwnProperty(file)) { 24788 output.source_map.get().setSourceContent(file, sourcesContent[file]); 24789 } 24790 } 24791 } 24792 24793 } 24794 if (options.output) { 24795 exports.merge(output, options.output); 24796 } 24797 var stream = exports.OutputStream(output); 24798 toplevel.print(stream); 24799 24800 24801 var source_map = output.source_map; 24802 if (source_map) { 24803 source_map = source_map + ""; 24804 } 24805 24806 var mappingUrlPrefix = "\n//# sourceMappingURL="; 24807 if (options.sourceMapInline) { 24808 stream += mappingUrlPrefix + "data:application/json;charset=utf-8;base64," + new Buffer(source_map).toString("base64"); 24809 } else if (options.outSourceMap && typeof options.outSourceMap === "string" && options.sourceMapUrl !== false) { 24810 stream += mappingUrlPrefix + (typeof options.sourceMapUrl === "string" ? options.sourceMapUrl : options.outSourceMap); 24811 } 24812 24813 return { 24814 code : stream + "", 24815 map : source_map 24816 }; 24817 }; 24818
24819// exports.describe_ast = function() { 24820// function doitem(ctor) { 24821// var sub = {}; 24822// ctor.SUBCLASSES.forEach(function(ctor){ 24823// sub[ctor.TYPE] = doitem(ctor); 24824// }); 24825// var ret = {}; 24826// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; 24827// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; 24828// return ret; 24829// } 24830// return doitem(exports.AST_Node).sub; 24831// } 24832 24833 exports.describe_ast = function() { 24834 var out = exports.OutputStream({ beautify: true }); 24835 function doitem(ctor) { 24836 out.print("AST_" + ctor.TYPE); 24837 var props = ctor.SELF_PROPS.filter(function(prop){ 24838 return !/^\$/.test(prop); 24839 }); 24840 if (props.length > 0) { 24841 out.space(); 24842 out.with_parens(function(){ 24843 props.forEach(function(prop, i){ 24844 if (i) out.space(); 24845 out.print(prop); 24846 }); 24847 }); 24848 } 24849 if (ctor.documentation) { 24850 out.space(); 24851 out.print_string(ctor.documentation); 24852 } 24853 if (ctor.SUBCLASSES.length > 0) { 24854 out.space(); 24855 out.with_block(function(){ 24856 ctor.SUBCLASSES.forEach(function(ctor, i){ 24857 out.indent(); 24858 doitem(ctor); 24859 out.newline(); 24860 }); 24861 }); 24862 } 24863 }; 24864 doitem(exports.AST_Node); 24865 return out + ""; 24866 }; 24867 24868 function readReservedFile(filename, reserved) { 24869 if (!reserved) { 24870 reserved = { vars: [], props: [] }; 24871 } 24872 var data = rjsFile.readFile(filename, "utf8"); 24873 data = JSON.parse(data); 24874 if (data.vars) { 24875 data.vars.forEach(function(name){ 24876 exports.push_uniq(reserved.vars, name); 24877 }); 24878 } 24879 if (data.props) { 24880 data.props.forEach(function(name){ 24881 exports.push_uniq(reserved.props, name); 24882 }); 24883 } 24884 return reserved; 24885 } 24886 24887 exports.readReservedFile = readReservedFile; 24888 24889 exports.readDefaultReservedFile = function(reserved) { 24890 return readReservedFile(require.resolve("./domprops.json"), reserved); 24891 }; 24892 24893 exports.readNameCache = function(filename, key) { 24894 var cache = null; 24895 if (filename) { 24896 try { 24897 var cache = rjsFile.readFile(filename, "utf8"); 24898 cache = JSON.parse(cache)[key]; 24899 if (!cache) throw "init"; 24900 cache.props = exports.Dictionary.fromObject(cache.props); 24901 } catch(ex) { 24902 cache = { 24903 cname: -1, 24904 props: new exports.Dictionary() 24905 }; 24906 } 24907 } 24908 return cache; 24909 }; 24910 24911 exports.writeNameCache = function(filename, key, cache) { 24912 if (filename) { 24913 var data; 24914 try { 24915 data = rjsFile.readFile(filename, "utf8"); 24916 data = JSON.parse(data); 24917 } catch(ex) { 24918 data = {}; 24919 } 24920 data[key] = { 24921 cname: cache.cname, 24922 props: cache.props.toObject() 24923 }; 24924 rjsFile.writeFile(filename, JSON.stringify(data, null, 2), "utf8"); 24925 } 24926 }; 24927 24928// A file glob function that only supports "*" and "?" wildcards in the base
24928name. 24929// Example: "foo/bar/*baz??.*.js" 24930// Argument `glob` may be a string or an array of strings. 24931// Returns an array of strings. Garbage in, garbage out. 24932 exports.simple_glob = function simple_glob(glob) { 24933 if (Array.isArray(glob)) { 24934 return [].concat.apply([], glob.map(simple_glob)); 24935 } 24936 if (glob.match(/\*|\?/)) { 24937 var dir = path.dirname(glob); 24938 try { 24939 var entries = fs.readdirSync(dir); 24940 } catch (ex) {} 24941 if (entries) { 24942 var pattern = "^" + path.basename(glob) 24943 .replace(/[.+^$[\]\\(){}]/g, "\\$&") 24944 .replace(/\*/g, "[^/\\\\]*") 24945 .replace(/\?/g, "[^/\\\\]") + "$"; 24946 var mod = process.platform === "win32" ? "i" : ""; 24947 var rx = new RegExp(pattern, mod); 24948 var results = entries.filter(function(name) { 24949 return rx.test(name); 24950 }).map(function(name) { 24951 return path.join(dir, name); 24952 }); 24953 if (results.length) return results; 24954 } 24955 } 24956 return [ glob ]; 24957 }; 24958 24959 24960 }); 24961 /*jslint plusplus: true */ 24962 /*global define: false */ 24963 24964 define('parse', ['./esprimaAdapter', 'lang'], function (esprima, lang) { 24965 'use strict'; 24966 24967 function arrayToString(ary) { 24968 var output = '['; 24969 if (ary) {
24970 ary.forEach(function (item, i) { 24971 output += (i > 0 ? ',' : '') + '"' + lang.jsEscape(item) + '"'; 24972 }); 24973 } 24974 output += ']'; 24975 24976 return output; 24977 } 24978 24979 //This string is saved off because JSLint complains 24980 //about obj.arguments use, as 'reserved word' 24981 var argPropName = 'arguments', 24982 //Default object to use for "scope" checking for UMD identifiers. 24983 emptyScope = {}, 24984 mixin = lang.mixin, 24985 hasProp = lang.hasProp; 24986 24987 //From an esprima example for traversing its ast. 24988 function traverse(object, visitor) { 24989 var child; 24990 24991 if (!object) { 24992 return; 24993 } 24994 24995 if (visitor.call(null, object) === false) { 24996 return false; 24997 } 24998 for (var i = 0, keys = Object.keys(object); i < keys.length; i++) { 24999 child = object[keys[i]]; 25000 if (typeof child === 'object' && child !== null) { 25001 if (traverse(child, visitor) === false) { 25002 return false; 25003 } 25004 } 25005 } 25006 } 25007 25008 //Like traverse, but visitor returning false just 25009 //stops that subtree analysis, not the rest of tree 25010 //visiting. 25011 function traverseBroad(object, visitor) { 25012 var child; 25013 25014 if (!object) { 25015 return; 25016 } 25017 25018 if (visitor.call(null, object) === false) { 25019 return false; 25020 } 25021 for (var i = 0, keys = Object.keys(object); i < keys.length; i++) { 25022 child = object[key]; 25023 if (typeof child === 'object' && child !== null) { 25024 traverseBroad(child, visitor); 25025 } 25026 } 25027 } 25028 25029 /** 25030 * Pulls out dependencies from an array literal with just string members. 25031 * If string literals, will just return those string values in an array, 25032 * skipping other items in the array. 25033 * 25034 * @param {Node} node an AST node. 25035 * 25036 * @returns {Array} an array of strings. 25037 * If null is returned, then it means the input node was not a valid 25038 * dependency. 25039 */ 25040 function getValidDeps(node) { 25041 if (!node || node.type !== 'ArrayExpression' || !node.elements) { 25042 return; 25043 } 25044 25045 var deps = []; 25046 25047 node.elements.some(function (elem) { 25048 if (elem.type === 'Literal') { 25049 deps.push(elem.value); 25050 } 25051 }); 25052 25053 return deps.length ? deps : undefined; 25054 } 25055 25056 // Detects regular or arrow function expressions as the desired expression 25057 // type. 25058 function isFnExpression(node) { 25059 return (node && (node.type === 'FunctionExpression' || 25060 node.type === 'ArrowFunctionExpression')); 25061 } 25062 25063 /** 25064 * Main parse function. Returns a string of any valid require or 25065 * define/require.def calls as part of one JavaScript source string. 25066 * @param {String} moduleName the module name that represents this file. 25067 * It is used to create a default define if there is not one already for the 25068 * file. This allows properly tracing dependencies for builds. Otherwise, if 25069 * the file just has a require() call, the file dependencies will not be 25070 * properly reflected: the file will come before its dependencies. 25071 * @param {String} moduleName 25072 * @param {String} fileName 25073 * @param {String} fileContents 25074 * @param {Object} options optional options. insertNeedsDefine: true will 25075 * add calls to require.needsDefine() if appropriate. 25076 * @returns {String} JS source string or null, if no require or 25077 * define/require.def calls are found. 25078 */ 25079 function parse(moduleName, fileName, fileContents, options) { 25080 options = options || {}; 25081 25082 //Set up source input
25083 var i, moduleCall, depString, 25084 moduleDeps = [], 25085 result = '', 25086 moduleList = [], 25087 needsDefine = true, 25088 astRoot = esprima.parse(fileContents); 25089 25090 parse.recurse(astRoot, function (callName, config, name, deps, node, factoryIdentifier, fnExpScope) { 25091 if (!deps) { 25092 deps = []; 25093 } 25094 25095 if (callName === 'define' && (!name || name === moduleName)) { 25096 needsDefine = false; 25097 } 25098 25099 if (!name) { 25100 //If there is no module name, the dependencies are for 25101 //this file/default module name. 25102 moduleDeps = moduleDeps.concat(deps); 25103 } else { 25104 moduleList.push({ 25105 name: name, 25106 deps: deps 25107 }); 25108 } 25109 25110 if (callName === 'define' && factoryIdentifier && hasProp(fnExpScope, factoryIdentifier)) { 25111 return factoryIdentifier; 25112 } 25113 25114 //If define was found, no need to dive deeper, unless 25115 //the config explicitly wants to dig deeper. 25116 return !!options.findNestedDependencies; 25117 }, options); 25118 25119 if (options.insertNeedsDefine && needsDefine) { 25120 result += 'require.needsDefine("' + moduleName + '");'; 25121 } 25122 25123 if (moduleDeps.length || moduleList.length) { 25124 for (i = 0; i < moduleList.length; i++) { 25125 moduleCall = moduleList[i]; 25126 if (result) { 25127 result += '\n'; 25128 } 25129 25130 //If this is the main module for this file, combine any 25131 //"anonymous" dependencies (could come from a nested require 25132 //call) with this module. 25133 if (moduleCall.name === moduleName) { 25134 moduleCall.deps = moduleCall.deps.concat(moduleDeps); 25135 moduleDeps = []; 25136 } 25137 25138 depString = arrayToString(moduleCall.deps); 25139 result += 'define("' + moduleCall.name + '",' + 25140 depString + ');'; 25141 } 25142 if (moduleDeps.length) { 25143 if (result) { 25144 result += '\n'; 25145 } 25146 depString = arrayToString(moduleDeps); 25147 result += 'define("' + moduleName + '",' + depString + ');'; 25148 } 25149 } 25150 25151 return result || null; 25152 } 25153 25154 parse.traverse = traverse; 25155 parse.traverseBroad = traverseBroad; 25156 parse.isFnExpression = isFnExpression; 25157 25158 /** 25159 * Handles parsing a file recursively for require calls. 25160 * @param {Array} parentNode the AST node to start with. 25161 * @param {Function} onMatch function to call on a parse match. 25162 * @param {Object} [options] This is normally the build config options if 25163 * it is passed. 25164 * @param {Object} [fnExpScope] holds list of function expresssion 25165 * argument identifiers, set up internally, not passed in 25166 */ 25167 parse.recurse = function (object, onMatch, options, fnExpScope) { 25168 //Like traverse, but skips if branches that would not be processed 25169 //after has application that results in tests of true or false boolean 25170 //literal values. 25171 var keys, child, result, i, params, param, tempObject, 25172 hasHas = options && options.has; 25173 25174 fnExpScope = fnExpScope || emptyScope; 25175 25176 if (!object) { 25177 return; 25178 } 25179 25180 //If has replacement has resulted in if(true){} or if(false){}, take 25181 //the appropriate branch and skip the other one. 25182 if (hasHas && object.type === 'IfStatement' && object.test.type && 25183 object.test.type === 'Literal') { 25184 if (object.test.value) { 25185 //Take the if branch 25186 this.recurse(object.consequent, onMatch, options, fnExpScope); 25187 } else { 25188 //Take the else branch 25189 this.recurse(object.alternate, onMatch, options, fnExpScope); 25190 } 25191 } else { 25192 result = this.parseNode(object, onMatch, fnExpScope); 25193 if (result === false) { 25194 return; 25195 } else if (typeof result === 'string') { 25196 return result; 25197 } 25198 25199 //Build up a "scope" object that informs nested recurse calls if 25200 //the define call references an identifier that is likely a UMD 25201 //wrapped function expression argument. 25202 //Catch (function(a) {... wrappers 25203 if (object.type === 'ExpressionStatement' && object.expression && 25204 object.expression.type === 'CallExpression' && object.expression.callee && 25205 isFnExpression(object.expression.callee)) { 25206 tempObject = object.expression.callee; 25207 } 25208 // Catch !function(a) {... wrappers 25209 if (object.type === 'UnaryExpression' && object.argument && 25210 object.argument.type === 'CallExpression' && object.argument.callee && 25211 isFnExpression(object.argument.callee)) { 25212 tempObject = object.argument.callee; 25213 } 25214 if (tempObject && tempObject.params && tempObject.params.length) { 25215 params = tempObject.params; 25216 fnExpScope = mixin({}, fnExpScope, true); 25217 for (i = 0; i < params.length; i++) { 25218 param = params[i]; 25219 if (param.type === 'Identifier') { 25220 fnExpScope[param.name] = true; 25221 } 25222 } 25223 } 25224 25225 for (i = 0, keys = Object.keys(object); i < keys.length; i++) { 25226 child = object[keys[i]]; 25227 if (typeof child === 'object' && child !== null) { 25228 result = this.recurse(child, onMatch, options, fnExpScope); 25229 if (typeof result === 'string' && hasProp(fnExpScope, result)) { 25230 //The result was still in fnExpScope so break. Otherwise, 25231 //was a return from a a tree that had a UMD definition, 25232 //but now out of that scope so keep siblings. 25233 break; 25234 } 25235 } 25236 } 25237 25238 //Check for an identifier for a factory function identifier being 25239 //passed in as a function expression, indicating a UMD-type of 25240 //wrapping. 25241 if (typeof result === 'string') { 25242 if (hasProp(fnExpScope, result)) { 25243 //result still in scope, keep jumping out indicating the 25244 //identifier still in use. 25245 return result; 25246 } 25247 25248 return; 25249 } 25250 } 25251 }; 25252 25253 /** 25254 * Determines if the file defines the require/define module API. 25255 * Specifically, it looks for the `define.amd = ` expression. 25256 * @param {String} fileName 25257 * @param {String} fileContents 25258 * @returns {Boolean} 25259 */ 25260 parse.definesRequire = function (fileName, fileContents) { 25261 var foundDefine = false, 25262 foundDefineAmd = false;
25263 25264 traverse(esprima.parse(fileContents), function (node) { 25265 // Look for a top level declaration of a define, like 25266 // var requirejs, require, define, off Program body. 25267 if (node.type === 'Program' && node.body && node.body.length) { 25268 foundDefine = node.body.some(function(bodyNode) { 25269 // var define 25270 if (bodyNode.type === 'VariableDeclaration') { 25271 var decls = bodyNode.declarations; 25272 if (decls) { 25273 var hasVarDefine = decls.some(function(declNode) { 25274 return (declNode.type === 'VariableDeclarator' && 25275 declNode.id && 25276 declNode.id.type === 'Identifier' && 25277 declNode.id.name === 'define'); 25278 }); 25279 if (hasVarDefine) { 25280 return true; 25281 } 25282 } 25283 } 25284 25285 // function define() {} 25286 if (bodyNode.type === 'FunctionDeclaration' && 25287 bodyNode.id && 25288 bodyNode.id.type === 'Identifier' && 25289 bodyNode.id.name === 'define') { 25290 return true; 25291 } 25292 25293 25294 25295 25296 25297 25298 }); 25299 } 25300 25301 // Need define variable found first, before detecting define.amd. 25302 if (foundDefine && parse.hasDefineAmd(node)) { 25303 foundDefineAmd = true; 25304 25305 //Stop traversal 25306 return false; 25307 } 25308 }); 25309 25310 return foundDefine && foundDefineAmd; 25311 }; 25312 25313 /** 25314 * Finds require("") calls inside a CommonJS anonymous module wrapped in a 25315 * define(function(require, exports, module){}) wrapper. These dependencies 25316 * will be added to a modified define() call that lists the dependencies 25317 * on the outside of the function. 25318 * @param {String} fileName 25319 * @param {String|Object} fileContents: a string of contents, or an already 25320 * parsed AST tree. 25321 * @returns {Array} an array of module names that are dependencies. Always 25322 * returns an array, but could be of length zero. 25323 */ 25324 parse.getAnonDeps = function (fileName, fileContents) { 25325 var astRoot = typeof fileContents === 'string' ? 25326 esprima.parse(fileContents) : fileContents, 25327 defFunc = this.findAnonDefineFactory(astRoot); 25328 25329 return parse.getAnonDepsFromNode(defFunc); 25330 }; 25331 25332 /** 25333 * Finds require("") calls inside a CommonJS anonymous module wrapped 25334 * in a define function, given an AST node for the definition function. 25335 * @param {Node} node the AST node for the definition function. 25336 * @returns {Array} and array of dependency names. Can be of zero length. 25337 */ 25338 parse.getAnonDepsFromNode = function (node) { 25339 var deps = [], 25340 funcArgLength; 25341 25342 if (node) { 25343 this.findRequireDepNames(node, deps); 25344 25345 //If no deps, still add the standard CommonJS require, exports, 25346 //module, in that order, to the deps, but only if specified as 25347 //function args. In particular, if exports is used, it is favored 25348 //over the return value of the function, so only add it if asked. 25349 funcArgLength = node.params && node.params.length; 25350 if (funcArgLength) { 25351 deps = (funcArgLength > 1 ? ["require", "exports", "module"] : 25352 ["require"]).concat(deps); 25353 } 25354 } 25355 return deps; 25356 }; 25357 25358 parse.isDefineNodeWithArgs = function (node) { 25359 return node && node.type === 'CallExpression' && 25360 node.callee && node.callee.type === 'Identifier' && 25361 node.callee.name === 'define' && node[argPropName]; 25362 }; 25363 25364 /** 25365 * Finds the function in define(function (require, exports, module){}); 25366 * @param {Array} node 25367 * @returns {Boolean} 25368 */ 25369 parse.findAnonDefineFactory = function (node) { 25370 var match; 25371 25372 traverse(node, function (node) { 25373 var arg0, arg1; 25374 25375 if (parse.isDefineNodeWithArgs(node)) { 25376 25377 //Just the factory function passed to define 25378 arg0 = node[argPropName][0]; 25379 if (isFnExpression(arg0)) { 25380 match = arg0; 25381 return false;
25382 } 25383 25384 //A string literal module ID followed by the factory function. 25385 arg1 = node[argPropName][1]; 25386 if (arg0.type === 'Literal' && isFnExpression(arg1)) { 25387 match = arg1; 25388 return false; 25389 } 25390 } 25391 }); 25392 25393 return match; 25394 }; 25395 25396 /** 25397 * Finds any config that is passed to requirejs. That includes calls to 25398 * require/requirejs.config(), as well as require({}, ...) and 25399 * requirejs({}, ...) 25400 * @param {String} fileContents 25401 * 25402 * @returns {Object} a config details object with the following properties: 25403 * - config: {Object} the config object found. Can be undefined if no 25404 * config found. 25405 * - range: {Array} the start index and end index in the contents where 25406 * the config was found. Can be undefined if no config found. 25407 * Can throw an error if the config in the file cannot be evaluated in 25408 * a build context to valid JavaScript. 25409 */ 25410 parse.findConfig = function (fileContents) { 25411 /*jslint evil: true */ 25412 var jsConfig, foundConfig, stringData, foundRange, quote, quoteMatch, 25413 quoteRegExp = /(:\s|\[\s*)(['"])/, 25414 astRoot = esprima.parse(fileContents, { 25415 loc: true 25416 }); 25417 25418 traverse(astRoot, function (node) { 25419 var arg, 25420 requireType = parse.hasRequire(node); 25421 25422 if (requireType && (requireType === 'require' || 25423 requireType === 'requirejs' || 25424 requireType === 'requireConfig' || 25425 requireType === 'requirejsConfig')) { 25426 25427 arg = node[argPropName] && node[argPropName][0]; 25428 25429 if (arg && arg.type === 'ObjectExpression') { 25430 stringData = parse.nodeToString(fileContents, arg); 25431 jsConfig = stringData.value; 25432 foundRange = stringData.range; 25433 return false; 25434 } 25435 } else { 25436 arg = parse.getRequireObjectLiteral(node); 25437 if (arg) { 25438 stringData = parse.nodeToString(fileContents, arg); 25439 jsConfig = stringData.value; 25440 foundRange = stringData.range; 25441 return false; 25442 } 25443 } 25444 }); 25445 25446 if (jsConfig) { 25447 // Eval the config 25448 quoteMatch = quoteRegExp.exec(jsConfig); 25449 quote = (quoteMatch && quoteMatch[2]) || '"'; 25450 foundConfig = eval('(' + jsConfig + ')'); 25451 } 25452 25453 return { 25454 config: foundConfig, 25455 range: foundRange, 25456 quote: quote 25457 }; 25458 }; 25459 25460 /** Returns the node for the object literal assigned to require/requirejs, 25461 * for holding a declarative config. 25462 */ 25463 parse.getRequireObjectLiteral = function (node) { 25464 if (node.id && node.id.type === 'Identifier' && 25465 (node.id.name === 'require' || node.id.name === 'requirejs') && 25466 node.init && node.init.type === 'ObjectExpression') { 25467 return node.init; 25468 } 25469 }; 25470 25471 /** 25472 * Renames require/requirejs/define calls to be ns + '.' + require/requirejs/define 25473 * Does *not* do .config calls though. See pragma.namespace for the complete 25474 * set of namespace transforms. This function is used because require calls 25475 * inside a define() call should not be renamed, so a simple regexp is not 25476 * good enough. 25477 * @param {String} fileContents the contents to transform. 25478 * @param {String} ns the namespace, *not* including trailing dot. 25479 * @return {String} the fileContents with the namespace applied 25480 */ 25481 parse.renameNamespace = function (fileContents, ns) { 25482 var lines, 25483 locs = [], 25484 astRoot = esprima.parse(fileContents, { 25485 loc: true 25486 }); 25487 25488 parse.recurse(astRoot, function (callName, config, name, deps, node) { 25489 locs.push(node.loc); 25490 //Do not recurse into define functions, they should be using 25491 //local defines. 25492 return callName !== 'define'; 25493 }, {}); 25494 25495 if (locs.length) { 25496 lines = fileContents.split('\n'); 25497 25498 //Go backwards through the found locs, adding in the namespace name 25499 //in front. 25500 locs.reverse(); 25501 locs.forEach(function (loc) { 25502 var startIndex = loc.start.column, 25503 //start.line is 1-based, not 0 based. 25504 lineIndex = loc.start.line - 1, 25505 line = lines[lineIndex]; 25506 25507 lines[lineIndex] = line.substring(0, startIndex) + 25508 ns + '.' + 25509 line.substring(startIndex, 25510 line.length); 25511 }); 25512 25513 fileContents = lines.join('\n'); 25514 } 25515 25516 return fileContents; 25517 }; 25518 25519 /** 25520 * Finds all dependencies specified in dependency arrays and inside 25521 * simplified commonjs wrappers. 25522 * @param {String} fileName 25523 * @param {String} fileContents 25524 * 25525 * @returns {Array} an array of dependency strings. The dependencies 25526 * have not been normalized, they may be relative IDs. 25527 */ 25528 parse.findDependencies = function (fileName, fileContents, options) { 25529 var dependencies = [], 25530 astRoot = esprima.parse(fileContents); 25531 25532 parse.recurse(astRoot, function (callName, config, name, deps) { 25533 if (deps) {
25534 dependencies = dependencies.concat(deps); 25535 } 25536 }, options); 25537 25538 return dependencies; 25539 }; 25540 25541 /** 25542 * Finds only CJS dependencies, ones that are the form 25543 * require('stringLiteral') 25544 */ 25545 parse.findCjsDependencies = function (fileName, fileContents) { 25546 var dependencies = []; 25547 25548 traverse(esprima.parse(fileContents), function (node) { 25549 var arg; 25550 25551 if (node && node.type === 'CallExpression' && node.callee && 25552 node.callee.type === 'Identifier' && 25553 node.callee.name === 'require' && node[argPropName] && 25554 node[argPropName].length === 1) { 25555 arg = node[argPropName][0]; 25556 if (arg.type === 'Literal') { 25557 dependencies.push(arg.value); 25558 } 25559 } 25560 }); 25561 25562 return dependencies; 25563 }; 25564 25565 //function define() {} 25566 parse.hasDefDefine = function (node) { 25567 return node.type === 'FunctionDeclaration' && node.id && 25568 node.id.type === 'Identifier' && node.id.name === 'define'; 25569 }; 25570 25571 //define.amd = ... 25572 parse.hasDefineAmd = function (node) { 25573 return node && node.type === 'AssignmentExpression' && 25574 node.left && node.left.type === 'MemberExpression' && 25575 node.left.object && node.left.object.name === 'define' && 25576 node.left.property && node.left.property.name === 'amd'; 25577 }; 25578 25579 //define.amd reference, as in: if (define.amd) 25580 parse.refsDefineAmd = function (node) { 25581 return node && node.type === 'MemberExpression' && 25582 node.object && node.object.name === 'define' && 25583 node.object.type === 'Identifier' && 25584 node.property && node.property.name === 'amd' && 25585 node.property.type === 'Identifier'; 25586 }; 25587 25588 //require(), requirejs(), require.config() and requirejs.config() 25589 parse.hasRequire = function (node) { 25590 var callName, 25591 c = node && node.callee; 25592 25593 if (node && node.type === 'CallExpression' && c) { 25594 if (c.type === 'Identifier' && 25595 (c.name === 'require' || 25596 c.name === 'requirejs')) { 25597 //A require/requirejs({}, ...) call 25598 callName = c.name; 25599 } else if (c.type === 'MemberExpression' && 25600 c.object && 25601 c.object.type === 'Identifier' && 25602 (c.object.name === 'require' || 25603 c.object.name === 'requirejs') && 25604 c.property && c.property.name === 'config') { 25605 // require/requirejs.config({}) call 25606 callName = c.object.name + 'Config'; 25607 } 25608 } 25609 25610 return callName; 25611 }; 25612 25613 //define() 25614 parse.hasDefine = function (node) { 25615 return node && node.type === 'CallExpression' && node.callee && 25616 node.callee.type === 'Identifier' && 25617 node.callee.name === 'define'; 25618 }; 25619 25620 /** 25621 * If there is a named define in the file, returns the name. Does not 25622 * scan for mulitple names, just the first one. 25623 */ 25624 parse.getNamedDefine = function (fileContents) { 25625 var name; 25626 traverse(esprima.parse(fileContents), function (node) { 25627 if (node && node.type === 'CallExpression' && node.callee && 25628 node.callee.type === 'Identifier' && 25629 node.callee.name === 'define' && 25630 node[argPropName] && node[argPropName][0] && 25631 node[argPropName][0].type === 'Literal') { 25632 name = node[argPropName][0].value; 25633 return false;
25634 } 25635 }); 25636 25637 return name; 25638 }; 25639 25640 /** 25641 * Finds all the named define module IDs in a file. 25642 */ 25643 parse.getAllNamedDefines = function (fileContents, excludeMap) { 25644 var names = []; 25645 parse.recurse(esprima.parse(fileContents), 25646 function (callName, config, name, deps, node, factoryIdentifier, fnExpScope) { 25647 if (callName === 'define' && name) { 25648 if (!excludeMap.hasOwnProperty(name)) { 25649 names.push(name); 25650 } 25651 } 25652 25653 //If a UMD definition that points to a factory that is an Identifier, 25654 //indicate processing should not traverse inside the UMD definition. 25655 if (callName === 'define' && factoryIdentifier && hasProp(fnExpScope, factoryIdentifier)) { 25656 return factoryIdentifier; 25657 } 25658 25659 //If define was found, no need to dive deeper, unless 25660 //the config explicitly wants to dig deeper. 25661 return true; 25662 }, {}); 25663 25664 return names; 25665 }; 25666 25667 /** 25668 * Determines if define(), require({}|[]) or requirejs was called in the 25669 * file. Also finds out if define() is declared and if define.amd is called. 25670 */ 25671 parse.usesAmdOrRequireJs = function (fileName, fileContents) { 25672 var uses; 25673 25674 traverse(esprima.parse(fileContents), function (node) { 25675 var type, callName, arg; 25676 25677 if (parse.hasDefDefine(node)) { 25678 //function define() {} 25679 type = 'declaresDefine'; 25680 } else if (parse.hasDefineAmd(node)) { 25681 type = 'defineAmd'; 25682 } else { 25683 callName = parse.hasRequire(node); 25684 if (callName) { 25685 arg = node[argPropName] && node[argPropName][0]; 25686 if (arg && (arg.type === 'ObjectExpression' || 25687 arg.type === 'ArrayExpression')) { 25688 type = callName; 25689 } 25690 } else if (parse.hasDefine(node)) { 25691 type = 'define'; 25692 } 25693 } 25694 25695 if (type) { 25696 if (!uses) { 25697 uses = {}; 25698 } 25699 uses[type] = true; 25700 } 25701 }); 25702 25703 return uses; 25704 }; 25705 25706 /** 25707 * Determines if require(''), exports.x =, module.exports =, 25708 * __dirname, __filename are used. So, not strictly traditional CommonJS, 25709 * also checks for Node variants. 25710 */ 25711 parse.usesCommonJs = function (fileName, fileContents) { 25712 var uses = null, 25713 assignsExports = false; 25714 25715 25716 traverse(esprima.parse(fileContents), function (node) { 25717 var type, 25718 exp = node.expression || node.init; 25719 25720 if (node.type === 'Identifier' && 25721 (node.name === '__dirname' || node.name === '__filename')) { 25722 type = node.name.substring(2); 25723 } else if (node.type === 'VariableDeclarator' && node.id && 25724 node.id.type === 'Identifier' && 25725 node.id.name === 'exports') { 25726 //Hmm, a variable assignment for exports, so does not use cjs 25727 //exports. 25728 type = 'varExports'; 25729 } else if (exp && exp.type === 'AssignmentExpression' && exp.left && 25730 exp.left.type === 'MemberExpression' && exp.left.object) { 25731 if (exp.left.object.name === 'module' && exp.left.property && 25732 exp.left.property.name === 'exports') { 25733 type = 'moduleExports'; 25734 } else if (exp.left.object.name === 'exports' && 25735 exp.left.property) { 25736 type = 'exports'; 25737 } else if (exp.left.object.type === 'MemberExpression' && 25738 exp.left.object.object.name === 'module' && 25739 exp.left.object.property.name === 'exports' && 25740 exp.left.object.property.type === 'Identifier') { 25741 type = 'moduleExports'; 25742 } 25743 25744 } else if (node && node.type === 'CallExpression' && node.callee && 25745 node.callee.type === 'Identifier' && 25746 node.callee.name === 'require' && node[argPropName] && 25747 node[argPropName].length === 1 && 25748 node[argPropName][0].type === 'Literal') { 25749 type = 'require'; 25750 } 25751 25752 if (type) { 25753 if (type === 'varExports') { 25754 assignsExports = true; 25755 } else if (type !== 'exports' || !assignsExports) { 25756 if (!uses) { 25757 uses = {}; 25758 } 25759 uses[type] = true; 25760 } 25761 } 25762 }); 25763 25764 return uses; 25765 }; 25766 25767 25768 parse.findRequireDepNames = function (node, deps) { 25769 traverse(node, function (node) { 25770 var arg; 25771 25772 if (node && node.type === 'CallExpression' && node.callee && 25773 node.callee.type === 'Identifier' && 25774 node.callee.name === 'require' && 25775 node[argPropName] && node[argPropName].length === 1) { 25776 25777 arg = node[argPropName][0]; 25778 if (arg.type === 'Literal') { 25779 deps.push(arg.value); 25780 } 25781 } 25782 }); 25783 }; 25784 25785 /** 25786 * Determines if a specific node is a valid require or define/require.def 25787 * call. 25788 * @param {Array} node 25789 * @param {Function} onMatch a function to call when a match is found. 25790 * It is passed the match name, and the config, name, deps possible args. 25791 * The config, name and deps args are not normalized. 25792 * @param {Object} fnExpScope an object whose keys are all function 25793 * expression identifiers that should be in scope. Useful for UMD wrapper 25794 * detection to avoid parsing more into the wrapped UMD code. 25795 * 25796 * @returns {String}
25796 a JS source string with the valid require/define call. 25797 * Otherwise null. 25798 */ 25799 parse.parseNode = function (node, onMatch, fnExpScope) { 25800 var name, deps, cjsDeps, arg, factory, exp, refsDefine, bodyNode, 25801 args = node && node[argPropName], 25802 callName = parse.hasRequire(node), 25803 isUmd = false; 25804 25805 if (callName === 'require' || callName === 'requirejs') { 25806 //A plain require/requirejs call 25807 arg = node[argPropName] && node[argPropName][0]; 25808 if (arg && arg.type !== 'ArrayExpression') { 25809 if (arg.type === 'ObjectExpression') { 25810 //A config call, try the second arg. 25811 arg = node[argPropName][1]; 25812 } 25813 } 25814 25815 deps = getValidDeps(arg); 25816 if (!deps) { 25817 return; 25818 } 25819 25820 return onMatch("require", null, null, deps, node); 25821 } else if (parse.hasDefine(node) && args && args.length) { 25822 name = args[0]; 25823 deps = args[1]; 25824 factory = args[2]; 25825 25826 if (name.type === 'ArrayExpression') { 25827 //No name, adjust args 25828 factory = deps; 25829 deps = name; 25830 name = null; 25831 } else if (isFnExpression(name)) { 25832 //Just the factory, no name or deps 25833 factory = name; 25834 name = deps = null; 25835 } else if (name.type === 'Identifier' && args.length === 1 && 25836 hasProp(fnExpScope, name.name)) { 25837 //define(e) where e is a UMD identifier for the factory 25838 //function. 25839 isUmd = true; 25840 factory = name; 25841 name = null; 25842 } else if (name.type !== 'Literal') { 25843 //An object literal, just null out 25844 name = deps = factory = null; 25845 } 25846 25847 if (name && name.type === 'Literal' && deps) { 25848 if (isFnExpression(deps)) { 25849 //deps is the factory 25850 factory = deps; 25851 deps = null; 25852 } else if (deps.type === 'ObjectExpression') { 25853 //deps is object literal, null out 25854 deps = factory = null; 25855 } else if (deps.type === 'Identifier') { 25856 if (args.length === 2) { 25857 //define('id', factory) 25858 deps = factory = null; 25859 } else if (args.length === 3 && isFnExpression(factory)) { 25860 //define('id', depsIdentifier, factory) 25861 //Since identifier, cannot know the deps, but do not 25862 //error out, assume they are taken care of outside of 25863 //static parsing. 25864 deps = null; 25865 } 25866 } 25867 } 25868 25869 if (deps && deps.type === 'ArrayExpression') { 25870 deps = getValidDeps(deps); 25871 } else if (isFnExpression(factory)) { 25872 //If no deps and a factory function, could be a commonjs sugar 25873 //wrapper, scan the function for dependencies. 25874 cjsDeps = parse.getAnonDepsFromNode(factory); 25875 if (cjsDeps.length) { 25876 deps = cjsDeps; 25877 } 25878 } else if (deps || (factory && !isUmd)) { 25879 //Does not match the shape of an AMD call. 25880 return; 25881 } 25882 25883 //Just save off the name as a string instead of an AST object. 25884 if (name && name.type === 'Literal') { 25885 name = name.value; 25886 } 25887 25888 return onMatch("define", null, name, deps, node, 25889 (factory && factory.type === 'Identifier' ? factory.name : undefined), 25890 fnExpScope); 25891 } else if (node.type === 'CallExpression' && node.callee && 25892 isFnExpression(node.callee) && 25893 node.callee.body && node.callee.body.body && 25894 node.callee.body.body.length === 1 && 25895 node.callee.body.body[0].type === 'IfStatement') { 25896 bodyNode = node.callee.body.body[0]; 25897 //Look for a define(Identifier) case, but only if inside an 25898 //if that has a define.amd test 25899 if (bodyNode.consequent && bodyNode.consequent.body) { 25900 exp = bodyNode.consequent.body[0]; 25901 if (exp.type === 'ExpressionStatement' && exp.expression && 25902 parse.hasDefine(exp.expression) && 25903 exp.expression.arguments && 25904 exp.expression.arguments.length === 1 && 25905 exp.expression.arguments[0].type === 'Identifier') { 25906 25907 //Calls define(Identifier) as first statement in body. 25908 //Confirm the if test references define.amd 25909 traverse(bodyNode.test, function (node) { 25910 if (parse.refsDefineAmd(node)) { 25911 refsDefine = true; 25912 return false;
25913 } 25914 }); 25915 25916 if (refsDefine) { 25917 return onMatch("define", null, null, null, exp.expression, 25918 exp.expression.arguments[0].name, fnExpScope); 25919 } 25920 } 25921 } 25922 } 25923 }; 25924 25925 /** 25926 * Converts an AST node into a JS source string by extracting 25927 * the node's location from the given contents string. Assumes 25928 * esprima.parse() with loc was done. 25929 * @param {String} contents 25930 * @param {Object} node 25931 * @returns {String} a JS source string. 25932 */ 25933 parse.nodeToString = function (contents, node) { 25934 var extracted, 25935 loc = node.loc, 25936 lines = contents.split('\n'), 25937 firstLine = loc.start.line > 1 ? 25938 lines.slice(0, loc.start.line - 1).join('\n') + '\n' : 25939 '', 25940 preamble = firstLine + 25941 lines[loc.start.line - 1].substring(0, loc.start.column); 25942 25943 if (loc.start.line === loc.end.line) { 25944 extracted = lines[loc.start.line - 1].substring(loc.start.column, 25945 loc.end.column); 25946 } else { 25947 extracted = lines[loc.start.line - 1].substring(loc.start.column) + 25948 '\n' + 25949 lines.slice(loc.start.line, loc.end.line - 1).join('\n') + 25950 '\n' + 25951 lines[loc.end.line - 1].substring(0, loc.end.column); 25952 } 25953 25954 return { 25955 value: extracted, 25956 range: [ 25957 preamble.length, 25958 preamble.length + extracted.length 25959 ] 25960 }; 25961 }; 25962 25963 /** 25964 * Extracts license comments from JS text. 25965 * @param {String} fileName 25966 * @param {String} contents 25967 * @returns {String} a string of license comments. 25968 */ 25969 parse.getLicenseComments = function (fileName, contents) { 25970 var commentNode, refNode, subNode, value, i, j, 25971 //xpconnect's Reflect does not support comment or range, but 25972 //prefer continued operation vs strict parity of operation, 25973 //as license comments can be expressed in other ways, like 25974 //via wrap args, or linked via sourcemaps. 25975 ast = esprima.parse(contents, { 25976 comment: true, 25977 range: true 25978 }), 25979 result = '', 25980 existsMap = {}, 25981 lineEnd = contents.indexOf('\r') === -1 ? '\n' : '\r\n'; 25982 25983 if (ast.comments) { 25984 for (i = 0; i < ast.comments.length; i++) { 25985 commentNode = ast.comments[i]; 25986 25987 if (commentNode.type === 'Line') { 25988 value = '//' + commentNode.value + lineEnd; 25989 refNode = commentNode; 25990 25991 if (i + 1 >= ast.comments.length) { 25992 value += lineEnd; 25993 } else { 25994 //Look for immediately adjacent single line comments 25995 //since it could from a multiple line comment made out 25996 //of single line comments. Like this comment. 25997 for (j = i + 1; j < ast.comments.length; j++) { 25998 subNode = ast.comments[j]; 25999 if (subNode.type === 'Line' && 26000 subNode.range[0] === refNode.range[1] + 1) { 26001 //Adjacent single line comment. Collect it. 26002 value += '//' + subNode.value + lineEnd; 26003 refNode = subNode; 26004 } else { 26005 //No more single line comment blocks. Break out 26006 //and continue outer looping. 26007 break; 26008 } 26009 } 26010 value += lineEnd; 26011 i = j - 1; 26012 } 26013 } else { 26014 value = '/*' + commentNode.value + '*/' + lineEnd + lineEnd; 26015 } 26016 26017 if (!existsMap[value] && (value.indexOf('license') !== -1 || 26018 (commentNode.type === 'Block' && 26019 value.indexOf('/*!') === 0) || 26020 value.indexOf('opyright') !== -1 || 26021 value.indexOf('(c)') !== -1)) { 26022 26023 result += value; 26024 existsMap[value] = true; 26025 } 26026 26027 } 26028 } 26029 26030 return result; 26031 }; 26032 26033 return parse; 26034 }); 26035 /*global define */ 26036 26037 define('transform', [ './esprimaAdapter', './parse', 'logger', 'lang'], 26038 function (esprima, parse, logger, lang) { 26039 'use strict'; 26040 var transform, 26041 baseIndentRegExp = /^([ \t]+)/, 26042 indentRegExp = /\{[\r\n]+([ \t]+)/, 26043 keyRegExp = /^[_A-Za-z]([A-Za-z\d_]*)$/, 26044 bulkIndentRegExps = { 26045 '\n': /\n/g, 26046 '\r\n': /\r\n/g 26047 }; 26048 26049 function applyIndent(str, indent, lineReturn) { 26050 var regExp = bulkIndentRegExps[lineReturn]; 26051 return str.replace(regExp, '$&' + indent); 26052 } 26053 26054 transform = { 26055 toTransport: function (namespace, moduleName, path, contents, onFound, options) { 26056 options = options || {}; 26057 26058 var astRoot, contentLines, modLine, 26059 foundAnon, 26060 scanCount = 0, 26061 scanReset = false, 26062 defineInfos = [], 26063 applySourceUrl = function (contents) { 26064 if (options.useSourceUrl) { 26065 contents = 'eval("' + lang.jsEscape(contents) + 26066 '\\n//# sourceURL=' + (path.indexOf('/') === 0 ? '' : '/') + 26067 path + 26068 '");\n'; 26069 } 26070 return contents; 26071 }; 26072 26073 try { 26074 astRoot = esprima.parse(contents, { 26075 loc: true 26076 }); 26077 } catch (e) { 26078 logger.trace('toTransport skipping ' + path + ': ' + 26079 e.toString()); 26080 return contents; 26081 } 26082 26083 //Find the define calls and their position in the files. 26084 parse.traverse(astRoot, function (node) { 26085 var args, firstArg, firstArgLoc, factoryNode, 26086 needsId, depAction, foundId, init, 26087 sourceUrlData, range, 26088 namespaceExists = false;
26089 26090 // If a bundle script with a define declaration, do not 26091 // parse any further at this level. Likely a built layer 26092 // by some other tool. 26093 if (node.type === 'VariableDeclarator' && 26094 node.id && node.id.name === 'define' && 26095 node.id.type === 'Identifier') { 26096 init = node.init; 26097 if (init && init.callee && 26098 init.callee.type === 'CallExpression' && 26099 init.callee.callee && 26100 init.callee.callee.type === 'Identifier' && 26101 init.callee.callee.name === 'require' && 26102 init.callee.arguments && init.callee.arguments.length === 1 && 26103 init.callee.arguments[0].type === 'Literal' && 26104 init.callee.arguments[0].value && 26105 init.callee.arguments[0].value.indexOf('amdefine') !== -1) { 26106 // the var define = require('amdefine')(module) case, 26107 // keep going in that case. 26108 } else { 26109 return false; 26110 } 26111 } 26112 26113 namespaceExists = namespace && 26114 node.type === 'CallExpression' && 26115 node.callee && node.callee.object && 26116 node.callee.object.type === 'Identifier' && 26117 node.callee.object.name === namespace && 26118 node.callee.property.type === 'Identifier' && 26119 node.callee.property.name === 'define'; 26120 26121 if (namespaceExists || parse.isDefineNodeWithArgs(node)) { 26122 //The arguments are where its at. 26123 args = node.arguments; 26124 if (!args || !args.length) { 26125 return; 26126 } 26127 26128 firstArg = args[0]; 26129 firstArgLoc = firstArg.loc; 26130 26131 if (args.length === 1) { 26132 if (firstArg.type === 'Identifier') { 26133 //The define(factory) case, but 26134 //only allow it if one Identifier arg, 26135 //to limit impact of false positives. 26136 needsId = true; 26137 depAction = 'empty'; 26138 } else if (parse.isFnExpression(firstArg)) { 26139 //define(function(){}) 26140 factoryNode = firstArg; 26141 needsId = true; 26142 depAction = 'scan'; 26143 } else if (firstArg.type === 'ObjectExpression') { 26144 //define({}); 26145 needsId = true; 26146 depAction = 'skip'; 26147 } else if (firstArg.type === 'Literal' && 26148 typeof firstArg.value === 'number') { 26149 //define('12345'); 26150 needsId = true; 26151 depAction = 'skip'; 26152 } else if (firstArg.type === 'UnaryExpression' && 26153 firstArg.operator === '-' && 26154 firstArg.argument && 26155 firstArg.argument.type === 'Literal' && 26156 typeof firstArg.argument.value === 'number') { 26157 //define('-12345'); 26158 needsId = true; 26159 depAction = 'skip'; 26160 } else if (firstArg.type === 'MemberExpression' && 26161 firstArg.object && 26162 firstArg.property && 26163 firstArg.property.type === 'Identifier') { 26164 //define(this.key); 26165 needsId = true; 26166 depAction = 'empty'; 26167 } 26168 } else if (firstArg.type === 'ArrayExpression') { 26169 //define([], ...); 26170 needsId = true; 26171 depAction = 'skip'; 26172 } else if (firstArg.type === 'Literal' && 26173 typeof firstArg.value === 'string') { 26174 //define('string', ....) 26175 //Already has an ID. 26176 needsId = false;
26177 if (args.length === 2 && 26178 parse.isFnExpression(args[1])) { 26179 //Needs dependency scanning. 26180 factoryNode = args[1]; 26181 depAction = 'scan'; 26182 } else { 26183 depAction = 'skip'; 26184 } 26185 } else { 26186 //Unknown define entity, keep looking, even 26187 //in the subtree for this node. 26188 return; 26189 } 26190 26191 range = { 26192 foundId: foundId, 26193 needsId: needsId, 26194 depAction: depAction, 26195 namespaceExists: namespaceExists, 26196 node: node, 26197 defineLoc: node.loc, 26198 firstArgLoc: firstArgLoc, 26199 factoryNode: factoryNode, 26200 sourceUrlData: sourceUrlData 26201 }; 26202 26203 //Only transform ones that do not have IDs. If it has an 26204 //ID but no dependency array, assume it is something like 26205 //a phonegap implementation, that has its own internal 26206 //define that cannot handle dependency array constructs, 26207 //and if it is a named module, then it means it has been 26208 //set for transport form. 26209 if (range.needsId) { 26210 if (foundAnon) { 26211 logger.trace(path + ' has more than one anonymous ' + 26212 'define. May be a built file from another ' + 26213 'build system like, Ender. Skipping normalization.'); 26214 defineInfos = []; 26215 return false; 26216 } else { 26217 foundAnon = range; 26218 defineInfos.push(range); 26219 } 26220 } else if (depAction === 'scan') { 26221 scanCount += 1; 26222 if (scanCount > 1) { 26223 //Just go back to an array that just has the 26224 //anon one, since this is an already optimized 26225 //file like the phonegap one. 26226 if (!scanReset) { 26227 defineInfos = foundAnon ? [foundAnon] : []; 26228 scanReset = true; 26229 } 26230 } else { 26231 defineInfos.push(range); 26232 } 26233 } 26234 } 26235 }); 26236 26237 26238 if (!defineInfos.length) { 26239 return applySourceUrl(contents); 26240 } 26241 26242 //Reverse the matches, need to start from the bottom of 26243 //the file to modify it, so that the ranges are still true 26244 //further up. 26245 defineInfos.reverse(); 26246 26247 contentLines = contents.split('\n'); 26248 26249 modLine = function (loc, contentInsertion) { 26250 var startIndex = loc.start.column, 26251 //start.line is 1-based, not 0 based. 26252 lineIndex = loc.start.line - 1, 26253 line = contentLines[lineIndex]; 26254 contentLines[lineIndex] = line.substring(0, startIndex) + 26255 contentInsertion + 26256 line.substring(startIndex, 26257 line.length); 26258 }; 26259 26260 defineInfos.forEach(function (info) { 26261 var deps, 26262 contentInsertion = '', 26263 depString = ''; 26264 26265 //Do the modifications "backwards", in other words, start with the 26266 //one that is farthest down and work up, so that the ranges in the 26267 //defineInfos still apply. So that means deps, id, then namespace. 26268 if (info.needsId && moduleName) { 26269 contentInsertion += "'" + moduleName + "',"; 26270 } 26271 26272 if (info.depAction === 'scan') { 26273 deps = parse.getAnonDepsFromNode(info.factoryNode); 26274 26275 if (deps.length) { 26276 depString = '[' + deps.map(function (dep) { 26277 return "'" + dep + "'"; 26278 }) + ']'; 26279 } else { 26280 depString = '[]'; 26281 } 26282 depString += ','; 26283 26284 if (info.factoryNode) { 26285 //Already have a named module, need to insert the 26286 //dependencies after the name. 26287 modLine(info.factoryNode.loc, depString); 26288 } else { 26289 contentInsertion += depString; 26290 } 26291 } 26292 26293 if (contentInsertion) { 26294 modLine(info.firstArgLoc, contentInsertion); 26295 } 26296 26297 //Do namespace last so that ui does not mess upthe parenRange 26298 //used above. 26299 if (namespace && !info.namespaceExists) { 26300 modLine(info.defineLoc, namespace + '.'); 26301 } 26302 26303 //Notify any listener for the found info 26304 if (onFound) { 26305 onFound(info); 26306 } 26307 }); 26308 26309 contents = contentLines.join('\n'); 26310 26311 return applySourceUrl(contents); 26312 }, 26313 26314 /** 26315 * Modify the contents of a require.config/requirejs.config call. This 26316 * call will LOSE any existing comments that are in the config string. 26317 * 26318 * @param {String} fileContents String that may contain a config call 26319 * @param {Function} onConfig Function called when the first config 26320 * call is found. It will be passed an Object which is the current 26321 * config, and the onConfig function should return an Object to use 26322 * as the config. 26323 * @return {String} the fileContents with the config changes applied. 26324 */ 26325 modifyConfig: function (fileContents, onConfig) { 26326 var details = parse.findConfig(fileContents), 26327 config = details.config; 26328 26329 if (config) { 26330 config = onConfig(config); 26331 if (config) { 26332 return transform.serializeConfig(config, 26333 fileContents, 26334 details.range[0], 26335 details.range[1], 26336 { 26337 quote: details.quote 26338 }); 26339 } 26340 } 26341 26342 return fileContents; 26343 }, 26344 26345 serializeConfig: function (config, fileContents, start, end, options) { 26346 //Calculate base level of indent
26347 var indent, match, configString, outDentRegExp, 26348 baseIndent = '', 26349 startString = fileContents.substring(0, start), 26350 existingConfigString = fileContents.substring(start, end), 26351 lineReturn = existingConfigString.indexOf('\r') === -1 ? '\n' : '\r\n', 26352 lastReturnIndex = startString.lastIndexOf('\n'); 26353 26354 //Get the basic amount of indent for the require config call. 26355 if (lastReturnIndex === -1) { 26356 lastReturnIndex = 0; 26357 } 26358 26359 match = baseIndentRegExp.exec(startString.substring(lastReturnIndex + 1, start)); 26360 if (match && match[1]) { 26361 baseIndent = match[1]; 26362 } 26363 26364 //Calculate internal indentation for config 26365 match = indentRegExp.exec(existingConfigString); 26366 if (match && match[1]) { 26367 indent = match[1]; 26368 } 26369 26370 if (!indent || indent.length < baseIndent) { 26371 indent = ' '; 26372 } else { 26373 indent = indent.substring(baseIndent.length); 26374 } 26375 26376 outDentRegExp = new RegExp('(' + lineReturn + ')' + indent, 'g'); 26377
26378 configString = transform.objectToString(config, { 26379 indent: indent, 26380 lineReturn: lineReturn, 26381 outDentRegExp: outDentRegExp, 26382 quote: options && options.quote 26383 }); 26384 26385 //Add in the base indenting level. 26386 configString = applyIndent(configString, baseIndent, lineReturn); 26387 26388 return startString + configString + fileContents.substring(end); 26389 }, 26390 26391 /** 26392 * Tries converting a JS object to a string. This will likely suck, and 26393 * is tailored to the type of config expected in a loader config call. 26394 * So, hasOwnProperty fields, strings, numbers, arrays and functions, 26395 * no weird recursively referenced stuff. 26396 * @param {Object} obj the object to convert 26397 * @param {Object} options options object with the following values: 26398 * {String} indent the indentation to use for each level 26399 * {String} lineReturn the type of line return to use 26400 * {outDentRegExp} outDentRegExp the regexp to use to outdent functions 26401 * {String} quote the quote type to use, ' or ". Optional. Default is " 26402 * @param {String} totalIndent the total indent to print for this level 26403 * @return {String} a string representation of the object. 26404 */ 26405 objectToString: function (obj, options, totalIndent) { 26406 var startBrace, endBrace, nextIndent, 26407 first = true, 26408 value = '', 26409 lineReturn = options.lineReturn, 26410 indent = options.indent, 26411 outDentRegExp = options.outDentRegExp, 26412 quote = options.quote || '"'; 26413 26414 totalIndent = totalIndent || ''; 26415 nextIndent = totalIndent + indent; 26416 26417 if (obj === null) { 26418 value = 'null'; 26419 } else if (obj === undefined) { 26420 value = 'undefined'; 26421 } else if (typeof obj === 'number' || typeof obj === 'boolean') { 26422 value = obj; 26423 } else if (typeof obj === 'string') { 26424 //Use double quotes in case the config may also work as JSON. 26425 value = quote + lang.jsEscape(obj) + quote; 26426 } else if (lang.isArray(obj)) { 26427 lang.each(obj, function (item, i) { 26428 value += (i !== 0 ? ',' + lineReturn : '' ) + 26429 nextIndent + 26430 transform.objectToString(item, 26431 options, 26432 nextIndent); 26433 }); 26434 26435 startBrace = '['; 26436 endBrace = ']'; 26437 } else if (lang.isFunction(obj) || lang.isRegExp(obj)) { 26438 //The outdent regexp just helps pretty up the conversion 26439 //just in node. Rhino strips comments and does a different 26440 //indent scheme for Function toString, so not really helpful 26441 //there. 26442 value = obj.toString().replace(outDentRegExp, '$1'); 26443 } else { 26444 //An object 26445 lang.eachProp(obj, function (v, prop) { 26446 value += (first ? '': ',' + lineReturn) + 26447 nextIndent + 26448 (keyRegExp.test(prop) ? prop : quote + lang.jsEscape(prop) + quote )+ 26449 ': ' + 26450 transform.objectToString(v, 26451 options, 26452 nextIndent); 26453 first = false;
26454 }); 26455 startBrace = '{'; 26456 endBrace = '}'; 26457 } 26458 26459 if (startBrace) { 26460 value = startBrace + 26461 lineReturn + 26462 value + 26463 lineReturn + totalIndent + 26464 endBrace; 26465 } 26466 26467 return value; 26468 } 26469 }; 26470 26471 return transform; 26472 }); 26473 /*jslint regexp: true, plusplus: true */ 26474 /*global define: false */ 26475 26476 define('pragma', ['parse', 'logger'], function (parse, logger) { 26477 'use strict'; 26478 function Temp() {} 26479 26480 function create(obj, mixin) { 26481 Temp.prototype = obj; 26482 var temp = new Temp(), prop; 26483 26484 //Avoid any extra memory hanging around 26485 Temp.prototype = null; 26486 26487 if (mixin) { 26488 for (prop in mixin) { 26489 if (mixin.hasOwnProperty(prop) && !temp.hasOwnProperty(prop)) { 26490 temp[prop] = mixin[prop]; 26491 } 26492 } 26493 } 26494 26495 return temp; // Object 26496 } 26497 26498 var pragma = { 26499 conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/, 26500 useStrictRegExp: /(^|[^{]\r?\n)['"]use strict['"];/g, 26501 hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\s*\)/g, 26502 configRegExp: /(^|[^\.])(requirejs|require)(\.config)\s*\(/g, 26503 nsWrapRegExp: /\/\*requirejs namespace: true \*\//, 26504 apiDefRegExp: /var requirejs,\s*require,\s*define;/, 26505 defineCheckRegExp: /typeof(\s+|\s*\(\s*)define(\s*\))?\s*===?\s*["']function["']\s*&&\s*define\s*\.\s*amd/g, 26506 defineStringCheckRegExp: /typeof\s+define\s*===?\s*["']function["']\s*&&\s*define\s*\[\s*["']amd["']\s*\]/g, 26507 defineTypeFirstCheckRegExp: /\s*["']function["']\s*==(=?)\s*typeof\s+define\s*&&\s*define\s*\.\s*amd/g, 26508 defineJQueryRegExp: /typeof\s+define\s*===?\s*["']function["']\s*&&\s*define\s*\.\s*amd\s*&&\s*define\s*\.\s*amd\s*\.\s*jQuery/g, 26509 defineHasRegExp: /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g, 26510 defineTernaryRegExp: /typeof\s+define\s*===?\s*['"]function["']\s*&&\s*define\s*\.\s*amd\s*\?\s*define/, 26511 defineExistsRegExp: /\s+typeof\s+define\s*!==?\s*['"]undefined["']\s*/, 26512 defineExistsAndAmdRegExp: /typeof\s+define\s*!==?\s*['"]undefined["']\s*&&\s*define\s*\.\s*amd\s*/, 26513 amdefineRegExp: /if\s*\(\s*typeof define\s*\!==\s*['"]function['"]\s*\)\s*\{\s*[^\{\}]+amdefine[^\{\}]+\}/g, 26514 26515 removeStrict: function (contents, config) { 26516 return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '$1'); 26517 }, 26518 26519 namespace: function (fileContents, ns, onLifecycleName) { 26520 if (ns) { 26521 //Namespace require/define calls 26522 fileContents = fileContents.replace(pragma.configRegExp, '$1' + ns + '.$2$3('); 26523 26524 26525 fileContents = parse.renameNamespace(fileContents, ns); 26526 26527 //Namespace define ternary use: 26528 fileContents = fileContents.replace(pragma.defineTernaryRegExp, 26529 "typeof " + ns + ".define === 'function' && " + ns + ".define.amd ? " + ns + ".define"); 26530 26531 //Namespace define jquery use: 26532 fileContents = fileContents.replace(pragma.defineJQueryRegExp, 26533 "typeof " + ns + ".define === 'function' && " + ns + ".define.amd && " + ns + ".define.amd.jQuery"); 26534 26535 //Namespace has.js define use: 26536 fileContents = fileContents.replace(pragma.defineHasRegExp, 26537 "typeof " + ns + ".define === 'function' && typeof " + ns + ".define.amd === 'object' && " + ns + ".define.amd"); 26538 26539 //Namespace async.js define use: 26540 fileContents = fileContents.replace(pragma.defineExistsAndAmdRegExp, 26541 "typeof " + ns + ".define !== 'undefined' && " + ns + ".define.amd"); 26542 26543 //Namespace define checks. 26544 //Do these ones last, since they are a subset of the more specific 26545 //checks above. 26546 fileContents = fileContents.replace(pragma.defineCheckRegExp, 26547 "typeof " + ns + ".define === 'function' && " + ns + ".define.amd"); 26548 fileContents = fileContents.replace(pragma.defineStringCheckRegExp, 26549 "typeof " + ns + ".define === 'function' && " + ns + ".define['amd']"); 26550 fileContents = fileContents.replace(pragma.defineTypeFirstCheckRegExp, 26551 "'function' === typeof " + ns + ".define && " + ns + ".define.amd"); 26552 fileContents = fileContents.replace(pragma.defineExistsRegExp, 26553 "typeof " + ns + ".define !== 'undefined'"); 26554 26555 //Check for require.js with the require/define definitions 26556 if (pragma.apiDefRegExp.test(fileContents) && 26557 fileContents.indexOf("if (!" + ns + " || !" + ns + ".requirejs)") === -1) { 26558 //Wrap the file contents in a typeof check, and a function 26559 //to contain the API globals. 26560 fileContents = "var " + ns + ";(function () { if (!" + ns + " || !" + ns + ".requirejs) {\n" + 26561 "if (!" + ns + ") { " + ns + ' = {}; } else { require = ' + ns + '; }\n' + 26562 fileContents + 26563 "\n" + 26564 ns + ".requirejs = requirejs;" + 26565 ns + ".require = require;" + 26566 ns + ".define = define;\n" + 26567 "}\n}());"; 26568 } 26569 26570 //Finally, if the file wants a special wrapper because it ties 26571 //in to the requirejs internals in a way that would not fit 26572 //the above matches, do that. Look for /*requirejs namespace: true*/ 26573 if (pragma.nsWrapRegExp.test(fileContents)) { 26574 //Remove the pragma. 26575 fileContents = fileContents.replace(pragma.nsWrapRegExp, ''); 26576 26577 //Alter the contents. 26578 fileContents = '(function () {\n' + 26579 'var require = ' + ns + '.require,' + 26580 'requirejs = ' + ns + '.requirejs,' + 26581 'define = ' + ns + '.define;\n' + 26582 fileContents + 26583 '\n}());'; 26584 } 26585 } 26586 26587 return fileContents; 26588 }, 26589 26590 /** 26591 * processes the fileContents for some //>> conditional statements 26592 */ 26593 process: function (fileName, fileContents, config, onLifecycleName, pluginCollector) { 26594 /*jslint evil: true */ 26595 var foundIndex = -1, startIndex = 0, lineEndIndex, conditionLine, 26596 matches, type, marker, condition, isTrue, endReg
26596Exp, endMatches, 26597 endMarkerIndex, shouldInclude, startLength, lifecycleHas, deps, 26598 i, dep, moduleName, collectorMod, 26599 lifecyclePragmas, pragmas = config.pragmas, hasConfig = config.has, 26600 //Legacy arg defined to help in dojo conversion script. Remove later 26601 //when dojo no longer needs conversion: 26602 kwArgs = pragmas; 26603 26604 //Mix in a specific lifecycle scoped object, to allow targeting 26605 //some pragmas/has tests to only when files are saved, or at different 26606 //lifecycle events. Do not bother with kwArgs in this section, since 26607 //the old dojo kwArgs were for all points in the build lifecycle. 26608 if (onLifecycleName) { 26609 lifecyclePragmas = config['pragmas' + onLifecycleName]; 26610 lifecycleHas = config['has' + onLifecycleName]; 26611 26612 if (lifecyclePragmas) { 26613 pragmas = create(pragmas || {}, lifecyclePragmas); 26614 } 26615 26616 if (lifecycleHas) { 26617 hasConfig = create(hasConfig || {}, lifecycleHas); 26618 } 26619 } 26620 26621 //Replace has references if desired 26622 if (hasConfig) { 26623 fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) { 26624 if (hasConfig.hasOwnProperty(test)) { 26625 return !!hasConfig[test]; 26626 } 26627 return match; 26628 }); 26629 } 26630 26631 if (!config.skipPragmas) { 26632 26633 while ((foundIndex = fileContents.indexOf("//>>", startIndex)) !== -1) { 26634 //Found a conditional. Get the conditional line. 26635 lineEndIndex = fileContents.indexOf("\n", foundIndex); 26636 if (lineEndIndex === -1) { 26637 lineEndIndex = fileContents.length - 1; 26638 } 26639 26640 //Increment startIndex past the line so the next conditional search can be done. 26641 startIndex = lineEndIndex + 1; 26642 26643 //Break apart the conditional. 26644 conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1); 26645 matches = conditionLine.match(pragma.conditionalRegExp); 26646 if (matches) { 26647 type = matches[1]; 26648 marker = matches[2]; 26649 condition = matches[3]; 26650 isTrue = false; 26651 //See if the condition is true. 26652 try { 26653 isTrue = !!eval("(" + condition + ")"); 26654 } catch (e) { 26655 throw "Error in file: " + 26656 fileName + 26657 ". Conditional comment: " + 26658 conditionLine + 26659 " failed with this error: " + e; 26660 } 26661 26662 //Find the endpoint marker. 26663 endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g"); 26664 endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length)); 26665 if (endMatches) { 26666 endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length; 26667 26668 //Find the next line return based on the match position. 26669 lineEndIndex = fileContents.indexOf("\n", endMarkerIndex); 26670 if (lineEndIndex === -1) { 26671 lineEndIndex = fileContents.length - 1; 26672 } 26673 26674 //Should we include the segment? 26675 shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue)); 26676 26677 //Remove the conditional comments, and optionally remove the content inside 26678 //the conditional comments. 26679 startLength = startIndex - foundIndex; 26680 fileContents = fileContents.substring(0, foundIndex) + 26681 (shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") + 26682 fileContents.substring(lineEndIndex + 1, fileContents.length); 26683 26684 //Move startIndex to foundIndex, since that is the new position in the file 26685 //where we need to look for more conditionals in the next while loop pass. 26686 startIndex = foundIndex; 26687 } else { 26688 throw "Error in file: " + 26689 fileName + 26690 ". Cannot find end marker for conditional comment: " + 26691 conditionLine; 26692 26693 } 26694 } 26695 } 26696 } 26697 26698 //If need to find all plugin resources to optimize, do that now, 26699 //before namespacing, since the namespacing will change the API 26700 //names. 26701 //If there is a plugin collector, scan the file for plugin resources. 26702 if (config.optimizeAllPluginResources && pluginCollector) { 26703 try { 26704 deps = parse.findDependencies(fileName, fileContents); 26705 if (deps.length) { 26706 for (i = 0; i < deps.length; i++) { 26707 dep = deps[i]; 26708 if (dep.indexOf('!') !== -1) { 26709 moduleName = dep.split('!')[0]; 26710 collectorMod = pluginCollector[moduleName]; 26711 if (!collectorMod) { 26712 collectorMod = pluginCollector[moduleName] = []; 26713 } 26714 collectorMod.push(dep); 26715 } 26716 } 26717 } 26718 } catch (eDep) { 26719 logger.error('Parse error looking for plugin resources in ' + 26720 fileName + ', skipping.'); 26721 } 26722 } 26723 26724 //Strip amdefine use for node-shared modules. 26725 if (!config.keepAmdefine) { 26726 fileContents = fileContents.replace(pragma.amdefineRegExp, ''); 26727 } 26728 26729 //Do namespacing 26730 if (onLifecycleName === 'OnSave' && config.namespace) { 26731 fileContents = pragma.namespace(fileContents, config.namespace, onLifecycleName); 26732 } 26733 26734 26735 return pragma.removeStrict(fileContents, config); 26736 } 26737 }; 26738 26739 return pragma; 26740 }); 26741 26742 if(env === 'browser') { 26743 /*jslint strict: false */ 26744 /*global define: false */ 26745 26746 define('browser/optimize', {}); 26747 26748 } 26749 26750 if(env === 'node') { 26751 /*jslint strict: false */ 26752 /*global define: false */ 26753 26754 define('node/optimize', {}); 26755 26756 } 26757 26758 if(env === 'rhino') { 26759 /*jslint sloppy: true, plusplus: true */ 26760 /*global define, java, Packages, com */ 26761 26762 define('rhino/optimize', ['logger', 'env!env/file'], function (logger, file) { 26763 26764 //Add .reduce to Rhino so UglifyJS can run in Rhino, 26765 //inspired by https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce 26766 //but rewritten for brevity, and to be good enough for use by UglifyJS. 26767 if (!Array.prototype.reduce) { 26768 Array.prototype.reduce = function (fn /*, initialValue */) { 26769 var i = 0, 26770 length = this.length, 26771 accumulator; 26772 26773 if (arguments.length >= 2) { 26774 accumulator = arguments[1]; 26775 } else { 26776 if (length) { 26777 while (!(i in this)) { 26778 i++; 26779 } 26780 accumulator = this[i++]; 26781 } 26782 } 26783 26784 for (; i < length; i++) { 26785 if (i in this) { 26786 accumulator = fn.call(undefined, accumulator, this[i], i, this); 26787 } 26788 } 26789 26790 return accumulator; 26791 }; 26792 } 26793 26794 var JSSourceFilefromCode, optimize,
26795 mapRegExp = /"file":"[^"]+"/; 26796 26797 //Bind to Closure compiler, but if it is not available, do not sweat it. 26798 try { 26799 // Try older closure compiler that worked on Java 6 26800 JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]); 26801 } catch (e) { 26802 try { 26803 // Try for newer closure compiler that needs Java 7+ 26804 JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.SourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]); 26805 } catch (e) { 26806 try { 26807 // Try Nashorn style 26808 var stringClass = Java.type("java.lang.String").class; 26809 JSSourceFilefromCode = Java.type("com.google.javascript.jscomp.SourceFile").class.getMethod("fromCode", [stringClass, stringClass]); 26810 } catch (e) {} 26811 } 26812 } 26813 26814 //Helper for closure compiler, because of weird Java-JavaScript interactions. 26815 function closurefromCode(filename, content) { 26816 return JSSourceFilefromCode.invoke(null, [filename, content]); 26817 } 26818 26819 26820 function getFileWriter(fileName, encoding) { 26821 var outFile = new java.io.File(fileName), outWriter, parentDir; 26822 26823 parentDir = outFile.getAbsoluteFile().getParentFile(); 26824 if (!parentDir.exists()) { 26825 if (!parentDir.mkdirs()) { 26826 throw "Could not create directory: " + parentDir.getAbsolutePath(); 26827 } 26828 } 26829 26830 if (encoding) { 26831 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding); 26832 } else { 26833 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile)); 26834 } 26835 26836 return new java.io.BufferedWriter(outWriter); 26837 } 26838 26839 optimize = { 26840 closure: function (fileName, fileContents, outFileName, keepLines, config) { 26841 config = config || {}; 26842 var result, mappings, optimized, compressed, baseName, writer, 26843 outBaseName, outFileNameMap, outFileNameMapContent, 26844 srcOutFileName, concatNameMap, 26845 jscomp = Packages.com.google.javascript.jscomp, 26846 flags = Packages.com.google.common.flags, 26847 //Set up source input 26848 jsSourceFile = closurefromCode(String(fileName), String(fileContents)), 26849 sourceListArray = new java.util.ArrayList(), 26850 externList = new java.util.ArrayList(), 26851 options, option, FLAG_compilation_level, compiler, externExportsPath, 26852 Compiler = Packages.com.google.javascript.jscomp.Compiler, 26853 CommandLineRunner = Packages.com.google.javascript.jscomp.CommandLineRunner; 26854 26855 logger.trace("Minifying file: " + fileName); 26856 26857 baseName = (new java.io.File(fileName)).getName(); 26858 26859 //Set up options 26860 options = new jscomp.CompilerOptions(); 26861 for (option in config.CompilerOptions) { 26862 // options are false by default and jslint wanted an if statement in this for loop 26863 if (config.CompilerOptions[option]) { 26864 options[option] = config.CompilerOptions[option]; 26865 } 26866 26867 } 26868 options.prettyPrint = keepLines || options.prettyPrint; 26869 26870 FLAG_compilation_level = jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS']; 26871 FLAG_compilation_level.setOptionsForCompilationLevel(options); 26872 26873 if (config.generateSourceMaps) { 26874 mappings = new java.util.ArrayList(); 26875 26876 mappings.add(new com.google.javascript.jscomp.SourceMap.LocationMapping(fileName, baseName + ".src.js")); 26877 options.setSourceMapLocationMappings(mappings); 26878 options.setSourceMapOutputPath(fileName + ".map"); 26879 } 26880 26881 //If we need to pass an externs file to Closure so that it does not create aliases 26882 //for certain symbols, do so here. 26883 externList.addAll(CommandLineRunner.getDefaultExterns()); 26884 if (config.externExportsPath) { 26885 externExportsPath = config.externExportsPath; 26886 externList.add(jscomp.SourceFile.fromFile(externExportsPath)); 26887 } 26888 26889 //Trigger the compiler 26890 Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']); 26891 compiler = new Compiler(); 26892 26893 //fill the sourceArrrayList; we need the ArrayList because the only overload of compile 26894 //accepting the getDefaultExterns return value (a List) also wants the sources as a List 26895 sourceListArray.add(jsSourceFile); 26896 26897 result = compiler.compile(externList, sourceListArray, options); 26898 if (result.success) { 26899 optimized = String(compiler.toSource()); 26900 26901 if (config.generateSourceMaps && result.sourceMap && outFileName) {
26902 outBaseName = (new java.io.File(outFileName)).getName(); 26903 26904 srcOutFileName = outFileName + ".src.js"; 26905 outFileNameMap = outFileName + ".map"; 26906 26907 //If previous .map file exists, move it to the ".src.js" 26908 //location. Need to update the sourceMappingURL part in the 26909 //src.js file too. 26910 if (file.exists(outFileNameMap)) { 26911 concatNameMap = outFileNameMap.replace(/\.map$/, '.src.js.map'); 26912 file.saveFile(concatNameMap, file.readFile(outFileNameMap)); 26913 file.saveFile(srcOutFileName, 26914 fileContents.replace(/\/\# sourceMappingURL=(.+).map/, 26915 '/# sourceMappingURL=$1.src.js.map')); 26916 } else { 26917 file.saveUtf8File(srcOutFileName, fileContents); 26918 } 26919 26920 writer = getFileWriter(outFileNameMap, "utf-8"); 26921 result.sourceMap.appendTo(writer, outFileName); 26922 writer.close(); 26923 26924 //Not sure how better to do this, but right now the .map file 26925 //leaks the full OS path in the "file" property. Manually 26926 //modify it to not do that. 26927 file.saveFile(outFileNameMap, 26928 file.readFile(outFileNameMap).replace(mapRegExp, '"file":"' + baseName + '"')); 26929 26930 fileContents = optimized + "\n//# sourceMappingURL=" + outBaseName + ".map"; 26931 } else { 26932 fileContents = optimized; 26933 } 26934 return fileContents; 26935 } else { 26936 throw new Error('Cannot closure compile file: ' + fileName + '. Skipping it.'); 26937 } 26938 26939 return fileContents; 26940 } 26941 }; 26942 26943 return optimize; 26944 }); 26945 } 26946 26947 if(env === 'xpconnect') { 26948 define('xpconnect/optimize', {}); 26949 } 26950 /*jslint plusplus: true, nomen: true, regexp: true */ 26951 /*global define: false */ 26952 26953 define('optimize', [ 'lang', 'logger', 'env!env/optimize', 'env!env/file', 'parse', 26954 'pragma', 'uglifyjs', 26955 'source-map'], 26956 function (lang, logger, envOptimize, file, parse, 26957 pragma, uglify, 26958 sourceMap) { 26959 'use strict'; 26960 26961 var optimize, 26962 cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/ig, 26963 cssCommentImportRegExp = /\/\*[^\*]*@import[^\*]*\*\//g, 26964 cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g, 26965 protocolRegExp = /^\w+:/, 26966 SourceMapGenerator = sourceMap.SourceMapGenerator, 26967 SourceMapConsumer = sourceMap.SourceMapConsumer, 26968 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.';
26969 26970 /** 26971 * If an URL from a CSS url value contains start/end quotes, remove them. 26972 * This is not done in the regexp, since my regexp fu is not that strong, 26973 * and the CSS spec allows for ' and " in the URL if they are backslash escaped. 26974 * @param {String} url 26975 */ 26976 function cleanCssUrlQuotes(url) { 26977 //Make sure we are not ending in whitespace. 26978 //Not very confident of the css regexps above that there will not be ending 26979 //whitespace. 26980 url = url.replace(/\s+$/, ""); 26981 26982 if (url.charAt(0) === "'" || url.charAt(0) === "\"") { 26983 url = url.substring(1, url.length - 1); 26984 } 26985 26986 return url; 26987 } 26988 26989 function fixCssUrlPaths(fileName, path, contents, cssPrefix) { 26990 return contents.replace(cssUrlRegExp, function (fullMatch, urlMatch) { 26991 var firstChar, hasProtocol, parts, i, 26992 fixedUrlMatch = cleanCssUrlQuotes(urlMatch); 26993 26994 fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/"); 26995 26996 //Only do the work for relative URLs. Skip things that start with / or #, or have 26997 //a protocol. 26998 firstChar = fixedUrlMatch.charAt(0); 26999 hasProtocol = protocolRegExp.test(fixedUrlMatch); 27000 if (firstChar !== "/" && firstChar !== "#" && !hasProtocol) { 27001 //It is a relative URL, tack on the cssPrefix and path prefix 27002 urlMatch = cssPrefix + path + fixedUrlMatch; 27003 } else if (!hasProtocol) { 27004 logger.trace(fileName + "\n URL not a relative URL, skipping: " + urlMatch); 27005 } 27006 27007 //Collapse .. and . 27008 parts = urlMatch.split("/"); 27009 for (i = parts.length - 1; i > 0; i--) { 27010 if (parts[i] === ".") { 27011 parts.splice(i, 1); 27012 } else if (parts[i] === "..") { 27013 if (i !== 0 && parts[i - 1] !== "..") { 27014 parts.splice(i - 1, 2); 27015 i -= 1; 27016 } 27017 } 27018 } 27019 27020 return "url(" + parts.join("/") + ")"; 27021 }); 27022 } 27023 27024 /** 27025 * Inlines nested stylesheets that have @import calls in them. 27026 * @param {String} fileName the file name 27027 * @param {String} fileContents the file contents 27028 * @param {String} cssImportIgnore comma delimited string of files to ignore 27029 * @param {String} cssPrefix string to be prefixed before relative URLs 27030 * @param {Object} included an object used to track the files already imported 27031 */ 27032 function flattenCss(fileName, fileContents, cssImportIgnore, cssPrefix, included, topLevel) { 27033 //Find the last slash in the name. 27034 fileName = fileName.replace(lang.backSlashRegExp, "/"); 27035 var endIndex = fileName.lastIndexOf("/"), 27036 //Make a file path based on the last slash. 27037 //If no slash, so must be just a file name. Use empty string then. 27038 filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "", 27039 //store a list of merged files 27040 importList = [], 27041 skippedList = []; 27042 27043 //First make a pass by removing any commented out @import calls. 27044 fileContents = fileContents.replace(cssCommentImportRegExp, ''); 27045 27046 //Make sure we have a delimited ignore list to make matching faster 27047 if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") { 27048 cssImportIgnore += ","; 27049 } 27050 27051 fileContents = fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) { 27052 //Only process media type "all" or empty media type rules. 27053 if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) { 27054 skippedList.push(fileName); 27055 return fullMatch; 27056 } 27057 27058 importFileName = cleanCssUrlQuotes(importFileName); 27059 27060 //Ignore the file import if it is part of an ignore list.
27061 if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) { 27062 return fullMatch; 27063 } 27064 27065 //Make sure we have a unix path for the rest of the operation. 27066 importFileName = importFileName.replace(lang.backSlashRegExp, "/"); 27067 27068 try { 27069 //if a relative path, then tack on the filePath. 27070 //If it is not a relative path, then the readFile below will fail, 27071 //and we will just skip that import. 27072 var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName, 27073 importContents = file.readFile(fullImportFileName), 27074 importEndIndex, importPath, flat; 27075 27076 //Skip the file if it has already been included. 27077 if (included[fullImportFileName]) { 27078 return ''; 27079 } 27080 included[fullImportFileName] = true; 27081 27082 //Make sure to flatten any nested imports. 27083 flat = flattenCss(fullImportFileName, importContents, cssImportIgnore, cssPrefix, included); 27084 importContents = flat.fileContents; 27085 27086 if (flat.importList.length) { 27087 importList.push.apply(importList, flat.importList); 27088 } 27089 if (flat.skippedList.length) { 27090 skippedList.push.apply(skippedList, flat.skippedList); 27091 } 27092 27093 //Make the full import path 27094 importEndIndex = importFileName.lastIndexOf("/"); 27095 27096 //Make a file path based on the last slash. 27097 //If no slash, so must be just a file name. Use empty string then. 27098 importPath = (importEndIndex !== -1) ? importFileName.substring(0, importEndIndex + 1) : ""; 27099 27100 //fix url() on relative import (#5) 27101 importPath = importPath.replace(/^\.\//, ''); 27102 27103 //Modify URL paths to match the path represented by this file. 27104 importContents = fixCssUrlPaths(importFileName, importPath, importContents, cssPrefix); 27105 27106 importList.push(fullImportFileName); 27107 return importContents; 27108 } catch (e) { 27109 logger.warn(fileName + "\n Cannot inline css import, skipping: " + importFileName); 27110 return fullMatch; 27111 } 27112 }); 27113 27114 if (cssPrefix && topLevel) { 27115 //Modify URL paths to match the path represented by this file. 27116 fileContents = fixCssUrlPaths(fileName, '', fileContents, cssPrefix); 27117 } 27118 27119 return { 27120 importList : importList, 27121 skippedList: skippedList, 27122 fileContents : fileContents 27123 }; 27124 } 27125 27126 optimize = { 27127 /** 27128 * Optimizes a file that contains JavaScript content. Optionally collects 27129 * plugin resources mentioned in a file, and then passes the content 27130 * through an minifier if one is specified via config.optimize. 27131 * 27132 * @param {String} fileName the name of the file to optimize 27133 * @param {String} fileContents the contents to optimize. If this is 27134 * a null value, then fileName will be used to read the fileContents. 27135 * @param {String} outFileName the name of the file to use for the 27136 * saved optimized content. 27137 * @param {Object} config the build config object. 27138 * @param {Array} [pluginCollector] storage for any plugin resources 27139 * found. 27140 */ 27141 jsFile: function (fileName, fileContents, outFileName, config, pluginCollector) { 27142 if (!fileContents) { 27143 fileContents = file.readFile(fileName); 27144 } 27145 27146 fileContents = optimize.js(fileName, fileContents, outFileName, config, pluginCollector); 27147 27148 file.saveUtf8File(outFileName, fileContents); 27149 }, 27150 27151 /** 27152 * Optimizes a file that contains JavaScript content. Optionally collects 27153 * plugin resources mentioned in a file, and then passes the content 27154 * through an minifier if one is specified via config.optimize. 27155 * 27156 * @param {String} fileName the name of the file that matches the 27157 * fileContents. 27158 * @param {String} fileContents the string of JS to optimize. 27159 * @param {Object} [config] the build config object. 27160 * @param {Array} [pluginCollector] storage for any plugin resources 27161 * found. 27162 */ 27163 js: function (fileName, fileContents, outFileName, config, pluginCollector) { 27164 var optFunc, optConfig, 27165 parts = (String(config.optimize)).split('.'), 27166 optimizerName = parts[0], 27167 keepLines = parts[1] === 'keepLines', 27168 licenseContents = ''; 27169 27170 config = config || {}; 27171 27172 //Apply pragmas/namespace renaming 27173 fileContents = pragma.process(fileName, fileContents, config, 'OnSave', pluginCollector); 27174 27175 //Optimize the JS files if asked. 27176 if (optimizerName && optimizerName !== 'none') { 27177 optFunc = envOptimize[optimizerName] || optimize.optimizers[optimizerName]; 27178 if (!optFunc) { 27179 throw new Error('optimizer with name of "' + 27180 optimizerName + 27181 '" not found for this environment'); 27182 } 27183 27184 optConfig = config[optimizerName] || {}; 27185 if (config.generateSourceMaps) { 27186 optConfig.generateSourceMaps = !!config.generateSourceMaps; 27187 optConfig._buildSourceMap = config._buildSourceMap; 27188 } 27189 27190 try { 27191 if (config.preserveLicenseComments) { 27192 //Pull out any license comments for prepending after optimization. 27193 try { 27194 licenseContents = parse.getLicenseComments(fileName, fileContents); 27195 } catch (e) { 27196 throw new Error('Cannot parse file: ' + fileName + ' for comments. Skipping it. Error is:\n' + e.toString()); 27197 } 27198 } 27199 27200 if (config.generateSourceMaps && licenseContents) { 27201 optConfig.preamble = licenseContents; 27202 licenseContents = ''; 27203 } 27204 27205 fileContents = licenseContents + optFunc(fileName, 27206 fileContents, 27207 outFileName, 27208 keepLines, 27209 optConfig); 27210 if (optConfig._buildSourceMap && optConfig._buildSourceMap !== config._buildSourceMap) { 27211 config._buildSourceMap = optConfig._buildSourceMap; 27212 } 27213 } catch (e) { 27214 if (config.throwWhen && config.throwWhen.optimize) { 27215 throw e; 27216 } else { 27217 logger.error(e); 27218 } 27219 } 27220 } else { 27221 if (config._buildSourceMap) { 27222 config._buildSourceMap = null; 27223 } 27224 } 27225 27226 return fileContents; 27227 }, 27228 27229 /** 27230 * Optimizes one CSS file, inlining @import calls, str
27230ipping comments, and 27231 * optionally removes line returns. 27232 * @param {String} fileName the path to the CSS file to optimize 27233 * @param {String} outFileName the path to save the optimized file. 27234 * @param {Object} config the config object with the optimizeCss and 27235 * cssImportIgnore options. 27236 */ 27237 cssFile: function (fileName, outFileName, config) { 27238 27239 //Read in the file. Make sure we have a JS string. 27240 var originalFileContents = file.readFile(fileName), 27241 flat = flattenCss(fileName, originalFileContents, config.cssImportIgnore, config.cssPrefix, {}, true), 27242 //Do not use the flattened CSS if there was one that was skipped. 27243 fileContents = flat.skippedList.length ? originalFileContents : flat.fileContents, 27244 startIndex, endIndex, buildText, comment; 27245 27246 if (flat.skippedList.length) { 27247 logger.warn('Cannot inline @imports for ' + fileName + 27248 ',\nthe following files had media queries in them:\n' + 27249 flat.skippedList.join('\n')); 27250 } 27251 27252 //Do comment removal. 27253 try { 27254 if (config.optimizeCss.indexOf(".keepComments") === -1) { 27255 startIndex = 0; 27256 //Get rid of comments. 27257 while ((startIndex = fileContents.indexOf("/*", startIndex)) !== -1) { 27258 endIndex = fileContents.indexOf("*/", startIndex + 2); 27259 if (endIndex === -1) { 27260 throw "Improper comment in CSS file: " + fileName; 27261 } 27262 comment = fileContents.substring(startIndex, endIndex); 27263 27264 if (config.preserveLicenseComments && 27265 (comment.indexOf('license') !== -1 || 27266 comment.indexOf('opyright') !== -1 || 27267 comment.indexOf('(c)') !== -1)) { 27268 //Keep the comment, just increment the startIndex 27269 startIndex = endIndex; 27270 } else { 27271 fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length); 27272 startIndex = 0; 27273 } 27274 } 27275 } 27276 //Get rid of newlines. 27277 if (config.optimizeCss.indexOf(".keepLines") === -1) { 27278 fileContents = fileContents.replace(/[\r\n]/g, " "); 27279 fileContents = fileContents.replace(/\s+/g, " "); 27280 fileContents = fileContents.replace(/\{\s/g, "{"); 27281 fileContents = fileContents.replace(/\s\}/g, "}"); 27282 } else { 27283 //Remove multiple empty lines. 27284 fileContents = fileContents.replace(/(\r\n)+/g, "\r\n"); 27285 fileContents = fileContents.replace(/(\n)+/g, "\n"); 27286 } 27287 //Remove unnecessary whitespace 27288 if (config.optimizeCss.indexOf(".keepWhitespace") === -1) { 27289 //Remove leading and trailing whitespace from lines 27290 fileContents = fileContents.replace(/^[ \t]+/gm, ""); 27291 fileContents = fileContents.replace(/[ \t]+$/gm, ""); 27292 //Remove whitespace after semicolon, colon, curly brackets and commas 27293 fileContents = fileContents.replace(/(;|:|\{|}|,)[ \t]+/g, "$1"); 27294 //Remove whitespace before opening curly brackets 27295 fileContents = fileContents.replace(/[ \t]+(\{)/g, "$1"); 27296 //Truncate double whitespace 27297 fileContents = fileContents.replace(/([ \t])+/g, "$1"); 27298 //Remove empty lines 27299 fileContents = fileContents.replace(/^[ \t]*[\r\n]/gm,''); 27300 } 27301 } catch (e) { 27302 fileContents = originalFileContents; 27303 logger.error("Could not optimized CSS file: " + fileName + ", error: " + e); 27304 } 27305 27306 file.saveUtf8File(outFileName, fileContents); 27307 27308 //text output to stdout and/or written to build.txt file 27309 buildText = "\n"+ outFileName.replace(config.dir, "") +"\n----------------\n"; 27310 flat.importList.push(fileName); 27311 buildText += flat.importList.map(function(path){ 27312 return path.replace(config.dir, ""); 27313 }).join("\n"); 27314 27315 return { 27316 importList: flat.importList, 27317 buildText: buildText +"\n" 27318 }; 27319 }, 27320 27321 /** 27322 * Optimizes CSS files, inlining @import calls, str
27322ipping comments, and 27323 * optionally removes line returns. 27324 * @param {String} startDir the path to the top level directory 27325 * @param {Object} config the config object with the optimizeCss and 27326 * cssImportIgnore options. 27327 */ 27328 css: function (startDir, config) { 27329 var buildText = "", 27330 importList = [], 27331 shouldRemove = config.dir && config.removeCombined, 27332 i, fileName, result, fileList; 27333 if (config.optimizeCss.indexOf("standard") !== -1) { 27334 fileList = file.getFilteredFileList(startDir, /\.css$/, true); 27335 if (fileList) { 27336 for (i = 0; i < fileList.length; i++) { 27337 fileName = fileList[i]; 27338 logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName); 27339 result = optimize.cssFile(fileName, fileName, config); 27340 buildText += result.buildText; 27341 if (shouldRemove) { 27342 result.importList.pop(); 27343 importList = importList.concat(result.importList); 27344 } 27345 } 27346 } 27347 27348 if (shouldRemove) { 27349 importList.forEach(function (path) { 27350 if (file.exists(path)) { 27351 file.deleteFile(path); 27352 } 27353 }); 27354 } 27355 } 27356 return buildText; 27357 }, 27358 27359 optimizers: { 27360 uglify: function (fileName, fileContents, outFileName, keepLines, config) { 27361 var result, existingMap, resultMap, finalMap, sourceIndex, 27362 uconfig = {}, 27363 existingMapPath = outFileName + '.map', 27364 baseName = fileName && fileName.split('/').pop(); 27365 27366 config = config || {}; 27367 27368 lang.mixin(uconfig, config, true); 27369 27370 uconfig.fromString = true; 27371 27372 if (config.preamble) { 27373 uconfig.output = {preamble: config.preamble}; 27374 } 27375 27376 27377 if (config.generateSourceMaps && (outFileName || config._buildSourceMap)) { 27378 uconfig.outSourceMap = baseName + '.map'; 27379 27380 if (config._buildSourceMap) { 27381 existingMap = JSON.parse(config._buildSourceMap); 27382 uconfig.inSourceMap = existingMap; 27383 } else if (file.exists(existingMapPath)) { 27384 uconfig.inSourceMap = existingMapPath; 27385 existingMap = JSON.parse(file.readFile(existingMapPath)); 27386 } 27387 } 27388 27389 logger.trace("Uglify file: " + fileName); 27390 27391 try { 27392 //var tempContents = fileContents.replace(/\/\/\# sourceMappingURL=.*$/, ''); 27393 result = uglify.minify(fileContents, uconfig, baseName + '.src.js'); 27394 if (uconfig.outSourceMap && result.map) { 27395 resultMap = result.map; 27396 if (!existingMap && !config._buildSourceMap) { 27397 file.saveFile(outFileName + '.src.js', fileContents); 27398 } 27399 27400 fileContents = result.code; 27401 27402 if (config._buildSourceMap) { 27403 config._buildSourceMap = resultMap; 27404 } else { 27405 file.saveFile(outFileName + '.map', resultMap); 27406 } 27407 } else { 27408 fileContents = result.code; 27409 } 27410 } catch (e) { 27411 var errorString = e.toString(); 27412 var isSyntaxError = /SyntaxError/.test(errorString); 27413 throw new Error('Cannot uglify file: ' + fileName + 27414 '. Skipping it. Error is:\n' + errorString + 27415 (isSyntaxError ? '\n\n' + es5PlusGuidance : '')); 27416 } 27417 return fileContents; 27418 } 27419 } 27420 }; 27421 27422 return optimize; 27423 }); 27424 /* 27425 * This file patches require.js to communicate with the build system. 27426 */ 27427 27428//Using sloppy since this uses eval for some code like plugins, 27429//which may not be strict mode compliant. So if use strict is used 27430//below they will have strict rules applied and may cause an error. 27431 /*jslint sloppy: true, nomen: true, plusplus: true, regexp: true */ 27432 /*global require, define: true */ 27433 27434//NOT asking for require as a dependency since the goal is to modify the 27435//global require below 27436 define('requirePatch', [ 'env!env/file', 'pragma', 'parse', 'lang', 'logger', 'commonJs', 'prim'], function ( 27437 file, 27438 pragma, 27439 parse, 27440 lang, 27441 logger, 27442 commonJs, 27443 prim 27444 ) { 27445 27446 var allowRun = true, 27447 hasProp = lang.hasProp, 27448 falseProp = lang.falseProp, 27449 getOwn = lang.getOwn, 27450 // Used to strip out use strict from toString()'d functions for the 27451 // shim config since they will explicitly want to not be bound by strict, 27452 // but some envs, explicitly xpcshell, adds a use strict. 27453 useStrictRegExp = /['"]use strict['"];/g, 27454 //Absolute path if starts with /, \, or x: 27455 absoluteUrlRegExp = /^[\/\\]|^\w:/; 27456 27457 //Turn off throwing on resolution conflict, that was just an older prim 27458 //idea about finding errors early, but does not comply with how promises 27459 //should operate. 27460 prim.hideResolutionConflict = true; 27461 27462 //This method should be called when the patches to require should take hold. 27463 return function () { 27464 if (!allowRun) { 27465 return; 27466 } 27467 allowRun = false;
27468 27469 var layer, 27470 pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/, 27471 oldNewContext = require.s.newContext, 27472 oldDef, 27473 27474 //create local undefined values for module and exports, 27475 //so that when files are evaled in this function they do not 27476 //see the node values used for r.js 27477 exports, 27478 module; 27479 27480 /** 27481 * Reset "global" build caches that are kept around between 27482 * build layer builds. Useful to do when there are multiple 27483 * top level requirejs.optimize() calls. 27484 */ 27485 require._cacheReset = function () { 27486 //Stored raw text caches, used by browser use. 27487 require._cachedRawText = {}; 27488 //Stored cached file contents for reuse in other layers. 27489 require._cachedFileContents = {}; 27490 //Store which cached files contain a require definition. 27491 require._cachedDefinesRequireUrls = {}; 27492 }; 27493 require._cacheReset(); 27494 27495 /** 27496 * Makes sure the URL is something that can be supported by the 27497 * optimization tool. 27498 * @param {String} url 27499 * @returns {Boolean} 27500 */ 27501 require._isSupportedBuildUrl = function (url) { 27502 //Ignore URLs with protocols, hosts or question marks, means either network 27503 //access is needed to fetch it or it is too dynamic. Note that 27504 //on Windows, full paths are used for some urls, which include 27505 //the drive, like c:/something, so need to test for something other 27506 //than just a colon. 27507 if (url.indexOf("://") === -1 && url.indexOf("?") === -1 && 27508 url.indexOf('empty:') !== 0 && url.indexOf('//') !== 0) { 27509 return true; 27510 } else { 27511 if (!layer.ignoredUrls[url]) { 27512 if (url.indexOf('empty:') === -1) { 27513 logger.info('Cannot optimize network URL, skipping: ' + url); 27514 } 27515 layer.ignoredUrls[url] = true; 27516 } 27517 return false; 27518 } 27519 }; 27520 27521 function normalizeUrlWithBase(context, moduleName, url) { 27522 //Adjust the URL if it was not transformed to use baseUrl, but only 27523 //if the URL is not already an absolute path. 27524 if (require.jsExtRegExp.test(moduleName) && 27525 !absoluteUrlRegExp.test(url)) { 27526 url = (context.config.dir || context.config.dirBaseUrl) + url; 27527 } 27528 return url; 27529 } 27530 27531 //Overrides the new context call to add existing tracking features. 27532 require.s.newContext = function (name) { 27533 var context = oldNewContext(name), 27534 oldEnable = context.enable, 27535 moduleProto = context.Module.prototype, 27536 oldInit = moduleProto.init, 27537 oldCallPlugin = moduleProto.callPlugin; 27538 27539 //Only do this for the context used for building. 27540 if (name === '_') { 27541 //For build contexts, do everything sync 27542 context.nextTick = function (fn) { 27543 fn(); 27544 }; 27545 27546 context.needFullExec = {}; 27547 context.fullExec = {}; 27548 context.plugins = {}; 27549 context.buildShimExports = {}; 27550 27551 //Override the shim exports function generator to just 27552 //spit out strings that can be used in the stringified 27553 //build output. 27554 context.makeShimExports = function (value) { 27555 var fn; 27556 if (context.config.wrapShim) { 27557 fn = function () { 27558 var str = 'return '; 27559 // If specifies an export that is just a global 27560 // name, no dot for a `this.` and such, then also 27561 // attach to the global, for `var a = {}` files 27562 // where the function closure would hide that from 27563 // the global object. 27564 if (value.exports && value.exports.indexOf('.') === -1) { 27565 str += 'root.' + value.exports + ' = '; 27566 } 27567 27568 if (value.init) { 27569 str += '(' + value.init.toString() 27570 .replace(useStrictRegExp, '') + '.apply(this, arguments))'; 27571 } 27572 if (value.init && value.exports) { 27573 str += ' || '; 27574 } 27575 if (value.exports) { 27576 str += value.exports; 27577 } 27578 str += ';'; 27579 return str; 27580 }; 27581 } else { 27582 fn = function () { 27583 return '(function (global) {\n' + 27584 ' return function () {\n' + 27585 ' var ret, fn;\n' + 27586 (value.init ? 27587 (' fn = ' + value.init.toString() 27588 .replace(useStrictRegExp, '') + ';\n' + 27589 ' ret = fn.apply(global, arguments);\n') : '') + 27590 (value.exports ?
27591 ' return ret || global.' + value.exports + ';\n' : 27592 ' return ret;\n') + 27593 ' };\n' + 27594 '}(this))'; 27595 }; 27596 } 27597 27598 return fn; 27599 }; 27600 27601 context.enable = function (depMap, parent) { 27602 var id = depMap.id, 27603 parentId = parent && parent.map.id, 27604 needFullExec = context.needFullExec, 27605 fullExec = context.fullExec, 27606 mod = getOwn(context.registry, id); 27607 27608 if (mod && !mod.defined) { 27609 if (parentId && getOwn(needFullExec, parentId)) { 27610 needFullExec[id] = depMap; 27611 } 27612 27613 } else if ((getOwn(needFullExec, id) && falseProp(fullExec, id)) || 27614 (parentId && getOwn(needFullExec, parentId) && 27615 falseProp(fullExec, id))) { 27616 context.require.undef(id); 27617 } 27618 27619 return oldEnable.apply(context, arguments); 27620 }; 27621 27622 //Override load so that the file paths can be collected. 27623 context.load = function (moduleName, url) { 27624 /*jslint evil: true */ 27625 var contents, pluginBuilderMatch, builderName, 27626 shim, shimExports; 27627 27628 //Do not mark the url as fetched if it is 27629 //not an empty: URL, used by the optimizer. 27630 //In that case we need to be sure to call 27631 //load() for each module that is mapped to 27632 //empty: so that dependencies are satisfied 27633 //correctly. 27634 if (url.indexOf('empty:') === 0) { 27635 delete context.urlFetched[url]; 27636 } 27637 27638 //Only handle urls that can be inlined, so that means avoiding some 27639 //URLs like ones that require network access or may be too dynamic, 27640 //like JSONP 27641 if (require._isSupportedBuildUrl(url)) { 27642 //Adjust the URL if it was not transformed to use baseUrl. 27643 url = normalizeUrlWithBase(context, moduleName, url); 27644 27645 //Save the module name to path and path to module name mappings. 27646 layer.buildPathMap[moduleName] = url; 27647 layer.buildFileToModule[url] = moduleName; 27648 27649 if (hasProp(context.plugins, moduleName)) { 27650 //plugins need to have their source evaled as-is. 27651 context.needFullExec[moduleName] = true; 27652 } 27653 27654 prim().start(function () { 27655 if (hasProp(require._cachedFileContents, url) && 27656 (falseProp(context.needFullExec, moduleName) || 27657 getOwn(context.fullExec, moduleName))) { 27658 contents = require._cachedFileContents[url]; 27659 27660 //If it defines require, mark it so it can be hoisted. 27661 //Done here and in the else below, before the 27662 //else block removes code from the contents. 27663 //Related to #263 27664 if (!layer.existingRequireUrl && require._cachedDefines
27664RequireUrls[url]) { 27665 layer.existingRequireUrl = url; 27666 } 27667 } else { 27668 //Load the file contents, process for conditionals, then 27669 //evaluate it. 27670 return require._cacheReadAsync(url).then(function (text) { 27671 contents = text; 27672 27673 if (context.config.cjsTranslate && 27674 (!context.config.shim || !lang.hasProp(context.config.shim, moduleName))) { 27675 contents = commonJs.convert(url, contents); 27676 } 27677 27678 //If there is a read filter, run it now. 27679 if (context.config.onBuildRead) { 27680 contents = context.config.onBuildRead(moduleName, url, contents); 27681 } 27682 27683 contents = pragma.process(url, contents, context.config, 'OnExecute'); 27684 27685 //Find out if the file contains a require() definition. Need to know 27686 //this so we can inject plugins right after it, but before they are needed, 27687 //and to make sure this file is first, so that define calls work. 27688 try { 27689 if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) { 27690 layer.existingRequireUrl = url; 27691 require._cachedDefinesRequireUrls[url] = true; 27692 } 27693 } catch (e1) { 27694 throw new Error('Parse error using esprima ' + 27695 'for file: ' + url + '\n' + e1); 27696 } 27697 }).then(function () { 27698 if (hasProp(context.plugins, moduleName)) { 27699 //This is a loader plugin, check to see if it has a build extension, 27700 //otherwise the plugin will act as the plugin builder too. 27701 pluginBuilderMatch = pluginBuilderRegExp.exec(contents); 27702 if (pluginBuilderMatch) { 27703 //Load the plugin builder for the plugin contents. 27704 builderName = context.makeModuleMap(pluginBuilderMatch[3], 27705 context.makeModuleMap(moduleName), 27706 null, 27707 true).id; 27708 return require._cacheReadAsync(context.nameToUrl(builderName)); 27709 } 27710 } 27711 return contents; 27712 }).then(function (text) { 27713 contents = text; 27714 27715 //Parse out the require and define calls. 27716 //Do this even for plugins in case they have their own 27717 //dependencies that may be separate to how the pluginBuilder works. 27718 try { 27719 if (falseProp(context.needFullExec, moduleName)) { 27720 contents = parse(moduleName, url, contents, { 27721 insertNeedsDefine: true, 27722 has: context.config.has, 27723 findNestedDependencies: context.config.findNestedDependencies 27724 }); 27725 } 27726 } catch (e2) { 27727 throw new Error('Parse error using esprima ' + 27728 'for file: ' + url + '\n' + e2); 27729 } 27730 27731 require._cachedFileContents[url] = contents; 27732 }); 27733 } 27734 }).then(function () { 27735 if (contents) { 27736 eval(contents); 27737 } 27738 27739 try { 27740 //If have a string shim config, and this is 27741 //a fully executed module, try to see if 27742 //it created a variable in this eval scope 27743 if (getOwn(context.needFullExec, moduleName)) { 27744 shim = getOwn(context.config.shim, moduleName); 27745 if (shim && shim.exports) { 27746 shimExports = eval(shim.exports); 27747 if (typeof shimExports !== 'undefined') { 27748 context.buildShimExports[moduleName] = shimExports; 27749 } 27750 } 27751 } 27752 27753 //Need to close out completion of this module 27754 //so that listeners will get notified that it is available. 27755 context.completeLoad(moduleName); 27756 } catch (e) { 27757 //Track which module could not complete loading. 27758 if (!e.moduleTree) { 27759 e.moduleTree = []; 27760 } 27761 e.moduleTree.push(moduleName); 27762 throw e; 27763 } 27764 }).then(null, function (eOuter) { 27765 27766 if (!eOuter.fileName) {
27767 eOuter.fileName = url; 27768 } 27769 throw eOuter; 27770 }).end(); 27771 } else { 27772 //With unsupported URLs still need to call completeLoad to 27773 //finish loading. 27774 context.completeLoad(moduleName); 27775 } 27776 }; 27777 27778 //Marks module has having a name, and optionally executes the 27779 //callback, but only if it meets certain criteria. 27780 context.execCb = function (name, cb, args, exports) { 27781 var buildShimExports = getOwn(layer.context.buildShimExports, name); 27782 27783 if (buildShimExports) { 27784 return buildShimExports; 27785 } else if (cb.__requireJsBuild || getOwn(layer.context.needFullExec, name)) { 27786 return cb.apply(exports, args); 27787 } 27788 return undefined; 27789 }; 27790 27791 moduleProto.init = function (depMaps) { 27792 if (context.needFullExec[this.map.id]) { 27793 lang.each(depMaps, lang.bind(this, function (depMap) { 27794 if (typeof depMap === 'string') { 27795 depMap = context.makeModuleMap(depMap, 27796 (this.map.isDefine ? this.map : this.map.parentMap), 27797 false, true); 27798 } 27799 27800 if (!context.fullExec[depMap.id]) { 27801 context.require.undef(depMap.id); 27802 } 27803 })); 27804 } 27805 27806 return oldInit.apply(this, arguments); 27807 }; 27808 27809 moduleProto.callPlugin = function () { 27810 var map = this.map, 27811 pluginMap = context.makeModuleMap(map.prefix), 27812 pluginId = pluginMap.id, 27813 pluginMod = getOwn(context.registry, pluginId); 27814 27815 context.plugins[pluginId] = true; 27816 context.needFullExec[pluginId] = map; 27817 27818 //If the module is not waiting to finish being defined, 27819 //undef it and start over, to get full execution. 27820 if (falseProp(context.fullExec, pluginId) && (!pluginMod || pluginMod.defined)) { 27821 context.require.undef(pluginMap.id); 27822 } 27823 27824 return oldCallPlugin.apply(this, arguments); 27825 }; 27826 } 27827 27828 return context; 27829 }; 27830 27831 //Clear up the existing context so that the newContext modifications 27832 //above will be active. 27833 delete require.s.contexts._; 27834 27835 /** Reset state for each build layer pass. */ 27836 require._buildReset = function () { 27837 var oldContext = require.s.contexts._; 27838 27839 //Clear up the existing context. 27840 delete require.s.contexts._; 27841 27842 //Set up new context, so the layer object can hold onto it. 27843 require({}); 27844 27845 layer = require._layer = { 27846 buildPathMap: {}, 27847 buildFileToModule: {}, 27848 buildFilePaths: [], 27849 pathAdded: {}, 27850 modulesWithNames: {}, 27851 needsDefine: {}, 27852 existingRequireUrl: "", 27853 ignoredUrls: {}, 27854 context: require.s.contexts._ 27855 }; 27856 27857 //Return the previous context in case it is needed, like for 27858 //the basic config object. 27859 return oldContext; 27860 }; 27861 27862 require._buildReset(); 27863 27864 //Override define() to catch modules that just define an object, so that 27865 //a dummy define call is not put in the build file for them. They do 27866 //not end up getting defined via context.execCb, so we need to catch them 27867 //at the define call. 27868 oldDef = define; 27869 27870 //This function signature does not have to be exact, just match what we 27871 //are looking for. 27872 define = function (name) { 27873 if (typeof name === "string" && falseProp(layer.needsDefine, name)) { 27874 layer.modulesWithNames[name] = true; 27875 } 27876 return oldDef.apply(require, arguments); 27877 }; 27878 27879 define.amd = oldDef.amd; 27880 27881 //Add some utilities for plugins 27882 require._readFile = file.readFile; 27883 require._fileExists = function (path) { 27884 return file.exists(path); 27885 }; 27886 27887 //Called when execManager runs for a dependency. Used to figure out 27888 //what order of execution. 27889 require.onResourceLoad = function (context, map) { 27890 var id = map.id, 27891 url; 27892 27893 // Fix up any maps that need to be normalized as part of the fullExec 27894 // plumbing for plugins to participate in the build. 27895 if (context.plugins && lang.hasProp(context.plugins, id)) { 27896 lang.eachProp(context.needFullExec, function(value, prop) { 27897 // For plugin entries themselves, they do not have a map 27898 // value in needFullExec, just a "true" entry. 27899 if (value !== true && value.prefix === id && value.unnormalized) { 27900 var map = context.makeModuleMap(value.originalName, value.parentMap); 27901 context.needFullExec[map.id] = map; 27902 } 27903 }); 27904 } 27905 27906 //If build needed a full execution, indicate it 27907 //has been done now. But only do it if the context is tracking 27908 //that. Only valid for the context used in a build, not for 27909 //other contexts being run, like for useLib, plain requirejs 27910 //use in node/rhino. 27911 if (context.needFullExec && getOwn(context.needFullExec, id)) { 27912 context.fullExec[id] = map; 27913 } 27914 27915 //A plugin. 27916 if (map.prefix) { 27917 if (falseProp(layer.pathAdded, id)) { 27918 layer.buildFilePaths.push(id); 27919 //For plugins the real path is not knowable, use the name 27920 //for both module to file and file to module mappings. 27921 layer.buildPathMap[id] = id; 27922 layer.buildFileToModule[id] = id; 27923 layer.modulesWithNames[id] = true; 27924 layer.pathAdded[id] = true; 27925 } 27926 } else if (map.url && require._isSupportedBuildUrl(map.url)) { 27927 //If the url has not been added to the layer yet, and it 27928 //is from an actual file that was loaded, add it now. 27929 url = normalizeUrlWithBase(context, id, map.url); 27930 if (!layer.pathAdded[url] && getOwn(layer.buildPathMap, id)) { 27931 //Remember the list of dependencies for this layer. 27932 layer.buildFilePaths.push(url); 27933 layer.pathAdded[url] = true; 27934 } 27935 } 27936 }; 27937 27938 //Called by output of the parse() function, when a file does not 27939 //explicitly call define, probably just require, but the parse() 27940 //function normalizes on define() for dependency mapping and file 27941 //ordering works correctly. 27942 require.needsDefine = function (moduleName) { 27943 layer.needsDefine[moduleName] = true; 27944 }; 27945 }; 27946 }); 27947 /*jslint */ 27948 /*global define: false, console: false */ 27949 27950 define('commonJs', ['env!env/file', 'parse'], function (file, parse) { 27951 'use strict'; 27952 var commonJs = { 27953 //Set to false if you do not want this file to log. Useful in environments 27954 //like node where you want the work to happen without noise. 27955 useLog: true, 27956 27957 convertDir: function (commonJsPath, savePath) { 27958 var fileList, i, 27959 jsFileRegExp = /\.js$/, 27960 fileName, convertedFileName, fileContents; 27961 27962 //Get list of files to convert. 27963 fileList = file.getFilteredFileList(commonJsPath, /\w/, true); 27964 27965 //Normalize on front slashes and make sure the paths do not end in a slash. 27966 commonJsPath = commonJsPath.replace(/\\/g, "/"); 27967 savePath = savePath.replace(/\\/g, "/"); 27968 if (commonJsPath.charAt(commonJsPath.length - 1) === "/") { 27969 commonJsPath = commonJsPath.substring(0, commonJsPath.length - 1); 27970 } 27971 if (savePath.charAt(savePath.length - 1) === "/") { 27972 savePath = savePath.substring(0, savePath.length - 1); 27973 } 27974 27975 //Cycle through all the JS files and convert them. 27976 if (!fileList || !fileList.length) { 27977 if (commonJs.useLog) { 27978 if (commonJsPath === "convert") { 27979 //A request just to convert one file. 27980 console.log('\n\n' + commonJs.convert(savePath, file.readFile(savePath))); 27981 } else { 27982 console.log("No files to convert in directory: " + commonJsPath); 27983 } 27984 } 27985 } else { 27986 for (i = 0; i < fileList.length; i++) { 27987 fileName = fileList[i]; 27988 convertedFileName = fileName.replace(commonJsPath, savePath); 27989 27990 //Handle JS files. 27991 if (jsFileRegExp.test(fileName)) { 27992 fileContents = file.readFile(fileName); 27993 fileContents = commonJs.convert(fileName, fileContents); 27994 file.saveUtf8File(convertedFileName, fileContents); 27995 } else {
27996 //Just copy the file over. 27997 file.copyFile(fileName, convertedFileName, true); 27998 } 27999 } 28000 } 28001 }, 28002 28003 /** 28004 * Does the actual file conversion. 28005 * 28006 * @param {String} fileName the name of the file. 28007 * 28008 * @param {String} fileContents the contents of a file :) 28009 * 28010 * @returns {String} the converted contents 28011 */ 28012 convert: function (fileName, fileContents) { 28013 //Strip out comments. 28014 try { 28015 var preamble = '', 28016 commonJsProps = parse.usesCommonJs(fileName, fileContents); 28017 28018 //First see if the module is not already RequireJS-formatted. 28019 if (parse.usesAmdOrRequireJs(fileName, fileContents) || !commonJsProps) { 28020 return fileContents; 28021 } 28022 28023 if (commonJsProps.dirname || commonJsProps.filename) { 28024 preamble = 'var __filename = module.uri || "", ' + 28025 '__dirname = __filename.substring(0, __filename.lastIndexOf("/") + 1); '; 28026 } 28027 28028 //Construct the wrapper boilerplate. 28029 fileContents = 'define(function (require, exports, module) {' + 28030 preamble + 28031 fileContents + 28032 '\n});\n'; 28033 28034 } catch (e) { 28035 console.log("commonJs.convert: COULD NOT CONVERT: " + fileName + ", so skipping it. Error was: " + e); 28036 return fileContents; 28037 } 28038 28039 return fileContents; 28040 } 28041 }; 28042 28043 return commonJs; 28044 }); 28045 /*jslint plusplus: true, nomen: true, regexp: true */ 28046 /*global define, requirejs, java, process, console */ 28047 28048 28049 define('build', function (require) { 28050 'use strict'; 28051 28052 var build, 28053 lang = require('lang'), 28054 prim = require('prim'), 28055 logger = require('logger'), 28056 file = require('env!env/file'), 28057 parse = require('parse'), 28058 optimize = require('optimize'), 28059 pragma = require('pragma'), 28060 transform = require('transform'), 28061 requirePatch = require('requirePatch'), 28062 env = require('env'), 28063 commonJs = require('commonJs'), 28064 SourceMapGenerator = require('source-map').SourceMapGenerator, 28065 hasProp = lang.hasProp, 28066 getOwn = lang.getOwn, 28067 falseProp = lang.falseProp, 28068 endsWithSemiColonRegExp = /;\s*$/, 28069 endsWithSlashRegExp = /[\/\\]$/, 28070 resourceIsModuleIdRegExp = /^[\w\/\\\.]+$/, 28071 deepCopyProps = { 28072 layer: true 28073 }; 28074 28075 //Deep copy a config object, but do not copy over the "layer" property, 28076 //as it can be a deeply nested structure with a full requirejs context. 28077 function copyConfig(obj) { 28078 return lang.deeplikeCopy(obj, deepCopyProps); 28079 } 28080 28081 prim.nextTick = function (fn) { 28082 fn(); 28083 }; 28084 28085 //Now map require to the outermost requirejs, now that we have 28086 //local dependencies for this module. The rest of the require use is 28087 //manipulating the requirejs loader. 28088 require = requirejs; 28089 28090 //Caching function for performance. Attached to 28091 //require so it can be reused in requirePatch.js. _cachedRawText 28092 //set up by requirePatch.js 28093 require._cacheReadAsync = function (path, encoding) { 28094 var d; 28095 28096 if (lang.hasProp(require._cachedRawText, path)) { 28097 d = prim(); 28098 d.resolve(require._cachedRawText[path]); 28099 return d.promise; 28100 } else { 28101 return file.readFileAsync(path, encoding).then(function (text) { 28102 require._cachedRawText[path] = text; 28103 return text; 28104 }); 28105 } 28106 }; 28107 28108 function makeBuildBaseConfig() { 28109 return { 28110 appDir: "", 28111 pragmas: {}, 28112 paths: {}, 28113 optimize: "uglify", 28114 optimizeCss: "standard.keepLines.keepWhitespace", 28115 inlineText: true, 28116 isBuild: true, 28117 optimizeAllPluginResources: false, 28118 findNestedDependencies: false, 28119 preserveLicenseComments: true, 28120 writeBuildTxt: true, 28121 //Some builds can take a while, up the default limit. 28122 waitSeconds: 30, 28123 //By default, all files/directories are copied, unless 28124 //they match this regexp, by default just excludes .folders 28125 dirExclusionRegExp: file.dirExclusionRegExp, 28126 _buildPathToModuleIndex: {} 28127 }; 28128 } 28129 28130 /** 28131 * Some JS may not be valid if concatenated with other JS, in particular 28132 * the style of omitting semicolons and rely on ASI. Add a semicolon in 28133 * those cases. 28134 */ 28135 function addSemiColon(text, config) { 28136 if (config.skipSemiColonInsertion || endsWithSemiColonRegExp.test(text)) { 28137 return text; 28138 } else {
28139 return text + ";"; 28140 } 28141 } 28142 28143 function endsWithSlash(dirName) { 28144 if (dirName.charAt(dirName.length - 1) !== "/") { 28145 dirName += "/"; 28146 } 28147 return dirName; 28148 } 28149 28150 function endsWithNewLine(text) { 28151 if (text.charAt(text.length - 1) !== "\n") { 28152 text += "\n"; 28153 } 28154 return text; 28155 } 28156 28157 //Method used by plugin writeFile calls, defined up here to avoid 28158 //jslint warning about "making a function in a loop". 28159 function makeWriteFile(namespace, layer) { 28160 function writeFile(name, contents) { 28161 logger.trace('Saving plugin-optimized file: ' + name); 28162 file.saveUtf8File(name, contents); 28163 } 28164 28165 writeFile.asModule = function (moduleName, fileName, contents) { 28166 writeFile(fileName, 28167 build.toTransport(namespace, moduleName, fileName, contents, layer)); 28168 }; 28169 28170 return writeFile; 28171 } 28172 28173 /** 28174 * Appends singleContents to fileContents and returns the result. If a sourceMapGenerator 28175 * is provided, adds singleContents to the source map. 28176 * 28177 * @param {string} fileContents - The file contents to which to append singleContents 28178 * @param {string} singleContents - The additional contents to append to fileContents 28179 * @param {string} path - An absolute path of a file whose name to use in the source map. 28180 * The file need not actually exist if the code in singleContents is generated. 28181 * @param {{out: ?string, baseUrl: ?string}} config - The build configuration object. 28182 * @param {?{_buildPath: ?string}} module - An object with module information. 28183 * @param {?SourceMapGenerator} sourceMapGenerator - An instance of Mozilla's SourceMapGenerator, 28184 * or null if no source map is being generated. 28185 * @returns {string} fileContents with singleContents appended 28186 */ 28187 function appendToFileContents(fileContents, singleContents, path, config, module, sourceMapGenerator) { 28188 var refPath, sourceMapPath, resourcePath, pluginId, sourceMapLineNumber, lineCount, parts, i; 28189 if (sourceMapGenerator) { 28190 if (config.out) { 28191 refPath = config.baseUrl; 28192 } else if (module && module._buildPath) { 28193 refPath = module._buildPath; 28194 } else { 28195 refPath = ""; 28196 } 28197 parts = path.split('!'); 28198 if (parts.length === 1) { 28199 //Not a plugin resource, fix the path 28200 sourceMapPath = build.makeRelativeFilePath(refPath, path); 28201 } else { 28202 //Plugin resource. If it looks like just a plugin 28203 //followed by a module ID, pull off the plugin 28204 //and put it at the end of the name, otherwise 28205 //just leave it alone. 28206 pluginId = parts.shift(); 28207 resourcePath = parts.join('!'); 28208 if (resourceIsModuleIdRegExp.test(resourcePath)) { 28209 sourceMapPath = build.makeRelativeFilePath(refPath, require.toUrl(resourcePath)) + 28210 '!' + pluginId; 28211 } else { 28212 sourceMapPath = path; 28213 } 28214 } 28215 28216 sourceMapLineNumber = fileContents.split('\n').length - 1; 28217 lineCount = singleContents.split('\n').length; 28218 for (i = 1; i <= lineCount; i += 1) { 28219 sourceMapGenerator.addMapping({ 28220 generated: { 28221 line: sourceMapLineNumber + i, 28222 column: 0 28223 }, 28224 original: { 28225 line: i, 28226 column: 0 28227 }, 28228 source: sourceMapPath 28229 }); 28230 } 28231 28232 //Store the content of the original in the source 28233 //map since other transforms later like minification 28234 //can mess up translating back to the original 28235 //source. 28236 sourceMapGenerator.setSourceContent(sourceMapPath, singleContents); 28237 } 28238 fileContents += singleContents; 28239 return fileContents; 28240 } 28241 28242 /** 28243 * Main API entry point into the build. The args argument can either be 28244 * an array of arguments (like the onese passed on a command-line), 28245 * or it can be a JavaScript object that has the format of a build profile 28246 * file. 28247 * 28248 * If it is an object, then in addition to the normal properties allowed in 28249 * a build profile file, the object should contain one other property: 28250 *
28251 * The object could also contain a "buildFile" property, which is a string 28252 * that is the file path to a build profile that contains the rest 28253 * of the build profile directives. 28254 * 28255 * This function does not return a status, it should throw an error if 28256 * there is a problem completing the build. 28257 */ 28258 build = function (args) { 28259 var buildFile, cmdConfig, errorMsg, errorStack, stackMatch, errorTree, 28260 i, j, errorMod, 28261 stackRegExp = /( {4}at[^\n]+)\n/, 28262 standardIndent = ' '; 28263 28264 return prim().start(function () { 28265 if (!args || lang.isArray(args)) { 28266 if (!args || args.length < 1) { 28267 logger.error("build.js buildProfile.js\n" + 28268 "where buildProfile.js is the name of the build file (see example.build.js for hints on how to make a build file)."); 28269 return undefined; 28270 } 28271 28272 //Next args can include a build file path as well as other build args. 28273 //build file path comes first. If it does not contain an = then it is 28274 //a build file path. Otherwise, just all build args. 28275 if (args[0].indexOf("=") === -1) { 28276 buildFile = args[0]; 28277 args.splice(0, 1); 28278 } 28279 28280 //Remaining args are options to the build 28281 cmdConfig = build.convertArrayToObject(args); 28282 cmdConfig.buildFile = buildFile; 28283 } else { 28284 cmdConfig = args; 28285 } 28286 28287 return build._run(cmdConfig); 28288 }).then(null, function (e) { 28289 var err; 28290 28291 errorMsg = e.toString(); 28292 errorTree = e.moduleTree; 28293 stackMatch = stackRegExp.exec(errorMsg); 28294 28295 if (stackMatch) { 28296 errorMsg += errorMsg.substring(0, stackMatch.index + stackMatch[0].length + 1); 28297 } 28298 28299 //If a module tree that shows what module triggered the error, 28300 //print it out. 28301 if (errorTree && errorTree.length > 0) { 28302 errorMsg += '\nIn module tree:\n'; 28303 28304 for (i = errorTree.length - 1; i > -1; i--) { 28305 errorMod = errorTree[i]; 28306 if (errorMod) { 28307 for (j = errorTree.length - i; j > -1; j--) { 28308 errorMsg += standardIndent; 28309 } 28310 errorMsg += errorMod + '\n'; 28311 } 28312 } 28313 28314 logger.error(errorMsg); 28315 } 28316 28317 errorStack = e.stack; 28318 28319 if (typeof args === 'string' && args.indexOf('stacktrace=true') !== -1) { 28320 errorMsg += '\n' + errorStack; 28321 } else { 28322 if (!stackMatch && errorStack) { 28323 //Just trim out the first "at" in the stack. 28324 stackMatch = stackRegExp.exec(errorStack); 28325 if (stackMatch) { 28326 errorMsg += '\n' + stackMatch[0] || ''; 28327 } 28328 } 28329 } 28330 28331 err = new Error(errorMsg); 28332 err.originalError = e; 28333 throw err; 28334 }); 28335 }; 28336 28337 build._run = function (cmdConfig) { 28338 var buildPaths, fileName, fileNames, 28339 paths, i, 28340 baseConfig, config, 28341 modules, srcPath, buildContext, 28342 destPath, moduleMap, parentModuleMap, context, 28343 resources, resource, plugin, fileContents, 28344 pluginProcessed = {}, 28345 buildFileContents = "", 28346 pluginCollector = {}; 28347 28348 return prim().start(function () { 28349 var prop; 28350 28351 //Can now run the patches to require.js to allow it to be used for 28352 //build generation. Do it here instead of at the top of the module 28353 //because we want normal require behavior to load the build tool 28354 //then want to switch to build mode. 28355 requirePatch(); 28356 28357 config = build.createConfig(cmdConfig); 28358 paths = config.paths; 28359 28360 //Remove the previous build dir, in case it contains source transforms, 28361 //like the ones done with onBuildRead and onBuildWrite. 28362 if (config.dir && !config.keepBuildDir && file.exists(config.dir)) { 28363 file.deleteFile(config.dir); 28364 } 28365 28366 if (!config.out && !config.cssIn) { 28367 //This is not just a one-off file build but a full build profile, with 28368 //lots of files to process. 28369 28370 //First copy all the baseUrl content 28371 file.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true); 28372 28373 //Adjust baseUrl if config.appDir is in play, and set up build output paths. 28374 buildPaths = {}; 28375 if (config.appDir) { 28376 //All the paths should be inside the appDir, so just adjust 28377 //the paths to use the dirBaseUrl 28378 for (prop in paths) { 28379 if (hasProp(paths, prop)) { 28380 buildPaths[prop] = paths[prop].replace(config.appDir, config.dir); 28381 } 28382 } 28383 } else { 28384 //If no appDir, then make sure to copy the other paths to this directory. 28385 for (prop in paths) { 28386 if (hasProp(paths, prop)) { 28387 //Set up build path for each path prefix, but only do so 28388 //if the path falls out of the current baseUrl 28389 if (paths[prop].indexOf(config.baseUrl) === 0) { 28390 buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl); 28391 } else { 28392 buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop; 28393 28394 //Make sure source path is fully formed with baseUrl, 28395 //if it is a relative URL. 28396 srcPath = paths[prop]; 28397 if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) { 28398 srcPath = config.baseUrl + srcPath; 28399 } 28400 28401 destPath = config.dirBaseUrl + buildPaths[prop]; 28402 28403 //Skip empty: paths 28404 if (srcPath !== 'empty:') { 28405 //If the srcPath is a directory, copy the whole directory. 28406 if (file.exists(srcPath) && file.isDirectory(srcPath)) { 28407 //Copy files to build area. Copy all files (the /\w/ regexp) 28408 file.copyDir(srcPath, destPath, /\w/, true); 28409 } else { 28410 //Try a .js extension 28411 srcPath += '.js'; 28412 destPath += '.js'; 28413 file.copyFile(srcPath, destPath); 28414 } 28415 } 28416 } 28417 } 28418 } 28419 } 28420 } 28421 28422 //Figure out source file location for each module layer. Do this by seeding require 28423 //with source area configuration. This is needed so that later the module layers 28424 //can be manually copied over to the source area, since the build may be 28425 //require multiple times and the above copyDir call only copies newer files. 28426 require({ 28427 baseUrl: config.baseUrl, 28428 paths: paths, 28429 packagePaths: config.packagePaths, 28430 packages: config.packages 28431 }); 28432 buildContext = require.s.contexts._; 28433 modules = config.modules; 28434 28435 if (modules) {
28436 modules.forEach(function (module) { 28437 if (module.name) { 28438 module._sourcePath = buildContext.nameToUrl(module.name); 28439 //If the module does not exist, and this is not a "new" module layer, 28440 //as indicated by a true "create" property on the module, and 28441 //it is not a plugin-loaded resource, and there is no 28442 //'rawText' containing the module's source then throw an error. 28443 if (!file.exists(module._sourcePath) && !module.create && 28444 module.name.indexOf('!') === -1 && 28445 (!config.rawText || !lang.hasProp(config.rawText, module.name))) { 28446 throw new Error("ERROR: module path does not exist: " + 28447 module._sourcePath + " for module named: " + module.name + 28448 ". Path is relative to: " + file.absPath('.')); 28449 } 28450 } 28451 }); 28452 } 28453 28454 if (config.out) { 28455 //Just set up the _buildPath for the module layer. 28456 require(config); 28457 if (!config.cssIn) { 28458 config.modules[0]._buildPath = typeof config.out === 'function' ? 28459 'FUNCTION' : config.out; 28460 } 28461 } else if (!config.cssIn) { 28462 //Now set up the config for require to use the build area, and calculate the 28463 //build file locations. Pass along any config info too. 28464 baseConfig = { 28465 baseUrl: config.dirBaseUrl, 28466 paths: buildPaths 28467 }; 28468 28469 lang.mixin(baseConfig, config); 28470 require(baseConfig); 28471 28472 if (modules) { 28473 modules.forEach(function (module) { 28474 if (module.name) { 28475 module._buildPath = buildContext.nameToUrl(module.name, null); 28476 28477 //If buildPath and sourcePath are the same, throw since this 28478 //would result in modifying source. This condition can happen 28479 //with some more tricky paths: config and appDir/baseUrl 28480 //setting, which is a sign of incorrect config. 28481 if (module._buildPath === module._sourcePath && 28482 !config.allowSourceOverwrites) { 28483 throw new Error('Module ID \'' + module.name + 28484 '\' has a source path that is same as output path: ' + 28485 module._sourcePath + 28486 '. Stopping, config is malformed.'); 28487 } 28488 28489 // Copy the file, but only if it is not provided in rawText. 28490 if (!module.create && (!config.rawText || !lang.hasProp(config.rawText, module.name))) { 28491 file.copyFile(module._sourcePath, module._buildPath); 28492 } 28493 } 28494 }); 28495 } 28496 } 28497 28498 //Run CSS optimizations before doing JS module tracing, to allow 28499 //things like text loader plugins loading CSS to get the optimized 28500 //CSS. 28501 if (config.optimizeCss && config.optimizeCss !== "none" && config.dir) { 28502 buildFileContents += optimize.css(config.dir, config); 28503 } 28504 }).then(function() { 28505 baseConfig = copyConfig(require.s.contexts._.config); 28506 }).then(function () { 28507 var actions = []; 28508 28509 if (modules) { 28510 actions = modules.map(function (module, i) { 28511 return function () { 28512 //Save off buildPath to module index in a hash for quicker 28513 //lookup later. 28514 config._buildPathToModuleIndex[file.normalize(module._buildPath)] = i; 28515 28516 //Call require to calculate dependencies.
28517 return build.traceDependencies(module, config, baseConfig) 28518 .then(function (layer) { 28519 module.layer = layer; 28520 }); 28521 }; 28522 }); 28523 28524 return prim.serial(actions); 28525 } 28526 }).then(function () { 28527 var actions; 28528 28529 if (modules) { 28530 //Now build up shadow layers for anything that should be excluded. 28531 //Do this after tracing dependencies for each module, in case one 28532 //of those modules end up being one of the excluded values. 28533 actions = modules.map(function (module) { 28534 return function () { 28535 if (module.exclude) { 28536 module.excludeLayers = []; 28537 return prim.serial(module.exclude.map(function (exclude, i) { 28538 return function () { 28539 //See if it is already in the list of modules. 28540 //If not trace dependencies for it. 28541 var found = build.findBuildModule(exclude, modules); 28542 if (found) { 28543 module.excludeLayers[i] = found; 28544 } else { 28545 return build.traceDependencies({name: exclude}, config, baseConfig) 28546 .then(function (layer) { 28547 module.excludeLayers[i] = { layer: layer }; 28548 }); 28549 } 28550 }; 28551 })); 28552 } 28553 }; 28554 }); 28555 28556 return prim.serial(actions); 28557 } 28558 }).then(function () { 28559 if (modules) { 28560 return prim.serial(modules.map(function (module) { 28561 return function () { 28562 if (module.exclude) { 28563 //module.exclude is an array of module names. For each one, 28564 //get the nested dependencies for it via a matching entry 28565 //in the module.excludeLayers array. 28566 module.exclude.forEach(function (excludeModule, i) { 28567 var excludeLayer = module.excludeLayers[i].layer, 28568 map = excludeLayer.buildFileToModule; 28569 excludeLayer.buildFilePaths.forEach(function(filePath){ 28570 build.removeModulePath(map[filePath], filePath, module.layer); 28571 }); 28572 }); 28573 } 28574 if (module.excludeShallow) { 28575 //module.excludeShallow is an array of module names. 28576 //shallow exclusions are just that module itself, and not 28577 //its nested dependencies. 28578 module.excludeShallow.forEach(function (excludeShallowModule) { 28579 var path = getOwn(module.layer.buildPathMap, excludeShallowModule); 28580 if (path) { 28581 build.removeModulePath(excludeShallowModule, path, module.layer); 28582 } 28583 }); 28584 } 28585 28586 //Flatten them and collect the build output for each module. 28587 return build.flattenModule(module, module.layer, config).then(function (builtModule) { 28588 var finalText, baseName; 28589 //Save it to a temp file for now, in case there are other layers that 28590 //contain optimized content that should not be included in later 28591 //layer optimizations. See issue #56. 28592 if (module._buildPath === 'FUNCTION') { 28593 module._buildText = builtModule.text; 28594 module._buildSourceMap = builtModule.sourceMap; 28595 } else { 28596 finalText = builtModule.text; 28597 if (builtModule.sourceMap) { 28598 baseName = module._buildPath.split('/'); 28599 baseName = baseName.pop(); 28600 finalText += '\n//# sourceMappingURL=' + baseName + '.map'; 28601 file.saveUtf8File(module._buildPath + '.map', builtModule.sourceMap); 28602 } 28603 file.saveUtf8File(module._buildPath + '-temp', finalText); 28604 28605 } 28606 buildFileContents += builtModule.buildText; 28607 }); 28608 }; 28609 })); 28610 } 28611 }).then(function () { 28612 var moduleName, outOrigSourceMap, 28613 bundlesConfig = {}, 28614 bundlesConfigOutFile = config.bundlesConfigOutFile; 28615 28616 if (modules) { 28617 //Now move the build layers to their final position.
28618 modules.forEach(function (module) { 28619 var entryConfig, 28620 finalPath = module._buildPath; 28621 28622 if (finalPath !== 'FUNCTION') { 28623 if (file.exists(finalPath)) { 28624 file.deleteFile(finalPath); 28625 } 28626 file.renameFile(finalPath + '-temp', finalPath); 28627 28628 //If bundles config should be written out, scan the 28629 //built file for module IDs. Favor doing this reparse 28630 //since tracking the IDs as the file is built has some 28631 //edge cases around files that had more than one ID in 28632 //them already, and likely loader plugin-written contents. 28633 if (bundlesConfigOutFile) { 28634 entryConfig = bundlesConfig[module.name] = []; 28635 var bundleContents = file.readFile(finalPath); 28636 var excludeMap = {}; 28637 excludeMap[module.name] = true; 28638 var parsedIds = parse.getAllNamedDefines(bundleContents, excludeMap); 28639 entryConfig.push.apply(entryConfig, parsedIds); 28640 } 28641 28642 //And finally, if removeCombined is specified, remove 28643 //any of the files that were used in this layer. 28644 //Be sure not to remove other build layers. 28645 if (config.removeCombined && !config.out) { 28646 module.layer.buildFilePaths.forEach(function (path) { 28647 var isLayer = modules.some(function (mod) { 28648 return mod._buildPath === path; 28649 }), 28650 relPath = build.makeRelativeFilePath(config.dir, path); 28651 28652 if (file.exists(path) && 28653 // not a build layer target 28654 !isLayer && 28655 // not outside the build directory 28656 relPath.indexOf('..') !== 0) { 28657 file.deleteFile(path); 28658 } 28659 }); 28660 } 28661 } 28662 28663 //Signal layer is done 28664 if (config.onModuleBundleComplete) { 28665 config.onModuleBundleComplete(module.onCompleteData); 28666 } 28667 }); 28668 28669 //Write out bundles config, if it is wanted. 28670 if (bundlesConfigOutFile) { 28671 var text = file.readFile(bundlesConfigOutFile); 28672 text = transform.modifyConfig(text, function (config) { 28673 if (!config.bundles) { 28674 config.bundles = {}; 28675 } 28676 28677 lang.eachProp(bundlesConfig, function (value, prop) { 28678 config.bundles[prop] = value; 28679 }); 28680 28681 return config; 28682 }); 28683 28684 file.saveUtf8File(bundlesConfigOutFile, text); 28685 } 28686 } 28687 28688 //If removeCombined in play, remove any empty directories that 28689 //may now exist because of its use 28690 if (config.removeCombined && !config.out && config.dir) { 28691 file.deleteEmptyDirs(config.dir); 28692 } 28693 28694 //Do other optimizations. 28695 if (config.out && !config.cssIn) { 28696 //Just need to worry about one JS file. 28697 fileName = config.modules[0]._buildPath; 28698 if (fileName === 'FUNCTION') { 28699 outOrigSourceMap = config.modules[0]._buildSourceMap; 28700 config._buildSourceMap = outOrigSourceMap; 28701 config.modules[0]._buildText = optimize.js((config.modules[0].name || 28702 config.modules[0].include[0] || 28703 fileName) + '.build.js', 28704 config.modules[0]._buildText, 28705 null, 28706 config); 28707 if (config._buildSourceMap && config._buildSourceMap !== outOrigSourceMap) { 28708 config.modules[0]._buildSourceMap = config._buildSourceMap; 28709 config._buildSourceMap = null; 28710 } 28711 } else { 28712 optimize.jsFile(fileName, null, fileName, config); 28713 } 28714 } else if (!config.cssIn) { 28715 //Normal optimizations across modules. 28716 28717 //JS optimizations. 28718 fileNames = file.getFilteredFileList(config.dir, /\.js$/, true);
28719 fileNames.forEach(function (fileName) { 28720 var cfg, override, moduleIndex; 28721 28722 //Generate the module name from the config.dir root. 28723 moduleName = fileName.replace(config.dir, ''); 28724 //Get rid of the extension 28725 moduleName = moduleName.substring(0, moduleName.length - 3); 28726 28727 //If there is an override for a specific layer build module, 28728 //and this file is that module, mix in the override for use 28729 //by optimize.jsFile. 28730 moduleIndex = getOwn(config._buildPathToModuleIndex, fileName); 28731 //Normalize, since getOwn could have returned undefined 28732 moduleIndex = moduleIndex === 0 || moduleIndex > 0 ? moduleIndex : -1; 28733 28734 //Try to avoid extra work if the other files do not need to 28735 //be read. Build layers should be processed at the very 28736 //least for optimization. 28737 if (moduleIndex > -1 || !config.skipDirOptimize || 28738 config.normalizeDirDefines === "all" || 28739 config.cjsTranslate) { 28740 //Convert the file to transport format, but without a name 28741 //inserted (by passing null for moduleName) since the files are 28742 //standalone, one module per file. 28743 fileContents = file.readFile(fileName); 28744 28745 28746 //For builds, if wanting cjs translation, do it now, so that 28747 //the individual modules can be loaded cross domain via 28748 //plain script tags. 28749 if (config.cjsTranslate && 28750 (!config.shim || !lang.hasProp(config.shim, moduleName))) { 28751 fileContents = commonJs.convert(fileName, fileContents); 28752 } 28753 28754 if (moduleIndex === -1) { 28755 if (config.onBuildRead) { 28756 fileContents = config.onBuildRead(moduleName, 28757 fileName, 28758 fileContents); 28759 } 28760 28761 //Only do transport normalization if this is not a build 28762 //layer (since it was already normalized) and if 28763 //normalizeDirDefines indicated all should be done. 28764 if (config.normalizeDirDefines === "all") { 28765 fileContents = build.toTransport(config.namespace, 28766 null, 28767 fileName, 28768 fileContents); 28769 } 28770 28771 if (config.onBuildWrite) { 28772 fileContents = config.onBuildWrite(moduleName, 28773 fileName, 28774 fileContents); 28775 } 28776 } 28777 28778 override = moduleIndex > -1 ? 28779 config.modules[moduleIndex].override : null; 28780 if (override) { 28781 cfg = build.createOverrideConfig(config, override); 28782 } else { 28783 cfg = config; 28784 } 28785 28786 if (moduleIndex > -1 || !config.skipDirOptimize) { 28787 optimize.jsFile(fileName, fileContents, fileName, cfg, pluginCollector); 28788 } 28789 } 28790 }); 28791 28792 //Normalize all the plugin resources. 28793 context = require.s.contexts._; 28794 28795 for (moduleName in pluginCollector) { 28796 if (hasProp(pluginCollector, moduleName)) { 28797 parentModuleMap = context.makeModuleMap(moduleName); 28798 resources = pluginCollector[moduleName]; 28799 for (i = 0; i < resources.length; i++) { 28800 resource = resources[i]; 28801 moduleMap = context.makeModuleMap(resource, parentModuleMap); 28802 if (falseProp(context.plugins, moduleMap.prefix)) { 28803 //Set the value in context.plugins so it 28804 //will be evaluated as a full plugin. 28805 context.plugins[moduleMap.prefix] = true; 28806 28807 //Do not bother if the plugin is not available. 28808 if (!file.exists(require.toUrl(moduleMap.prefix + '.js'))) { 28809 continue; 28810 } 28811 28812 //Rely on the require in the build environment 28813 //to be synchronous 28814 context.require([moduleMap.prefix]); 28815 28816 //Now that the plugin is loaded, redo the moduleMap 28817 //since the plugin will need to normalize part of the path.
28818 moduleMap = context.makeModuleMap(resource, parentModuleMap); 28819 } 28820 28821 //Only bother with plugin resources that can be handled 28822 //processed by the plugin, via support of the writeFile 28823 //method. 28824 if (falseProp(pluginProcessed, moduleMap.id)) { 28825 //Only do the work if the plugin was really loaded. 28826 //Using an internal access because the file may 28827 //not really be loaded. 28828 plugin = getOwn(context.defined, moduleMap.prefix); 28829 if (plugin && plugin.writeFile) { 28830 plugin.writeFile( 28831 moduleMap.prefix, 28832 moduleMap.name, 28833 require, 28834 makeWriteFile( 28835 config.namespace 28836 ), 28837 context.config 28838 ); 28839 } 28840 28841 pluginProcessed[moduleMap.id] = true; 28842 } 28843 } 28844 28845 } 28846 } 28847 28848 //console.log('PLUGIN COLLECTOR: ' + JSON.stringify(pluginCollector, null, " ")); 28849 28850 28851 //All module layers are done, write out the build.txt file. 28852 if (config.writeBuildTxt) { 28853 file.saveUtf8File(config.dir + "build.txt", buildFileContents); 28854 } 28855 } 28856 28857 //If just have one CSS file to optimize, do that here. 28858 if (config.cssIn) { 28859 buildFileContents += optimize.cssFile(config.cssIn, config.out, config).buildText; 28860 } 28861 28862 if (typeof config.out === 'function') { 28863 config.out(config.modules[0]._buildText, config.modules[0]._buildSourceMap); 28864 } 28865 28866 //Print out what was built into which layers. 28867 if (buildFileContents) { 28868 logger.info(buildFileContents); 28869 return buildFileContents; 28870 } 28871 28872 return ''; 28873 }); 28874 }; 28875 28876 /** 28877 * Converts command line args like "paths.foo=../some/path" 28878 * result.paths = { foo: '../some/path' } where prop = paths, 28879 * name = paths.foo and value = ../some/path, so it assumes the 28880 * name=value splitting has already happened. 28881 */ 28882 function stringDotToObj(result, name, value) { 28883 var parts = name.split('.'); 28884 28885 parts.forEach(function (prop, i) { 28886 if (i === parts.length - 1) { 28887 result[prop] = value; 28888 } else { 28889 if (falseProp(result, prop)) { 28890 result[prop] = {}; 28891 } 28892 result = result[prop]; 28893 } 28894 28895 }); 28896 } 28897 28898 build.objProps = { 28899 paths: true, 28900 wrap: true, 28901 pragmas: true, 28902 pragmasOnSave: true, 28903 has: true, 28904 hasOnSave: true, 28905 uglify: true, 28906 uglify2: true, 28907 closure: true, 28908 map: true, 28909 throwWhen: true, 28910 rawText: true 28911 }; 28912 28913 build.hasDotPropMatch = function (prop) { 28914 var dotProp, 28915 index = prop.indexOf('.'); 28916 28917 if (index !== -1) { 28918 dotProp = prop.substring(0, index); 28919 return hasProp(build.objProps, dotProp); 28920 } 28921 return false;
28922 }; 28923 28924 /** 28925 * Converts an array that has String members of "name=value" 28926 * into an object, where the properties on the object are the names in the array. 28927 * Also converts the strings "true" and "false" to booleans for the values. 28928 * member name/value pairs, and converts some comma-separated lists into 28929 * arrays. 28930 * @param {Array} ary 28931 */ 28932 build.convertArrayToObject = function (ary) { 28933 var result = {}, i, separatorIndex, prop, value, 28934 needArray = { 28935 "include": true, 28936 "exclude": true, 28937 "excludeShallow": true, 28938 "insertRequire": true, 28939 "stubModules": true, 28940 "deps": true, 28941 "mainConfigFile": true, 28942 "wrap.startFile": true, 28943 "wrap.endFile": true 28944 }; 28945 28946 for (i = 0; i < ary.length; i++) { 28947 separatorIndex = ary[i].indexOf("="); 28948 if (separatorIndex === -1) { 28949 throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value"; 28950 } 28951 28952 value = ary[i].substring(separatorIndex + 1, ary[i].length); 28953 if (value === "true") { 28954 value = true; 28955 } else if (value === "false") { 28956 value = false; 28957 } 28958 28959 prop = ary[i].substring(0, separatorIndex); 28960 28961 //Convert to array if necessary 28962 if (getOwn(needArray, prop)) { 28963 value = value.split(","); 28964 } 28965 28966 if (build.hasDotPropMatch(prop)) { 28967 stringDotToObj(result, prop, value); 28968 } else { 28969 result[prop] = value; 28970 } 28971 } 28972 return result; //Object 28973 }; 28974 28975 build.makeAbsPath = function (path, absFilePath) { 28976 if (!absFilePath) { 28977 return path; 28978 } 28979 28980 //Add abspath if necessary. If path starts with a slash or has a colon, 28981 //then already is an abolute path. 28982 if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) { 28983 path = absFilePath + 28984 (absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') + 28985 path; 28986 path = file.normalize(path); 28987 } 28988 return path.replace(lang.backSlashRegExp, '/'); 28989 }; 28990 28991 build.makeAbsObject = function (props, obj, absFilePath) { 28992 var i, prop; 28993 if (obj) { 28994 for (i = 0; i < props.length; i++) { 28995 prop = props[i]; 28996 if (hasProp(obj, prop) && typeof obj[prop] === 'string') { 28997 obj[prop] = build.makeAbsPath(obj[prop], absFilePath); 28998 } 28999 } 29000 } 29001 }; 29002 29003 /** 29004 * For any path in a possible config, make it absolute relative 29005 * to the absFilePath passed in. 29006 */ 29007 build.makeAbsConfig = function (config, absFilePath) { 29008 var props, prop, i; 29009 29010 props = ["appDir", "dir", "baseUrl"]; 29011 for (i = 0; i < props.length; i++) { 29012 prop = props[i]; 29013 29014 if (getOwn(config, prop)) { 29015 //Add abspath if necessary, make sure these paths end in 29016 //slashes 29017 if (prop === "baseUrl") { 29018 config.originalBaseUrl = config.baseUrl; 29019 if (config.appDir) { 29020 //If baseUrl with an appDir, the baseUrl is relative to 29021 //the appDir, *not* the absFilePath. appDir and dir are 29022 //made absolute before baseUrl, so this will work. 29023 config.baseUrl = build.makeAbsPath(config.originalBaseUrl, config.appDir); 29024 } else { 29025 //The dir output baseUrl is same as regular baseUrl, both 29026 //relative to the absFilePath. 29027 config.baseUrl = build.makeAbsPath(config[prop], absFilePath); 29028 } 29029 } else { 29030 config[prop] = build.makeAbsPath(config[prop], absFilePath); 29031 } 29032 29033 config[prop] = endsWithSlash(config[prop]); 29034 } 29035 } 29036 29037 build.makeAbsObject((config.out === "stdout" ? ["cssIn"] : ["out", "cssIn"]), 29038 config, absFilePath); 29039 build.makeAbsObject(["startFile", "endFile"], config.wrap, absFilePath); 29040 build.makeAbsObject(["externExportsPath"], config.closure, absFilePath); 29041 }; 29042 29043 /** 29044 * Creates a relative path to targetPath from refPath. 29045 * Only deals with file paths, not folders. If folders, 29046 * make sure paths end in a trailing '/'. 29047 */ 29048 build.makeRelativeFilePath = function (refPath, targetPath) { 29049 var i, dotLength, finalParts, length, targetParts, targetName, 29050 refParts = refPath.split('/'), 29051 hasEndSlash = endsWithSlashRegExp.test(targetPath), 29052 dotParts = []; 29053 29054 targetPath = file.normalize(targetPath); 29055 if (hasEndSlash && !endsWithSlashRegExp.test(targetPath)) { 29056 targetPath += '/'; 29057 } 29058 targetParts = targetPath.split('/'); 29059 //Pull off file name 29060 targetName = targetParts.pop(); 29061 29062 //Also pop off the ref file name to make the matches against 29063 //targetParts equivalent. 29064 refParts.pop(); 29065 29066 length = refParts.length; 29067 29068 for (i = 0; i < length; i += 1) { 29069 if (refParts[i] !== targetParts[i]) { 29070 break; 29071 } 29072 } 29073 29074 //Now i is the index in which they diverge. 29075 finalParts = targetParts.slice(i); 29076 29077 dotLength = length - i; 29078 for (i = 0; i > -1 && i < dotLength; i += 1) { 29079 dotParts.push('..'); 29080 } 29081 29082 return dotParts.join('/') + (dotParts.length ? '/' : '') + 29083 finalParts.join('/') + (finalParts.length ? '/' : '') + 29084 targetName; 29085 }; 29086 29087 build.nestedMix = { 29088 paths: true, 29089 has: true, 29090 hasOnSave: true, 29091 pragmas: true, 29092 pragmasOnSave: true 29093 }; 29094 29095 /** 29096 * Mixes additional source config into target config, and merges some 29097 * nested config, like paths, correctly. 29098 */ 29099 function mixConfig(target, source, skipArrays) { 29100 var prop, value, isArray, targetValue; 29101 29102 for (prop in source) { 29103 if (hasProp(source, prop)) { 29104 //If the value of the property is a plain object, then 29105 //allow a one-level-deep mixing of it. 29106 value = source[prop]; 29107 isArray = lang.isArray(value); 29108 if (typeof value === 'object' && value && 29109 !isArray && !lang.isFunction(value) && 29110 !lang.isRegExp(value)) { 29111 29112 // TODO: need to generalize this work, maybe also reuse 29113 // the work done in requirejs configure, perhaps move to 29114 // just a deep copy/merge overall. However, given the 29115 // amount of observable change, wait for a dot release. 29116 // This change is in relation to #645 29117 if (prop === 'map') { 29118 if (!target.map) { 29119 target.map = {}; 29120 } 29121 lang.deepMix(target.map, source.map
29121); 29122 } else { 29123 target[prop] = lang.mixin({}, target[prop], value, true); 29124 } 29125 } else if (isArray) { 29126 if (!skipArrays) { 29127 // Some config, like packages, are arrays. For those, 29128 // just merge the results. 29129 targetValue = target[prop]; 29130 if (lang.isArray(targetValue)) { 29131 target[prop] = targetValue.concat(value); 29132 } else { 29133 target[prop] = value; 29134 } 29135 } 29136 } else { 29137 target[prop] = value; 29138 } 29139 } 29140 } 29141 29142 //Set up log level since it can affect if errors are thrown 29143 //or caught and passed to errbacks while doing config setup. 29144 if (lang.hasProp(target, 'logLevel')) { 29145 logger.logLevel(target.logLevel); 29146 } 29147 } 29148 29149 /** 29150 * Converts a wrap.startFile or endFile to be start/end as a string. 29151 * the startFile/endFile values can be arrays. 29152 */ 29153 function flattenWrapFile(config, keyName, absFilePath) { 29154 var wrap = config.wrap, 29155 keyFileName = keyName + 'File', 29156 keyMapName = '__' + keyName + 'Map'; 29157 29158 if (typeof wrap[keyName] !== 'string' && wrap[keyFileName]) { 29159 wrap[keyName] = ''; 29160 if (typeof wrap[keyFileName] === 'string') { 29161 wrap[keyFileName] = [wrap[keyFileName]]; 29162 } 29163 wrap[keyMapName] = []; 29164 wrap[keyFileName].forEach(function (fileName) { 29165 var absPath = build.makeAbsPath(fileName, absFilePath), 29166 fileText = endsWithNewLine(file.readFile(absPath)); 29167 wrap[keyMapName].push(function (fileContents, cfg, sourceMapGenerator) { 29168 return appendToFileContents(fileContents, fileText, absPath, cfg, null, sourceMapGenerator); 29169 }); 29170 wrap[keyName] += fileText; 29171 }); 29172 } else if (wrap[keyName] === null || wrap[keyName] === undefined) { 29173 //Allow missing one, just set to empty string. 29174 wrap[keyName] = ''; 29175 } else if (typeof wrap[keyName] === 'string') { 29176 wrap[keyName] = endsWithNewLine(wrap[keyName]); 29177 wrap[keyMapName] = [ 29178 function (fileContents, cfg, sourceMapGenerator) { 29179 var absPath = build.makeAbsPath("config-wrap-" + keyName + "-default.js", absFilePath); 29180 return appendToFileContents(fileContents, wrap[keyName], absPath, cfg, null, sourceMapGenerator); 29181 } 29182 ]; 29183 } else { 29184 throw new Error('wrap.' + keyName + ' or wrap.' + keyFileName + ' malformed'); 29185 } 29186 } 29187 29188 function normalizeWrapConfig(config, absFilePath) { 29189 //Get any wrap text. 29190 try { 29191 if (config.wrap) { 29192 if (config.wrap === true) { 29193 //Use default values. 29194 config.wrap = { 29195 start: '(function () {\n', 29196 end: '}());', 29197 __startMap: [ 29198 function (fileContents, cfg, sourceMapGenerator) { 29199 return appendToFileContents(fileContents, "(function () {\n", 29200 build.makeAbsPath("config-wrap-start-default.js", 29201 absFilePath), cfg, null, 29202 sourceMapGenerator); 29203 } 29204 ], 29205 __endMap: [ 29206 function (fileContents, cfg, sourceMapGenerator) { 29207 return appendToFileContents(fileContents, "}());", 29208 build.makeAbsPath("config-wrap-end-default.js", absFilePath), 29209 cfg, null, sourceMapGenerator); 29210 } 29211 ] 29212 }; 29213 } else { 29214 flattenWrapFile(config, 'start', absFilePath); 29215 flattenWrapFile(config, 'end', absFilePath); 29216 } 29217 } 29218 } catch (wrapError) { 29219 throw new Error('Malformed wrap config: ' + wrapError.toString()); 29220 } 29221 } 29222 29223 /** 29224 * Creates a config object for an optimization build. 29225 * It will also read the build profile if it is available, to create 29226 * the configuration. 29227 * 29228 * @param {Object} cfg config options that take priority 29229 * over defaults and ones in the build file. These options could 29230 * be from a command line, for instance. 29231 * 29232 * @param {Object} the created config object. 29233 */ 29234 build.createConfig = function (cfg) { 29235 /*jslint evil: true */ 29236 var buildFileContents, buildFileConfig, mainConfig, 29237 mainConfigFile, mainConfigPath, buildFile, absFilePath, 29238 config = {}, 29239 buildBaseConfig = makeBuildBaseConfig(); 29240 29241 //Make sure all paths are relative to current directory. 29242 absFilePath = file.absPath('.'); 29243 build.makeAbsConfig(cfg, absFilePath); 29244 build.makeAbsConfig(buildBaseConfig, absFilePath); 29245 29246 lang.mixin(config, buildBaseConfig); 29247 lang.mixin(config, cfg, true); 29248 29249 //Set up log level early since it can affect if errors are thrown 29250 //or caught and passed to errbacks, even while constructing config. 29251 if (lang.hasProp(config, 'logLevel')) { 29252 logger.logLevel(config.logLevel); 29253 } 29254 29255 if (config.buildFile) { 29256 //A build file exists, load it to get more config. 29257 buildFile = file.absPath(config.buildFile); 29258 29259 //Find the build file, and make sure it exists, if this is a build 29260 //that has a build profile, and not just command line args with an in=path 29261 if (!file.exists(buildFile)) { 29262 throw new Error("ERROR: build file does not exist: " + buildFile); 29263 } 29264 29265 absFilePath = config.baseUrl = file.absPath(file.parent(buildFile)); 29266 29267 //Load build file options. 29268 buildFileContents = file.readFile(buildFile); 29269 try { 29270 //Be a bit lenient in the file ending in a ; or ending with 29271 //a //# sourceMappingUrl comment, mostly for compiled languages 29272 //that create a config, like typescript. 29273 buildFileContents = buildFileContents 29274 .replace(/\/\/\#[^\n\r]+[\n\r]*$/, '') 29275 .trim() 29276 .replace(/;$/, ''); 29277 29278 buildFileConfig = eval("(" + buildFileContents + ")"); 29279 build.makeAbsConfig(buildFileConfig, absFilePath); 29280 29281 //Mix in the config now so that items in mainConfigFile can 29282 //be resolved relative to them if necessary, like if appDir 29283 //is set here, but the baseUrl is in mainConfigFile. Will 29284 //re-mix in the same build config later after mainConfigFile 29285 //is processed, since build config should take priority. 29286 mixConfig(config, buildFileConfig); 29287 } catch (e) { 29288 throw new Error("Build file " + buildFile + " is malformed: " + e); 29289 } 29290 } 29291 29292 mainConfigFile = config.mainConfigFile || (buildFileConfig && buildFileConfig.mainConfigFile); 29293 if (mainConfigFile) { 29294 if (typeof mainConfigFile === 'string') { 29295 mainConfigFile = [mainConfigFile]; 29296 } 29297 29298 mainConfigFile.forEach(function (configFile) { 29299 configFile = build.makeAbsPath(configFile, absFilePath); 29300 if (!file.exists(configFile)) { 29301 throw new Error(configFile + ' does not exist.'); 29302 } 29303 try { 29304 mainConfig = parse.findConfig(file.readFile(configFile)).config; 29305 } catch (configError) { 29306 throw new Error('The config in mainConfigFile ' + 29307 configFile + 29308 ' cannot be used because it cannot be evaluated' + 29309 ' correctly while running in the optimizer. Try only' + 29310 ' using a config that is also valid JSON, or do not use' + 29311 ' mainConfigFile and instead copy the config values needed' + 29312 ' into a build file or command line arguments given to the optimizer.\n' + 29313 'Source error from parsing: ' + configFile + ': ' + configError); 29314 } 29315 if (mainConfig) { 29316 mainConfigPath = configFile.substring(0, configFile.lastIndexOf('/')); 29317 29318 //Add in some existing config, like appDir, since they can be 29319 //used inside the configFile -- paths and baseUrl are 29320 //relative to them. 29321 if (config.appDir && !mainConfig.appDir) { 29322 mainConfig.appDir = config.appDir; 29323 } 29324 29325 //If no baseUrl, then use the directory holding the main config. 29326 if (!mainConfig.baseUrl) { 29327 mainConfig.baseUrl = mainConfigPath; 29328 } 29329 29330 build.makeAbsConfig(mainConfig, mainConfigPath); 29331 mixConfig(config, mainConfig); 29332 } 29333 }); 29334 } 29335 29336 //Mix in build file config, but only after mainConfig has been mixed in. 29337 //Since this is a re-application, skip array merging. 29338 if (buildFileConfig) { 29339 mixConfig(config, buildFileConfig, true); 29340 } 29341 29342 //Re-apply the override config values. Command line 29343 //args should take precedence over build file values. 29344 //Since this is a re-application, skip array merging. 29345 mixConfig(config, cfg, true); 29346 29347 //Fix paths to full paths so that they can be adju
29347sted consistently 29348 //lately to be in the output area. 29349 lang.eachProp(config.paths, function (value, prop) { 29350 if (lang.isArray(value)) { 29351 throw new Error('paths fallback not supported in optimizer. ' + 29352 'Please provide a build config path override ' + 29353 'for ' + prop); 29354 } 29355 config.paths[prop] = build.makeAbsPath(value, config.baseUrl); 29356 }); 29357 29358 //Set final output dir 29359 if (hasProp(config, "baseUrl")) { 29360 if (config.appDir) { 29361 if (!config.originalBaseUrl) { 29362 throw new Error('Please set a baseUrl in the build config'); 29363 } 29364 config.dirBaseUrl = build.makeAbsPath(config.originalBaseUrl, config.dir); 29365 } else { 29366 config.dirBaseUrl = config.dir || config.baseUrl; 29367 } 29368 //Make sure dirBaseUrl ends in a slash, since it is 29369 //concatenated with other strings. 29370 config.dirBaseUrl = endsWithSlash(config.dirBaseUrl); 29371 } 29372 29373 if (config.bundlesConfigOutFile) { 29374 if (!config.dir) { 29375 throw new Error('bundlesConfigOutFile can only be used with optimizations ' + 29376 'that use "dir".'); 29377 } 29378 config.bundlesConfigOutFile = build.makeAbsPath(config.bundlesConfigOutFile, config.dir); 29379 } 29380 29381 //If out=stdout, write output to STDOUT instead of a file. 29382 if (config.out && config.out === 'stdout') { 29383 config.out = function (content) { 29384 var e = env.get(); 29385 if (e === 'rhino') { 29386 var out = new java.io.PrintStream(java.lang.System.out, true, 'UTF-8'); 29387 out.println(content); 29388 } else if (e === 'node') { 29389 process.stdout.write(content, 'utf8'); 29390 } else { 29391 console.log(content); 29392 } 29393 }; 29394 } 29395 29396 //Check for errors in config 29397 if (config.main) { 29398 throw new Error('"main" passed as an option, but the ' + 29399 'supported option is called "name".'); 29400 } 29401 if (config.out && !config.name && !config.modules && !config.include && 29402 !config.cssIn) { 29403 throw new Error('Missing either a "name", "include" or "modules" ' + 29404 'option'); 29405 } 29406 if (config.cssIn) { 29407 if (config.dir || config.appDir) { 29408 throw new Error('cssIn is only for the output of single file ' + 29409 'CSS optimizations and is not compatible with "dir" or "appDir" configuration.'); 29410 } 29411 if (!config.out) { 29412 throw new Error('"out" option missing.'); 29413 } 29414 } 29415 if (!config.cssIn && !config.baseUrl) { 29416 //Just use the current directory as the baseUrl 29417 config.baseUrl = './'; 29418 } 29419 if (!config.out && !config.dir) { 29420 throw new Error('Missing either an "out" or "dir" config value. ' + 29421 'If using "appDir" for a full project optimization, ' + 29422 'use "dir". If you want to optimize to one file, ' + 29423 'use "out".'); 29424 } 29425 if (config.appDir && config.out) { 29426 throw new Error('"appDir" is not compatible with "out". Use "dir" ' + 29427 'instead. appDir is used to copy whole projects, ' + 29428 'where "out" with "baseUrl" is used to just ' + 29429 'optimize to one file.'); 29430 } 29431 if (config.out && config.dir) { 29432 throw new Error('The "out" and "dir" options are incompatible.' + 29433 ' Use "out" if you are targeting a single file' + 29434 ' for optimization, and "dir" if you want the appDir' + 29435 ' or baseUrl directories optimized.'); 29436 } 29437 29438 29439 if (config.dir) { 29440 // Make sure the output dir is not set to a parent of the 29441 // source dir or the same dir, as it will result in source 29442 // code deletion. 29443 if (!config.allowSourceOverwrites && (config.dir === config.baseUrl || 29444 config.dir === config.appDir || 29445 (config.baseUrl && build.makeRelativeFilePath(config.dir, 29446 config.baseUrl).indexOf('..') !== 0) || 29447 (config.appDir && 29448 build.makeRelativeFilePath(config.dir, config.appDir).indexOf('..') !== 0))) { 29449 throw new Error('"dir" is set to a parent or same directory as' + 29450 ' "appDir" or "baseUrl". This can result in' + 29451 ' the deletion of source code. Stopping. If' + 29452 ' you want to allow possible overwriting of' + 29453 ' source code, set "allowSourceOverwrites"' + 29454 ' to true in the build config, but do so at' + 29455 ' your own risk. In that case, you may want' + 29456 ' to also set "keepBuildDir" to true.'); 29457 } 29458 } 29459 29460 if (config.insertRequire && !lang.isArray(config.insertRequire)) { 29461 throw new Error('insertRequire should be a list of module IDs' + 29462 ' to insert in to a require([]) call.'); 29463 } 29464 29465 //Support older configs with uglify2 settings, but now that uglify1 has 29466 //been removed, just translate it to 'uglify' settings. 29467 if (config.optimize === 'uglify2') { 29468 config.optimize = 'uglify'; 29469 } 29470 if (config.uglify2) { 29471 config.uglify = config.uglify2; 29472 delete config.uglify2; 29473 } 29474 29475 if (config.generateSourceMaps) { 29476 if (config.preserveLicenseComments && !(config.optimize === 'none' || config.optimize === 'uglify')) { 29477 throw new Error('Cannot use preserveLicenseComments and ' + 29478 'generateSourceMaps together, unless optimize is set ' + 29479 'to \'uglify\'. Either explicitly set preserveLicenseComments ' +
29480 'to false (default is true) or turn off generateSourceMaps. ' + 29481 'If you want source maps with license comments, see: ' + 29482 'http://requirejs.org/docs/errors.html#sourcemapcomments'); 29483 } else if (config.optimize !== 'none' && 29484 config.optimize !== 'closure' && 29485 config.optimize !== 'uglify') { 29486 //Allow optimize: none to pass, since it is useful when toggling 29487 //minification on and off to debug something, and it implicitly 29488 //works, since it does not need a source map. 29489 throw new Error('optimize: "' + config.optimize + 29490 '" does not support generateSourceMaps.'); 29491 } 29492 } 29493 29494 if ((config.name || config.include) && !config.modules) { 29495 //Just need to build one file, but may be part of a whole appDir/ 29496 //baseUrl copy, but specified on the command line, so cannot do 29497 //the modules array setup. So create a modules section in that 29498 //case. 29499 config.modules = [ 29500 { 29501 name: config.name, 29502 out: config.out, 29503 create: config.create, 29504 include: config.include, 29505 exclude: config.exclude, 29506 excludeShallow: config.excludeShallow, 29507 insertRequire: config.insertRequire, 29508 stubModules: config.stubModules 29509 } 29510 ]; 29511 delete config.stubModules; 29512 } else if (config.modules && config.out) { 29513 throw new Error('If the "modules" option is used, then there ' + 29514 'should be a "dir" option set and "out" should ' + 29515 'not be used since "out" is only for single file ' + 29516 'optimization output.'); 29517 } else if (config.modules && config.name) { 29518 throw new Error('"name" and "modules" options are incompatible. ' + 29519 'Either use "name" if doing a single file ' + 29520 'optimization, or "modules" if you want to target ' + 29521 'more than one file for optimization.'); 29522 } 29523 29524 if (config.out && !config.cssIn) { 29525 //Just one file to optimize. 29526 29527 //Does not have a build file, so set up some defaults. 29528 //Optimizing CSS should not be allowed, unless explicitly 29529 //asked for on command line. In that case the only task is 29530 //to optimize a CSS file. 29531 if (!cfg.optimizeCss) { 29532 config.optimizeCss = "none"; 29533 } 29534 } 29535 29536 //Normalize cssPrefix 29537 if (config.cssPrefix) { 29538 //Make sure cssPrefix ends in a slash 29539 config.cssPrefix = endsWithSlash(config.cssPrefix); 29540 } else { 29541 config.cssPrefix = ''; 29542 } 29543 29544 //Cycle through modules and normalize 29545 if (config.modules && config.modules.length) { 29546 config.modules.forEach(function (mod) { 29547 if (lang.isArray(mod) || typeof mod === 'string' || !mod) { 29548 throw new Error('modules config item is malformed: it should' + 29549 ' be an object with a \'name\' property.'); 29550 } 29551 29552 //Combine any local stubModules with global values. 29553 if (config.stubModules) { 29554 mod.stubModules = config.stubModules.concat(mod.stubModules || []); 29555 } 29556 29557 //Create a hash lookup for the stubModules config to make lookup 29558 //cheaper later. 29559 if (mod.stubModules) { 29560 mod.stubModules._byName = {};
29561 mod.stubModules.forEach(function (id) { 29562 mod.stubModules._byName[id] = true; 29563 }); 29564 } 29565 29566 // Legacy command support, which allowed a single string ID 29567 // for include. 29568 if (typeof mod.include === 'string') { 29569 mod.include = [mod.include]; 29570 } 29571 29572 //Allow wrap config in overrides, but normalize it. 29573 if (mod.override) { 29574 normalizeWrapConfig(mod.override, absFilePath); 29575 } 29576 }); 29577 } 29578 29579 normalizeWrapConfig(config, absFilePath); 29580 29581 //Do final input verification 29582 if (config.context) { 29583 throw new Error('The build argument "context" is not supported' + 29584 ' in a build. It should only be used in web' + 29585 ' pages.'); 29586 } 29587 29588 //Set up normalizeDirDefines. If not explicitly set, if optimize "none", 29589 //set to "skip" otherwise set to "all". 29590 if (!hasProp(config, 'normalizeDirDefines')) { 29591 if (config.optimize === 'none' || config.skipDirOptimize) { 29592 config.normalizeDirDefines = 'skip'; 29593 } else { 29594 config.normalizeDirDefines = 'all'; 29595 } 29596 } 29597 29598 //Set file.fileExclusionRegExp if desired 29599 if (hasProp(config, 'fileExclusionRegExp')) { 29600 if (typeof config.fileExclusionRegExp === "string") { 29601 file.exclusionRegExp = new RegExp(config.fileExclusionRegExp); 29602 } else { 29603 file.exclusionRegExp = config.fileExclusionRegExp; 29604 } 29605 } else if (hasProp(config, 'dirExclusionRegExp')) { 29606 //Set file.dirExclusionRegExp if desired, this is the old 29607 //name for fileExclusionRegExp before 1.0.2. Support for backwards 29608 //compatibility 29609 file.exclusionRegExp = config.dirExclusionRegExp; 29610 } 29611 29612 //Track the deps, but in a different key, so that they are not loaded 29613 //as part of config seeding before all config is in play (#648). Was 29614 //going to merge this in with "include", but include is added after 29615 //the "name" target. To preserve what r.js has done previously, make 29616 //sure "deps" comes before the "name". 29617 if (config.deps) { 29618 config._depsInclude = config.deps; 29619 } 29620 29621 29622 //Remove things that may cause problems in the build. 29623 //deps already merged above 29624 delete config.deps; 29625 delete config.jQuery; 29626 delete config.enforceDefine; 29627 delete config.urlArgs; 29628 29629 return config; 29630 }; 29631 29632 /** 29633 * finds the module being built/optimized with the given moduleName, 29634 * or returns null. 29635 * @param {String} moduleName 29636 * @param {Array} modules 29637 * @returns {Object} the module object from the build profile, or null. 29638 */ 29639 build.findBuildModule = function (moduleName, modules) { 29640 var i, module; 29641 for (i = 0; i < modules.length; i++) { 29642 module = modules[i]; 29643 if (module.name === moduleName) { 29644 return module; 29645 } 29646 } 29647 return null; 29648 }; 29649 29650 /** 29651 * Removes a module name and path from a layer, if it is supposed to be 29652 * excluded from the layer. 29653 * @param {String} moduleName the name of the module 29654 * @param {String} path the file path for the module 29655 * @param {Object} layer the layer to remove the module/path from 29656 */
29657 build.removeModulePath = function (module, path, layer) { 29658 var index = layer.buildFilePaths.indexOf(path); 29659 if (index !== -1) { 29660 layer.buildFilePaths.splice(index, 1); 29661 } 29662 }; 29663 29664 /** 29665 * Uses the module build config object to trace the dependencies for the 29666 * given module. 29667 * 29668 * @param {Object} module the module object from the build config info. 29669 * @param {Object} config the build config object. 29670 * @param {Object} [baseLoaderConfig] the base loader config to use for env resets. 29671 * 29672 * @returns {Object} layer information about what paths and modules should 29673 * be in the flattened module. 29674 */ 29675 build.traceDependencies = function (module, config, baseLoaderConfig) { 29676 var include, override, layer, context, oldContext, 29677 rawTextByIds, 29678 syncChecks = { 29679 rhino: true, 29680 node: true, 29681 xpconnect: true 29682 }, 29683 deferred = prim(); 29684 29685 //Reset some state set up in requirePatch.js, and clean up require's 29686 //current context. 29687 oldContext = require._buildReset(); 29688 29689 //Grab the reset layer and context after the reset, but keep the 29690 //old config to reuse in the new context. 29691 layer = require._layer; 29692 context = layer.context; 29693 29694 //Put back basic config, use a fresh object for it. 29695 if (baseLoaderConfig) { 29696 require(copyConfig(baseLoaderConfig)); 29697 } 29698 29699 logger.trace("\nTracing dependencies for: " + (module.name || 29700 (typeof module.out === 'function' ? 'FUNCTION' : module.out))); 29701 include = config._depsInclude || []; 29702 include = include.concat(module.name && !module.create ? [module.name] : []); 29703 if (module.include) { 29704 include = include.concat(module.include); 29705 } 29706 29707 //If there are overrides to basic config, set that up now.; 29708 if (module.override) { 29709 if (baseLoaderConfig) { 29710 override = build.createOverrideConfig(baseLoaderConfig, module.override); 29711 } else { 29712 override = copyConfig(module.override); 29713 } 29714 require(override); 29715 } 29716 29717 //Now, populate the rawText cache with any values explicitly passed in 29718 //via config. 29719 rawTextByIds = require.s.contexts._.config.rawText; 29720 if (rawTextByIds) { 29721 lang.eachProp(rawTextByIds, function (contents, id) { 29722 var url = require.toUrl(id) + '.js'; 29723 require._cachedRawText[url] = contents; 29724 }); 29725 } 29726 29727 29728 //Configure the callbacks to be called. 29729 deferred.reject.__requireJsBuild = true; 29730 29731 //Use a wrapping function so can check for errors. 29732 function includeFinished(value) { 29733 //If a sync build environment, check for errors here, instead of 29734 //in the then callback below, since some errors, like two IDs pointed 29735 //to same URL but only one anon ID will leave the loader in an 29736 //unresolved state since a setTimeout cannot be used to check for 29737 //timeout. 29738 var hasError = false; 29739 if (syncChecks[env.get()]) { 29740 try { 29741 build.checkForErrors(context, layer); 29742 } catch (e) { 29743 hasError = true; 29744 deferred.reject(e); 29745 } 29746 } 29747 29748 if (!hasError) { 29749 deferred.resolve(value); 29750 } 29751 } 29752 includeFinished.__requireJsBuild = true; 29753 29754 //Figure out module layer dependencies by calling require to do the work. 29755 require(include, includeFinished, deferred.reject); 29756 29757 // If a sync env, then with the "two IDs to same anon module path" 29758 // issue, the require never completes, need to check for errors 29759 // here. 29760 if (syncChecks[env.get()]) { 29761 build.checkForErrors(context, layer); 29762 } 29763 29764 return deferred.promise.then(function () { 29765 //Reset config 29766 if (module.override && baseLoaderConfig) { 29767 require(copyConfig(baseLoaderConfig)); 29768 } 29769 29770 build.checkForErrors(context, layer); 29771 29772 return layer; 29773 }); 29774 }; 29775 29776 build.checkForErrors = function (context, layer) { 29777 //Check to see if it all loaded. If not, then throw, and give 29778 //a message on what is left. 29779 var id, prop, mod, idParts, pluginId, pluginResources, 29780 errMessage = '', 29781 failedPluginMap = {}, 29782 failedPluginIds = [], 29783 errIds = [], 29784 errUrlMap = {}, 29785 errUrlConflicts = {}, 29786 hasErrUrl = false, 29787 hasUndefined = false, 29788 defined = context.defined, 29789 registry = context.registry; 29790 29791 function populateErrUrlMap(id, errUrl, skipNew) { 29792 // Loader plugins do not have an errUrl, so skip them. 29793 if (!errUrl) { 29794 return; 29795 } 29796 29797 if (!skipNew) { 29798 errIds.push(id); 29799 } 29800 29801 if (errUrlMap[errUrl]) { 29802 hasErrUrl = true; 29803 //This error module has the same URL as another 29804 //error module, could be misconfiguration. 29805 if (!errUrlConflicts[errUrl]) { 29806 errUrlConflicts[errUrl] = []; 29807 //Store the original module that had the same URL. 29808 errUrlConflicts[errUrl].push(errUrlMap[errUrl]); 29809 } 29810 errUrlConflicts[errUrl].push(id); 29811 } else if (!skipNew) { 29812 errUrlMap[errUrl] = id; 29813 } 29814 } 29815 29816 for (id in registry) { 29817 if (hasProp(registry, id) && id.indexOf('_@r') !== 0) { 29818 hasUndefined = true; 29819 mod = getOwn(registry, id); 29820 idParts = id.split('!'); 29821 pluginId = idParts[0]; 29822 29823 if (id.indexOf('_unnormalized') === -1 && mod && mod.enabled) { 29824 populateErrUrlMap(id, mod.map.url); 29825 } 29826 29827 //Look for plugins that did not call load() 29828 //But skip plugin IDs that were already inlined and called 29829 //define() with a name. 29830 if (!hasProp(layer.modulesWithNames, id) && idParts.length > 1) { 29831 if (falseProp(failedPluginMap, pluginId)) { 29832 failedPluginIds.push(pluginId); 29833 } 29834 pluginResources = failedPluginMap[pluginId]; 29835 if (!pluginResources) { 29836 pluginResources = failedPluginMap[pluginId] = []; 29837 } 29838 pluginResources.push(id + (mod.error ? ': ' + mod.error : '')); 29839 } 29840 } 29841 } 29842 29843 // If have some modules that are not defined/stuck in the registry, 29844 // then check defined modules for URL overlap. 29845 if (hasUndefined) { 29846 for (id in defined) { 29847 if (hasProp(defined, id) && id.indexOf('!') === -1) { 29848 populateErrUrlMap(id, require.toUrl(id) + '.js', true); 29849 } 29850 } 29851 } 29852 29853 if (errIds.length || failedPluginIds.length) { 29854 if (failedPluginIds.length) { 29855 errMessage += 'Loader plugin' + 29856 (failedPluginIds.length === 1 ? '' : 's') + 29857 ' did not call ' + 29858 'the load callback in the build:\n' + 29859 failedPluginIds.map(function (pluginId) { 29860 var pluginResources = failedPluginMap[pluginId]; 29861 return pluginId + ':\n ' + pluginResources.join('\n '); 29862 }).join('\n') + '\n'; 29863 }
29864 errMessage += 'Module loading did not complete for: ' + errIds.join(', '); 29865 29866 if (hasErrUrl) { 29867 errMessage += '\nThe following modules share the same URL. This ' + 29868 'could be a misconfiguration if that URL only has ' + 29869 'one anonymous module in it:'; 29870 for (prop in errUrlConflicts) { 29871 if (hasProp(errUrlConflicts, prop)) { 29872 errMessage += '\n' + prop + ': ' + 29873 errUrlConflicts[prop].join(', '); 29874 } 29875 } 29876 } 29877 throw new Error(errMessage); 29878 } 29879 }; 29880 29881 build.createOverrideConfig = function (config, override) { 29882 var cfg = copyConfig(config), 29883 oride = copyConfig(override); 29884 29885 lang.eachProp(oride, function (value, prop) { 29886 if (hasProp(build.objProps, prop)) { 29887 //An object property, merge keys. Start a new object 29888 //so that source object in config does not get modified. 29889 cfg[prop] = {}; 29890 lang.mixin(cfg[prop], config[prop], true); 29891 lang.mixin(cfg[prop], override[prop], true); 29892 } else { 29893 cfg[prop] = override[prop]; 29894 } 29895 }); 29896 29897 return cfg; 29898 }; 29899 29900 /** 29901 * Uses the module build config object to create an flattened version 29902 * of the module, with deep dependencies included. 29903 * 29904 * @param {Object} module the module object from the build config info. 29905 * 29906 * @param {Object} layer the layer object returned from build.traceDependencies. 29907 * 29908 * @param {Object} the build config object. 29909 * 29910 * @returns {Object} with two properties: "text", the text of the flattened 29911 * module, and "buildText", a string of text representing which files were 29912 * included in the flattened module text. 29913 */ 29914 build.flattenModule = function (module, layer, config) { 29915 var fileContents, sourceMapGenerator, 29916 sourceMapBase, 29917 buildFileContents = ''; 29918 29919 return prim().start(function () { 29920 var reqIndex, currContents, fileForSourceMap, 29921 moduleName, shim, packageName, 29922 parts, builder, writeApi, 29923 namespace, namespaceWithDot, stubModulesByName, 29924 context = layer.context, 29925 onLayerEnds = [], 29926 onLayerEndAdded = {}, 29927 pkgsMainMap = {}; 29928 29929 //Use override settings, particularly for pragmas 29930 //Do this before the var readings since it reads config values. 29931 if (module.override) { 29932 config = build.createOverrideConfig(config, module.override); 29933 } 29934 29935 namespace = config.namespace || ''; 29936 namespaceWithDot = namespace ? namespace + '.' : ''; 29937 stubModulesByName = (module.stubModules && module.stubModules._byName) || {}; 29938 29939 //Start build output for the module. 29940 module.onCompleteData = { 29941 name: module.name, 29942 path: (config.dir ? module._buildPath.replace(config.dir, "") : module._buildPath), 29943 included: [] 29944 }; 29945 29946 buildFileContents += "\n" + 29947 module.onCompleteData.path + 29948 "\n----------------\n"; 29949 29950 //If there was an existing file with require in it, hoist to the top. 29951 if (layer.existingRequireUrl) { 29952 reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl); 29953 if (reqIndex !== -1) { 29954 layer.buildFilePaths.splice(reqIndex, 1); 29955 layer.buildFilePaths.unshift(layer.existingRequireUrl); 29956 } 29957 } 29958 29959 if (config.generateSourceMaps) { 29960 sourceMapBase = config.dir || config.baseUrl; 29961 if (module._buildPath === 'FUNCTION') { 29962 fileForSourceMap = (module.name || module.include[0] || 'FUNCTION') + '.build.js'; 29963 } else if (config.out) { 29964 fileForSourceMap = module._buildPath.split('/').pop(); 29965 } else { 29966 fileForSourceMap = module._buildPath.replace(sourceMapBase, ''); 29967 } 29968 sourceMapGenerator = new SourceMapGenerator({ 29969 file: fileForSourceMap 29970 }); 29971 } 29972 29973 //Create a reverse lookup for packages main module IDs to their package 29974 //names, useful for knowing when to write out define() package main ID
29975 //adapters. 29976 lang.eachProp(layer.context.config.pkgs, function(value, prop) { 29977 pkgsMainMap[value] = prop; 29978 }); 29979 29980 //Write the built module to disk, and build up the build output. 29981 fileContents = ""; 29982 if (config.wrap && config.wrap.__startMap) { 29983 config.wrap.__startMap.forEach(function (wrapFunction) { 29984 fileContents = wrapFunction(fileContents, config, sourceMapGenerator); 29985 }); 29986 } 29987 29988 return prim.serial(layer.buildFilePaths.map(function (path) { 29989 return function () { 29990 var singleContents = ''; 29991 29992 moduleName = layer.buildFileToModule[path]; 29993 29994 //If the moduleName is a package main, then hold on to the 29995 //packageName in case an adapter needs to be written. 29996 packageName = getOwn(pkgsMainMap, moduleName); 29997 29998 return prim().start(function () { 29999 //Figure out if the module is a result of a build plugin, and if so, 30000 //then delegate to that plugin. 30001 parts = context.makeModuleMap(moduleName); 30002 builder = parts.prefix && getOwn(context.defined, parts.prefix); 30003 if (builder) { 30004 if (builder.onLayerEnd && falseProp(onLayerEndAdded, parts.prefix)) { 30005 onLayerEnds.push(builder); 30006 onLayerEndAdded[parts.prefix] = true; 30007 } 30008 30009 if (builder.write) { 30010 writeApi = function (input) { 30011 singleContents += "\n" + addSemiColon(input, config); 30012 if (config.onBuildWrite) { 30013 singleContents = config.onBuildWrite(moduleName, path, singleContents); 30014 } 30015 }; 30016 writeApi.asModule = function (moduleName, input) { 30017 singleContents += "\n" + 30018 addSemiColon(build.toTransport(namespace, moduleName, path, input, layer, { 30019 useSourceUrl: layer.context.config.useSourceUrl 30020 }), config); 30021 if (config.onBuildWrite) { 30022 singleContents = config.onBuildWrite(moduleName, path, singleContents); 30023 } 30024 }; 30025 30026 builder.write(parts.prefix, parts.name, writeApi, { 30027 name: module.onCompleteData.name, 30028 path: module.onCompleteData.path 30029 }); 30030 } 30031 return; 30032 } else { 30033 return prim().start(function () { 30034 if (hasProp(stubModulesByName, moduleName)) { 30035 //Just want to insert a simple module definition instead 30036 //of the source module. Useful for plugins that inline 30037 //all their resources. 30038 if (hasProp(layer.context.plugins, moduleName)) { 30039 //Slightly different content for plugins, to indicate 30040 //that dynamic loading will not work. 30041 return 'define({load: function(id){throw new Error("Dynamic load not allowed: " + id);}});'; 30042 } else { 30043 return 'define({});'; 30044 } 30045 } else { 30046 return require._cacheReadAsync(path); 30047 } 30048 }).then(function (text) { 30049 var hasPackageName; 30050 30051 currContents = text; 30052 30053 if (config.cjsTranslate && 30054 (!config.shim || !lang.hasProp(config.shim, moduleName))) { 30055 currContents = commonJs.convert(path, currContents); 30056 } 30057 30058 if (config.onBuildRead) { 30059 currContents = config.onBuildRead(moduleName, path, currContents); 30060 } 30061 30062 if (packageName) { 30063 hasPackageName = (packageName === parse.getNamedDefine(currContents)); 30064 } 30065 30066 if (namespace) { 30067 currContents = pragma.namespace(currContents, namespace); 30068 } 30069 30070 currContents = build.toTransport(namespace, moduleName, path, currContents, layer, { 30071 useSourceUrl: config.useSourceUrl 30072 }); 30073 30074 if (packageName && !hasPackageName) { 30075 currContents = addSemiColon(currContents, config) + '\n'; 30076 currContents += namespaceWithDot + "define('" + 30077 packageName + "', ['" + moduleName + 30078 "'], function (main) { return main; });\n"; 30079 } 30080 30081 if (config.onBuildWrite) { 30082 currContents = config.onBuildWrite(moduleName, path, currContents); 30083 } 30084 30085 //Semicolon is for files that are not well formed when 30086 //concatenated with other content. 30087 singleContents += addSemiColon(currContents, config); 30088 }); 30089 } 30090 }).then(function () { 30091 var shimDeps, shortPath = path.replace(config.dir, ""); 30092 30093 module.onCompleteData.included.push(shortPath); 30094 buildFileContents += shortPath + "\n"; 30095 30096 //Some files may not have declared a require module, and if so, 30097 //put in a placeholder call so the require does not try to load them
30098 //after the module is processed. 30099 //If we have a name, but no defined module, then add in the placeholder. 30100 if (moduleName && falseProp(layer.modulesWithNames, moduleName) && !config.skipModuleInsertion) { 30101 shim = config.shim && (getOwn(config.shim, moduleName) || (packageName && getOwn(config.shim, packageName))); 30102 if (shim) { 30103 shimDeps = lang.isArray(shim) ? shim : shim.deps; 30104 if (config.wrapShim) { 30105 30106 singleContents = '(function(root) {\n' + 30107 namespaceWithDot + 'define("' + moduleName + '", ' + 30108 (shimDeps && shimDeps.length ? 30109 build.makeJsArrayString(shimDeps) + ', ' : '[], ') + 30110 'function() {\n' + 30111 ' return (function() {\n' + 30112 singleContents + 30113 // Start with a \n in case last line is a comment 30114 // in the singleContents, like a sourceURL comment. 30115 '\n' + (shim.exportsFn ? shim.exportsFn() : '') + 30116 '\n' + 30117 ' }).apply(root, arguments);\n' + 30118 '});\n' + 30119 '}(this));\n'; 30120 } else { 30121 singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", ' + 30122 (shimDeps && shimDeps.length ? 30123 build.makeJsArrayString(shimDeps) + ', ' : '') + 30124 (shim.exportsFn ? shim.exportsFn() : 'function(){}') + 30125 ');\n'; 30126 } 30127 } else { 30128 singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", function(){});\n'; 30129 } 30130 } 30131 30132 //Add line break at end of file, instead of at beginning, 30133 //so source map line numbers stay correct, but still allow 30134 //for some space separation between files in case ASI issues 30135 //for concatenation would cause an error otherwise. 30136 singleContents += '\n'; 30137 30138 //Add to the source map and to the final contents 30139 fileContents = appendToFileContents(fileContents, singleContents, path, config, module, 30140 sourceMapGenerator); 30141 }); 30142 }; 30143 })).then(function () { 30144 if (onLayerEnds.length) { 30145 onLayerEnds.forEach(function (builder, index) { 30146 var path; 30147 if (typeof module.out === 'string') { 30148 path = module.out; 30149 } else if (typeof module._buildPath === 'string') { 30150 path = module._buildPath; 30151 } 30152 builder.onLayerEnd(function (input) { 30153 fileContents = 30154 appendToFileContents(fileContents, "\n" + addSemiColon(input, config), 30155 'onLayerEnd' + index + '.js', config, module, sourceMapGenerator); 30156 }, { 30157 name: module.name, 30158 path: path 30159 }); 30160 }); 30161 } 30162 30163 if (module.create) { 30164 //The ID is for a created layer. Write out 30165 //a module definition for it in case the 30166 //built file is used with enforceDefine 30167 //(#432) 30168 fileContents = 30169 appendToFileContents(fileContents, '\n' + namespaceWithDot + 'define("' + module.name + 30170 '", function(){});\n', 'module-create.js', config, module, 30171 sourceMapGenerator); 30172 } 30173 30174 //Add a require at the end to kick start module execution, if that 30175 //was desired. Usually this is only specified when using small shim 30176 //loaders like almond. 30177 if (module.insertRequire) { 30178 fileContents = 30179 appendToFileContents(fileContents, '\n' + namespaceWithDot + 'require(["' + module.insertRequire.join('", "') + 30180 '"]);\n', 'module-insertRequire.js', config, module, 30181 sourceMapGenerator); 30182 } 30183 }); 30184 }).then(function () { 30185 if (config.wrap && config.wrap.__endMap) {
30186 config.wrap.__endMap.forEach(function (wrapFunction) { 30187 fileContents = wrapFunction(fileContents, config, sourceMapGenerator); 30188 }); 30189 } 30190 return { 30191 text: fileContents, 30192 buildText: buildFileContents, 30193 sourceMap: sourceMapGenerator ? 30194 JSON.stringify(sourceMapGenerator.toJSON(), null, ' ') : 30195 undefined 30196 }; 30197 }); 30198 }; 30199 30200 //Converts an JS array of strings to a string representation. 30201 //Not using JSON.stringify() for Rhino's sake. 30202 build.makeJsArrayString = function (ary) { 30203 return '["' + ary.map(function (item) { 30204 //Escape any double quotes, backslashes 30205 return lang.jsEscape(item); 30206 }).join('","') + '"]'; 30207 }; 30208 30209 build.toTransport = function (namespace, moduleName, path, contents, layer, options) { 30210 var baseUrl = layer && layer.context.config.baseUrl; 30211 30212 function onFound(info) { 30213 //Only mark this module as having a name if not a named module, 30214 //or if a named module and the name matches expectations. 30215 if (layer && (info.needsId || info.foundId === moduleName)) { 30216 layer.modulesWithNames[moduleName] = true; 30217 } 30218 } 30219 30220 //Convert path to be a local one to the baseUrl, useful for 30221 //useSourceUrl. 30222 if (baseUrl) { 30223 path = path.replace(baseUrl, ''); 30224 } 30225 30226 return transform.toTransport(namespace, moduleName, path, contents, onFound, options); 30227 }; 30228 30229 return build; 30230 }); 30231 30232 } 30233 30234 30235 /** 30236 * Sets the default baseUrl for requirejs to be directory of top level 30237 * script. 30238 */ 30239 function setBaseUrl(fileName) { 30240 //Use the file name's directory as the baseUrl if available. 30241 dir = fileName.replace(/\\/g, '/'); 30242 if (dir.indexOf('/') !== -1) { 30243 dir = dir.split('/'); 30244 dir.pop(); 30245 dir = dir.join('/'); 30246 //Make sure dir is JS-escaped, since it will be part of a JS string. 30247 exec("require({baseUrl: '" + dir.replace(/[\\"']/g, '\\$&') + "'});"); 30248 } 30249 } 30250 30251 function createRjsApi() { 30252 //Create a method that will run the optimzer given an object 30253 //config. 30254 requirejs.optimize = function (config, callback, errback) { 30255 if (!loadedOptimizedLib) { 30256 loadLib(); 30257 loadedOptimizedLib = true; 30258 } 30259 30260 //Create the function that will be called once build modules 30261 //have been loaded. 30262 var runBuild = function (build, logger, quit) { 30263 //Make sure config has a log level, and if not, 30264 //make it "silent" by default. 30265 config.logLevel = config.hasOwnProperty('logLevel') ? 30266 config.logLevel : logger.SILENT; 30267 30268 //Reset build internals first in case this is part 30269 //of a long-running server process that could have 30270 //exceptioned out in a bad state. It is only defined 30271 //after the first call though. 30272 if (requirejs._buildReset) { 30273 requirejs._buildReset(); 30274 requirejs._cacheReset(); 30275 } 30276 30277 function done(result) { 30278 //And clean up, in case something else triggers 30279 //a build in another pathway. 30280 if (requirejs._buildReset) { 30281 requirejs._buildReset(); 30282 requirejs._cacheReset(); 30283 } 30284 30285 // Ensure errors get propagated to the errback 30286 if (result instanceof Error) { 30287 throw result; 30288 } 30289 30290 return result; 30291 } 30292 30293 errback = errback || function (err) { 30294 // Using console here since logger may have 30295 // turned off error logging. Since quit is 30296 // called want to be sure a message is printed. 30297 console.log(err); 30298 quit(1); 30299 }; 30300 30301 build(config).then(done, done).then(callback, errback); 30302 }; 30303 30304 requirejs({ 30305 context: 'build' 30306 }, ['build', 'logger', 'env!env/quit'], runBuild); 30307 }; 30308 30309 requirejs.tools = { 30310 useLib: function (contextName, callback) { 30311 if (!callback) { 30312 callback = contextName; 30313 contextName = 'uselib'; 30314 } 30315 30316 if (!useLibLoaded[contextName]) { 30317 loadLib();
30318 useLibLoaded[contextName] = true; 30319 } 30320 30321 var req = requirejs({ 30322 context: contextName 30323 }); 30324 30325 req(['build'], function () { 30326 callback(req); 30327 }); 30328 } 30329 }; 30330 30331 requirejs.define = define; 30332 } 30333 30334 //If in Node, and included via a require('requirejs'), just export and 30335 //THROW IT ON THE GROUND! 30336 if (env === 'node' && reqMain !== module) { 30337 setBaseUrl(path.resolve(reqMain ? reqMain.filename : '.')); 30338 30339 createRjsApi(); 30340 30341 module.exports = requirejs; 30342 return; 30343 } else if (env === 'browser') { 30344 //Only option is to use the API. 30345 setBaseUrl(location.href); 30346 createRjsApi(); 30347 return; 30348 } else if ((env === 'rhino' || env === 'xpconnect') && 30349 //User sets up requirejsAsLib variable to indicate it is loaded 30350 //via load() to be used as a library. 30351 typeof requirejsAsLib !== 'undefined' && requirejsAsLib) { 30352 //This script is loaded via rhino's load() method, expose the 30353 //API and get out. 30354 setBaseUrl(fileName); 30355 createRjsApi(); 30356 return; 30357 } 30358 30359 if (commandOption === 'o') { 30360 //Do the optimizer work. 30361 loadLib(); 30362 30363 /* 30364 * Create a build.js file that has the build options you want and pass that 30365 * build file to this file to do the build. See example.build.js for more information. 30366 */ 30367 30368 /*jslint strict: false, nomen: false */ 30369 /*global require: false */ 30370 30371 require({ 30372 baseUrl: require.s.contexts._.config.baseUrl, 30373 //Use a separate context than the default context so that the 30374 //build can use the default context. 30375 context: 'build', 30376 catchError: { 30377 define: true 30378 } 30379 }, ['env!env/args', 'env!env/quit', 'logger', 'build'], 30380 function (args, quit, logger, build) { 30381 build(args).then(function () {}, function (err) { 30382 logger.error(err); 30383 quit(1); 30384 }); 30385 }); 30386 30387 30388 } else if (commandOption === 'v') { 30389 console.log('r.js: ' + version + 30390 ', RequireJS: ' + this.requirejsVars.require.version + 30391 ', UglifyJS: 2.8.29'); 30392 } else if (commandOption === 'convert') { 30393 loadLib(); 30394 30395 this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'], 30396 function (args, commonJs, print) { 30397 30398 var srcDir, outDir; 30399 srcDir = args[0]; 30400 outDir = args[1]; 30401 30402 if (!srcDir || !outDir) { 30403 print('Usage: path/to/commonjs/modules output/dir'); 30404 return; 30405 } 30406 30407 commonJs.convertDir(args[0], args[1]); 30408 }); 30409 } else { 30410 //Just run an app 30411 30412 //Load the bundled libraries for use in the app. 30413 if (commandOption === 'lib') { 30414 loadLib(); 30415 } 30416 30417 setBaseUrl(fileName); 30418 30419 if (exists(fileName)) { 30420 exec(readFile(fileName), fileName); 30421 } else { 30422 showHelp(); 30423 } 30424 } 30425 30426}((typeof console !== 'undefined' ? console : undefined), 30427 (typeof Packages !== 'undefined' || (typeof window === 'undefined' && 30428 typeof Components !== 'undefined' && Components.interfaces) ? 30429 Array.prototype.slice.call(arguments, 0) : []), 30430 (typeof readFile !== 'undefined' ? readFile : undefined)));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.