github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/third_party/react/JSXTransformer.js (about) 1 /** 2 * JSXTransformer v0.8.0 3 */ 4 !function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSXTransformer=e():"undefined"!=typeof global?global.JSXTransformer=e():"undefined"!=typeof self&&(self.JSXTransformer=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 5 6 7 // 8 // The shims in this file are not fully implemented shims for the ES5 9 // features, but do work for the particular usecases there is in 10 // the other modules. 11 // 12 13 var toString = Object.prototype.toString; 14 var hasOwnProperty = Object.prototype.hasOwnProperty; 15 16 // Array.isArray is supported in IE9 17 function isArray(xs) { 18 return toString.call(xs) === '[object Array]'; 19 } 20 exports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray; 21 22 // Array.prototype.indexOf is supported in IE9 23 exports.indexOf = function indexOf(xs, x) { 24 if (xs.indexOf) return xs.indexOf(x); 25 for (var i = 0; i < xs.length; i++) { 26 if (x === xs[i]) return i; 27 } 28 return -1; 29 }; 30 31 // Array.prototype.filter is supported in IE9 32 exports.filter = function filter(xs, fn) { 33 if (xs.filter) return xs.filter(fn); 34 var res = []; 35 for (var i = 0; i < xs.length; i++) { 36 if (fn(xs[i], i, xs)) res.push(xs[i]); 37 } 38 return res; 39 }; 40 41 // Array.prototype.forEach is supported in IE9 42 exports.forEach = function forEach(xs, fn, self) { 43 if (xs.forEach) return xs.forEach(fn, self); 44 for (var i = 0; i < xs.length; i++) { 45 fn.call(self, xs[i], i, xs); 46 } 47 }; 48 49 // Array.prototype.map is supported in IE9 50 exports.map = function map(xs, fn) { 51 if (xs.map) return xs.map(fn); 52 var out = new Array(xs.length); 53 for (var i = 0; i < xs.length; i++) { 54 out[i] = fn(xs[i], i, xs); 55 } 56 return out; 57 }; 58 59 // Array.prototype.reduce is supported in IE9 60 exports.reduce = function reduce(array, callback, opt_initialValue) { 61 if (array.reduce) return array.reduce(callback, opt_initialValue); 62 var value, isValueSet = false; 63 64 if (2 < arguments.length) { 65 value = opt_initialValue; 66 isValueSet = true; 67 } 68 for (var i = 0, l = array.length; l > i; ++i) { 69 if (array.hasOwnProperty(i)) { 70 if (isValueSet) { 71 value = callback(value, array[i], i, array); 72 } 73 else { 74 value = array[i]; 75 isValueSet = true; 76 } 77 } 78 } 79 80 return value; 81 }; 82 83 // String.prototype.substr - negative index don't work in IE8 84 if ('ab'.substr(-1) !== 'b') { 85 exports.substr = function (str, start, length) { 86 // did we get a negative start, calculate how much it is from the beginning of the string 87 if (start < 0) start = str.length + start; 88 89 // call the original function 90 return str.substr(start, length); 91 }; 92 } else { 93 exports.substr = function (str, start, length) { 94 return str.substr(start, length); 95 }; 96 } 97 98 // String.prototype.trim is supported in IE9 99 exports.trim = function (str) { 100 if (str.trim) return str.trim(); 101 return str.replace(/^\s+|\s+$/g, ''); 102 }; 103 104 // Function.prototype.bind is supported in IE9 105 exports.bind = function () { 106 var args = Array.prototype.slice.call(arguments); 107 var fn = args.shift(); 108 if (fn.bind) return fn.bind.apply(fn, args); 109 var self = args.shift(); 110 return function () { 111 fn.apply(self, args.concat([Array.prototype.slice.call(arguments)])); 112 }; 113 }; 114 115 // Object.create is supported in IE9 116 function create(prototype, properties) { 117 var object; 118 if (prototype === null) { 119 object = { '__proto__' : null }; 120 } 121 else { 122 if (typeof prototype !== 'object') { 123 throw new TypeError( 124 'typeof prototype[' + (typeof prototype) + '] != \'object\'' 125 ); 126 } 127 var Type = function () {}; 128 Type.prototype = prototype; 129 object = new Type(); 130 object.__proto__ = prototype; 131 } 132 if (typeof properties !== 'undefined' && Object.defineProperties) { 133 Object.defineProperties(object, properties); 134 } 135 return object; 136 } 137 exports.create = typeof Object.create === 'function' ? Object.create : create; 138 139 // Object.keys and Object.getOwnPropertyNames is supported in IE9 however 140 // they do show a description and number property on Error objects 141 function notObject(object) { 142 return ((typeof object != "object" && typeof object != "function") || object === null); 143 } 144 145 function keysShim(object) { 146 if (notObject(object)) { 147 throw new TypeError("Object.keys called on a non-object"); 148 } 149 150 var result = []; 151 for (var name in object) { 152 if (hasOwnProperty.call(object, name)) { 153 result.push(name); 154 } 155 } 156 return result; 157 } 158 159 // getOwnPropertyNames is almost the same as Object.keys one key feature 160 // is that it returns hidden properties, since that can't be implemented, 161 // this feature gets reduced so it just shows the length property on arrays 162 function propertyShim(object) { 163 if (notObject(object)) { 164 throw new TypeError("Object.getOwnPropertyNames called on a non-object"); 165 } 166 167 var result = keysShim(object); 168 if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) { 169 result.push('length'); 170 } 171 return result; 172 } 173 174 var keys = typeof Object.keys === 'function' ? Object.keys : keysShim; 175 var getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ? 176 Object.getOwnPropertyNames : propertyShim; 177 178 if (new Error().hasOwnProperty('description')) { 179 var ERROR_PROPERTY_FILTER = function (obj, array) { 180 if (toString.call(obj) === '[object Error]') { 181 array = exports.filter(array, function (name) { 182 return name !== 'description' && name !== 'number' && name !== 'message'; 183 }); 184 } 185 return array; 186 }; 187 188 exports.keys = function (object) { 189 return ERROR_PROPERTY_FILTER(object, keys(object)); 190 }; 191 exports.getOwnPropertyNames = function (object) { 192 return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object)); 193 }; 194 } else { 195 exports.keys = keys; 196 exports.getOwnPropertyNames = getOwnPropertyNames; 197 } 198 199 // Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements 200 function valueObject(value, key) { 201 return { value: value[key] }; 202 } 203 204 if (typeof Object.getOwnPropertyDescriptor === 'function') { 205 try { 206 Object.getOwnPropertyDescriptor({'a': 1}, 'a'); 207 exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; 208 } catch (e) { 209 // IE8 dom element issue - use a try catch and default to valueObject 210 exports.getOwnPropertyDescriptor = function (value, key) { 211 try { 212 return Object.getOwnPropertyDescriptor(value, key); 213 } catch (e) { 214 return valueObject(value, key); 215 } 216 }; 217 } 218 } else { 219 exports.getOwnPropertyDescriptor = valueObject; 220 } 221 222 },{}],2:[function(require,module,exports){ 223 var process=require("__browserify_process");// Copyright Joyent, Inc. and other Node contributors. 224 // 225 // Permission is hereby granted, free of charge, to any person obtaining a 226 // copy of this software and associated documentation files (the 227 // "Software"), to deal in the Software without restriction, including 228 // without limitation the rights to use, copy, modify, merge, publish, 229 // distribute, sublicense, and/or sell copies of the Software, and to permit 230 // persons to whom the Software is furnished to do so, subject to the 231 // following conditions: 232 // 233 // The above copyright notice and this permission notice shall be included 234 // in all copies or substantial portions of the Software. 235 // 236 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 237 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 238 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 239 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 240 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 241 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 242 // USE OR OTHER DEALINGS IN THE SOFTWARE. 243 244 var util = require('util'); 245 var shims = require('_shims'); 246 247 // resolves . and .. elements in a path array with directory names there 248 // must be no slashes, empty elements, or device names (c:\) in the array 249 // (so also no leading and trailing slashes - it does not distinguish 250 // relative and absolute paths) 251 function normalizeArray(parts, allowAboveRoot) { 252 // if the path tries to go above the root, `up` ends up > 0 253 var up = 0; 254 for (var i = parts.length - 1; i >= 0; i--) { 255 var last = parts[i]; 256 if (last === '.') { 257 parts.splice(i, 1); 258 } else if (last === '..') { 259 parts.splice(i, 1); 260 up++; 261 } else if (up) { 262 parts.splice(i, 1); 263 up--; 264 } 265 } 266 267 // if the path is allowed to go above the root, restore leading ..s 268 if (allowAboveRoot) { 269 for (; up--; up) { 270 parts.unshift('..'); 271 } 272 } 273 274 return parts; 275 } 276 277 // Split a filename into [root, dir, basename, ext], unix version 278 // 'root' is just a slash, or nothing. 279 var splitPathRe = 280 /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; 281 var splitPath = function(filename) { 282 return splitPathRe.exec(filename).slice(1); 283 }; 284 285 // path.resolve([from ...], to) 286 // posix version 287 exports.resolve = function() { 288 var resolvedPath = '', 289 resolvedAbsolute = false; 290 291 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { 292 var path = (i >= 0) ? arguments[i] : process.cwd(); 293 294 // Skip empty and invalid entries 295 if (!util.isString(path)) { 296 throw new TypeError('Arguments to path.resolve must be strings'); 297 } else if (!path) { 298 continue; 299 } 300 301 resolvedPath = path + '/' + resolvedPath; 302 resolvedAbsolute = path.charAt(0) === '/'; 303 } 304 305 // At this point the path should be resolved to a full absolute path, but 306 // handle relative paths to be safe (might happen when process.cwd() fails) 307 308 // Normalize the path 309 resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) { 310 return !!p; 311 }), !resolvedAbsolute).join('/'); 312 313 return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; 314 }; 315 316 // path.normalize(path) 317 // posix version 318 exports.normalize = function(path) { 319 var isAbsolute = exports.isAbsolute(path), 320 trailingSlash = shims.substr(path, -1) === '/'; 321 322 // Normalize the path 323 path = normalizeArray(shims.filter(path.split('/'), function(p) { 324 return !!p; 325 }), !isAbsolute).join('/'); 326 327 if (!path && !isAbsolute) { 328 path = '.'; 329 } 330 if (path && trailingSlash) { 331 path += '/'; 332 } 333 334 return (isAbsolute ? '/' : '') + path; 335 }; 336 337 // posix version 338 exports.isAbsolute = function(path) { 339 return path.charAt(0) === '/'; 340 }; 341 342 // posix version 343 exports.join = function() { 344 var paths = Array.prototype.slice.call(arguments, 0); 345 return exports.normalize(shims.filter(paths, function(p, index) { 346 if (!util.isString(p)) { 347 throw new TypeError('Arguments to path.join must be strings'); 348 } 349 return p; 350 }).join('/')); 351 }; 352 353 354 // path.relative(from, to) 355 // posix version 356 exports.relative = function(from, to) { 357 from = exports.resolve(from).substr(1); 358 to = exports.resolve(to).substr(1); 359 360 function trim(arr) { 361 var start = 0; 362 for (; start < arr.length; start++) { 363 if (arr[start] !== '') break; 364 } 365 366 var end = arr.length - 1; 367 for (; end >= 0; end--) { 368 if (arr[end] !== '') break; 369 } 370 371 if (start > end) return []; 372 return arr.slice(start, end - start + 1); 373 } 374 375 var fromParts = trim(from.split('/')); 376 var toParts = trim(to.split('/')); 377 378 var length = Math.min(fromParts.length, toParts.length); 379 var samePartsLength = length; 380 for (var i = 0; i < length; i++) { 381 if (fromParts[i] !== toParts[i]) { 382 samePartsLength = i; 383 break; 384 } 385 } 386 387 var outputParts = []; 388 for (var i = samePartsLength; i < fromParts.length; i++) { 389 outputParts.push('..'); 390 } 391 392 outputParts = outputParts.concat(toParts.slice(samePartsLength)); 393 394 return outputParts.join('/'); 395 }; 396 397 exports.sep = '/'; 398 exports.delimiter = ':'; 399 400 exports.dirname = function(path) { 401 var result = splitPath(path), 402 root = result[0], 403 dir = result[1]; 404 405 if (!root && !dir) { 406 // No dirname whatsoever 407 return '.'; 408 } 409 410 if (dir) { 411 // It has a dirname, strip trailing slash 412 dir = dir.substr(0, dir.length - 1); 413 } 414 415 return root + dir; 416 }; 417 418 419 exports.basename = function(path, ext) { 420 var f = splitPath(path)[2]; 421 // TODO: make this comparison case-insensitive on windows? 422 if (ext && f.substr(-1 * ext.length) === ext) { 423 f = f.substr(0, f.length - ext.length); 424 } 425 return f; 426 }; 427 428 429 exports.extname = function(path) { 430 return splitPath(path)[3]; 431 }; 432 433 },{"__browserify_process":4,"_shims":1,"util":3}],3:[function(require,module,exports){ 434 // Copyright Joyent, Inc. and other Node contributors. 435 // 436 // Permission is hereby granted, free of charge, to any person obtaining a 437 // copy of this software and associated documentation files (the 438 // "Software"), to deal in the Software without restriction, including 439 // without limitation the rights to use, copy, modify, merge, publish, 440 // distribute, sublicense, and/or sell copies of the Software, and to permit 441 // persons to whom the Software is furnished to do so, subject to the 442 // following conditions: 443 // 444 // The above copyright notice and this permission notice shall be included 445 // in all copies or substantial portions of the Software. 446 // 447 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 448 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 449 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 450 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 451 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 452 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 453 // USE OR OTHER DEALINGS IN THE SOFTWARE. 454 455 var shims = require('_shims'); 456 457 var formatRegExp = /%[sdj%]/g; 458 exports.format = function(f) { 459 if (!isString(f)) { 460 var objects = []; 461 for (var i = 0; i < arguments.length; i++) { 462 objects.push(inspect(arguments[i])); 463 } 464 return objects.join(' '); 465 } 466 467 var i = 1; 468 var args = arguments; 469 var len = args.length; 470 var str = String(f).replace(formatRegExp, function(x) { 471 if (x === '%%') return '%'; 472 if (i >= len) return x; 473 switch (x) { 474 case '%s': return String(args[i++]); 475 case '%d': return Number(args[i++]); 476 case '%j': 477 try { 478 return JSON.stringify(args[i++]); 479 } catch (_) { 480 return '[Circular]'; 481 } 482 default: 483 return x; 484 } 485 }); 486 for (var x = args[i]; i < len; x = args[++i]) { 487 if (isNull(x) || !isObject(x)) { 488 str += ' ' + x; 489 } else { 490 str += ' ' + inspect(x); 491 } 492 } 493 return str; 494 }; 495 496 /** 497 * Echos the value of a value. Trys to print the value out 498 * in the best way possible given the different types. 499 * 500 * @param {Object} obj The object to print out. 501 * @param {Object} opts Optional options object that alters the output. 502 */ 503 /* legacy: obj, showHidden, depth, colors*/ 504 function inspect(obj, opts) { 505 // default options 506 var ctx = { 507 seen: [], 508 stylize: stylizeNoColor 509 }; 510 // legacy... 511 if (arguments.length >= 3) ctx.depth = arguments[2]; 512 if (arguments.length >= 4) ctx.colors = arguments[3]; 513 if (isBoolean(opts)) { 514 // legacy... 515 ctx.showHidden = opts; 516 } else if (opts) { 517 // got an "options" object 518 exports._extend(ctx, opts); 519 } 520 // set default options 521 if (isUndefined(ctx.showHidden)) ctx.showHidden = false; 522 if (isUndefined(ctx.depth)) ctx.depth = 2; 523 if (isUndefined(ctx.colors)) ctx.colors = false; 524 if (isUndefined(ctx.customInspect)) ctx.customInspect = true; 525 if (ctx.colors) ctx.stylize = stylizeWithColor; 526 return formatValue(ctx, obj, ctx.depth); 527 } 528 exports.inspect = inspect; 529 530 531 // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics 532 inspect.colors = { 533 'bold' : [1, 22], 534 'italic' : [3, 23], 535 'underline' : [4, 24], 536 'inverse' : [7, 27], 537 'white' : [37, 39], 538 'grey' : [90, 39], 539 'black' : [30, 39], 540 'blue' : [34, 39], 541 'cyan' : [36, 39], 542 'green' : [32, 39], 543 'magenta' : [35, 39], 544 'red' : [31, 39], 545 'yellow' : [33, 39] 546 }; 547 548 // Don't use 'blue' not visible on cmd.exe 549 inspect.styles = { 550 'special': 'cyan', 551 'number': 'yellow', 552 'boolean': 'yellow', 553 'undefined': 'grey', 554 'null': 'bold', 555 'string': 'green', 556 'date': 'magenta', 557 // "name": intentionally not styling 558 'regexp': 'red' 559 }; 560 561 562 function stylizeWithColor(str, styleType) { 563 var style = inspect.styles[styleType]; 564 565 if (style) { 566 return '\u001b[' + inspect.colors[style][0] + 'm' + str + 567 '\u001b[' + inspect.colors[style][1] + 'm'; 568 } else { 569 return str; 570 } 571 } 572 573 574 function stylizeNoColor(str, styleType) { 575 return str; 576 } 577 578 579 function arrayToHash(array) { 580 var hash = {}; 581 582 shims.forEach(array, function(val, idx) { 583 hash[val] = true; 584 }); 585 586 return hash; 587 } 588 589 590 function formatValue(ctx, value, recurseTimes) { 591 // Provide a hook for user-specified inspect functions. 592 // Check that value is an object with an inspect function on it 593 if (ctx.customInspect && 594 value && 595 isFunction(value.inspect) && 596 // Filter out the util module, it's inspect function is special 597 value.inspect !== exports.inspect && 598 // Also filter out any prototype objects using the circular check. 599 !(value.constructor && value.constructor.prototype === value)) { 600 var ret = value.inspect(recurseTimes); 601 if (!isString(ret)) { 602 ret = formatValue(ctx, ret, recurseTimes); 603 } 604 return ret; 605 } 606 607 // Primitive types cannot have properties 608 var primitive = formatPrimitive(ctx, value); 609 if (primitive) { 610 return primitive; 611 } 612 613 // Look up the keys of the object. 614 var keys = shims.keys(value); 615 var visibleKeys = arrayToHash(keys); 616 617 if (ctx.showHidden) { 618 keys = shims.getOwnPropertyNames(value); 619 } 620 621 // Some type of object without properties can be shortcutted. 622 if (keys.length === 0) { 623 if (isFunction(value)) { 624 var name = value.name ? ': ' + value.name : ''; 625 return ctx.stylize('[Function' + name + ']', 'special'); 626 } 627 if (isRegExp(value)) { 628 return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); 629 } 630 if (isDate(value)) { 631 return ctx.stylize(Date.prototype.toString.call(value), 'date'); 632 } 633 if (isError(value)) { 634 return formatError(value); 635 } 636 } 637 638 var base = '', array = false, braces = ['{', '}']; 639 640 // Make Array say that they are Array 641 if (isArray(value)) { 642 array = true; 643 braces = ['[', ']']; 644 } 645 646 // Make functions say that they are functions 647 if (isFunction(value)) { 648 var n = value.name ? ': ' + value.name : ''; 649 base = ' [Function' + n + ']'; 650 } 651 652 // Make RegExps say that they are RegExps 653 if (isRegExp(value)) { 654 base = ' ' + RegExp.prototype.toString.call(value); 655 } 656 657 // Make dates with properties first say the date 658 if (isDate(value)) { 659 base = ' ' + Date.prototype.toUTCString.call(value); 660 } 661 662 // Make error with message first say the error 663 if (isError(value)) { 664 base = ' ' + formatError(value); 665 } 666 667 if (keys.length === 0 && (!array || value.length == 0)) { 668 return braces[0] + base + braces[1]; 669 } 670 671 if (recurseTimes < 0) { 672 if (isRegExp(value)) { 673 return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); 674 } else { 675 return ctx.stylize('[Object]', 'special'); 676 } 677 } 678 679 ctx.seen.push(value); 680 681 var output; 682 if (array) { 683 output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); 684 } else { 685 output = keys.map(function(key) { 686 return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); 687 }); 688 } 689 690 ctx.seen.pop(); 691 692 return reduceToSingleString(output, base, braces); 693 } 694 695 696 function formatPrimitive(ctx, value) { 697 if (isUndefined(value)) 698 return ctx.stylize('undefined', 'undefined'); 699 if (isString(value)) { 700 var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') 701 .replace(/'/g, "\\'") 702 .replace(/\\"/g, '"') + '\''; 703 return ctx.stylize(simple, 'string'); 704 } 705 if (isNumber(value)) 706 return ctx.stylize('' + value, 'number'); 707 if (isBoolean(value)) 708 return ctx.stylize('' + value, 'boolean'); 709 // For some reason typeof null is "object", so special case here. 710 if (isNull(value)) 711 return ctx.stylize('null', 'null'); 712 } 713 714 715 function formatError(value) { 716 return '[' + Error.prototype.toString.call(value) + ']'; 717 } 718 719 720 function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { 721 var output = []; 722 for (var i = 0, l = value.length; i < l; ++i) { 723 if (hasOwnProperty(value, String(i))) { 724 output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, 725 String(i), true)); 726 } else { 727 output.push(''); 728 } 729 } 730 731 shims.forEach(keys, function(key) { 732 if (!key.match(/^\d+$/)) { 733 output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, 734 key, true)); 735 } 736 }); 737 return output; 738 } 739 740 741 function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { 742 var name, str, desc; 743 desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] }; 744 if (desc.get) { 745 if (desc.set) { 746 str = ctx.stylize('[Getter/Setter]', 'special'); 747 } else { 748 str = ctx.stylize('[Getter]', 'special'); 749 } 750 } else { 751 if (desc.set) { 752 str = ctx.stylize('[Setter]', 'special'); 753 } 754 } 755 756 if (!hasOwnProperty(visibleKeys, key)) { 757 name = '[' + key + ']'; 758 } 759 if (!str) { 760 if (shims.indexOf(ctx.seen, desc.value) < 0) { 761 if (isNull(recurseTimes)) { 762 str = formatValue(ctx, desc.value, null); 763 } else { 764 str = formatValue(ctx, desc.value, recurseTimes - 1); 765 } 766 if (str.indexOf('\n') > -1) { 767 if (array) { 768 str = str.split('\n').map(function(line) { 769 return ' ' + line; 770 }).join('\n').substr(2); 771 } else { 772 str = '\n' + str.split('\n').map(function(line) { 773 return ' ' + line; 774 }).join('\n'); 775 } 776 } 777 } else { 778 str = ctx.stylize('[Circular]', 'special'); 779 } 780 } 781 if (isUndefined(name)) { 782 if (array && key.match(/^\d+$/)) { 783 return str; 784 } 785 name = JSON.stringify('' + key); 786 if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { 787 name = name.substr(1, name.length - 2); 788 name = ctx.stylize(name, 'name'); 789 } else { 790 name = name.replace(/'/g, "\\'") 791 .replace(/\\"/g, '"') 792 .replace(/(^"|"$)/g, "'"); 793 name = ctx.stylize(name, 'string'); 794 } 795 } 796 797 return name + ': ' + str; 798 } 799 800 801 function reduceToSingleString(output, base, braces) { 802 var numLinesEst = 0; 803 var length = shims.reduce(output, function(prev, cur) { 804 numLinesEst++; 805 if (cur.indexOf('\n') >= 0) numLinesEst++; 806 return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; 807 }, 0); 808 809 if (length > 60) { 810 return braces[0] + 811 (base === '' ? '' : base + '\n ') + 812 ' ' + 813 output.join(',\n ') + 814 ' ' + 815 braces[1]; 816 } 817 818 return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; 819 } 820 821 822 // NOTE: These type checking functions intentionally don't use `instanceof` 823 // because it is fragile and can be easily faked with `Object.create()`. 824 function isArray(ar) { 825 return shims.isArray(ar); 826 } 827 exports.isArray = isArray; 828 829 function isBoolean(arg) { 830 return typeof arg === 'boolean'; 831 } 832 exports.isBoolean = isBoolean; 833 834 function isNull(arg) { 835 return arg === null; 836 } 837 exports.isNull = isNull; 838 839 function isNullOrUndefined(arg) { 840 return arg == null; 841 } 842 exports.isNullOrUndefined = isNullOrUndefined; 843 844 function isNumber(arg) { 845 return typeof arg === 'number'; 846 } 847 exports.isNumber = isNumber; 848 849 function isString(arg) { 850 return typeof arg === 'string'; 851 } 852 exports.isString = isString; 853 854 function isSymbol(arg) { 855 return typeof arg === 'symbol'; 856 } 857 exports.isSymbol = isSymbol; 858 859 function isUndefined(arg) { 860 return arg === void 0; 861 } 862 exports.isUndefined = isUndefined; 863 864 function isRegExp(re) { 865 return isObject(re) && objectToString(re) === '[object RegExp]'; 866 } 867 exports.isRegExp = isRegExp; 868 869 function isObject(arg) { 870 return typeof arg === 'object' && arg; 871 } 872 exports.isObject = isObject; 873 874 function isDate(d) { 875 return isObject(d) && objectToString(d) === '[object Date]'; 876 } 877 exports.isDate = isDate; 878 879 function isError(e) { 880 return isObject(e) && objectToString(e) === '[object Error]'; 881 } 882 exports.isError = isError; 883 884 function isFunction(arg) { 885 return typeof arg === 'function'; 886 } 887 exports.isFunction = isFunction; 888 889 function isPrimitive(arg) { 890 return arg === null || 891 typeof arg === 'boolean' || 892 typeof arg === 'number' || 893 typeof arg === 'string' || 894 typeof arg === 'symbol' || // ES6 symbol 895 typeof arg === 'undefined'; 896 } 897 exports.isPrimitive = isPrimitive; 898 899 function isBuffer(arg) { 900 return arg && typeof arg === 'object' 901 && typeof arg.copy === 'function' 902 && typeof arg.fill === 'function' 903 && typeof arg.binarySlice === 'function' 904 ; 905 } 906 exports.isBuffer = isBuffer; 907 908 function objectToString(o) { 909 return Object.prototype.toString.call(o); 910 } 911 912 913 function pad(n) { 914 return n < 10 ? '0' + n.toString(10) : n.toString(10); 915 } 916 917 918 var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 919 'Oct', 'Nov', 'Dec']; 920 921 // 26 Feb 16:19:34 922 function timestamp() { 923 var d = new Date(); 924 var time = [pad(d.getHours()), 925 pad(d.getMinutes()), 926 pad(d.getSeconds())].join(':'); 927 return [d.getDate(), months[d.getMonth()], time].join(' '); 928 } 929 930 931 // log is just a thin wrapper to console.log that prepends a timestamp 932 exports.log = function() { 933 console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); 934 }; 935 936 937 /** 938 * Inherit the prototype methods from one constructor into another. 939 * 940 * The Function.prototype.inherits from lang.js rewritten as a standalone 941 * function (not on Function.prototype). NOTE: If this file is to be loaded 942 * during bootstrapping this function needs to be rewritten using some native 943 * functions as prototype setup using normal JavaScript does not work as 944 * expected during bootstrapping (see mirror.js in r114903). 945 * 946 * @param {function} ctor Constructor function which needs to inherit the 947 * prototype. 948 * @param {function} superCtor Constructor function to inherit prototype from. 949 */ 950 exports.inherits = function(ctor, superCtor) { 951 ctor.super_ = superCtor; 952 ctor.prototype = shims.create(superCtor.prototype, { 953 constructor: { 954 value: ctor, 955 enumerable: false, 956 writable: true, 957 configurable: true 958 } 959 }); 960 }; 961 962 exports._extend = function(origin, add) { 963 // Don't do anything if add isn't an object 964 if (!add || !isObject(add)) return origin; 965 966 var keys = shims.keys(add); 967 var i = keys.length; 968 while (i--) { 969 origin[keys[i]] = add[keys[i]]; 970 } 971 return origin; 972 }; 973 974 function hasOwnProperty(obj, prop) { 975 return Object.prototype.hasOwnProperty.call(obj, prop); 976 } 977 978 },{"_shims":1}],4:[function(require,module,exports){ 979 // shim for using process in browser 980 981 var process = module.exports = {}; 982 983 process.nextTick = (function () { 984 var canSetImmediate = typeof window !== 'undefined' 985 && window.setImmediate; 986 var canPost = typeof window !== 'undefined' 987 && window.postMessage && window.addEventListener 988 ; 989 990 if (canSetImmediate) { 991 return function (f) { return window.setImmediate(f) }; 992 } 993 994 if (canPost) { 995 var queue = []; 996 window.addEventListener('message', function (ev) { 997 if (ev.source === window && ev.data === 'process-tick') { 998 ev.stopPropagation(); 999 if (queue.length > 0) { 1000 var fn = queue.shift(); 1001 fn(); 1002 } 1003 } 1004 }, true); 1005 1006 return function nextTick(fn) { 1007 queue.push(fn); 1008 window.postMessage('process-tick', '*'); 1009 }; 1010 } 1011 1012 return function nextTick(fn) { 1013 setTimeout(fn, 0); 1014 }; 1015 })(); 1016 1017 process.title = 'browser'; 1018 process.browser = true; 1019 process.env = {}; 1020 process.argv = []; 1021 1022 process.binding = function (name) { 1023 throw new Error('process.binding is not supported'); 1024 } 1025 1026 // TODO(shtylman) 1027 process.cwd = function () { return '/' }; 1028 process.chdir = function (dir) { 1029 throw new Error('process.chdir is not supported'); 1030 }; 1031 1032 },{}],5:[function(require,module,exports){ 1033 /* 1034 Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com> 1035 Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com> 1036 Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com> 1037 Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be> 1038 Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl> 1039 Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com> 1040 Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com> 1041 Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com> 1042 Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com> 1043 1044 Redistribution and use in source and binary forms, with or without 1045 modification, are permitted provided that the following conditions are met: 1046 1047 * Redistributions of source code must retain the above copyright 1048 notice, this list of conditions and the following disclaimer. 1049 * Redistributions in binary form must reproduce the above copyright 1050 notice, this list of conditions and the following disclaimer in the 1051 documentation and/or other materials provided with the distribution. 1052 1053 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1054 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1055 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1056 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 1057 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1058 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1059 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 1060 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1061 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1062 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1063 */ 1064 1065 /*jslint bitwise:true plusplus:true */ 1066 /*global esprima:true, define:true, exports:true, window: true, 1067 throwError: true, generateStatement: true, peek: true, 1068 parseAssignmentExpression: true, parseBlock: true, 1069 parseClassExpression: true, parseClassDeclaration: true, parseExpression: true, 1070 parseForStatement: true, 1071 parseFunctionDeclaration: true, parseFunctionExpression: true, 1072 parseFunctionSourceElements: true, parseVariableIdentifier: true, 1073 parseImportSpecifier: true, 1074 parseLeftHandSideExpression: true, parseParams: true, validateParam: true, 1075 parseSpreadOrAssignmentExpression: true, 1076 parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true, 1077 advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true, 1078 scanXJSStringLiteral: true, scanXJSIdentifier: true, 1079 parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpressionContainer: true, parseXJSEmptyExpression: true, 1080 parseTypeAnnotation: true, parseTypeAnnotatableIdentifier: true, 1081 parseYieldExpression: true 1082 */ 1083 1084 (function (root, factory) { 1085 'use strict'; 1086 1087 // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, 1088 // Rhino, and plain browser loading. 1089 if (typeof define === 'function' && define.amd) { 1090 define(['exports'], factory); 1091 } else if (typeof exports !== 'undefined') { 1092 factory(exports); 1093 } else { 1094 factory((root.esprima = {})); 1095 } 1096 }(this, function (exports) { 1097 'use strict'; 1098 1099 var Token, 1100 TokenName, 1101 FnExprTokens, 1102 Syntax, 1103 PropertyKind, 1104 Messages, 1105 Regex, 1106 SyntaxTreeDelegate, 1107 XHTMLEntities, 1108 ClassPropertyType, 1109 source, 1110 strict, 1111 index, 1112 lineNumber, 1113 lineStart, 1114 length, 1115 delegate, 1116 lookahead, 1117 state, 1118 extra; 1119 1120 Token = { 1121 BooleanLiteral: 1, 1122 EOF: 2, 1123 Identifier: 3, 1124 Keyword: 4, 1125 NullLiteral: 5, 1126 NumericLiteral: 6, 1127 Punctuator: 7, 1128 StringLiteral: 8, 1129 RegularExpression: 9, 1130 Template: 10, 1131 XJSIdentifier: 11, 1132 XJSText: 12 1133 }; 1134 1135 TokenName = {}; 1136 TokenName[Token.BooleanLiteral] = 'Boolean'; 1137 TokenName[Token.EOF] = '<end>'; 1138 TokenName[Token.Identifier] = 'Identifier'; 1139 TokenName[Token.Keyword] = 'Keyword'; 1140 TokenName[Token.NullLiteral] = 'Null'; 1141 TokenName[Token.NumericLiteral] = 'Numeric'; 1142 TokenName[Token.Punctuator] = 'Punctuator'; 1143 TokenName[Token.StringLiteral] = 'String'; 1144 TokenName[Token.XJSIdentifier] = 'XJSIdentifier'; 1145 TokenName[Token.XJSText] = 'XJSText'; 1146 TokenName[Token.RegularExpression] = 'RegularExpression'; 1147 1148 // A function following one of those tokens is an expression. 1149 FnExprTokens = ["(", "{", "[", "in", "typeof", "instanceof", "new", 1150 "return", "case", "delete", "throw", "void", 1151 // assignment operators 1152 "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", 1153 "&=", "|=", "^=", ",", 1154 // binary/unary operators 1155 "+", "-", "*", "/", "%", "++", "--", "<<", ">>", ">>>", "&", 1156 "|", "^", "!", "~", "&&", "||", "?", ":", "===", "==", ">=", 1157 "<=", "<", ">", "!=", "!=="]; 1158 1159 Syntax = { 1160 ArrayExpression: 'ArrayExpression', 1161 ArrayPattern: 'ArrayPattern', 1162 ArrowFunctionExpression: 'ArrowFunctionExpression', 1163 AssignmentExpression: 'AssignmentExpression', 1164 BinaryExpression: 'BinaryExpression', 1165 BlockStatement: 'BlockStatement', 1166 BreakStatement: 'BreakStatement', 1167 CallExpression: 'CallExpression', 1168 CatchClause: 'CatchClause', 1169 ClassBody: 'ClassBody', 1170 ClassDeclaration: 'ClassDeclaration', 1171 ClassExpression: 'ClassExpression', 1172 ClassHeritage: 'ClassHeritage', 1173 ComprehensionBlock: 'ComprehensionBlock', 1174 ComprehensionExpression: 'ComprehensionExpression', 1175 ConditionalExpression: 'ConditionalExpression', 1176 ContinueStatement: 'ContinueStatement', 1177 DebuggerStatement: 'DebuggerStatement', 1178 DoWhileStatement: 'DoWhileStatement', 1179 EmptyStatement: 'EmptyStatement', 1180 ExportDeclaration: 'ExportDeclaration', 1181 ExportBatchSpecifier: 'ExportBatchSpecifier', 1182 ExportSpecifier: 'ExportSpecifier', 1183 ExpressionStatement: 'ExpressionStatement', 1184 ForInStatement: 'ForInStatement', 1185 ForOfStatement: 'ForOfStatement', 1186 ForStatement: 'ForStatement', 1187 FunctionDeclaration: 'FunctionDeclaration', 1188 FunctionExpression: 'FunctionExpression', 1189 Identifier: 'Identifier', 1190 IfStatement: 'IfStatement', 1191 ImportDeclaration: 'ImportDeclaration', 1192 ImportSpecifier: 'ImportSpecifier', 1193 LabeledStatement: 'LabeledStatement', 1194 Literal: 'Literal', 1195 LogicalExpression: 'LogicalExpression', 1196 MemberExpression: 'MemberExpression', 1197 MethodDefinition: 'MethodDefinition', 1198 ModuleDeclaration: 'ModuleDeclaration', 1199 NewExpression: 'NewExpression', 1200 ObjectExpression: 'ObjectExpression', 1201 ObjectPattern: 'ObjectPattern', 1202 Program: 'Program', 1203 Property: 'Property', 1204 ReturnStatement: 'ReturnStatement', 1205 SequenceExpression: 'SequenceExpression', 1206 SpreadElement: 'SpreadElement', 1207 SwitchCase: 'SwitchCase', 1208 SwitchStatement: 'SwitchStatement', 1209 TaggedTemplateExpression: 'TaggedTemplateExpression', 1210 TemplateElement: 'TemplateElement', 1211 TemplateLiteral: 'TemplateLiteral', 1212 ThisExpression: 'ThisExpression', 1213 ThrowStatement: 'ThrowStatement', 1214 TryStatement: 'TryStatement', 1215 TypeAnnotatedIdentifier: 'TypeAnnotatedIdentifier', 1216 TypeAnnotation: 'TypeAnnotation', 1217 UnaryExpression: 'UnaryExpression', 1218 UpdateExpression: 'UpdateExpression', 1219 VariableDeclaration: 'VariableDeclaration', 1220 VariableDeclarator: 'VariableDeclarator', 1221 WhileStatement: 'WhileStatement', 1222 WithStatement: 'WithStatement', 1223 XJSIdentifier: 'XJSIdentifier', 1224 XJSEmptyExpression: 'XJSEmptyExpression', 1225 XJSExpressionContainer: 'XJSExpressionContainer', 1226 XJSElement: 'XJSElement', 1227 XJSClosingElement: 'XJSClosingElement', 1228 XJSOpeningElement: 'XJSOpeningElement', 1229 XJSAttribute: 'XJSAttribute', 1230 XJSText: 'XJSText', 1231 YieldExpression: 'YieldExpression' 1232 }; 1233 1234 PropertyKind = { 1235 Data: 1, 1236 Get: 2, 1237 Set: 4 1238 }; 1239 1240 ClassPropertyType = { 1241 static: 'static', 1242 prototype: 'prototype' 1243 }; 1244 1245 // Error messages should be identical to V8. 1246 Messages = { 1247 UnexpectedToken: 'Unexpected token %0', 1248 UnexpectedNumber: 'Unexpected number', 1249 UnexpectedString: 'Unexpected string', 1250 UnexpectedIdentifier: 'Unexpected identifier', 1251 UnexpectedReserved: 'Unexpected reserved word', 1252 UnexpectedTemplate: 'Unexpected quasi %0', 1253 UnexpectedEOS: 'Unexpected end of input', 1254 NewlineAfterThrow: 'Illegal newline after throw', 1255 InvalidRegExp: 'Invalid regular expression', 1256 UnterminatedRegExp: 'Invalid regular expression: missing /', 1257 InvalidLHSInAssignment: 'Invalid left-hand side in assignment', 1258 InvalidLHSInFormalsList: 'Invalid left-hand side in formals list', 1259 InvalidLHSInForIn: 'Invalid left-hand side in for-in', 1260 MultipleDefaultsInSwitch: 'More than one default clause in switch statement', 1261 NoCatchOrFinally: 'Missing catch or finally after try', 1262 UnknownLabel: 'Undefined label \'%0\'', 1263 Redeclaration: '%0 \'%1\' has already been declared', 1264 IllegalContinue: 'Illegal continue statement', 1265 IllegalBreak: 'Illegal break statement', 1266 IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition', 1267 IllegalReturn: 'Illegal return statement', 1268 IllegalYield: 'Illegal yield expression', 1269 IllegalSpread: 'Illegal spread element', 1270 StrictModeWith: 'Strict mode code may not include a with statement', 1271 StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', 1272 StrictVarName: 'Variable name may not be eval or arguments in strict mode', 1273 StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', 1274 StrictParamDupe: 'Strict mode function may not have duplicate parameter names', 1275 ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list', 1276 DefaultRestParameter: 'Rest parameter can not have a default value', 1277 ElementAfterSpreadElement: 'Spread must be the final element of an element list', 1278 ObjectPatternAsRestParameter: 'Invalid rest parameter', 1279 ObjectPatternAsSpread: 'Invalid spread argument', 1280 StrictFunctionName: 'Function name may not be eval or arguments in strict mode', 1281 StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', 1282 StrictDelete: 'Delete of an unqualified identifier in strict mode.', 1283 StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', 1284 AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', 1285 AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', 1286 StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', 1287 StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', 1288 StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', 1289 StrictReservedWord: 'Use of future reserved word in strict mode', 1290 NewlineAfterModule: 'Illegal newline after module', 1291 NoFromAfterImport: 'Missing from after import', 1292 InvalidModuleSpecifier: 'Invalid module specifier', 1293 NestedModule: 'Module declaration can not be nested', 1294 NoYieldInGenerator: 'Missing yield in generator', 1295 NoUnintializedConst: 'Const must be initialized', 1296 ComprehensionRequiresBlock: 'Comprehension must have at least one block', 1297 ComprehensionError: 'Comprehension Error', 1298 EachNotAllowed: 'Each is not supported', 1299 InvalidXJSTagName: 'XJS tag name can not be empty', 1300 InvalidXJSAttributeValue: 'XJS value should be either an expression or a quoted XJS text', 1301 ExpectedXJSClosingTag: 'Expected corresponding XJS closing tag for %0' 1302 }; 1303 1304 // See also tools/generate-unicode-regex.py. 1305 Regex = { 1306 NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), 1307 NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') 1308 }; 1309 1310 // Ensure the condition is true, otherwise throw an error. 1311 // This is only to have a better contract semantic, i.e. another safety net 1312 // to catch a logic error. The condition shall be fulfilled in normal case. 1313 // Do NOT use this to enforce a certain condition on any user input. 1314 1315 function assert(condition, message) { 1316 if (!condition) { 1317 throw new Error('ASSERT: ' + message); 1318 } 1319 } 1320 1321 function isDecimalDigit(ch) { 1322 return (ch >= 48 && ch <= 57); // 0..9 1323 } 1324 1325 function isHexDigit(ch) { 1326 return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; 1327 } 1328 1329 function isOctalDigit(ch) { 1330 return '01234567'.indexOf(ch) >= 0; 1331 } 1332 1333 1334 // 7.2 White Space 1335 1336 function isWhiteSpace(ch) { 1337 return (ch === 32) || // space 1338 (ch === 9) || // tab 1339 (ch === 0xB) || 1340 (ch === 0xC) || 1341 (ch === 0xA0) || 1342 (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0); 1343 } 1344 1345 // 7.3 Line Terminators 1346 1347 function isLineTerminator(ch) { 1348 return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029); 1349 } 1350 1351 // 7.6 Identifier Names and Identifiers 1352 1353 function isIdentifierStart(ch) { 1354 return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) 1355 (ch >= 65 && ch <= 90) || // A..Z 1356 (ch >= 97 && ch <= 122) || // a..z 1357 (ch === 92) || // \ (backslash) 1358 ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); 1359 } 1360 1361 function isIdentifierPart(ch) { 1362 return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) 1363 (ch >= 65 && ch <= 90) || // A..Z 1364 (ch >= 97 && ch <= 122) || // a..z 1365 (ch >= 48 && ch <= 57) || // 0..9 1366 (ch === 92) || // \ (backslash) 1367 ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); 1368 } 1369 1370 // 7.6.1.2 Future Reserved Words 1371 1372 function isFutureReservedWord(id) { 1373 switch (id) { 1374 case 'class': 1375 case 'enum': 1376 case 'export': 1377 case 'extends': 1378 case 'import': 1379 case 'super': 1380 return true; 1381 default: 1382 return false; 1383 } 1384 } 1385 1386 function isStrictModeReservedWord(id) { 1387 switch (id) { 1388 case 'implements': 1389 case 'interface': 1390 case 'package': 1391 case 'private': 1392 case 'protected': 1393 case 'public': 1394 case 'static': 1395 case 'yield': 1396 case 'let': 1397 return true; 1398 default: 1399 return false; 1400 } 1401 } 1402 1403 function isRestrictedWord(id) { 1404 return id === 'eval' || id === 'arguments'; 1405 } 1406 1407 // 7.6.1.1 Keywords 1408 1409 function isKeyword(id) { 1410 if (strict && isStrictModeReservedWord(id)) { 1411 return true; 1412 } 1413 1414 // 'const' is specialized as Keyword in V8. 1415 // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next. 1416 // Some others are from future reserved words. 1417 1418 switch (id.length) { 1419 case 2: 1420 return (id === 'if') || (id === 'in') || (id === 'do'); 1421 case 3: 1422 return (id === 'var') || (id === 'for') || (id === 'new') || 1423 (id === 'try') || (id === 'let'); 1424 case 4: 1425 return (id === 'this') || (id === 'else') || (id === 'case') || 1426 (id === 'void') || (id === 'with') || (id === 'enum'); 1427 case 5: 1428 return (id === 'while') || (id === 'break') || (id === 'catch') || 1429 (id === 'throw') || (id === 'const') || (id === 'yield') || 1430 (id === 'class') || (id === 'super'); 1431 case 6: 1432 return (id === 'return') || (id === 'typeof') || (id === 'delete') || 1433 (id === 'switch') || (id === 'export') || (id === 'import'); 1434 case 7: 1435 return (id === 'default') || (id === 'finally') || (id === 'extends'); 1436 case 8: 1437 return (id === 'function') || (id === 'continue') || (id === 'debugger'); 1438 case 10: 1439 return (id === 'instanceof'); 1440 default: 1441 return false; 1442 } 1443 } 1444 1445 // 7.4 Comments 1446 1447 function skipComment() { 1448 var ch, blockComment, lineComment; 1449 1450 blockComment = false; 1451 lineComment = false; 1452 1453 while (index < length) { 1454 ch = source.charCodeAt(index); 1455 1456 if (lineComment) { 1457 ++index; 1458 if (isLineTerminator(ch)) { 1459 lineComment = false; 1460 if (ch === 13 && source.charCodeAt(index) === 10) { 1461 ++index; 1462 } 1463 ++lineNumber; 1464 lineStart = index; 1465 } 1466 } else if (blockComment) { 1467 if (isLineTerminator(ch)) { 1468 if (ch === 13 && source.charCodeAt(index + 1) === 10) { 1469 ++index; 1470 } 1471 ++lineNumber; 1472 ++index; 1473 lineStart = index; 1474 if (index >= length) { 1475 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1476 } 1477 } else { 1478 ch = source.charCodeAt(index++); 1479 if (index >= length) { 1480 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1481 } 1482 // Block comment ends with '*/' (char #42, char #47). 1483 if (ch === 42) { 1484 ch = source.charCodeAt(index); 1485 if (ch === 47) { 1486 ++index; 1487 blockComment = false; 1488 } 1489 } 1490 } 1491 } else if (ch === 47) { 1492 ch = source.charCodeAt(index + 1); 1493 // Line comment starts with '//' (char #47, char #47). 1494 if (ch === 47) { 1495 index += 2; 1496 lineComment = true; 1497 } else if (ch === 42) { 1498 // Block comment starts with '/*' (char #47, char #42). 1499 index += 2; 1500 blockComment = true; 1501 if (index >= length) { 1502 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1503 } 1504 } else { 1505 break; 1506 } 1507 } else if (isWhiteSpace(ch)) { 1508 ++index; 1509 } else if (isLineTerminator(ch)) { 1510 ++index; 1511 if (ch === 13 && source.charCodeAt(index) === 10) { 1512 ++index; 1513 } 1514 ++lineNumber; 1515 lineStart = index; 1516 } else { 1517 break; 1518 } 1519 } 1520 } 1521 1522 function scanHexEscape(prefix) { 1523 var i, len, ch, code = 0; 1524 1525 len = (prefix === 'u') ? 4 : 2; 1526 for (i = 0; i < len; ++i) { 1527 if (index < length && isHexDigit(source[index])) { 1528 ch = source[index++]; 1529 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); 1530 } else { 1531 return ''; 1532 } 1533 } 1534 return String.fromCharCode(code); 1535 } 1536 1537 function scanUnicodeCodePointEscape() { 1538 var ch, code, cu1, cu2; 1539 1540 ch = source[index]; 1541 code = 0; 1542 1543 // At least, one hex digit is required. 1544 if (ch === '}') { 1545 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1546 } 1547 1548 while (index < length) { 1549 ch = source[index++]; 1550 if (!isHexDigit(ch)) { 1551 break; 1552 } 1553 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); 1554 } 1555 1556 if (code > 0x10FFFF || ch !== '}') { 1557 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1558 } 1559 1560 // UTF-16 Encoding 1561 if (code <= 0xFFFF) { 1562 return String.fromCharCode(code); 1563 } 1564 cu1 = ((code - 0x10000) >> 10) + 0xD800; 1565 cu2 = ((code - 0x10000) & 1023) + 0xDC00; 1566 return String.fromCharCode(cu1, cu2); 1567 } 1568 1569 function getEscapedIdentifier() { 1570 var ch, id; 1571 1572 ch = source.charCodeAt(index++); 1573 id = String.fromCharCode(ch); 1574 1575 // '\u' (char #92, char #117) denotes an escaped character. 1576 if (ch === 92) { 1577 if (source.charCodeAt(index) !== 117) { 1578 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1579 } 1580 ++index; 1581 ch = scanHexEscape('u'); 1582 if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) { 1583 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1584 } 1585 id = ch; 1586 } 1587 1588 while (index < length) { 1589 ch = source.charCodeAt(index); 1590 if (!isIdentifierPart(ch)) { 1591 break; 1592 } 1593 ++index; 1594 id += String.fromCharCode(ch); 1595 1596 // '\u' (char #92, char #117) denotes an escaped character. 1597 if (ch === 92) { 1598 id = id.substr(0, id.length - 1); 1599 if (source.charCodeAt(index) !== 117) { 1600 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1601 } 1602 ++index; 1603 ch = scanHexEscape('u'); 1604 if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) { 1605 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1606 } 1607 id += ch; 1608 } 1609 } 1610 1611 return id; 1612 } 1613 1614 function getIdentifier() { 1615 var start, ch; 1616 1617 start = index++; 1618 while (index < length) { 1619 ch = source.charCodeAt(index); 1620 if (ch === 92) { 1621 // Blackslash (char #92) marks Unicode escape sequence. 1622 index = start; 1623 return getEscapedIdentifier(); 1624 } 1625 if (isIdentifierPart(ch)) { 1626 ++index; 1627 } else { 1628 break; 1629 } 1630 } 1631 1632 return source.slice(start, index); 1633 } 1634 1635 function scanIdentifier() { 1636 var start, id, type; 1637 1638 start = index; 1639 1640 // Backslash (char #92) starts an escaped character. 1641 id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier(); 1642 1643 // There is no keyword or literal with only one character. 1644 // Thus, it must be an identifier. 1645 if (id.length === 1) { 1646 type = Token.Identifier; 1647 } else if (isKeyword(id)) { 1648 type = Token.Keyword; 1649 } else if (id === 'null') { 1650 type = Token.NullLiteral; 1651 } else if (id === 'true' || id === 'false') { 1652 type = Token.BooleanLiteral; 1653 } else { 1654 type = Token.Identifier; 1655 } 1656 1657 return { 1658 type: type, 1659 value: id, 1660 lineNumber: lineNumber, 1661 lineStart: lineStart, 1662 range: [start, index] 1663 }; 1664 } 1665 1666 1667 // 7.7 Punctuators 1668 1669 function scanPunctuator() { 1670 var start = index, 1671 code = source.charCodeAt(index), 1672 code2, 1673 ch1 = source[index], 1674 ch2, 1675 ch3, 1676 ch4; 1677 1678 switch (code) { 1679 // Check for most common single-character punctuators. 1680 case 40: // ( open bracket 1681 case 41: // ) close bracket 1682 case 59: // ; semicolon 1683 case 44: // , comma 1684 case 123: // { open curly brace 1685 case 125: // } close curly brace 1686 case 91: // [ 1687 case 93: // ] 1688 case 58: // : 1689 case 63: // ? 1690 case 126: // ~ 1691 ++index; 1692 if (extra.tokenize) { 1693 if (code === 40) { 1694 extra.openParenToken = extra.tokens.length; 1695 } else if (code === 123) { 1696 extra.openCurlyToken = extra.tokens.length; 1697 } 1698 } 1699 return { 1700 type: Token.Punctuator, 1701 value: String.fromCharCode(code), 1702 lineNumber: lineNumber, 1703 lineStart: lineStart, 1704 range: [start, index] 1705 }; 1706 1707 default: 1708 code2 = source.charCodeAt(index + 1); 1709 1710 // '=' (char #61) marks an assignment or comparison operator. 1711 if (code2 === 61) { 1712 switch (code) { 1713 case 37: // % 1714 case 38: // & 1715 case 42: // *: 1716 case 43: // + 1717 case 45: // - 1718 case 47: // / 1719 case 60: // < 1720 case 62: // > 1721 case 94: // ^ 1722 case 124: // | 1723 index += 2; 1724 return { 1725 type: Token.Punctuator, 1726 value: String.fromCharCode(code) + String.fromCharCode(code2), 1727 lineNumber: lineNumber, 1728 lineStart: lineStart, 1729 range: [start, index] 1730 }; 1731 1732 case 33: // ! 1733 case 61: // = 1734 index += 2; 1735 1736 // !== and === 1737 if (source.charCodeAt(index) === 61) { 1738 ++index; 1739 } 1740 return { 1741 type: Token.Punctuator, 1742 value: source.slice(start, index), 1743 lineNumber: lineNumber, 1744 lineStart: lineStart, 1745 range: [start, index] 1746 }; 1747 default: 1748 break; 1749 } 1750 } 1751 break; 1752 } 1753 1754 // Peek more characters. 1755 1756 ch2 = source[index + 1]; 1757 ch3 = source[index + 2]; 1758 ch4 = source[index + 3]; 1759 1760 // 4-character punctuator: >>>= 1761 1762 if (ch1 === '>' && ch2 === '>' && ch3 === '>') { 1763 if (ch4 === '=') { 1764 index += 4; 1765 return { 1766 type: Token.Punctuator, 1767 value: '>>>=', 1768 lineNumber: lineNumber, 1769 lineStart: lineStart, 1770 range: [start, index] 1771 }; 1772 } 1773 } 1774 1775 // 3-character punctuators: === !== >>> <<= >>= 1776 1777 if (ch1 === '>' && ch2 === '>' && ch3 === '>') { 1778 index += 3; 1779 return { 1780 type: Token.Punctuator, 1781 value: '>>>', 1782 lineNumber: lineNumber, 1783 lineStart: lineStart, 1784 range: [start, index] 1785 }; 1786 } 1787 1788 if (ch1 === '<' && ch2 === '<' && ch3 === '=') { 1789 index += 3; 1790 return { 1791 type: Token.Punctuator, 1792 value: '<<=', 1793 lineNumber: lineNumber, 1794 lineStart: lineStart, 1795 range: [start, index] 1796 }; 1797 } 1798 1799 if (ch1 === '>' && ch2 === '>' && ch3 === '=') { 1800 index += 3; 1801 return { 1802 type: Token.Punctuator, 1803 value: '>>=', 1804 lineNumber: lineNumber, 1805 lineStart: lineStart, 1806 range: [start, index] 1807 }; 1808 } 1809 1810 if (ch1 === '.' && ch2 === '.' && ch3 === '.') { 1811 index += 3; 1812 return { 1813 type: Token.Punctuator, 1814 value: '...', 1815 lineNumber: lineNumber, 1816 lineStart: lineStart, 1817 range: [start, index] 1818 }; 1819 } 1820 1821 // Other 2-character punctuators: ++ -- << >> && || 1822 1823 if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { 1824 index += 2; 1825 return { 1826 type: Token.Punctuator, 1827 value: ch1 + ch2, 1828 lineNumber: lineNumber, 1829 lineStart: lineStart, 1830 range: [start, index] 1831 }; 1832 } 1833 1834 if (ch1 === '=' && ch2 === '>') { 1835 index += 2; 1836 return { 1837 type: Token.Punctuator, 1838 value: '=>', 1839 lineNumber: lineNumber, 1840 lineStart: lineStart, 1841 range: [start, index] 1842 }; 1843 } 1844 1845 if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { 1846 ++index; 1847 return { 1848 type: Token.Punctuator, 1849 value: ch1, 1850 lineNumber: lineNumber, 1851 lineStart: lineStart, 1852 range: [start, index] 1853 }; 1854 } 1855 1856 if (ch1 === '.') { 1857 ++index; 1858 return { 1859 type: Token.Punctuator, 1860 value: ch1, 1861 lineNumber: lineNumber, 1862 lineStart: lineStart, 1863 range: [start, index] 1864 }; 1865 } 1866 1867 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1868 } 1869 1870 // 7.8.3 Numeric Literals 1871 1872 function scanHexLiteral(start) { 1873 var number = ''; 1874 1875 while (index < length) { 1876 if (!isHexDigit(source[index])) { 1877 break; 1878 } 1879 number += source[index++]; 1880 } 1881 1882 if (number.length === 0) { 1883 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1884 } 1885 1886 if (isIdentifierStart(source.charCodeAt(index))) { 1887 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1888 } 1889 1890 return { 1891 type: Token.NumericLiteral, 1892 value: parseInt('0x' + number, 16), 1893 lineNumber: lineNumber, 1894 lineStart: lineStart, 1895 range: [start, index] 1896 }; 1897 } 1898 1899 function scanOctalLiteral(prefix, start) { 1900 var number, octal; 1901 1902 if (isOctalDigit(prefix)) { 1903 octal = true; 1904 number = '0' + source[index++]; 1905 } else { 1906 octal = false; 1907 ++index; 1908 number = ''; 1909 } 1910 1911 while (index < length) { 1912 if (!isOctalDigit(source[index])) { 1913 break; 1914 } 1915 number += source[index++]; 1916 } 1917 1918 if (!octal && number.length === 0) { 1919 // only 0o or 0O 1920 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1921 } 1922 1923 if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { 1924 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1925 } 1926 1927 return { 1928 type: Token.NumericLiteral, 1929 value: parseInt(number, 8), 1930 octal: octal, 1931 lineNumber: lineNumber, 1932 lineStart: lineStart, 1933 range: [start, index] 1934 }; 1935 } 1936 1937 function scanNumericLiteral() { 1938 var number, start, ch, octal; 1939 1940 ch = source[index]; 1941 assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), 1942 'Numeric literal must start with a decimal digit or a decimal point'); 1943 1944 start = index; 1945 number = ''; 1946 if (ch !== '.') { 1947 number = source[index++]; 1948 ch = source[index]; 1949 1950 // Hex number starts with '0x'. 1951 // Octal number starts with '0'. 1952 // Octal number in ES6 starts with '0o'. 1953 // Binary number in ES6 starts with '0b'. 1954 if (number === '0') { 1955 if (ch === 'x' || ch === 'X') { 1956 ++index; 1957 return scanHexLiteral(start); 1958 } 1959 if (ch === 'b' || ch === 'B') { 1960 ++index; 1961 number = ''; 1962 1963 while (index < length) { 1964 ch = source[index]; 1965 if (ch !== '0' && ch !== '1') { 1966 break; 1967 } 1968 number += source[index++]; 1969 } 1970 1971 if (number.length === 0) { 1972 // only 0b or 0B 1973 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1974 } 1975 1976 if (index < length) { 1977 ch = source.charCodeAt(index); 1978 if (isIdentifierStart(ch) || isDecimalDigit(ch)) { 1979 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1980 } 1981 } 1982 return { 1983 type: Token.NumericLiteral, 1984 value: parseInt(number, 2), 1985 lineNumber: lineNumber, 1986 lineStart: lineStart, 1987 range: [start, index] 1988 }; 1989 } 1990 if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) { 1991 return scanOctalLiteral(ch, start); 1992 } 1993 // decimal number starts with '0' such as '09' is illegal. 1994 if (ch && isDecimalDigit(ch.charCodeAt(0))) { 1995 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 1996 } 1997 } 1998 1999 while (isDecimalDigit(source.charCodeAt(index))) { 2000 number += source[index++]; 2001 } 2002 ch = source[index]; 2003 } 2004 2005 if (ch === '.') { 2006 number += source[index++]; 2007 while (isDecimalDigit(source.charCodeAt(index))) { 2008 number += source[index++]; 2009 } 2010 ch = source[index]; 2011 } 2012 2013 if (ch === 'e' || ch === 'E') { 2014 number += source[index++]; 2015 2016 ch = source[index]; 2017 if (ch === '+' || ch === '-') { 2018 number += source[index++]; 2019 } 2020 if (isDecimalDigit(source.charCodeAt(index))) { 2021 while (isDecimalDigit(source.charCodeAt(index))) { 2022 number += source[index++]; 2023 } 2024 } else { 2025 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 2026 } 2027 } 2028 2029 if (isIdentifierStart(source.charCodeAt(index))) { 2030 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 2031 } 2032 2033 return { 2034 type: Token.NumericLiteral, 2035 value: parseFloat(number), 2036 lineNumber: lineNumber, 2037 lineStart: lineStart, 2038 range: [start, index] 2039 }; 2040 } 2041 2042 // 7.8.4 String Literals 2043 2044 function scanStringLiteral() { 2045 var str = '', quote, start, ch, code, unescaped, restore, octal = false; 2046 2047 quote = source[index]; 2048 assert((quote === '\'' || quote === '"'), 2049 'String literal must starts with a quote'); 2050 2051 start = index; 2052 ++index; 2053 2054 while (index < length) { 2055 ch = source[index++]; 2056 2057 if (ch === quote) { 2058 quote = ''; 2059 break; 2060 } else if (ch === '\\') { 2061 ch = source[index++]; 2062 if (!ch || !isLineTerminator(ch.charCodeAt(0))) { 2063 switch (ch) { 2064 case 'n': 2065 str += '\n'; 2066 break; 2067 case 'r': 2068 str += '\r'; 2069 break; 2070 case 't': 2071 str += '\t'; 2072 break; 2073 case 'u': 2074 case 'x': 2075 if (source[index] === '{') { 2076 ++index; 2077 str += scanUnicodeCodePointEscape(); 2078 } else { 2079 restore = index; 2080 unescaped = scanHexEscape(ch); 2081 if (unescaped) { 2082 str += unescaped; 2083 } else { 2084 index = restore; 2085 str += ch; 2086 } 2087 } 2088 break; 2089 case 'b': 2090 str += '\b'; 2091 break; 2092 case 'f': 2093 str += '\f'; 2094 break; 2095 case 'v': 2096 str += '\x0B'; 2097 break; 2098 2099 default: 2100 if (isOctalDigit(ch)) { 2101 code = '01234567'.indexOf(ch); 2102 2103 // \0 is not octal escape sequence 2104 if (code !== 0) { 2105 octal = true; 2106 } 2107 2108 if (index < length && isOctalDigit(source[index])) { 2109 octal = true; 2110 code = code * 8 + '01234567'.indexOf(source[index++]); 2111 2112 // 3 digits are only allowed when string starts 2113 // with 0, 1, 2, 3 2114 if ('0123'.indexOf(ch) >= 0 && 2115 index < length && 2116 isOctalDigit(source[index])) { 2117 code = code * 8 + '01234567'.indexOf(source[index++]); 2118 } 2119 } 2120 str += String.fromCharCode(code); 2121 } else { 2122 str += ch; 2123 } 2124 break; 2125 } 2126 } else { 2127 ++lineNumber; 2128 if (ch === '\r' && source[index] === '\n') { 2129 ++index; 2130 } 2131 } 2132 } else if (isLineTerminator(ch.charCodeAt(0))) { 2133 break; 2134 } else { 2135 str += ch; 2136 } 2137 } 2138 2139 if (quote !== '') { 2140 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 2141 } 2142 2143 return { 2144 type: Token.StringLiteral, 2145 value: str, 2146 octal: octal, 2147 lineNumber: lineNumber, 2148 lineStart: lineStart, 2149 range: [start, index] 2150 }; 2151 } 2152 2153 function scanTemplate() { 2154 var cooked = '', ch, start, terminated, tail, restore, unescaped, code, octal; 2155 2156 terminated = false; 2157 tail = false; 2158 start = index; 2159 2160 ++index; 2161 2162 while (index < length) { 2163 ch = source[index++]; 2164 if (ch === '`') { 2165 tail = true; 2166 terminated = true; 2167 break; 2168 } else if (ch === '$') { 2169 if (source[index] === '{') { 2170 ++index; 2171 terminated = true; 2172 break; 2173 } 2174 cooked += ch; 2175 } else if (ch === '\\') { 2176 ch = source[index++]; 2177 if (!isLineTerminator(ch.charCodeAt(0))) { 2178 switch (ch) { 2179 case 'n': 2180 cooked += '\n'; 2181 break; 2182 case 'r': 2183 cooked += '\r'; 2184 break; 2185 case 't': 2186 cooked += '\t'; 2187 break; 2188 case 'u': 2189 case 'x': 2190 if (source[index] === '{') { 2191 ++index; 2192 cooked += scanUnicodeCodePointEscape(); 2193 } else { 2194 restore = index; 2195 unescaped = scanHexEscape(ch); 2196 if (unescaped) { 2197 cooked += unescaped; 2198 } else { 2199 index = restore; 2200 cooked += ch; 2201 } 2202 } 2203 break; 2204 case 'b': 2205 cooked += '\b'; 2206 break; 2207 case 'f': 2208 cooked += '\f'; 2209 break; 2210 case 'v': 2211 cooked += '\v'; 2212 break; 2213 2214 default: 2215 if (isOctalDigit(ch)) { 2216 code = '01234567'.indexOf(ch); 2217 2218 // \0 is not octal escape sequence 2219 if (code !== 0) { 2220 octal = true; 2221 } 2222 2223 if (index < length && isOctalDigit(source[index])) { 2224 octal = true; 2225 code = code * 8 + '01234567'.indexOf(source[index++]); 2226 2227 // 3 digits are only allowed when string starts 2228 // with 0, 1, 2, 3 2229 if ('0123'.indexOf(ch) >= 0 && 2230 index < length && 2231 isOctalDigit(source[index])) { 2232 code = code * 8 + '01234567'.indexOf(source[index++]); 2233 } 2234 } 2235 cooked += String.fromCharCode(code); 2236 } else { 2237 cooked += ch; 2238 } 2239 break; 2240 } 2241 } else { 2242 ++lineNumber; 2243 if (ch === '\r' && source[index] === '\n') { 2244 ++index; 2245 } 2246 } 2247 } else if (isLineTerminator(ch.charCodeAt(0))) { 2248 ++lineNumber; 2249 if (ch === '\r' && source[index] === '\n') { 2250 ++index; 2251 } 2252 cooked += '\n'; 2253 } else { 2254 cooked += ch; 2255 } 2256 } 2257 2258 if (!terminated) { 2259 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 2260 } 2261 2262 return { 2263 type: Token.Template, 2264 value: { 2265 cooked: cooked, 2266 raw: source.slice(start + 1, index - ((tail) ? 1 : 2)) 2267 }, 2268 tail: tail, 2269 octal: octal, 2270 lineNumber: lineNumber, 2271 lineStart: lineStart, 2272 range: [start, index] 2273 }; 2274 } 2275 2276 function scanTemplateElement(option) { 2277 var startsWith, template; 2278 2279 lookahead = null; 2280 skipComment(); 2281 2282 startsWith = (option.head) ? '`' : '}'; 2283 2284 if (source[index] !== startsWith) { 2285 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 2286 } 2287 2288 template = scanTemplate(); 2289 2290 peek(); 2291 2292 return template; 2293 } 2294 2295 function scanRegExp() { 2296 var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; 2297 2298 lookahead = null; 2299 skipComment(); 2300 2301 start = index; 2302 ch = source[index]; 2303 assert(ch === '/', 'Regular expression literal must start with a slash'); 2304 str = source[index++]; 2305 2306 while (index < length) { 2307 ch = source[index++]; 2308 str += ch; 2309 if (classMarker) { 2310 if (ch === ']') { 2311 classMarker = false; 2312 } 2313 } else { 2314 if (ch === '\\') { 2315 ch = source[index++]; 2316 // ECMA-262 7.8.5 2317 if (isLineTerminator(ch.charCodeAt(0))) { 2318 throwError({}, Messages.UnterminatedRegExp); 2319 } 2320 str += ch; 2321 } else if (ch === '/') { 2322 terminated = true; 2323 break; 2324 } else if (ch === '[') { 2325 classMarker = true; 2326 } else if (isLineTerminator(ch.charCodeAt(0))) { 2327 throwError({}, Messages.UnterminatedRegExp); 2328 } 2329 } 2330 } 2331 2332 if (!terminated) { 2333 throwError({}, Messages.UnterminatedRegExp); 2334 } 2335 2336 // Exclude leading and trailing slash. 2337 pattern = str.substr(1, str.length - 2); 2338 2339 flags = ''; 2340 while (index < length) { 2341 ch = source[index]; 2342 if (!isIdentifierPart(ch.charCodeAt(0))) { 2343 break; 2344 } 2345 2346 ++index; 2347 if (ch === '\\' && index < length) { 2348 ch = source[index]; 2349 if (ch === 'u') { 2350 ++index; 2351 restore = index; 2352 ch = scanHexEscape('u'); 2353 if (ch) { 2354 flags += ch; 2355 for (str += '\\u'; restore < index; ++restore) { 2356 str += source[restore]; 2357 } 2358 } else { 2359 index = restore; 2360 flags += 'u'; 2361 str += '\\u'; 2362 } 2363 } else { 2364 str += '\\'; 2365 } 2366 } else { 2367 flags += ch; 2368 str += ch; 2369 } 2370 } 2371 2372 try { 2373 value = new RegExp(pattern, flags); 2374 } catch (e) { 2375 throwError({}, Messages.InvalidRegExp); 2376 } 2377 2378 peek(); 2379 2380 2381 if (extra.tokenize) { 2382 return { 2383 type: Token.RegularExpression, 2384 value: value, 2385 lineNumber: lineNumber, 2386 lineStart: lineStart, 2387 range: [start, index] 2388 }; 2389 } 2390 return { 2391 literal: str, 2392 value: value, 2393 range: [start, index] 2394 }; 2395 } 2396 2397 function isIdentifierName(token) { 2398 return token.type === Token.Identifier || 2399 token.type === Token.Keyword || 2400 token.type === Token.BooleanLiteral || 2401 token.type === Token.NullLiteral; 2402 } 2403 2404 function advanceSlash() { 2405 var prevToken, 2406 checkToken; 2407 // Using the following algorithm: 2408 // https://github.com/mozilla/sweet.js/wiki/design 2409 prevToken = extra.tokens[extra.tokens.length - 1]; 2410 if (!prevToken) { 2411 // Nothing before that: it cannot be a division. 2412 return scanRegExp(); 2413 } 2414 if (prevToken.type === "Punctuator") { 2415 if (prevToken.value === ")") { 2416 checkToken = extra.tokens[extra.openParenToken - 1]; 2417 if (checkToken && 2418 checkToken.type === "Keyword" && 2419 (checkToken.value === "if" || 2420 checkToken.value === "while" || 2421 checkToken.value === "for" || 2422 checkToken.value === "with")) { 2423 return scanRegExp(); 2424 } 2425 return scanPunctuator(); 2426 } 2427 if (prevToken.value === "}") { 2428 // Dividing a function by anything makes little sense, 2429 // but we have to check for that. 2430 if (extra.tokens[extra.openCurlyToken - 3] && 2431 extra.tokens[extra.openCurlyToken - 3].type === "Keyword") { 2432 // Anonymous function. 2433 checkToken = extra.tokens[extra.openCurlyToken - 4]; 2434 if (!checkToken) { 2435 return scanPunctuator(); 2436 } 2437 } else if (extra.tokens[extra.openCurlyToken - 4] && 2438 extra.tokens[extra.openCurlyToken - 4].type === "Keyword") { 2439 // Named function. 2440 checkToken = extra.tokens[extra.openCurlyToken - 5]; 2441 if (!checkToken) { 2442 return scanRegExp(); 2443 } 2444 } else { 2445 return scanPunctuator(); 2446 } 2447 // checkToken determines whether the function is 2448 // a declaration or an expression. 2449 if (FnExprTokens.indexOf(checkToken.value) >= 0) { 2450 // It is an expression. 2451 return scanPunctuator(); 2452 } 2453 // It is a declaration. 2454 return scanRegExp(); 2455 } 2456 return scanRegExp(); 2457 } 2458 if (prevToken.type === "Keyword") { 2459 return scanRegExp(); 2460 } 2461 return scanPunctuator(); 2462 } 2463 2464 function advance() { 2465 var ch; 2466 2467 if (state.inXJSChild) { 2468 return advanceXJSChild(); 2469 } 2470 2471 skipComment(); 2472 2473 if (index >= length) { 2474 return { 2475 type: Token.EOF, 2476 lineNumber: lineNumber, 2477 lineStart: lineStart, 2478 range: [index, index] 2479 }; 2480 } 2481 2482 ch = source.charCodeAt(index); 2483 2484 // Very common: ( and ) and ; 2485 if (ch === 40 || ch === 41 || ch === 58) { 2486 return scanPunctuator(); 2487 } 2488 2489 // String literal starts with single quote (#39) or double quote (#34). 2490 if (ch === 39 || ch === 34) { 2491 if (state.inXJSTag) { 2492 return scanXJSStringLiteral(); 2493 } 2494 return scanStringLiteral(); 2495 } 2496 2497 if (state.inXJSTag && isXJSIdentifierStart(ch)) { 2498 return scanXJSIdentifier(); 2499 } 2500 2501 if (ch === 96) { 2502 return scanTemplate(); 2503 } 2504 if (isIdentifierStart(ch)) { 2505 return scanIdentifier(); 2506 } 2507 2508 // Dot (.) char #46 can also start a floating-point number, hence the need 2509 // to check the next character. 2510 if (ch === 46) { 2511 if (isDecimalDigit(source.charCodeAt(index + 1))) { 2512 return scanNumericLiteral(); 2513 } 2514 return scanPunctuator(); 2515 } 2516 2517 if (isDecimalDigit(ch)) { 2518 return scanNumericLiteral(); 2519 } 2520 2521 // Slash (/) char #47 can also start a regex. 2522 if (extra.tokenize && ch === 47) { 2523 return advanceSlash(); 2524 } 2525 2526 return scanPunctuator(); 2527 } 2528 2529 function lex() { 2530 var token; 2531 2532 token = lookahead; 2533 index = token.range[1]; 2534 lineNumber = token.lineNumber; 2535 lineStart = token.lineStart; 2536 2537 lookahead = advance(); 2538 2539 index = token.range[1]; 2540 lineNumber = token.lineNumber; 2541 lineStart = token.lineStart; 2542 2543 return token; 2544 } 2545 2546 function peek() { 2547 var pos, line, start; 2548 2549 pos = index; 2550 line = lineNumber; 2551 start = lineStart; 2552 lookahead = advance(); 2553 index = pos; 2554 lineNumber = line; 2555 lineStart = start; 2556 } 2557 2558 function lookahead2() { 2559 var adv, pos, line, start, result; 2560 2561 // If we are collecting the tokens, don't grab the next one yet. 2562 adv = (typeof extra.advance === 'function') ? extra.advance : advance; 2563 2564 pos = index; 2565 line = lineNumber; 2566 start = lineStart; 2567 2568 // Scan for the next immediate token. 2569 if (lookahead === null) { 2570 lookahead = adv(); 2571 } 2572 index = lookahead.range[1]; 2573 lineNumber = lookahead.lineNumber; 2574 lineStart = lookahead.lineStart; 2575 2576 // Grab the token right after. 2577 result = adv(); 2578 index = pos; 2579 lineNumber = line; 2580 lineStart = start; 2581 2582 return result; 2583 } 2584 2585 SyntaxTreeDelegate = { 2586 2587 name: 'SyntaxTree', 2588 2589 postProcess: function (node) { 2590 return node; 2591 }, 2592 2593 createArrayExpression: function (elements) { 2594 return { 2595 type: Syntax.ArrayExpression, 2596 elements: elements 2597 }; 2598 }, 2599 2600 createAssignmentExpression: function (operator, left, right) { 2601 return { 2602 type: Syntax.AssignmentExpression, 2603 operator: operator, 2604 left: left, 2605 right: right 2606 }; 2607 }, 2608 2609 createBinaryExpression: function (operator, left, right) { 2610 var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : 2611 Syntax.BinaryExpression; 2612 return { 2613 type: type, 2614 operator: operator, 2615 left: left, 2616 right: right 2617 }; 2618 }, 2619 2620 createBlockStatement: function (body) { 2621 return { 2622 type: Syntax.BlockStatement, 2623 body: body 2624 }; 2625 }, 2626 2627 createBreakStatement: function (label) { 2628 return { 2629 type: Syntax.BreakStatement, 2630 label: label 2631 }; 2632 }, 2633 2634 createCallExpression: function (callee, args) { 2635 return { 2636 type: Syntax.CallExpression, 2637 callee: callee, 2638 'arguments': args 2639 }; 2640 }, 2641 2642 createCatchClause: function (param, body) { 2643 return { 2644 type: Syntax.CatchClause, 2645 param: param, 2646 body: body 2647 }; 2648 }, 2649 2650 createConditionalExpression: function (test, consequent, alternate) { 2651 return { 2652 type: Syntax.ConditionalExpression, 2653 test: test, 2654 consequent: consequent, 2655 alternate: alternate 2656 }; 2657 }, 2658 2659 createContinueStatement: function (label) { 2660 return { 2661 type: Syntax.ContinueStatement, 2662 label: label 2663 }; 2664 }, 2665 2666 createDebuggerStatement: function () { 2667 return { 2668 type: Syntax.DebuggerStatement 2669 }; 2670 }, 2671 2672 createDoWhileStatement: function (body, test) { 2673 return { 2674 type: Syntax.DoWhileStatement, 2675 body: body, 2676 test: test 2677 }; 2678 }, 2679 2680 createEmptyStatement: function () { 2681 return { 2682 type: Syntax.EmptyStatement 2683 }; 2684 }, 2685 2686 createExpressionStatement: function (expression) { 2687 return { 2688 type: Syntax.ExpressionStatement, 2689 expression: expression 2690 }; 2691 }, 2692 2693 createForStatement: function (init, test, update, body) { 2694 return { 2695 type: Syntax.ForStatement, 2696 init: init, 2697 test: test, 2698 update: update, 2699 body: body 2700 }; 2701 }, 2702 2703 createForInStatement: function (left, right, body) { 2704 return { 2705 type: Syntax.ForInStatement, 2706 left: left, 2707 right: right, 2708 body: body, 2709 each: false 2710 }; 2711 }, 2712 2713 createForOfStatement: function (left, right, body) { 2714 return { 2715 type: Syntax.ForOfStatement, 2716 left: left, 2717 right: right, 2718 body: body, 2719 }; 2720 }, 2721 2722 createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression, 2723 returnType) { 2724 return { 2725 type: Syntax.FunctionDeclaration, 2726 id: id, 2727 params: params, 2728 defaults: defaults, 2729 body: body, 2730 rest: rest, 2731 generator: generator, 2732 expression: expression, 2733 returnType: returnType 2734 }; 2735 }, 2736 2737 createFunctionExpression: function (id, params, defaults, body, rest, generator, expression, 2738 returnType) { 2739 return { 2740 type: Syntax.FunctionExpression, 2741 id: id, 2742 params: params, 2743 defaults: defaults, 2744 body: body, 2745 rest: rest, 2746 generator: generator, 2747 expression: expression, 2748 returnType: returnType 2749 }; 2750 }, 2751 2752 createIdentifier: function (name) { 2753 return { 2754 type: Syntax.Identifier, 2755 name: name, 2756 // Only here to initialize the shape of the object to ensure 2757 // that the 'typeAnnotation' key is ordered before others that 2758 // are added later (like 'loc' and 'range'). This just helps 2759 // keep the shape of Identifier nodes consistent with everything 2760 // else. 2761 typeAnnotation: undefined 2762 }; 2763 }, 2764 2765 createTypeAnnotation: function (typeIdentifier, paramTypes, returnType, isNullable) { 2766 return { 2767 type: Syntax.TypeAnnotation, 2768 id: typeIdentifier, 2769 paramTypes: paramTypes, 2770 returnType: returnType, 2771 isNullable: isNullable 2772 }; 2773 }, 2774 2775 createTypeAnnotatedIdentifier: function (identifier, annotation) { 2776 return { 2777 type: Syntax.TypeAnnotatedIdentifier, 2778 id: identifier, 2779 annotation: annotation 2780 }; 2781 }, 2782 2783 createXJSAttribute: function (name, value) { 2784 return { 2785 type: Syntax.XJSAttribute, 2786 name: name, 2787 value: value 2788 }; 2789 }, 2790 2791 createXJSIdentifier: function (name, namespace) { 2792 return { 2793 type: Syntax.XJSIdentifier, 2794 name: name, 2795 namespace: namespace 2796 }; 2797 }, 2798 2799 createXJSElement: function (openingElement, closingElement, children) { 2800 return { 2801 type: Syntax.XJSElement, 2802 name: openingElement.name, 2803 selfClosing: openingElement.selfClosing, 2804 openingElement: openingElement, 2805 closingElement: closingElement, 2806 attributes: openingElement.attributes, 2807 children: children 2808 }; 2809 }, 2810 2811 createXJSEmptyExpression: function () { 2812 return { 2813 type: Syntax.XJSEmptyExpression 2814 }; 2815 }, 2816 2817 createXJSExpressionContainer: function (expression) { 2818 return { 2819 type: Syntax.XJSExpressionContainer, 2820 expression: expression 2821 }; 2822 }, 2823 2824 createXJSOpeningElement: function (name, attributes, selfClosing) { 2825 return { 2826 type: Syntax.XJSOpeningElement, 2827 name: name, 2828 selfClosing: selfClosing, 2829 attributes: attributes 2830 }; 2831 }, 2832 2833 createXJSClosingElement: function (name) { 2834 return { 2835 type: Syntax.XJSClosingElement, 2836 name: name 2837 }; 2838 }, 2839 2840 createIfStatement: function (test, consequent, alternate) { 2841 return { 2842 type: Syntax.IfStatement, 2843 test: test, 2844 consequent: consequent, 2845 alternate: alternate 2846 }; 2847 }, 2848 2849 createLabeledStatement: function (label, body) { 2850 return { 2851 type: Syntax.LabeledStatement, 2852 label: label, 2853 body: body 2854 }; 2855 }, 2856 2857 createLiteral: function (token) { 2858 return { 2859 type: Syntax.Literal, 2860 value: token.value, 2861 raw: source.slice(token.range[0], token.range[1]) 2862 }; 2863 }, 2864 2865 createMemberExpression: function (accessor, object, property) { 2866 return { 2867 type: Syntax.MemberExpression, 2868 computed: accessor === '[', 2869 object: object, 2870 property: property 2871 }; 2872 }, 2873 2874 createNewExpression: function (callee, args) { 2875 return { 2876 type: Syntax.NewExpression, 2877 callee: callee, 2878 'arguments': args 2879 }; 2880 }, 2881 2882 createObjectExpression: function (properties) { 2883 return { 2884 type: Syntax.ObjectExpression, 2885 properties: properties 2886 }; 2887 }, 2888 2889 createPostfixExpression: function (operator, argument) { 2890 return { 2891 type: Syntax.UpdateExpression, 2892 operator: operator, 2893 argument: argument, 2894 prefix: false 2895 }; 2896 }, 2897 2898 createProgram: function (body) { 2899 return { 2900 type: Syntax.Program, 2901 body: body 2902 }; 2903 }, 2904 2905 createProperty: function (kind, key, value, method, shorthand) { 2906 return { 2907 type: Syntax.Property, 2908 key: key, 2909 value: value, 2910 kind: kind, 2911 method: method, 2912 shorthand: shorthand 2913 }; 2914 }, 2915 2916 createReturnStatement: function (argument) { 2917 return { 2918 type: Syntax.ReturnStatement, 2919 argument: argument 2920 }; 2921 }, 2922 2923 createSequenceExpression: function (expressions) { 2924 return { 2925 type: Syntax.SequenceExpression, 2926 expressions: expressions 2927 }; 2928 }, 2929 2930 createSwitchCase: function (test, consequent) { 2931 return { 2932 type: Syntax.SwitchCase, 2933 test: test, 2934 consequent: consequent 2935 }; 2936 }, 2937 2938 createSwitchStatement: function (discriminant, cases) { 2939 return { 2940 type: Syntax.SwitchStatement, 2941 discriminant: discriminant, 2942 cases: cases 2943 }; 2944 }, 2945 2946 createThisExpression: function () { 2947 return { 2948 type: Syntax.ThisExpression 2949 }; 2950 }, 2951 2952 createThrowStatement: function (argument) { 2953 return { 2954 type: Syntax.ThrowStatement, 2955 argument: argument 2956 }; 2957 }, 2958 2959 createTryStatement: function (block, guardedHandlers, handlers, finalizer) { 2960 return { 2961 type: Syntax.TryStatement, 2962 block: block, 2963 guardedHandlers: guardedHandlers, 2964 handlers: handlers, 2965 finalizer: finalizer 2966 }; 2967 }, 2968 2969 createUnaryExpression: function (operator, argument) { 2970 if (operator === '++' || operator === '--') { 2971 return { 2972 type: Syntax.UpdateExpression, 2973 operator: operator, 2974 argument: argument, 2975 prefix: true 2976 }; 2977 } 2978 return { 2979 type: Syntax.UnaryExpression, 2980 operator: operator, 2981 argument: argument 2982 }; 2983 }, 2984 2985 createVariableDeclaration: function (declarations, kind) { 2986 return { 2987 type: Syntax.VariableDeclaration, 2988 declarations: declarations, 2989 kind: kind 2990 }; 2991 }, 2992 2993 createVariableDeclarator: function (id, init) { 2994 return { 2995 type: Syntax.VariableDeclarator, 2996 id: id, 2997 init: init 2998 }; 2999 }, 3000 3001 createWhileStatement: function (test, body) { 3002 return { 3003 type: Syntax.WhileStatement, 3004 test: test, 3005 body: body 3006 }; 3007 }, 3008 3009 createWithStatement: function (object, body) { 3010 return { 3011 type: Syntax.WithStatement, 3012 object: object, 3013 body: body 3014 }; 3015 }, 3016 3017 createTemplateElement: function (value, tail) { 3018 return { 3019 type: Syntax.TemplateElement, 3020 value: value, 3021 tail: tail 3022 }; 3023 }, 3024 3025 createTemplateLiteral: function (quasis, expressions) { 3026 return { 3027 type: Syntax.TemplateLiteral, 3028 quasis: quasis, 3029 expressions: expressions 3030 }; 3031 }, 3032 3033 createSpreadElement: function (argument) { 3034 return { 3035 type: Syntax.SpreadElement, 3036 argument: argument 3037 }; 3038 }, 3039 3040 createTaggedTemplateExpression: function (tag, quasi) { 3041 return { 3042 type: Syntax.TaggedTemplateExpression, 3043 tag: tag, 3044 quasi: quasi 3045 }; 3046 }, 3047 3048 createArrowFunctionExpression: function (params, defaults, body, rest, expression) { 3049 return { 3050 type: Syntax.ArrowFunctionExpression, 3051 id: null, 3052 params: params, 3053 defaults: defaults, 3054 body: body, 3055 rest: rest, 3056 generator: false, 3057 expression: expression 3058 }; 3059 }, 3060 3061 createMethodDefinition: function (propertyType, kind, key, value) { 3062 return { 3063 type: Syntax.MethodDefinition, 3064 key: key, 3065 value: value, 3066 kind: kind, 3067 'static': propertyType === ClassPropertyType.static 3068 }; 3069 }, 3070 3071 createClassBody: function (body) { 3072 return { 3073 type: Syntax.ClassBody, 3074 body: body 3075 }; 3076 }, 3077 3078 createClassExpression: function (id, superClass, body) { 3079 return { 3080 type: Syntax.ClassExpression, 3081 id: id, 3082 superClass: superClass, 3083 body: body 3084 }; 3085 }, 3086 3087 createClassDeclaration: function (id, superClass, body) { 3088 return { 3089 type: Syntax.ClassDeclaration, 3090 id: id, 3091 superClass: superClass, 3092 body: body 3093 }; 3094 }, 3095 3096 createExportSpecifier: function (id, name) { 3097 return { 3098 type: Syntax.ExportSpecifier, 3099 id: id, 3100 name: name 3101 }; 3102 }, 3103 3104 createExportBatchSpecifier: function () { 3105 return { 3106 type: Syntax.ExportBatchSpecifier 3107 }; 3108 }, 3109 3110 createExportDeclaration: function (declaration, specifiers, source) { 3111 return { 3112 type: Syntax.ExportDeclaration, 3113 declaration: declaration, 3114 specifiers: specifiers, 3115 source: source 3116 }; 3117 }, 3118 3119 createImportSpecifier: function (id, name) { 3120 return { 3121 type: Syntax.ImportSpecifier, 3122 id: id, 3123 name: name 3124 }; 3125 }, 3126 3127 createImportDeclaration: function (specifiers, kind, source) { 3128 return { 3129 type: Syntax.ImportDeclaration, 3130 specifiers: specifiers, 3131 kind: kind, 3132 source: source 3133 }; 3134 }, 3135 3136 createYieldExpression: function (argument, delegate) { 3137 return { 3138 type: Syntax.YieldExpression, 3139 argument: argument, 3140 delegate: delegate 3141 }; 3142 }, 3143 3144 createModuleDeclaration: function (id, source, body) { 3145 return { 3146 type: Syntax.ModuleDeclaration, 3147 id: id, 3148 source: source, 3149 body: body 3150 }; 3151 } 3152 3153 3154 }; 3155 3156 // Return true if there is a line terminator before the next token. 3157 3158 function peekLineTerminator() { 3159 var pos, line, start, found; 3160 3161 pos = index; 3162 line = lineNumber; 3163 start = lineStart; 3164 skipComment(); 3165 found = lineNumber !== line; 3166 index = pos; 3167 lineNumber = line; 3168 lineStart = start; 3169 3170 return found; 3171 } 3172 3173 // Throw an exception 3174 3175 function throwError(token, messageFormat) { 3176 var error, 3177 args = Array.prototype.slice.call(arguments, 2), 3178 msg = messageFormat.replace( 3179 /%(\d)/g, 3180 function (whole, index) { 3181 assert(index < args.length, 'Message reference must be in range'); 3182 return args[index]; 3183 } 3184 ); 3185 3186 if (typeof token.lineNumber === 'number') { 3187 error = new Error('Line ' + token.lineNumber + ': ' + msg); 3188 error.index = token.range[0]; 3189 error.lineNumber = token.lineNumber; 3190 error.column = token.range[0] - lineStart + 1; 3191 } else { 3192 error = new Error('Line ' + lineNumber + ': ' + msg); 3193 error.index = index; 3194 error.lineNumber = lineNumber; 3195 error.column = index - lineStart + 1; 3196 } 3197 3198 error.description = msg; 3199 throw error; 3200 } 3201 3202 function throwErrorTolerant() { 3203 try { 3204 throwError.apply(null, arguments); 3205 } catch (e) { 3206 if (extra.errors) { 3207 extra.errors.push(e); 3208 } else { 3209 throw e; 3210 } 3211 } 3212 } 3213 3214 3215 // Throw an exception because of the token. 3216 3217 function throwUnexpected(token) { 3218 if (token.type === Token.EOF) { 3219 throwError(token, Messages.UnexpectedEOS); 3220 } 3221 3222 if (token.type === Token.NumericLiteral) { 3223 throwError(token, Messages.UnexpectedNumber); 3224 } 3225 3226 if (token.type === Token.StringLiteral) { 3227 throwError(token, Messages.UnexpectedString); 3228 } 3229 3230 if (token.type === Token.Identifier) { 3231 throwError(token, Messages.UnexpectedIdentifier); 3232 } 3233 3234 if (token.type === Token.Keyword) { 3235 if (isFutureReservedWord(token.value)) { 3236 throwError(token, Messages.UnexpectedReserved); 3237 } else if (strict && isStrictModeReservedWord(token.value)) { 3238 throwErrorTolerant(token, Messages.StrictReservedWord); 3239 return; 3240 } 3241 throwError(token, Messages.UnexpectedToken, token.value); 3242 } 3243 3244 if (token.type === Token.Template) { 3245 throwError(token, Messages.UnexpectedTemplate, token.value.raw); 3246 } 3247 3248 // BooleanLiteral, NullLiteral, or Punctuator. 3249 throwError(token, Messages.UnexpectedToken, token.value); 3250 } 3251 3252 // Expect the next token to match the specified punctuator. 3253 // If not, an exception will be thrown. 3254 3255 function expect(value) { 3256 var token = lex(); 3257 if (token.type !== Token.Punctuator || token.value !== value) { 3258 throwUnexpected(token); 3259 } 3260 } 3261 3262 // Expect the next token to match the specified keyword. 3263 // If not, an exception will be thrown. 3264 3265 function expectKeyword(keyword) { 3266 var token = lex(); 3267 if (token.type !== Token.Keyword || token.value !== keyword) { 3268 throwUnexpected(token); 3269 } 3270 } 3271 3272 // Return true if the next token matches the specified punctuator. 3273 3274 function match(value) { 3275 return lookahead.type === Token.Punctuator && lookahead.value === value; 3276 } 3277 3278 // Return true if the next token matches the specified keyword 3279 3280 function matchKeyword(keyword) { 3281 return lookahead.type === Token.Keyword && lookahead.value === keyword; 3282 } 3283 3284 3285 // Return true if the next token matches the specified contextual keyword 3286 3287 function matchContextualKeyword(keyword) { 3288 return lookahead.type === Token.Identifier && lookahead.value === keyword; 3289 } 3290 3291 // Return true if the next token is an assignment operator 3292 3293 function matchAssign() { 3294 var op; 3295 3296 if (lookahead.type !== Token.Punctuator) { 3297 return false; 3298 } 3299 op = lookahead.value; 3300 return op === '=' || 3301 op === '*=' || 3302 op === '/=' || 3303 op === '%=' || 3304 op === '+=' || 3305 op === '-=' || 3306 op === '<<=' || 3307 op === '>>=' || 3308 op === '>>>=' || 3309 op === '&=' || 3310 op === '^=' || 3311 op === '|='; 3312 } 3313 3314 function consumeSemicolon() { 3315 var line; 3316 3317 // Catch the very common case first: immediately a semicolon (char #59). 3318 if (source.charCodeAt(index) === 59) { 3319 lex(); 3320 return; 3321 } 3322 3323 line = lineNumber; 3324 skipComment(); 3325 if (lineNumber !== line) { 3326 return; 3327 } 3328 3329 if (match(';')) { 3330 lex(); 3331 return; 3332 } 3333 3334 if (lookahead.type !== Token.EOF && !match('}')) { 3335 throwUnexpected(lookahead); 3336 } 3337 } 3338 3339 // Return true if provided expression is LeftHandSideExpression 3340 3341 function isLeftHandSide(expr) { 3342 return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; 3343 } 3344 3345 function isAssignableLeftHandSide(expr) { 3346 return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern; 3347 } 3348 3349 // 11.1.4 Array Initialiser 3350 3351 function parseArrayInitialiser() { 3352 var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true, body; 3353 3354 expect('['); 3355 while (!match(']')) { 3356 if (lookahead.value === 'for' && 3357 lookahead.type === Token.Keyword) { 3358 if (!possiblecomprehension) { 3359 throwError({}, Messages.ComprehensionError); 3360 } 3361 matchKeyword('for'); 3362 tmp = parseForStatement({ignore_body: true}); 3363 tmp.of = tmp.type === Syntax.ForOfStatement; 3364 tmp.type = Syntax.ComprehensionBlock; 3365 if (tmp.left.kind) { // can't be let or const 3366 throwError({}, Messages.ComprehensionError); 3367 } 3368 blocks.push(tmp); 3369 } else if (lookahead.value === 'if' && 3370 lookahead.type === Token.Keyword) { 3371 if (!possiblecomprehension) { 3372 throwError({}, Messages.ComprehensionError); 3373 } 3374 expectKeyword('if'); 3375 expect('('); 3376 filter = parseExpression(); 3377 expect(')'); 3378 } else if (lookahead.value === ',' && 3379 lookahead.type === Token.Punctuator) { 3380 possiblecomprehension = false; // no longer allowed. 3381 lex(); 3382 elements.push(null); 3383 } else { 3384 tmp = parseSpreadOrAssignmentExpression(); 3385 elements.push(tmp); 3386 if (tmp && tmp.type === Syntax.SpreadElement) { 3387 if (!match(']')) { 3388 throwError({}, Messages.ElementAfterSpreadElement); 3389 } 3390 } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) { 3391 expect(','); // this lexes. 3392 possiblecomprehension = false; 3393 } 3394 } 3395 } 3396 3397 expect(']'); 3398 3399 if (filter && !blocks.length) { 3400 throwError({}, Messages.ComprehensionRequiresBlock); 3401 } 3402 3403 if (blocks.length) { 3404 if (elements.length !== 1) { 3405 throwError({}, Messages.ComprehensionError); 3406 } 3407 return { 3408 type: Syntax.ComprehensionExpression, 3409 filter: filter, 3410 blocks: blocks, 3411 body: elements[0] 3412 }; 3413 } 3414 return delegate.createArrayExpression(elements); 3415 } 3416 3417 // 11.1.5 Object Initialiser 3418 3419 function parsePropertyFunction(options) { 3420 var previousStrict, previousYieldAllowed, params, defaults, body; 3421 3422 previousStrict = strict; 3423 previousYieldAllowed = state.yieldAllowed; 3424 state.yieldAllowed = options.generator; 3425 params = options.params || []; 3426 defaults = options.defaults || []; 3427 3428 body = parseConciseBody(); 3429 if (options.name && strict && isRestrictedWord(params[0].name)) { 3430 throwErrorTolerant(options.name, Messages.StrictParamName); 3431 } 3432 if (state.yieldAllowed && !state.yieldFound) { 3433 throwErrorTolerant({}, Messages.NoYieldInGenerator); 3434 } 3435 strict = previousStrict; 3436 state.yieldAllowed = previousYieldAllowed; 3437 3438 return delegate.createFunctionExpression(null, params, defaults, body, options.rest || null, options.generator, body.type !== Syntax.BlockStatement, 3439 options.returnTypeAnnotation); 3440 } 3441 3442 3443 function parsePropertyMethodFunction(options) { 3444 var previousStrict, tmp, method; 3445 3446 previousStrict = strict; 3447 strict = true; 3448 3449 tmp = parseParams(); 3450 3451 if (tmp.stricted) { 3452 throwErrorTolerant(tmp.stricted, tmp.message); 3453 } 3454 3455 3456 method = parsePropertyFunction({ 3457 params: tmp.params, 3458 defaults: tmp.defaults, 3459 rest: tmp.rest, 3460 generator: options.generator, 3461 returnTypeAnnotation: tmp.returnTypeAnnotation 3462 }); 3463 3464 strict = previousStrict; 3465 3466 return method; 3467 } 3468 3469 3470 function parseObjectPropertyKey() { 3471 var token = lex(); 3472 3473 // Note: This function is called only from parseObjectProperty(), where 3474 // EOF and Punctuator tokens are already filtered out. 3475 3476 if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { 3477 if (strict && token.octal) { 3478 throwErrorTolerant(token, Messages.StrictOctalLiteral); 3479 } 3480 return delegate.createLiteral(token); 3481 } 3482 3483 return delegate.createIdentifier(token.value); 3484 } 3485 3486 function parseObjectProperty() { 3487 var token, key, id, value, param; 3488 3489 token = lookahead; 3490 3491 if (token.type === Token.Identifier) { 3492 3493 id = parseObjectPropertyKey(); 3494 3495 // Property Assignment: Getter and Setter. 3496 3497 if (token.value === 'get' && !(match(':') || match('('))) { 3498 key = parseObjectPropertyKey(); 3499 expect('('); 3500 expect(')'); 3501 return delegate.createProperty('get', key, parsePropertyFunction({ generator: false }), false, false); 3502 } 3503 if (token.value === 'set' && !(match(':') || match('('))) { 3504 key = parseObjectPropertyKey(); 3505 expect('('); 3506 token = lookahead; 3507 param = [ parseTypeAnnotatableIdentifier() ]; 3508 expect(')'); 3509 return delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false); 3510 } 3511 if (match(':')) { 3512 lex(); 3513 return delegate.createProperty('init', id, parseAssignmentExpression(), false, false); 3514 } 3515 if (match('(')) { 3516 return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: false }), true, false); 3517 } 3518 return delegate.createProperty('init', id, id, false, true); 3519 } 3520 if (token.type === Token.EOF || token.type === Token.Punctuator) { 3521 if (!match('*')) { 3522 throwUnexpected(token); 3523 } 3524 lex(); 3525 3526 id = parseObjectPropertyKey(); 3527 3528 if (!match('(')) { 3529 throwUnexpected(lex()); 3530 } 3531 3532 return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: true }), true, false); 3533 } 3534 key = parseObjectPropertyKey(); 3535 if (match(':')) { 3536 lex(); 3537 return delegate.createProperty('init', key, parseAssignmentExpression(), false, false); 3538 } 3539 if (match('(')) { 3540 return delegate.createProperty('init', key, parsePropertyMethodFunction({ generator: false }), true, false); 3541 } 3542 throwUnexpected(lex()); 3543 } 3544 3545 function parseObjectInitialiser() { 3546 var properties = [], property, name, key, kind, map = {}, toString = String; 3547 3548 expect('{'); 3549 3550 while (!match('}')) { 3551 property = parseObjectProperty(); 3552 3553 if (property.key.type === Syntax.Identifier) { 3554 name = property.key.name; 3555 } else { 3556 name = toString(property.key.value); 3557 } 3558 kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; 3559 3560 key = '$' + name; 3561 if (Object.prototype.hasOwnProperty.call(map, key)) { 3562 if (map[key] === PropertyKind.Data) { 3563 if (strict && kind === PropertyKind.Data) { 3564 throwErrorTolerant({}, Messages.StrictDuplicateProperty); 3565 } else if (kind !== PropertyKind.Data) { 3566 throwErrorTolerant({}, Messages.AccessorDataProperty); 3567 } 3568 } else { 3569 if (kind === PropertyKind.Data) { 3570 throwErrorTolerant({}, Messages.AccessorDataProperty); 3571 } else if (map[key] & kind) { 3572 throwErrorTolerant({}, Messages.AccessorGetSet); 3573 } 3574 } 3575 map[key] |= kind; 3576 } else { 3577 map[key] = kind; 3578 } 3579 3580 properties.push(property); 3581 3582 if (!match('}')) { 3583 expect(','); 3584 } 3585 } 3586 3587 expect('}'); 3588 3589 return delegate.createObjectExpression(properties); 3590 } 3591 3592 function parseTemplateElement(option) { 3593 var token = scanTemplateElement(option); 3594 if (strict && token.octal) { 3595 throwError(token, Messages.StrictOctalLiteral); 3596 } 3597 return delegate.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail); 3598 } 3599 3600 function parseTemplateLiteral() { 3601 var quasi, quasis, expressions; 3602 3603 quasi = parseTemplateElement({ head: true }); 3604 quasis = [ quasi ]; 3605 expressions = []; 3606 3607 while (!quasi.tail) { 3608 expressions.push(parseExpression()); 3609 quasi = parseTemplateElement({ head: false }); 3610 quasis.push(quasi); 3611 } 3612 3613 return delegate.createTemplateLiteral(quasis, expressions); 3614 } 3615 3616 // 11.1.6 The Grouping Operator 3617 3618 function parseGroupExpression() { 3619 var expr; 3620 3621 expect('('); 3622 3623 ++state.parenthesizedCount; 3624 3625 state.allowArrowFunction = !state.allowArrowFunction; 3626 expr = parseExpression(); 3627 state.allowArrowFunction = false; 3628 3629 if (expr.type !== Syntax.ArrowFunctionExpression) { 3630 expect(')'); 3631 } 3632 3633 return expr; 3634 } 3635 3636 3637 // 11.1 Primary Expressions 3638 3639 function parsePrimaryExpression() { 3640 var type, token; 3641 3642 token = lookahead; 3643 type = lookahead.type; 3644 3645 if (type === Token.Identifier) { 3646 lex(); 3647 return delegate.createIdentifier(token.value); 3648 } 3649 3650 if (type === Token.StringLiteral || type === Token.NumericLiteral) { 3651 if (strict && lookahead.octal) { 3652 throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); 3653 } 3654 return delegate.createLiteral(lex()); 3655 } 3656 3657 if (type === Token.Keyword) { 3658 if (matchKeyword('this')) { 3659 lex(); 3660 return delegate.createThisExpression(); 3661 } 3662 3663 if (matchKeyword('function')) { 3664 return parseFunctionExpression(); 3665 } 3666 3667 if (matchKeyword('class')) { 3668 return parseClassExpression(); 3669 } 3670 3671 if (matchKeyword('super')) { 3672 lex(); 3673 return delegate.createIdentifier('super'); 3674 } 3675 } 3676 3677 if (type === Token.BooleanLiteral) { 3678 token = lex(); 3679 token.value = (token.value === 'true'); 3680 return delegate.createLiteral(token); 3681 } 3682 3683 if (type === Token.NullLiteral) { 3684 token = lex(); 3685 token.value = null; 3686 return delegate.createLiteral(token); 3687 } 3688 3689 if (match('[')) { 3690 return parseArrayInitialiser(); 3691 } 3692 3693 if (match('{')) { 3694 return parseObjectInitialiser(); 3695 } 3696 3697 if (match('(')) { 3698 return parseGroupExpression(); 3699 } 3700 3701 if (match('/') || match('/=')) { 3702 return delegate.createLiteral(scanRegExp()); 3703 } 3704 3705 if (type === Token.Template) { 3706 return parseTemplateLiteral(); 3707 } 3708 3709 if (match('<')) { 3710 return parseXJSElement(); 3711 } 3712 3713 return throwUnexpected(lex()); 3714 } 3715 3716 // 11.2 Left-Hand-Side Expressions 3717 3718 function parseArguments() { 3719 var args = [], arg; 3720 3721 expect('('); 3722 3723 if (!match(')')) { 3724 while (index < length) { 3725 arg = parseSpreadOrAssignmentExpression(); 3726 args.push(arg); 3727 3728 if (match(')')) { 3729 break; 3730 } else if (arg.type === Syntax.SpreadElement) { 3731 throwError({}, Messages.ElementAfterSpreadElement); 3732 } 3733 3734 expect(','); 3735 } 3736 } 3737 3738 expect(')'); 3739 3740 return args; 3741 } 3742 3743 function parseSpreadOrAssignmentExpression() { 3744 if (match('...')) { 3745 lex(); 3746 return delegate.createSpreadElement(parseAssignmentExpression()); 3747 } 3748 return parseAssignmentExpression(); 3749 } 3750 3751 function parseNonComputedProperty() { 3752 var token = lex(); 3753 3754 if (!isIdentifierName(token)) { 3755 throwUnexpected(token); 3756 } 3757 3758 return delegate.createIdentifier(token.value); 3759 } 3760 3761 function parseNonComputedMember() { 3762 expect('.'); 3763 3764 return parseNonComputedProperty(); 3765 } 3766 3767 function parseComputedMember() { 3768 var expr; 3769 3770 expect('['); 3771 3772 expr = parseExpression(); 3773 3774 expect(']'); 3775 3776 return expr; 3777 } 3778 3779 function parseNewExpression() { 3780 var callee, args; 3781 3782 expectKeyword('new'); 3783 callee = parseLeftHandSideExpression(); 3784 args = match('(') ? parseArguments() : []; 3785 3786 return delegate.createNewExpression(callee, args); 3787 } 3788 3789 function parseLeftHandSideExpressionAllowCall() { 3790 var expr, args, property; 3791 3792 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); 3793 3794 while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) { 3795 if (match('(')) { 3796 args = parseArguments(); 3797 expr = delegate.createCallExpression(expr, args); 3798 } else if (match('[')) { 3799 expr = delegate.createMemberExpression('[', expr, parseComputedMember()); 3800 } else if (match('.')) { 3801 expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); 3802 } else { 3803 expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); 3804 } 3805 } 3806 3807 return expr; 3808 } 3809 3810 3811 function parseLeftHandSideExpression() { 3812 var expr, property; 3813 3814 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); 3815 3816 while (match('.') || match('[') || lookahead.type === Token.Template) { 3817 if (match('[')) { 3818 expr = delegate.createMemberExpression('[', expr, parseComputedMember()); 3819 } else if (match('.')) { 3820 expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); 3821 } else { 3822 expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); 3823 } 3824 } 3825 3826 return expr; 3827 } 3828 3829 // 11.3 Postfix Expressions 3830 3831 function parsePostfixExpression() { 3832 var expr = parseLeftHandSideExpressionAllowCall(), 3833 token = lookahead; 3834 3835 if (lookahead.type !== Token.Punctuator) { 3836 return expr; 3837 } 3838 3839 if ((match('++') || match('--')) && !peekLineTerminator()) { 3840 // 11.3.1, 11.3.2 3841 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { 3842 throwErrorTolerant({}, Messages.StrictLHSPostfix); 3843 } 3844 3845 if (!isLeftHandSide(expr)) { 3846 throwError({}, Messages.InvalidLHSInAssignment); 3847 } 3848 3849 token = lex(); 3850 expr = delegate.createPostfixExpression(token.value, expr); 3851 } 3852 3853 return expr; 3854 } 3855 3856 // 11.4 Unary Operators 3857 3858 function parseUnaryExpression() { 3859 var token, expr; 3860 3861 if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { 3862 return parsePostfixExpression(); 3863 } 3864 3865 if (match('++') || match('--')) { 3866 token = lex(); 3867 expr = parseUnaryExpression(); 3868 // 11.4.4, 11.4.5 3869 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { 3870 throwErrorTolerant({}, Messages.StrictLHSPrefix); 3871 } 3872 3873 if (!isLeftHandSide(expr)) { 3874 throwError({}, Messages.InvalidLHSInAssignment); 3875 } 3876 3877 return delegate.createUnaryExpression(token.value, expr); 3878 } 3879 3880 if (match('+') || match('-') || match('~') || match('!')) { 3881 token = lex(); 3882 expr = parseUnaryExpression(); 3883 return delegate.createUnaryExpression(token.value, expr); 3884 } 3885 3886 if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { 3887 token = lex(); 3888 expr = parseUnaryExpression(); 3889 expr = delegate.createUnaryExpression(token.value, expr); 3890 if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { 3891 throwErrorTolerant({}, Messages.StrictDelete); 3892 } 3893 return expr; 3894 } 3895 3896 return parsePostfixExpression(); 3897 } 3898 3899 function binaryPrecedence(token, allowIn) { 3900 var prec = 0; 3901 3902 if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { 3903 return 0; 3904 } 3905 3906 switch (token.value) { 3907 case '||': 3908 prec = 1; 3909 break; 3910 3911 case '&&': 3912 prec = 2; 3913 break; 3914 3915 case '|': 3916 prec = 3; 3917 break; 3918 3919 case '^': 3920 prec = 4; 3921 break; 3922 3923 case '&': 3924 prec = 5; 3925 break; 3926 3927 case '==': 3928 case '!=': 3929 case '===': 3930 case '!==': 3931 prec = 6; 3932 break; 3933 3934 case '<': 3935 case '>': 3936 case '<=': 3937 case '>=': 3938 case 'instanceof': 3939 prec = 7; 3940 break; 3941 3942 case 'in': 3943 prec = allowIn ? 7 : 0; 3944 break; 3945 3946 case '<<': 3947 case '>>': 3948 case '>>>': 3949 prec = 8; 3950 break; 3951 3952 case '+': 3953 case '-': 3954 prec = 9; 3955 break; 3956 3957 case '*': 3958 case '/': 3959 case '%': 3960 prec = 11; 3961 break; 3962 3963 default: 3964 break; 3965 } 3966 3967 return prec; 3968 } 3969 3970 // 11.5 Multiplicative Operators 3971 // 11.6 Additive Operators 3972 // 11.7 Bitwise Shift Operators 3973 // 11.8 Relational Operators 3974 // 11.9 Equality Operators 3975 // 11.10 Binary Bitwise Operators 3976 // 11.11 Binary Logical Operators 3977 3978 function parseBinaryExpression() { 3979 var expr, token, prec, previousAllowIn, stack, right, operator, left, i; 3980 3981 previousAllowIn = state.allowIn; 3982 state.allowIn = true; 3983 3984 expr = parseUnaryExpression(); 3985 3986 token = lookahead; 3987 prec = binaryPrecedence(token, previousAllowIn); 3988 if (prec === 0) { 3989 return expr; 3990 } 3991 token.prec = prec; 3992 lex(); 3993 3994 stack = [expr, token, parseUnaryExpression()]; 3995 3996 while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) { 3997 3998 // Reduce: make a binary expression from the three topmost entries. 3999 while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { 4000 right = stack.pop(); 4001 operator = stack.pop().value; 4002 left = stack.pop(); 4003 stack.push(delegate.createBinaryExpression(operator, left, right)); 4004 } 4005 4006 // Shift. 4007 token = lex(); 4008 token.prec = prec; 4009 stack.push(token); 4010 stack.push(parseUnaryExpression()); 4011 } 4012 4013 state.allowIn = previousAllowIn; 4014 4015 // Final reduce to clean-up the stack. 4016 i = stack.length - 1; 4017 expr = stack[i]; 4018 while (i > 1) { 4019 expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr); 4020 i -= 2; 4021 } 4022 return expr; 4023 } 4024 4025 4026 // 11.12 Conditional Operator 4027 4028 function parseConditionalExpression() { 4029 var expr, previousAllowIn, consequent, alternate; 4030 4031 expr = parseBinaryExpression(); 4032 4033 if (match('?')) { 4034 lex(); 4035 previousAllowIn = state.allowIn; 4036 state.allowIn = true; 4037 consequent = parseAssignmentExpression(); 4038 state.allowIn = previousAllowIn; 4039 expect(':'); 4040 alternate = parseAssignmentExpression(); 4041 4042 expr = delegate.createConditionalExpression(expr, consequent, alternate); 4043 } 4044 4045 return expr; 4046 } 4047 4048 // 11.13 Assignment Operators 4049 4050 function reinterpretAsAssignmentBindingPattern(expr) { 4051 var i, len, property, element; 4052 4053 if (expr.type === Syntax.ObjectExpression) { 4054 expr.type = Syntax.ObjectPattern; 4055 for (i = 0, len = expr.properties.length; i < len; i += 1) { 4056 property = expr.properties[i]; 4057 if (property.kind !== 'init') { 4058 throwError({}, Messages.InvalidLHSInAssignment); 4059 } 4060 reinterpretAsAssignmentBindingPattern(property.value); 4061 } 4062 } else if (expr.type === Syntax.ArrayExpression) { 4063 expr.type = Syntax.ArrayPattern; 4064 for (i = 0, len = expr.elements.length; i < len; i += 1) { 4065 element = expr.elements[i]; 4066 if (element) { 4067 reinterpretAsAssignmentBindingPattern(element); 4068 } 4069 } 4070 } else if (expr.type === Syntax.Identifier) { 4071 if (isRestrictedWord(expr.name)) { 4072 throwError({}, Messages.InvalidLHSInAssignment); 4073 } 4074 } else if (expr.type === Syntax.SpreadElement) { 4075 reinterpretAsAssignmentBindingPattern(expr.argument); 4076 if (expr.argument.type === Syntax.ObjectPattern) { 4077 throwError({}, Messages.ObjectPatternAsSpread); 4078 } 4079 } else { 4080 if (expr.type !== Syntax.MemberExpression && expr.type !== Syntax.CallExpression && expr.type !== Syntax.NewExpression) { 4081 throwError({}, Messages.InvalidLHSInAssignment); 4082 } 4083 } 4084 } 4085 4086 4087 function reinterpretAsDestructuredParameter(options, expr) { 4088 var i, len, property, element; 4089 4090 if (expr.type === Syntax.ObjectExpression) { 4091 expr.type = Syntax.ObjectPattern; 4092 for (i = 0, len = expr.properties.length; i < len; i += 1) { 4093 property = expr.properties[i]; 4094 if (property.kind !== 'init') { 4095 throwError({}, Messages.InvalidLHSInFormalsList); 4096 } 4097 reinterpretAsDestructuredParameter(options, property.value); 4098 } 4099 } else if (expr.type === Syntax.ArrayExpression) { 4100 expr.type = Syntax.ArrayPattern; 4101 for (i = 0, len = expr.elements.length; i < len; i += 1) { 4102 element = expr.elements[i]; 4103 if (element) { 4104 reinterpretAsDestructuredParameter(options, element); 4105 } 4106 } 4107 } else if (expr.type === Syntax.Identifier) { 4108 validateParam(options, expr, expr.name); 4109 } else { 4110 if (expr.type !== Syntax.MemberExpression) { 4111 throwError({}, Messages.InvalidLHSInFormalsList); 4112 } 4113 } 4114 } 4115 4116 function reinterpretAsCoverFormalsList(expressions) { 4117 var i, len, param, params, defaults, defaultCount, options, rest; 4118 4119 params = []; 4120 defaults = []; 4121 defaultCount = 0; 4122 rest = null; 4123 options = { 4124 paramSet: {} 4125 }; 4126 4127 for (i = 0, len = expressions.length; i < len; i += 1) { 4128 param = expressions[i]; 4129 if (param.type === Syntax.Identifier) { 4130 params.push(param); 4131 defaults.push(null); 4132 validateParam(options, param, param.name); 4133 } else if (param.type === Syntax.ObjectExpression || param.type === Syntax.ArrayExpression) { 4134 reinterpretAsDestructuredParameter(options, param); 4135 params.push(param); 4136 defaults.push(null); 4137 } else if (param.type === Syntax.SpreadElement) { 4138 assert(i === len - 1, "It is guaranteed that SpreadElement is last element by parseExpression"); 4139 reinterpretAsDestructuredParameter(options, param.argument); 4140 rest = param.argument; 4141 } else if (param.type === Syntax.AssignmentExpression) { 4142 params.push(param.left); 4143 defaults.push(param.right); 4144 ++defaultCount; 4145 } else { 4146 return null; 4147 } 4148 } 4149 4150 if (options.firstRestricted) { 4151 throwError(options.firstRestricted, options.message); 4152 } 4153 if (options.stricted) { 4154 throwErrorTolerant(options.stricted, options.message); 4155 } 4156 4157 if (defaultCount === 0) { 4158 defaults = []; 4159 } 4160 4161 return { params: params, defaults: defaults, rest: rest }; 4162 } 4163 4164 function parseArrowFunctionExpression(options) { 4165 var previousStrict, previousYieldAllowed, body; 4166 4167 expect('=>'); 4168 4169 previousStrict = strict; 4170 previousYieldAllowed = state.yieldAllowed; 4171 strict = true; 4172 state.yieldAllowed = false; 4173 body = parseConciseBody(); 4174 strict = previousStrict; 4175 state.yieldAllowed = previousYieldAllowed; 4176 4177 return delegate.createArrowFunctionExpression(options.params, options.defaults, body, options.rest, body.type !== Syntax.BlockStatement); 4178 } 4179 4180 function parseAssignmentExpression() { 4181 var expr, token, params, oldParenthesizedCount; 4182 4183 if (matchKeyword('yield')) { 4184 return parseYieldExpression(); 4185 } 4186 4187 oldParenthesizedCount = state.parenthesizedCount; 4188 4189 if (match('(')) { 4190 token = lookahead2(); 4191 if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') { 4192 params = parseParams(); 4193 if (!match('=>')) { 4194 throwUnexpected(lex()); 4195 } 4196 return parseArrowFunctionExpression(params); 4197 } 4198 } 4199 4200 token = lookahead; 4201 expr = parseConditionalExpression(); 4202 4203 if (match('=>') && expr.type === Syntax.Identifier) { 4204 if (state.parenthesizedCount === oldParenthesizedCount || state.parenthesizedCount === (oldParenthesizedCount + 1)) { 4205 if (isRestrictedWord(expr.name)) { 4206 throwError({}, Messages.StrictParamName); 4207 } 4208 return parseArrowFunctionExpression({ params: [ expr ], defaults: [], rest: null }); 4209 } 4210 } 4211 4212 if (matchAssign()) { 4213 // 11.13.1 4214 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { 4215 throwErrorTolerant(token, Messages.StrictLHSAssignment); 4216 } 4217 4218 // ES.next draf 11.13 Runtime Semantics step 1 4219 if (match('=') && (expr.type === Syntax.ObjectExpression || expr.type === Syntax.ArrayExpression)) { 4220 reinterpretAsAssignmentBindingPattern(expr); 4221 } else if (!isLeftHandSide(expr)) { 4222 throwError({}, Messages.InvalidLHSInAssignment); 4223 } 4224 4225 expr = delegate.createAssignmentExpression(lex().value, expr, parseAssignmentExpression()); 4226 } 4227 4228 return expr; 4229 } 4230 4231 // 11.14 Comma Operator 4232 4233 function parseExpression() { 4234 var expr, expressions, sequence, coverFormalsList, spreadFound, token; 4235 4236 expr = parseAssignmentExpression(); 4237 expressions = [ expr ]; 4238 4239 if (match(',')) { 4240 while (index < length) { 4241 if (!match(',')) { 4242 break; 4243 } 4244 4245 lex(); 4246 expr = parseSpreadOrAssignmentExpression(); 4247 expressions.push(expr); 4248 4249 if (expr.type === Syntax.SpreadElement) { 4250 spreadFound = true; 4251 if (!match(')')) { 4252 throwError({}, Messages.ElementAfterSpreadElement); 4253 } 4254 break; 4255 } 4256 } 4257 4258 sequence = delegate.createSequenceExpression(expressions); 4259 } 4260 4261 if (state.allowArrowFunction && match(')')) { 4262 token = lookahead2(); 4263 if (token.value === '=>') { 4264 lex(); 4265 4266 state.allowArrowFunction = false; 4267 expr = expressions; 4268 coverFormalsList = reinterpretAsCoverFormalsList(expr); 4269 if (coverFormalsList) { 4270 return parseArrowFunctionExpression(coverFormalsList); 4271 } 4272 4273 throwUnexpected(token); 4274 } 4275 } 4276 4277 if (spreadFound) { 4278 throwError({}, Messages.IllegalSpread); 4279 } 4280 4281 return sequence || expr; 4282 } 4283 4284 // 12.1 Block 4285 4286 function parseStatementList() { 4287 var list = [], 4288 statement; 4289 4290 while (index < length) { 4291 if (match('}')) { 4292 break; 4293 } 4294 statement = parseSourceElement(); 4295 if (typeof statement === 'undefined') { 4296 break; 4297 } 4298 list.push(statement); 4299 } 4300 4301 return list; 4302 } 4303 4304 function parseBlock() { 4305 var block; 4306 4307 expect('{'); 4308 4309 block = parseStatementList(); 4310 4311 expect('}'); 4312 4313 return delegate.createBlockStatement(block); 4314 } 4315 4316 // 12.2 Variable Statement 4317 4318 function parseTypeAnnotation(dontExpectColon) { 4319 var typeIdentifier = null, paramTypes = null, returnType = null, 4320 isNullable = false; 4321 4322 if (!dontExpectColon) { 4323 expect(':'); 4324 } 4325 4326 if (match('?')) { 4327 lex(); 4328 isNullable = true; 4329 } 4330 4331 if (lookahead.type === Token.Identifier) { 4332 typeIdentifier = parseVariableIdentifier(); 4333 } 4334 4335 if (match('(')) { 4336 lex(); 4337 paramTypes = []; 4338 while (lookahead.type === Token.Identifier || match('?')) { 4339 paramTypes.push(parseTypeAnnotation(true)); 4340 if (!match(')')) { 4341 expect(','); 4342 } 4343 } 4344 expect(')'); 4345 expect('=>'); 4346 4347 if (matchKeyword('void')) { 4348 lex(); 4349 } else { 4350 returnType = parseTypeAnnotation(true); 4351 } 4352 } 4353 4354 return delegate.createTypeAnnotation( 4355 typeIdentifier, 4356 paramTypes, 4357 returnType, 4358 isNullable 4359 ); 4360 } 4361 4362 function parseVariableIdentifier() { 4363 var token = lex(); 4364 4365 if (token.type !== Token.Identifier) { 4366 throwUnexpected(token); 4367 } 4368 4369 return delegate.createIdentifier(token.value); 4370 } 4371 4372 function parseTypeAnnotatableIdentifier() { 4373 var ident = parseVariableIdentifier(); 4374 4375 if (match(':')) { 4376 return delegate.createTypeAnnotatedIdentifier(ident, parseTypeAnnotation()); 4377 } 4378 4379 return ident; 4380 } 4381 4382 function parseVariableDeclaration(kind) { 4383 var id, 4384 init = null; 4385 if (match('{')) { 4386 id = parseObjectInitialiser(); 4387 reinterpretAsAssignmentBindingPattern(id); 4388 } else if (match('[')) { 4389 id = parseArrayInitialiser(); 4390 reinterpretAsAssignmentBindingPattern(id); 4391 } else { 4392 id = state.allowKeyword ? parseNonComputedProperty() : parseTypeAnnotatableIdentifier(); 4393 // 12.2.1 4394 if (strict && isRestrictedWord(id.name)) { 4395 throwErrorTolerant({}, Messages.StrictVarName); 4396 } 4397 } 4398 4399 if (kind === 'const') { 4400 if (!match('=')) { 4401 throwError({}, Messages.NoUnintializedConst); 4402 } 4403 expect('='); 4404 init = parseAssignmentExpression(); 4405 } else if (match('=')) { 4406 lex(); 4407 init = parseAssignmentExpression(); 4408 } 4409 4410 return delegate.createVariableDeclarator(id, init); 4411 } 4412 4413 function parseVariableDeclarationList(kind) { 4414 var list = []; 4415 4416 do { 4417 list.push(parseVariableDeclaration(kind)); 4418 if (!match(',')) { 4419 break; 4420 } 4421 lex(); 4422 } while (index < length); 4423 4424 return list; 4425 } 4426 4427 function parseVariableStatement() { 4428 var declarations; 4429 4430 expectKeyword('var'); 4431 4432 declarations = parseVariableDeclarationList(); 4433 4434 consumeSemicolon(); 4435 4436 return delegate.createVariableDeclaration(declarations, 'var'); 4437 } 4438 4439 // kind may be `const` or `let` 4440 // Both are experimental and not in the specification yet. 4441 // see http://wiki.ecmascript.org/doku.php?id=harmony:const 4442 // and http://wiki.ecmascript.org/doku.php?id=harmony:let 4443 function parseConstLetDeclaration(kind) { 4444 var declarations; 4445 4446 expectKeyword(kind); 4447 4448 declarations = parseVariableDeclarationList(kind); 4449 4450 consumeSemicolon(); 4451 4452 return delegate.createVariableDeclaration(declarations, kind); 4453 } 4454 4455 // http://wiki.ecmascript.org/doku.php?id=harmony:modules 4456 4457 function parseModuleDeclaration() { 4458 var id, src, body; 4459 4460 lex(); // 'module' 4461 4462 if (peekLineTerminator()) { 4463 throwError({}, Messages.NewlineAfterModule); 4464 } 4465 4466 switch (lookahead.type) { 4467 4468 case Token.StringLiteral: 4469 id = parsePrimaryExpression(); 4470 body = parseModuleBlock(); 4471 src = null; 4472 break; 4473 4474 case Token.Identifier: 4475 id = parseVariableIdentifier(); 4476 body = null; 4477 if (!matchContextualKeyword('from')) { 4478 throwUnexpected(lex()); 4479 } 4480 lex(); 4481 src = parsePrimaryExpression(); 4482 if (src.type !== Syntax.Literal) { 4483 throwError({}, Messages.InvalidModuleSpecifier); 4484 } 4485 break; 4486 } 4487 4488 consumeSemicolon(); 4489 return delegate.createModuleDeclaration(id, src, body); 4490 } 4491 4492 function parseExportBatchSpecifier() { 4493 expect('*'); 4494 return delegate.createExportBatchSpecifier(); 4495 } 4496 4497 function parseExportSpecifier() { 4498 var id, name = null; 4499 4500 id = parseVariableIdentifier(); 4501 if (matchContextualKeyword('as')) { 4502 lex(); 4503 name = parseNonComputedProperty(); 4504 } 4505 4506 return delegate.createExportSpecifier(id, name); 4507 } 4508 4509 function parseExportDeclaration() { 4510 var previousAllowKeyword, decl, def, src, specifiers; 4511 4512 expectKeyword('export'); 4513 4514 if (lookahead.type === Token.Keyword) { 4515 switch (lookahead.value) { 4516 case 'let': 4517 case 'const': 4518 case 'var': 4519 case 'class': 4520 case 'function': 4521 return delegate.createExportDeclaration(parseSourceElement(), null, null); 4522 } 4523 } 4524 4525 if (isIdentifierName(lookahead)) { 4526 previousAllowKeyword = state.allowKeyword; 4527 state.allowKeyword = true; 4528 decl = parseVariableDeclarationList('let'); 4529 state.allowKeyword = previousAllowKeyword; 4530 return delegate.createExportDeclaration(decl, null, null); 4531 } 4532 4533 specifiers = []; 4534 src = null; 4535 4536 if (match('*')) { 4537 specifiers.push(parseExportBatchSpecifier()); 4538 } else { 4539 expect('{'); 4540 do { 4541 specifiers.push(parseExportSpecifier()); 4542 } while (match(',') && lex()); 4543 expect('}'); 4544 } 4545 4546 if (matchContextualKeyword('from')) { 4547 lex(); 4548 src = parsePrimaryExpression(); 4549 if (src.type !== Syntax.Literal) { 4550 throwError({}, Messages.InvalidModuleSpecifier); 4551 } 4552 } 4553 4554 consumeSemicolon(); 4555 4556 return delegate.createExportDeclaration(null, specifiers, src); 4557 } 4558 4559 function parseImportDeclaration() { 4560 var specifiers, kind, src; 4561 4562 expectKeyword('import'); 4563 specifiers = []; 4564 4565 if (isIdentifierName(lookahead)) { 4566 kind = 'default'; 4567 specifiers.push(parseImportSpecifier()); 4568 4569 if (!matchContextualKeyword('from')) { 4570 throwError({}, Messages.NoFromAfterImport); 4571 } 4572 lex(); 4573 } else if (match('{')) { 4574 kind = 'named'; 4575 lex(); 4576 do { 4577 specifiers.push(parseImportSpecifier()); 4578 } while (match(',') && lex()); 4579 expect('}'); 4580 4581 if (!matchContextualKeyword('from')) { 4582 throwError({}, Messages.NoFromAfterImport); 4583 } 4584 lex(); 4585 } 4586 4587 src = parsePrimaryExpression(); 4588 if (src.type !== Syntax.Literal) { 4589 throwError({}, Messages.InvalidModuleSpecifier); 4590 } 4591 4592 consumeSemicolon(); 4593 4594 return delegate.createImportDeclaration(specifiers, kind, src); 4595 } 4596 4597 function parseImportSpecifier() { 4598 var id, name = null; 4599 4600 id = parseNonComputedProperty(); 4601 if (matchContextualKeyword('as')) { 4602 lex(); 4603 name = parseVariableIdentifier(); 4604 } 4605 4606 return delegate.createImportSpecifier(id, name); 4607 } 4608 4609 // 12.3 Empty Statement 4610 4611 function parseEmptyStatement() { 4612 expect(';'); 4613 return delegate.createEmptyStatement(); 4614 } 4615 4616 // 12.4 Expression Statement 4617 4618 function parseExpressionStatement() { 4619 var expr = parseExpression(); 4620 consumeSemicolon(); 4621 return delegate.createExpressionStatement(expr); 4622 } 4623 4624 // 12.5 If statement 4625 4626 function parseIfStatement() { 4627 var test, consequent, alternate; 4628 4629 expectKeyword('if'); 4630 4631 expect('('); 4632 4633 test = parseExpression(); 4634 4635 expect(')'); 4636 4637 consequent = parseStatement(); 4638 4639 if (matchKeyword('else')) { 4640 lex(); 4641 alternate = parseStatement(); 4642 } else { 4643 alternate = null; 4644 } 4645 4646 return delegate.createIfStatement(test, consequent, alternate); 4647 } 4648 4649 // 12.6 Iteration Statements 4650 4651 function parseDoWhileStatement() { 4652 var body, test, oldInIteration; 4653 4654 expectKeyword('do'); 4655 4656 oldInIteration = state.inIteration; 4657 state.inIteration = true; 4658 4659 body = parseStatement(); 4660 4661 state.inIteration = oldInIteration; 4662 4663 expectKeyword('while'); 4664 4665 expect('('); 4666 4667 test = parseExpression(); 4668 4669 expect(')'); 4670 4671 if (match(';')) { 4672 lex(); 4673 } 4674 4675 return delegate.createDoWhileStatement(body, test); 4676 } 4677 4678 function parseWhileStatement() { 4679 var test, body, oldInIteration; 4680 4681 expectKeyword('while'); 4682 4683 expect('('); 4684 4685 test = parseExpression(); 4686 4687 expect(')'); 4688 4689 oldInIteration = state.inIteration; 4690 state.inIteration = true; 4691 4692 body = parseStatement(); 4693 4694 state.inIteration = oldInIteration; 4695 4696 return delegate.createWhileStatement(test, body); 4697 } 4698 4699 function parseForVariableDeclaration() { 4700 var token = lex(), 4701 declarations = parseVariableDeclarationList(); 4702 4703 return delegate.createVariableDeclaration(declarations, token.value); 4704 } 4705 4706 function parseForStatement(opts) { 4707 var init, test, update, left, right, body, operator, oldInIteration; 4708 init = test = update = null; 4709 expectKeyword('for'); 4710 4711 // http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators&s=each 4712 if (matchContextualKeyword("each")) { 4713 throwError({}, Messages.EachNotAllowed); 4714 } 4715 4716 expect('('); 4717 4718 if (match(';')) { 4719 lex(); 4720 } else { 4721 if (matchKeyword('var') || matchKeyword('let') || matchKeyword('const')) { 4722 state.allowIn = false; 4723 init = parseForVariableDeclaration(); 4724 state.allowIn = true; 4725 4726 if (init.declarations.length === 1) { 4727 if (matchKeyword('in') || matchContextualKeyword('of')) { 4728 operator = lookahead; 4729 if (!((operator.value === 'in' || init.kind !== 'var') && init.declarations[0].init)) { 4730 lex(); 4731 left = init; 4732 right = parseExpression(); 4733 init = null; 4734 } 4735 } 4736 } 4737 } else { 4738 state.allowIn = false; 4739 init = parseExpression(); 4740 state.allowIn = true; 4741 4742 if (matchContextualKeyword('of')) { 4743 operator = lex(); 4744 left = init; 4745 right = parseExpression(); 4746 init = null; 4747 } else if (matchKeyword('in')) { 4748 // LeftHandSideExpression 4749 if (!isAssignableLeftHandSide(init)) { 4750 throwError({}, Messages.InvalidLHSInForIn); 4751 } 4752 operator = lex(); 4753 left = init; 4754 right = parseExpression(); 4755 init = null; 4756 } 4757 } 4758 4759 if (typeof left === 'undefined') { 4760 expect(';'); 4761 } 4762 } 4763 4764 if (typeof left === 'undefined') { 4765 4766 if (!match(';')) { 4767 test = parseExpression(); 4768 } 4769 expect(';'); 4770 4771 if (!match(')')) { 4772 update = parseExpression(); 4773 } 4774 } 4775 4776 expect(')'); 4777 4778 oldInIteration = state.inIteration; 4779 state.inIteration = true; 4780 4781 if (!(opts !== undefined && opts.ignore_body)) { 4782 body = parseStatement(); 4783 } 4784 4785 state.inIteration = oldInIteration; 4786 4787 if (typeof left === 'undefined') { 4788 return delegate.createForStatement(init, test, update, body); 4789 } 4790 4791 if (operator.value === 'in') { 4792 return delegate.createForInStatement(left, right, body); 4793 } 4794 return delegate.createForOfStatement(left, right, body); 4795 } 4796 4797 // 12.7 The continue statement 4798 4799 function parseContinueStatement() { 4800 var label = null, key; 4801 4802 expectKeyword('continue'); 4803 4804 // Optimize the most common form: 'continue;'. 4805 if (source.charCodeAt(index) === 59) { 4806 lex(); 4807 4808 if (!state.inIteration) { 4809 throwError({}, Messages.IllegalContinue); 4810 } 4811 4812 return delegate.createContinueStatement(null); 4813 } 4814 4815 if (peekLineTerminator()) { 4816 if (!state.inIteration) { 4817 throwError({}, Messages.IllegalContinue); 4818 } 4819 4820 return delegate.createContinueStatement(null); 4821 } 4822 4823 if (lookahead.type === Token.Identifier) { 4824 label = parseVariableIdentifier(); 4825 4826 key = '$' + label.name; 4827 if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { 4828 throwError({}, Messages.UnknownLabel, label.name); 4829 } 4830 } 4831 4832 consumeSemicolon(); 4833 4834 if (label === null && !state.inIteration) { 4835 throwError({}, Messages.IllegalContinue); 4836 } 4837 4838 return delegate.createContinueStatement(label); 4839 } 4840 4841 // 12.8 The break statement 4842 4843 function parseBreakStatement() { 4844 var label = null, key; 4845 4846 expectKeyword('break'); 4847 4848 // Catch the very common case first: immediately a semicolon (char #59). 4849 if (source.charCodeAt(index) === 59) { 4850 lex(); 4851 4852 if (!(state.inIteration || state.inSwitch)) { 4853 throwError({}, Messages.IllegalBreak); 4854 } 4855 4856 return delegate.createBreakStatement(null); 4857 } 4858 4859 if (peekLineTerminator()) { 4860 if (!(state.inIteration || state.inSwitch)) { 4861 throwError({}, Messages.IllegalBreak); 4862 } 4863 4864 return delegate.createBreakStatement(null); 4865 } 4866 4867 if (lookahead.type === Token.Identifier) { 4868 label = parseVariableIdentifier(); 4869 4870 key = '$' + label.name; 4871 if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { 4872 throwError({}, Messages.UnknownLabel, label.name); 4873 } 4874 } 4875 4876 consumeSemicolon(); 4877 4878 if (label === null && !(state.inIteration || state.inSwitch)) { 4879 throwError({}, Messages.IllegalBreak); 4880 } 4881 4882 return delegate.createBreakStatement(label); 4883 } 4884 4885 // 12.9 The return statement 4886 4887 function parseReturnStatement() { 4888 var argument = null; 4889 4890 expectKeyword('return'); 4891 4892 if (!state.inFunctionBody) { 4893 throwErrorTolerant({}, Messages.IllegalReturn); 4894 } 4895 4896 // 'return' followed by a space and an identifier is very common. 4897 if (source.charCodeAt(index) === 32) { 4898 if (isIdentifierStart(source.charCodeAt(index + 1))) { 4899 argument = parseExpression(); 4900 consumeSemicolon(); 4901 return delegate.createReturnStatement(argument); 4902 } 4903 } 4904 4905 if (peekLineTerminator()) { 4906 return delegate.createReturnStatement(null); 4907 } 4908 4909 if (!match(';')) { 4910 if (!match('}') && lookahead.type !== Token.EOF) { 4911 argument = parseExpression(); 4912 } 4913 } 4914 4915 consumeSemicolon(); 4916 4917 return delegate.createReturnStatement(argument); 4918 } 4919 4920 // 12.10 The with statement 4921 4922 function parseWithStatement() { 4923 var object, body; 4924 4925 if (strict) { 4926 throwErrorTolerant({}, Messages.StrictModeWith); 4927 } 4928 4929 expectKeyword('with'); 4930 4931 expect('('); 4932 4933 object = parseExpression(); 4934 4935 expect(')'); 4936 4937 body = parseStatement(); 4938 4939 return delegate.createWithStatement(object, body); 4940 } 4941 4942 // 12.10 The swith statement 4943 4944 function parseSwitchCase() { 4945 var test, 4946 consequent = [], 4947 sourceElement; 4948 4949 if (matchKeyword('default')) { 4950 lex(); 4951 test = null; 4952 } else { 4953 expectKeyword('case'); 4954 test = parseExpression(); 4955 } 4956 expect(':'); 4957 4958 while (index < length) { 4959 if (match('}') || matchKeyword('default') || matchKeyword('case')) { 4960 break; 4961 } 4962 sourceElement = parseSourceElement(); 4963 if (typeof sourceElement === 'undefined') { 4964 break; 4965 } 4966 consequent.push(sourceElement); 4967 } 4968 4969 return delegate.createSwitchCase(test, consequent); 4970 } 4971 4972 function parseSwitchStatement() { 4973 var discriminant, cases, clause, oldInSwitch, defaultFound; 4974 4975 expectKeyword('switch'); 4976 4977 expect('('); 4978 4979 discriminant = parseExpression(); 4980 4981 expect(')'); 4982 4983 expect('{'); 4984 4985 cases = []; 4986 4987 if (match('}')) { 4988 lex(); 4989 return delegate.createSwitchStatement(discriminant, cases); 4990 } 4991 4992 oldInSwitch = state.inSwitch; 4993 state.inSwitch = true; 4994 defaultFound = false; 4995 4996 while (index < length) { 4997 if (match('}')) { 4998 break; 4999 } 5000 clause = parseSwitchCase(); 5001 if (clause.test === null) { 5002 if (defaultFound) { 5003 throwError({}, Messages.MultipleDefaultsInSwitch); 5004 } 5005 defaultFound = true; 5006 } 5007 cases.push(clause); 5008 } 5009 5010 state.inSwitch = oldInSwitch; 5011 5012 expect('}'); 5013 5014 return delegate.createSwitchStatement(discriminant, cases); 5015 } 5016 5017 // 12.13 The throw statement 5018 5019 function parseThrowStatement() { 5020 var argument; 5021 5022 expectKeyword('throw'); 5023 5024 if (peekLineTerminator()) { 5025 throwError({}, Messages.NewlineAfterThrow); 5026 } 5027 5028 argument = parseExpression(); 5029 5030 consumeSemicolon(); 5031 5032 return delegate.createThrowStatement(argument); 5033 } 5034 5035 // 12.14 The try statement 5036 5037 function parseCatchClause() { 5038 var param, body; 5039 5040 expectKeyword('catch'); 5041 5042 expect('('); 5043 if (match(')')) { 5044 throwUnexpected(lookahead); 5045 } 5046 5047 param = parseExpression(); 5048 // 12.14.1 5049 if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) { 5050 throwErrorTolerant({}, Messages.StrictCatchVariable); 5051 } 5052 5053 expect(')'); 5054 body = parseBlock(); 5055 return delegate.createCatchClause(param, body); 5056 } 5057 5058 function parseTryStatement() { 5059 var block, handlers = [], finalizer = null; 5060 5061 expectKeyword('try'); 5062 5063 block = parseBlock(); 5064 5065 if (matchKeyword('catch')) { 5066 handlers.push(parseCatchClause()); 5067 } 5068 5069 if (matchKeyword('finally')) { 5070 lex(); 5071 finalizer = parseBlock(); 5072 } 5073 5074 if (handlers.length === 0 && !finalizer) { 5075 throwError({}, Messages.NoCatchOrFinally); 5076 } 5077 5078 return delegate.createTryStatement(block, [], handlers, finalizer); 5079 } 5080 5081 // 12.15 The debugger statement 5082 5083 function parseDebuggerStatement() { 5084 expectKeyword('debugger'); 5085 5086 consumeSemicolon(); 5087 5088 return delegate.createDebuggerStatement(); 5089 } 5090 5091 // 12 Statements 5092 5093 function parseStatement() { 5094 var type = lookahead.type, 5095 expr, 5096 labeledBody, 5097 key; 5098 5099 if (type === Token.EOF) { 5100 throwUnexpected(lookahead); 5101 } 5102 5103 if (type === Token.Punctuator) { 5104 switch (lookahead.value) { 5105 case ';': 5106 return parseEmptyStatement(); 5107 case '{': 5108 return parseBlock(); 5109 case '(': 5110 return parseExpressionStatement(); 5111 default: 5112 break; 5113 } 5114 } 5115 5116 if (type === Token.Keyword) { 5117 switch (lookahead.value) { 5118 case 'break': 5119 return parseBreakStatement(); 5120 case 'continue': 5121 return parseContinueStatement(); 5122 case 'debugger': 5123 return parseDebuggerStatement(); 5124 case 'do': 5125 return parseDoWhileStatement(); 5126 case 'for': 5127 return parseForStatement(); 5128 case 'function': 5129 return parseFunctionDeclaration(); 5130 case 'class': 5131 return parseClassDeclaration(); 5132 case 'if': 5133 return parseIfStatement(); 5134 case 'return': 5135 return parseReturnStatement(); 5136 case 'switch': 5137 return parseSwitchStatement(); 5138 case 'throw': 5139 return parseThrowStatement(); 5140 case 'try': 5141 return parseTryStatement(); 5142 case 'var': 5143 return parseVariableStatement(); 5144 case 'while': 5145 return parseWhileStatement(); 5146 case 'with': 5147 return parseWithStatement(); 5148 default: 5149 break; 5150 } 5151 } 5152 5153 expr = parseExpression(); 5154 5155 // 12.12 Labelled Statements 5156 if ((expr.type === Syntax.Identifier) && match(':')) { 5157 lex(); 5158 5159 key = '$' + expr.name; 5160 if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { 5161 throwError({}, Messages.Redeclaration, 'Label', expr.name); 5162 } 5163 5164 state.labelSet[key] = true; 5165 labeledBody = parseStatement(); 5166 delete state.labelSet[key]; 5167 return delegate.createLabeledStatement(expr, labeledBody); 5168 } 5169 5170 consumeSemicolon(); 5171 5172 return delegate.createExpressionStatement(expr); 5173 } 5174 5175 // 13 Function Definition 5176 5177 function parseConciseBody() { 5178 if (match('{')) { 5179 return parseFunctionSourceElements(); 5180 } 5181 return parseAssignmentExpression(); 5182 } 5183 5184 function parseFunctionSourceElements() { 5185 var sourceElement, sourceElements = [], token, directive, firstRestricted, 5186 oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesizedCount; 5187 5188 expect('{'); 5189 5190 while (index < length) { 5191 if (lookahead.type !== Token.StringLiteral) { 5192 break; 5193 } 5194 token = lookahead; 5195 5196 sourceElement = parseSourceElement(); 5197 sourceElements.push(sourceElement); 5198 if (sourceElement.expression.type !== Syntax.Literal) { 5199 // this is not directive 5200 break; 5201 } 5202 directive = source.slice(token.range[0] + 1, token.range[1] - 1); 5203 if (directive === 'use strict') { 5204 strict = true; 5205 if (firstRestricted) { 5206 throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); 5207 } 5208 } else { 5209 if (!firstRestricted && token.octal) { 5210 firstRestricted = token; 5211 } 5212 } 5213 } 5214 5215 oldLabelSet = state.labelSet; 5216 oldInIteration = state.inIteration; 5217 oldInSwitch = state.inSwitch; 5218 oldInFunctionBody = state.inFunctionBody; 5219 oldParenthesizedCount = state.parenthesizedCount; 5220 5221 state.labelSet = {}; 5222 state.inIteration = false; 5223 state.inSwitch = false; 5224 state.inFunctionBody = true; 5225 state.parenthesizedCount = 0; 5226 5227 while (index < length) { 5228 if (match('}')) { 5229 break; 5230 } 5231 sourceElement = parseSourceElement(); 5232 if (typeof sourceElement === 'undefined') { 5233 break; 5234 } 5235 sourceElements.push(sourceElement); 5236 } 5237 5238 expect('}'); 5239 5240 state.labelSet = oldLabelSet; 5241 state.inIteration = oldInIteration; 5242 state.inSwitch = oldInSwitch; 5243 state.inFunctionBody = oldInFunctionBody; 5244 state.parenthesizedCount = oldParenthesizedCount; 5245 5246 return delegate.createBlockStatement(sourceElements); 5247 } 5248 5249 function validateParam(options, param, name) { 5250 var key = '$' + name; 5251 if (strict) { 5252 if (isRestrictedWord(name)) { 5253 options.stricted = param; 5254 options.message = Messages.StrictParamName; 5255 } 5256 if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { 5257 options.stricted = param; 5258 options.message = Messages.StrictParamDupe; 5259 } 5260 } else if (!options.firstRestricted) { 5261 if (isRestrictedWord(name)) { 5262 options.firstRestricted = param; 5263 options.message = Messages.StrictParamName; 5264 } else if (isStrictModeReservedWord(name)) { 5265 options.firstRestricted = param; 5266 options.message = Messages.StrictReservedWord; 5267 } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { 5268 options.firstRestricted = param; 5269 options.message = Messages.StrictParamDupe; 5270 } 5271 } 5272 options.paramSet[key] = true; 5273 } 5274 5275 function parseParam(options) { 5276 var token, rest, param, def; 5277 5278 token = lookahead; 5279 if (token.value === '...') { 5280 token = lex(); 5281 rest = true; 5282 } 5283 5284 if (match('[')) { 5285 param = parseArrayInitialiser(); 5286 reinterpretAsDestructuredParameter(options, param); 5287 } else if (match('{')) { 5288 if (rest) { 5289 throwError({}, Messages.ObjectPatternAsRestParameter); 5290 } 5291 param = parseObjectInitialiser(); 5292 reinterpretAsDestructuredParameter(options, param); 5293 } else { 5294 // Typing rest params is awkward, so punting on that for now 5295 param = rest 5296 ? parseVariableIdentifier() 5297 : parseTypeAnnotatableIdentifier(); 5298 validateParam(options, token, token.value); 5299 if (match('=')) { 5300 if (rest) { 5301 throwErrorTolerant(lookahead, Messages.DefaultRestParameter); 5302 } 5303 lex(); 5304 def = parseAssignmentExpression(); 5305 ++options.defaultCount; 5306 } 5307 } 5308 5309 if (rest) { 5310 if (!match(')')) { 5311 throwError({}, Messages.ParameterAfterRestParameter); 5312 } 5313 options.rest = param; 5314 return false; 5315 } 5316 5317 options.params.push(param); 5318 options.defaults.push(def); 5319 return !match(')'); 5320 } 5321 5322 function parseParams(firstRestricted) { 5323 var options; 5324 5325 options = { 5326 params: [], 5327 defaultCount: 0, 5328 defaults: [], 5329 rest: null, 5330 firstRestricted: firstRestricted 5331 }; 5332 5333 expect('('); 5334 5335 if (!match(')')) { 5336 options.paramSet = {}; 5337 while (index < length) { 5338 if (!parseParam(options)) { 5339 break; 5340 } 5341 expect(','); 5342 } 5343 } 5344 5345 expect(')'); 5346 5347 if (options.defaultCount === 0) { 5348 options.defaults = []; 5349 } 5350 5351 if (match(':')) { 5352 options.returnTypeAnnotation = parseTypeAnnotation(); 5353 } 5354 5355 return options; 5356 } 5357 5358 function parseFunctionDeclaration() { 5359 var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator, expression; 5360 5361 expectKeyword('function'); 5362 5363 generator = false; 5364 if (match('*')) { 5365 lex(); 5366 generator = true; 5367 } 5368 5369 token = lookahead; 5370 5371 id = parseVariableIdentifier(); 5372 5373 if (strict) { 5374 if (isRestrictedWord(token.value)) { 5375 throwErrorTolerant(token, Messages.StrictFunctionName); 5376 } 5377 } else { 5378 if (isRestrictedWord(token.value)) { 5379 firstRestricted = token; 5380 message = Messages.StrictFunctionName; 5381 } else if (isStrictModeReservedWord(token.value)) { 5382 firstRestricted = token; 5383 message = Messages.StrictReservedWord; 5384 } 5385 } 5386 5387 tmp = parseParams(firstRestricted); 5388 firstRestricted = tmp.firstRestricted; 5389 if (tmp.message) { 5390 message = tmp.message; 5391 } 5392 5393 previousStrict = strict; 5394 previousYieldAllowed = state.yieldAllowed; 5395 state.yieldAllowed = generator; 5396 5397 // here we redo some work in order to set 'expression' 5398 expression = !match('{'); 5399 body = parseConciseBody(); 5400 5401 if (strict && firstRestricted) { 5402 throwError(firstRestricted, message); 5403 } 5404 if (strict && tmp.stricted) { 5405 throwErrorTolerant(tmp.stricted, message); 5406 } 5407 if (state.yieldAllowed && !state.yieldFound) { 5408 throwErrorTolerant({}, Messages.NoYieldInGenerator); 5409 } 5410 strict = previousStrict; 5411 state.yieldAllowed = previousYieldAllowed; 5412 5413 return delegate.createFunctionDeclaration(id, tmp.params, tmp.defaults, body, tmp.rest, generator, expression, 5414 tmp.returnTypeAnnotation); 5415 } 5416 5417 function parseFunctionExpression() { 5418 var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator, expression; 5419 5420 expectKeyword('function'); 5421 5422 generator = false; 5423 5424 if (match('*')) { 5425 lex(); 5426 generator = true; 5427 } 5428 5429 if (!match('(')) { 5430 token = lookahead; 5431 id = parseVariableIdentifier(); 5432 if (strict) { 5433 if (isRestrictedWord(token.value)) { 5434 throwErrorTolerant(token, Messages.StrictFunctionName); 5435 } 5436 } else { 5437 if (isRestrictedWord(token.value)) { 5438 firstRestricted = token; 5439 message = Messages.StrictFunctionName; 5440 } else if (isStrictModeReservedWord(token.value)) { 5441 firstRestricted = token; 5442 message = Messages.StrictReservedWord; 5443 } 5444 } 5445 } 5446 5447 tmp = parseParams(firstRestricted); 5448 firstRestricted = tmp.firstRestricted; 5449 if (tmp.message) { 5450 message = tmp.message; 5451 } 5452 5453 previousStrict = strict; 5454 previousYieldAllowed = state.yieldAllowed; 5455 state.yieldAllowed = generator; 5456 5457 // here we redo some work in order to set 'expression' 5458 expression = !match('{'); 5459 body = parseConciseBody(); 5460 5461 if (strict && firstRestricted) { 5462 throwError(firstRestricted, message); 5463 } 5464 if (strict && tmp.stricted) { 5465 throwErrorTolerant(tmp.stricted, message); 5466 } 5467 if (state.yieldAllowed && !state.yieldFound) { 5468 throwErrorTolerant({}, Messages.NoYieldInGenerator); 5469 } 5470 strict = previousStrict; 5471 state.yieldAllowed = previousYieldAllowed; 5472 5473 return delegate.createFunctionExpression(id, tmp.params, tmp.defaults, body, tmp.rest, generator, expression, 5474 tmp.returnTypeAnnotation); 5475 } 5476 5477 function parseYieldExpression() { 5478 var delegateFlag, expr, previousYieldAllowed; 5479 5480 expectKeyword('yield'); 5481 5482 if (!state.yieldAllowed) { 5483 throwErrorTolerant({}, Messages.IllegalYield); 5484 } 5485 5486 delegateFlag = false; 5487 if (match('*')) { 5488 lex(); 5489 delegateFlag = true; 5490 } 5491 5492 // It is a Syntax Error if any AssignmentExpression Contains YieldExpression. 5493 previousYieldAllowed = state.yieldAllowed; 5494 state.yieldAllowed = false; 5495 expr = parseAssignmentExpression(); 5496 state.yieldAllowed = previousYieldAllowed; 5497 state.yieldFound = true; 5498 5499 return delegate.createYieldExpression(expr, delegateFlag); 5500 } 5501 5502 // 14 Classes 5503 5504 function parseMethodDefinition(existingPropNames) { 5505 var token, key, param, propType, isValidDuplicateProp = false; 5506 5507 if (lookahead.value === 'static') { 5508 propType = ClassPropertyType.static; 5509 lex(); 5510 } else { 5511 propType = ClassPropertyType.prototype; 5512 } 5513 5514 if (match('*')) { 5515 lex(); 5516 return delegate.createMethodDefinition( 5517 propType, 5518 '', 5519 parseObjectPropertyKey(), 5520 parsePropertyMethodFunction({ generator: true }) 5521 ); 5522 } 5523 5524 token = lookahead; 5525 key = parseObjectPropertyKey(); 5526 5527 if (token.value === 'get' && !match('(')) { 5528 key = parseObjectPropertyKey(); 5529 5530 // It is a syntax error if any other properties have a name 5531 // duplicating this one unless they are a setter 5532 if (existingPropNames[propType].hasOwnProperty(key.name)) { 5533 isValidDuplicateProp = 5534 // There isn't already a getter for this prop 5535 existingPropNames[propType][key.name].get === undefined 5536 // There isn't already a data prop by this name 5537 && existingPropNames[propType][key.name].data === undefined 5538 // The only existing prop by this name is a setter 5539 && existingPropNames[propType][key.name].set !== undefined; 5540 if (!isValidDuplicateProp) { 5541 throwError(key, Messages.IllegalDuplicateClassProperty); 5542 } 5543 } else { 5544 existingPropNames[propType][key.name] = {}; 5545 } 5546 existingPropNames[propType][key.name].get = true; 5547 5548 expect('('); 5549 expect(')'); 5550 return delegate.createMethodDefinition( 5551 propType, 5552 'get', 5553 key, 5554 parsePropertyFunction({ generator: false }) 5555 ); 5556 } 5557 if (token.value === 'set' && !match('(')) { 5558 key = parseObjectPropertyKey(); 5559 5560 // It is a syntax error if any other properties have a name 5561 // duplicating this one unless they are a getter 5562 if (existingPropNames[propType].hasOwnProperty(key.name)) { 5563 isValidDuplicateProp = 5564 // There isn't already a setter for this prop 5565 existingPropNames[propType][key.name].set === undefined 5566 // There isn't already a data prop by this name 5567 && existingPropNames[propType][key.name].data === undefined 5568 // The only existing prop by this name is a getter 5569 && existingPropNames[propType][key.name].get !== undefined; 5570 if (!isValidDuplicateProp) { 5571 throwError(key, Messages.IllegalDuplicateClassProperty); 5572 } 5573 } else { 5574 existingPropNames[propType][key.name] = {}; 5575 } 5576 existingPropNames[propType][key.name].set = true; 5577 5578 expect('('); 5579 token = lookahead; 5580 param = [ parseTypeAnnotatableIdentifier() ]; 5581 expect(')'); 5582 return delegate.createMethodDefinition( 5583 propType, 5584 'set', 5585 key, 5586 parsePropertyFunction({ params: param, generator: false, name: token }) 5587 ); 5588 } 5589 5590 // It is a syntax error if any other properties have the same name as a 5591 // non-getter, non-setter method 5592 if (existingPropNames[propType].hasOwnProperty(key.name)) { 5593 throwError(key, Messages.IllegalDuplicateClassProperty); 5594 } else { 5595 existingPropNames[propType][key.name] = {}; 5596 } 5597 existingPropNames[propType][key.name].data = true; 5598 5599 return delegate.createMethodDefinition( 5600 propType, 5601 '', 5602 key, 5603 parsePropertyMethodFunction({ generator: false }) 5604 ); 5605 } 5606 5607 function parseClassElement(existingProps) { 5608 if (match(';')) { 5609 lex(); 5610 return; 5611 } 5612 return parseMethodDefinition(existingProps); 5613 } 5614 5615 function parseClassBody() { 5616 var classElement, classElements = [], existingProps = {}; 5617 5618 existingProps[ClassPropertyType.static] = {}; 5619 existingProps[ClassPropertyType.prototype] = {}; 5620 5621 expect('{'); 5622 5623 while (index < length) { 5624 if (match('}')) { 5625 break; 5626 } 5627 classElement = parseClassElement(existingProps); 5628 5629 if (typeof classElement !== 'undefined') { 5630 classElements.push(classElement); 5631 } 5632 } 5633 5634 expect('}'); 5635 5636 return delegate.createClassBody(classElements); 5637 } 5638 5639 function parseClassExpression() { 5640 var id, previousYieldAllowed, superClass = null; 5641 5642 expectKeyword('class'); 5643 5644 if (!matchKeyword('extends') && !match('{')) { 5645 id = parseVariableIdentifier(); 5646 } 5647 5648 if (matchKeyword('extends')) { 5649 expectKeyword('extends'); 5650 previousYieldAllowed = state.yieldAllowed; 5651 state.yieldAllowed = false; 5652 superClass = parseAssignmentExpression(); 5653 state.yieldAllowed = previousYieldAllowed; 5654 } 5655 5656 return delegate.createClassExpression(id, superClass, parseClassBody()); 5657 } 5658 5659 function parseClassDeclaration() { 5660 var id, previousYieldAllowed, superClass = null; 5661 5662 expectKeyword('class'); 5663 5664 id = parseVariableIdentifier(); 5665 5666 if (matchKeyword('extends')) { 5667 expectKeyword('extends'); 5668 previousYieldAllowed = state.yieldAllowed; 5669 state.yieldAllowed = false; 5670 superClass = parseAssignmentExpression(); 5671 state.yieldAllowed = previousYieldAllowed; 5672 } 5673 5674 return delegate.createClassDeclaration(id, superClass, parseClassBody()); 5675 } 5676 5677 // 15 Program 5678 5679 function matchModuleDeclaration() { 5680 var id; 5681 if (matchContextualKeyword('module')) { 5682 id = lookahead2(); 5683 return id.type === Token.StringLiteral || id.type === Token.Identifier; 5684 } 5685 return false; 5686 } 5687 5688 function parseSourceElement() { 5689 if (lookahead.type === Token.Keyword) { 5690 switch (lookahead.value) { 5691 case 'const': 5692 case 'let': 5693 return parseConstLetDeclaration(lookahead.value); 5694 case 'function': 5695 return parseFunctionDeclaration(); 5696 case 'export': 5697 return parseExportDeclaration(); 5698 case 'import': 5699 return parseImportDeclaration(); 5700 default: 5701 return parseStatement(); 5702 } 5703 } 5704 5705 if (matchModuleDeclaration()) { 5706 throwError({}, Messages.NestedModule); 5707 } 5708 5709 if (lookahead.type !== Token.EOF) { 5710 return parseStatement(); 5711 } 5712 } 5713 5714 function parseProgramElement() { 5715 if (lookahead.type === Token.Keyword) { 5716 switch (lookahead.value) { 5717 case 'export': 5718 return parseExportDeclaration(); 5719 case 'import': 5720 return parseImportDeclaration(); 5721 } 5722 } 5723 5724 if (matchModuleDeclaration()) { 5725 return parseModuleDeclaration(); 5726 } 5727 5728 return parseSourceElement(); 5729 } 5730 5731 function parseProgramElements() { 5732 var sourceElement, sourceElements = [], token, directive, firstRestricted; 5733 5734 while (index < length) { 5735 token = lookahead; 5736 if (token.type !== Token.StringLiteral) { 5737 break; 5738 } 5739 5740 sourceElement = parseProgramElement(); 5741 sourceElements.push(sourceElement); 5742 if (sourceElement.expression.type !== Syntax.Literal) { 5743 // this is not directive 5744 break; 5745 } 5746 directive = source.slice(token.range[0] + 1, token.range[1] - 1); 5747 if (directive === 'use strict') { 5748 strict = true; 5749 if (firstRestricted) { 5750 throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); 5751 } 5752 } else { 5753 if (!firstRestricted && token.octal) { 5754 firstRestricted = token; 5755 } 5756 } 5757 } 5758 5759 while (index < length) { 5760 sourceElement = parseProgramElement(); 5761 if (typeof sourceElement === 'undefined') { 5762 break; 5763 } 5764 sourceElements.push(sourceElement); 5765 } 5766 return sourceElements; 5767 } 5768 5769 function parseModuleElement() { 5770 return parseSourceElement(); 5771 } 5772 5773 function parseModuleElements() { 5774 var list = [], 5775 statement; 5776 5777 while (index < length) { 5778 if (match('}')) { 5779 break; 5780 } 5781 statement = parseModuleElement(); 5782 if (typeof statement === 'undefined') { 5783 break; 5784 } 5785 list.push(statement); 5786 } 5787 5788 return list; 5789 } 5790 5791 function parseModuleBlock() { 5792 var block; 5793 5794 expect('{'); 5795 5796 block = parseModuleElements(); 5797 5798 expect('}'); 5799 5800 return delegate.createBlockStatement(block); 5801 } 5802 5803 function parseProgram() { 5804 var body; 5805 strict = false; 5806 peek(); 5807 body = parseProgramElements(); 5808 return delegate.createProgram(body); 5809 } 5810 5811 // The following functions are needed only when the option to preserve 5812 // the comments is active. 5813 5814 function addComment(type, value, start, end, loc) { 5815 assert(typeof start === 'number', 'Comment must have valid position'); 5816 5817 // Because the way the actual token is scanned, often the comments 5818 // (if any) are skipped twice during the lexical analysis. 5819 // Thus, we need to skip adding a comment if the comment array already 5820 // handled it. 5821 if (extra.comments.length > 0) { 5822 if (extra.comments[extra.comments.length - 1].range[1] > start) { 5823 return; 5824 } 5825 } 5826 5827 extra.comments.push({ 5828 type: type, 5829 value: value, 5830 range: [start, end], 5831 loc: loc 5832 }); 5833 } 5834 5835 function scanComment() { 5836 var comment, ch, loc, start, blockComment, lineComment; 5837 5838 comment = ''; 5839 blockComment = false; 5840 lineComment = false; 5841 5842 while (index < length) { 5843 ch = source[index]; 5844 5845 if (lineComment) { 5846 ch = source[index++]; 5847 if (isLineTerminator(ch.charCodeAt(0))) { 5848 loc.end = { 5849 line: lineNumber, 5850 column: index - lineStart - 1 5851 }; 5852 lineComment = false; 5853 addComment('Line', comment, start, index - 1, loc); 5854 if (ch === '\r' && source[index] === '\n') { 5855 ++index; 5856 } 5857 ++lineNumber; 5858 lineStart = index; 5859 comment = ''; 5860 } else if (index >= length) { 5861 lineComment = false; 5862 comment += ch; 5863 loc.end = { 5864 line: lineNumber, 5865 column: length - lineStart 5866 }; 5867 addComment('Line', comment, start, length, loc); 5868 } else { 5869 comment += ch; 5870 } 5871 } else if (blockComment) { 5872 if (isLineTerminator(ch.charCodeAt(0))) { 5873 if (ch === '\r' && source[index + 1] === '\n') { 5874 ++index; 5875 comment += '\r\n'; 5876 } else { 5877 comment += ch; 5878 } 5879 ++lineNumber; 5880 ++index; 5881 lineStart = index; 5882 if (index >= length) { 5883 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 5884 } 5885 } else { 5886 ch = source[index++]; 5887 if (index >= length) { 5888 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 5889 } 5890 comment += ch; 5891 if (ch === '*') { 5892 ch = source[index]; 5893 if (ch === '/') { 5894 comment = comment.substr(0, comment.length - 1); 5895 blockComment = false; 5896 ++index; 5897 loc.end = { 5898 line: lineNumber, 5899 column: index - lineStart 5900 }; 5901 addComment('Block', comment, start, index, loc); 5902 comment = ''; 5903 } 5904 } 5905 } 5906 } else if (ch === '/') { 5907 ch = source[index + 1]; 5908 if (ch === '/') { 5909 loc = { 5910 start: { 5911 line: lineNumber, 5912 column: index - lineStart 5913 } 5914 }; 5915 start = index; 5916 index += 2; 5917 lineComment = true; 5918 if (index >= length) { 5919 loc.end = { 5920 line: lineNumber, 5921 column: index - lineStart 5922 }; 5923 lineComment = false; 5924 addComment('Line', comment, start, index, loc); 5925 } 5926 } else if (ch === '*') { 5927 start = index; 5928 index += 2; 5929 blockComment = true; 5930 loc = { 5931 start: { 5932 line: lineNumber, 5933 column: index - lineStart - 2 5934 } 5935 }; 5936 if (index >= length) { 5937 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 5938 } 5939 } else { 5940 break; 5941 } 5942 } else if (isWhiteSpace(ch.charCodeAt(0))) { 5943 ++index; 5944 } else if (isLineTerminator(ch.charCodeAt(0))) { 5945 ++index; 5946 if (ch === '\r' && source[index] === '\n') { 5947 ++index; 5948 } 5949 ++lineNumber; 5950 lineStart = index; 5951 } else { 5952 break; 5953 } 5954 } 5955 } 5956 5957 function filterCommentLocation() { 5958 var i, entry, comment, comments = []; 5959 5960 for (i = 0; i < extra.comments.length; ++i) { 5961 entry = extra.comments[i]; 5962 comment = { 5963 type: entry.type, 5964 value: entry.value 5965 }; 5966 if (extra.range) { 5967 comment.range = entry.range; 5968 } 5969 if (extra.loc) { 5970 comment.loc = entry.loc; 5971 } 5972 comments.push(comment); 5973 } 5974 5975 extra.comments = comments; 5976 } 5977 5978 // 16 XJS 5979 5980 XHTMLEntities = { 5981 quot: '\u0022', 5982 amp: '&', 5983 apos: "\u0027", 5984 lt: "<", 5985 gt: ">", 5986 nbsp: "\u00A0", 5987 iexcl: "\u00A1", 5988 cent: "\u00A2", 5989 pound: "\u00A3", 5990 curren: "\u00A4", 5991 yen: "\u00A5", 5992 brvbar: "\u00A6", 5993 sect: "\u00A7", 5994 uml: "\u00A8", 5995 copy: "\u00A9", 5996 ordf: "\u00AA", 5997 laquo: "\u00AB", 5998 not: "\u00AC", 5999 shy: "\u00AD", 6000 reg: "\u00AE", 6001 macr: "\u00AF", 6002 deg: "\u00B0", 6003 plusmn: "\u00B1", 6004 sup2: "\u00B2", 6005 sup3: "\u00B3", 6006 acute: "\u00B4", 6007 micro: "\u00B5", 6008 para: "\u00B6", 6009 middot: "\u00B7", 6010 cedil: "\u00B8", 6011 sup1: "\u00B9", 6012 ordm: "\u00BA", 6013 raquo: "\u00BB", 6014 frac14: "\u00BC", 6015 frac12: "\u00BD", 6016 frac34: "\u00BE", 6017 iquest: "\u00BF", 6018 Agrave: "\u00C0", 6019 Aacute: "\u00C1", 6020 Acirc: "\u00C2", 6021 Atilde: "\u00C3", 6022 Auml: "\u00C4", 6023 Aring: "\u00C5", 6024 AElig: "\u00C6", 6025 Ccedil: "\u00C7", 6026 Egrave: "\u00C8", 6027 Eacute: "\u00C9", 6028 Ecirc: "\u00CA", 6029 Euml: "\u00CB", 6030 Igrave: "\u00CC", 6031 Iacute: "\u00CD", 6032 Icirc: "\u00CE", 6033 Iuml: "\u00CF", 6034 ETH: "\u00D0", 6035 Ntilde: "\u00D1", 6036 Ograve: "\u00D2", 6037 Oacute: "\u00D3", 6038 Ocirc: "\u00D4", 6039 Otilde: "\u00D5", 6040 Ouml: "\u00D6", 6041 times: "\u00D7", 6042 Oslash: "\u00D8", 6043 Ugrave: "\u00D9", 6044 Uacute: "\u00DA", 6045 Ucirc: "\u00DB", 6046 Uuml: "\u00DC", 6047 Yacute: "\u00DD", 6048 THORN: "\u00DE", 6049 szlig: "\u00DF", 6050 agrave: "\u00E0", 6051 aacute: "\u00E1", 6052 acirc: "\u00E2", 6053 atilde: "\u00E3", 6054 auml: "\u00E4", 6055 aring: "\u00E5", 6056 aelig: "\u00E6", 6057 ccedil: "\u00E7", 6058 egrave: "\u00E8", 6059 eacute: "\u00E9", 6060 ecirc: "\u00EA", 6061 euml: "\u00EB", 6062 igrave: "\u00EC", 6063 iacute: "\u00ED", 6064 icirc: "\u00EE", 6065 iuml: "\u00EF", 6066 eth: "\u00F0", 6067 ntilde: "\u00F1", 6068 ograve: "\u00F2", 6069 oacute: "\u00F3", 6070 ocirc: "\u00F4", 6071 otilde: "\u00F5", 6072 ouml: "\u00F6", 6073 divide: "\u00F7", 6074 oslash: "\u00F8", 6075 ugrave: "\u00F9", 6076 uacute: "\u00FA", 6077 ucirc: "\u00FB", 6078 uuml: "\u00FC", 6079 yacute: "\u00FD", 6080 thorn: "\u00FE", 6081 yuml: "\u00FF", 6082 OElig: "\u0152", 6083 oelig: "\u0153", 6084 Scaron: "\u0160", 6085 scaron: "\u0161", 6086 Yuml: "\u0178", 6087 fnof: "\u0192", 6088 circ: "\u02C6", 6089 tilde: "\u02DC", 6090 Alpha: "\u0391", 6091 Beta: "\u0392", 6092 Gamma: "\u0393", 6093 Delta: "\u0394", 6094 Epsilon: "\u0395", 6095 Zeta: "\u0396", 6096 Eta: "\u0397", 6097 Theta: "\u0398", 6098 Iota: "\u0399", 6099 Kappa: "\u039A", 6100 Lambda: "\u039B", 6101 Mu: "\u039C", 6102 Nu: "\u039D", 6103 Xi: "\u039E", 6104 Omicron: "\u039F", 6105 Pi: "\u03A0", 6106 Rho: "\u03A1", 6107 Sigma: "\u03A3", 6108 Tau: "\u03A4", 6109 Upsilon: "\u03A5", 6110 Phi: "\u03A6", 6111 Chi: "\u03A7", 6112 Psi: "\u03A8", 6113 Omega: "\u03A9", 6114 alpha: "\u03B1", 6115 beta: "\u03B2", 6116 gamma: "\u03B3", 6117 delta: "\u03B4", 6118 epsilon: "\u03B5", 6119 zeta: "\u03B6", 6120 eta: "\u03B7", 6121 theta: "\u03B8", 6122 iota: "\u03B9", 6123 kappa: "\u03BA", 6124 lambda: "\u03BB", 6125 mu: "\u03BC", 6126 nu: "\u03BD", 6127 xi: "\u03BE", 6128 omicron: "\u03BF", 6129 pi: "\u03C0", 6130 rho: "\u03C1", 6131 sigmaf: "\u03C2", 6132 sigma: "\u03C3", 6133 tau: "\u03C4", 6134 upsilon: "\u03C5", 6135 phi: "\u03C6", 6136 chi: "\u03C7", 6137 psi: "\u03C8", 6138 omega: "\u03C9", 6139 thetasym: "\u03D1", 6140 upsih: "\u03D2", 6141 piv: "\u03D6", 6142 ensp: "\u2002", 6143 emsp: "\u2003", 6144 thinsp: "\u2009", 6145 zwnj: "\u200C", 6146 zwj: "\u200D", 6147 lrm: "\u200E", 6148 rlm: "\u200F", 6149 ndash: "\u2013", 6150 mdash: "\u2014", 6151 lsquo: "\u2018", 6152 rsquo: "\u2019", 6153 sbquo: "\u201A", 6154 ldquo: "\u201C", 6155 rdquo: "\u201D", 6156 bdquo: "\u201E", 6157 dagger: "\u2020", 6158 Dagger: "\u2021", 6159 bull: "\u2022", 6160 hellip: "\u2026", 6161 permil: "\u2030", 6162 prime: "\u2032", 6163 Prime: "\u2033", 6164 lsaquo: "\u2039", 6165 rsaquo: "\u203A", 6166 oline: "\u203E", 6167 frasl: "\u2044", 6168 euro: "\u20AC", 6169 image: "\u2111", 6170 weierp: "\u2118", 6171 real: "\u211C", 6172 trade: "\u2122", 6173 alefsym: "\u2135", 6174 larr: "\u2190", 6175 uarr: "\u2191", 6176 rarr: "\u2192", 6177 darr: "\u2193", 6178 harr: "\u2194", 6179 crarr: "\u21B5", 6180 lArr: "\u21D0", 6181 uArr: "\u21D1", 6182 rArr: "\u21D2", 6183 dArr: "\u21D3", 6184 hArr: "\u21D4", 6185 forall: "\u2200", 6186 part: "\u2202", 6187 exist: "\u2203", 6188 empty: "\u2205", 6189 nabla: "\u2207", 6190 isin: "\u2208", 6191 notin: "\u2209", 6192 ni: "\u220B", 6193 prod: "\u220F", 6194 sum: "\u2211", 6195 minus: "\u2212", 6196 lowast: "\u2217", 6197 radic: "\u221A", 6198 prop: "\u221D", 6199 infin: "\u221E", 6200 ang: "\u2220", 6201 and: "\u2227", 6202 or: "\u2228", 6203 cap: "\u2229", 6204 cup: "\u222A", 6205 "int": "\u222B", 6206 there4: "\u2234", 6207 sim: "\u223C", 6208 cong: "\u2245", 6209 asymp: "\u2248", 6210 ne: "\u2260", 6211 equiv: "\u2261", 6212 le: "\u2264", 6213 ge: "\u2265", 6214 sub: "\u2282", 6215 sup: "\u2283", 6216 nsub: "\u2284", 6217 sube: "\u2286", 6218 supe: "\u2287", 6219 oplus: "\u2295", 6220 otimes: "\u2297", 6221 perp: "\u22A5", 6222 sdot: "\u22C5", 6223 lceil: "\u2308", 6224 rceil: "\u2309", 6225 lfloor: "\u230A", 6226 rfloor: "\u230B", 6227 lang: "\u2329", 6228 rang: "\u232A", 6229 loz: "\u25CA", 6230 spades: "\u2660", 6231 clubs: "\u2663", 6232 hearts: "\u2665", 6233 diams: "\u2666" 6234 }; 6235 6236 function isXJSIdentifierStart(ch) { 6237 // exclude backslash (\) 6238 return (ch !== 92) && isIdentifierStart(ch); 6239 } 6240 6241 function isXJSIdentifierPart(ch) { 6242 // exclude backslash (\) and add hyphen (-) 6243 return (ch !== 92) && (ch === 45 || isIdentifierPart(ch)); 6244 } 6245 6246 function scanXJSIdentifier() { 6247 var ch, start, id = '', namespace; 6248 6249 start = index; 6250 while (index < length) { 6251 ch = source.charCodeAt(index); 6252 if (!isXJSIdentifierPart(ch)) { 6253 break; 6254 } 6255 id += source[index++]; 6256 } 6257 6258 if (ch === 58) { // : 6259 ++index; 6260 namespace = id; 6261 id = ''; 6262 6263 while (index < length) { 6264 ch = source.charCodeAt(index); 6265 if (!isXJSIdentifierPart(ch)) { 6266 break; 6267 } 6268 id += source[index++]; 6269 } 6270 } 6271 6272 if (!id) { 6273 throwError({}, Messages.InvalidXJSTagName); 6274 } 6275 6276 return { 6277 type: Token.XJSIdentifier, 6278 value: id, 6279 namespace: namespace, 6280 lineNumber: lineNumber, 6281 lineStart: lineStart, 6282 range: [start, index] 6283 }; 6284 } 6285 6286 function scanXJSEntity() { 6287 var ch, str = '', count = 0, entity; 6288 ch = source[index]; 6289 assert(ch === '&', 'Entity must start with an ampersand'); 6290 index++; 6291 while (index < length && count++ < 10) { 6292 ch = source[index++]; 6293 if (ch === ';') { 6294 break; 6295 } 6296 str += ch; 6297 } 6298 6299 if (str[0] === '#' && str[1] === 'x') { 6300 entity = String.fromCharCode(parseInt(str.substr(2), 16)); 6301 } else if (str[0] === '#') { 6302 entity = String.fromCharCode(parseInt(str.substr(1), 10)); 6303 } else { 6304 entity = XHTMLEntities[str]; 6305 } 6306 return entity; 6307 } 6308 6309 function scanXJSText(stopChars) { 6310 var ch, str = '', start; 6311 start = index; 6312 while (index < length) { 6313 ch = source[index]; 6314 if (stopChars.indexOf(ch) !== -1) { 6315 break; 6316 } 6317 if (ch === '&') { 6318 str += scanXJSEntity(); 6319 } else { 6320 ch = source[index++]; 6321 if (isLineTerminator(ch.charCodeAt(0))) { 6322 ++lineNumber; 6323 lineStart = index; 6324 } 6325 str += ch; 6326 } 6327 } 6328 return { 6329 type: Token.XJSText, 6330 value: str, 6331 lineNumber: lineNumber, 6332 lineStart: lineStart, 6333 range: [start, index] 6334 }; 6335 } 6336 6337 function scanXJSStringLiteral() { 6338 var innerToken, quote, start; 6339 6340 quote = source[index]; 6341 assert((quote === '\'' || quote === '"'), 6342 'String literal must starts with a quote'); 6343 6344 start = index; 6345 ++index; 6346 6347 innerToken = scanXJSText([quote]); 6348 6349 if (quote !== source[index]) { 6350 throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); 6351 } 6352 6353 ++index; 6354 6355 innerToken.range = [start, index]; 6356 6357 return innerToken; 6358 } 6359 6360 /** 6361 * Between XJS opening and closing tags (e.g. <foo>HERE</foo>), anything that 6362 * is not another XJS tag and is not an expression wrapped by {} is text. 6363 */ 6364 function advanceXJSChild() { 6365 var ch = source.charCodeAt(index); 6366 6367 // { (123) and < (60) 6368 if (ch !== 123 && ch !== 60) { 6369 return scanXJSText(['<', '{']); 6370 } 6371 6372 return scanPunctuator(); 6373 } 6374 6375 function parseXJSIdentifier() { 6376 var token; 6377 6378 if (lookahead.type !== Token.XJSIdentifier) { 6379 throwUnexpected(lookahead); 6380 } 6381 6382 token = lex(); 6383 return delegate.createXJSIdentifier(token.value, token.namespace); 6384 } 6385 6386 function parseXJSAttributeValue() { 6387 var value; 6388 if (match('{')) { 6389 value = parseXJSExpressionContainer(); 6390 if (value.expression.type === Syntax.XJSEmptyExpression) { 6391 throwError( 6392 value, 6393 'XJS attributes must only be assigned a non-empty ' + 6394 'expression' 6395 ); 6396 } 6397 } else if (lookahead.type === Token.XJSText) { 6398 value = delegate.createLiteral(lex()); 6399 } else { 6400 throwError({}, Messages.InvalidXJSAttributeValue); 6401 } 6402 return value; 6403 } 6404 6405 function parseXJSEmptyExpression() { 6406 while (source.charAt(index) !== '}') { 6407 index++; 6408 } 6409 return delegate.createXJSEmptyExpression(); 6410 } 6411 6412 function parseXJSExpressionContainer() { 6413 var expression, origInXJSChild, origInXJSTag; 6414 6415 origInXJSChild = state.inXJSChild; 6416 origInXJSTag = state.inXJSTag; 6417 state.inXJSChild = false; 6418 state.inXJSTag = false; 6419 6420 expect('{'); 6421 6422 if (match('}')) { 6423 expression = parseXJSEmptyExpression(); 6424 } else { 6425 expression = parseExpression(); 6426 } 6427 6428 state.inXJSChild = origInXJSChild; 6429 state.inXJSTag = origInXJSTag; 6430 6431 expect('}'); 6432 6433 return delegate.createXJSExpressionContainer(expression); 6434 } 6435 6436 function parseXJSAttribute() { 6437 var token, name, value; 6438 6439 name = parseXJSIdentifier(); 6440 6441 // HTML empty attribute 6442 if (match('=')) { 6443 lex(); 6444 return delegate.createXJSAttribute(name, parseXJSAttributeValue()); 6445 } 6446 6447 return delegate.createXJSAttribute(name); 6448 } 6449 6450 function parseXJSChild() { 6451 var token; 6452 if (match('{')) { 6453 token = parseXJSExpressionContainer(); 6454 } else if (lookahead.type === Token.XJSText) { 6455 token = delegate.createLiteral(lex()); 6456 } else { 6457 state.inXJSChild = false; 6458 token = parseXJSElement(); 6459 state.inXJSChild = true; 6460 } 6461 return token; 6462 } 6463 6464 function parseXJSClosingElement() { 6465 var name, origInXJSTag; 6466 origInXJSTag = state.inXJSTag; 6467 state.inXJSTag = true; 6468 state.inXJSChild = false; 6469 expect('<'); 6470 expect('/'); 6471 name = parseXJSIdentifier(); 6472 state.inXJSTag = origInXJSTag; 6473 expect('>'); 6474 return delegate.createXJSClosingElement(name); 6475 } 6476 6477 function parseXJSOpeningElement() { 6478 var name, attribute, attributes = [], selfClosing = false, origInXJSTag; 6479 6480 origInXJSTag = state.inXJSTag; 6481 state.inXJSTag = true; 6482 6483 expect('<'); 6484 6485 name = parseXJSIdentifier(); 6486 6487 while (index < length && 6488 lookahead.value !== '/' && 6489 lookahead.value !== '>') { 6490 attributes.push(parseXJSAttribute()); 6491 } 6492 6493 state.inXJSTag = origInXJSTag; 6494 6495 if (lookahead.value === '/') { 6496 expect('/'); 6497 expect('>'); 6498 selfClosing = true; 6499 } else { 6500 state.inXJSChild = true; 6501 expect('>'); 6502 } 6503 return delegate.createXJSOpeningElement(name, attributes, selfClosing); 6504 } 6505 6506 function parseXJSElement() { 6507 var openingElement, closingElement, children = [], origInXJSChild; 6508 6509 openingElement = parseXJSOpeningElement(); 6510 6511 if (!openingElement.selfClosing) { 6512 origInXJSChild = state.inXJSChild; 6513 while (index < length) { 6514 state.inXJSChild = false; // </ should not be considered in the child 6515 if (lookahead.value === '<' && lookahead2().value === '/') { 6516 break; 6517 } 6518 state.inXJSChild = true; 6519 peek(); // reset lookahead token 6520 children.push(parseXJSChild()); 6521 } 6522 state.inXJSChild = origInXJSChild; 6523 closingElement = parseXJSClosingElement(); 6524 if (closingElement.name.namespace !== openingElement.name.namespace || closingElement.name.name !== openingElement.name.name) { 6525 throwError({}, Messages.ExpectedXJSClosingTag, openingElement.name.namespace ? openingElement.name.namespace + ':' + openingElement.name.name : openingElement.name.name); 6526 } 6527 } 6528 6529 return delegate.createXJSElement(openingElement, closingElement, children); 6530 } 6531 6532 function collectToken() { 6533 var start, loc, token, range, value; 6534 6535 skipComment(); 6536 start = index; 6537 loc = { 6538 start: { 6539 line: lineNumber, 6540 column: index - lineStart 6541 } 6542 }; 6543 6544 token = extra.advance(); 6545 loc.end = { 6546 line: lineNumber, 6547 column: index - lineStart 6548 }; 6549 6550 if (token.type !== Token.EOF) { 6551 range = [token.range[0], token.range[1]]; 6552 value = source.slice(token.range[0], token.range[1]); 6553 extra.tokens.push({ 6554 type: TokenName[token.type], 6555 value: value, 6556 range: range, 6557 loc: loc 6558 }); 6559 } 6560 6561 return token; 6562 } 6563 6564 function collectRegex() { 6565 var pos, loc, regex, token; 6566 6567 skipComment(); 6568 6569 pos = index; 6570 loc = { 6571 start: { 6572 line: lineNumber, 6573 column: index - lineStart 6574 } 6575 }; 6576 6577 regex = extra.scanRegExp(); 6578 loc.end = { 6579 line: lineNumber, 6580 column: index - lineStart 6581 }; 6582 6583 if (!extra.tokenize) { 6584 // Pop the previous token, which is likely '/' or '/=' 6585 if (extra.tokens.length > 0) { 6586 token = extra.tokens[extra.tokens.length - 1]; 6587 if (token.range[0] === pos && token.type === 'Punctuator') { 6588 if (token.value === '/' || token.value === '/=') { 6589 extra.tokens.pop(); 6590 } 6591 } 6592 } 6593 6594 extra.tokens.push({ 6595 type: 'RegularExpression', 6596 value: regex.literal, 6597 range: [pos, index], 6598 loc: loc 6599 }); 6600 } 6601 6602 return regex; 6603 } 6604 6605 function filterTokenLocation() { 6606 var i, entry, token, tokens = []; 6607 6608 for (i = 0; i < extra.tokens.length; ++i) { 6609 entry = extra.tokens[i]; 6610 token = { 6611 type: entry.type, 6612 value: entry.value 6613 }; 6614 if (extra.range) { 6615 token.range = entry.range; 6616 } 6617 if (extra.loc) { 6618 token.loc = entry.loc; 6619 } 6620 tokens.push(token); 6621 } 6622 6623 extra.tokens = tokens; 6624 } 6625 6626 function LocationMarker() { 6627 this.range = [index, index]; 6628 this.loc = { 6629 start: { 6630 line: lineNumber, 6631 column: index - lineStart 6632 }, 6633 end: { 6634 line: lineNumber, 6635 column: index - lineStart 6636 } 6637 }; 6638 } 6639 6640 LocationMarker.prototype = { 6641 constructor: LocationMarker, 6642 6643 end: function () { 6644 this.range[1] = index; 6645 this.loc.end.line = lineNumber; 6646 this.loc.end.column = index - lineStart; 6647 }, 6648 6649 applyGroup: function (node) { 6650 if (extra.range) { 6651 node.groupRange = [this.range[0], this.range[1]]; 6652 } 6653 if (extra.loc) { 6654 node.groupLoc = { 6655 start: { 6656 line: this.loc.start.line, 6657 column: this.loc.start.column 6658 }, 6659 end: { 6660 line: this.loc.end.line, 6661 column: this.loc.end.column 6662 } 6663 }; 6664 node = delegate.postProcess(node); 6665 } 6666 }, 6667 6668 apply: function (node) { 6669 var nodeType = typeof node; 6670 assert(nodeType === "object", 6671 "Applying location marker to an unexpected node type: " + 6672 nodeType); 6673 6674 if (extra.range) { 6675 node.range = [this.range[0], this.range[1]]; 6676 } 6677 if (extra.loc) { 6678 node.loc = { 6679 start: { 6680 line: this.loc.start.line, 6681 column: this.loc.start.column 6682 }, 6683 end: { 6684 line: this.loc.end.line, 6685 column: this.loc.end.column 6686 } 6687 }; 6688 node = delegate.postProcess(node); 6689 } 6690 } 6691 }; 6692 6693 function createLocationMarker() { 6694 return new LocationMarker(); 6695 } 6696 6697 function trackGroupExpression() { 6698 var marker, expr; 6699 6700 skipComment(); 6701 marker = createLocationMarker(); 6702 expect('('); 6703 6704 ++state.parenthesizedCount; 6705 6706 state.allowArrowFunction = !state.allowArrowFunction; 6707 expr = parseExpression(); 6708 state.allowArrowFunction = false; 6709 6710 if (expr.type === 'ArrowFunctionExpression') { 6711 marker.end(); 6712 marker.apply(expr); 6713 } else { 6714 expect(')'); 6715 marker.end(); 6716 marker.applyGroup(expr); 6717 } 6718 6719 return expr; 6720 } 6721 6722 function trackLeftHandSideExpression() { 6723 var marker, expr; 6724 6725 skipComment(); 6726 marker = createLocationMarker(); 6727 6728 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); 6729 6730 while (match('.') || match('[') || lookahead.type === Token.Template) { 6731 if (match('[')) { 6732 expr = delegate.createMemberExpression('[', expr, parseComputedMember()); 6733 marker.end(); 6734 marker.apply(expr); 6735 } else if (match('.')) { 6736 expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); 6737 marker.end(); 6738 marker.apply(expr); 6739 } else { 6740 expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); 6741 marker.end(); 6742 marker.apply(expr); 6743 } 6744 } 6745 6746 return expr; 6747 } 6748 6749 function trackLeftHandSideExpressionAllowCall() { 6750 var marker, expr, args; 6751 6752 skipComment(); 6753 marker = createLocationMarker(); 6754 6755 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); 6756 6757 while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) { 6758 if (match('(')) { 6759 args = parseArguments(); 6760 expr = delegate.createCallExpression(expr, args); 6761 marker.end(); 6762 marker.apply(expr); 6763 } else if (match('[')) { 6764 expr = delegate.createMemberExpression('[', expr, parseComputedMember()); 6765 marker.end(); 6766 marker.apply(expr); 6767 } else if (match('.')) { 6768 expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); 6769 marker.end(); 6770 marker.apply(expr); 6771 } else { 6772 expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); 6773 marker.end(); 6774 marker.apply(expr); 6775 } 6776 } 6777 6778 return expr; 6779 } 6780 6781 function filterGroup(node) { 6782 var n, i, entry; 6783 6784 n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {}; 6785 for (i in node) { 6786 if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') { 6787 entry = node[i]; 6788 if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) { 6789 n[i] = entry; 6790 } else { 6791 n[i] = filterGroup(entry); 6792 } 6793 } 6794 } 6795 return n; 6796 } 6797 6798 function wrapTrackingFunction(range, loc, preserveWhitespace) { 6799 6800 return function (parseFunction) { 6801 6802 function isBinary(node) { 6803 return node.type === Syntax.LogicalExpression || 6804 node.type === Syntax.BinaryExpression; 6805 } 6806 6807 function visit(node) { 6808 var start, end; 6809 6810 if (isBinary(node.left)) { 6811 visit(node.left); 6812 } 6813 if (isBinary(node.right)) { 6814 visit(node.right); 6815 } 6816 6817 if (range) { 6818 if (node.left.groupRange || node.right.groupRange) { 6819 start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0]; 6820 end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1]; 6821 node.range = [start, end]; 6822 } else if (typeof node.range === 'undefined') { 6823 start = node.left.range[0]; 6824 end = node.right.range[1]; 6825 node.range = [start, end]; 6826 } 6827 } 6828 if (loc) { 6829 if (node.left.groupLoc || node.right.groupLoc) { 6830 start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start; 6831 end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end; 6832 node.loc = { 6833 start: start, 6834 end: end 6835 }; 6836 node = delegate.postProcess(node); 6837 } else if (typeof node.loc === 'undefined') { 6838 node.loc = { 6839 start: node.left.loc.start, 6840 end: node.right.loc.end 6841 }; 6842 node = delegate.postProcess(node); 6843 } 6844 } 6845 } 6846 6847 return function () { 6848 var marker, node; 6849 6850 if (!preserveWhitespace) { 6851 skipComment(); 6852 } 6853 6854 marker = createLocationMarker(); 6855 node = parseFunction.apply(null, arguments); 6856 marker.end(); 6857 6858 if (range && typeof node.range === 'undefined') { 6859 marker.apply(node); 6860 } 6861 6862 if (loc && typeof node.loc === 'undefined') { 6863 marker.apply(node); 6864 } 6865 6866 if (isBinary(node)) { 6867 visit(node); 6868 } 6869 6870 return node; 6871 }; 6872 }; 6873 } 6874 6875 function patch() { 6876 6877 var wrapTracking, wrapTrackingPreserveWhitespace; 6878 6879 if (extra.comments) { 6880 extra.skipComment = skipComment; 6881 skipComment = scanComment; 6882 } 6883 6884 if (extra.range || extra.loc) { 6885 6886 extra.parseGroupExpression = parseGroupExpression; 6887 extra.parseLeftHandSideExpression = parseLeftHandSideExpression; 6888 extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall; 6889 parseGroupExpression = trackGroupExpression; 6890 parseLeftHandSideExpression = trackLeftHandSideExpression; 6891 parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall; 6892 6893 wrapTracking = wrapTrackingFunction(extra.range, extra.loc); 6894 wrapTrackingPreserveWhitespace = 6895 wrapTrackingFunction(extra.range, extra.loc, true); 6896 6897 extra.parseAssignmentExpression = parseAssignmentExpression; 6898 extra.parseBinaryExpression = parseBinaryExpression; 6899 extra.parseBlock = parseBlock; 6900 extra.parseFunctionSourceElements = parseFunctionSourceElements; 6901 extra.parseCatchClause = parseCatchClause; 6902 extra.parseComputedMember = parseComputedMember; 6903 extra.parseConditionalExpression = parseConditionalExpression; 6904 extra.parseConstLetDeclaration = parseConstLetDeclaration; 6905 extra.parseExportBatchSpecifier = parseExportBatchSpecifier; 6906 extra.parseExportDeclaration = parseExportDeclaration; 6907 extra.parseExportSpecifier = parseExportSpecifier; 6908 extra.parseExpression = parseExpression; 6909 extra.parseForVariableDeclaration = parseForVariableDeclaration; 6910 extra.parseFunctionDeclaration = parseFunctionDeclaration; 6911 extra.parseFunctionExpression = parseFunctionExpression; 6912 extra.parseParams = parseParams; 6913 extra.parseImportDeclaration = parseImportDeclaration; 6914 extra.parseImportSpecifier = parseImportSpecifier; 6915 extra.parseModuleDeclaration = parseModuleDeclaration; 6916 extra.parseModuleBlock = parseModuleBlock; 6917 extra.parseNewExpression = parseNewExpression; 6918 extra.parseNonComputedProperty = parseNonComputedProperty; 6919 extra.parseObjectProperty = parseObjectProperty; 6920 extra.parseObjectPropertyKey = parseObjectPropertyKey; 6921 extra.parsePostfixExpression = parsePostfixExpression; 6922 extra.parsePrimaryExpression = parsePrimaryExpression; 6923 extra.parseProgram = parseProgram; 6924 extra.parsePropertyFunction = parsePropertyFunction; 6925 extra.parseSpreadOrAssignmentExpression = parseSpreadOrAssignmentExpression; 6926 extra.parseTemplateElement = parseTemplateElement; 6927 extra.parseTemplateLiteral = parseTemplateLiteral; 6928 extra.parseTypeAnnotatableIdentifier = parseTypeAnnotatableIdentifier; 6929 extra.parseTypeAnnotation = parseTypeAnnotation; 6930 extra.parseStatement = parseStatement; 6931 extra.parseSwitchCase = parseSwitchCase; 6932 extra.parseUnaryExpression = parseUnaryExpression; 6933 extra.parseVariableDeclaration = parseVariableDeclaration; 6934 extra.parseVariableIdentifier = parseVariableIdentifier; 6935 extra.parseMethodDefinition = parseMethodDefinition; 6936 extra.parseClassDeclaration = parseClassDeclaration; 6937 extra.parseClassExpression = parseClassExpression; 6938 extra.parseClassBody = parseClassBody; 6939 extra.parseXJSIdentifier = parseXJSIdentifier; 6940 extra.parseXJSChild = parseXJSChild; 6941 extra.parseXJSAttribute = parseXJSAttribute; 6942 extra.parseXJSAttributeValue = parseXJSAttributeValue; 6943 extra.parseXJSExpressionContainer = parseXJSExpressionContainer; 6944 extra.parseXJSEmptyExpression = parseXJSEmptyExpression; 6945 extra.parseXJSElement = parseXJSElement; 6946 extra.parseXJSClosingElement = parseXJSClosingElement; 6947 extra.parseXJSOpeningElement = parseXJSOpeningElement; 6948 6949 parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); 6950 parseBinaryExpression = wrapTracking(extra.parseBinaryExpression); 6951 parseBlock = wrapTracking(extra.parseBlock); 6952 parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements); 6953 parseCatchClause = wrapTracking(extra.parseCatchClause); 6954 parseComputedMember = wrapTracking(extra.parseComputedMember); 6955 parseConditionalExpression = wrapTracking(extra.parseConditionalExpression); 6956 parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration); 6957 parseExportBatchSpecifier = wrapTracking(parseExportBatchSpecifier); 6958 parseExportDeclaration = wrapTracking(parseExportDeclaration); 6959 parseExportSpecifier = wrapTracking(parseExportSpecifier); 6960 parseExpression = wrapTracking(extra.parseExpression); 6961 parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration); 6962 parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration); 6963 parseFunctionExpression = wrapTracking(extra.parseFunctionExpression); 6964 parseParams = wrapTracking(extra.parseParams); 6965 parseImportDeclaration = wrapTracking(extra.parseImportDeclaration); 6966 parseImportSpecifier = wrapTracking(extra.parseImportSpecifier); 6967 parseModuleDeclaration = wrapTracking(extra.parseModuleDeclaration); 6968 parseModuleBlock = wrapTracking(extra.parseModuleBlock); 6969 parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression); 6970 parseNewExpression = wrapTracking(extra.parseNewExpression); 6971 parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty); 6972 parseObjectProperty = wrapTracking(extra.parseObjectProperty); 6973 parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey); 6974 parsePostfixExpression = wrapTracking(extra.parsePostfixExpression); 6975 parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression); 6976 parseProgram = wrapTracking(extra.parseProgram); 6977 parsePropertyFunction = wrapTracking(extra.parsePropertyFunction); 6978 parseTemplateElement = wrapTracking(extra.parseTemplateElement); 6979 parseTemplateLiteral = wrapTracking(extra.parseTemplateLiteral); 6980 parseTypeAnnotatableIdentifier = wrapTracking(extra.parseTypeAnnotatableIdentifier); 6981 parseTypeAnnotation = wrapTracking(extra.parseTypeAnnotation); 6982 parseSpreadOrAssignmentExpression = wrapTracking(extra.parseSpreadOrAssignmentExpression); 6983 parseStatement = wrapTracking(extra.parseStatement); 6984 parseSwitchCase = wrapTracking(extra.parseSwitchCase); 6985 parseUnaryExpression = wrapTracking(extra.parseUnaryExpression); 6986 parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration); 6987 parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier); 6988 parseMethodDefinition = wrapTracking(extra.parseMethodDefinition); 6989 parseClassDeclaration = wrapTracking(extra.parseClassDeclaration); 6990 parseClassExpression = wrapTracking(extra.parseClassExpression); 6991 parseClassBody = wrapTracking(extra.parseClassBody); 6992 parseXJSIdentifier = wrapTracking(extra.parseXJSIdentifier); 6993 parseXJSChild = wrapTrackingPreserveWhitespace(extra.parseXJSChild); 6994 parseXJSAttribute = wrapTracking(extra.parseXJSAttribute); 6995 parseXJSAttributeValue = wrapTracking(extra.parseXJSAttributeValue); 6996 parseXJSExpressionContainer = wrapTracking(extra.parseXJSExpressionContainer); 6997 parseXJSEmptyExpression = wrapTrackingPreserveWhitespace(extra.parseXJSEmptyExpression); 6998 parseXJSElement = wrapTracking(extra.parseXJSElement); 6999 parseXJSClosingElement = wrapTracking(extra.parseXJSClosingElement); 7000 parseXJSOpeningElement = wrapTracking(extra.parseXJSOpeningElement); 7001 } 7002 7003 if (typeof extra.tokens !== 'undefined') { 7004 extra.advance = advance; 7005 extra.scanRegExp = scanRegExp; 7006 7007 advance = collectToken; 7008 scanRegExp = collectRegex; 7009 } 7010 } 7011 7012 function unpatch() { 7013 if (typeof extra.skipComment === 'function') { 7014 skipComment = extra.skipComment; 7015 } 7016 7017 if (extra.range || extra.loc) { 7018 parseAssignmentExpression = extra.parseAssignmentExpression; 7019 parseBinaryExpression = extra.parseBinaryExpression; 7020 parseBlock = extra.parseBlock; 7021 parseFunctionSourceElements = extra.parseFunctionSourceElements; 7022 parseCatchClause = extra.parseCatchClause; 7023 parseComputedMember = extra.parseComputedMember; 7024 parseConditionalExpression = extra.parseConditionalExpression; 7025 parseConstLetDeclaration = extra.parseConstLetDeclaration; 7026 parseExportBatchSpecifier = extra.parseExportBatchSpecifier; 7027 parseExportDeclaration = extra.parseExportDeclaration; 7028 parseExportSpecifier = extra.parseExportSpecifier; 7029 parseExpression = extra.parseExpression; 7030 parseForVariableDeclaration = extra.parseForVariableDeclaration; 7031 parseFunctionDeclaration = extra.parseFunctionDeclaration; 7032 parseFunctionExpression = extra.parseFunctionExpression; 7033 parseImportDeclaration = extra.parseImportDeclaration; 7034 parseImportSpecifier = extra.parseImportSpecifier; 7035 parseGroupExpression = extra.parseGroupExpression; 7036 parseLeftHandSideExpression = extra.parseLeftHandSideExpression; 7037 parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall; 7038 parseModuleDeclaration = extra.parseModuleDeclaration; 7039 parseModuleBlock = extra.parseModuleBlock; 7040 parseNewExpression = extra.parseNewExpression; 7041 parseNonComputedProperty = extra.parseNonComputedProperty; 7042 parseObjectProperty = extra.parseObjectProperty; 7043 parseObjectPropertyKey = extra.parseObjectPropertyKey; 7044 parsePostfixExpression = extra.parsePostfixExpression; 7045 parsePrimaryExpression = extra.parsePrimaryExpression; 7046 parseProgram = extra.parseProgram; 7047 parsePropertyFunction = extra.parsePropertyFunction; 7048 parseTemplateElement = extra.parseTemplateElement; 7049 parseTemplateLiteral = extra.parseTemplateLiteral; 7050 parseTypeAnnotatableIdentifier = extra.parseTypeAnnotatableIdentifier; 7051 parseTypeAnnotation = extra.parseTypeAnnotation; 7052 parseSpreadOrAssignmentExpression = extra.parseSpreadOrAssignmentExpression; 7053 parseStatement = extra.parseStatement; 7054 parseSwitchCase = extra.parseSwitchCase; 7055 parseUnaryExpression = extra.parseUnaryExpression; 7056 parseVariableDeclaration = extra.parseVariableDeclaration; 7057 parseVariableIdentifier = extra.parseVariableIdentifier; 7058 parseMethodDefinition = extra.parseMethodDefinition; 7059 parseClassDeclaration = extra.parseClassDeclaration; 7060 parseClassExpression = extra.parseClassExpression; 7061 parseClassBody = extra.parseClassBody; 7062 parseXJSIdentifier = extra.parseXJSIdentifier; 7063 parseXJSChild = extra.parseXJSChild; 7064 parseXJSAttribute = extra.parseXJSAttribute; 7065 parseXJSAttributeValue = extra.parseXJSAttributeValue; 7066 parseXJSExpressionContainer = extra.parseXJSExpressionContainer; 7067 parseXJSEmptyExpression = extra.parseXJSEmptyExpression; 7068 parseXJSElement = extra.parseXJSElement; 7069 parseXJSClosingElement = extra.parseXJSClosingElement; 7070 parseXJSOpeningElement = extra.parseXJSOpeningElement; 7071 } 7072 7073 if (typeof extra.scanRegExp === 'function') { 7074 advance = extra.advance; 7075 scanRegExp = extra.scanRegExp; 7076 } 7077 } 7078 7079 // This is used to modify the delegate. 7080 7081 function extend(object, properties) { 7082 var entry, result = {}; 7083 7084 for (entry in object) { 7085 if (object.hasOwnProperty(entry)) { 7086 result[entry] = object[entry]; 7087 } 7088 } 7089 7090 for (entry in properties) { 7091 if (properties.hasOwnProperty(entry)) { 7092 result[entry] = properties[entry]; 7093 } 7094 } 7095 7096 return result; 7097 } 7098 7099 function tokenize(code, options) { 7100 var toString, 7101 token, 7102 tokens; 7103 7104 toString = String; 7105 if (typeof code !== 'string' && !(code instanceof String)) { 7106 code = toString(code); 7107 } 7108 7109 delegate = SyntaxTreeDelegate; 7110 source = code; 7111 index = 0; 7112 lineNumber = (source.length > 0) ? 1 : 0; 7113 lineStart = 0; 7114 length = source.length; 7115 lookahead = null; 7116 state = { 7117 allowKeyword: true, 7118 allowIn: true, 7119 labelSet: {}, 7120 inFunctionBody: false, 7121 inIteration: false, 7122 inSwitch: false 7123 }; 7124 7125 extra = {}; 7126 7127 // Options matching. 7128 options = options || {}; 7129 7130 // Of course we collect tokens here. 7131 options.tokens = true; 7132 extra.tokens = []; 7133 extra.tokenize = true; 7134 // The following two fields are necessary to compute the Regex tokens. 7135 extra.openParenToken = -1; 7136 extra.openCurlyToken = -1; 7137 7138 extra.range = (typeof options.range === 'boolean') && options.range; 7139 extra.loc = (typeof options.loc === 'boolean') && options.loc; 7140 7141 if (typeof options.comment === 'boolean' && options.comment) { 7142 extra.comments = []; 7143 } 7144 if (typeof options.tolerant === 'boolean' && options.tolerant) { 7145 extra.errors = []; 7146 } 7147 7148 if (length > 0) { 7149 if (typeof source[0] === 'undefined') { 7150 // Try first to convert to a string. This is good as fast path 7151 // for old IE which understands string indexing for string 7152 // literals only and not for string object. 7153 if (code instanceof String) { 7154 source = code.valueOf(); 7155 } 7156 } 7157 } 7158 7159 patch(); 7160 7161 try { 7162 peek(); 7163 if (lookahead.type === Token.EOF) { 7164 return extra.tokens; 7165 } 7166 7167 token = lex(); 7168 while (lookahead.type !== Token.EOF) { 7169 try { 7170 token = lex(); 7171 } catch (lexError) { 7172 token = lookahead; 7173 if (extra.errors) { 7174 extra.errors.push(lexError); 7175 // We have to break on the first error 7176 // to avoid infinite loops. 7177 break; 7178 } else { 7179 throw lexError; 7180 } 7181 } 7182 } 7183 7184 filterTokenLocation(); 7185 tokens = extra.tokens; 7186 if (typeof extra.comments !== 'undefined') { 7187 filterCommentLocation(); 7188 tokens.comments = extra.comments; 7189 } 7190 if (typeof extra.errors !== 'undefined') { 7191 tokens.errors = extra.errors; 7192 } 7193 } catch (e) { 7194 throw e; 7195 } finally { 7196 unpatch(); 7197 extra = {}; 7198 } 7199 return tokens; 7200 } 7201 7202 function parse(code, options) { 7203 var program, toString; 7204 7205 toString = String; 7206 if (typeof code !== 'string' && !(code instanceof String)) { 7207 code = toString(code); 7208 } 7209 7210 delegate = SyntaxTreeDelegate; 7211 source = code; 7212 index = 0; 7213 lineNumber = (source.length > 0) ? 1 : 0; 7214 lineStart = 0; 7215 length = source.length; 7216 lookahead = null; 7217 state = { 7218 allowKeyword: false, 7219 allowIn: true, 7220 labelSet: {}, 7221 parenthesizedCount: 0, 7222 inFunctionBody: false, 7223 inIteration: false, 7224 inSwitch: false, 7225 yieldAllowed: false, 7226 yieldFound: false 7227 }; 7228 7229 extra = {}; 7230 if (typeof options !== 'undefined') { 7231 extra.range = (typeof options.range === 'boolean') && options.range; 7232 extra.loc = (typeof options.loc === 'boolean') && options.loc; 7233 7234 if (extra.loc && options.source !== null && options.source !== undefined) { 7235 delegate = extend(delegate, { 7236 'postProcess': function (node) { 7237 node.loc.source = toString(options.source); 7238 return node; 7239 } 7240 }); 7241 } 7242 7243 if (typeof options.tokens === 'boolean' && options.tokens) { 7244 extra.tokens = []; 7245 } 7246 if (typeof options.comment === 'boolean' && options.comment) { 7247 extra.comments = []; 7248 } 7249 if (typeof options.tolerant === 'boolean' && options.tolerant) { 7250 extra.errors = []; 7251 } 7252 } 7253 7254 if (length > 0) { 7255 if (typeof source[0] === 'undefined') { 7256 // Try first to convert to a string. This is good as fast path 7257 // for old IE which understands string indexing for string 7258 // literals only and not for string object. 7259 if (code instanceof String) { 7260 source = code.valueOf(); 7261 } 7262 } 7263 } 7264 7265 patch(); 7266 try { 7267 program = parseProgram(); 7268 if (typeof extra.comments !== 'undefined') { 7269 filterCommentLocation(); 7270 program.comments = extra.comments; 7271 } 7272 if (typeof extra.tokens !== 'undefined') { 7273 filterTokenLocation(); 7274 program.tokens = extra.tokens; 7275 } 7276 if (typeof extra.errors !== 'undefined') { 7277 program.errors = extra.errors; 7278 } 7279 if (extra.range || extra.loc) { 7280 program.body = filterGroup(program.body); 7281 } 7282 } catch (e) { 7283 throw e; 7284 } finally { 7285 unpatch(); 7286 extra = {}; 7287 } 7288 7289 return program; 7290 } 7291 7292 // Sync with package.json and component.json. 7293 exports.version = '1.1.0-dev-harmony'; 7294 7295 exports.tokenize = tokenize; 7296 7297 exports.parse = parse; 7298 7299 // Deep copy. 7300 exports.Syntax = (function () { 7301 var name, types = {}; 7302 7303 if (typeof Object.create === 'function') { 7304 types = Object.create(null); 7305 } 7306 7307 for (name in Syntax) { 7308 if (Syntax.hasOwnProperty(name)) { 7309 types[name] = Syntax[name]; 7310 } 7311 } 7312 7313 if (typeof Object.freeze === 'function') { 7314 Object.freeze(types); 7315 } 7316 7317 return types; 7318 }()); 7319 7320 })); 7321 /* vim: set sw=4 ts=4 et tw=80 : */ 7322 7323 },{}],6:[function(require,module,exports){ 7324 var Base62 = (function (my) { 7325 my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] 7326 7327 my.encode = function(i){ 7328 if (i === 0) {return '0'} 7329 var s = '' 7330 while (i > 0) { 7331 s = this.chars[i % 62] + s 7332 i = Math.floor(i/62) 7333 } 7334 return s 7335 }; 7336 my.decode = function(a,b,c,d){ 7337 for ( 7338 b = c = ( 7339 a === (/\W|_|^$/.test(a += "") || a) 7340 ) - 1; 7341 d = a.charCodeAt(c++); 7342 ) 7343 b = b * 62 + d - [, 48, 29, 87][d >> 5]; 7344 return b 7345 }; 7346 7347 return my; 7348 }({})); 7349 7350 module.exports = Base62 7351 },{}],7:[function(require,module,exports){ 7352 /* 7353 * Copyright 2009-2011 Mozilla Foundation and contributors 7354 * Licensed under the New BSD license. See LICENSE.txt or: 7355 * http://opensource.org/licenses/BSD-3-Clause 7356 */ 7357 exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; 7358 exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; 7359 exports.SourceNode = require('./source-map/source-node').SourceNode; 7360 7361 },{"./source-map/source-map-consumer":12,"./source-map/source-map-generator":13,"./source-map/source-node":14}],8:[function(require,module,exports){ 7362 /* -*- Mode: js; js-indent-level: 2; -*- */ 7363 /* 7364 * Copyright 2011 Mozilla Foundation and contributors 7365 * Licensed under the New BSD license. See LICENSE or: 7366 * http://opensource.org/licenses/BSD-3-Clause 7367 */ 7368 if (typeof define !== 'function') { 7369 var define = require('amdefine')(module); 7370 } 7371 define(function (require, exports, module) { 7372 7373 /** 7374 * A data structure which is a combination of an array and a set. Adding a new 7375 * member is O(1), testing for membership is O(1), and finding the index of an 7376 * element is O(1). Removing elements from the set is not supported. Only 7377 * strings are supported for membership. 7378 */ 7379 function ArraySet() { 7380 this._array = []; 7381 this._set = {}; 7382 } 7383 7384 /** 7385 * Static method for creating ArraySet instances from an existing array. 7386 */ 7387 ArraySet.fromArray = function ArraySet_fromArray(aArray) { 7388 var set = new ArraySet(); 7389 for (var i = 0, len = aArray.length; i < len; i++) { 7390 set.add(aArray[i]); 7391 } 7392 return set; 7393 }; 7394 7395 /** 7396 * Because behavior goes wacky when you set `__proto__` on `this._set`, we 7397 * have to prefix all the strings in our set with an arbitrary character. 7398 * 7399 * See https://github.com/mozilla/source-map/pull/31 and 7400 * https://github.com/mozilla/source-map/issues/30 7401 * 7402 * @param String aStr 7403 */ 7404 ArraySet.prototype._toSetString = function ArraySet__toSetString (aStr) { 7405 return "$" + aStr; 7406 }; 7407 7408 /** 7409 * Add the given string to this set. 7410 * 7411 * @param String aStr 7412 */ 7413 ArraySet.prototype.add = function ArraySet_add(aStr) { 7414 if (this.has(aStr)) { 7415 // Already a member; nothing to do. 7416 return; 7417 } 7418 var idx = this._array.length; 7419 this._array.push(aStr); 7420 this._set[this._toSetString(aStr)] = idx; 7421 }; 7422 7423 /** 7424 * Is the given string a member of this set? 7425 * 7426 * @param String aStr 7427 */ 7428 ArraySet.prototype.has = function ArraySet_has(aStr) { 7429 return Object.prototype.hasOwnProperty.call(this._set, 7430 this._toSetString(aStr)); 7431 }; 7432 7433 /** 7434 * What is the index of the given string in the array? 7435 * 7436 * @param String aStr 7437 */ 7438 ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { 7439 if (this.has(aStr)) { 7440 return this._set[this._toSetString(aStr)]; 7441 } 7442 throw new Error('"' + aStr + '" is not in the set.'); 7443 }; 7444 7445 /** 7446 * What is the element at the given index? 7447 * 7448 * @param Number aIdx 7449 */ 7450 ArraySet.prototype.at = function ArraySet_at(aIdx) { 7451 if (aIdx >= 0 && aIdx < this._array.length) { 7452 return this._array[aIdx]; 7453 } 7454 throw new Error('No element indexed by ' + aIdx); 7455 }; 7456 7457 /** 7458 * Returns the array representation of this set (which has the proper indices 7459 * indicated by indexOf). Note that this is a copy of the internal array used 7460 * for storing the members so that no one can mess with internal state. 7461 */ 7462 ArraySet.prototype.toArray = function ArraySet_toArray() { 7463 return this._array.slice(); 7464 }; 7465 7466 exports.ArraySet = ArraySet; 7467 7468 }); 7469 7470 },{"amdefine":16}],9:[function(require,module,exports){ 7471 /* -*- Mode: js; js-indent-level: 2; -*- */ 7472 /* 7473 * Copyright 2011 Mozilla Foundation and contributors 7474 * Licensed under the New BSD license. See LICENSE or: 7475 * http://opensource.org/licenses/BSD-3-Clause 7476 * 7477 * Based on the Base 64 VLQ implementation in Closure Compiler: 7478 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java 7479 * 7480 * Copyright 2011 The Closure Compiler Authors. All rights reserved. 7481 * Redistribution and use in source and binary forms, with or without 7482 * modification, are permitted provided that the following conditions are 7483 * met: 7484 * 7485 * * Redistributions of source code must retain the above copyright 7486 * notice, this list of conditions and the following disclaimer. 7487 * * Redistributions in binary form must reproduce the above 7488 * copyright notice, this list of conditions and the following 7489 * disclaimer in the documentation and/or other materials provided 7490 * with the distribution. 7491 * * Neither the name of Google Inc. nor the names of its 7492 * contributors may be used to endorse or promote products derived 7493 * from this software without specific prior written permission. 7494 * 7495 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 7496 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 7497 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 7498 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 7499 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 7500 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 7501 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 7502 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 7503 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 7504 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 7505 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 7506 */ 7507 if (typeof define !== 'function') { 7508 var define = require('amdefine')(module); 7509 } 7510 define(function (require, exports, module) { 7511 7512 var base64 = require('./base64'); 7513 7514 // A single base 64 digit can contain 6 bits of data. For the base 64 variable 7515 // length quantities we use in the source map spec, the first bit is the sign, 7516 // the next four bits are the actual value, and the 6th bit is the 7517 // continuation bit. The continuation bit tells us whether there are more 7518 // digits in this value following this digit. 7519 // 7520 // Continuation 7521 // | Sign 7522 // | | 7523 // V V 7524 // 101011 7525 7526 var VLQ_BASE_SHIFT = 5; 7527 7528 // binary: 100000 7529 var VLQ_BASE = 1 << VLQ_BASE_SHIFT; 7530 7531 // binary: 011111 7532 var VLQ_BASE_MASK = VLQ_BASE - 1; 7533 7534 // binary: 100000 7535 var VLQ_CONTINUATION_BIT = VLQ_BASE; 7536 7537 /** 7538 * Converts from a two-complement value to a value where the sign bit is 7539 * is placed in the least significant bit. For example, as decimals: 7540 * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) 7541 * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) 7542 */ 7543 function toVLQSigned(aValue) { 7544 return aValue < 0 7545 ? ((-aValue) << 1) + 1 7546 : (aValue << 1) + 0; 7547 } 7548 7549 /** 7550 * Converts to a two-complement value from a value where the sign bit is 7551 * is placed in the least significant bit. For example, as decimals: 7552 * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 7553 * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 7554 */ 7555 function fromVLQSigned(aValue) { 7556 var isNegative = (aValue & 1) === 1; 7557 var shifted = aValue >> 1; 7558 return isNegative 7559 ? -shifted 7560 : shifted; 7561 } 7562 7563 /** 7564 * Returns the base 64 VLQ encoded value. 7565 */ 7566 exports.encode = function base64VLQ_encode(aValue) { 7567 var encoded = ""; 7568 var digit; 7569 7570 var vlq = toVLQSigned(aValue); 7571 7572 do { 7573 digit = vlq & VLQ_BASE_MASK; 7574 vlq >>>= VLQ_BASE_SHIFT; 7575 if (vlq > 0) { 7576 // There are still more digits in this value, so we must make sure the 7577 // continuation bit is marked. 7578 digit |= VLQ_CONTINUATION_BIT; 7579 } 7580 encoded += base64.encode(digit); 7581 } while (vlq > 0); 7582 7583 return encoded; 7584 }; 7585 7586 /** 7587 * Decodes the next base 64 VLQ value from the given string and returns the 7588 * value and the rest of the string. 7589 */ 7590 exports.decode = function base64VLQ_decode(aStr) { 7591 var i = 0; 7592 var strLen = aStr.length; 7593 var result = 0; 7594 var shift = 0; 7595 var continuation, digit; 7596 7597 do { 7598 if (i >= strLen) { 7599 throw new Error("Expected more digits in base 64 VLQ value."); 7600 } 7601 digit = base64.decode(aStr.charAt(i++)); 7602 continuation = !!(digit & VLQ_CONTINUATION_BIT); 7603 digit &= VLQ_BASE_MASK; 7604 result = result + (digit << shift); 7605 shift += VLQ_BASE_SHIFT; 7606 } while (continuation); 7607 7608 return { 7609 value: fromVLQSigned(result), 7610 rest: aStr.slice(i) 7611 }; 7612 }; 7613 7614 }); 7615 7616 },{"./base64":10,"amdefine":16}],10:[function(require,module,exports){ 7617 /* -*- Mode: js; js-indent-level: 2; -*- */ 7618 /* 7619 * Copyright 2011 Mozilla Foundation and contributors 7620 * Licensed under the New BSD license. See LICENSE or: 7621 * http://opensource.org/licenses/BSD-3-Clause 7622 */ 7623 if (typeof define !== 'function') { 7624 var define = require('amdefine')(module); 7625 } 7626 define(function (require, exports, module) { 7627 7628 var charToIntMap = {}; 7629 var intToCharMap = {}; 7630 7631 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' 7632 .split('') 7633 .forEach(function (ch, index) { 7634 charToIntMap[ch] = index; 7635 intToCharMap[index] = ch; 7636 }); 7637 7638 /** 7639 * Encode an integer in the range of 0 to 63 to a single base 64 digit. 7640 */ 7641 exports.encode = function base64_encode(aNumber) { 7642 if (aNumber in intToCharMap) { 7643 return intToCharMap[aNumber]; 7644 } 7645 throw new TypeError("Must be between 0 and 63: " + aNumber); 7646 }; 7647 7648 /** 7649 * Decode a single base 64 digit to an integer. 7650 */ 7651 exports.decode = function base64_decode(aChar) { 7652 if (aChar in charToIntMap) { 7653 return charToIntMap[aChar]; 7654 } 7655 throw new TypeError("Not a valid base 64 digit: " + aChar); 7656 }; 7657 7658 }); 7659 7660 },{"amdefine":16}],11:[function(require,module,exports){ 7661 /* -*- Mode: js; js-indent-level: 2; -*- */ 7662 /* 7663 * Copyright 2011 Mozilla Foundation and contributors 7664 * Licensed under the New BSD license. See LICENSE or: 7665 * http://opensource.org/licenses/BSD-3-Clause 7666 */ 7667 if (typeof define !== 'function') { 7668 var define = require('amdefine')(module); 7669 } 7670 define(function (require, exports, module) { 7671 7672 /** 7673 * Recursive implementation of binary search. 7674 * 7675 * @param aLow Indices here and lower do not contain the needle. 7676 * @param aHigh Indices here and higher do not contain the needle. 7677 * @param aNeedle The element being searched for. 7678 * @param aHaystack The non-empty array being searched. 7679 * @param aCompare Function which takes two elements and returns -1, 0, or 1. 7680 */ 7681 function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { 7682 // This function terminates when one of the following is true: 7683 // 7684 // 1. We find the exact element we are looking for. 7685 // 7686 // 2. We did not find the exact element, but we can return the next 7687 // closest element that is less than that element. 7688 // 7689 // 3. We did not find the exact element, and there is no next-closest 7690 // element which is less than the one we are searching for, so we 7691 // return null. 7692 var mid = Math.floor((aHigh - aLow) / 2) + aLow; 7693 var cmp = aCompare(aNeedle, aHaystack[mid]); 7694 if (cmp === 0) { 7695 // Found the element we are looking for. 7696 return aHaystack[mid]; 7697 } 7698 else if (cmp > 0) { 7699 // aHaystack[mid] is greater than our needle. 7700 if (aHigh - mid > 1) { 7701 // The element is in the upper half. 7702 return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); 7703 } 7704 // We did not find an exact match, return the next closest one 7705 // (termination case 2). 7706 return aHaystack[mid]; 7707 } 7708 else { 7709 // aHaystack[mid] is less than our needle. 7710 if (mid - aLow > 1) { 7711 // The element is in the lower half. 7712 return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); 7713 } 7714 // The exact needle element was not found in this haystack. Determine if 7715 // we are in termination case (2) or (3) and return the appropriate thing. 7716 return aLow < 0 7717 ? null 7718 : aHaystack[aLow]; 7719 } 7720 } 7721 7722 /** 7723 * This is an implementation of binary search which will always try and return 7724 * the next lowest value checked if there is no exact hit. This is because 7725 * mappings between original and generated line/col pairs are single points, 7726 * and there is an implicit region between each of them, so a miss just means 7727 * that you aren't on the very start of a region. 7728 * 7729 * @param aNeedle The element you are looking for. 7730 * @param aHaystack The array that is being searched. 7731 * @param aCompare A function which takes the needle and an element in the 7732 * array and returns -1, 0, or 1 depending on whether the needle is less 7733 * than, equal to, or greater than the element, respectively. 7734 */ 7735 exports.search = function search(aNeedle, aHaystack, aCompare) { 7736 return aHaystack.length > 0 7737 ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) 7738 : null; 7739 }; 7740 7741 }); 7742 7743 },{"amdefine":16}],12:[function(require,module,exports){ 7744 /* -*- Mode: js; js-indent-level: 2; -*- */ 7745 /* 7746 * Copyright 2011 Mozilla Foundation and contributors 7747 * Licensed under the New BSD license. See LICENSE or: 7748 * http://opensource.org/licenses/BSD-3-Clause 7749 */ 7750 if (typeof define !== 'function') { 7751 var define = require('amdefine')(module); 7752 } 7753 define(function (require, exports, module) { 7754 7755 var util = require('./util'); 7756 var binarySearch = require('./binary-search'); 7757 var ArraySet = require('./array-set').ArraySet; 7758 var base64VLQ = require('./base64-vlq'); 7759 7760 /** 7761 * A SourceMapConsumer instance represents a parsed source map which we can 7762 * query for information about the original file positions by giving it a file 7763 * position in the generated source. 7764 * 7765 * The only parameter is the raw source map (either as a JSON string, or 7766 * already parsed to an object). According to the spec, source maps have the 7767 * following attributes: 7768 * 7769 * - version: Which version of the source map spec this map is following. 7770 * - sources: An array of URLs to the original source files. 7771 * - names: An array of identifiers which can be referrenced by individual mappings. 7772 * - sourceRoot: Optional. The URL root from which all sources are relative. 7773 * - mappings: A string of base64 VLQs which contain the actual mappings. 7774 * - file: The generated file this source map is associated with. 7775 * 7776 * Here is an example source map, taken from the source map spec[0]: 7777 * 7778 * { 7779 * version : 3, 7780 * file: "out.js", 7781 * sourceRoot : "", 7782 * sources: ["foo.js", "bar.js"], 7783 * names: ["src", "maps", "are", "fun"], 7784 * mappings: "AA,AB;;ABCDE;" 7785 * } 7786 * 7787 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# 7788 */ 7789 function SourceMapConsumer(aSourceMap) { 7790 var sourceMap = aSourceMap; 7791 if (typeof aSourceMap === 'string') { 7792 sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); 7793 } 7794 7795 var version = util.getArg(sourceMap, 'version'); 7796 var sources = util.getArg(sourceMap, 'sources'); 7797 var names = util.getArg(sourceMap, 'names'); 7798 var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); 7799 var mappings = util.getArg(sourceMap, 'mappings'); 7800 var file = util.getArg(sourceMap, 'file'); 7801 7802 if (version !== this._version) { 7803 throw new Error('Unsupported version: ' + version); 7804 } 7805 7806 this._names = ArraySet.fromArray(names); 7807 this._sources = ArraySet.fromArray(sources); 7808 this._sourceRoot = sourceRoot; 7809 this.file = file; 7810 7811 // `this._generatedMappings` and `this._originalMappings` hold the parsed 7812 // mapping coordinates from the source map's "mappings" attribute. Each 7813 // object in the array is of the form 7814 // 7815 // { 7816 // generatedLine: The line number in the generated code, 7817 // generatedColumn: The column number in the generated code, 7818 // source: The path to the original source file that generated this 7819 // chunk of code, 7820 // originalLine: The line number in the original source that 7821 // corresponds to this chunk of generated code, 7822 // originalColumn: The column number in the original source that 7823 // corresponds to this chunk of generated code, 7824 // name: The name of the original symbol which generated this chunk of 7825 // code. 7826 // } 7827 // 7828 // All properties except for `generatedLine` and `generatedColumn` can be 7829 // `null`. 7830 // 7831 // `this._generatedMappings` is ordered by the generated positions. 7832 // 7833 // `this._originalMappings` is ordered by the original positions. 7834 this._generatedMappings = []; 7835 this._originalMappings = []; 7836 this._parseMappings(mappings, sourceRoot); 7837 } 7838 7839 /** 7840 * The version of the source mapping spec that we are consuming. 7841 */ 7842 SourceMapConsumer.prototype._version = 3; 7843 7844 /** 7845 * The list of original sources. 7846 */ 7847 Object.defineProperty(SourceMapConsumer.prototype, 'sources', { 7848 get: function () { 7849 return this._sources.toArray().map(function (s) { 7850 return this._sourceRoot ? util.join(this._sourceRoot, s) : s; 7851 }, this); 7852 } 7853 }); 7854 7855 /** 7856 * Parse the mappings in a string in to a data structure which we can easily 7857 * query (an ordered list in this._generatedMappings). 7858 */ 7859 SourceMapConsumer.prototype._parseMappings = 7860 function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { 7861 var generatedLine = 1; 7862 var previousGeneratedColumn = 0; 7863 var previousOriginalLine = 0; 7864 var previousOriginalColumn = 0; 7865 var previousSource = 0; 7866 var previousName = 0; 7867 var mappingSeparator = /^[,;]/; 7868 var str = aStr; 7869 var mapping; 7870 var temp; 7871 7872 while (str.length > 0) { 7873 if (str.charAt(0) === ';') { 7874 generatedLine++; 7875 str = str.slice(1); 7876 previousGeneratedColumn = 0; 7877 } 7878 else if (str.charAt(0) === ',') { 7879 str = str.slice(1); 7880 } 7881 else { 7882 mapping = {}; 7883 mapping.generatedLine = generatedLine; 7884 7885 // Generated column. 7886 temp = base64VLQ.decode(str); 7887 mapping.generatedColumn = previousGeneratedColumn + temp.value; 7888 previousGeneratedColumn = mapping.generatedColumn; 7889 str = temp.rest; 7890 7891 if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { 7892 // Original source. 7893 temp = base64VLQ.decode(str); 7894 if (aSourceRoot) { 7895 mapping.source = util.join(aSourceRoot, this._sources.at(previousSource + temp.value)); 7896 } 7897 else { 7898 mapping.source = this._sources.at(previousSource + temp.value); 7899 } 7900 previousSource += temp.value; 7901 str = temp.rest; 7902 if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { 7903 throw new Error('Found a source, but no line and column'); 7904 } 7905 7906 // Original line. 7907 temp = base64VLQ.decode(str); 7908 mapping.originalLine = previousOriginalLine + temp.value; 7909 previousOriginalLine = mapping.originalLine; 7910 // Lines are stored 0-based 7911 mapping.originalLine += 1; 7912 str = temp.rest; 7913 if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { 7914 throw new Error('Found a source and line, but no column'); 7915 } 7916 7917 // Original column. 7918 temp = base64VLQ.decode(str); 7919 mapping.originalColumn = previousOriginalColumn + temp.value; 7920 previousOriginalColumn = mapping.originalColumn; 7921 str = temp.rest; 7922 7923 if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { 7924 // Original name. 7925 temp = base64VLQ.decode(str); 7926 mapping.name = this._names.at(previousName + temp.value); 7927 previousName += temp.value; 7928 str = temp.rest; 7929 } 7930 } 7931 7932 this._generatedMappings.push(mapping); 7933 this._originalMappings.push(mapping); 7934 } 7935 } 7936 7937 this._originalMappings.sort(this._compareOriginalPositions); 7938 }; 7939 7940 /** 7941 * Comparator between two mappings where the original positions are compared. 7942 */ 7943 SourceMapConsumer.prototype._compareOriginalPositions = 7944 function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) { 7945 if (mappingA.source > mappingB.source) { 7946 return 1; 7947 } 7948 else if (mappingA.source < mappingB.source) { 7949 return -1; 7950 } 7951 else { 7952 var cmp = mappingA.originalLine - mappingB.originalLine; 7953 return cmp === 0 7954 ? mappingA.originalColumn - mappingB.originalColumn 7955 : cmp; 7956 } 7957 }; 7958 7959 /** 7960 * Comparator between two mappings where the generated positions are compared. 7961 */ 7962 SourceMapConsumer.prototype._compareGeneratedPositions = 7963 function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) { 7964 var cmp = mappingA.generatedLine - mappingB.generatedLine; 7965 return cmp === 0 7966 ? mappingA.generatedColumn - mappingB.generatedColumn 7967 : cmp; 7968 }; 7969 7970 /** 7971 * Find the mapping that best matches the hypothetical "needle" mapping that 7972 * we are searching for in the given "haystack" of mappings. 7973 */ 7974 SourceMapConsumer.prototype._findMapping = 7975 function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, 7976 aColumnName, aComparator) { 7977 // To return the position we are searching for, we must first find the 7978 // mapping for the given position and then return the opposite position it 7979 // points to. Because the mappings are sorted, we can use binary search to 7980 // find the best mapping. 7981 7982 if (aNeedle[aLineName] <= 0) { 7983 throw new TypeError('Line must be greater than or equal to 1, got ' 7984 + aNeedle[aLineName]); 7985 } 7986 if (aNeedle[aColumnName] < 0) { 7987 throw new TypeError('Column must be greater than or equal to 0, got ' 7988 + aNeedle[aColumnName]); 7989 } 7990 7991 return binarySearch.search(aNeedle, aMappings, aComparator); 7992 }; 7993 7994 /** 7995 * Returns the original source, line, and column information for the generated 7996 * source's line and column positions provided. The only argument is an object 7997 * with the following properties: 7998 * 7999 * - line: The line number in the generated source. 8000 * - column: The column number in the generated source. 8001 * 8002 * and an object is returned with the following properties: 8003 * 8004 * - source: The original source file, or null. 8005 * - line: The line number in the original source, or null. 8006 * - column: The column number in the original source, or null. 8007 * - name: The original identifier, or null. 8008 */ 8009 SourceMapConsumer.prototype.originalPositionFor = 8010 function SourceMapConsumer_originalPositionFor(aArgs) { 8011 var needle = { 8012 generatedLine: util.getArg(aArgs, 'line'), 8013 generatedColumn: util.getArg(aArgs, 'column') 8014 }; 8015 8016 var mapping = this._findMapping(needle, 8017 this._generatedMappings, 8018 "generatedLine", 8019 "generatedColumn", 8020 this._compareGeneratedPositions) 8021 8022 if (mapping) { 8023 return { 8024 source: util.getArg(mapping, 'source', null), 8025 line: util.getArg(mapping, 'originalLine', null), 8026 column: util.getArg(mapping, 'originalColumn', null), 8027 name: util.getArg(mapping, 'name', null) 8028 }; 8029 } 8030 8031 return { 8032 source: null, 8033 line: null, 8034 column: null, 8035 name: null 8036 }; 8037 }; 8038 8039 /** 8040 * Returns the generated line and column information for the original source, 8041 * line, and column positions provided. The only argument is an object with 8042 * the following properties: 8043 * 8044 * - source: The filename of the original source. 8045 * - line: The line number in the original source. 8046 * - column: The column number in the original source. 8047 * 8048 * and an object is returned with the following properties: 8049 * 8050 * - line: The line number in the generated source, or null. 8051 * - column: The column number in the generated source, or null. 8052 */ 8053 SourceMapConsumer.prototype.generatedPositionFor = 8054 function SourceMapConsumer_generatedPositionFor(aArgs) { 8055 var needle = { 8056 source: util.getArg(aArgs, 'source'), 8057 originalLine: util.getArg(aArgs, 'line'), 8058 originalColumn: util.getArg(aArgs, 'column') 8059 }; 8060 8061 var mapping = this._findMapping(needle, 8062 this._originalMappings, 8063 "originalLine", 8064 "originalColumn", 8065 this._compareOriginalPositions) 8066 8067 if (mapping) { 8068 return { 8069 line: util.getArg(mapping, 'generatedLine', null), 8070 column: util.getArg(mapping, 'generatedColumn', null) 8071 }; 8072 } 8073 8074 return { 8075 line: null, 8076 column: null 8077 }; 8078 }; 8079 8080 SourceMapConsumer.GENERATED_ORDER = 1; 8081 SourceMapConsumer.ORIGINAL_ORDER = 2; 8082 8083 /** 8084 * Iterate over each mapping between an original source/line/column and a 8085 * generated line/column in this source map. 8086 * 8087 * @param Function aCallback 8088 * The function that is called with each mapping. This function should 8089 * not mutate the mapping. 8090 * @param Object aContext 8091 * Optional. If specified, this object will be the value of `this` every 8092 * time that `aCallback` is called. 8093 * @param aOrder 8094 * Either `SourceMapConsumer.GENERATED_ORDER` or 8095 * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to 8096 * iterate over the mappings sorted by the generated file's line/column 8097 * order or the original's source/line/column order, respectively. Defaults to 8098 * `SourceMapConsumer.GENERATED_ORDER`. 8099 */ 8100 SourceMapConsumer.prototype.eachMapping = 8101 function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { 8102 var context = aContext || null; 8103 var order = aOrder || SourceMapConsumer.GENERATED_ORDER; 8104 8105 var mappings; 8106 switch (order) { 8107 case SourceMapConsumer.GENERATED_ORDER: 8108 mappings = this._generatedMappings; 8109 break; 8110 case SourceMapConsumer.ORIGINAL_ORDER: 8111 mappings = this._originalMappings; 8112 break; 8113 default: 8114 throw new Error("Unknown order of iteration."); 8115 } 8116 8117 mappings.forEach(aCallback, context); 8118 }; 8119 8120 exports.SourceMapConsumer = SourceMapConsumer; 8121 8122 }); 8123 8124 },{"./array-set":8,"./base64-vlq":9,"./binary-search":11,"./util":15,"amdefine":16}],13:[function(require,module,exports){ 8125 /* -*- Mode: js; js-indent-level: 2; -*- */ 8126 /* 8127 * Copyright 2011 Mozilla Foundation and contributors 8128 * Licensed under the New BSD license. See LICENSE or: 8129 * http://opensource.org/licenses/BSD-3-Clause 8130 */ 8131 if (typeof define !== 'function') { 8132 var define = require('amdefine')(module); 8133 } 8134 define(function (require, exports, module) { 8135 8136 var base64VLQ = require('./base64-vlq'); 8137 var util = require('./util'); 8138 var ArraySet = require('./array-set').ArraySet; 8139 8140 /** 8141 * An instance of the SourceMapGenerator represents a source map which is 8142 * being built incrementally. To create a new one, you must pass an object 8143 * with the following properties: 8144 * 8145 * - file: The filename of the generated source. 8146 * - sourceRoot: An optional root for all URLs in this source map. 8147 */ 8148 function SourceMapGenerator(aArgs) { 8149 this._file = util.getArg(aArgs, 'file'); 8150 this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); 8151 this._sources = new ArraySet(); 8152 this._names = new ArraySet(); 8153 this._mappings = []; 8154 } 8155 8156 SourceMapGenerator.prototype._version = 3; 8157 8158 /** 8159 * Add a single mapping from original source line and column to the generated 8160 * source's line and column for this source map being created. The mapping 8161 * object should have the following properties: 8162 * 8163 * - generated: An object with the generated line and column positions. 8164 * - original: An object with the original line and column positions. 8165 * - source: The original source file (relative to the sourceRoot). 8166 * - name: An optional original token name for this mapping. 8167 */ 8168 SourceMapGenerator.prototype.addMapping = 8169 function SourceMapGenerator_addMapping(aArgs) { 8170 var generated = util.getArg(aArgs, 'generated'); 8171 var original = util.getArg(aArgs, 'original', null); 8172 var source = util.getArg(aArgs, 'source', null); 8173 var name = util.getArg(aArgs, 'name', null); 8174 8175 this._validateMapping(generated, original, source, name); 8176 8177 if (source && !this._sources.has(source)) { 8178 this._sources.add(source); 8179 } 8180 8181 if (name && !this._names.has(name)) { 8182 this._names.add(name); 8183 } 8184 8185 this._mappings.push({ 8186 generated: generated, 8187 original: original, 8188 source: source, 8189 name: name 8190 }); 8191 }; 8192 8193 /** 8194 * A mapping can have one of the three levels of data: 8195 * 8196 * 1. Just the generated position. 8197 * 2. The Generated position, original position, and original source. 8198 * 3. Generated and original position, original source, as well as a name 8199 * token. 8200 * 8201 * To maintain consistency, we validate that any new mapping being added falls 8202 * in to one of these categories. 8203 */ 8204 SourceMapGenerator.prototype._validateMapping = 8205 function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, 8206 aName) { 8207 if (aGenerated && 'line' in aGenerated && 'column' in aGenerated 8208 && aGenerated.line > 0 && aGenerated.column >= 0 8209 && !aOriginal && !aSource && !aName) { 8210 // Case 1. 8211 return; 8212 } 8213 else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated 8214 && aOriginal && 'line' in aOriginal && 'column' in aOriginal 8215 && aGenerated.line > 0 && aGenerated.column >= 0 8216 && aOriginal.line > 0 && aOriginal.column >= 0 8217 && aSource) { 8218 // Cases 2 and 3. 8219 return; 8220 } 8221 else { 8222 throw new Error('Invalid mapping.'); 8223 } 8224 }; 8225 8226 /** 8227 * Serialize the accumulated mappings in to the stream of base 64 VLQs 8228 * specified by the source map format. 8229 */ 8230 SourceMapGenerator.prototype._serializeMappings = 8231 function SourceMapGenerator_serializeMappings() { 8232 var previousGeneratedColumn = 0; 8233 var previousGeneratedLine = 1; 8234 var previousOriginalColumn = 0; 8235 var previousOriginalLine = 0; 8236 var previousName = 0; 8237 var previousSource = 0; 8238 var result = ''; 8239 var mapping; 8240 8241 // The mappings must be guarenteed to be in sorted order before we start 8242 // serializing them or else the generated line numbers (which are defined 8243 // via the ';' separators) will be all messed up. Note: it might be more 8244 // performant to maintain the sorting as we insert them, rather than as we 8245 // serialize them, but the big O is the same either way. 8246 this._mappings.sort(function (mappingA, mappingB) { 8247 var cmp = mappingA.generated.line - mappingB.generated.line; 8248 return cmp === 0 8249 ? mappingA.generated.column - mappingB.generated.column 8250 : cmp; 8251 }); 8252 8253 for (var i = 0, len = this._mappings.length; i < len; i++) { 8254 mapping = this._mappings[i]; 8255 8256 if (mapping.generated.line !== previousGeneratedLine) { 8257 previousGeneratedColumn = 0; 8258 while (mapping.generated.line !== previousGeneratedLine) { 8259 result += ';'; 8260 previousGeneratedLine++; 8261 } 8262 } 8263 else { 8264 if (i > 0) { 8265 result += ','; 8266 } 8267 } 8268 8269 result += base64VLQ.encode(mapping.generated.column 8270 - previousGeneratedColumn); 8271 previousGeneratedColumn = mapping.generated.column; 8272 8273 if (mapping.source && mapping.original) { 8274 result += base64VLQ.encode(this._sources.indexOf(mapping.source) 8275 - previousSource); 8276 previousSource = this._sources.indexOf(mapping.source); 8277 8278 // lines are stored 0-based in SourceMap spec version 3 8279 result += base64VLQ.encode(mapping.original.line - 1 8280 - previousOriginalLine); 8281 previousOriginalLine = mapping.original.line - 1; 8282 8283 result += base64VLQ.encode(mapping.original.column 8284 - previousOriginalColumn); 8285 previousOriginalColumn = mapping.original.column; 8286 8287 if (mapping.name) { 8288 result += base64VLQ.encode(this._names.indexOf(mapping.name) 8289 - previousName); 8290 previousName = this._names.indexOf(mapping.name); 8291 } 8292 } 8293 } 8294 8295 return result; 8296 }; 8297 8298 /** 8299 * Externalize the source map. 8300 */ 8301 SourceMapGenerator.prototype.toJSON = 8302 function SourceMapGenerator_toJSON() { 8303 var map = { 8304 version: this._version, 8305 file: this._file, 8306 sources: this._sources.toArray(), 8307 names: this._names.toArray(), 8308 mappings: this._serializeMappings() 8309 }; 8310 if (this._sourceRoot) { 8311 map.sourceRoot = this._sourceRoot; 8312 } 8313 return map; 8314 }; 8315 8316 /** 8317 * Render the source map being generated to a string. 8318 */ 8319 SourceMapGenerator.prototype.toString = 8320 function SourceMapGenerator_toString() { 8321 return JSON.stringify(this); 8322 }; 8323 8324 exports.SourceMapGenerator = SourceMapGenerator; 8325 8326 }); 8327 8328 },{"./array-set":8,"./base64-vlq":9,"./util":15,"amdefine":16}],14:[function(require,module,exports){ 8329 /* -*- Mode: js; js-indent-level: 2; -*- */ 8330 /* 8331 * Copyright 2011 Mozilla Foundation and contributors 8332 * Licensed under the New BSD license. See LICENSE or: 8333 * http://opensource.org/licenses/BSD-3-Clause 8334 */ 8335 if (typeof define !== 'function') { 8336 var define = require('amdefine')(module); 8337 } 8338 define(function (require, exports, module) { 8339 8340 var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; 8341 8342 /** 8343 * SourceNodes provide a way to abstract over interpolating/concatenating 8344 * snippets of generated JavaScript source code while maintaining the line and 8345 * column information associated with the original source code. 8346 * 8347 * @param aLine The original line number. 8348 * @param aColumn The original column number. 8349 * @param aSource The original source's filename. 8350 * @param aChunks Optional. An array of strings which are snippets of 8351 * generated JS, or other SourceNodes. 8352 */ 8353 function SourceNode(aLine, aColumn, aSource, aChunks) { 8354 this.children = []; 8355 this.line = aLine; 8356 this.column = aColumn; 8357 this.source = aSource; 8358 if (aChunks != null) this.add(aChunks); 8359 } 8360 8361 /** 8362 * Add a chunk of generated JS to this source node. 8363 * 8364 * @param aChunk A string snippet of generated JS code, another instance of 8365 * SourceNode, or an array where each member is one of those things. 8366 */ 8367 SourceNode.prototype.add = function SourceNode_add(aChunk) { 8368 if (Array.isArray(aChunk)) { 8369 aChunk.forEach(function (chunk) { 8370 this.add(chunk); 8371 }, this); 8372 } 8373 else if (aChunk instanceof SourceNode || typeof aChunk === "string") { 8374 if (aChunk) { 8375 this.children.push(aChunk); 8376 } 8377 } 8378 else { 8379 throw new TypeError( 8380 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk 8381 ); 8382 } 8383 return this; 8384 }; 8385 8386 /** 8387 * Add a chunk of generated JS to the beginning of this source node. 8388 * 8389 * @param aChunk A string snippet of generated JS code, another instance of 8390 * SourceNode, or an array where each member is one of those things. 8391 */ 8392 SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { 8393 if (Array.isArray(aChunk)) { 8394 for (var i = aChunk.length-1; i >= 0; i--) { 8395 this.prepend(aChunk[i]); 8396 } 8397 } 8398 else if (aChunk instanceof SourceNode || typeof aChunk === "string") { 8399 this.children.unshift(aChunk); 8400 } 8401 else { 8402 throw new TypeError( 8403 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk 8404 ); 8405 } 8406 return this; 8407 }; 8408 8409 /** 8410 * Walk over the tree of JS snippets in this node and its children. The 8411 * walking function is called once for each snippet of JS and is passed that 8412 * snippet and the its original associated source's line/column location. 8413 * 8414 * @param aFn The traversal function. 8415 */ 8416 SourceNode.prototype.walk = function SourceNode_walk(aFn) { 8417 this.children.forEach(function (chunk) { 8418 if (chunk instanceof SourceNode) { 8419 chunk.walk(aFn); 8420 } 8421 else { 8422 if (chunk !== '') { 8423 aFn(chunk, { source: this.source, line: this.line, column: this.column }); 8424 } 8425 } 8426 }, this); 8427 }; 8428 8429 /** 8430 * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between 8431 * each of `this.children`. 8432 * 8433 * @param aSep The separator. 8434 */ 8435 SourceNode.prototype.join = function SourceNode_join(aSep) { 8436 var newChildren; 8437 var i; 8438 var len = this.children.length 8439 if (len > 0) { 8440 newChildren = []; 8441 for (i = 0; i < len-1; i++) { 8442 newChildren.push(this.children[i]); 8443 newChildren.push(aSep); 8444 } 8445 newChildren.push(this.children[i]); 8446 this.children = newChildren; 8447 } 8448 return this; 8449 }; 8450 8451 /** 8452 * Call String.prototype.replace on the very right-most source snippet. Useful 8453 * for trimming whitespace from the end of a source node, etc. 8454 * 8455 * @param aPattern The pattern to replace. 8456 * @param aReplacement The thing to replace the pattern with. 8457 */ 8458 SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { 8459 var lastChild = this.children[this.children.length - 1]; 8460 if (lastChild instanceof SourceNode) { 8461 lastChild.replaceRight(aPattern, aReplacement); 8462 } 8463 else if (typeof lastChild === 'string') { 8464 this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); 8465 } 8466 else { 8467 this.children.push(''.replace(aPattern, aReplacement)); 8468 } 8469 return this; 8470 }; 8471 8472 /** 8473 * Return the string representation of this source node. Walks over the tree 8474 * and concatenates all the various snippets together to one string. 8475 */ 8476 SourceNode.prototype.toString = function SourceNode_toString() { 8477 var str = ""; 8478 this.walk(function (chunk) { 8479 str += chunk; 8480 }); 8481 return str; 8482 }; 8483 8484 /** 8485 * Returns the string representation of this source node along with a source 8486 * map. 8487 */ 8488 SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { 8489 var generated = { 8490 code: "", 8491 line: 1, 8492 column: 0 8493 }; 8494 var map = new SourceMapGenerator(aArgs); 8495 this.walk(function (chunk, original) { 8496 generated.code += chunk; 8497 if (original.source != null 8498 && original.line != null 8499 && original.column != null) { 8500 map.addMapping({ 8501 source: original.source, 8502 original: { 8503 line: original.line, 8504 column: original.column 8505 }, 8506 generated: { 8507 line: generated.line, 8508 column: generated.column 8509 } 8510 }); 8511 } 8512 chunk.split('').forEach(function (char) { 8513 if (char === '\n') { 8514 generated.line++; 8515 generated.column = 0; 8516 } else { 8517 generated.column++; 8518 } 8519 }); 8520 }); 8521 8522 return { code: generated.code, map: map }; 8523 }; 8524 8525 exports.SourceNode = SourceNode; 8526 8527 }); 8528 8529 },{"./source-map-generator":13,"amdefine":16}],15:[function(require,module,exports){ 8530 /* -*- Mode: js; js-indent-level: 2; -*- */ 8531 /* 8532 * Copyright 2011 Mozilla Foundation and contributors 8533 * Licensed under the New BSD license. See LICENSE or: 8534 * http://opensource.org/licenses/BSD-3-Clause 8535 */ 8536 if (typeof define !== 'function') { 8537 var define = require('amdefine')(module); 8538 } 8539 define(function (require, exports, module) { 8540 8541 /** 8542 * This is a helper function for getting values from parameter/options 8543 * objects. 8544 * 8545 * @param args The object we are extracting values from 8546 * @param name The name of the property we are getting. 8547 * @param defaultValue An optional value to return if the property is missing 8548 * from the object. If this is not specified and the property is missing, an 8549 * error will be thrown. 8550 */ 8551 function getArg(aArgs, aName, aDefaultValue) { 8552 if (aName in aArgs) { 8553 return aArgs[aName]; 8554 } else if (arguments.length === 3) { 8555 return aDefaultValue; 8556 } else { 8557 throw new Error('"' + aName + '" is a required argument.'); 8558 } 8559 } 8560 exports.getArg = getArg; 8561 8562 function join(aRoot, aPath) { 8563 return aPath.charAt(0) === '/' 8564 ? aPath 8565 : aRoot.replace(/\/*$/, '') + '/' + aPath; 8566 } 8567 exports.join = join; 8568 8569 }); 8570 8571 },{"amdefine":16}],16:[function(require,module,exports){ 8572 var process=require("__browserify_process"),__filename="/../node_modules/jstransform/node_modules/source-map/node_modules/amdefine/amdefine.js";/** vim: et:ts=4:sw=4:sts=4 8573 * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. 8574 * Available via the MIT or new BSD license. 8575 * see: http://github.com/jrburke/amdefine for details 8576 */ 8577 8578 /*jslint node: true */ 8579 /*global module, process */ 8580 'use strict'; 8581 8582 /** 8583 * Creates a define for node. 8584 * @param {Object} module the "module" object that is defined by Node for the 8585 * current module. 8586 * @param {Function} [requireFn]. Node's require function for the current module. 8587 * It only needs to be passed in Node versions before 0.5, when module.require 8588 * did not exist. 8589 * @returns {Function} a define function that is usable for the current node 8590 * module. 8591 */ 8592 function amdefine(module, requireFn) { 8593 'use strict'; 8594 var defineCache = {}, 8595 loaderCache = {}, 8596 alreadyCalled = false, 8597 path = require('path'), 8598 makeRequire, stringRequire; 8599 8600 /** 8601 * Trims the . and .. from an array of path segments. 8602 * It will keep a leading path segment if a .. will become 8603 * the first path segment, to help with module name lookups, 8604 * which act like paths, but can be remapped. But the end result, 8605 * all paths that use this function should look normalized. 8606 * NOTE: this method MODIFIES the input array. 8607 * @param {Array} ary the array of path segments. 8608 */ 8609 function trimDots(ary) { 8610 var i, part; 8611 for (i = 0; ary[i]; i+= 1) { 8612 part = ary[i]; 8613 if (part === '.') { 8614 ary.splice(i, 1); 8615 i -= 1; 8616 } else if (part === '..') { 8617 if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { 8618 //End of the line. Keep at least one non-dot 8619 //path segment at the front so it can be mapped 8620 //correctly to disk. Otherwise, there is likely 8621 //no path mapping for a path starting with '..'. 8622 //This can still fail, but catches the most reasonable 8623 //uses of .. 8624 break; 8625 } else if (i > 0) { 8626 ary.splice(i - 1, 2); 8627 i -= 2; 8628 } 8629 } 8630 } 8631 } 8632 8633 function normalize(name, baseName) { 8634 var baseParts; 8635 8636 //Adjust any relative paths. 8637 if (name && name.charAt(0) === '.') { 8638 //If have a base name, try to normalize against it, 8639 //otherwise, assume it is a top-level require that will 8640 //be relative to baseUrl in the end. 8641 if (baseName) { 8642 baseParts = baseName.split('/'); 8643 baseParts = baseParts.slice(0, baseParts.length - 1); 8644 baseParts = baseParts.concat(name.split('/')); 8645 trimDots(baseParts); 8646 name = baseParts.join('/'); 8647 } 8648 } 8649 8650 return name; 8651 } 8652 8653 /** 8654 * Create the normalize() function passed to a loader plugin's 8655 * normalize method. 8656 */ 8657 function makeNormalize(relName) { 8658 return function (name) { 8659 return normalize(name, relName); 8660 }; 8661 } 8662 8663 function makeLoad(id) { 8664 function load(value) { 8665 loaderCache[id] = value; 8666 } 8667 8668 load.fromText = function (id, text) { 8669 //This one is difficult because the text can/probably uses 8670 //define, and any relative paths and requires should be relative 8671 //to that id was it would be found on disk. But this would require 8672 //bootstrapping a module/require fairly deeply from node core. 8673 //Not sure how best to go about that yet. 8674 throw new Error('amdefine does not implement load.fromText'); 8675 }; 8676 8677 return load; 8678 } 8679 8680 makeRequire = function (systemRequire, exports, module, relId) { 8681 function amdRequire(deps, callback) { 8682 if (typeof deps === 'string') { 8683 //Synchronous, single module require('') 8684 return stringRequire(systemRequire, exports, module, deps, relId); 8685 } else { 8686 //Array of dependencies with a callback. 8687 8688 //Convert the dependencies to modules. 8689 deps = deps.map(function (depName) { 8690 return stringRequire(systemRequire, exports, module, depName, relId); 8691 }); 8692 8693 //Wait for next tick to call back the require call. 8694 process.nextTick(function () { 8695 callback.apply(null, deps); 8696 }); 8697 } 8698 } 8699 8700 amdRequire.toUrl = function (filePath) { 8701 if (filePath.indexOf('.') === 0) { 8702 return normalize(filePath, path.dirname(module.filename)); 8703 } else { 8704 return filePath; 8705 } 8706 }; 8707 8708 return amdRequire; 8709 }; 8710 8711 //Favor explicit value, passed in if the module wants to support Node 0.4. 8712 requireFn = requireFn || function req() { 8713 return module.require.apply(module, arguments); 8714 }; 8715 8716 function runFactory(id, deps, factory) { 8717 var r, e, m, result; 8718 8719 if (id) { 8720 e = loaderCache[id] = {}; 8721 m = { 8722 id: id, 8723 uri: __filename, 8724 exports: e 8725 }; 8726 r = makeRequire(requireFn, e, m, id); 8727 } else { 8728 //Only support one define call per file 8729 if (alreadyCalled) { 8730 throw new Error('amdefine with no module ID cannot be called more than once per file.'); 8731 } 8732 alreadyCalled = true; 8733 8734 //Use the real variables from node 8735 //Use module.exports for exports, since 8736 //the exports in here is amdefine exports. 8737 e = module.exports; 8738 m = module; 8739 r = makeRequire(requireFn, e, m, module.id); 8740 } 8741 8742 //If there are dependencies, they are strings, so need 8743 //to convert them to dependency values. 8744 if (deps) { 8745 deps = deps.map(function (depName) { 8746 return r(depName); 8747 }); 8748 } 8749 8750 //Call the factory with the right dependencies. 8751 if (typeof factory === 'function') { 8752 result = factory.apply(m.exports, deps); 8753 } else { 8754 result = factory; 8755 } 8756 8757 if (result !== undefined) { 8758 m.exports = result; 8759 if (id) { 8760 loaderCache[id] = m.exports; 8761 } 8762 } 8763 } 8764 8765 stringRequire = function (systemRequire, exports, module, id, relId) { 8766 //Split the ID by a ! so that 8767 var index = id.indexOf('!'), 8768 originalId = id, 8769 prefix, plugin; 8770 8771 if (index === -1) { 8772 id = normalize(id, relId); 8773 8774 //Straight module lookup. If it is one of the special dependencies, 8775 //deal with it, otherwise, delegate to node. 8776 if (id === 'require') { 8777 return makeRequire(systemRequire, exports, module, relId); 8778 } else if (id === 'exports') { 8779 return exports; 8780 } else if (id === 'module') { 8781 return module; 8782 } else if (loaderCache.hasOwnProperty(id)) { 8783 return loaderCache[id]; 8784 } else if (defineCache[id]) { 8785 runFactory.apply(null, defineCache[id]); 8786 return loaderCache[id]; 8787 } else { 8788 if(systemRequire) { 8789 return systemRequire(originalId); 8790 } else { 8791 throw new Error('No module with ID: ' + id); 8792 } 8793 } 8794 } else { 8795 //There is a plugin in play. 8796 prefix = id.substring(0, index); 8797 id = id.substring(index + 1, id.length); 8798 8799 plugin = stringRequire(systemRequire, exports, module, prefix, relId); 8800 8801 if (plugin.normalize) { 8802 id = plugin.normalize(id, makeNormalize(relId)); 8803 } else { 8804 //Normalize the ID normally. 8805 id = normalize(id, relId); 8806 } 8807 8808 if (loaderCache[id]) { 8809 return loaderCache[id]; 8810 } else { 8811 plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); 8812 8813 return loaderCache[id]; 8814 } 8815 } 8816 }; 8817 8818 //Create a define function specific to the module asking for amdefine. 8819 function define(id, deps, factory) { 8820 if (Array.isArray(id)) { 8821 factory = deps; 8822 deps = id; 8823 id = undefined; 8824 } else if (typeof id !== 'string') { 8825 factory = id; 8826 id = deps = undefined; 8827 } 8828 8829 if (deps && !Array.isArray(deps)) { 8830 factory = deps; 8831 deps = undefined; 8832 } 8833 8834 if (!deps) { 8835 deps = ['require', 'exports', 'module']; 8836 } 8837 8838 //Set up properties for this module. If an ID, then use 8839 //internal cache. If no ID, then use the external variables 8840 //for this node module. 8841 if (id) { 8842 //Put the module in deep freeze until there is a 8843 //require call for it. 8844 defineCache[id] = [id, deps, factory]; 8845 } else { 8846 runFactory(id, deps, factory); 8847 } 8848 } 8849 8850 //define.require, which has access to all the values in the 8851 //cache. Useful for AMD modules that all have IDs in the file, 8852 //but need to finally export a value to node based on one of those 8853 //IDs. 8854 define.require = function (id) { 8855 if (loaderCache[id]) { 8856 return loaderCache[id]; 8857 } 8858 8859 if (defineCache[id]) { 8860 runFactory.apply(null, defineCache[id]); 8861 return loaderCache[id]; 8862 } 8863 }; 8864 8865 define.amd = {}; 8866 8867 return define; 8868 } 8869 8870 module.exports = amdefine; 8871 8872 },{"__browserify_process":4,"path":2}],17:[function(require,module,exports){ 8873 /** 8874 * Copyright 2013 Facebook, Inc. 8875 * 8876 * Licensed under the Apache License, Version 2.0 (the "License"); 8877 * you may not use this file except in compliance with the License. 8878 * You may obtain a copy of the License at 8879 * 8880 * http://www.apache.org/licenses/LICENSE-2.0 8881 * 8882 * Unless required by applicable law or agreed to in writing, software 8883 * distributed under the License is distributed on an "AS IS" BASIS, 8884 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8885 * See the License for the specific language governing permissions and 8886 * limitations under the License. 8887 */ 8888 8889 var docblockRe = /^\s*(\/\*\*(.|\r?\n)*?\*\/)/; 8890 var ltrimRe = /^\s*/; 8891 /** 8892 * @param {String} contents 8893 * @return {String} 8894 */ 8895 function extract(contents) { 8896 var match = contents.match(docblockRe); 8897 if (match) { 8898 return match[0].replace(ltrimRe, '') || ''; 8899 } 8900 return ''; 8901 } 8902 8903 8904 var commentStartRe = /^\/\*\*?/; 8905 var commentEndRe = /\*\/$/; 8906 var wsRe = /[\t ]+/g; 8907 var stringStartRe = /(\r?\n|^) *\*/g; 8908 var multilineRe = /(?:^|\r?\n) *(@[^\r\n]*?) *\r?\n *([^@\r\n\s][^@\r\n]+?) *\r?\n/g; 8909 var propertyRe = /(?:^|\r?\n) *@(\S+) *([^\r\n]*)/g; 8910 8911 /** 8912 * @param {String} contents 8913 * @return {Array} 8914 */ 8915 function parse(docblock) { 8916 docblock = docblock 8917 .replace(commentStartRe, '') 8918 .replace(commentEndRe, '') 8919 .replace(wsRe, ' ') 8920 .replace(stringStartRe, '$1'); 8921 8922 // Normalize multi-line directives 8923 var prev = ''; 8924 while (prev != docblock) { 8925 prev = docblock; 8926 docblock = docblock.replace(multilineRe, "\n$1 $2\n"); 8927 } 8928 docblock = docblock.trim(); 8929 8930 var result = []; 8931 var match; 8932 while (match = propertyRe.exec(docblock)) { 8933 result.push([match[1], match[2]]); 8934 } 8935 8936 return result; 8937 } 8938 8939 /** 8940 * Same as parse but returns an object of prop: value instead of array of paris 8941 * If a property appers more than once the last one will be returned 8942 * 8943 * @param {String} contents 8944 * @return {Object} 8945 */ 8946 function parseAsObject(docblock) { 8947 var pairs = parse(docblock); 8948 var result = {}; 8949 for (var i = 0; i < pairs.length; i++) { 8950 result[pairs[i][0]] = pairs[i][1]; 8951 } 8952 return result; 8953 } 8954 8955 8956 exports.extract = extract; 8957 exports.parse = parse; 8958 exports.parseAsObject = parseAsObject; 8959 8960 },{}],18:[function(require,module,exports){ 8961 /** 8962 * Copyright 2013 Facebook, Inc. 8963 * 8964 * Licensed under the Apache License, Version 2.0 (the "License"); 8965 * you may not use this file except in compliance with the License. 8966 * You may obtain a copy of the License at 8967 * 8968 * http://www.apache.org/licenses/LICENSE-2.0 8969 * 8970 * Unless required by applicable law or agreed to in writing, software 8971 * distributed under the License is distributed on an "AS IS" BASIS, 8972 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8973 * See the License for the specific language governing permissions and 8974 * limitations under the License. 8975 */ 8976 8977 8978 /*jslint node: true*/ 8979 "use strict"; 8980 8981 /** 8982 * Syntax transfomer for javascript. Takes the source in, spits the source 8983 * out. 8984 * 8985 * Parses input source with esprima, applies the given list of visitors to the 8986 * AST tree, and returns the resulting output. 8987 */ 8988 var esprima = require('esprima-fb'); 8989 8990 var createState = require('./utils').createState; 8991 var catchup = require('./utils').catchup; 8992 var updateState = require('./utils').updateState; 8993 var analyzeAndTraverse = require('./utils').analyzeAndTraverse; 8994 8995 var Syntax = esprima.Syntax; 8996 8997 /** 8998 * @param {object} node 8999 * @param {object} parentNode 9000 * @return {boolean} 9001 */ 9002 function _nodeIsClosureScopeBoundary(node, parentNode) { 9003 if (node.type === Syntax.Program) { 9004 return true; 9005 } 9006 9007 var parentIsFunction = 9008 parentNode.type === Syntax.FunctionDeclaration 9009 || parentNode.type === Syntax.FunctionExpression; 9010 9011 return node.type === Syntax.BlockStatement && parentIsFunction; 9012 } 9013 9014 function _nodeIsBlockScopeBoundary(node, parentNode) { 9015 if (node.type === Syntax.Program) { 9016 return false; 9017 } 9018 9019 return node.type === Syntax.BlockStatement 9020 && parentNode.type === Syntax.CatchClause; 9021 } 9022 9023 /** 9024 * @param {object} node 9025 * @param {function} visitor 9026 * @param {array} path 9027 * @param {object} state 9028 */ 9029 function traverse(node, path, state) { 9030 // Create a scope stack entry if this is the first node we've encountered in 9031 // its local scope 9032 var parentNode = path[0]; 9033 if (!Array.isArray(node) && state.localScope.parentNode !== parentNode) { 9034 if (_nodeIsClosureScopeBoundary(node, parentNode)) { 9035 var scopeIsStrict = 9036 state.scopeIsStrict 9037 || node.body.length > 0 9038 && node.body[0].type === Syntax.ExpressionStatement 9039 && node.body[0].expression.type === Syntax.Literal 9040 && node.body[0].expression.value === 'use strict'; 9041 9042 if (node.type === Syntax.Program) { 9043 state = updateState(state, { 9044 scopeIsStrict: scopeIsStrict 9045 }); 9046 } else { 9047 state = updateState(state, { 9048 localScope: { 9049 parentNode: parentNode, 9050 parentScope: state.localScope, 9051 identifiers: {} 9052 }, 9053 scopeIsStrict: scopeIsStrict 9054 }); 9055 9056 // All functions have an implicit 'arguments' object in scope 9057 state.localScope.identifiers['arguments'] = true; 9058 9059 // Include function arg identifiers in the scope boundaries of the 9060 // function 9061 if (parentNode.params.length > 0) { 9062 var param; 9063 for (var i = 0; i < parentNode.params.length; i++) { 9064 param = parentNode.params[i]; 9065 if (param.type === Syntax.Identifier) { 9066 state.localScope.identifiers[param.name] = true; 9067 } 9068 } 9069 } 9070 9071 // Named FunctionExpressions scope their name within the body block of 9072 // themselves only 9073 if (parentNode.type === Syntax.FunctionExpression && parentNode.id) { 9074 state.localScope.identifiers[parentNode.id.name] = true; 9075 } 9076 } 9077 9078 // Traverse and find all local identifiers in this closure first to 9079 // account for function/variable declaration hoisting 9080 collectClosureIdentsAndTraverse(node, path, state); 9081 } 9082 9083 if (_nodeIsBlockScopeBoundary(node, parentNode)) { 9084 state = updateState(state, { 9085 localScope: { 9086 parentNode: parentNode, 9087 parentScope: state.localScope, 9088 identifiers: {} 9089 } 9090 }); 9091 9092 if (parentNode.type === Syntax.CatchClause) { 9093 state.localScope.identifiers[parentNode.param.name] = true; 9094 } 9095 collectBlockIdentsAndTraverse(node, path, state); 9096 } 9097 } 9098 9099 // Only catchup() before and after traversing a child node 9100 function traverser(node, path, state) { 9101 node.range && catchup(node.range[0], state); 9102 traverse(node, path, state); 9103 node.range && catchup(node.range[1], state); 9104 } 9105 9106 analyzeAndTraverse(walker, traverser, node, path, state); 9107 } 9108 9109 function collectClosureIdentsAndTraverse(node, path, state) { 9110 analyzeAndTraverse( 9111 visitLocalClosureIdentifiers, 9112 collectClosureIdentsAndTraverse, 9113 node, 9114 path, 9115 state 9116 ); 9117 } 9118 9119 function collectBlockIdentsAndTraverse(node, path, state) { 9120 analyzeAndTraverse( 9121 visitLocalBlockIdentifiers, 9122 collectBlockIdentsAndTraverse, 9123 node, 9124 path, 9125 state 9126 ); 9127 } 9128 9129 function visitLocalClosureIdentifiers(node, path, state) { 9130 var identifiers = state.localScope.identifiers; 9131 switch (node.type) { 9132 case Syntax.FunctionExpression: 9133 // Function expressions don't get their names (if there is one) added to 9134 // the closure scope they're defined in 9135 return false; 9136 case Syntax.ClassDeclaration: 9137 case Syntax.ClassExpression: 9138 case Syntax.FunctionDeclaration: 9139 if (node.id) { 9140 identifiers[node.id.name] = true; 9141 } 9142 return false; 9143 case Syntax.VariableDeclarator: 9144 if (path[0].kind === 'var') { 9145 identifiers[node.id.name] = true; 9146 } 9147 break; 9148 } 9149 } 9150 9151 function visitLocalBlockIdentifiers(node, path, state) { 9152 // TODO: Support 'let' here...maybe...one day...or something... 9153 if (node.type === Syntax.CatchClause) { 9154 return false; 9155 } 9156 } 9157 9158 function walker(node, path, state) { 9159 var visitors = state.g.visitors; 9160 for (var i = 0; i < visitors.length; i++) { 9161 if (visitors[i].test(node, path, state)) { 9162 return visitors[i](traverse, node, path, state); 9163 } 9164 } 9165 } 9166 9167 /** 9168 * Applies all available transformations to the source 9169 * @param {array} visitors 9170 * @param {string} source 9171 * @param {?object} options 9172 * @return {object} 9173 */ 9174 function transform(visitors, source, options) { 9175 options = options || {}; 9176 9177 var ast; 9178 try { 9179 ast = esprima.parse(source, { 9180 comment: true, 9181 loc: true, 9182 range: true 9183 }); 9184 } catch (e) { 9185 e.message = 'Parse Error: ' + e.message; 9186 throw e; 9187 } 9188 var state = createState(source, ast, options); 9189 state.g.visitors = visitors; 9190 9191 if (options.sourceMap) { 9192 var SourceMapGenerator = require('source-map').SourceMapGenerator; 9193 state.g.sourceMap = new SourceMapGenerator({file: 'transformed.js'}); 9194 } 9195 9196 traverse(ast, [], state); 9197 catchup(source.length, state); 9198 9199 var ret = {code: state.g.buffer}; 9200 if (options.sourceMap) { 9201 ret.sourceMap = state.g.sourceMap; 9202 ret.sourceMapFilename = options.filename || 'source.js'; 9203 } 9204 return ret; 9205 } 9206 9207 exports.transform = transform; 9208 9209 },{"./utils":19,"esprima-fb":5,"source-map":7}],19:[function(require,module,exports){ 9210 /** 9211 * Copyright 2013 Facebook, Inc. 9212 * 9213 * Licensed under the Apache License, Version 2.0 (the "License"); 9214 * you may not use this file except in compliance with the License. 9215 * You may obtain a copy of the License at 9216 * 9217 * http://www.apache.org/licenses/LICENSE-2.0 9218 * 9219 * Unless required by applicable law or agreed to in writing, software 9220 * distributed under the License is distributed on an "AS IS" BASIS, 9221 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9222 * See the License for the specific language governing permissions and 9223 * limitations under the License. 9224 */ 9225 9226 9227 /*jslint node: true*/ 9228 9229 /** 9230 * A `state` object represents the state of the parser. It has "local" and 9231 * "global" parts. Global contains parser position, source, etc. Local contains 9232 * scope based properties like current class name. State should contain all the 9233 * info required for transformation. It's the only mandatory object that is 9234 * being passed to every function in transform chain. 9235 * 9236 * @param {string} source 9237 * @param {object} transformOptions 9238 * @return {object} 9239 */ 9240 function createState(source, rootNode, transformOptions) { 9241 return { 9242 /** 9243 * A tree representing the current local scope (and its lexical scope chain) 9244 * Useful for tracking identifiers from parent scopes, etc. 9245 * @type {Object} 9246 */ 9247 localScope: { 9248 parentNode: rootNode, 9249 parentScope: null, 9250 identifiers: {} 9251 }, 9252 /** 9253 * The name (and, if applicable, expression) of the super class 9254 * @type {Object} 9255 */ 9256 superClass: null, 9257 /** 9258 * The namespace to use when munging identifiers 9259 * @type {String} 9260 */ 9261 mungeNamespace: '', 9262 /** 9263 * Ref to the node for the FunctionExpression of the enclosing 9264 * MethodDefinition 9265 * @type {Object} 9266 */ 9267 methodFuncNode: null, 9268 /** 9269 * Name of the enclosing class 9270 * @type {String} 9271 */ 9272 className: null, 9273 /** 9274 * Whether we're currently within a `strict` scope 9275 * @type {Bool} 9276 */ 9277 scopeIsStrict: null, 9278 /** 9279 * Global state (not affected by updateState) 9280 * @type {Object} 9281 */ 9282 g: { 9283 /** 9284 * A set of general options that transformations can consider while doing 9285 * a transformation: 9286 * 9287 * - minify 9288 * Specifies that transformation steps should do their best to minify 9289 * the output source when possible. This is useful for places where 9290 * minification optimizations are possible with higher-level context 9291 * info than what jsxmin can provide. 9292 * 9293 * For example, the ES6 class transform will minify munged private 9294 * variables if this flag is set. 9295 */ 9296 opts: transformOptions, 9297 /** 9298 * Current position in the source code 9299 * @type {Number} 9300 */ 9301 position: 0, 9302 /** 9303 * Buffer containing the result 9304 * @type {String} 9305 */ 9306 buffer: '', 9307 /** 9308 * Indentation offset (only negative offset is supported now) 9309 * @type {Number} 9310 */ 9311 indentBy: 0, 9312 /** 9313 * Source that is being transformed 9314 * @type {String} 9315 */ 9316 source: source, 9317 9318 /** 9319 * Cached parsed docblock (see getDocblock) 9320 * @type {object} 9321 */ 9322 docblock: null, 9323 9324 /** 9325 * Whether the thing was used 9326 * @type {Boolean} 9327 */ 9328 tagNamespaceUsed: false, 9329 9330 /** 9331 * If using bolt xjs transformation 9332 * @type {Boolean} 9333 */ 9334 isBolt: undefined, 9335 9336 /** 9337 * Whether to record source map (expensive) or not 9338 * @type {SourceMapGenerator|null} 9339 */ 9340 sourceMap: null, 9341 9342 /** 9343 * Filename of the file being processed. Will be returned as a source 9344 * attribute in the source map 9345 */ 9346 sourceMapFilename: 'source.js', 9347 9348 /** 9349 * Only when source map is used: last line in the source for which 9350 * source map was generated 9351 * @type {Number} 9352 */ 9353 sourceLine: 1, 9354 9355 /** 9356 * Only when source map is used: last line in the buffer for which 9357 * source map was generated 9358 * @type {Number} 9359 */ 9360 bufferLine: 1, 9361 9362 /** 9363 * The top-level Program AST for the original file. 9364 */ 9365 originalProgramAST: null, 9366 9367 sourceColumn: 0, 9368 bufferColumn: 0 9369 } 9370 }; 9371 } 9372 9373 /** 9374 * Updates a copy of a given state with "update" and returns an updated state. 9375 * 9376 * @param {object} state 9377 * @param {object} update 9378 * @return {object} 9379 */ 9380 function updateState(state, update) { 9381 var ret = Object.create(state); 9382 Object.keys(update).forEach(function(updatedKey) { 9383 ret[updatedKey] = update[updatedKey]; 9384 }); 9385 return ret; 9386 } 9387 9388 /** 9389 * Given a state fill the resulting buffer from the original source up to 9390 * the end 9391 * 9392 * @param {number} end 9393 * @param {object} state 9394 * @param {?function} contentTransformer Optional callback to transform newly 9395 * added content. 9396 */ 9397 function catchup(end, state, contentTransformer) { 9398 if (end < state.g.position) { 9399 // cannot move backwards 9400 return; 9401 } 9402 var source = state.g.source.substring(state.g.position, end); 9403 var transformed = updateIndent(source, state); 9404 if (state.g.sourceMap && transformed) { 9405 // record where we are 9406 state.g.sourceMap.addMapping({ 9407 generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, 9408 original: { line: state.g.sourceLine, column: state.g.sourceColumn }, 9409 source: state.g.sourceMapFilename 9410 }); 9411 9412 // record line breaks in transformed source 9413 var sourceLines = source.split('\n'); 9414 var transformedLines = transformed.split('\n'); 9415 // Add line break mappings between last known mapping and the end of the 9416 // added piece. So for the code piece 9417 // (foo, bar); 9418 // > var x = 2; 9419 // > var b = 3; 9420 // var c = 9421 // only add lines marked with ">": 2, 3. 9422 for (var i = 1; i < sourceLines.length - 1; i++) { 9423 state.g.sourceMap.addMapping({ 9424 generated: { line: state.g.bufferLine, column: 0 }, 9425 original: { line: state.g.sourceLine, column: 0 }, 9426 source: state.g.sourceMapFilename 9427 }); 9428 state.g.sourceLine++; 9429 state.g.bufferLine++; 9430 } 9431 // offset for the last piece 9432 if (sourceLines.length > 1) { 9433 state.g.sourceLine++; 9434 state.g.bufferLine++; 9435 state.g.sourceColumn = 0; 9436 state.g.bufferColumn = 0; 9437 } 9438 state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; 9439 state.g.bufferColumn += 9440 transformedLines[transformedLines.length - 1].length; 9441 } 9442 state.g.buffer += 9443 contentTransformer ? contentTransformer(transformed) : transformed; 9444 state.g.position = end; 9445 } 9446 9447 /** 9448 * Removes all non-whitespace characters 9449 */ 9450 var reNonWhite = /(\S)/g; 9451 function stripNonWhite(value) { 9452 return value.replace(reNonWhite, function() { 9453 return ''; 9454 }); 9455 } 9456 9457 /** 9458 * Catches up as `catchup` but removes all non-whitespace characters. 9459 */ 9460 function catchupWhiteSpace(end, state) { 9461 catchup(end, state, stripNonWhite); 9462 } 9463 9464 /** 9465 * Removes all non-newline characters 9466 */ 9467 var reNonNewline = /[^\n]/g; 9468 function stripNonNewline(value) { 9469 return value.replace(reNonNewline, function() { 9470 return ''; 9471 }); 9472 } 9473 9474 /** 9475 * Catches up as `catchup` but removes all non-newline characters. 9476 * 9477 * Equivalent to appending as many newlines as there are in the original source 9478 * between the current position and `end`. 9479 */ 9480 function catchupNewlines(end, state) { 9481 catchup(end, state, stripNonNewline); 9482 } 9483 9484 9485 /** 9486 * Same as catchup but does not touch the buffer 9487 * 9488 * @param {number} end 9489 * @param {object} state 9490 */ 9491 function move(end, state) { 9492 // move the internal cursors 9493 if (state.g.sourceMap) { 9494 if (end < state.g.position) { 9495 state.g.position = 0; 9496 state.g.sourceLine = 1; 9497 state.g.sourceColumn = 0; 9498 } 9499 9500 var source = state.g.source.substring(state.g.position, end); 9501 var sourceLines = source.split('\n'); 9502 if (sourceLines.length > 1) { 9503 state.g.sourceLine += sourceLines.length - 1; 9504 state.g.sourceColumn = 0; 9505 } 9506 state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; 9507 } 9508 state.g.position = end; 9509 } 9510 9511 /** 9512 * Appends a string of text to the buffer 9513 * 9514 * @param {string} str 9515 * @param {object} state 9516 */ 9517 function append(str, state) { 9518 if (state.g.sourceMap && str) { 9519 state.g.sourceMap.addMapping({ 9520 generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, 9521 original: { line: state.g.sourceLine, column: state.g.sourceColumn }, 9522 source: state.g.sourceMapFilename 9523 }); 9524 var transformedLines = str.split('\n'); 9525 if (transformedLines.length > 1) { 9526 state.g.bufferLine += transformedLines.length - 1; 9527 state.g.bufferColumn = 0; 9528 } 9529 state.g.bufferColumn += 9530 transformedLines[transformedLines.length - 1].length; 9531 } 9532 state.g.buffer += str; 9533 } 9534 9535 /** 9536 * Update indent using state.indentBy property. Indent is measured in 9537 * double spaces. Updates a single line only. 9538 * 9539 * @param {string} str 9540 * @param {object} state 9541 * @return {string} 9542 */ 9543 function updateIndent(str, state) { 9544 for (var i = 0; i < -state.g.indentBy; i++) { 9545 str = str.replace(/(^|\n)( {2}|\t)/g, '$1'); 9546 } 9547 return str; 9548 } 9549 9550 /** 9551 * Calculates indent from the beginning of the line until "start" or the first 9552 * character before start. 9553 * @example 9554 * " foo.bar()" 9555 * ^ 9556 * start 9557 * indent will be 2 9558 * 9559 * @param {number} start 9560 * @param {object} state 9561 * @return {number} 9562 */ 9563 function indentBefore(start, state) { 9564 var end = start; 9565 start = start - 1; 9566 9567 while (start > 0 && state.g.source[start] != '\n') { 9568 if (!state.g.source[start].match(/[ \t]/)) { 9569 end = start; 9570 } 9571 start--; 9572 } 9573 return state.g.source.substring(start + 1, end); 9574 } 9575 9576 function getDocblock(state) { 9577 if (!state.g.docblock) { 9578 var docblock = require('./docblock'); 9579 state.g.docblock = 9580 docblock.parseAsObject(docblock.extract(state.g.source)); 9581 } 9582 return state.g.docblock; 9583 } 9584 9585 function identWithinLexicalScope(identName, state, stopBeforeNode) { 9586 var currScope = state.localScope; 9587 while (currScope) { 9588 if (currScope.identifiers[identName] !== undefined) { 9589 return true; 9590 } 9591 9592 if (stopBeforeNode && currScope.parentNode === stopBeforeNode) { 9593 break; 9594 } 9595 9596 currScope = currScope.parentScope; 9597 } 9598 return false; 9599 } 9600 9601 function identInLocalScope(identName, state) { 9602 return state.localScope.identifiers[identName] !== undefined; 9603 } 9604 9605 function declareIdentInLocalScope(identName, state) { 9606 state.localScope.identifiers[identName] = true; 9607 } 9608 9609 /** 9610 * Apply the given analyzer function to the current node. If the analyzer 9611 * doesn't return false, traverse each child of the current node using the given 9612 * traverser function. 9613 * 9614 * @param {function} analyzer 9615 * @param {function} traverser 9616 * @param {object} node 9617 * @param {function} visitor 9618 * @param {array} path 9619 * @param {object} state 9620 */ 9621 function analyzeAndTraverse(analyzer, traverser, node, path, state) { 9622 var key, child; 9623 9624 if (node.type) { 9625 if (analyzer(node, path, state) === false) { 9626 return; 9627 } 9628 path.unshift(node); 9629 } 9630 9631 for (key in node) { 9632 // skip obviously wrong attributes 9633 if (key === 'range' || key === 'loc') { 9634 continue; 9635 } 9636 if (node.hasOwnProperty(key)) { 9637 child = node[key]; 9638 if (typeof child === 'object' && child !== null) { 9639 traverser(child, path, state); 9640 } 9641 } 9642 } 9643 node.type && path.shift(); 9644 } 9645 9646 /** 9647 * Checks whether a node or any of its sub-nodes contains 9648 * a syntactic construct of the passed type. 9649 * @param {object} node - AST node to test. 9650 * @param {string} type - node type to lookup. 9651 */ 9652 function containsChildOfType(node, type) { 9653 var foundMatchingChild = false; 9654 function nodeTypeAnalyzer(node) { 9655 if (node.type === type) { 9656 foundMatchingChild = true; 9657 return false; 9658 } 9659 } 9660 function nodeTypeTraverser(child, path, state) { 9661 if (!foundMatchingChild) { 9662 foundMatchingChild = containsChildOfType(child, type); 9663 } 9664 } 9665 analyzeAndTraverse( 9666 nodeTypeAnalyzer, 9667 nodeTypeTraverser, 9668 node, 9669 [] 9670 ); 9671 return foundMatchingChild; 9672 } 9673 9674 exports.append = append; 9675 exports.catchup = catchup; 9676 exports.catchupWhiteSpace = catchupWhiteSpace; 9677 exports.catchupNewlines = catchupNewlines; 9678 exports.containsChildOfType = containsChildOfType; 9679 exports.createState = createState; 9680 exports.declareIdentInLocalScope = declareIdentInLocalScope; 9681 exports.getDocblock = getDocblock; 9682 exports.identWithinLexicalScope = identWithinLexicalScope; 9683 exports.identInLocalScope = identInLocalScope; 9684 exports.indentBefore = indentBefore; 9685 exports.move = move; 9686 exports.updateIndent = updateIndent; 9687 exports.updateState = updateState; 9688 exports.analyzeAndTraverse = analyzeAndTraverse; 9689 9690 },{"./docblock":17}],20:[function(require,module,exports){ 9691 /** 9692 * Copyright 2013 Facebook, Inc. 9693 * 9694 * Licensed under the Apache License, Version 2.0 (the "License"); 9695 * you may not use this file except in compliance with the License. 9696 * You may obtain a copy of the License at 9697 * 9698 * http://www.apache.org/licenses/LICENSE-2.0 9699 * 9700 * Unless required by applicable law or agreed to in writing, software 9701 * distributed under the License is distributed on an "AS IS" BASIS, 9702 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9703 * See the License for the specific language governing permissions and 9704 * limitations under the License. 9705 */ 9706 9707 /*jslint node:true*/ 9708 9709 /** 9710 * @typechecks 9711 */ 9712 'use strict'; 9713 9714 var base62 = require('base62'); 9715 var Syntax = require('esprima-fb').Syntax; 9716 var utils = require('../src/utils'); 9717 9718 var SUPER_PROTO_IDENT_PREFIX = '____SuperProtoOf'; 9719 9720 var _anonClassUUIDCounter = 0; 9721 var _mungedSymbolMaps = {}; 9722 9723 /** 9724 * Used to generate a unique class for use with code-gens for anonymous class 9725 * expressions. 9726 * 9727 * @param {object} state 9728 * @return {string} 9729 */ 9730 function _generateAnonymousClassName(state) { 9731 var mungeNamespace = state.mungeNamespace || ''; 9732 return '____Class' + mungeNamespace + base62.encode(_anonClassUUIDCounter++); 9733 } 9734 9735 /** 9736 * Given an identifier name, munge it using the current state's mungeNamespace. 9737 * 9738 * @param {string} identName 9739 * @param {object} state 9740 * @return {string} 9741 */ 9742 function _getMungedName(identName, state) { 9743 var mungeNamespace = state.mungeNamespace; 9744 var shouldMinify = state.g.opts.minify; 9745 9746 if (shouldMinify) { 9747 if (!_mungedSymbolMaps[mungeNamespace]) { 9748 _mungedSymbolMaps[mungeNamespace] = { 9749 symbolMap: {}, 9750 identUUIDCounter: 0 9751 }; 9752 } 9753 9754 var symbolMap = _mungedSymbolMaps[mungeNamespace].symbolMap; 9755 if (!symbolMap[identName]) { 9756 symbolMap[identName] = 9757 base62.encode(_mungedSymbolMaps[mungeNamespace].identUUIDCounter++); 9758 } 9759 identName = symbolMap[identName]; 9760 } 9761 return '$' + mungeNamespace + identName; 9762 } 9763 9764 /** 9765 * Extracts super class information from a class node. 9766 * 9767 * Information includes name of the super class and/or the expression string 9768 * (if extending from an expression) 9769 * 9770 * @param {object} node 9771 * @param {object} state 9772 * @return {object} 9773 */ 9774 function _getSuperClassInfo(node, state) { 9775 var ret = { 9776 name: null, 9777 expression: null 9778 }; 9779 if (node.superClass) { 9780 if (node.superClass.type === Syntax.Identifier) { 9781 ret.name = node.superClass.name; 9782 } else { 9783 // Extension from an expression 9784 ret.name = _generateAnonymousClassName(state); 9785 ret.expression = state.g.source.substring( 9786 node.superClass.range[0], 9787 node.superClass.range[1] 9788 ); 9789 } 9790 } 9791 return ret; 9792 } 9793 9794 /** 9795 * Used with .filter() to find the constructor method in a list of 9796 * MethodDefinition nodes. 9797 * 9798 * @param {object} classElement 9799 * @return {boolean} 9800 */ 9801 function _isConstructorMethod(classElement) { 9802 return classElement.type === Syntax.MethodDefinition && 9803 classElement.key.type === Syntax.Identifier && 9804 classElement.key.name === 'constructor'; 9805 } 9806 9807 /** 9808 * @param {object} node 9809 * @param {object} state 9810 * @return {boolean} 9811 */ 9812 function _shouldMungeIdentifier(node, state) { 9813 return ( 9814 !!state.methodFuncNode && 9815 !utils.getDocblock(state).hasOwnProperty('preventMunge') && 9816 /^_(?!_)/.test(node.name) 9817 ); 9818 } 9819 9820 /** 9821 * @param {function} traverse 9822 * @param {object} node 9823 * @param {array} path 9824 * @param {object} state 9825 */ 9826 function visitClassMethod(traverse, node, path, state) { 9827 utils.catchup(node.range[0], state); 9828 path.unshift(node); 9829 traverse(node.value, path, state); 9830 path.shift(); 9831 return false; 9832 } 9833 visitClassMethod.test = function(node, path, state) { 9834 return node.type === Syntax.MethodDefinition; 9835 }; 9836 9837 /** 9838 * @param {function} traverse 9839 * @param {object} node 9840 * @param {array} path 9841 * @param {object} state 9842 */ 9843 function visitClassFunctionExpression(traverse, node, path, state) { 9844 var methodNode = path[0]; 9845 9846 state = utils.updateState(state, { 9847 methodFuncNode: node 9848 }); 9849 9850 if (methodNode.key.name === 'constructor') { 9851 utils.append('function ' + state.className, state); 9852 } else { 9853 var methodName = methodNode.key.name; 9854 if (_shouldMungeIdentifier(methodNode.key, state)) { 9855 methodName = _getMungedName(methodName, state); 9856 } 9857 9858 var prototypeOrStatic = methodNode.static ? '' : 'prototype.'; 9859 utils.append( 9860 state.className + '.' + prototypeOrStatic + methodName + '=function', 9861 state 9862 ); 9863 } 9864 utils.move(methodNode.key.range[1], state); 9865 9866 var params = node.params; 9867 var paramName; 9868 if (params.length > 0) { 9869 for (var i = 0; i < params.length; i++) { 9870 utils.catchup(node.params[i].range[0], state); 9871 paramName = params[i].name; 9872 if (_shouldMungeIdentifier(params[i], state)) { 9873 paramName = _getMungedName(params[i].name, state); 9874 } 9875 utils.append(paramName, state); 9876 utils.move(params[i].range[1], state); 9877 } 9878 } else { 9879 utils.append('(', state); 9880 } 9881 utils.append(')', state); 9882 utils.catchupWhiteSpace(node.body.range[0], state); 9883 utils.append('{', state); 9884 if (!state.scopeIsStrict) { 9885 utils.append('"use strict";', state); 9886 } 9887 utils.move(node.body.range[0] + '{'.length, state); 9888 9889 path.unshift(node); 9890 traverse(node.body, path, state); 9891 path.shift(); 9892 utils.catchup(node.body.range[1], state); 9893 9894 if (methodNode.key.name !== 'constructor') { 9895 utils.append(';', state); 9896 } 9897 return false; 9898 } 9899 visitClassFunctionExpression.test = function(node, path, state) { 9900 return node.type === Syntax.FunctionExpression 9901 && path[0].type === Syntax.MethodDefinition; 9902 }; 9903 9904 /** 9905 * @param {function} traverse 9906 * @param {object} node 9907 * @param {array} path 9908 * @param {object} state 9909 */ 9910 function _renderClassBody(traverse, node, path, state) { 9911 var className = state.className; 9912 var superClass = state.superClass; 9913 9914 // Set up prototype of constructor on same line as `extends` for line-number 9915 // preservation. This relies on function-hoisting if a constructor function is 9916 // defined in the class body. 9917 if (superClass.name) { 9918 // If the super class is an expression, we need to memoize the output of the 9919 // expression into the generated class name variable and use that to refer 9920 // to the super class going forward. Example: 9921 // 9922 // class Foo extends mixin(Bar, Baz) {} 9923 // --transforms to-- 9924 // function Foo() {} var ____Class0Blah = mixin(Bar, Baz); 9925 if (superClass.expression !== null) { 9926 utils.append( 9927 'var ' + superClass.name + '=' + superClass.expression + ';', 9928 state 9929 ); 9930 } 9931 9932 var keyName = superClass.name + '____Key'; 9933 var keyNameDeclarator = ''; 9934 if (!utils.identWithinLexicalScope(keyName, state)) { 9935 keyNameDeclarator = 'var '; 9936 utils.declareIdentInLocalScope(keyName, state); 9937 } 9938 utils.append( 9939 'for(' + keyNameDeclarator + keyName + ' in ' + superClass.name + '){' + 9940 'if(' + superClass.name + '.hasOwnProperty(' + keyName + ')){' + 9941 className + '[' + keyName + ']=' + 9942 superClass.name + '[' + keyName + '];' + 9943 '}' + 9944 '}', 9945 state 9946 ); 9947 9948 var superProtoIdentStr = SUPER_PROTO_IDENT_PREFIX + superClass.name; 9949 if (!utils.identWithinLexicalScope(superProtoIdentStr, state)) { 9950 utils.append( 9951 'var ' + superProtoIdentStr + '=' + superClass.name + '===null?' + 9952 'null:' + superClass.name + '.prototype;', 9953 state 9954 ); 9955 utils.declareIdentInLocalScope(superProtoIdentStr, state); 9956 } 9957 9958 utils.append( 9959 className + '.prototype=Object.create(' + superProtoIdentStr + ');', 9960 state 9961 ); 9962 utils.append( 9963 className + '.prototype.constructor=' + className + ';', 9964 state 9965 ); 9966 utils.append( 9967 className + '.__superConstructor__=' + superClass.name + ';', 9968 state 9969 ); 9970 } 9971 9972 // If there's no constructor method specified in the class body, create an 9973 // empty constructor function at the top (same line as the class keyword) 9974 if (!node.body.body.filter(_isConstructorMethod).pop()) { 9975 utils.append('function ' + className + '(){', state); 9976 if (!state.scopeIsStrict) { 9977 utils.append('"use strict";', state); 9978 } 9979 if (superClass.name) { 9980 utils.append( 9981 'if(' + superClass.name + '!==null){' + 9982 superClass.name + '.apply(this,arguments);}', 9983 state 9984 ); 9985 } 9986 utils.append('}', state); 9987 } 9988 9989 utils.move(node.body.range[0] + '{'.length, state); 9990 traverse(node.body, path, state); 9991 utils.catchupWhiteSpace(node.range[1], state); 9992 } 9993 9994 /** 9995 * @param {function} traverse 9996 * @param {object} node 9997 * @param {array} path 9998 * @param {object} state 9999 */ 10000 function visitClassDeclaration(traverse, node, path, state) { 10001 var className = node.id.name; 10002 var superClass = _getSuperClassInfo(node, state); 10003 10004 state = utils.updateState(state, { 10005 mungeNamespace: className, 10006 className: className, 10007 superClass: superClass 10008 }); 10009 10010 _renderClassBody(traverse, node, path, state); 10011 10012 return false; 10013 } 10014 visitClassDeclaration.test = function(node, path, state) { 10015 return node.type === Syntax.ClassDeclaration; 10016 }; 10017 10018 /** 10019 * @param {function} traverse 10020 * @param {object} node 10021 * @param {array} path 10022 * @param {object} state 10023 */ 10024 function visitClassExpression(traverse, node, path, state) { 10025 var className = node.id && node.id.name || _generateAnonymousClassName(state); 10026 var superClass = _getSuperClassInfo(node, state); 10027 10028 utils.append('(function(){', state); 10029 10030 state = utils.updateState(state, { 10031 mungeNamespace: className, 10032 className: className, 10033 superClass: superClass 10034 }); 10035 10036 _renderClassBody(traverse, node, path, state); 10037 10038 utils.append('return ' + className + ';})()', state); 10039 return false; 10040 } 10041 visitClassExpression.test = function(node, path, state) { 10042 return node.type === Syntax.ClassExpression; 10043 }; 10044 10045 /** 10046 * @param {function} traverse 10047 * @param {object} node 10048 * @param {array} path 10049 * @param {object} state 10050 */ 10051 function visitPrivateIdentifier(traverse, node, path, state) { 10052 utils.append(_getMungedName(node.name, state), state); 10053 utils.move(node.range[1], state); 10054 } 10055 visitPrivateIdentifier.test = function(node, path, state) { 10056 if (node.type === Syntax.Identifier && _shouldMungeIdentifier(node, state)) { 10057 // Always munge non-computed properties of MemberExpressions 10058 // (a la preventing access of properties of unowned objects) 10059 if (path[0].type === Syntax.MemberExpression && path[0].object !== node 10060 && path[0].computed === false) { 10061 return true; 10062 } 10063 10064 // Always munge identifiers that were declared within the method function 10065 // scope 10066 if (utils.identWithinLexicalScope(node.name, state, state.methodFuncNode)) { 10067 return true; 10068 } 10069 10070 // Always munge private keys on object literals defined within a method's 10071 // scope. 10072 if (path[0].type === Syntax.Property 10073 && path[1].type === Syntax.ObjectExpression) { 10074 return true; 10075 } 10076 10077 // Always munge function parameters 10078 if (path[0].type === Syntax.FunctionExpression 10079 || path[0].type === Syntax.FunctionDeclaration) { 10080 for (var i = 0; i < path[0].params.length; i++) { 10081 if (path[0].params[i] === node) { 10082 return true; 10083 } 10084 } 10085 } 10086 } 10087 return false; 10088 }; 10089 10090 /** 10091 * @param {function} traverse 10092 * @param {object} node 10093 * @param {array} path 10094 * @param {object} state 10095 */ 10096 function visitSuperCallExpression(traverse, node, path, state) { 10097 var superClassName = state.superClass.name; 10098 10099 if (node.callee.type === Syntax.Identifier) { 10100 utils.append(superClassName + '.call(', state); 10101 utils.move(node.callee.range[1], state); 10102 } else if (node.callee.type === Syntax.MemberExpression) { 10103 utils.append(SUPER_PROTO_IDENT_PREFIX + superClassName, state); 10104 utils.move(node.callee.object.range[1], state); 10105 10106 if (node.callee.computed) { 10107 // ["a" + "b"] 10108 utils.catchup(node.callee.property.range[1] + ']'.length, state); 10109 } else { 10110 // .ab 10111 utils.append('.' + node.callee.property.name, state); 10112 } 10113 10114 utils.append('.call(', state); 10115 utils.move(node.callee.range[1], state); 10116 } 10117 10118 utils.append('this', state); 10119 if (node.arguments.length > 0) { 10120 utils.append(',', state); 10121 utils.catchupWhiteSpace(node.arguments[0].range[0], state); 10122 traverse(node.arguments, path, state); 10123 } 10124 10125 utils.catchupWhiteSpace(node.range[1], state); 10126 utils.append(')', state); 10127 return false; 10128 } 10129 visitSuperCallExpression.test = function(node, path, state) { 10130 if (state.superClass && node.type === Syntax.CallExpression) { 10131 var callee = node.callee; 10132 if (callee.type === Syntax.Identifier && callee.name === 'super' 10133 || callee.type == Syntax.MemberExpression 10134 && callee.object.name === 'super') { 10135 return true; 10136 } 10137 } 10138 return false; 10139 }; 10140 10141 /** 10142 * @param {function} traverse 10143 * @param {object} node 10144 * @param {array} path 10145 * @param {object} state 10146 */ 10147 function visitSuperMemberExpression(traverse, node, path, state) { 10148 var superClassName = state.superClass.name; 10149 10150 utils.append(SUPER_PROTO_IDENT_PREFIX + superClassName, state); 10151 utils.move(node.object.range[1], state); 10152 } 10153 visitSuperMemberExpression.test = function(node, path, state) { 10154 return state.superClass 10155 && node.type === Syntax.MemberExpression 10156 && node.object.type === Syntax.Identifier 10157 && node.object.name === 'super'; 10158 }; 10159 10160 exports.visitorList = [ 10161 visitClassDeclaration, 10162 visitClassExpression, 10163 visitClassFunctionExpression, 10164 visitClassMethod, 10165 visitPrivateIdentifier, 10166 visitSuperCallExpression, 10167 visitSuperMemberExpression 10168 ]; 10169 10170 },{"../src/utils":19,"base62":6,"esprima-fb":5}],21:[function(require,module,exports){ 10171 /** 10172 * Copyright 2013 Facebook, Inc. 10173 * 10174 * Licensed under the Apache License, Version 2.0 (the "License"); 10175 * you may not use this file except in compliance with the License. 10176 * You may obtain a copy of the License at 10177 * 10178 * http://www.apache.org/licenses/LICENSE-2.0 10179 * 10180 * Unless required by applicable law or agreed to in writing, software 10181 * distributed under the License is distributed on an "AS IS" BASIS, 10182 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10183 * See the License for the specific language governing permissions and 10184 * limitations under the License. 10185 */ 10186 /* jshint browser: true */ 10187 /* jslint evil: true */ 10188 10189 'use strict'; 10190 var runScripts; 10191 var headEl; 10192 10193 var transform = require('jstransform').transform; 10194 var visitors = require('./fbtransform/visitors').transformVisitors; 10195 var transform = transform.bind(null, visitors.react); 10196 var docblock = require('jstransform/src/docblock'); 10197 10198 10199 exports.transform = transform; 10200 10201 exports.exec = function(code) { 10202 return eval(transform(code).code); 10203 }; 10204 10205 if (typeof window === "undefined" || window === null) { 10206 return; 10207 } 10208 headEl = document.getElementsByTagName('head')[0]; 10209 10210 var run = exports.run = function(code) { 10211 var jsx = docblock.parseAsObject(docblock.extract(code)).jsx; 10212 10213 var functionBody = jsx ? transform(code).code : code; 10214 var scriptEl = document.createElement('script'); 10215 10216 scriptEl.text = functionBody; 10217 headEl.appendChild(scriptEl); 10218 }; 10219 10220 var load = exports.load = function(url, callback) { 10221 var xhr; 10222 xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') 10223 : new XMLHttpRequest(); 10224 10225 // Disable async since we need to execute scripts in the order they are in the 10226 // DOM to mirror normal script loading. 10227 xhr.open('GET', url, false); 10228 if ('overrideMimeType' in xhr) { 10229 xhr.overrideMimeType('text/plain'); 10230 } 10231 xhr.onreadystatechange = function() { 10232 if (xhr.readyState === 4) { 10233 if (xhr.status === 0 || xhr.status === 200) { 10234 run(xhr.responseText); 10235 } else { 10236 throw new Error("Could not load " + url); 10237 } 10238 if (callback) { 10239 return callback(); 10240 } 10241 } 10242 }; 10243 return xhr.send(null); 10244 }; 10245 10246 runScripts = function() { 10247 var scripts = document.getElementsByTagName('script'); 10248 10249 // Array.prototype.slice cannot be used on NodeList on IE8 10250 var jsxScripts = []; 10251 for (var i = 0; i < scripts.length; i++) { 10252 if (scripts.item(i).type === 'text/jsx') { 10253 jsxScripts.push(scripts.item(i)); 10254 } 10255 } 10256 10257 console.warn("You are using the in-browser JSX transformer. Be sure to precompile your JSX for production - http://facebook.github.io/react/docs/tooling-integration.html#jsx"); 10258 10259 jsxScripts.forEach(function(script) { 10260 if (script.src) { 10261 load(script.src); 10262 } else { 10263 run(script.innerHTML); 10264 } 10265 }); 10266 }; 10267 10268 if (window.addEventListener) { 10269 window.addEventListener('DOMContentLoaded', runScripts, false); 10270 } else { 10271 window.attachEvent('onload', runScripts); 10272 } 10273 10274 },{"./fbtransform/visitors":25,"jstransform":18,"jstransform/src/docblock":17}],22:[function(require,module,exports){ 10275 /** 10276 * Copyright 2013 Facebook, Inc. 10277 * 10278 * Licensed under the Apache License, Version 2.0 (the "License"); 10279 * you may not use this file except in compliance with the License. 10280 * You may obtain a copy of the License at 10281 * 10282 * http://www.apache.org/licenses/LICENSE-2.0 10283 * 10284 * Unless required by applicable law or agreed to in writing, software 10285 * distributed under the License is distributed on an "AS IS" BASIS, 10286 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10287 * See the License for the specific language governing permissions and 10288 * limitations under the License. 10289 */ 10290 /*global exports:true*/ 10291 "use strict"; 10292 10293 var Syntax = require('esprima-fb').Syntax; 10294 var utils = require('jstransform/src/utils'); 10295 10296 var FALLBACK_TAGS = require('./xjs').knownTags; 10297 var renderXJSExpressionContainer = 10298 require('./xjs').renderXJSExpressionContainer; 10299 var renderXJSLiteral = require('./xjs').renderXJSLiteral; 10300 var quoteAttrName = require('./xjs').quoteAttrName; 10301 10302 /** 10303 * Customized desugar processor. 10304 * 10305 * Currently: (Somewhat tailored to React) 10306 * <X> </X> => X(null, null) 10307 * <X prop="1" /> => X({prop: '1'}, null) 10308 * <X prop="2"><Y /></X> => X({prop:'2'}, Y(null, null)) 10309 * <X prop="2"><Y /><Z /></X> => X({prop:'2'}, [Y(null, null), Z(null, null)]) 10310 * 10311 * Exceptions to the simple rules above: 10312 * if a property is named "class" it will be changed to "className" in the 10313 * javascript since "class" is not a valid object key in javascript. 10314 */ 10315 10316 var JSX_ATTRIBUTE_TRANSFORMS = { 10317 cxName: function(attr) { 10318 if (attr.value.type !== Syntax.Literal) { 10319 throw new Error("cx only accepts a string literal"); 10320 } else { 10321 var classNames = attr.value.value.split(/\s+/g); 10322 return 'cx(' + classNames.map(JSON.stringify).join(',') + ')'; 10323 } 10324 } 10325 }; 10326 10327 function visitReactTag(traverse, object, path, state) { 10328 var jsxObjIdent = utils.getDocblock(state).jsx; 10329 10330 utils.catchup(object.openingElement.range[0], state); 10331 10332 if (object.name.namespace) { 10333 throw new Error( 10334 'Namespace tags are not supported. ReactJSX is not XML.'); 10335 } 10336 10337 var isFallbackTag = FALLBACK_TAGS[object.name.name]; 10338 utils.append( 10339 (isFallbackTag ? jsxObjIdent + '.' : '') + (object.name.name) + '(', 10340 state 10341 ); 10342 10343 utils.move(object.name.range[1], state); 10344 10345 var childrenToRender = object.children.filter(function(child) { 10346 return !(child.type === Syntax.Literal && !child.value.match(/\S/)); 10347 }); 10348 10349 // if we don't have any attributes, pass in null 10350 if (object.attributes.length === 0) { 10351 utils.append('null', state); 10352 } 10353 10354 // write attributes 10355 object.attributes.forEach(function(attr, index) { 10356 utils.catchup(attr.range[0], state); 10357 if (attr.name.namespace) { 10358 throw new Error( 10359 'Namespace attributes are not supported. ReactJSX is not XML.'); 10360 } 10361 var name = attr.name.name; 10362 var isFirst = index === 0; 10363 var isLast = index === object.attributes.length - 1; 10364 10365 if (isFirst) { 10366 utils.append('{', state); 10367 } 10368 10369 utils.append(quoteAttrName(name), state); 10370 utils.append(':', state); 10371 10372 if (!attr.value) { 10373 state.g.buffer += 'true'; 10374 state.g.position = attr.name.range[1]; 10375 if (!isLast) { 10376 utils.append(',', state); 10377 } 10378 } else { 10379 utils.move(attr.name.range[1], state); 10380 // Use catchupWhiteSpace to skip over the '=' in the attribute 10381 utils.catchupWhiteSpace(attr.value.range[0], state); 10382 if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) { 10383 utils.append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state); 10384 utils.move(attr.value.range[1], state); 10385 if (!isLast) { 10386 utils.append(',', state); 10387 } 10388 } else if (attr.value.type === Syntax.Literal) { 10389 renderXJSLiteral(attr.value, isLast, state); 10390 } else { 10391 renderXJSExpressionContainer(traverse, attr.value, isLast, path, state); 10392 } 10393 } 10394 10395 if (isLast) { 10396 utils.append('}', state); 10397 } 10398 10399 utils.catchup(attr.range[1], state); 10400 }); 10401 10402 if (!object.selfClosing) { 10403 utils.catchup(object.openingElement.range[1] - 1, state); 10404 utils.move(object.openingElement.range[1], state); 10405 } 10406 10407 // filter out whitespace 10408 if (childrenToRender.length > 0) { 10409 utils.append(', ', state); 10410 10411 object.children.forEach(function(child) { 10412 if (child.type === Syntax.Literal && !child.value.match(/\S/)) { 10413 return; 10414 } 10415 utils.catchup(child.range[0], state); 10416 10417 var isLast = child === childrenToRender[childrenToRender.length - 1]; 10418 10419 if (child.type === Syntax.Literal) { 10420 renderXJSLiteral(child, isLast, state); 10421 } else if (child.type === Syntax.XJSExpressionContainer) { 10422 renderXJSExpressionContainer(traverse, child, isLast, path, state); 10423 } else { 10424 traverse(child, path, state); 10425 if (!isLast) { 10426 utils.append(',', state); 10427 state.g.buffer = state.g.buffer.replace(/(\s*),$/, ',$1'); 10428 } 10429 } 10430 10431 utils.catchup(child.range[1], state); 10432 }); 10433 } 10434 10435 if (object.selfClosing) { 10436 // everything up to /> 10437 utils.catchup(object.openingElement.range[1] - 2, state); 10438 utils.move(object.openingElement.range[1], state); 10439 } else { 10440 // everything up to </ sdflksjfd> 10441 utils.catchup(object.closingElement.range[0], state); 10442 utils.move(object.closingElement.range[1], state); 10443 } 10444 10445 utils.append(')', state); 10446 return false; 10447 } 10448 10449 visitReactTag.test = function(object, path, state) { 10450 // only run react when react @jsx namespace is specified in docblock 10451 var jsx = utils.getDocblock(state).jsx; 10452 return object.type === Syntax.XJSElement && jsx && jsx.length; 10453 }; 10454 10455 exports.visitReactTag = visitReactTag; 10456 10457 },{"./xjs":24,"esprima-fb":5,"jstransform/src/utils":19}],23:[function(require,module,exports){ 10458 /** 10459 * Copyright 2013 Facebook, Inc. 10460 * 10461 * Licensed under the Apache License, Version 2.0 (the "License"); 10462 * you may not use this file except in compliance with the License. 10463 * You may obtain a copy of the License at 10464 * 10465 * http://www.apache.org/licenses/LICENSE-2.0 10466 * 10467 * Unless required by applicable law or agreed to in writing, software 10468 * distributed under the License is distributed on an "AS IS" BASIS, 10469 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10470 * See the License for the specific language governing permissions and 10471 * limitations under the License. 10472 */ 10473 /*global exports:true*/ 10474 "use strict"; 10475 10476 var Syntax = require('esprima-fb').Syntax; 10477 var utils = require('jstransform/src/utils'); 10478 10479 /** 10480 * Transforms the following: 10481 * 10482 * var MyComponent = React.createClass({ 10483 * render: ... 10484 * }); 10485 * 10486 * into: 10487 * 10488 * var MyComponent = React.createClass({ 10489 * displayName: 'MyComponent', 10490 * render: ... 10491 * }); 10492 */ 10493 function visitReactDisplayName(traverse, object, path, state) { 10494 if (object.id.type === Syntax.Identifier && 10495 object.init && 10496 object.init.type === Syntax.CallExpression && 10497 object.init.callee.type === Syntax.MemberExpression && 10498 object.init.callee.object.type === Syntax.Identifier && 10499 object.init.callee.object.name === 'React' && 10500 object.init.callee.property.type === Syntax.Identifier && 10501 object.init.callee.property.name === 'createClass' && 10502 object.init['arguments'].length === 1 && 10503 object.init['arguments'][0].type === Syntax.ObjectExpression) { 10504 10505 var displayName = object.id.name; 10506 utils.catchup(object.init['arguments'][0].range[0] + 1, state); 10507 utils.append("displayName: '" + displayName + "',", state); 10508 } 10509 } 10510 10511 /** 10512 * Will only run on @jsx files for now. 10513 */ 10514 visitReactDisplayName.test = function(object, path, state) { 10515 return object.type === Syntax.VariableDeclarator && !!utils.getDocblock(state).jsx; 10516 }; 10517 10518 exports.visitReactDisplayName = visitReactDisplayName; 10519 10520 },{"esprima-fb":5,"jstransform/src/utils":19}],24:[function(require,module,exports){ 10521 /** 10522 * Copyright 2013 Facebook, Inc. 10523 * 10524 * Licensed under the Apache License, Version 2.0 (the "License"); 10525 * you may not use this file except in compliance with the License. 10526 * You may obtain a copy of the License at 10527 * 10528 * http://www.apache.org/licenses/LICENSE-2.0 10529 * 10530 * Unless required by applicable law or agreed to in writing, software 10531 * distributed under the License is distributed on an "AS IS" BASIS, 10532 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10533 * See the License for the specific language governing permissions and 10534 * limitations under the License. 10535 */ 10536 /*global exports:true*/ 10537 "use strict"; 10538 var append = require('jstransform/src/utils').append; 10539 var catchup = require('jstransform/src/utils').catchup; 10540 var move = require('jstransform/src/utils').move; 10541 var Syntax = require('esprima-fb').Syntax; 10542 10543 var knownTags = { 10544 a: true, 10545 abbr: true, 10546 address: true, 10547 applet: true, 10548 area: true, 10549 article: true, 10550 aside: true, 10551 audio: true, 10552 b: true, 10553 base: true, 10554 bdi: true, 10555 bdo: true, 10556 big: true, 10557 blockquote: true, 10558 body: true, 10559 br: true, 10560 button: true, 10561 canvas: true, 10562 caption: true, 10563 circle: true, 10564 cite: true, 10565 code: true, 10566 col: true, 10567 colgroup: true, 10568 command: true, 10569 data: true, 10570 datalist: true, 10571 dd: true, 10572 del: true, 10573 details: true, 10574 dfn: true, 10575 dialog: true, 10576 div: true, 10577 dl: true, 10578 dt: true, 10579 ellipse: true, 10580 em: true, 10581 embed: true, 10582 fieldset: true, 10583 figcaption: true, 10584 figure: true, 10585 footer: true, 10586 form: true, 10587 g: true, 10588 h1: true, 10589 h2: true, 10590 h3: true, 10591 h4: true, 10592 h5: true, 10593 h6: true, 10594 head: true, 10595 header: true, 10596 hgroup: true, 10597 hr: true, 10598 html: true, 10599 i: true, 10600 iframe: true, 10601 img: true, 10602 input: true, 10603 ins: true, 10604 kbd: true, 10605 keygen: true, 10606 label: true, 10607 legend: true, 10608 li: true, 10609 line: true, 10610 link: true, 10611 main: true, 10612 map: true, 10613 mark: true, 10614 marquee: true, 10615 menu: true, 10616 menuitem: true, 10617 meta: true, 10618 meter: true, 10619 nav: true, 10620 noscript: true, 10621 object: true, 10622 ol: true, 10623 optgroup: true, 10624 option: true, 10625 output: true, 10626 p: true, 10627 param: true, 10628 path: true, 10629 polyline: true, 10630 pre: true, 10631 progress: true, 10632 q: true, 10633 rect: true, 10634 rp: true, 10635 rt: true, 10636 ruby: true, 10637 s: true, 10638 samp: true, 10639 script: true, 10640 section: true, 10641 select: true, 10642 small: true, 10643 source: true, 10644 span: true, 10645 strong: true, 10646 style: true, 10647 sub: true, 10648 summary: true, 10649 sup: true, 10650 svg: true, 10651 table: true, 10652 tbody: true, 10653 td: true, 10654 text: true, 10655 textarea: true, 10656 tfoot: true, 10657 th: true, 10658 thead: true, 10659 time: true, 10660 title: true, 10661 tr: true, 10662 track: true, 10663 u: true, 10664 ul: true, 10665 'var': true, 10666 video: true, 10667 wbr: true 10668 }; 10669 10670 function safeTrim(string) { 10671 return string.replace(/^[ \t]+/, '').replace(/[ \t]+$/, ''); 10672 } 10673 10674 // Replace all trailing whitespace characters with a single space character 10675 function trimWithSingleSpace(string) { 10676 return string.replace(/^[ \t\xA0]{2,}/, ' '). 10677 replace(/[ \t\xA0]{2,}$/, ' ').replace(/^\s+$/, ''); 10678 } 10679 10680 /** 10681 * Special handling for multiline string literals 10682 * print lines: 10683 * 10684 * line 10685 * line 10686 * 10687 * as: 10688 * 10689 * "line "+ 10690 * "line" 10691 */ 10692 function renderXJSLiteral(object, isLast, state, start, end) { 10693 /** Added blank check filtering and triming*/ 10694 var trimmedChildValue = safeTrim(object.value); 10695 var hasFinalNewLine = false; 10696 10697 if (trimmedChildValue) { 10698 // head whitespace 10699 append(object.value.match(/^[\t ]*/)[0], state); 10700 if (start) { 10701 append(start, state); 10702 } 10703 10704 var trimmedChildValueWithSpace = trimWithSingleSpace(object.value); 10705 10706 /** 10707 */ 10708 var initialLines = trimmedChildValue.split(/\r\n|\n|\r/); 10709 10710 var lines = initialLines.filter(function(line) { 10711 return safeTrim(line).length > 0; 10712 }); 10713 10714 var hasInitialNewLine = initialLines[0] !== lines[0]; 10715 hasFinalNewLine = 10716 initialLines[initialLines.length - 1] !== lines[lines.length - 1]; 10717 10718 var numLines = lines.length; 10719 lines.forEach(function (line, ii) { 10720 var lastLine = ii === numLines - 1; 10721 var trimmedLine = safeTrim(line); 10722 if (trimmedLine === '' && !lastLine) { 10723 append(line, state); 10724 } else { 10725 var preString = ''; 10726 var postString = ''; 10727 var leading = line.match(/^[ \t]*/)[0]; 10728 10729 if (ii === 0) { 10730 if (hasInitialNewLine) { 10731 preString = ' '; 10732 leading = '\n' + leading; 10733 } 10734 if (trimmedChildValueWithSpace.substring(0, 1) === ' ') { 10735 // If this is the first line, and the original content starts with 10736 // whitespace, place a single space at the beginning. 10737 preString = ' '; 10738 } 10739 } 10740 if (!lastLine || trimmedChildValueWithSpace.substr( 10741 trimmedChildValueWithSpace.length - 1, 1) === ' ' || 10742 hasFinalNewLine 10743 ) { 10744 // If either not on the last line, or the original content ends with 10745 // whitespace, place a single character at the end. 10746 postString = ' '; 10747 } 10748 10749 append( 10750 leading + 10751 JSON.stringify( 10752 preString + trimmedLine + postString 10753 ) + 10754 (lastLine ? '' : '+') + 10755 line.match(/[ \t]*$/)[0], 10756 state); 10757 } 10758 if (!lastLine) { 10759 append('\n', state); 10760 } 10761 }); 10762 } else { 10763 if (start) { 10764 append(start, state); 10765 } 10766 append('""', state); 10767 } 10768 if (end) { 10769 append(end, state); 10770 } 10771 10772 // add comma before trailing whitespace 10773 if (!isLast) { 10774 append(',', state); 10775 } 10776 10777 // tail whitespace 10778 if (hasFinalNewLine) { 10779 append('\n', state); 10780 } 10781 append(object.value.match(/[ \t]*$/)[0], state); 10782 move(object.range[1], state); 10783 } 10784 10785 function renderXJSExpressionContainer(traverse, object, isLast, path, state) { 10786 // Plus 1 to skip `{`. 10787 move(object.range[0] + 1, state); 10788 traverse(object.expression, path, state); 10789 if (!isLast && object.expression.type !== Syntax.XJSEmptyExpression) { 10790 // If we need to append a comma, make sure to do so after the expression. 10791 catchup(object.expression.range[1], state); 10792 append(',', state); 10793 } 10794 10795 // Minus 1 to skip `}`. 10796 catchup(object.range[1] - 1, state); 10797 move(object.range[1], state); 10798 return false; 10799 } 10800 10801 function quoteAttrName(attr) { 10802 // Quote invalid JS identifiers. 10803 if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { 10804 return "'" + attr + "'"; 10805 } 10806 return attr; 10807 } 10808 10809 exports.knownTags = knownTags; 10810 exports.renderXJSExpressionContainer = renderXJSExpressionContainer; 10811 exports.renderXJSLiteral = renderXJSLiteral; 10812 exports.quoteAttrName = quoteAttrName; 10813 10814 },{"esprima-fb":5,"jstransform/src/utils":19}],25:[function(require,module,exports){ 10815 /*global exports:true*/ 10816 var es6Classes = require('jstransform/visitors/es6-class-visitors').visitorList; 10817 var react = require('./transforms/react'); 10818 var reactDisplayName = require('./transforms/reactDisplayName'); 10819 10820 /** 10821 * Map from transformName => orderedListOfVisitors. 10822 */ 10823 var transformVisitors = { 10824 'es6-classes': es6Classes, 10825 'react': [ 10826 react.visitReactTag, 10827 reactDisplayName.visitReactDisplayName 10828 ] 10829 }; 10830 10831 /** 10832 * Specifies the order in which each transform should run. 10833 */ 10834 var transformRunOrder = [ 10835 'es6-classes', 10836 'react' 10837 ]; 10838 10839 /** 10840 * Given a list of transform names, return the ordered list of visitors to be 10841 * passed to the transform() function. 10842 * 10843 * @param {array?} excludes 10844 * @return {array} 10845 */ 10846 function getVisitorsList(excludes) { 10847 var ret = []; 10848 for (var i = 0, il = transformRunOrder.length; i < il; i++) { 10849 if (!excludes || excludes.indexOf(transformRunOrder[i]) === -1) { 10850 ret = ret.concat(transformVisitors[transformRunOrder[i]]); 10851 } 10852 } 10853 return ret; 10854 } 10855 10856 exports.getVisitorsList = getVisitorsList; 10857 exports.transformVisitors = transformVisitors; 10858 10859 },{"./transforms/react":22,"./transforms/reactDisplayName":23,"jstransform/visitors/es6-class-visitors":20}]},{},[21]) 10860 (21) 10861 }); 10862 ;