UNPKG

205 kBJavaScriptView Raw
1/*! blanket - v1.2.1 */
2
3if (typeof QUnit !== 'undefined'){ QUnit.config.autostart = false; }
4(function(define){
5(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.acorn = f()}})(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);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.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(_dereq_,module,exports){
6
7
8// The main exported interface (under `self.acorn` when in the
9// browser) is a `parse` function that takes a code string and
10// returns an abstract syntax tree as specified by [Mozilla parser
11// API][api].
12//
13// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
14
15"use strict";
16
17exports.parse = parse;
18
19// This function tries to parse a single expression at a given
20// offset in a string. Useful for parsing mixed-language formats
21// that embed JavaScript expressions.
22
23exports.parseExpressionAt = parseExpressionAt;
24
25// Acorn is organized as a tokenizer and a recursive-descent parser.
26// The `tokenize` export provides an interface to the tokenizer.
27
28exports.tokenizer = tokenizer;
29exports.__esModule = true;
30// Acorn is a tiny, fast JavaScript parser written in JavaScript.
31//
32// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
33// various contributors and released under an MIT license.
34//
35// Git repositories for Acorn are available at
36//
37// http://marijnhaverbeke.nl/git/acorn
38// https://github.com/marijnh/acorn.git
39//
40// Please use the [github bug tracker][ghbt] to report issues.
41//
42// [ghbt]: https://github.com/marijnh/acorn/issues
43//
44// This file defines the main parser interface. The library also comes
45// with a [error-tolerant parser][dammit] and an
46// [abstract syntax tree walker][walk], defined in other files.
47//
48// [dammit]: acorn_loose.js
49// [walk]: util/walk.js
50
51var _state = _dereq_("./state");
52
53var Parser = _state.Parser;
54
55var _options = _dereq_("./options");
56
57var getOptions = _options.getOptions;
58
59_dereq_("./parseutil");
60
61_dereq_("./statement");
62
63_dereq_("./lval");
64
65_dereq_("./expression");
66
67exports.Parser = _state.Parser;
68exports.plugins = _state.plugins;
69exports.defaultOptions = _options.defaultOptions;
70
71var _location = _dereq_("./location");
72
73exports.SourceLocation = _location.SourceLocation;
74exports.getLineInfo = _location.getLineInfo;
75exports.Node = _dereq_("./node").Node;
76
77var _tokentype = _dereq_("./tokentype");
78
79exports.TokenType = _tokentype.TokenType;
80exports.tokTypes = _tokentype.types;
81
82var _tokencontext = _dereq_("./tokencontext");
83
84exports.TokContext = _tokencontext.TokContext;
85exports.tokContexts = _tokencontext.types;
86
87var _identifier = _dereq_("./identifier");
88
89exports.isIdentifierChar = _identifier.isIdentifierChar;
90exports.isIdentifierStart = _identifier.isIdentifierStart;
91exports.Token = _dereq_("./tokenize").Token;
92
93var _whitespace = _dereq_("./whitespace");
94
95exports.isNewLine = _whitespace.isNewLine;
96exports.lineBreak = _whitespace.lineBreak;
97exports.lineBreakG = _whitespace.lineBreakG;
98var version = "1.2.2";exports.version = version;
99
100function parse(input, options) {
101 var p = parser(options, input);
102 var startPos = p.pos,
103 startLoc = p.options.locations && p.curPosition();
104 p.nextToken();
105 return p.parseTopLevel(p.options.program || p.startNodeAt(startPos, startLoc));
106}
107
108function parseExpressionAt(input, pos, options) {
109 var p = parser(options, input, pos);
110 p.nextToken();
111 return p.parseExpression();
112}
113
114function tokenizer(input, options) {
115 return parser(options, input);
116}
117
118function parser(options, input) {
119 return new Parser(getOptions(options), String(input));
120}
121
122},{"./expression":6,"./identifier":7,"./location":8,"./lval":9,"./node":10,"./options":11,"./parseutil":12,"./state":13,"./statement":14,"./tokencontext":15,"./tokenize":16,"./tokentype":17,"./whitespace":19}],2:[function(_dereq_,module,exports){
123if (typeof Object.create === 'function') {
124 // implementation from standard node.js 'util' module
125 module.exports = function inherits(ctor, superCtor) {
126 ctor.super_ = superCtor
127 ctor.prototype = Object.create(superCtor.prototype, {
128 constructor: {
129 value: ctor,
130 enumerable: false,
131 writable: true,
132 configurable: true
133 }
134 });
135 };
136} else {
137 // old school shim for old browsers
138 module.exports = function inherits(ctor, superCtor) {
139 ctor.super_ = superCtor
140 var TempCtor = function () {}
141 TempCtor.prototype = superCtor.prototype
142 ctor.prototype = new TempCtor()
143 ctor.prototype.constructor = ctor
144 }
145}
146
147},{}],3:[function(_dereq_,module,exports){
148// shim for using process in browser
149
150var process = module.exports = {};
151var queue = [];
152var draining = false;
153
154function drainQueue() {
155 if (draining) {
156 return;
157 }
158 draining = true;
159 var currentQueue;
160 var len = queue.length;
161 while(len) {
162 currentQueue = queue;
163 queue = [];
164 var i = -1;
165 while (++i < len) {
166 currentQueue[i]();
167 }
168 len = queue.length;
169 }
170 draining = false;
171}
172process.nextTick = function (fun) {
173 queue.push(fun);
174 if (!draining) {
175 setTimeout(drainQueue, 0);
176 }
177};
178
179process.title = 'browser';
180process.browser = true;
181process.env = {};
182process.argv = [];
183process.version = ''; // empty string to avoid regexp issues
184process.versions = {};
185
186function noop() {}
187
188process.on = noop;
189process.addListener = noop;
190process.once = noop;
191process.off = noop;
192process.removeListener = noop;
193process.removeAllListeners = noop;
194process.emit = noop;
195
196process.binding = function (name) {
197 throw new Error('process.binding is not supported');
198};
199
200// TODO(shtylman)
201process.cwd = function () { return '/' };
202process.chdir = function (dir) {
203 throw new Error('process.chdir is not supported');
204};
205process.umask = function() { return 0; };
206
207},{}],4:[function(_dereq_,module,exports){
208module.exports = function isBuffer(arg) {
209 return arg && typeof arg === 'object'
210 && typeof arg.copy === 'function'
211 && typeof arg.fill === 'function'
212 && typeof arg.readUInt8 === 'function';
213}
214},{}],5:[function(_dereq_,module,exports){
215(function (process,global){
216// Copyright Joyent, Inc. and other Node contributors.
217//
218// Permission is hereby granted, free of charge, to any person obtaining a
219// copy of this software and associated documentation files (the
220// "Software"), to deal in the Software without restriction, including
221// without limitation the rights to use, copy, modify, merge, publish,
222// distribute, sublicense, and/or sell copies of the Software, and to permit
223// persons to whom the Software is furnished to do so, subject to the
224// following conditions:
225//
226// The above copyright notice and this permission notice shall be included
227// in all copies or substantial portions of the Software.
228//
229// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
230// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
231// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
232// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
233// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
234// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
235// USE OR OTHER DEALINGS IN THE SOFTWARE.
236
237var formatRegExp = /%[sdj%]/g;
238exports.format = function(f) {
239 if (!isString(f)) {
240 var objects = [];
241 for (var i = 0; i < arguments.length; i++) {
242 objects.push(inspect(arguments[i]));
243 }
244 return objects.join(' ');
245 }
246
247 var i = 1;
248 var args = arguments;
249 var len = args.length;
250 var str = String(f).replace(formatRegExp, function(x) {
251 if (x === '%%') return '%';
252 if (i >= len) return x;
253 switch (x) {
254 case '%s': return String(args[i++]);
255 case '%d': return Number(args[i++]);
256 case '%j':
257 try {
258 return JSON.stringify(args[i++]);
259 } catch (_) {
260 return '[Circular]';
261 }
262 default:
263 return x;
264 }
265 });
266 for (var x = args[i]; i < len; x = args[++i]) {
267 if (isNull(x) || !isObject(x)) {
268 str += ' ' + x;
269 } else {
270 str += ' ' + inspect(x);
271 }
272 }
273 return str;
274};
275
276
277// Mark that a method should not be used.
278// Returns a modified function which warns once by default.
279// If --no-deprecation is set, then it is a no-op.
280exports.deprecate = function(fn, msg) {
281 // Allow for deprecating things in the process of starting up.
282 if (isUndefined(global.process)) {
283 return function() {
284 return exports.deprecate(fn, msg).apply(this, arguments);
285 };
286 }
287
288 if (process.noDeprecation === true) {
289 return fn;
290 }
291
292 var warned = false;
293 function deprecated() {
294 if (!warned) {
295 if (process.throwDeprecation) {
296 throw new Error(msg);
297 } else if (process.traceDeprecation) {
298 console.trace(msg);
299 } else {
300 console.error(msg);
301 }
302 warned = true;
303 }
304 return fn.apply(this, arguments);
305 }
306
307 return deprecated;
308};
309
310
311var debugs = {};
312var debugEnviron;
313exports.debuglog = function(set) {
314 if (isUndefined(debugEnviron))
315 debugEnviron = process.env.NODE_DEBUG || '';
316 set = set.toUpperCase();
317 if (!debugs[set]) {
318 if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
319 var pid = process.pid;
320 debugs[set] = function() {
321 var msg = exports.format.apply(exports, arguments);
322 console.error('%s %d: %s', set, pid, msg);
323 };
324 } else {
325 debugs[set] = function() {};
326 }
327 }
328 return debugs[set];
329};
330
331
332/**
333 * Echos the value of a value. Trys to print the value out
334 * in the best way possible given the different types.
335 *
336 * @param {Object} obj The object to print out.
337 * @param {Object} opts Optional options object that alters the output.
338 */
339/* legacy: obj, showHidden, depth, colors*/
340function inspect(obj, opts) {
341 // default options
342 var ctx = {
343 seen: [],
344 stylize: stylizeNoColor
345 };
346 // legacy...
347 if (arguments.length >= 3) ctx.depth = arguments[2];
348 if (arguments.length >= 4) ctx.colors = arguments[3];
349 if (isBoolean(opts)) {
350 // legacy...
351 ctx.showHidden = opts;
352 } else if (opts) {
353 // got an "options" object
354 exports._extend(ctx, opts);
355 }
356 // set default options
357 if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
358 if (isUndefined(ctx.depth)) ctx.depth = 2;
359 if (isUndefined(ctx.colors)) ctx.colors = false;
360 if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
361 if (ctx.colors) ctx.stylize = stylizeWithColor;
362 return formatValue(ctx, obj, ctx.depth);
363}
364exports.inspect = inspect;
365
366
367// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
368inspect.colors = {
369 'bold' : [1, 22],
370 'italic' : [3, 23],
371 'underline' : [4, 24],
372 'inverse' : [7, 27],
373 'white' : [37, 39],
374 'grey' : [90, 39],
375 'black' : [30, 39],
376 'blue' : [34, 39],
377 'cyan' : [36, 39],
378 'green' : [32, 39],
379 'magenta' : [35, 39],
380 'red' : [31, 39],
381 'yellow' : [33, 39]
382};
383
384// Don't use 'blue' not visible on cmd.exe
385inspect.styles = {
386 'special': 'cyan',
387 'number': 'yellow',
388 'boolean': 'yellow',
389 'undefined': 'grey',
390 'null': 'bold',
391 'string': 'green',
392 'date': 'magenta',
393 // "name": intentionally not styling
394 'regexp': 'red'
395};
396
397
398function stylizeWithColor(str, styleType) {
399 var style = inspect.styles[styleType];
400
401 if (style) {
402 return '\u001b[' + inspect.colors[style][0] + 'm' + str +
403 '\u001b[' + inspect.colors[style][1] + 'm';
404 } else {
405 return str;
406 }
407}
408
409
410function stylizeNoColor(str, styleType) {
411 return str;
412}
413
414
415function arrayToHash(array) {
416 var hash = {};
417
418 array.forEach(function(val, idx) {
419 hash[val] = true;
420 });
421
422 return hash;
423}
424
425
426function formatValue(ctx, value, recurseTimes) {
427 // Provide a hook for user-specified inspect functions.
428 // Check that value is an object with an inspect function on it
429 if (ctx.customInspect &&
430 value &&
431 isFunction(value.inspect) &&
432 // Filter out the util module, it's inspect function is special
433 value.inspect !== exports.inspect &&
434 // Also filter out any prototype objects using the circular check.
435 !(value.constructor && value.constructor.prototype === value)) {
436 var ret = value.inspect(recurseTimes, ctx);
437 if (!isString(ret)) {
438 ret = formatValue(ctx, ret, recurseTimes);
439 }
440 return ret;
441 }
442
443 // Primitive types cannot have properties
444 var primitive = formatPrimitive(ctx, value);
445 if (primitive) {
446 return primitive;
447 }
448
449 // Look up the keys of the object.
450 var keys = Object.keys(value);
451 var visibleKeys = arrayToHash(keys);
452
453 if (ctx.showHidden) {
454 keys = Object.getOwnPropertyNames(value);
455 }
456
457 // IE doesn't make error fields non-enumerable
458 // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
459 if (isError(value)
460 && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
461 return formatError(value);
462 }
463
464 // Some type of object without properties can be shortcutted.
465 if (keys.length === 0) {
466 if (isFunction(value)) {
467 var name = value.name ? ': ' + value.name : '';
468 return ctx.stylize('[Function' + name + ']', 'special');
469 }
470 if (isRegExp(value)) {
471 return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
472 }
473 if (isDate(value)) {
474 return ctx.stylize(Date.prototype.toString.call(value), 'date');
475 }
476 if (isError(value)) {
477 return formatError(value);
478 }
479 }
480
481 var base = '', array = false, braces = ['{', '}'];
482
483 // Make Array say that they are Array
484 if (isArray(value)) {
485 array = true;
486 braces = ['[', ']'];
487 }
488
489 // Make functions say that they are functions
490 if (isFunction(value)) {
491 var n = value.name ? ': ' + value.name : '';
492 base = ' [Function' + n + ']';
493 }
494
495 // Make RegExps say that they are RegExps
496 if (isRegExp(value)) {
497 base = ' ' + RegExp.prototype.toString.call(value);
498 }
499
500 // Make dates with properties first say the date
501 if (isDate(value)) {
502 base = ' ' + Date.prototype.toUTCString.call(value);
503 }
504
505 // Make error with message first say the error
506 if (isError(value)) {
507 base = ' ' + formatError(value);
508 }
509
510 if (keys.length === 0 && (!array || value.length == 0)) {
511 return braces[0] + base + braces[1];
512 }
513
514 if (recurseTimes < 0) {
515 if (isRegExp(value)) {
516 return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
517 } else {
518 return ctx.stylize('[Object]', 'special');
519 }
520 }
521
522 ctx.seen.push(value);
523
524 var output;
525 if (array) {
526 output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
527 } else {
528 output = keys.map(function(key) {
529 return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
530 });
531 }
532
533 ctx.seen.pop();
534
535 return reduceToSingleString(output, base, braces);
536}
537
538
539function formatPrimitive(ctx, value) {
540 if (isUndefined(value))
541 return ctx.stylize('undefined', 'undefined');
542 if (isString(value)) {
543 var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
544 .replace(/'/g, "\\'")
545 .replace(/\\"/g, '"') + '\'';
546 return ctx.stylize(simple, 'string');
547 }
548 if (isNumber(value))
549 return ctx.stylize('' + value, 'number');
550 if (isBoolean(value))
551 return ctx.stylize('' + value, 'boolean');
552 // For some reason typeof null is "object", so special case here.
553 if (isNull(value))
554 return ctx.stylize('null', 'null');
555}
556
557
558function formatError(value) {
559 return '[' + Error.prototype.toString.call(value) + ']';
560}
561
562
563function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
564 var output = [];
565 for (var i = 0, l = value.length; i < l; ++i) {
566 if (hasOwnProperty(value, String(i))) {
567 output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
568 String(i), true));
569 } else {
570 output.push('');
571 }
572 }
573 keys.forEach(function(key) {
574 if (!key.match(/^\d+$/)) {
575 output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
576 key, true));
577 }
578 });
579 return output;
580}
581
582
583function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
584 var name, str, desc;
585 desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
586 if (desc.get) {
587 if (desc.set) {
588 str = ctx.stylize('[Getter/Setter]', 'special');
589 } else {
590 str = ctx.stylize('[Getter]', 'special');
591 }
592 } else {
593 if (desc.set) {
594 str = ctx.stylize('[Setter]', 'special');
595 }
596 }
597 if (!hasOwnProperty(visibleKeys, key)) {
598 name = '[' + key + ']';
599 }
600 if (!str) {
601 if (ctx.seen.indexOf(desc.value) < 0) {
602 if (isNull(recurseTimes)) {
603 str = formatValue(ctx, desc.value, null);
604 } else {
605 str = formatValue(ctx, desc.value, recurseTimes - 1);
606 }
607 if (str.indexOf('\n') > -1) {
608 if (array) {
609 str = str.split('\n').map(function(line) {
610 return ' ' + line;
611 }).join('\n').substr(2);
612 } else {
613 str = '\n' + str.split('\n').map(function(line) {
614 return ' ' + line;
615 }).join('\n');
616 }
617 }
618 } else {
619 str = ctx.stylize('[Circular]', 'special');
620 }
621 }
622 if (isUndefined(name)) {
623 if (array && key.match(/^\d+$/)) {
624 return str;
625 }
626 name = JSON.stringify('' + key);
627 if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
628 name = name.substr(1, name.length - 2);
629 name = ctx.stylize(name, 'name');
630 } else {
631 name = name.replace(/'/g, "\\'")
632 .replace(/\\"/g, '"')
633 .replace(/(^"|"$)/g, "'");
634 name = ctx.stylize(name, 'string');
635 }
636 }
637
638 return name + ': ' + str;
639}
640
641
642function reduceToSingleString(output, base, braces) {
643 var numLinesEst = 0;
644 var length = output.reduce(function(prev, cur) {
645 numLinesEst++;
646 if (cur.indexOf('\n') >= 0) numLinesEst++;
647 return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
648 }, 0);
649
650 if (length > 60) {
651 return braces[0] +
652 (base === '' ? '' : base + '\n ') +
653 ' ' +
654 output.join(',\n ') +
655 ' ' +
656 braces[1];
657 }
658
659 return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
660}
661
662
663// NOTE: These type checking functions intentionally don't use `instanceof`
664// because it is fragile and can be easily faked with `Object.create()`.
665function isArray(ar) {
666 return Array.isArray(ar);
667}
668exports.isArray = isArray;
669
670function isBoolean(arg) {
671 return typeof arg === 'boolean';
672}
673exports.isBoolean = isBoolean;
674
675function isNull(arg) {
676 return arg === null;
677}
678exports.isNull = isNull;
679
680function isNullOrUndefined(arg) {
681 return arg == null;
682}
683exports.isNullOrUndefined = isNullOrUndefined;
684
685function isNumber(arg) {
686 return typeof arg === 'number';
687}
688exports.isNumber = isNumber;
689
690function isString(arg) {
691 return typeof arg === 'string';
692}
693exports.isString = isString;
694
695function isSymbol(arg) {
696 return typeof arg === 'symbol';
697}
698exports.isSymbol = isSymbol;
699
700function isUndefined(arg) {
701 return arg === void 0;
702}
703exports.isUndefined = isUndefined;
704
705function isRegExp(re) {
706 return isObject(re) && objectToString(re) === '[object RegExp]';
707}
708exports.isRegExp = isRegExp;
709
710function isObject(arg) {
711 return typeof arg === 'object' && arg !== null;
712}
713exports.isObject = isObject;
714
715function isDate(d) {
716 return isObject(d) && objectToString(d) === '[object Date]';
717}
718exports.isDate = isDate;
719
720function isError(e) {
721 return isObject(e) &&
722 (objectToString(e) === '[object Error]' || e instanceof Error);
723}
724exports.isError = isError;
725
726function isFunction(arg) {
727 return typeof arg === 'function';
728}
729exports.isFunction = isFunction;
730
731function isPrimitive(arg) {
732 return arg === null ||
733 typeof arg === 'boolean' ||
734 typeof arg === 'number' ||
735 typeof arg === 'string' ||
736 typeof arg === 'symbol' || // ES6 symbol
737 typeof arg === 'undefined';
738}
739exports.isPrimitive = isPrimitive;
740
741exports.isBuffer = _dereq_('./support/isBuffer');
742
743function objectToString(o) {
744 return Object.prototype.toString.call(o);
745}
746
747
748function pad(n) {
749 return n < 10 ? '0' + n.toString(10) : n.toString(10);
750}
751
752
753var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
754 'Oct', 'Nov', 'Dec'];
755
756// 26 Feb 16:19:34
757function timestamp() {
758 var d = new Date();
759 var time = [pad(d.getHours()),
760 pad(d.getMinutes()),
761 pad(d.getSeconds())].join(':');
762 return [d.getDate(), months[d.getMonth()], time].join(' ');
763}
764
765
766// log is just a thin wrapper to console.log that prepends a timestamp
767exports.log = function() {
768 console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
769};
770
771
772/**
773 * Inherit the prototype methods from one constructor into another.
774 *
775 * The Function.prototype.inherits from lang.js rewritten as a standalone
776 * function (not on Function.prototype). NOTE: If this file is to be loaded
777 * during bootstrapping this function needs to be rewritten using some native
778 * functions as prototype setup using normal JavaScript does not work as
779 * expected during bootstrapping (see mirror.js in r114903).
780 *
781 * @param {function} ctor Constructor function which needs to inherit the
782 * prototype.
783 * @param {function} superCtor Constructor function to inherit prototype from.
784 */
785exports.inherits = _dereq_('inherits');
786
787exports._extend = function(origin, add) {
788 // Don't do anything if add isn't an object
789 if (!add || !isObject(add)) return origin;
790
791 var keys = Object.keys(add);
792 var i = keys.length;
793 while (i--) {
794 origin[keys[i]] = add[keys[i]];
795 }
796 return origin;
797};
798
799function hasOwnProperty(obj, prop) {
800 return Object.prototype.hasOwnProperty.call(obj, prop);
801}
802
803}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
804},{"./support/isBuffer":4,"_process":3,"inherits":2}],6:[function(_dereq_,module,exports){
805// A recursive descent parser operates by defining functions for all
806// syntactic elements, and recursively calling those, each function
807// advancing the input stream and returning an AST node. Precedence
808// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
809// instead of `(!x)[1]` is handled by the fact that the parser
810// function that parses unary prefix operators is called first, and
811// in turn calls the function that parses `[]` subscripts — that
812// way, it'll receive the node for `x[1]` already parsed, and wraps
813// *that* in the unary operator node.
814//
815// Acorn uses an [operator precedence parser][opp] to handle binary
816// operator precedence, because it is much more compact than using
817// the technique outlined above, which uses different, nesting
818// functions to specify precedence, for all of the ten binary
819// precedence levels that JavaScript defines.
820//
821// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
822
823"use strict";
824
825var tt = _dereq_("./tokentype").types;
826
827var Parser = _dereq_("./state").Parser;
828
829var reservedWords = _dereq_("./identifier").reservedWords;
830
831var has = _dereq_("./util").has;
832
833var pp = Parser.prototype;
834
835// Check if property name clashes with already added.
836// Object/class getters and setters are not allowed to clash —
837// either with each other or with an init property — and in
838// strict mode, init properties are also not allowed to be repeated.
839
840pp.checkPropClash = function (prop, propHash) {
841 if (this.options.ecmaVersion >= 6) return;
842 var key = prop.key,
843 name = undefined;
844 switch (key.type) {
845 case "Identifier":
846 name = key.name;break;
847 case "Literal":
848 name = String(key.value);break;
849 default:
850 return;
851 }
852 var kind = prop.kind || "init",
853 other = undefined;
854 if (has(propHash, name)) {
855 other = propHash[name];
856 var isGetSet = kind !== "init";
857 if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) this.raise(key.start, "Redefinition of property");
858 } else {
859 other = propHash[name] = {
860 init: false,
861 get: false,
862 set: false
863 };
864 }
865 other[kind] = true;
866};
867
868// ### Expression parsing
869
870// These nest, from the most general expression type at the top to
871// 'atomic', nondivisible expression types at the bottom. Most of
872// the functions will simply let the function(s) below them parse,
873// and, *if* the syntactic construct they handle is present, wrap
874// the AST node that the inner parser gave them in another node.
875
876// Parse a full expression. The optional arguments are used to
877// forbid the `in` operator (in for loops initalization expressions)
878// and provide reference for storing '=' operator inside shorthand
879// property assignment in contexts where both object expression
880// and object pattern might appear (so it's possible to raise
881// delayed syntax error at correct position).
882
883pp.parseExpression = function (noIn, refShorthandDefaultPos) {
884 var startPos = this.start,
885 startLoc = this.startLoc;
886 var expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos);
887 if (this.type === tt.comma) {
888 var node = this.startNodeAt(startPos, startLoc);
889 node.expressions = [expr];
890 while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refShorthandDefaultPos));
891 return this.finishNode(node, "SequenceExpression");
892 }
893 return expr;
894};
895
896// Parse an assignment expression. This includes applications of
897// operators like `+=`.
898
899pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) {
900 if (this.type == tt._yield && this.inGenerator) return this.parseYield();
901
902 var failOnShorthandAssign = undefined;
903 if (!refShorthandDefaultPos) {
904 refShorthandDefaultPos = { start: 0 };
905 failOnShorthandAssign = true;
906 } else {
907 failOnShorthandAssign = false;
908 }
909 var startPos = this.start,
910 startLoc = this.startLoc;
911 if (this.type == tt.parenL || this.type == tt.name) this.potentialArrowAt = this.start;
912 var left = this.parseMaybeConditional(noIn, refShorthandDefaultPos);
913 if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc);
914 if (this.type.isAssign) {
915 var node = this.startNodeAt(startPos, startLoc);
916 node.operator = this.value;
917 node.left = this.type === tt.eq ? this.toAssignable(left) : left;
918 refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly
919 this.checkLVal(left);
920 this.next();
921 node.right = this.parseMaybeAssign(noIn);
922 return this.finishNode(node, "AssignmentExpression");
923 } else if (failOnShorthandAssign && refShorthandDefaultPos.start) {
924 this.unexpected(refShorthandDefaultPos.start);
925 }
926 return left;
927};
928
929// Parse a ternary conditional (`?:`) operator.
930
931pp.parseMaybeConditional = function (noIn, refShorthandDefaultPos) {
932 var startPos = this.start,
933 startLoc = this.startLoc;
934 var expr = this.parseExprOps(noIn, refShorthandDefaultPos);
935 if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
936 if (this.eat(tt.question)) {
937 var node = this.startNodeAt(startPos, startLoc);
938 node.test = expr;
939 node.consequent = this.parseMaybeAssign();
940 this.expect(tt.colon);
941 node.alternate = this.parseMaybeAssign(noIn);
942 return this.finishNode(node, "ConditionalExpression");
943 }
944 return expr;
945};
946
947// Start the precedence parser.
948
949pp.parseExprOps = function (noIn, refShorthandDefaultPos) {
950 var startPos = this.start,
951 startLoc = this.startLoc;
952 var expr = this.parseMaybeUnary(refShorthandDefaultPos);
953 if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
954 return this.parseExprOp(expr, startPos, startLoc, -1, noIn);
955};
956
957// Parse binary operators with the operator precedence parsing
958// algorithm. `left` is the left-hand side of the operator.
959// `minPrec` provides context that allows the function to stop and
960// defer further parser to one of its callers when it encounters an
961// operator that has a lower precedence than the set it is parsing.
962
963pp.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) {
964 var prec = this.type.binop;
965 if (Array.isArray(leftStartPos)) {
966 if (this.options.locations && noIn === undefined) {
967 // shift arguments to left by one
968 noIn = minPrec;
969 minPrec = leftStartLoc;
970 // flatten leftStartPos
971 leftStartLoc = leftStartPos[1];
972 leftStartPos = leftStartPos[0];
973 }
974 }
975 if (prec != null && (!noIn || this.type !== tt._in)) {
976 if (prec > minPrec) {
977 var node = this.startNodeAt(leftStartPos, leftStartLoc);
978 node.left = left;
979 node.operator = this.value;
980 var op = this.type;
981 this.next();
982 var startPos = this.start,
983 startLoc = this.startLoc;
984 node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, prec, noIn);
985 this.finishNode(node, op === tt.logicalOR || op === tt.logicalAND ? "LogicalExpression" : "BinaryExpression");
986 return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn);
987 }
988 }
989 return left;
990};
991
992// Parse unary operators, both prefix and postfix.
993
994pp.parseMaybeUnary = function (refShorthandDefaultPos) {
995 if (this.type.prefix) {
996 var node = this.startNode(),
997 update = this.type === tt.incDec;
998 node.operator = this.value;
999 node.prefix = true;
1000 this.next();
1001 node.argument = this.parseMaybeUnary();
1002 if (refShorthandDefaultPos && refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
1003 if (update) this.checkLVal(node.argument);else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") this.raise(node.start, "Deleting local variable in strict mode");
1004 return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
1005 }
1006 var startPos = this.start,
1007 startLoc = this.startLoc;
1008 var expr = this.parseExprSubscripts(refShorthandDefaultPos);
1009 if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
1010 while (this.type.postfix && !this.canInsertSemicolon()) {
1011 var node = this.startNodeAt(startPos, startLoc);
1012 node.operator = this.value;
1013 node.prefix = false;
1014 node.argument = expr;
1015 this.checkLVal(expr);
1016 this.next();
1017 expr = this.finishNode(node, "UpdateExpression");
1018 }
1019 return expr;
1020};
1021
1022// Parse call, dot, and `[]`-subscript expressions.
1023
1024pp.parseExprSubscripts = function (refShorthandDefaultPos) {
1025 var startPos = this.start,
1026 startLoc = this.startLoc;
1027 var expr = this.parseExprAtom(refShorthandDefaultPos);
1028 if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
1029 return this.parseSubscripts(expr, startPos, startLoc);
1030};
1031
1032pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
1033 if (Array.isArray(startPos)) {
1034 if (this.options.locations && noCalls === undefined) {
1035 // shift arguments to left by one
1036 noCalls = startLoc;
1037 // flatten startPos
1038 startLoc = startPos[1];
1039 startPos = startPos[0];
1040 }
1041 }
1042 for (;;) {
1043 if (this.eat(tt.dot)) {
1044 var node = this.startNodeAt(startPos, startLoc);
1045 node.object = base;
1046 node.property = this.parseIdent(true);
1047 node.computed = false;
1048 base = this.finishNode(node, "MemberExpression");
1049 } else if (this.eat(tt.bracketL)) {
1050 var node = this.startNodeAt(startPos, startLoc);
1051 node.object = base;
1052 node.property = this.parseExpression();
1053 node.computed = true;
1054 this.expect(tt.bracketR);
1055 base = this.finishNode(node, "MemberExpression");
1056 } else if (!noCalls && this.eat(tt.parenL)) {
1057 var node = this.startNodeAt(startPos, startLoc);
1058 node.callee = base;
1059 node.arguments = this.parseExprList(tt.parenR, false);
1060 base = this.finishNode(node, "CallExpression");
1061 } else if (this.type === tt.backQuote) {
1062 var node = this.startNodeAt(startPos, startLoc);
1063 node.tag = base;
1064 node.quasi = this.parseTemplate();
1065 base = this.finishNode(node, "TaggedTemplateExpression");
1066 } else {
1067 return base;
1068 }
1069 }
1070};
1071
1072// Parse an atomic expression — either a single token that is an
1073// expression, an expression started by a keyword like `function` or
1074// `new`, or an expression wrapped in punctuation like `()`, `[]`,
1075// or `{}`.
1076
1077pp.parseExprAtom = function (refShorthandDefaultPos) {
1078 var node = undefined,
1079 canBeArrow = this.potentialArrowAt == this.start;
1080 switch (this.type) {
1081 case tt._this:
1082 case tt._super:
1083 var type = this.type === tt._this ? "ThisExpression" : "Super";
1084 node = this.startNode();
1085 this.next();
1086 return this.finishNode(node, type);
1087
1088 case tt._yield:
1089 if (this.inGenerator) this.unexpected();
1090
1091 case tt.name:
1092 var startPos = this.start,
1093 startLoc = this.startLoc;
1094 var id = this.parseIdent(this.type !== tt.name);
1095 if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id]);
1096 return id;
1097
1098 case tt.regexp:
1099 var value = this.value;
1100 node = this.parseLiteral(value.value);
1101 node.regex = { pattern: value.pattern, flags: value.flags };
1102 return node;
1103
1104 case tt.num:case tt.string:
1105 return this.parseLiteral(this.value);
1106
1107 case tt._null:case tt._true:case tt._false:
1108 node = this.startNode();
1109 node.value = this.type === tt._null ? null : this.type === tt._true;
1110 node.raw = this.type.keyword;
1111 this.next();
1112 return this.finishNode(node, "Literal");
1113
1114 case tt.parenL:
1115 return this.parseParenAndDistinguishExpression(canBeArrow);
1116
1117 case tt.bracketL:
1118 node = this.startNode();
1119 this.next();
1120 // check whether this is array comprehension or regular array
1121 if (this.options.ecmaVersion >= 7 && this.type === tt._for) {
1122 return this.parseComprehension(node, false);
1123 }
1124 node.elements = this.parseExprList(tt.bracketR, true, true, refShorthandDefaultPos);
1125 return this.finishNode(node, "ArrayExpression");
1126
1127 case tt.braceL:
1128 return this.parseObj(false, refShorthandDefaultPos);
1129
1130 case tt._function:
1131 node = this.startNode();
1132 this.next();
1133 return this.parseFunction(node, false);
1134
1135 case tt._class:
1136 return this.parseClass(this.startNode(), false);
1137
1138 case tt._new:
1139 return this.parseNew();
1140
1141 case tt.backQuote:
1142 return this.parseTemplate();
1143
1144 default:
1145 this.unexpected();
1146 }
1147};
1148
1149pp.parseLiteral = function (value) {
1150 var node = this.startNode();
1151 node.value = value;
1152 node.raw = this.input.slice(this.start, this.end);
1153 this.next();
1154 return this.finishNode(node, "Literal");
1155};
1156
1157pp.parseParenExpression = function () {
1158 this.expect(tt.parenL);
1159 var val = this.parseExpression();
1160 this.expect(tt.parenR);
1161 return val;
1162};
1163
1164pp.parseParenAndDistinguishExpression = function (canBeArrow) {
1165 var startPos = this.start,
1166 startLoc = this.startLoc,
1167 val = undefined;
1168 if (this.options.ecmaVersion >= 6) {
1169 this.next();
1170
1171 if (this.options.ecmaVersion >= 7 && this.type === tt._for) {
1172 return this.parseComprehension(this.startNodeAt(startPos, startLoc), true);
1173 }
1174
1175 var innerStartPos = this.start,
1176 innerStartLoc = this.startLoc;
1177 var exprList = [],
1178 first = true;
1179 var refShorthandDefaultPos = { start: 0 },
1180 spreadStart = undefined,
1181 innerParenStart = undefined;
1182 while (this.type !== tt.parenR) {
1183 first ? first = false : this.expect(tt.comma);
1184 if (this.type === tt.ellipsis) {
1185 spreadStart = this.start;
1186 exprList.push(this.parseParenItem(this.parseRest()));
1187 break;
1188 } else {
1189 if (this.type === tt.parenL && !innerParenStart) {
1190 innerParenStart = this.start;
1191 }
1192 exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem));
1193 }
1194 }
1195 var innerEndPos = this.start,
1196 innerEndLoc = this.startLoc;
1197 this.expect(tt.parenR);
1198
1199 if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
1200 if (innerParenStart) this.unexpected(innerParenStart);
1201 return this.parseParenArrowList(startPos, startLoc, exprList);
1202 }
1203
1204 if (!exprList.length) this.unexpected(this.lastTokStart);
1205 if (spreadStart) this.unexpected(spreadStart);
1206 if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
1207
1208 if (exprList.length > 1) {
1209 val = this.startNodeAt(innerStartPos, innerStartLoc);
1210 val.expressions = exprList;
1211 this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
1212 } else {
1213 val = exprList[0];
1214 }
1215 } else {
1216 val = this.parseParenExpression();
1217 }
1218
1219 if (this.options.preserveParens) {
1220 var par = this.startNodeAt(startPos, startLoc);
1221 par.expression = val;
1222 return this.finishNode(par, "ParenthesizedExpression");
1223 } else {
1224 return val;
1225 }
1226};
1227
1228pp.parseParenItem = function (item) {
1229 return item;
1230};
1231
1232pp.parseParenArrowList = function (startPos, startLoc, exprList) {
1233 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList);
1234};
1235
1236// New's precedence is slightly tricky. It must allow its argument
1237// to be a `[]` or dot subscript expression, but not a call — at
1238// least, not without wrapping it in parentheses. Thus, it uses the
1239
1240var empty = [];
1241
1242pp.parseNew = function () {
1243 var node = this.startNode();
1244 var meta = this.parseIdent(true);
1245 if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) {
1246 node.meta = meta;
1247 node.property = this.parseIdent(true);
1248 if (node.property.name !== "target") this.raise(node.property.start, "The only valid meta property for new is new.target");
1249 return this.finishNode(node, "MetaProperty");
1250 }
1251 var startPos = this.start,
1252 startLoc = this.startLoc;
1253 node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
1254 if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, false);else node.arguments = empty;
1255 return this.finishNode(node, "NewExpression");
1256};
1257
1258// Parse template expression.
1259
1260pp.parseTemplateElement = function () {
1261 var elem = this.startNode();
1262 elem.value = {
1263 raw: this.input.slice(this.start, this.end),
1264 cooked: this.value
1265 };
1266 this.next();
1267 elem.tail = this.type === tt.backQuote;
1268 return this.finishNode(elem, "TemplateElement");
1269};
1270
1271pp.parseTemplate = function () {
1272 var node = this.startNode();
1273 this.next();
1274 node.expressions = [];
1275 var curElt = this.parseTemplateElement();
1276 node.quasis = [curElt];
1277 while (!curElt.tail) {
1278 this.expect(tt.dollarBraceL);
1279 node.expressions.push(this.parseExpression());
1280 this.expect(tt.braceR);
1281 node.quasis.push(curElt = this.parseTemplateElement());
1282 }
1283 this.next();
1284 return this.finishNode(node, "TemplateLiteral");
1285};
1286
1287// Parse an object literal or binding pattern.
1288
1289pp.parseObj = function (isPattern, refShorthandDefaultPos) {
1290 var node = this.startNode(),
1291 first = true,
1292 propHash = {};
1293 node.properties = [];
1294 this.next();
1295 while (!this.eat(tt.braceR)) {
1296 if (!first) {
1297 this.expect(tt.comma);
1298 if (this.afterTrailingComma(tt.braceR)) break;
1299 } else first = false;
1300
1301 var prop = this.startNode(),
1302 isGenerator = undefined,
1303 startPos = undefined,
1304 startLoc = undefined;
1305 if (this.options.ecmaVersion >= 6) {
1306 prop.method = false;
1307 prop.shorthand = false;
1308 if (isPattern || refShorthandDefaultPos) {
1309 startPos = this.start;
1310 startLoc = this.startLoc;
1311 }
1312 if (!isPattern) isGenerator = this.eat(tt.star);
1313 }
1314 this.parsePropertyName(prop);
1315 this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refShorthandDefaultPos);
1316 this.checkPropClash(prop, propHash);
1317 node.properties.push(this.finishNode(prop, "Property"));
1318 }
1319 return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
1320};
1321
1322pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refShorthandDefaultPos) {
1323 if (this.eat(tt.colon)) {
1324 prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refShorthandDefaultPos);
1325 prop.kind = "init";
1326 } else if (this.options.ecmaVersion >= 6 && this.type === tt.parenL) {
1327 if (isPattern) this.unexpected();
1328 prop.kind = "init";
1329 prop.method = true;
1330 prop.value = this.parseMethod(isGenerator);
1331 } else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.type != tt.comma && this.type != tt.braceR)) {
1332 if (isGenerator || isPattern) this.unexpected();
1333 prop.kind = prop.key.name;
1334 this.parsePropertyName(prop);
1335 prop.value = this.parseMethod(false);
1336 } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
1337 prop.kind = "init";
1338 if (isPattern) {
1339 if (this.isKeyword(prop.key.name) || this.strict && (reservedWords.strictBind(prop.key.name) || reservedWords.strict(prop.key.name)) || !this.options.allowReserved && this.isReservedWord(prop.key.name)) this.raise(prop.key.start, "Binding " + prop.key.name);
1340 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
1341 } else if (this.type === tt.eq && refShorthandDefaultPos) {
1342 if (!refShorthandDefaultPos.start) refShorthandDefaultPos.start = this.start;
1343 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
1344 } else {
1345 prop.value = prop.key;
1346 }
1347 prop.shorthand = true;
1348 } else this.unexpected();
1349};
1350
1351pp.parsePropertyName = function (prop) {
1352 if (this.options.ecmaVersion >= 6) {
1353 if (this.eat(tt.bracketL)) {
1354 prop.computed = true;
1355 prop.key = this.parseMaybeAssign();
1356 this.expect(tt.bracketR);
1357 return prop.key;
1358 } else {
1359 prop.computed = false;
1360 }
1361 }
1362 return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(true);
1363};
1364
1365// Initialize empty function node.
1366
1367pp.initFunction = function (node) {
1368 node.id = null;
1369 if (this.options.ecmaVersion >= 6) {
1370 node.generator = false;
1371 node.expression = false;
1372 }
1373};
1374
1375// Parse object or class method.
1376
1377pp.parseMethod = function (isGenerator) {
1378 var node = this.startNode();
1379 this.initFunction(node);
1380 this.expect(tt.parenL);
1381 node.params = this.parseBindingList(tt.parenR, false, false);
1382 var allowExpressionBody = undefined;
1383 if (this.options.ecmaVersion >= 6) {
1384 node.generator = isGenerator;
1385 allowExpressionBody = true;
1386 } else {
1387 allowExpressionBody = false;
1388 }
1389 this.parseFunctionBody(node, allowExpressionBody);
1390 return this.finishNode(node, "FunctionExpression");
1391};
1392
1393// Parse arrow function expression with given parameters.
1394
1395pp.parseArrowExpression = function (node, params) {
1396 this.initFunction(node);
1397 node.params = this.toAssignableList(params, true);
1398 this.parseFunctionBody(node, true);
1399 return this.finishNode(node, "ArrowFunctionExpression");
1400};
1401
1402// Parse function body and check parameters.
1403
1404pp.parseFunctionBody = function (node, allowExpression) {
1405 var isExpression = allowExpression && this.type !== tt.braceL;
1406
1407 if (isExpression) {
1408 node.body = this.parseMaybeAssign();
1409 node.expression = true;
1410 } else {
1411 // Start a new scope with regard to labels and the `inFunction`
1412 // flag (restore them to their old value afterwards).
1413 var oldInFunc = this.inFunction,
1414 oldInGen = this.inGenerator,
1415 oldLabels = this.labels;
1416 this.inFunction = true;this.inGenerator = node.generator;this.labels = [];
1417 node.body = this.parseBlock(true);
1418 node.expression = false;
1419 this.inFunction = oldInFunc;this.inGenerator = oldInGen;this.labels = oldLabels;
1420 }
1421
1422 // If this is a strict mode function, verify that argument names
1423 // are not repeated, and it does not try to bind the words `eval`
1424 // or `arguments`.
1425 if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) {
1426 var nameHash = {},
1427 oldStrict = this.strict;
1428 this.strict = true;
1429 if (node.id) this.checkLVal(node.id, true);
1430 for (var i = 0; i < node.params.length; i++) {
1431 this.checkLVal(node.params[i], true, nameHash);
1432 }this.strict = oldStrict;
1433 }
1434};
1435
1436// Parses a comma-separated list of expressions, and returns them as
1437// an array. `close` is the token type that ends the list, and
1438// `allowEmpty` can be turned on to allow subsequent commas with
1439// nothing in between them to be parsed as `null` (which is needed
1440// for array literals).
1441
1442pp.parseExprList = function (close, allowTrailingComma, allowEmpty, refShorthandDefaultPos) {
1443 var elts = [],
1444 first = true;
1445 while (!this.eat(close)) {
1446 if (!first) {
1447 this.expect(tt.comma);
1448 if (allowTrailingComma && this.afterTrailingComma(close)) break;
1449 } else first = false;
1450
1451 if (allowEmpty && this.type === tt.comma) {
1452 elts.push(null);
1453 } else {
1454 if (this.type === tt.ellipsis) elts.push(this.parseSpread(refShorthandDefaultPos));else elts.push(this.parseMaybeAssign(false, refShorthandDefaultPos));
1455 }
1456 }
1457 return elts;
1458};
1459
1460// Parse the next token as an identifier. If `liberal` is true (used
1461// when parsing properties), it will also convert keywords into
1462// identifiers.
1463
1464pp.parseIdent = function (liberal) {
1465 var node = this.startNode();
1466 if (liberal && this.options.allowReserved == "never") liberal = false;
1467 if (this.type === tt.name) {
1468 if (!liberal && (!this.options.allowReserved && this.isReservedWord(this.value) || this.strict && reservedWords.strict(this.value) && (this.options.ecmaVersion >= 6 || this.input.slice(this.start, this.end).indexOf("\\") == -1))) this.raise(this.start, "The keyword '" + this.value + "' is reserved");
1469 node.name = this.value;
1470 } else if (liberal && this.type.keyword) {
1471 node.name = this.type.keyword;
1472 } else {
1473 this.unexpected();
1474 }
1475 this.next();
1476 return this.finishNode(node, "Identifier");
1477};
1478
1479// Parses yield expression inside generator.
1480
1481pp.parseYield = function () {
1482 var node = this.startNode();
1483 this.next();
1484 if (this.type == tt.semi || this.canInsertSemicolon() || this.type != tt.star && !this.type.startsExpr) {
1485 node.delegate = false;
1486 node.argument = null;
1487 } else {
1488 node.delegate = this.eat(tt.star);
1489 node.argument = this.parseMaybeAssign();
1490 }
1491 return this.finishNode(node, "YieldExpression");
1492};
1493
1494// Parses array and generator comprehensions.
1495
1496pp.parseComprehension = function (node, isGenerator) {
1497 node.blocks = [];
1498 while (this.type === tt._for) {
1499 var block = this.startNode();
1500 this.next();
1501 this.expect(tt.parenL);
1502 block.left = this.parseBindingAtom();
1503 this.checkLVal(block.left, true);
1504 this.expectContextual("of");
1505 block.right = this.parseExpression();
1506 this.expect(tt.parenR);
1507 node.blocks.push(this.finishNode(block, "ComprehensionBlock"));
1508 }
1509 node.filter = this.eat(tt._if) ? this.parseParenExpression() : null;
1510 node.body = this.parseExpression();
1511 this.expect(isGenerator ? tt.parenR : tt.bracketR);
1512 node.generator = isGenerator;
1513 return this.finishNode(node, "ComprehensionExpression");
1514};
1515
1516},{"./identifier":7,"./state":13,"./tokentype":17,"./util":18}],7:[function(_dereq_,module,exports){
1517
1518
1519// Test whether a given character code starts an identifier.
1520
1521"use strict";
1522
1523exports.isIdentifierStart = isIdentifierStart;
1524
1525// Test whether a given character is part of an identifier.
1526
1527exports.isIdentifierChar = isIdentifierChar;
1528exports.__esModule = true;
1529// This is a trick taken from Esprima. It turns out that, on
1530// non-Chrome browsers, to check whether a string is in a set, a
1531// predicate containing a big ugly `switch` statement is faster than
1532// a regular expression, and on Chrome the two are about on par.
1533// This function uses `eval` (non-lexical) to produce such a
1534// predicate from a space-separated string of words.
1535//
1536// It starts by sorting the words by length.
1537
1538function makePredicate(words) {
1539 words = words.split(" ");
1540 var f = "",
1541 cats = [];
1542 out: for (var i = 0; i < words.length; ++i) {
1543 for (var j = 0; j < cats.length; ++j) {
1544 if (cats[j][0].length == words[i].length) {
1545 cats[j].push(words[i]);
1546 continue out;
1547 }
1548 }cats.push([words[i]]);
1549 }
1550 function compareTo(arr) {
1551 if (arr.length == 1) {
1552 return f += "return str === " + JSON.stringify(arr[0]) + ";";
1553 }f += "switch(str){";
1554 for (var i = 0; i < arr.length; ++i) {
1555 f += "case " + JSON.stringify(arr[i]) + ":";
1556 }f += "return true}return false;";
1557 }
1558
1559 // When there are more than three length categories, an outer
1560 // switch first dispatches on the lengths, to save on comparisons.
1561
1562 if (cats.length > 3) {
1563 cats.sort(function (a, b) {
1564 return b.length - a.length;
1565 });
1566 f += "switch(str.length){";
1567 for (var i = 0; i < cats.length; ++i) {
1568 var cat = cats[i];
1569 f += "case " + cat[0].length + ":";
1570 compareTo(cat);
1571 }
1572 f += "}"
1573
1574 // Otherwise, simply generate a flat `switch` statement.
1575
1576 ;
1577 } else {
1578 compareTo(words);
1579 }
1580 return new Function("str", f);
1581}
1582
1583// Reserved word lists for various dialects of the language
1584
1585var reservedWords = {
1586 3: makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),
1587 5: makePredicate("class enum extends super const export import"),
1588 6: makePredicate("enum await"),
1589 strict: makePredicate("implements interface let package private protected public static yield"),
1590 strictBind: makePredicate("eval arguments")
1591};
1592
1593exports.reservedWords = reservedWords;
1594// And the keywords
1595
1596var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
1597
1598var keywords = {
1599 5: makePredicate(ecma5AndLessKeywords),
1600 6: makePredicate(ecma5AndLessKeywords + " let const class extends export import yield super")
1601};
1602
1603exports.keywords = keywords;
1604// ## Character categories
1605
1606// Big ugly regular expressions that match characters in the
1607// whitespace, identifier, and identifier-start categories. These
1608// are only applied when a character is found to actually have a
1609// code point above 128.
1610// Generated by `tools/generate-identifier-regex.js`.
1611
1612var nonASCIIidentifierStartChars = "ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠ-ࢲऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘౙౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൠൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕ℘-ℝℤΩℨK-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〇〡-〩〱-〵〸-〼ぁ-ゖ゛-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚝꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞭꞰꞱꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭟꭤꭥꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ";
1613var nonASCIIidentifierChars = "‌‍·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-٩ٰۖ-ۜ۟-۪ۤۧۨ-ۭ۰-۹ܑܰ-݊ަ-ް߀-߉߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣤ-ःऺ-़ा-ॏ॑-ॗॢॣ०-९ঁ-ঃ়া-ৄেৈো-্ৗৢৣ০-৯ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑ੦-ੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣ૦-૯ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣ୦-୯ஂா-ூெ-ைொ-்ௗ௦-௯ఀ-ఃా-ౄె-ైొ-్ౕౖౢౣ౦-౯ಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣ೦-೯ഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣ൦-൯ංඃ්ා-ුූෘ-ෟ෦-෯ෲෳัิ-ฺ็-๎๐-๙ັິ-ູົຼ່-ໍ໐-໙༘༙༠-༩༹༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှ၀-၉ၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏ-ႝ፝-፟፩-፱ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝០-៩᠋-᠍᠐-᠙ᢩᤠ-ᤫᤰ-᤻᥆-᥏ᦰ-ᧀᧈᧉ᧐-᧚ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼-᪉᪐-᪙᪰-᪽ᬀ-ᬄ᬴-᭄᭐-᭙᭫-᭳ᮀ-ᮂᮡ-ᮭ᮰-᮹᯦-᯳ᰤ-᰷᱀-᱉᱐-᱙᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷼-᷿‿⁀⁔⃐-⃥⃜⃡-⃰⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꘠-꘩꙯ꙴ-꙽ꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-꣄꣐-꣙꣠-꣱꤀-꤉ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀꧐-꧙ꧥ꧰-꧹ꨩ-ꨶꩃꩌꩍ꩐-꩙ꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭꯰-꯹ﬞ︀-️︠-︭︳︴﹍-﹏0-9_";
1614
1615var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
1616var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
1617
1618nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
1619
1620// These are a run-length and offset encoded representation of the
1621// >0xffff code points that are a valid part of identifiers. The
1622// offset starts at 0x10000, and each pair of numbers represents an
1623// offset to the next range, and then a size of the range. They were
1624// generated by tools/generate-identifier-regex.js
1625var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 17, 26, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 99, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 98, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 26, 45, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 955, 52, 76, 44, 33, 24, 27, 35, 42, 34, 4, 0, 13, 47, 15, 3, 22, 0, 38, 17, 2, 24, 133, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 32, 4, 287, 47, 21, 1, 2, 0, 185, 46, 82, 47, 21, 0, 60, 42, 502, 63, 32, 0, 449, 56, 1288, 920, 104, 110, 2962, 1070, 13266, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 881, 68, 12, 0, 67, 12, 16481, 1, 3071, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 4149, 196, 1340, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 16355, 541];
1626var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 1306, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 52, 0, 13, 2, 49, 13, 16, 9, 83, 11, 168, 11, 6, 9, 8, 2, 57, 0, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 316, 19, 13, 9, 214, 6, 3, 8, 112, 16, 16, 9, 82, 12, 9, 9, 535, 9, 20855, 9, 135, 4, 60, 6, 26, 9, 1016, 45, 17, 3, 19723, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 4305, 6, 792618, 239];
1627
1628// This has a complexity linear to the value of the code. The
1629// assumption is that looking up astral identifier characters is
1630// rare.
1631function isInAstralSet(code, set) {
1632 var pos = 65536;
1633 for (var i = 0; i < set.length; i += 2) {
1634 pos += set[i];
1635 if (pos > code) {
1636 return false;
1637 }pos += set[i + 1];
1638 if (pos >= code) {
1639 return true;
1640 }
1641 }
1642}
1643function isIdentifierStart(code, astral) {
1644 if (code < 65) {
1645 return code === 36;
1646 }if (code < 91) {
1647 return true;
1648 }if (code < 97) {
1649 return code === 95;
1650 }if (code < 123) {
1651 return true;
1652 }if (code <= 65535) {
1653 return code >= 170 && nonASCIIidentifierStart.test(String.fromCharCode(code));
1654 }if (astral === false) {
1655 return false;
1656 }return isInAstralSet(code, astralIdentifierStartCodes);
1657}
1658
1659function isIdentifierChar(code, astral) {
1660 if (code < 48) {
1661 return code === 36;
1662 }if (code < 58) {
1663 return true;
1664 }if (code < 65) {
1665 return false;
1666 }if (code < 91) {
1667 return true;
1668 }if (code < 97) {
1669 return code === 95;
1670 }if (code < 123) {
1671 return true;
1672 }if (code <= 65535) {
1673 return code >= 170 && nonASCIIidentifier.test(String.fromCharCode(code));
1674 }if (astral === false) {
1675 return false;
1676 }return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
1677}
1678
1679},{}],8:[function(_dereq_,module,exports){
1680"use strict";
1681
1682var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
1683
1684// The `getLineInfo` function is mostly useful when the
1685// `locations` option is off (for performance reasons) and you
1686// want to find the line/column position for a given character
1687// offset. `input` should be the code string that the offset refers
1688// into.
1689
1690exports.getLineInfo = getLineInfo;
1691exports.__esModule = true;
1692
1693var Parser = _dereq_("./state").Parser;
1694
1695var lineBreakG = _dereq_("./whitespace").lineBreakG;
1696
1697var deprecate = _dereq_("util").deprecate;
1698
1699// These are used when `options.locations` is on, for the
1700// `startLoc` and `endLoc` properties.
1701
1702var Position = exports.Position = (function () {
1703 function Position(line, col) {
1704 _classCallCheck(this, Position);
1705
1706 this.line = line;
1707 this.column = col;
1708 }
1709
1710 Position.prototype.offset = function offset(n) {
1711 return new Position(this.line, this.column + n);
1712 };
1713
1714 return Position;
1715})();
1716
1717var SourceLocation = exports.SourceLocation = function SourceLocation(p, start, end) {
1718 _classCallCheck(this, SourceLocation);
1719
1720 this.start = start;
1721 this.end = end;
1722 if (p.sourceFile !== null) this.source = p.sourceFile;
1723};
1724
1725function getLineInfo(input, offset) {
1726 for (var line = 1, cur = 0;;) {
1727 lineBreakG.lastIndex = cur;
1728 var match = lineBreakG.exec(input);
1729 if (match && match.index < offset) {
1730 ++line;
1731 cur = match.index + match[0].length;
1732 } else {
1733 return new Position(line, offset - cur);
1734 }
1735 }
1736}
1737
1738var pp = Parser.prototype;
1739
1740// This function is used to raise exceptions on parse errors. It
1741// takes an offset integer (into the current `input`) to indicate
1742// the location of the error, attaches the position to the end
1743// of the error message, and then raises a `SyntaxError` with that
1744// message.
1745
1746pp.raise = function (pos, message) {
1747 var loc = getLineInfo(this.input, pos);
1748 message += " (" + loc.line + ":" + loc.column + ")";
1749 var err = new SyntaxError(message);
1750 err.pos = pos;err.loc = loc;err.raisedAt = this.pos;
1751 throw err;
1752};
1753
1754pp.curPosition = function () {
1755 return new Position(this.curLine, this.pos - this.lineStart);
1756};
1757
1758pp.markPosition = function () {
1759 return this.options.locations ? [this.start, this.startLoc] : this.start;
1760};
1761
1762},{"./state":13,"./whitespace":19,"util":5}],9:[function(_dereq_,module,exports){
1763"use strict";
1764
1765var tt = _dereq_("./tokentype").types;
1766
1767var Parser = _dereq_("./state").Parser;
1768
1769var reservedWords = _dereq_("./identifier").reservedWords;
1770
1771var has = _dereq_("./util").has;
1772
1773var pp = Parser.prototype;
1774
1775// Convert existing expression atom to assignable pattern
1776// if possible.
1777
1778pp.toAssignable = function (node, isBinding) {
1779 if (this.options.ecmaVersion >= 6 && node) {
1780 switch (node.type) {
1781 case "Identifier":
1782 case "ObjectPattern":
1783 case "ArrayPattern":
1784 case "AssignmentPattern":
1785 break;
1786
1787 case "ObjectExpression":
1788 node.type = "ObjectPattern";
1789 for (var i = 0; i < node.properties.length; i++) {
1790 var prop = node.properties[i];
1791 if (prop.kind !== "init") this.raise(prop.key.start, "Object pattern can't contain getter or setter");
1792 this.toAssignable(prop.value, isBinding);
1793 }
1794 break;
1795
1796 case "ArrayExpression":
1797 node.type = "ArrayPattern";
1798 this.toAssignableList(node.elements, isBinding);
1799 break;
1800
1801 case "AssignmentExpression":
1802 if (node.operator === "=") {
1803 node.type = "AssignmentPattern";
1804 } else {
1805 this.raise(node.left.end, "Only '=' operator can be used for specifying default value.");
1806 }
1807 break;
1808
1809 case "ParenthesizedExpression":
1810 node.expression = this.toAssignable(node.expression, isBinding);
1811 break;
1812
1813 case "MemberExpression":
1814 if (!isBinding) break;
1815
1816 default:
1817 this.raise(node.start, "Assigning to rvalue");
1818 }
1819 }
1820 return node;
1821};
1822
1823// Convert list of expression atoms to binding list.
1824
1825pp.toAssignableList = function (exprList, isBinding) {
1826 var end = exprList.length;
1827 if (end) {
1828 var last = exprList[end - 1];
1829 if (last && last.type == "RestElement") {
1830 --end;
1831 } else if (last && last.type == "SpreadElement") {
1832 last.type = "RestElement";
1833 var arg = last.argument;
1834 this.toAssignable(arg, isBinding);
1835 if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") this.unexpected(arg.start);
1836 --end;
1837 }
1838 }
1839 for (var i = 0; i < end; i++) {
1840 var elt = exprList[i];
1841 if (elt) this.toAssignable(elt, isBinding);
1842 }
1843 return exprList;
1844};
1845
1846// Parses spread element.
1847
1848pp.parseSpread = function (refShorthandDefaultPos) {
1849 var node = this.startNode();
1850 this.next();
1851 node.argument = this.parseMaybeAssign(refShorthandDefaultPos);
1852 return this.finishNode(node, "SpreadElement");
1853};
1854
1855pp.parseRest = function () {
1856 var node = this.startNode();
1857 this.next();
1858 node.argument = this.type === tt.name || this.type === tt.bracketL ? this.parseBindingAtom() : this.unexpected();
1859 return this.finishNode(node, "RestElement");
1860};
1861
1862// Parses lvalue (assignable) atom.
1863
1864pp.parseBindingAtom = function () {
1865 if (this.options.ecmaVersion < 6) return this.parseIdent();
1866 switch (this.type) {
1867 case tt.name:
1868 return this.parseIdent();
1869
1870 case tt.bracketL:
1871 var node = this.startNode();
1872 this.next();
1873 node.elements = this.parseBindingList(tt.bracketR, true, true);
1874 return this.finishNode(node, "ArrayPattern");
1875
1876 case tt.braceL:
1877 return this.parseObj(true);
1878
1879 default:
1880 this.unexpected();
1881 }
1882};
1883
1884pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
1885 var elts = [],
1886 first = true;
1887 while (!this.eat(close)) {
1888 if (first) first = false;else this.expect(tt.comma);
1889 if (allowEmpty && this.type === tt.comma) {
1890 elts.push(null);
1891 } else if (allowTrailingComma && this.afterTrailingComma(close)) {
1892 break;
1893 } else if (this.type === tt.ellipsis) {
1894 var rest = this.parseRest();
1895 this.parseBindingListItem(rest);
1896 elts.push(rest);
1897 this.expect(close);
1898 break;
1899 } else {
1900 var elem = this.parseMaybeDefault(this.start, this.startLoc);
1901 this.parseBindingListItem(elem);
1902 elts.push(elem);
1903 }
1904 }
1905 return elts;
1906};
1907
1908pp.parseBindingListItem = function (param) {
1909 return param;
1910};
1911
1912// Parses assignment pattern around given atom if possible.
1913
1914pp.parseMaybeDefault = function (startPos, startLoc, left) {
1915 if (Array.isArray(startPos)) {
1916 if (this.options.locations && noCalls === undefined) {
1917 // shift arguments to left by one
1918 left = startLoc;
1919 // flatten startPos
1920 startLoc = startPos[1];
1921 startPos = startPos[0];
1922 }
1923 }
1924 left = left || this.parseBindingAtom();
1925 if (!this.eat(tt.eq)) return left;
1926 var node = this.startNodeAt(startPos, startLoc);
1927 node.operator = "=";
1928 node.left = left;
1929 node.right = this.parseMaybeAssign();
1930 return this.finishNode(node, "AssignmentPattern");
1931};
1932
1933// Verify that a node is an lval — something that can be assigned
1934// to.
1935
1936pp.checkLVal = function (expr, isBinding, checkClashes) {
1937 switch (expr.type) {
1938 case "Identifier":
1939 if (this.strict && (reservedWords.strictBind(expr.name) || reservedWords.strict(expr.name))) this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode");
1940 if (checkClashes) {
1941 if (has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash in strict mode");
1942 checkClashes[expr.name] = true;
1943 }
1944 break;
1945
1946 case "MemberExpression":
1947 if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression");
1948 break;
1949
1950 case "ObjectPattern":
1951 for (var i = 0; i < expr.properties.length; i++) {
1952 this.checkLVal(expr.properties[i].value, isBinding, checkClashes);
1953 }break;
1954
1955 case "ArrayPattern":
1956 for (var i = 0; i < expr.elements.length; i++) {
1957 var elem = expr.elements[i];
1958 if (elem) this.checkLVal(elem, isBinding, checkClashes);
1959 }
1960 break;
1961
1962 case "AssignmentPattern":
1963 this.checkLVal(expr.left, isBinding, checkClashes);
1964 break;
1965
1966 case "RestElement":
1967 this.checkLVal(expr.argument, isBinding, checkClashes);
1968 break;
1969
1970 case "ParenthesizedExpression":
1971 this.checkLVal(expr.expression, isBinding, checkClashes);
1972 break;
1973
1974 default:
1975 this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue");
1976 }
1977};
1978
1979},{"./identifier":7,"./state":13,"./tokentype":17,"./util":18}],10:[function(_dereq_,module,exports){
1980"use strict";
1981
1982var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
1983
1984exports.__esModule = true;
1985
1986var Parser = _dereq_("./state").Parser;
1987
1988var SourceLocation = _dereq_("./location").SourceLocation;
1989
1990// Start an AST node, attaching a start offset.
1991
1992var pp = Parser.prototype;
1993
1994var Node = exports.Node = function Node() {
1995 _classCallCheck(this, Node);
1996};
1997
1998pp.startNode = function () {
1999 var node = new Node();
2000 node.start = this.start;
2001 if (this.options.locations) node.loc = new SourceLocation(this, this.startLoc);
2002 if (this.options.directSourceFile) node.sourceFile = this.options.directSourceFile;
2003 if (this.options.ranges) node.range = [this.start, 0];
2004 return node;
2005};
2006
2007pp.startNodeAt = function (pos, loc) {
2008 var node = new Node();
2009 if (Array.isArray(pos)) {
2010 if (this.options.locations && loc === undefined) {
2011 // flatten pos
2012 loc = pos[1];
2013 pos = pos[0];
2014 }
2015 }
2016 node.start = pos;
2017 if (this.options.locations) node.loc = new SourceLocation(this, loc);
2018 if (this.options.directSourceFile) node.sourceFile = this.options.directSourceFile;
2019 if (this.options.ranges) node.range = [pos, 0];
2020 return node;
2021};
2022
2023// Finish an AST node, adding `type` and `end` properties.
2024
2025pp.finishNode = function (node, type) {
2026 node.type = type;
2027 node.end = this.lastTokEnd;
2028 if (this.options.locations) node.loc.end = this.lastTokEndLoc;
2029 if (this.options.ranges) node.range[1] = this.lastTokEnd;
2030 return node;
2031};
2032
2033// Finish node at given position
2034
2035pp.finishNodeAt = function (node, type, pos, loc) {
2036 node.type = type;
2037 if (Array.isArray(pos)) {
2038 if (this.options.locations && loc === undefined) {
2039 // flatten pos
2040 loc = pos[1];
2041 pos = pos[0];
2042 }
2043 }
2044 node.end = pos;
2045 if (this.options.locations) node.loc.end = loc;
2046 if (this.options.ranges) node.range[1] = pos;
2047 return node;
2048};
2049
2050},{"./location":8,"./state":13}],11:[function(_dereq_,module,exports){
2051
2052
2053// Interpret and default an options object
2054
2055"use strict";
2056
2057exports.getOptions = getOptions;
2058exports.__esModule = true;
2059
2060var _util = _dereq_("./util");
2061
2062var has = _util.has;
2063var isArray = _util.isArray;
2064
2065var SourceLocation = _dereq_("./location").SourceLocation;
2066
2067// A second optional argument can be given to further configure
2068// the parser process. These options are recognized:
2069
2070var defaultOptions = {
2071 // `ecmaVersion` indicates the ECMAScript version to parse. Must
2072 // be either 3, or 5, or 6. This influences support for strict
2073 // mode, the set of reserved words, support for getters and
2074 // setters and other features.
2075 ecmaVersion: 5,
2076 // Source type ("script" or "module") for different semantics
2077 sourceType: "script",
2078 // `onInsertedSemicolon` can be a callback that will be called
2079 // when a semicolon is automatically inserted. It will be passed
2080 // th position of the comma as an offset, and if `locations` is
2081 // enabled, it is given the location as a `{line, column}` object
2082 // as second argument.
2083 onInsertedSemicolon: null,
2084 // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
2085 // trailing commas.
2086 onTrailingComma: null,
2087 // By default, reserved words are not enforced. Disable
2088 // `allowReserved` to enforce them. When this option has the
2089 // value "never", reserved words and keywords can also not be
2090 // used as property names.
2091 allowReserved: true,
2092 // When enabled, a return at the top level is not considered an
2093 // error.
2094 allowReturnOutsideFunction: false,
2095 // When enabled, import/export statements are not constrained to
2096 // appearing at the top of the program.
2097 allowImportExportEverywhere: false,
2098 // When enabled, hashbang directive in the beginning of file
2099 // is allowed and treated as a line comment.
2100 allowHashBang: false,
2101 // When `locations` is on, `loc` properties holding objects with
2102 // `start` and `end` properties in `{line, column}` form (with
2103 // line being 1-based and column 0-based) will be attached to the
2104 // nodes.
2105 locations: false,
2106 // A function can be passed as `onToken` option, which will
2107 // cause Acorn to call that function with object in the same
2108 // format as tokenize() returns. Note that you are not
2109 // allowed to call the parser from the callback—that will
2110 // corrupt its internal state.
2111 onToken: null,
2112 // A function can be passed as `onComment` option, which will
2113 // cause Acorn to call that function with `(block, text, start,
2114 // end)` parameters whenever a comment is skipped. `block` is a
2115 // boolean indicating whether this is a block (`/* */`) comment,
2116 // `text` is the content of the comment, and `start` and `end` are
2117 // character offsets that denote the start and end of the comment.
2118 // When the `locations` option is on, two more parameters are
2119 // passed, the full `{line, column}` locations of the start and
2120 // end of the comments. Note that you are not allowed to call the
2121 // parser from the callback—that will corrupt its internal state.
2122 onComment: null,
2123 // Nodes have their start and end characters offsets recorded in
2124 // `start` and `end` properties (directly on the node, rather than
2125 // the `loc` object, which holds line/column data. To also add a
2126 // [semi-standardized][range] `range` property holding a `[start,
2127 // end]` array with the same numbers, set the `ranges` option to
2128 // `true`.
2129 //
2130 // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
2131 ranges: false,
2132 // It is possible to parse multiple files into a single AST by
2133 // passing the tree produced by parsing the first file as
2134 // `program` option in subsequent parses. This will add the
2135 // toplevel forms of the parsed file to the `Program` (top) node
2136 // of an existing parse tree.
2137 program: null,
2138 // When `locations` is on, you can pass this to record the source
2139 // file in every node's `loc` object.
2140 sourceFile: null,
2141 // This value, if given, is stored in every node, whether
2142 // `locations` is on or off.
2143 directSourceFile: null,
2144 // When enabled, parenthesized expressions are represented by
2145 // (non-standard) ParenthesizedExpression nodes
2146 preserveParens: false,
2147 plugins: {}
2148};exports.defaultOptions = defaultOptions;
2149
2150function getOptions(opts) {
2151 var options = {};
2152 for (var opt in defaultOptions) {
2153 options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt];
2154 }if (isArray(options.onToken)) {
2155 (function () {
2156 var tokens = options.onToken;
2157 options.onToken = function (token) {
2158 return tokens.push(token);
2159 };
2160 })();
2161 }
2162 if (isArray(options.onComment)) options.onComment = pushComment(options, options.onComment);
2163
2164 return options;
2165}
2166
2167function pushComment(options, array) {
2168 return function (block, text, start, end, startLoc, endLoc) {
2169 var comment = {
2170 type: block ? "Block" : "Line",
2171 value: text,
2172 start: start,
2173 end: end
2174 };
2175 if (options.locations) comment.loc = new SourceLocation(this, startLoc, endLoc);
2176 if (options.ranges) comment.range = [start, end];
2177 array.push(comment);
2178 };
2179}
2180
2181},{"./location":8,"./util":18}],12:[function(_dereq_,module,exports){
2182"use strict";
2183
2184var tt = _dereq_("./tokentype").types;
2185
2186var Parser = _dereq_("./state").Parser;
2187
2188var lineBreak = _dereq_("./whitespace").lineBreak;
2189
2190var pp = Parser.prototype;
2191
2192// ## Parser utilities
2193
2194// Test whether a statement node is the string literal `"use strict"`.
2195
2196pp.isUseStrict = function (stmt) {
2197 return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && stmt.expression.value === "use strict";
2198};
2199
2200// Predicate that tests whether the next token is of the given
2201// type, and if yes, consumes it as a side effect.
2202
2203pp.eat = function (type) {
2204 if (this.type === type) {
2205 this.next();
2206 return true;
2207 } else {
2208 return false;
2209 }
2210};
2211
2212// Tests whether parsed token is a contextual keyword.
2213
2214pp.isContextual = function (name) {
2215 return this.type === tt.name && this.value === name;
2216};
2217
2218// Consumes contextual keyword if possible.
2219
2220pp.eatContextual = function (name) {
2221 return this.value === name && this.eat(tt.name);
2222};
2223
2224// Asserts that following token is given contextual keyword.
2225
2226pp.expectContextual = function (name) {
2227 if (!this.eatContextual(name)) this.unexpected();
2228};
2229
2230// Test whether a semicolon can be inserted at the current position.
2231
2232pp.canInsertSemicolon = function () {
2233 return this.type === tt.eof || this.type === tt.braceR || lineBreak.test(this.input.slice(this.lastTokEnd, this.start));
2234};
2235
2236pp.insertSemicolon = function () {
2237 if (this.canInsertSemicolon()) {
2238 if (this.options.onInsertedSemicolon) this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc);
2239 return true;
2240 }
2241};
2242
2243// Consume a semicolon, or, failing that, see if we are allowed to
2244// pretend that there is a semicolon at this position.
2245
2246pp.semicolon = function () {
2247 if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected();
2248};
2249
2250pp.afterTrailingComma = function (tokType) {
2251 if (this.type == tokType) {
2252 if (this.options.onTrailingComma) this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc);
2253 this.next();
2254 return true;
2255 }
2256};
2257
2258// Expect a token of a given type. If found, consume it, otherwise,
2259// raise an unexpected token error.
2260
2261pp.expect = function (type) {
2262 this.eat(type) || this.unexpected();
2263};
2264
2265// Raise an unexpected token error.
2266
2267pp.unexpected = function (pos) {
2268 this.raise(pos != null ? pos : this.start, "Unexpected token");
2269};
2270
2271},{"./state":13,"./tokentype":17,"./whitespace":19}],13:[function(_dereq_,module,exports){
2272"use strict";
2273
2274exports.Parser = Parser;
2275exports.__esModule = true;
2276
2277var _identifier = _dereq_("./identifier");
2278
2279var reservedWords = _identifier.reservedWords;
2280var keywords = _identifier.keywords;
2281
2282var tt = _dereq_("./tokentype").types;
2283
2284var lineBreak = _dereq_("./whitespace").lineBreak;
2285
2286function Parser(options, input, startPos) {
2287 this.options = options;
2288 this.sourceFile = this.options.sourceFile || null;
2289 this.isKeyword = keywords[this.options.ecmaVersion >= 6 ? 6 : 5];
2290 this.isReservedWord = reservedWords[this.options.ecmaVersion];
2291 this.input = input;
2292
2293 // Load plugins
2294 this.loadPlugins(this.options.plugins);
2295
2296 // Set up token state
2297
2298 // The current position of the tokenizer in the input.
2299 if (startPos) {
2300 this.pos = startPos;
2301 this.lineStart = Math.max(0, this.input.lastIndexOf("\n", startPos));
2302 this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
2303 } else {
2304 this.pos = this.lineStart = 0;
2305 this.curLine = 1;
2306 }
2307
2308 // Properties of the current token:
2309 // Its type
2310 this.type = tt.eof;
2311 // For tokens that include more information than their type, the value
2312 this.value = null;
2313 // Its start and end offset
2314 this.start = this.end = this.pos;
2315 // And, if locations are used, the {line, column} object
2316 // corresponding to those offsets
2317 this.startLoc = this.endLoc = null;
2318
2319 // Position information for the previous token
2320 this.lastTokEndLoc = this.lastTokStartLoc = null;
2321 this.lastTokStart = this.lastTokEnd = this.pos;
2322
2323 // The context stack is used to superficially track syntactic
2324 // context to predict whether a regular expression is allowed in a
2325 // given position.
2326 this.context = this.initialContext();
2327 this.exprAllowed = true;
2328
2329 // Figure out if it's a module code.
2330 this.strict = this.inModule = this.options.sourceType === "module";
2331
2332 // Used to signify the start of a potential arrow function
2333 this.potentialArrowAt = -1;
2334
2335 // Flags to track whether we are in a function, a generator.
2336 this.inFunction = this.inGenerator = false;
2337 // Labels in scope.
2338 this.labels = [];
2339
2340 // If enabled, skip leading hashbang line.
2341 if (this.pos === 0 && this.options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2);
2342}
2343
2344Parser.prototype.extend = function (name, f) {
2345 this[name] = f(this[name]);
2346};
2347
2348// Registered plugins
2349
2350var plugins = {};
2351
2352exports.plugins = plugins;
2353Parser.prototype.loadPlugins = function (plugins) {
2354 for (var _name in plugins) {
2355 var plugin = exports.plugins[_name];
2356 if (!plugin) throw new Error("Plugin '" + _name + "' not found");
2357 plugin(this, plugins[_name]);
2358 }
2359};
2360
2361},{"./identifier":7,"./tokentype":17,"./whitespace":19}],14:[function(_dereq_,module,exports){
2362"use strict";
2363
2364var tt = _dereq_("./tokentype").types;
2365
2366var Parser = _dereq_("./state").Parser;
2367
2368var lineBreak = _dereq_("./whitespace").lineBreak;
2369
2370var pp = Parser.prototype;
2371
2372// ### Statement parsing
2373
2374// Parse a program. Initializes the parser, reads any number of
2375// statements, and wraps them in a Program node. Optionally takes a
2376// `program` argument. If present, the statements will be appended
2377// to its body instead of creating a new node.
2378
2379pp.parseTopLevel = function (node) {
2380 var first = true;
2381 if (!node.body) node.body = [];
2382 while (this.type !== tt.eof) {
2383 var stmt = this.parseStatement(true, true);
2384 node.body.push(stmt);
2385 if (first && this.isUseStrict(stmt)) this.setStrict(true);
2386 first = false;
2387 }
2388 this.next();
2389 if (this.options.ecmaVersion >= 6) {
2390 node.sourceType = this.options.sourceType;
2391 }
2392 return this.finishNode(node, "Program");
2393};
2394
2395var loopLabel = { kind: "loop" },
2396 switchLabel = { kind: "switch" };
2397
2398// Parse a single statement.
2399//
2400// If expecting a statement and finding a slash operator, parse a
2401// regular expression literal. This is to handle cases like
2402// `if (foo) /blah/.exec(foo)`, where looking at the previous token
2403// does not help.
2404
2405pp.parseStatement = function (declaration, topLevel) {
2406 var starttype = this.type,
2407 node = this.startNode();
2408
2409 // Most types of statements are recognized by the keyword they
2410 // start with. Many are trivial to parse, some require a bit of
2411 // complexity.
2412
2413 switch (starttype) {
2414 case tt._break:case tt._continue:
2415 return this.parseBreakContinueStatement(node, starttype.keyword);
2416 case tt._debugger:
2417 return this.parseDebuggerStatement(node);
2418 case tt._do:
2419 return this.parseDoStatement(node);
2420 case tt._for:
2421 return this.parseForStatement(node);
2422 case tt._function:
2423 if (!declaration && this.options.ecmaVersion >= 6) this.unexpected();
2424 return this.parseFunctionStatement(node);
2425 case tt._class:
2426 if (!declaration) this.unexpected();
2427 return this.parseClass(node, true);
2428 case tt._if:
2429 return this.parseIfStatement(node);
2430 case tt._return:
2431 return this.parseReturnStatement(node);
2432 case tt._switch:
2433 return this.parseSwitchStatement(node);
2434 case tt._throw:
2435 return this.parseThrowStatement(node);
2436 case tt._try:
2437 return this.parseTryStatement(node);
2438 case tt._let:case tt._const:
2439 if (!declaration) this.unexpected(); // NOTE: falls through to _var
2440 case tt._var:
2441 return this.parseVarStatement(node, starttype);
2442 case tt._while:
2443 return this.parseWhileStatement(node);
2444 case tt._with:
2445 return this.parseWithStatement(node);
2446 case tt.braceL:
2447 return this.parseBlock();
2448 case tt.semi:
2449 return this.parseEmptyStatement(node);
2450 case tt._export:
2451 case tt._import:
2452 if (!this.options.allowImportExportEverywhere) {
2453 if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level");
2454 if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'");
2455 }
2456 return starttype === tt._import ? this.parseImport(node) : this.parseExport(node);
2457
2458 // If the statement does not start with a statement keyword or a
2459 // brace, it's an ExpressionStatement or LabeledStatement. We
2460 // simply start parsing an expression, and afterwards, if the
2461 // next token is a colon and the expression was a simple
2462 // Identifier node, we switch to interpreting it as a label.
2463 default:
2464 var maybeName = this.value,
2465 expr = this.parseExpression();
2466 if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) return this.parseLabeledStatement(node, maybeName, expr);else return this.parseExpressionStatement(node, expr);
2467 }
2468};
2469
2470pp.parseBreakContinueStatement = function (node, keyword) {
2471 var isBreak = keyword == "break";
2472 this.next();
2473 if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null;else if (this.type !== tt.name) this.unexpected();else {
2474 node.label = this.parseIdent();
2475 this.semicolon();
2476 }
2477
2478 // Verify that there is an actual destination to break or
2479 // continue to.
2480 for (var i = 0; i < this.labels.length; ++i) {
2481 var lab = this.labels[i];
2482 if (node.label == null || lab.name === node.label.name) {
2483 if (lab.kind != null && (isBreak || lab.kind === "loop")) break;
2484 if (node.label && isBreak) break;
2485 }
2486 }
2487 if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword);
2488 return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
2489};
2490
2491pp.parseDebuggerStatement = function (node) {
2492 this.next();
2493 this.semicolon();
2494 return this.finishNode(node, "DebuggerStatement");
2495};
2496
2497pp.parseDoStatement = function (node) {
2498 this.next();
2499 this.labels.push(loopLabel);
2500 node.body = this.parseStatement(false);
2501 this.labels.pop();
2502 this.expect(tt._while);
2503 node.test = this.parseParenExpression();
2504 if (this.options.ecmaVersion >= 6) this.eat(tt.semi);else this.semicolon();
2505 return this.finishNode(node, "DoWhileStatement");
2506};
2507
2508// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
2509// loop is non-trivial. Basically, we have to parse the init `var`
2510// statement or expression, disallowing the `in` operator (see
2511// the second parameter to `parseExpression`), and then check
2512// whether the next token is `in` or `of`. When there is no init
2513// part (semicolon immediately after the opening parenthesis), it
2514// is a regular `for` loop.
2515
2516pp.parseForStatement = function (node) {
2517 this.next();
2518 this.labels.push(loopLabel);
2519 this.expect(tt.parenL);
2520 if (this.type === tt.semi) return this.parseFor(node, null);
2521 if (this.type === tt._var || this.type === tt._let || this.type === tt._const) {
2522 var _init = this.startNode(),
2523 varKind = this.type;
2524 this.next();
2525 this.parseVar(_init, true, varKind);
2526 this.finishNode(_init, "VariableDeclaration");
2527 if ((this.type === tt._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && _init.declarations.length === 1 && !(varKind !== tt._var && _init.declarations[0].init)) return this.parseForIn(node, _init);
2528 return this.parseFor(node, _init);
2529 }
2530 var refShorthandDefaultPos = { start: 0 };
2531 var init = this.parseExpression(true, refShorthandDefaultPos);
2532 if (this.type === tt._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) {
2533 this.toAssignable(init);
2534 this.checkLVal(init);
2535 return this.parseForIn(node, init);
2536 } else if (refShorthandDefaultPos.start) {
2537 this.unexpected(refShorthandDefaultPos.start);
2538 }
2539 return this.parseFor(node, init);
2540};
2541
2542pp.parseFunctionStatement = function (node) {
2543 this.next();
2544 return this.parseFunction(node, true);
2545};
2546
2547pp.parseIfStatement = function (node) {
2548 this.next();
2549 node.test = this.parseParenExpression();
2550 node.consequent = this.parseStatement(false);
2551 node.alternate = this.eat(tt._else) ? this.parseStatement(false) : null;
2552 return this.finishNode(node, "IfStatement");
2553};
2554
2555pp.parseReturnStatement = function (node) {
2556 if (!this.inFunction && !this.options.allowReturnOutsideFunction) this.raise(this.start, "'return' outside of function");
2557 this.next();
2558
2559 // In `return` (and `break`/`continue`), the keywords with
2560 // optional arguments, we eagerly look for a semicolon or the
2561 // possibility to insert one.
2562
2563 if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null;else {
2564 node.argument = this.parseExpression();this.semicolon();
2565 }
2566 return this.finishNode(node, "ReturnStatement");
2567};
2568
2569pp.parseSwitchStatement = function (node) {
2570 this.next();
2571 node.discriminant = this.parseParenExpression();
2572 node.cases = [];
2573 this.expect(tt.braceL);
2574 this.labels.push(switchLabel);
2575
2576 // Statements under must be grouped (by label) in SwitchCase
2577 // nodes. `cur` is used to keep the node that we are currently
2578 // adding statements to.
2579
2580 for (var cur, sawDefault; this.type != tt.braceR;) {
2581 if (this.type === tt._case || this.type === tt._default) {
2582 var isCase = this.type === tt._case;
2583 if (cur) this.finishNode(cur, "SwitchCase");
2584 node.cases.push(cur = this.startNode());
2585 cur.consequent = [];
2586 this.next();
2587 if (isCase) {
2588 cur.test = this.parseExpression();
2589 } else {
2590 if (sawDefault) this.raise(this.lastTokStart, "Multiple default clauses");
2591 sawDefault = true;
2592 cur.test = null;
2593 }
2594 this.expect(tt.colon);
2595 } else {
2596 if (!cur) this.unexpected();
2597 cur.consequent.push(this.parseStatement(true));
2598 }
2599 }
2600 if (cur) this.finishNode(cur, "SwitchCase");
2601 this.next(); // Closing brace
2602 this.labels.pop();
2603 return this.finishNode(node, "SwitchStatement");
2604};
2605
2606pp.parseThrowStatement = function (node) {
2607 this.next();
2608 if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) this.raise(this.lastTokEnd, "Illegal newline after throw");
2609 node.argument = this.parseExpression();
2610 this.semicolon();
2611 return this.finishNode(node, "ThrowStatement");
2612};
2613
2614// Reused empty array added for node fields that are always empty.
2615
2616var empty = [];
2617
2618pp.parseTryStatement = function (node) {
2619 this.next();
2620 node.block = this.parseBlock();
2621 node.handler = null;
2622 if (this.type === tt._catch) {
2623 var clause = this.startNode();
2624 this.next();
2625 this.expect(tt.parenL);
2626 clause.param = this.parseBindingAtom();
2627 this.checkLVal(clause.param, true);
2628 this.expect(tt.parenR);
2629 clause.guard = null;
2630 clause.body = this.parseBlock();
2631 node.handler = this.finishNode(clause, "CatchClause");
2632 }
2633 node.guardedHandlers = empty;
2634 node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null;
2635 if (!node.handler && !node.finalizer) this.raise(node.start, "Missing catch or finally clause");
2636 return this.finishNode(node, "TryStatement");
2637};
2638
2639pp.parseVarStatement = function (node, kind) {
2640 this.next();
2641 this.parseVar(node, false, kind);
2642 this.semicolon();
2643 return this.finishNode(node, "VariableDeclaration");
2644};
2645
2646pp.parseWhileStatement = function (node) {
2647 this.next();
2648 node.test = this.parseParenExpression();
2649 this.labels.push(loopLabel);
2650 node.body = this.parseStatement(false);
2651 this.labels.pop();
2652 return this.finishNode(node, "WhileStatement");
2653};
2654
2655pp.parseWithStatement = function (node) {
2656 if (this.strict) this.raise(this.start, "'with' in strict mode");
2657 this.next();
2658 node.object = this.parseParenExpression();
2659 node.body = this.parseStatement(false);
2660 return this.finishNode(node, "WithStatement");
2661};
2662
2663pp.parseEmptyStatement = function (node) {
2664 this.next();
2665 return this.finishNode(node, "EmptyStatement");
2666};
2667
2668pp.parseLabeledStatement = function (node, maybeName, expr) {
2669 for (var i = 0; i < this.labels.length; ++i) {
2670 if (this.labels[i].name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared");
2671 }var kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null;
2672 this.labels.push({ name: maybeName, kind: kind });
2673 node.body = this.parseStatement(true);
2674 this.labels.pop();
2675 node.label = expr;
2676 return this.finishNode(node, "LabeledStatement");
2677};
2678
2679pp.parseExpressionStatement = function (node, expr) {
2680 node.expression = expr;
2681 this.semicolon();
2682 return this.finishNode(node, "ExpressionStatement");
2683};
2684
2685// Parse a semicolon-enclosed block of statements, handling `"use
2686// strict"` declarations when `allowStrict` is true (used for
2687// function bodies).
2688
2689pp.parseBlock = function (allowStrict) {
2690 var node = this.startNode(),
2691 first = true,
2692 oldStrict = undefined;
2693 node.body = [];
2694 this.expect(tt.braceL);
2695 while (!this.eat(tt.braceR)) {
2696 var stmt = this.parseStatement(true);
2697 node.body.push(stmt);
2698 if (first && allowStrict && this.isUseStrict(stmt)) {
2699 oldStrict = this.strict;
2700 this.setStrict(this.strict = true);
2701 }
2702 first = false;
2703 }
2704 if (oldStrict === false) this.setStrict(false);
2705 return this.finishNode(node, "BlockStatement");
2706};
2707
2708// Parse a regular `for` loop. The disambiguation code in
2709// `parseStatement` will already have parsed the init statement or
2710// expression.
2711
2712pp.parseFor = function (node, init) {
2713 node.init = init;
2714 this.expect(tt.semi);
2715 node.test = this.type === tt.semi ? null : this.parseExpression();
2716 this.expect(tt.semi);
2717 node.update = this.type === tt.parenR ? null : this.parseExpression();
2718 this.expect(tt.parenR);
2719 node.body = this.parseStatement(false);
2720 this.labels.pop();
2721 return this.finishNode(node, "ForStatement");
2722};
2723
2724// Parse a `for`/`in` and `for`/`of` loop, which are almost
2725// same from parser's perspective.
2726
2727pp.parseForIn = function (node, init) {
2728 var type = this.type === tt._in ? "ForInStatement" : "ForOfStatement";
2729 this.next();
2730 node.left = init;
2731 node.right = this.parseExpression();
2732 this.expect(tt.parenR);
2733 node.body = this.parseStatement(false);
2734 this.labels.pop();
2735 return this.finishNode(node, type);
2736};
2737
2738// Parse a list of variable declarations.
2739
2740pp.parseVar = function (node, isFor, kind) {
2741 node.declarations = [];
2742 node.kind = kind.keyword;
2743 for (;;) {
2744 var decl = this.startNode();
2745 this.parseVarId(decl);
2746 if (this.eat(tt.eq)) {
2747 decl.init = this.parseMaybeAssign(isFor);
2748 } else if (kind === tt._const && !(this.type === tt._in || this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
2749 this.unexpected();
2750 } else if (decl.id.type != "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) {
2751 this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
2752 } else {
2753 decl.init = null;
2754 }
2755 node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
2756 if (!this.eat(tt.comma)) break;
2757 }
2758 return node;
2759};
2760
2761pp.parseVarId = function (decl) {
2762 decl.id = this.parseBindingAtom();
2763 this.checkLVal(decl.id, true);
2764};
2765
2766// Parse a function declaration or literal (depending on the
2767// `isStatement` parameter).
2768
2769pp.parseFunction = function (node, isStatement, allowExpressionBody) {
2770 this.initFunction(node);
2771 if (this.options.ecmaVersion >= 6) node.generator = this.eat(tt.star);
2772 if (isStatement || this.type === tt.name) node.id = this.parseIdent();
2773 this.parseFunctionParams(node);
2774 this.parseFunctionBody(node, allowExpressionBody);
2775 return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
2776};
2777
2778pp.parseFunctionParams = function (node) {
2779 this.expect(tt.parenL);
2780 node.params = this.parseBindingList(tt.parenR, false, false);
2781};
2782
2783// Parse a class declaration or literal (depending on the
2784// `isStatement` parameter).
2785
2786pp.parseClass = function (node, isStatement) {
2787 this.next();
2788 this.parseClassId(node, isStatement);
2789 this.parseClassSuper(node);
2790 var classBody = this.startNode();
2791 var hadConstructor = false;
2792 classBody.body = [];
2793 this.expect(tt.braceL);
2794 while (!this.eat(tt.braceR)) {
2795 if (this.eat(tt.semi)) continue;
2796 var method = this.startNode();
2797 var isGenerator = this.eat(tt.star);
2798 var isMaybeStatic = this.type === tt.name && this.value === "static";
2799 this.parsePropertyName(method);
2800 method["static"] = isMaybeStatic && this.type !== tt.parenL;
2801 if (method["static"]) {
2802 if (isGenerator) this.unexpected();
2803 isGenerator = this.eat(tt.star);
2804 this.parsePropertyName(method);
2805 }
2806 method.kind = "method";
2807 if (!method.computed) {
2808 var key = method.key;
2809
2810 var isGetSet = false;
2811 if (!isGenerator && key.type === "Identifier" && this.type !== tt.parenL && (key.name === "get" || key.name === "set")) {
2812 isGetSet = true;
2813 method.kind = key.name;
2814 key = this.parsePropertyName(method);
2815 }
2816 if (!method["static"] && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) {
2817 if (hadConstructor) this.raise(key.start, "Duplicate constructor in the same class");
2818 if (isGetSet) this.raise(key.start, "Constructor can't have get/set modifier");
2819 if (isGenerator) this.raise(key.start, "Constructor can't be a generator");
2820 method.kind = "constructor";
2821 hadConstructor = true;
2822 }
2823 }
2824 this.parseClassMethod(classBody, method, isGenerator);
2825 }
2826 node.body = this.finishNode(classBody, "ClassBody");
2827 return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
2828};
2829
2830pp.parseClassMethod = function (classBody, method, isGenerator) {
2831 method.value = this.parseMethod(isGenerator);
2832 classBody.body.push(this.finishNode(method, "MethodDefinition"));
2833};
2834
2835pp.parseClassId = function (node, isStatement) {
2836 node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null;
2837};
2838
2839pp.parseClassSuper = function (node) {
2840 node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null;
2841};
2842
2843// Parses module export declaration.
2844
2845pp.parseExport = function (node) {
2846 this.next();
2847 // export * from '...'
2848 if (this.eat(tt.star)) {
2849 this.expectContextual("from");
2850 node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
2851 this.semicolon();
2852 return this.finishNode(node, "ExportAllDeclaration");
2853 }
2854 if (this.eat(tt._default)) {
2855 // export default ...
2856 var expr = this.parseMaybeAssign();
2857 var needsSemi = true;
2858 if (expr.type == "FunctionExpression" || expr.type == "ClassExpression") {
2859 needsSemi = false;
2860 if (expr.id) {
2861 expr.type = expr.type == "FunctionExpression" ? "FunctionDeclaration" : "ClassDeclaration";
2862 }
2863 }
2864 node.declaration = expr;
2865 if (needsSemi) this.semicolon();
2866 return this.finishNode(node, "ExportDefaultDeclaration");
2867 }
2868 // export var|const|let|function|class ...
2869 if (this.shouldParseExportStatement()) {
2870 node.declaration = this.parseStatement(true);
2871 node.specifiers = [];
2872 node.source = null;
2873 } else {
2874 // export { x, y as z } [from '...']
2875 node.declaration = null;
2876 node.specifiers = this.parseExportSpecifiers();
2877 if (this.eatContextual("from")) {
2878 node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
2879 } else {
2880 node.source = null;
2881 }
2882 this.semicolon();
2883 }
2884 return this.finishNode(node, "ExportNamedDeclaration");
2885};
2886
2887pp.shouldParseExportStatement = function () {
2888 return this.type.keyword;
2889};
2890
2891// Parses a comma-separated list of module exports.
2892
2893pp.parseExportSpecifiers = function () {
2894 var nodes = [],
2895 first = true;
2896 // export { x, y as z } [from '...']
2897 this.expect(tt.braceL);
2898 while (!this.eat(tt.braceR)) {
2899 if (!first) {
2900 this.expect(tt.comma);
2901 if (this.afterTrailingComma(tt.braceR)) break;
2902 } else first = false;
2903
2904 var node = this.startNode();
2905 node.local = this.parseIdent(this.type === tt._default);
2906 node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local;
2907 nodes.push(this.finishNode(node, "ExportSpecifier"));
2908 }
2909 return nodes;
2910};
2911
2912// Parses import declaration.
2913
2914pp.parseImport = function (node) {
2915 this.next();
2916 // import '...'
2917 if (this.type === tt.string) {
2918 node.specifiers = empty;
2919 node.source = this.parseExprAtom();
2920 node.kind = "";
2921 } else {
2922 node.specifiers = this.parseImportSpecifiers();
2923 this.expectContextual("from");
2924 node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
2925 }
2926 this.semicolon();
2927 return this.finishNode(node, "ImportDeclaration");
2928};
2929
2930// Parses a comma-separated list of module imports.
2931
2932pp.parseImportSpecifiers = function () {
2933 var nodes = [],
2934 first = true;
2935 if (this.type === tt.name) {
2936 // import defaultObj, { x, y as z } from '...'
2937 var node = this.startNode();
2938 node.local = this.parseIdent();
2939 this.checkLVal(node.local, true);
2940 nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
2941 if (!this.eat(tt.comma)) return nodes;
2942 }
2943 if (this.type === tt.star) {
2944 var node = this.startNode();
2945 this.next();
2946 this.expectContextual("as");
2947 node.local = this.parseIdent();
2948 this.checkLVal(node.local, true);
2949 nodes.push(this.finishNode(node, "ImportNamespaceSpecifier"));
2950 return nodes;
2951 }
2952 this.expect(tt.braceL);
2953 while (!this.eat(tt.braceR)) {
2954 if (!first) {
2955 this.expect(tt.comma);
2956 if (this.afterTrailingComma(tt.braceR)) break;
2957 } else first = false;
2958
2959 var node = this.startNode();
2960 node.imported = this.parseIdent(true);
2961 node.local = this.eatContextual("as") ? this.parseIdent() : node.imported;
2962 this.checkLVal(node.local, true);
2963 nodes.push(this.finishNode(node, "ImportSpecifier"));
2964 }
2965 return nodes;
2966};
2967
2968},{"./state":13,"./tokentype":17,"./whitespace":19}],15:[function(_dereq_,module,exports){
2969"use strict";
2970
2971var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
2972
2973exports.__esModule = true;
2974// The algorithm used to determine whether a regexp can appear at a
2975// given point in the program is loosely based on sweet.js' approach.
2976// See https://github.com/mozilla/sweet.js/wiki/design
2977
2978var Parser = _dereq_("./state").Parser;
2979
2980var tt = _dereq_("./tokentype").types;
2981
2982var lineBreak = _dereq_("./whitespace").lineBreak;
2983
2984var TokContext = exports.TokContext = function TokContext(token, isExpr, preserveSpace, override) {
2985 _classCallCheck(this, TokContext);
2986
2987 this.token = token;
2988 this.isExpr = isExpr;
2989 this.preserveSpace = preserveSpace;
2990 this.override = override;
2991};
2992
2993var types = {
2994 b_stat: new TokContext("{", false),
2995 b_expr: new TokContext("{", true),
2996 b_tmpl: new TokContext("${", true),
2997 p_stat: new TokContext("(", false),
2998 p_expr: new TokContext("(", true),
2999 q_tmpl: new TokContext("`", true, true, function (p) {
3000 return p.readTmplToken();
3001 }),
3002 f_expr: new TokContext("function", true)
3003};
3004
3005exports.types = types;
3006var pp = Parser.prototype;
3007
3008pp.initialContext = function () {
3009 return [types.b_stat];
3010};
3011
3012pp.braceIsBlock = function (prevType) {
3013 var parent = undefined;
3014 if (prevType === tt.colon && (parent = this.curContext()).token == "{") return !parent.isExpr;
3015 if (prevType === tt._return) return lineBreak.test(this.input.slice(this.lastTokEnd, this.start));
3016 if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof) return true;
3017 if (prevType == tt.braceL) return this.curContext() === types.b_stat;
3018 return !this.exprAllowed;
3019};
3020
3021pp.updateContext = function (prevType) {
3022 var update = undefined,
3023 type = this.type;
3024 if (type.keyword && prevType == tt.dot) this.exprAllowed = false;else if (update = type.updateContext) update.call(this, prevType);else this.exprAllowed = type.beforeExpr;
3025};
3026
3027// Token-specific context update code
3028
3029tt.parenR.updateContext = tt.braceR.updateContext = function () {
3030 if (this.context.length == 1) {
3031 this.exprAllowed = true;
3032 return;
3033 }
3034 var out = this.context.pop();
3035 if (out === types.b_stat && this.curContext() === types.f_expr) {
3036 this.context.pop();
3037 this.exprAllowed = false;
3038 } else if (out === types.b_tmpl) {
3039 this.exprAllowed = true;
3040 } else {
3041 this.exprAllowed = !out.isExpr;
3042 }
3043};
3044
3045tt.braceL.updateContext = function (prevType) {
3046 this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr);
3047 this.exprAllowed = true;
3048};
3049
3050tt.dollarBraceL.updateContext = function () {
3051 this.context.push(types.b_tmpl);
3052 this.exprAllowed = true;
3053};
3054
3055tt.parenL.updateContext = function (prevType) {
3056 var statementParens = prevType === tt._if || prevType === tt._for || prevType === tt._with || prevType === tt._while;
3057 this.context.push(statementParens ? types.p_stat : types.p_expr);
3058 this.exprAllowed = true;
3059};
3060
3061tt.incDec.updateContext = function () {};
3062
3063tt._function.updateContext = function () {
3064 if (this.curContext() !== types.b_stat) this.context.push(types.f_expr);
3065 this.exprAllowed = false;
3066};
3067
3068tt.backQuote.updateContext = function () {
3069 if (this.curContext() === types.q_tmpl) this.context.pop();else this.context.push(types.q_tmpl);
3070 this.exprAllowed = false;
3071};
3072
3073// tokExprAllowed stays unchanged
3074
3075},{"./state":13,"./tokentype":17,"./whitespace":19}],16:[function(_dereq_,module,exports){
3076"use strict";
3077
3078var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
3079
3080exports.__esModule = true;
3081
3082var _identifier = _dereq_("./identifier");
3083
3084var isIdentifierStart = _identifier.isIdentifierStart;
3085var isIdentifierChar = _identifier.isIdentifierChar;
3086
3087var _tokentype = _dereq_("./tokentype");
3088
3089var tt = _tokentype.types;
3090var keywordTypes = _tokentype.keywords;
3091
3092var Parser = _dereq_("./state").Parser;
3093
3094var SourceLocation = _dereq_("./location").SourceLocation;
3095
3096var _whitespace = _dereq_("./whitespace");
3097
3098var lineBreak = _whitespace.lineBreak;
3099var lineBreakG = _whitespace.lineBreakG;
3100var isNewLine = _whitespace.isNewLine;
3101var nonASCIIwhitespace = _whitespace.nonASCIIwhitespace;
3102
3103// Object type used to represent tokens. Note that normally, tokens
3104// simply exist as properties on the parser object. This is only
3105// used for the onToken callback and the external tokenizer.
3106
3107var Token = exports.Token = function Token(p) {
3108 _classCallCheck(this, Token);
3109
3110 this.type = p.type;
3111 this.value = p.value;
3112 this.start = p.start;
3113 this.end = p.end;
3114 if (p.options.locations) this.loc = new SourceLocation(p, p.startLoc, p.endLoc);
3115 if (p.options.ranges) this.range = [p.start, p.end];
3116};
3117
3118// ## Tokenizer
3119
3120var pp = Parser.prototype;
3121
3122// Are we running under Rhino?
3123var isRhino = typeof Packages !== "undefined";
3124
3125// Move to the next token
3126
3127pp.next = function () {
3128 if (this.options.onToken) this.options.onToken(new Token(this));
3129
3130 this.lastTokEnd = this.end;
3131 this.lastTokStart = this.start;
3132 this.lastTokEndLoc = this.endLoc;
3133 this.lastTokStartLoc = this.startLoc;
3134 this.nextToken();
3135};
3136
3137pp.getToken = function () {
3138 this.next();
3139 return new Token(this);
3140};
3141
3142// If we're in an ES6 environment, make parsers iterable
3143if (typeof Symbol !== "undefined") pp[Symbol.iterator] = function () {
3144 var self = this;
3145 return { next: function next() {
3146 var token = self.getToken();
3147 return {
3148 done: token.type === tt.eof,
3149 value: token
3150 };
3151 } };
3152};
3153
3154// Toggle strict mode. Re-reads the next number or string to please
3155// pedantic tests (`"use strict"; 010;` should fail).
3156
3157pp.setStrict = function (strict) {
3158 this.strict = strict;
3159 if (this.type !== tt.num && this.type !== tt.string) return;
3160 this.pos = this.start;
3161 if (this.options.locations) {
3162 while (this.pos < this.lineStart) {
3163 this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1;
3164 --this.curLine;
3165 }
3166 }
3167 this.nextToken();
3168};
3169
3170pp.curContext = function () {
3171 return this.context[this.context.length - 1];
3172};
3173
3174// Read a single token, updating the parser object's token-related
3175// properties.
3176
3177pp.nextToken = function () {
3178 var curContext = this.curContext();
3179 if (!curContext || !curContext.preserveSpace) this.skipSpace();
3180
3181 this.start = this.pos;
3182 if (this.options.locations) this.startLoc = this.curPosition();
3183 if (this.pos >= this.input.length) return this.finishToken(tt.eof);
3184
3185 if (curContext.override) return curContext.override(this);else this.readToken(this.fullCharCodeAtPos());
3186};
3187
3188pp.readToken = function (code) {
3189 // Identifier or keyword. '\uXXXX' sequences are allowed in
3190 // identifiers, so '\' also dispatches to that.
3191 if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) return this.readWord();
3192
3193 return this.getTokenFromCode(code);
3194};
3195
3196pp.fullCharCodeAtPos = function () {
3197 var code = this.input.charCodeAt(this.pos);
3198 if (code <= 55295 || code >= 57344) return code;
3199 var next = this.input.charCodeAt(this.pos + 1);
3200 return (code << 10) + next - 56613888;
3201};
3202
3203pp.skipBlockComment = function () {
3204 var startLoc = this.options.onComment && this.options.locations && this.curPosition();
3205 var start = this.pos,
3206 end = this.input.indexOf("*/", this.pos += 2);
3207 if (end === -1) this.raise(this.pos - 2, "Unterminated comment");
3208 this.pos = end + 2;
3209 if (this.options.locations) {
3210 lineBreakG.lastIndex = start;
3211 var match = undefined;
3212 while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
3213 ++this.curLine;
3214 this.lineStart = match.index + match[0].length;
3215 }
3216 }
3217 if (this.options.onComment) this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, startLoc, this.options.locations && this.curPosition());
3218};
3219
3220pp.skipLineComment = function (startSkip) {
3221 var start = this.pos;
3222 var startLoc = this.options.onComment && this.options.locations && this.curPosition();
3223 var ch = this.input.charCodeAt(this.pos += startSkip);
3224 while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
3225 ++this.pos;
3226 ch = this.input.charCodeAt(this.pos);
3227 }
3228 if (this.options.onComment) this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, startLoc, this.options.locations && this.curPosition());
3229};
3230
3231// Called at the start of the parse and after every token. Skips
3232// whitespace and comments, and.
3233
3234pp.skipSpace = function () {
3235 while (this.pos < this.input.length) {
3236 var ch = this.input.charCodeAt(this.pos);
3237 if (ch === 32) {
3238 // ' '
3239 ++this.pos;
3240 } else if (ch === 13) {
3241 ++this.pos;
3242 var next = this.input.charCodeAt(this.pos);
3243 if (next === 10) {
3244 ++this.pos;
3245 }
3246 if (this.options.locations) {
3247 ++this.curLine;
3248 this.lineStart = this.pos;
3249 }
3250 } else if (ch === 10 || ch === 8232 || ch === 8233) {
3251 ++this.pos;
3252 if (this.options.locations) {
3253 ++this.curLine;
3254 this.lineStart = this.pos;
3255 }
3256 } else if (ch > 8 && ch < 14) {
3257 ++this.pos;
3258 } else if (ch === 47) {
3259 // '/'
3260 var next = this.input.charCodeAt(this.pos + 1);
3261 if (next === 42) {
3262 // '*'
3263 this.skipBlockComment();
3264 } else if (next === 47) {
3265 // '/'
3266 this.skipLineComment(2);
3267 } else break;
3268 } else if (ch === 160) {
3269 // '\xa0'
3270 ++this.pos;
3271 } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
3272 ++this.pos;
3273 } else {
3274 break;
3275 }
3276 }
3277};
3278
3279// Called at the end of every token. Sets `end`, `val`, and
3280// maintains `context` and `exprAllowed`, and skips the space after
3281// the token, so that the next one's `start` will point at the
3282// right position.
3283
3284pp.finishToken = function (type, val) {
3285 this.end = this.pos;
3286 if (this.options.locations) this.endLoc = this.curPosition();
3287 var prevType = this.type;
3288 this.type = type;
3289 this.value = val;
3290
3291 this.updateContext(prevType);
3292};
3293
3294// ### Token reading
3295
3296// This is the function that is called to fetch the next token. It
3297// is somewhat obscure, because it works in character codes rather
3298// than characters, and because operator parsing has been inlined
3299// into it.
3300//
3301// All in the name of speed.
3302//
3303pp.readToken_dot = function () {
3304 var next = this.input.charCodeAt(this.pos + 1);
3305 if (next >= 48 && next <= 57) return this.readNumber(true);
3306 var next2 = this.input.charCodeAt(this.pos + 2);
3307 if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) {
3308 // 46 = dot '.'
3309 this.pos += 3;
3310 return this.finishToken(tt.ellipsis);
3311 } else {
3312 ++this.pos;
3313 return this.finishToken(tt.dot);
3314 }
3315};
3316
3317pp.readToken_slash = function () {
3318 // '/'
3319 var next = this.input.charCodeAt(this.pos + 1);
3320 if (this.exprAllowed) {
3321 ++this.pos;return this.readRegexp();
3322 }
3323 if (next === 61) return this.finishOp(tt.assign, 2);
3324 return this.finishOp(tt.slash, 1);
3325};
3326
3327pp.readToken_mult_modulo = function (code) {
3328 // '%*'
3329 var next = this.input.charCodeAt(this.pos + 1);
3330 if (next === 61) return this.finishOp(tt.assign, 2);
3331 return this.finishOp(code === 42 ? tt.star : tt.modulo, 1);
3332};
3333
3334pp.readToken_pipe_amp = function (code) {
3335 // '|&'
3336 var next = this.input.charCodeAt(this.pos + 1);
3337 if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2);
3338 if (next === 61) return this.finishOp(tt.assign, 2);
3339 return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1);
3340};
3341
3342pp.readToken_caret = function () {
3343 // '^'
3344 var next = this.input.charCodeAt(this.pos + 1);
3345 if (next === 61) return this.finishOp(tt.assign, 2);
3346 return this.finishOp(tt.bitwiseXOR, 1);
3347};
3348
3349pp.readToken_plus_min = function (code) {
3350 // '+-'
3351 var next = this.input.charCodeAt(this.pos + 1);
3352 if (next === code) {
3353 if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 && lineBreak.test(this.input.slice(this.lastTokEnd, this.pos))) {
3354 // A `-->` line comment
3355 this.skipLineComment(3);
3356 this.skipSpace();
3357 return this.nextToken();
3358 }
3359 return this.finishOp(tt.incDec, 2);
3360 }
3361 if (next === 61) return this.finishOp(tt.assign, 2);
3362 return this.finishOp(tt.plusMin, 1);
3363};
3364
3365pp.readToken_lt_gt = function (code) {
3366 // '<>'
3367 var next = this.input.charCodeAt(this.pos + 1);
3368 var size = 1;
3369 if (next === code) {
3370 size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
3371 if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1);
3372 return this.finishOp(tt.bitShift, size);
3373 }
3374 if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 && this.input.charCodeAt(this.pos + 3) == 45) {
3375 if (this.inModule) this.unexpected();
3376 // `<!--`, an XML-style comment that should be interpreted as a line comment
3377 this.skipLineComment(4);
3378 this.skipSpace();
3379 return this.nextToken();
3380 }
3381 if (next === 61) size = this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2;
3382 return this.finishOp(tt.relational, size);
3383};
3384
3385pp.readToken_eq_excl = function (code) {
3386 // '=!'
3387 var next = this.input.charCodeAt(this.pos + 1);
3388 if (next === 61) return this.finishOp(tt.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2);
3389 if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) {
3390 // '=>'
3391 this.pos += 2;
3392 return this.finishToken(tt.arrow);
3393 }
3394 return this.finishOp(code === 61 ? tt.eq : tt.prefix, 1);
3395};
3396
3397pp.getTokenFromCode = function (code) {
3398 switch (code) {
3399 // The interpretation of a dot depends on whether it is followed
3400 // by a digit or another two dots.
3401 case 46:
3402 // '.'
3403 return this.readToken_dot();
3404
3405 // Punctuation tokens.
3406 case 40:
3407 ++this.pos;return this.finishToken(tt.parenL);
3408 case 41:
3409 ++this.pos;return this.finishToken(tt.parenR);
3410 case 59:
3411 ++this.pos;return this.finishToken(tt.semi);
3412 case 44:
3413 ++this.pos;return this.finishToken(tt.comma);
3414 case 91:
3415 ++this.pos;return this.finishToken(tt.bracketL);
3416 case 93:
3417 ++this.pos;return this.finishToken(tt.bracketR);
3418 case 123:
3419 ++this.pos;return this.finishToken(tt.braceL);
3420 case 125:
3421 ++this.pos;return this.finishToken(tt.braceR);
3422 case 58:
3423 ++this.pos;return this.finishToken(tt.colon);
3424 case 63:
3425 ++this.pos;return this.finishToken(tt.question);
3426
3427 case 96:
3428 // '`'
3429 if (this.options.ecmaVersion < 6) break;
3430 ++this.pos;
3431 return this.finishToken(tt.backQuote);
3432
3433 case 48:
3434 // '0'
3435 var next = this.input.charCodeAt(this.pos + 1);
3436 if (next === 120 || next === 88) return this.readRadixNumber(16); // '0x', '0X' - hex number
3437 if (this.options.ecmaVersion >= 6) {
3438 if (next === 111 || next === 79) return this.readRadixNumber(8); // '0o', '0O' - octal number
3439 if (next === 98 || next === 66) return this.readRadixNumber(2); // '0b', '0B' - binary number
3440 }
3441 // Anything else beginning with a digit is an integer, octal
3442 // number, or float.
3443 case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:
3444 // 1-9
3445 return this.readNumber(false);
3446
3447 // Quotes produce strings.
3448 case 34:case 39:
3449 // '"', "'"
3450 return this.readString(code);
3451
3452 // Operators are parsed inline in tiny state machines. '=' (61) is
3453 // often referred to. `finishOp` simply skips the amount of
3454 // characters it is given as second argument, and returns a token
3455 // of the type given by its first argument.
3456
3457 case 47:
3458 // '/'
3459 return this.readToken_slash();
3460
3461 case 37:case 42:
3462 // '%*'
3463 return this.readToken_mult_modulo(code);
3464
3465 case 124:case 38:
3466 // '|&'
3467 return this.readToken_pipe_amp(code);
3468
3469 case 94:
3470 // '^'
3471 return this.readToken_caret();
3472
3473 case 43:case 45:
3474 // '+-'
3475 return this.readToken_plus_min(code);
3476
3477 case 60:case 62:
3478 // '<>'
3479 return this.readToken_lt_gt(code);
3480
3481 case 61:case 33:
3482 // '=!'
3483 return this.readToken_eq_excl(code);
3484
3485 case 126:
3486 // '~'
3487 return this.finishOp(tt.prefix, 1);
3488 }
3489
3490 this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
3491};
3492
3493pp.finishOp = function (type, size) {
3494 var str = this.input.slice(this.pos, this.pos + size);
3495 this.pos += size;
3496 return this.finishToken(type, str);
3497};
3498
3499var regexpUnicodeSupport = false;
3500try {
3501 new RegExp("￿", "u");regexpUnicodeSupport = true;
3502} catch (e) {}
3503
3504// Parse a regular expression. Some context-awareness is necessary,
3505// since a '/' inside a '[]' set does not end the expression.
3506
3507pp.readRegexp = function () {
3508 var escaped = undefined,
3509 inClass = undefined,
3510 start = this.pos;
3511 for (;;) {
3512 if (this.pos >= this.input.length) this.raise(start, "Unterminated regular expression");
3513 var ch = this.input.charAt(this.pos);
3514 if (lineBreak.test(ch)) this.raise(start, "Unterminated regular expression");
3515 if (!escaped) {
3516 if (ch === "[") inClass = true;else if (ch === "]" && inClass) inClass = false;else if (ch === "/" && !inClass) break;
3517 escaped = ch === "\\";
3518 } else escaped = false;
3519 ++this.pos;
3520 }
3521 var content = this.input.slice(start, this.pos);
3522 ++this.pos;
3523 // Need to use `readWord1` because '\uXXXX' sequences are allowed
3524 // here (don't ask).
3525 var mods = this.readWord1();
3526 var tmp = content;
3527 if (mods) {
3528 var validFlags = /^[gmsiy]*$/;
3529 if (this.options.ecmaVersion >= 6) validFlags = /^[gmsiyu]*$/;
3530 if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag");
3531 if (mods.indexOf("u") >= 0 && !regexpUnicodeSupport) {
3532 // Replace each astral symbol and every Unicode escape sequence that
3533 // possibly represents an astral symbol or a paired surrogate with a
3534 // single ASCII symbol to avoid throwing on regular expressions that
3535 // are only valid in combination with the `/u` flag.
3536 // Note: replacing with the ASCII symbol `x` might cause false
3537 // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
3538 // perfectly valid pattern that is equivalent to `[a-b]`, but it would
3539 // be replaced by `[x-b]` which throws an error.
3540 tmp = tmp.replace(/\\u([a-fA-F0-9]{4})|\\u\{([0-9a-fA-F]+)\}|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x");
3541 }
3542 }
3543 // Detect invalid regular expressions.
3544 var value = null;
3545 // Rhino's regular expression parser is flaky and throws uncatchable exceptions,
3546 // so don't do detection if we are running under Rhino
3547 if (!isRhino) {
3548 try {
3549 new RegExp(tmp);
3550 } catch (e) {
3551 if (e instanceof SyntaxError) this.raise(start, "Error parsing regular expression: " + e.message);
3552 this.raise(e);
3553 }
3554 // Get a regular expression object for this pattern-flag pair, or `null` in
3555 // case the current environment doesn't support the flags it uses.
3556 try {
3557 value = new RegExp(content, mods);
3558 } catch (err) {}
3559 }
3560 return this.finishToken(tt.regexp, { pattern: content, flags: mods, value: value });
3561};
3562
3563// Read an integer in the given radix. Return null if zero digits
3564// were read, the integer value otherwise. When `len` is given, this
3565// will return `null` unless the integer has exactly `len` digits.
3566
3567pp.readInt = function (radix, len) {
3568 var start = this.pos,
3569 total = 0;
3570 for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
3571 var code = this.input.charCodeAt(this.pos),
3572 val = undefined;
3573 if (code >= 97) val = code - 97 + 10; // a
3574 else if (code >= 65) val = code - 65 + 10; // A
3575 else if (code >= 48 && code <= 57) val = code - 48; // 0-9
3576 else val = Infinity;
3577 if (val >= radix) break;
3578 ++this.pos;
3579 total = total * radix + val;
3580 }
3581 if (this.pos === start || len != null && this.pos - start !== len) return null;
3582
3583 return total;
3584};
3585
3586pp.readRadixNumber = function (radix) {
3587 this.pos += 2; // 0x
3588 var val = this.readInt(radix);
3589 if (val == null) this.raise(this.start + 2, "Expected number in radix " + radix);
3590 if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number");
3591 return this.finishToken(tt.num, val);
3592};
3593
3594// Read an integer, octal integer, or floating-point number.
3595
3596pp.readNumber = function (startsWithDot) {
3597 var start = this.pos,
3598 isFloat = false,
3599 octal = this.input.charCodeAt(this.pos) === 48;
3600 if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number");
3601 if (this.input.charCodeAt(this.pos) === 46) {
3602 ++this.pos;
3603 this.readInt(10);
3604 isFloat = true;
3605 }
3606 var next = this.input.charCodeAt(this.pos);
3607 if (next === 69 || next === 101) {
3608 // 'eE'
3609 next = this.input.charCodeAt(++this.pos);
3610 if (next === 43 || next === 45) ++this.pos; // '+-'
3611 if (this.readInt(10) === null) this.raise(start, "Invalid number");
3612 isFloat = true;
3613 }
3614 if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number");
3615
3616 var str = this.input.slice(start, this.pos),
3617 val = undefined;
3618 if (isFloat) val = parseFloat(str);else if (!octal || str.length === 1) val = parseInt(str, 10);else if (/[89]/.test(str) || this.strict) this.raise(start, "Invalid number");else val = parseInt(str, 8);
3619 return this.finishToken(tt.num, val);
3620};
3621
3622// Read a string value, interpreting backslash-escapes.
3623
3624pp.readCodePoint = function () {
3625 var ch = this.input.charCodeAt(this.pos),
3626 code = undefined;
3627
3628 if (ch === 123) {
3629 if (this.options.ecmaVersion < 6) this.unexpected();
3630 ++this.pos;
3631 code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
3632 ++this.pos;
3633 if (code > 1114111) this.unexpected();
3634 } else {
3635 code = this.readHexChar(4);
3636 }
3637 return code;
3638};
3639
3640function codePointToString(code) {
3641 // UTF-16 Decoding
3642 if (code <= 65535) {
3643 return String.fromCharCode(code);
3644 }return String.fromCharCode((code - 65536 >> 10) + 55296, (code - 65536 & 1023) + 56320);
3645}
3646
3647pp.readString = function (quote) {
3648 var out = "",
3649 chunkStart = ++this.pos;
3650 for (;;) {
3651 if (this.pos >= this.input.length) this.raise(this.start, "Unterminated string constant");
3652 var ch = this.input.charCodeAt(this.pos);
3653 if (ch === quote) break;
3654 if (ch === 92) {
3655 // '\'
3656 out += this.input.slice(chunkStart, this.pos);
3657 out += this.readEscapedChar();
3658 chunkStart = this.pos;
3659 } else {
3660 if (isNewLine(ch)) this.raise(this.start, "Unterminated string constant");
3661 ++this.pos;
3662 }
3663 }
3664 out += this.input.slice(chunkStart, this.pos++);
3665 return this.finishToken(tt.string, out);
3666};
3667
3668// Reads template string tokens.
3669
3670pp.readTmplToken = function () {
3671 var out = "",
3672 chunkStart = this.pos;
3673 for (;;) {
3674 if (this.pos >= this.input.length) this.raise(this.start, "Unterminated template");
3675 var ch = this.input.charCodeAt(this.pos);
3676 if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) {
3677 // '`', '${'
3678 if (this.pos === this.start && this.type === tt.template) {
3679 if (ch === 36) {
3680 this.pos += 2;
3681 return this.finishToken(tt.dollarBraceL);
3682 } else {
3683 ++this.pos;
3684 return this.finishToken(tt.backQuote);
3685 }
3686 }
3687 out += this.input.slice(chunkStart, this.pos);
3688 return this.finishToken(tt.template, out);
3689 }
3690 if (ch === 92) {
3691 // '\'
3692 out += this.input.slice(chunkStart, this.pos);
3693 out += this.readEscapedChar();
3694 chunkStart = this.pos;
3695 } else if (isNewLine(ch)) {
3696 out += this.input.slice(chunkStart, this.pos);
3697 ++this.pos;
3698 if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
3699 ++this.pos;
3700 out += "\n";
3701 } else {
3702 out += String.fromCharCode(ch);
3703 }
3704 if (this.options.locations) {
3705 ++this.curLine;
3706 this.lineStart = this.pos;
3707 }
3708 chunkStart = this.pos;
3709 } else {
3710 ++this.pos;
3711 }
3712 }
3713};
3714
3715// Used to read escaped characters
3716
3717pp.readEscapedChar = function () {
3718 var ch = this.input.charCodeAt(++this.pos);
3719 var octal = /^[0-7]+/.exec(this.input.slice(this.pos, this.pos + 3));
3720 if (octal) octal = octal[0];
3721 while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);
3722 if (octal === "0") octal = null;
3723 ++this.pos;
3724 if (octal) {
3725 if (this.strict) this.raise(this.pos - 2, "Octal literal in strict mode");
3726 this.pos += octal.length - 1;
3727 return String.fromCharCode(parseInt(octal, 8));
3728 } else {
3729 switch (ch) {
3730 case 110:
3731 return "\n"; // 'n' -> '\n'
3732 case 114:
3733 return "\r"; // 'r' -> '\r'
3734 case 120:
3735 return String.fromCharCode(this.readHexChar(2)); // 'x'
3736 case 117:
3737 return codePointToString(this.readCodePoint()); // 'u'
3738 case 116:
3739 return "\t"; // 't' -> '\t'
3740 case 98:
3741 return "\b"; // 'b' -> '\b'
3742 case 118:
3743 return "\u000b"; // 'v' -> '\u000b'
3744 case 102:
3745 return "\f"; // 'f' -> '\f'
3746 case 48:
3747 return "\u0000"; // 0 -> '\0'
3748 case 13:
3749 if (this.input.charCodeAt(this.pos) === 10) ++this.pos; // '\r\n'
3750 case 10:
3751 // ' \n'
3752 if (this.options.locations) {
3753 this.lineStart = this.pos;++this.curLine;
3754 }
3755 return "";
3756 default:
3757 return String.fromCharCode(ch);
3758 }
3759 }
3760};
3761
3762// Used to read character escape sequences ('\x', '\u', '\U').
3763
3764pp.readHexChar = function (len) {
3765 var n = this.readInt(16, len);
3766 if (n === null) this.raise(this.start, "Bad character escape sequence");
3767 return n;
3768};
3769
3770// Used to signal to callers of `readWord1` whether the word
3771// contained any escape sequences. This is needed because words with
3772// escape sequences must not be interpreted as keywords.
3773
3774var containsEsc;
3775
3776// Read an identifier, and return it as a string. Sets `containsEsc`
3777// to whether the word contained a '\u' escape.
3778//
3779// Incrementally adds only escaped chars, adding other chunks as-is
3780// as a micro-optimization.
3781
3782pp.readWord1 = function () {
3783 containsEsc = false;
3784 var word = "",
3785 first = true,
3786 chunkStart = this.pos;
3787 var astral = this.options.ecmaVersion >= 6;
3788 while (this.pos < this.input.length) {
3789 var ch = this.fullCharCodeAtPos();
3790 if (isIdentifierChar(ch, astral)) {
3791 this.pos += ch <= 65535 ? 1 : 2;
3792 } else if (ch === 92) {
3793 // "\"
3794 containsEsc = true;
3795 word += this.input.slice(chunkStart, this.pos);
3796 var escStart = this.pos;
3797 if (this.input.charCodeAt(++this.pos) != 117) // "u"
3798 this.raise(this.pos, "Expecting Unicode escape sequence \\uXXXX");
3799 ++this.pos;
3800 var esc = this.readCodePoint();
3801 if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral)) this.raise(escStart, "Invalid Unicode escape");
3802 word += codePointToString(esc);
3803 chunkStart = this.pos;
3804 } else {
3805 break;
3806 }
3807 first = false;
3808 }
3809 return word + this.input.slice(chunkStart, this.pos);
3810};
3811
3812// Read an identifier or keyword token. Will check for reserved
3813// words when necessary.
3814
3815pp.readWord = function () {
3816 var word = this.readWord1();
3817 var type = tt.name;
3818 if ((this.options.ecmaVersion >= 6 || !containsEsc) && this.isKeyword(word)) type = keywordTypes[word];
3819 return this.finishToken(type, word);
3820};
3821
3822},{"./identifier":7,"./location":8,"./state":13,"./tokentype":17,"./whitespace":19}],17:[function(_dereq_,module,exports){
3823"use strict";
3824
3825var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
3826
3827exports.__esModule = true;
3828// ## Token types
3829
3830// The assignment of fine-grained, information-carrying type objects
3831// allows the tokenizer to store the information it has about a
3832// token in a way that is very cheap for the parser to look up.
3833
3834// All token type variables start with an underscore, to make them
3835// easy to recognize.
3836
3837// The `beforeExpr` property is used to disambiguate between regular
3838// expressions and divisions. It is set on all token types that can
3839// be followed by an expression (thus, a slash after them would be a
3840// regular expression).
3841//
3842// `isLoop` marks a keyword as starting a loop, which is important
3843// to know when parsing a label, in order to allow or disallow
3844// continue jumps to that label.
3845
3846var TokenType = exports.TokenType = function TokenType(label) {
3847 var conf = arguments[1] === undefined ? {} : arguments[1];
3848
3849 _classCallCheck(this, TokenType);
3850
3851 this.label = label;
3852 this.keyword = conf.keyword;
3853 this.beforeExpr = !!conf.beforeExpr;
3854 this.startsExpr = !!conf.startsExpr;
3855 this.isLoop = !!conf.isLoop;
3856 this.isAssign = !!conf.isAssign;
3857 this.prefix = !!conf.prefix;
3858 this.postfix = !!conf.postfix;
3859 this.binop = conf.binop || null;
3860 this.updateContext = null;
3861};
3862
3863function binop(name, prec) {
3864 return new TokenType(name, { beforeExpr: true, binop: prec });
3865}
3866var beforeExpr = { beforeExpr: true },
3867 startsExpr = { startsExpr: true };
3868
3869var types = {
3870 num: new TokenType("num", startsExpr),
3871 regexp: new TokenType("regexp", startsExpr),
3872 string: new TokenType("string", startsExpr),
3873 name: new TokenType("name", startsExpr),
3874 eof: new TokenType("eof"),
3875
3876 // Punctuation token types.
3877 bracketL: new TokenType("[", { beforeExpr: true, startsExpr: true }),
3878 bracketR: new TokenType("]"),
3879 braceL: new TokenType("{", { beforeExpr: true, startsExpr: true }),
3880 braceR: new TokenType("}"),
3881 parenL: new TokenType("(", { beforeExpr: true, startsExpr: true }),
3882 parenR: new TokenType(")"),
3883 comma: new TokenType(",", beforeExpr),
3884 semi: new TokenType(";", beforeExpr),
3885 colon: new TokenType(":", beforeExpr),
3886 dot: new TokenType("."),
3887 question: new TokenType("?", beforeExpr),
3888 arrow: new TokenType("=>", beforeExpr),
3889 template: new TokenType("template"),
3890 ellipsis: new TokenType("...", beforeExpr),
3891 backQuote: new TokenType("`", startsExpr),
3892 dollarBraceL: new TokenType("${", { beforeExpr: true, startsExpr: true }),
3893
3894 // Operators. These carry several kinds of properties to help the
3895 // parser use them properly (the presence of these properties is
3896 // what categorizes them as operators).
3897 //
3898 // `binop`, when present, specifies that this operator is a binary
3899 // operator, and will refer to its precedence.
3900 //
3901 // `prefix` and `postfix` mark the operator as a prefix or postfix
3902 // unary operator.
3903 //
3904 // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
3905 // binary operators with a very low precedence, that should result
3906 // in AssignmentExpression nodes.
3907
3908 eq: new TokenType("=", { beforeExpr: true, isAssign: true }),
3909 assign: new TokenType("_=", { beforeExpr: true, isAssign: true }),
3910 incDec: new TokenType("++/--", { prefix: true, postfix: true, startsExpr: true }),
3911 prefix: new TokenType("prefix", { beforeExpr: true, prefix: true, startsExpr: true }),
3912 logicalOR: binop("||", 1),
3913 logicalAND: binop("&&", 2),
3914 bitwiseOR: binop("|", 3),
3915 bitwiseXOR: binop("^", 4),
3916 bitwiseAND: binop("&", 5),
3917 equality: binop("==/!=", 6),
3918 relational: binop("</>", 7),
3919 bitShift: binop("<</>>", 8),
3920 plusMin: new TokenType("+/-", { beforeExpr: true, binop: 9, prefix: true, startsExpr: true }),
3921 modulo: binop("%", 10),
3922 star: binop("*", 10),
3923 slash: binop("/", 10)
3924};
3925
3926exports.types = types;
3927// Map keyword names to token types.
3928
3929var keywords = {};
3930
3931exports.keywords = keywords;
3932// Succinct definitions of keyword token types
3933function kw(name) {
3934 var options = arguments[1] === undefined ? {} : arguments[1];
3935
3936 options.keyword = name;
3937 keywords[name] = types["_" + name] = new TokenType(name, options);
3938}
3939
3940kw("break");
3941kw("case", beforeExpr);
3942kw("catch");
3943kw("continue");
3944kw("debugger");
3945kw("default");
3946kw("do", { isLoop: true });
3947kw("else", beforeExpr);
3948kw("finally");
3949kw("for", { isLoop: true });
3950kw("function", startsExpr);
3951kw("if");
3952kw("return", beforeExpr);
3953kw("switch");
3954kw("throw", beforeExpr);
3955kw("try");
3956kw("var");
3957kw("let");
3958kw("const");
3959kw("while", { isLoop: true });
3960kw("with");
3961kw("new", { beforeExpr: true, startsExpr: true });
3962kw("this", startsExpr);
3963kw("super", startsExpr);
3964kw("class");
3965kw("extends", beforeExpr);
3966kw("export");
3967kw("import");
3968kw("yield", { beforeExpr: true, startsExpr: true });
3969kw("null", startsExpr);
3970kw("true", startsExpr);
3971kw("false", startsExpr);
3972kw("in", { beforeExpr: true, binop: 7 });
3973kw("instanceof", { beforeExpr: true, binop: 7 });
3974kw("typeof", { beforeExpr: true, prefix: true, startsExpr: true });
3975kw("void", { beforeExpr: true, prefix: true, startsExpr: true });
3976kw("delete", { beforeExpr: true, prefix: true, startsExpr: true });
3977
3978},{}],18:[function(_dereq_,module,exports){
3979"use strict";
3980
3981exports.isArray = isArray;
3982
3983// Checks if an object has a property.
3984
3985exports.has = has;
3986exports.__esModule = true;
3987
3988function isArray(obj) {
3989 return Object.prototype.toString.call(obj) === "[object Array]";
3990}
3991
3992function has(obj, propName) {
3993 return Object.prototype.hasOwnProperty.call(obj, propName);
3994}
3995
3996},{}],19:[function(_dereq_,module,exports){
3997"use strict";
3998
3999exports.isNewLine = isNewLine;
4000exports.__esModule = true;
4001// Matches a whole line break (where CRLF is considered a single
4002// line break). Used to count lines.
4003
4004var lineBreak = /\r\n?|\n|\u2028|\u2029/;
4005exports.lineBreak = lineBreak;
4006var lineBreakG = new RegExp(lineBreak.source, "g");
4007
4008exports.lineBreakG = lineBreakG;
4009
4010function isNewLine(code) {
4011 return code === 10 || code === 13 || code === 8232 || code == 8233;
4012}
4013
4014var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
4015exports.nonASCIIwhitespace = nonASCIIwhitespace;
4016
4017},{}]},{},[1])(1)
4018});
4019})(null);
4020(function(module){
4021'use strict';
4022
4023var toStr = Object.prototype.toString;
4024
4025module.exports = function isArguments(value) {
4026 var str = toStr.call(value);
4027 var isArgs = str === '[object Arguments]';
4028 if (!isArgs) {
4029 isArgs = str !== '[object Array]' &&
4030 value !== null &&
4031 typeof value === 'object' &&
4032 typeof value.length === 'number' &&
4033 value.length >= 0 &&
4034 toStr.call(value.callee) === '[object Function]';
4035 }
4036 return isArgs;
4037};
4038
4039window.isArguments = module.exports;
4040})({exports: {}});
4041(function(module){
4042
4043var hasOwn = Object.prototype.hasOwnProperty;
4044var toString = Object.prototype.toString;
4045
4046module.exports = function forEach (obj, fn, ctx) {
4047 if (toString.call(fn) !== '[object Function]') {
4048 throw new TypeError('iterator must be a function');
4049 }
4050 var l = obj.length;
4051 if (l === +l) {
4052 for (var i = 0; i < l; i++) {
4053 fn.call(ctx, obj[i], i, obj);
4054 }
4055 } else {
4056 for (var k in obj) {
4057 if (hasOwn.call(obj, k)) {
4058 fn.call(ctx, obj[k], k, obj);
4059 }
4060 }
4061 }
4062};
4063
4064
4065window.forEach = module.exports;
4066})({exports: {}});
4067(function(module){
4068module.exports = Array.isArray || function (arr) {
4069 return Object.prototype.toString.call(arr) == '[object Array]';
4070};
4071
4072window.isArray = module.exports;
4073})({exports: {}});
4074(function(require,module){
4075'use strict';
4076
4077// modified from https://github.com/es-shims/es5-shim
4078var has = Object.prototype.hasOwnProperty;
4079var toStr = Object.prototype.toString;
4080var slice = Array.prototype.slice;
4081var isArgs = require('./isArguments');
4082var hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString');
4083var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');
4084var dontEnums = [
4085 'toString',
4086 'toLocaleString',
4087 'valueOf',
4088 'hasOwnProperty',
4089 'isPrototypeOf',
4090 'propertyIsEnumerable',
4091 'constructor'
4092];
4093var equalsConstructorPrototype = function (o) {
4094 var ctor = o.constructor;
4095 return ctor && ctor.prototype === o;
4096};
4097var blacklistedKeys = {
4098 $console: true,
4099 $frame: true,
4100 $frameElement: true,
4101 $frames: true,
4102 $parent: true,
4103 $self: true,
4104 $webkitIndexedDB: true,
4105 $webkitStorageInfo: true,
4106 $window: true
4107};
4108var hasAutomationEqualityBug = (function () {
4109 /* global window */
4110 if (typeof window === 'undefined') { return false; }
4111 for (var k in window) {
4112 try {
4113 if (!blacklistedKeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') {
4114 try {
4115 equalsConstructorPrototype(window[k]);
4116 } catch (e) {
4117 return true;
4118 }
4119 }
4120 } catch (e) {
4121 return true;
4122 }
4123 }
4124 return false;
4125}());
4126var equalsConstructorPrototypeIfNotBuggy = function (o) {
4127 /* global window */
4128 if (typeof window === 'undefined' || !hasAutomationEqualityBug) {
4129 return equalsConstructorPrototype(o);
4130 }
4131 try {
4132 return equalsConstructorPrototype(o);
4133 } catch (e) {
4134 return false;
4135 }
4136};
4137
4138var keysShim = function keys(object) {
4139 var isObject = object !== null && typeof object === 'object';
4140 var isFunction = toStr.call(object) === '[object Function]';
4141 var isArguments = isArgs(object);
4142 var isString = isObject && toStr.call(object) === '[object String]';
4143 var theKeys = [];
4144
4145 if (!isObject && !isFunction && !isArguments) {
4146 throw new TypeError('Object.keys called on a non-object');
4147 }
4148
4149 var skipProto = hasProtoEnumBug && isFunction;
4150 if (isString && object.length > 0 && !has.call(object, 0)) {
4151 for (var i = 0; i < object.length; ++i) {
4152 theKeys.push(String(i));
4153 }
4154 }
4155
4156 if (isArguments && object.length > 0) {
4157 for (var j = 0; j < object.length; ++j) {
4158 theKeys.push(String(j));
4159 }
4160 } else {
4161 for (var name in object) {
4162 if (!(skipProto && name === 'prototype') && has.call(object, name)) {
4163 theKeys.push(String(name));
4164 }
4165 }
4166 }
4167
4168 if (hasDontEnumBug) {
4169 var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
4170
4171 for (var k = 0; k < dontEnums.length; ++k) {
4172 if (!(skipConstructor && dontEnums[k] === 'constructor') && has.call(object, dontEnums[k])) {
4173 theKeys.push(dontEnums[k]);
4174 }
4175 }
4176 }
4177 return theKeys;
4178};
4179
4180keysShim.shim = function shimObjectKeys() {
4181 if (Object.keys) {
4182 var keysWorksWithArguments = (function () {
4183 // Safari 5.0 bug
4184 return (Object.keys(arguments) || '').length === 2;
4185 }(1, 2));
4186 if (!keysWorksWithArguments) {
4187 var originalKeys = Object.keys;
4188 Object.keys = function keys(object) {
4189 if (isArgs(object)) {
4190 return originalKeys(slice.call(object));
4191 } else {
4192 return originalKeys(object);
4193 }
4194 };
4195 }
4196 } else {
4197 Object.keys = keysShim;
4198 }
4199 return Object.keys || keysShim;
4200};
4201
4202module.exports = keysShim;
4203
4204window.objectKeys = module.exports;
4205})(function(){return isArguments;},{exports: {}});
4206/*!
4207 * falafel (c) James Halliday / MIT License
4208 * https://github.com/substack/node-falafel
4209 */
4210
4211(function(require,module){
4212var parse = require('acorn').parse;
4213var isArray = require('isarray');
4214var objectKeys = require('object-keys');
4215var forEach = require('foreach');
4216
4217module.exports = function (src, opts, fn) {
4218 if (typeof opts === 'function') {
4219 fn = opts;
4220 opts = {};
4221 }
4222 if (src && typeof src === 'object' && src.constructor.name === 'Buffer') {
4223 src = src.toString();
4224 }
4225 else if (src && typeof src === 'object') {
4226 opts = src;
4227 src = opts.source;
4228 delete opts.source;
4229 }
4230 src = src === undefined ? opts.source : src;
4231 if (typeof src !== 'string') src = String(src);
4232 if (opts.parser) parse = opts.parser.parse;
4233 var ast = parse(src, opts);
4234
4235 var result = {
4236 chunks : src.split(''),
4237 toString : function () { return result.chunks.join('') },
4238 inspect : function () { return result.toString() }
4239 };
4240 var index = 0;
4241
4242 (function walk (node, parent) {
4243 insertHelpers(node, parent, result.chunks);
4244
4245 forEach(objectKeys(node), function (key) {
4246 if (key === 'parent') return;
4247
4248 var child = node[key];
4249 if (isArray(child)) {
4250 forEach(child, function (c) {
4251 if (c && typeof c.type === 'string') {
4252 walk(c, node);
4253 }
4254 });
4255 }
4256 else if (child && typeof child.type === 'string') {
4257 walk(child, node);
4258 }
4259 });
4260 fn(node);
4261 })(ast, undefined);
4262
4263 return result;
4264};
4265
4266function insertHelpers (node, parent, chunks) {
4267 node.parent = parent;
4268
4269 node.source = function () {
4270 return chunks.slice(node.start, node.end).join('');
4271 };
4272
4273 if (node.update && typeof node.update === 'object') {
4274 var prev = node.update;
4275 forEach(objectKeys(prev), function (key) {
4276 update[key] = prev[key];
4277 });
4278 node.update = update;
4279 }
4280 else {
4281 node.update = update;
4282 }
4283
4284 function update (s) {
4285 chunks[node.start] = s;
4286 for (var i = node.start + 1; i < node.end; i++) {
4287 chunks[i] = '';
4288 }
4289 }
4290}
4291
4292window.falafel = module.exports;})(function(moduleName){switch(moduleName){case "acorn":
4293return {parse: acorn.parse};
4294case "object-keys":
4295return objectKeys;
4296case "foreach":
4297return forEach;
4298case "isarray":
4299return isArray;}},{exports: {}});
4300var inBrowser = typeof window !== 'undefined' && this === window;
4301var parseAndModify = (inBrowser ? window.falafel : require("falafel"));
4302
4303(inBrowser ? window : exports).blanket = (function(){
4304 var linesToAddTracking = [
4305 "ExpressionStatement",
4306 "BreakStatement" ,
4307 "ContinueStatement" ,
4308 "VariableDeclaration",
4309 "ReturnStatement" ,
4310 "ThrowStatement" ,
4311 "TryStatement" ,
4312 "FunctionDeclaration" ,
4313 "IfStatement" ,
4314 "WhileStatement" ,
4315 "DoWhileStatement" ,
4316 "ForStatement" ,
4317 "ForInStatement" ,
4318 "SwitchStatement" ,
4319 "WithStatement"
4320 ],
4321 linesToAddBrackets = [
4322 "IfStatement" ,
4323 "WhileStatement" ,
4324 "DoWhileStatement" ,
4325 "ForStatement" ,
4326 "ForInStatement" ,
4327 "WithStatement"
4328 ],
4329 __blanket,
4330 copynumber = Math.floor(Math.random()*1000),
4331 coverageInfo = {},options = {
4332 reporter: null,
4333 adapter:null,
4334 filter: null,
4335 customVariable: null,
4336 loader: null,
4337 ignoreScriptError: false,
4338 existingRequireJS:false,
4339 autoStart: false,
4340 timeout: 180,
4341 ignoreCors: false,
4342 branchTracking: false,
4343 sourceURL: false,
4344 debug:false,
4345 engineOnly:false,
4346 testReadyCallback:null,
4347 commonJS:false,
4348 instrumentCache:false,
4349 modulePattern: null,
4350 ecmaVersion: 5
4351 };
4352
4353 if (inBrowser && typeof window.blanket !== 'undefined'){
4354 __blanket = window.blanket.noConflict();
4355 }
4356
4357 _blanket = {
4358 noConflict: function(){
4359 if (__blanket){
4360 return __blanket;
4361 }
4362 return _blanket;
4363 },
4364 _getCopyNumber: function(){
4365 //internal method
4366 //for differentiating between instances
4367 return copynumber;
4368 },
4369 extend: function(obj) {
4370 //borrowed from underscore
4371 _blanket._extend(_blanket,obj);
4372 },
4373 _extend: function(dest,source){
4374 if (source) {
4375 for (var prop in source) {
4376 if ( dest[prop] instanceof Object && typeof dest[prop] !== "function"){
4377 _blanket._extend(dest[prop],source[prop]);
4378 }else{
4379 dest[prop] = source[prop];
4380 }
4381 }
4382 }
4383 },
4384 getCovVar: function(){
4385 var opt = _blanket.options("customVariable");
4386 if (opt){
4387 if (_blanket.options("debug")) {console.log("BLANKET-Using custom tracking variable:",opt);}
4388 return inBrowser ? "window."+opt : opt;
4389 }
4390 return inBrowser ? "window._$blanket" : "_$jscoverage";
4391 },
4392 options: function(key,value){
4393 if (typeof key !== "string"){
4394 _blanket._extend(options,key);
4395 }else if (typeof value === 'undefined'){
4396 return options[key];
4397 }else{
4398 options[key]=value;
4399 }
4400 },
4401 // instrument the file synchronously
4402 // `next` is optional callback which will be called
4403 // with instrumented code when present
4404 instrumentSync: function(config, next){
4405 //check instrumented hash table,
4406 //return instrumented code if available.
4407 var inFile = config.inputFile,
4408 inFileName = config.inputFileName;
4409 //check instrument cache
4410 if (_blanket.options("instrumentCache") && sessionStorage && sessionStorage.getItem("blanket_instrument_store-"+inFileName)){
4411 if (_blanket.options("debug")) {console.log("BLANKET-Reading instrumentation from cache: ",inFileName);}
4412 if (next) {
4413 next(sessionStorage.getItem("blanket_instrument_store-"+inFileName));
4414 } else {
4415 return(sessionStorage.getItem("blanket_instrument_store-"+inFileName));
4416 }
4417 }else{
4418 var sourceArray = _blanket._prepareSource(inFile);
4419 _blanket._trackingArraySetup=[];
4420 //remove shebang
4421 inFile = inFile.replace(/^\#\!.*/, "");
4422 var instrumented = parseAndModify(inFile,{locations:true,comment:true,ecmaVersion:_blanket.options("ecmaVersion")}, _blanket._addTracking(inFileName));
4423 instrumented = _blanket._trackingSetup(inFileName,sourceArray)+instrumented;
4424 if (_blanket.options("sourceURL")){
4425 instrumented += "\n//@ sourceURL="+inFileName.replace("http://","");
4426 }
4427 if (_blanket.options("debug")) {console.log("BLANKET-Instrumented file: ",inFileName);}
4428 if (_blanket.options("instrumentCache") && sessionStorage){
4429 if (_blanket.options("debug")) {console.log("BLANKET-Saving instrumentation to cache: ",inFileName);}
4430 sessionStorage.setItem("blanket_instrument_store-"+inFileName,instrumented);
4431 }
4432 if (next) {
4433 next(instrumented);
4434 } else {
4435 return(instrumented);
4436 }
4437 }
4438 },
4439 instrument: function(config, next){
4440 _blanket.instrumentSync(config, next);
4441 },
4442 _trackingArraySetup: [],
4443 _branchingArraySetup: [],
4444 _useStrictMode: false,
4445 _prepareSource: function(source){
4446 return source.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/(\r\n|\n|\r)/gm,"\n").split('\n');
4447 },
4448 _trackingSetup: function(filename,sourceArray){
4449 var branches = _blanket.options("branchTracking");
4450 var sourceString = sourceArray.join("',\n'");
4451 var intro = "";
4452 var covVar = _blanket.getCovVar();
4453
4454 if(_blanket._useStrictMode) {
4455 intro += "'use strict';\n";
4456 }
4457
4458 intro += "if (typeof "+covVar+" === 'undefined') "+covVar+" = {};\n";
4459 if (branches){
4460 intro += "var _$branchFcn=function(f,l,c,r){ ";
4461 intro += "if (!!r) { ";
4462 intro += covVar+"[f].branchData[l][c][0] = "+covVar+"[f].branchData[l][c][0] || [];";
4463 intro += covVar+"[f].branchData[l][c][0].push(r); }";
4464 intro += "else { ";
4465 intro += covVar+"[f].branchData[l][c][1] = "+covVar+"[f].branchData[l][c][1] || [];";
4466 intro += covVar+"[f].branchData[l][c][1].push(r); }";
4467 intro += "return r;};\n";
4468 }
4469 intro += "if (typeof "+covVar+"['"+filename+"'] === 'undefined'){";
4470
4471 intro += covVar+"['"+filename+"']=[];\n";
4472 if (branches){
4473 intro += covVar+"['"+filename+"'].branchData=[];\n";
4474 }
4475 intro += covVar+"['"+filename+"'].source=['"+sourceString+"'];\n";
4476 //initialize array values
4477 _blanket._trackingArraySetup.sort(function(a,b){
4478 return parseInt(a,10) > parseInt(b,10);
4479 }).forEach(function(item){
4480 intro += covVar+"['"+filename+"']["+item+"]=0;\n";
4481 });
4482 if (branches){
4483 _blanket._branchingArraySetup.sort(function(a,b){
4484 return a.line > b.line;
4485 }).sort(function(a,b){
4486 return a.column > b.column;
4487 }).forEach(function(item){
4488 if (item.file === filename){
4489 intro += "if (typeof "+ covVar+"['"+filename+"'].branchData["+item.line+"] === 'undefined'){\n";
4490 intro += covVar+"['"+filename+"'].branchData["+item.line+"]=[];\n";
4491 intro += "}";
4492 intro += covVar+"['"+filename+"'].branchData["+item.line+"]["+item.column+"] = [];\n";
4493 intro += covVar+"['"+filename+"'].branchData["+item.line+"]["+item.column+"].consequent = "+JSON.stringify(item.consequent)+";\n";
4494 intro += covVar+"['"+filename+"'].branchData["+item.line+"]["+item.column+"].alternate = "+JSON.stringify(item.alternate)+";\n";
4495 }
4496 });
4497 }
4498 intro += "}";
4499
4500 return intro;
4501 },
4502 _blockifyIf: function(node){
4503 if (linesToAddBrackets.indexOf(node.type) > -1){
4504 var bracketsExistObject = node.consequent || node.body;
4505 var bracketsExistAlt = node.alternate;
4506 if( bracketsExistAlt && bracketsExistAlt.type !== "BlockStatement") {
4507 bracketsExistAlt.update("{\n"+bracketsExistAlt.source()+"}\n");
4508 }
4509 if( bracketsExistObject && bracketsExistObject.type !== "BlockStatement") {
4510 bracketsExistObject.update("{\n"+bracketsExistObject.source()+"}\n");
4511 }
4512 }
4513 },
4514 _trackBranch: function(node,filename){
4515 //recursive on consequent and alternative
4516 var line = node.loc.start.line;
4517 var col = node.loc.start.column;
4518
4519 _blanket._branchingArraySetup.push({
4520 line: line,
4521 column: col,
4522 file:filename,
4523 consequent: node.consequent.loc,
4524 alternate: node.alternate.loc
4525 });
4526
4527 var updated = "_$branchFcn"+
4528 "('"+filename+"',"+line+","+col+","+node.test.source()+
4529 ")?"+node.consequent.source()+":"+node.alternate.source();
4530 node.update(updated);
4531 },
4532 _addTracking: function (filename) {
4533 //falafel doesn't take a file name
4534 //so we include the filename in a closure
4535 //and return the function to falafel
4536 var covVar = _blanket.getCovVar();
4537
4538 return function(node){
4539 _blanket._blockifyIf(node);
4540
4541 if (linesToAddTracking.indexOf(node.type) > -1 && node.parent.type !== "LabeledStatement") {
4542 _blanket._checkDefs(node,filename);
4543 if (node.type === "VariableDeclaration" &&
4544 (node.parent.type === "ForStatement" || node.parent.type === "ForInStatement")){
4545 return;
4546 }
4547 if (node.loc && node.loc.start){
4548 node.update(covVar+"['"+filename+"']["+node.loc.start.line+"]++;\n"+node.source());
4549 _blanket._trackingArraySetup.push(node.loc.start.line);
4550 }else{
4551 //I don't think we can handle a node with no location
4552 throw new Error("The instrumenter encountered a node with no location: "+Object.keys(node));
4553 }
4554 }else if (_blanket.options("branchTracking") && node.type === "ConditionalExpression"){
4555 _blanket._trackBranch(node,filename);
4556 }else if (node.type === "Literal" && node.value === "use strict" && node.parent && node.parent.type === "ExpressionStatement" && node.parent.parent && node.parent.parent.type === "Program"){
4557 _blanket._useStrictMode = true;
4558 }
4559 };
4560 },
4561 _checkDefs: function(node,filename){
4562 // Make sure developers don't redefine window. if they do, inform them it is wrong.
4563 if (inBrowser){
4564 if (node.type === "VariableDeclaration" && node.declarations) {
4565 node.declarations.forEach(function(declaration) {
4566 if (declaration.id.name === "window") {
4567 throw new Error("Instrumentation error, you cannot redefine the 'window' variable in " + filename + ":" + node.loc.start.line);
4568 }
4569 });
4570 }
4571 if (node.type === "FunctionDeclaration" && node.params) {
4572 node.params.forEach(function(param) {
4573 if (param.name === "window") {
4574 throw new Error("Instrumentation error, you cannot redefine the 'window' variable in " + filename + ":" + node.loc.start.line);
4575 }
4576 });
4577 }
4578 //Make sure developers don't redefine the coverage variable
4579 if (node.type === "ExpressionStatement" &&
4580 node.expression && node.expression.left &&
4581 node.expression.left.object && node.expression.left.property &&
4582 node.expression.left.object.name +
4583 "." + node.expression.left.property.name === _blanket.getCovVar()) {
4584 throw new Error("Instrumentation error, you cannot redefine the coverage variable in " + filename + ":" + node.loc.start.line);
4585 }
4586 }else{
4587 //Make sure developers don't redefine the coverage variable in node
4588 if (node.type === "ExpressionStatement" &&
4589 node.expression && node.expression.left &&
4590 !node.expression.left.object && !node.expression.left.property &&
4591 node.expression.left.name === _blanket.getCovVar()) {
4592 throw new Error("Instrumentation error, you cannot redefine the coverage variable in " + filename + ":" + node.loc.start.line);
4593 }
4594 }
4595 },
4596 setupCoverage: function(){
4597 coverageInfo.instrumentation = "blanket";
4598 coverageInfo.stats = {
4599 "suites": 0,
4600 "tests": 0,
4601 "passes": 0,
4602 "pending": 0,
4603 "failures": 0,
4604 "start": new Date()
4605 };
4606 },
4607 _checkIfSetup: function(){
4608 if (!coverageInfo.stats){
4609 throw new Error("You must call blanket.setupCoverage() first.");
4610 }
4611 },
4612 onTestStart: function(){
4613 if (_blanket.options("debug")) {console.log("BLANKET-Test event started");}
4614 this._checkIfSetup();
4615 coverageInfo.stats.tests++;
4616 coverageInfo.stats.pending++;
4617 },
4618 onTestDone: function(total,passed){
4619 this._checkIfSetup();
4620 if(passed === total){
4621 coverageInfo.stats.passes++;
4622 }else{
4623 coverageInfo.stats.failures++;
4624 }
4625 coverageInfo.stats.pending--;
4626 },
4627 onModuleStart: function(){
4628 this._checkIfSetup();
4629 coverageInfo.stats.suites++;
4630 },
4631 onTestsDone: function(){
4632 if (_blanket.options("debug")) {console.log("BLANKET-Test event done");}
4633 this._checkIfSetup();
4634 coverageInfo.stats.end = new Date();
4635
4636 if (inBrowser){
4637 this.report(coverageInfo);
4638 }else{
4639 if (!_blanket.options("branchTracking")){
4640 delete (inBrowser ? window : global)[_blanket.getCovVar()].branchFcn;
4641 }
4642 this.options("reporter").call(this,coverageInfo);
4643 }
4644 }
4645 };
4646 return _blanket;
4647})();
4648
4649(function(_blanket){
4650 var oldOptions = _blanket.options;
4651_blanket.extend({
4652 outstandingRequireFiles:[],
4653 options: function(key,value){
4654 var newVal={};
4655
4656 if (typeof key !== "string"){
4657 //key is key/value map
4658 oldOptions(key);
4659 newVal = key;
4660 }else if (typeof value === 'undefined'){
4661 //accessor
4662 return oldOptions(key);
4663 }else{
4664 //setter
4665 oldOptions(key,value);
4666 newVal[key] = value;
4667 }
4668
4669 if (newVal.adapter){
4670 _blanket._loadFile(newVal.adapter);
4671 }
4672 if (newVal.loader){
4673 _blanket._loadFile(newVal.loader);
4674 }
4675 },
4676 requiringFile: function(filename,done){
4677 if (typeof filename === "undefined"){
4678 _blanket.outstandingRequireFiles=[];
4679 }else if (typeof done === "undefined"){
4680 _blanket.outstandingRequireFiles.push(filename);
4681 }else{
4682 _blanket.outstandingRequireFiles.splice(_blanket.outstandingRequireFiles.indexOf(filename),1);
4683 }
4684 },
4685 requireFilesLoaded: function(){
4686 return _blanket.outstandingRequireFiles.length === 0;
4687 },
4688 showManualLoader: function(){
4689 if (document.getElementById("blanketLoaderDialog")){
4690 return;
4691 }
4692 //copied from http://blog.avtex.com/2012/01/26/cross-browser-css-only-modal-box/
4693 var loader = "<div class='blanketDialogOverlay'>";
4694 loader += "&nbsp;</div>";
4695 loader += "<div class='blanketDialogVerticalOffset'>";
4696 loader += "<div class='blanketDialogBox'>";
4697 loader += "<b>Error:</b> Blanket.js encountered a cross origin request error while instrumenting the source files. ";
4698 loader += "<br><br>This is likely caused by the source files being referenced locally (using the file:// protocol). ";
4699 loader += "<br><br>Some solutions include <a href='http://askubuntu.com/questions/160245/making-google-chrome-option-allow-file-access-from-files-permanent' target='_blank'>starting Chrome with special flags</a>, <a target='_blank' href='https://github.com/remy/servedir'>running a server locally</a>, or using a browser without these CORS restrictions (Safari).";
4700 loader += "<br>";
4701 if (typeof FileReader !== "undefined"){
4702 loader += "<br>Or, try the experimental loader. When prompted, simply click on the directory containing all the source files you want covered.";
4703 loader += "<a href='javascript:document.getElementById(\"fileInput\").click();'>Start Loader</a>";
4704 loader += "<input type='file' type='application/x-javascript' accept='application/x-javascript' webkitdirectory id='fileInput' multiple onchange='window.blanket.manualFileLoader(this.files)' style='visibility:hidden;position:absolute;top:-50;left:-50'/>";
4705 }
4706 loader += "<br><span style='float:right;cursor:pointer;' onclick=document.getElementById('blanketLoaderDialog').style.display='none';>Close</span>";
4707 loader += "<div style='clear:both'></div>";
4708 loader += "</div></div>";
4709
4710 var css = ".blanketDialogWrapper {";
4711 css += "display:block;";
4712 css += "position:fixed;";
4713 css += "z-index:40001; }";
4714
4715 css += ".blanketDialogOverlay {";
4716 css += "position:fixed;";
4717 css += "width:100%;";
4718 css += "height:100%;";
4719 css += "background-color:black;";
4720 css += "opacity:.5; ";
4721 css += "-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=50)'; ";
4722 css += "filter:alpha(opacity=50); ";
4723 css += "z-index:40001; }";
4724
4725 css += ".blanketDialogVerticalOffset { ";
4726 css += "position:fixed;";
4727 css += "top:30%;";
4728 css += "width:100%;";
4729 css += "z-index:40002; }";
4730
4731 css += ".blanketDialogBox { ";
4732 css += "width:405px; ";
4733 css += "position:relative;";
4734 css += "margin:0 auto;";
4735 css += "background-color:white;";
4736 css += "padding:10px;";
4737 css += "border:1px solid black; }";
4738
4739 var dom = document.createElement("style");
4740 dom.innerHTML = css;
4741 document.head.appendChild(dom);
4742
4743 var div = document.createElement("div");
4744 div.id = "blanketLoaderDialog";
4745 div.className = "blanketDialogWrapper";
4746 div.innerHTML = loader;
4747 document.body.insertBefore(div,document.body.firstChild);
4748
4749 },
4750 manualFileLoader: function(files){
4751 var toArray =Array.prototype.slice;
4752 files = toArray.call(files).filter(function(item){
4753 return item.type !== "";
4754 });
4755 var sessionLength = files.length-1;
4756 var sessionIndx=0;
4757 var sessionArray = {};
4758 if (sessionStorage["blanketSessionLoader"]){
4759 sessionArray = JSON.parse(sessionStorage["blanketSessionLoader"]);
4760 }
4761
4762
4763 var fileLoader = function(event){
4764 var fileContent = event.currentTarget.result;
4765 var file = files[sessionIndx];
4766 var filename = file.webkitRelativePath && file.webkitRelativePath !== '' ? file.webkitRelativePath : file.name;
4767 sessionArray[filename] = fileContent;
4768 sessionIndx++;
4769 if (sessionIndx === sessionLength){
4770 sessionStorage.setItem("blanketSessionLoader", JSON.stringify(sessionArray));
4771 document.location.reload();
4772 }else{
4773 readFile(files[sessionIndx]);
4774 }
4775 };
4776 function readFile(file){
4777 var reader = new FileReader();
4778 reader.onload = fileLoader;
4779 reader.readAsText(file);
4780 }
4781 readFile(files[sessionIndx]);
4782 },
4783 _loadFile: function(path){
4784 if (typeof path !== "undefined"){
4785 var request = new XMLHttpRequest();
4786 request.open('GET', path, false);
4787 request.send();
4788 _blanket._addScript(request.responseText);
4789 }
4790 },
4791 _addScript: function(data){
4792 var script = document.createElement("script");
4793 script.type = "text/javascript";
4794 script.text = data;
4795 (document.body || document.getElementsByTagName('head')[0]).appendChild(script);
4796 },
4797 hasAdapter: function(callback){
4798 return _blanket.options("adapter") !== null;
4799 },
4800 report: function(coverage_data){
4801 if (!document.getElementById("blanketLoaderDialog")){
4802 //all found, clear it
4803 _blanket.blanketSession = null;
4804 }
4805 coverage_data.files = window._$blanket;
4806 var require = blanket.options("commonJS") ? blanket._commonjs.require : window.require;
4807
4808 // Check if we have any covered files that requires reporting
4809 // otherwise just exit gracefully.
4810 if (!coverage_data.files || !Object.keys(coverage_data.files).length) {
4811 if (_blanket.options("debug")) {console.log("BLANKET-Reporting No files were instrumented.");}
4812 return;
4813 }
4814
4815 if (typeof coverage_data.files.branchFcn !== "undefined"){
4816 delete coverage_data.files.branchFcn;
4817 }
4818 if (typeof _blanket.options("reporter") === "string"){
4819 _blanket._loadFile(_blanket.options("reporter"));
4820 _blanket.customReporter(coverage_data,_blanket.options("reporter_options"));
4821 }else if (typeof _blanket.options("reporter") === "function"){
4822 _blanket.options("reporter")(coverage_data,_blanket.options("reporter_options"));
4823 }else if (typeof _blanket.defaultReporter === 'function'){
4824 _blanket.defaultReporter(coverage_data,_blanket.options("reporter_options"));
4825 }else{
4826 throw new Error("no reporter defined.");
4827 }
4828 },
4829 _bindStartTestRunner: function(bindEvent,startEvent){
4830 if (bindEvent){
4831 bindEvent(startEvent);
4832 }else{
4833 if (document.readyState === "complete") {
4834 startEvent();
4835 } else {
4836 window.addEventListener("load",startEvent,false);
4837 }
4838 }
4839 },
4840 _loadSourceFiles: function(callback){
4841 var require = blanket.options("commonJS") ? blanket._commonjs.require : window.require;
4842 function copy(o){
4843 var _copy = Object.create( Object.getPrototypeOf(o) );
4844 var propNames = Object.getOwnPropertyNames(o);
4845
4846 propNames.forEach(function(name){
4847 var desc = Object.getOwnPropertyDescriptor(o, name);
4848 Object.defineProperty(_copy, name, desc);
4849 });
4850
4851 return _copy;
4852 }
4853 if (_blanket.options("debug")) {console.log("BLANKET-Collecting page scripts");}
4854 var scripts = _blanket.utils.collectPageScripts();
4855 //_blanket.options("filter",scripts);
4856 if (scripts.length === 0){
4857 callback();
4858 }else{
4859
4860 //check session state
4861 if (sessionStorage["blanketSessionLoader"]){
4862 _blanket.blanketSession = JSON.parse(sessionStorage["blanketSessionLoader"]);
4863 }
4864
4865 scripts.forEach(function(file,indx){
4866 _blanket.utils.cache[file]={
4867 loaded:false
4868 };
4869 });
4870
4871 var currScript=-1;
4872 _blanket.utils.loadAll(function(test){
4873 if (test){
4874 return typeof scripts[currScript+1] !== 'undefined';
4875 }
4876 currScript++;
4877 if (currScript >= scripts.length){
4878 return null;
4879 }
4880 return scripts[currScript];
4881 },callback);
4882 }
4883 },
4884 beforeStartTestRunner: function(opts){
4885 opts = opts || {};
4886 opts.checkRequirejs = typeof opts.checkRequirejs === "undefined" ? true : opts.checkRequirejs;
4887 opts.callback = opts.callback || function() { };
4888 opts.coverage = typeof opts.coverage === "undefined" ? true : opts.coverage;
4889 if (opts.coverage) {
4890 _blanket._bindStartTestRunner(opts.bindEvent,
4891 function(){
4892 _blanket._loadSourceFiles(function() {
4893
4894 var allLoaded = function(){
4895 return opts.condition ? opts.condition() : _blanket.requireFilesLoaded();
4896 };
4897 var check = function() {
4898 if (allLoaded()) {
4899 if (_blanket.options("debug")) {console.log("BLANKET-All files loaded, init start test runner callback.");}
4900 var cb = _blanket.options("testReadyCallback");
4901
4902 if (cb){
4903 if (typeof cb === "function"){
4904 cb(opts.callback);
4905 }else if (typeof cb === "string"){
4906 _blanket._addScript(cb);
4907 opts.callback();
4908 }
4909 }else{
4910 opts.callback();
4911 }
4912 } else {
4913 setTimeout(check, 13);
4914 }
4915 };
4916 check();
4917 });
4918 });
4919 }else{
4920 opts.callback();
4921 }
4922 },
4923 utils: {
4924 qualifyURL: function (url) {
4925 //http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
4926 var a = document.createElement('a');
4927 a.href = url;
4928 return a.href;
4929 }
4930 }
4931});
4932
4933})(blanket);
4934
4935blanket.defaultReporter = function(coverage){
4936 var cssSytle = "#blanket-main {margin:2px;background:#EEE;color:#333;clear:both;font-family:'Helvetica Neue Light', 'HelveticaNeue-Light', 'Helvetica Neue', Calibri, Helvetica, Arial, sans-serif; font-size:17px;} #blanket-main a {color:#333;text-decoration:none;} #blanket-main a:hover {text-decoration:underline;} .blanket {margin:0;padding:5px;clear:both;border-bottom: 1px solid #FFFFFF;} .bl-error {color:red;}.bl-success {color:#5E7D00;} .bl-file{width:auto;} .bl-cl{float:left;} .blanket div.rs {margin-left:50px; width:150px; float:right} .bl-nb {padding-right:10px;} #blanket-main a.bl-logo {color: #EB1764;cursor: pointer;font-weight: bold;text-decoration: none} .bl-source{ overflow-x:scroll; background-color: #FFFFFF; border: 1px solid #CBCBCB; color: #363636; margin: 25px 20px; width: 80%;} .bl-source div{white-space: pre;font-family: monospace;} .bl-source > div > span:first-child{background-color: #EAEAEA;color: #949494;display: inline-block;padding: 0 10px;text-align: center;width: 30px;} .bl-source .hit{background-color:#c3e6c7} .bl-source .miss{background-color:#e6c3c7} .bl-source span.branchWarning{color:#000;background-color:yellow;} .bl-source span.branchOkay{color:#000;background-color:transparent;}",
4937 successRate = 60,
4938 head = document.head,
4939 fileNumber = 0,
4940 body = document.body,
4941 headerContent,
4942 hasBranchTracking = Object.keys(coverage.files).some(function(elem){
4943 return typeof coverage.files[elem].branchData !== 'undefined';
4944 }),
4945 bodyContent = "<div id='blanket-main'><div class='blanket bl-title'><div class='bl-cl bl-file'><a href='http://alex-seville.github.com/blanket/' target='_blank' class='bl-logo'>Blanket.js</a> results</div><div class='bl-cl rs'>Coverage (%)</div><div class='bl-cl rs'>Covered/Total Smts.</div>"+(hasBranchTracking ? "<div class='bl-cl rs'>Covered/Total Branches</div>":"")+"<div style='clear:both;'></div></div>",
4946 fileTemplate = "<div class='blanket {{statusclass}}'><div class='bl-cl bl-file'><span class='bl-nb'>{{fileNumber}}.</span><a href='javascript:blanket_toggleSource(\"file-{{fileNumber}}\")'>{{file}}</a></div><div class='bl-cl rs'>{{percentage}} %</div><div class='bl-cl rs'>{{numberCovered}}/{{totalSmts}}</div>"+( hasBranchTracking ? "<div class='bl-cl rs'>{{passedBranches}}/{{totalBranches}}</div>" : "" )+"<div id='file-{{fileNumber}}' class='bl-source' style='display:none;'>{{source}}</div><div style='clear:both;'></div></div>";
4947 grandTotalTemplate = "<div class='blanket grand-total {{statusclass}}'><div class='bl-cl'>{{rowTitle}}</div><div class='bl-cl rs'>{{percentage}} %</div><div class='bl-cl rs'>{{numberCovered}}/{{totalSmts}}</div>"+( hasBranchTracking ? "<div class='bl-cl rs'>{{passedBranches}}/{{totalBranches}}</div>" : "" ) + "<div style='clear:both;'></div></div>";
4948
4949 function blanket_toggleSource(id) {
4950 var element = document.getElementById(id);
4951 if(element.style.display === 'block') {
4952 element.style.display = 'none';
4953 } else {
4954 element.style.display = 'block';
4955 }
4956 }
4957
4958
4959 var script = document.createElement("script");
4960 script.type = "text/javascript";
4961 script.text = blanket_toggleSource.toString().replace('function ' + blanket_toggleSource.name, 'function blanket_toggleSource');
4962 body.appendChild(script);
4963
4964 var percentage = function(number, total) {
4965 return (Math.round(((number/total) * 100)*100)/100);
4966 };
4967
4968 var appendTag = function (type, el, str) {
4969 var dom = document.createElement(type);
4970 dom.innerHTML = str;
4971 el.appendChild(dom);
4972 };
4973
4974 function escapeInvalidXmlChars(str) {
4975 return str.replace(/\&/g, "&amp;")
4976 .replace(/</g, "&lt;")
4977 .replace(/\>/g, "&gt;")
4978 .replace(/\"/g, "&quot;")
4979 .replace(/\'/g, "&apos;")
4980 .replace(/`/g, "&grave;")
4981 .replace(/[$]/g, "&dollar;")
4982 .replace(/&/g, "&amp;");
4983 }
4984
4985 function isBranchFollowed(data,bool){
4986 var mode = bool ? 0 : 1;
4987 if (typeof data === 'undefined' ||
4988 typeof data === null ||
4989 typeof data[mode] === 'undefined'){
4990 return false;
4991 }
4992 return data[mode].length > 0;
4993 }
4994
4995 var branchStack = [];
4996
4997 function branchReport(colsIndex,src,cols,offset,lineNum){
4998 var newsrc="";
4999 var postfix="";
5000 if (branchStack.length > 0){
5001 newsrc += "<span class='" + (isBranchFollowed(branchStack[0][1],branchStack[0][1].consequent === branchStack[0][0]) ? 'branchOkay' : 'branchWarning') + "'>";
5002 if (branchStack[0][0].end.line === lineNum){
5003 newsrc += escapeInvalidXmlChars(src.slice(0,branchStack[0][0].end.column)) + "</span>";
5004 src = src.slice(branchStack[0][0].end.column);
5005 branchStack.shift();
5006 if (branchStack.length > 0){
5007 newsrc += "<span class='" + (isBranchFollowed(branchStack[0][1],false) ? 'branchOkay' : 'branchWarning') + "'>";
5008 if (branchStack[0][0].end.line === lineNum){
5009 newsrc += escapeInvalidXmlChars(src.slice(0,branchStack[0][0].end.column)) + "</span>";
5010 src = src.slice(branchStack[0][0].end.column);
5011 branchStack.shift();
5012 if (!cols){
5013 return {src: newsrc + escapeInvalidXmlChars(src) ,cols:cols};
5014 }
5015 }
5016 else if (!cols){
5017 return {src: newsrc + escapeInvalidXmlChars(src) + "</span>",cols:cols};
5018 }
5019 else{
5020 postfix = "</span>";
5021 }
5022 }else if (!cols){
5023 return {src: newsrc + escapeInvalidXmlChars(src) ,cols:cols};
5024 }
5025 }else if(!cols){
5026 return {src: newsrc + escapeInvalidXmlChars(src) + "</span>",cols:cols};
5027 }else{
5028 postfix = "</span>";
5029 }
5030 }
5031 var thisline = cols[colsIndex];
5032 //consequent
5033
5034 var cons = thisline.consequent;
5035 if (cons.start.line > lineNum){
5036 branchStack.unshift([thisline.alternate,thisline]);
5037 branchStack.unshift([cons,thisline]);
5038 src = escapeInvalidXmlChars(src);
5039 }else{
5040 var style = "<span class='" + (isBranchFollowed(thisline,true) ? 'branchOkay' : 'branchWarning') + "'>";
5041 newsrc += escapeInvalidXmlChars(src.slice(0,cons.start.column-offset)) + style;
5042
5043 if (cols.length > colsIndex+1 &&
5044 cols[colsIndex+1].consequent.start.line === lineNum &&
5045 cols[colsIndex+1].consequent.start.column-offset < cols[colsIndex].consequent.end.column-offset)
5046 {
5047 var res = branchReport(colsIndex+1,src.slice(cons.start.column-offset,cons.end.column-offset),cols,cons.start.column-offset,lineNum);
5048 newsrc += res.src;
5049 cols = res.cols;
5050 cols[colsIndex+1] = cols[colsIndex+2];
5051 cols.length--;
5052 }else{
5053 newsrc += escapeInvalidXmlChars(src.slice(cons.start.column-offset,cons.end.column-offset));
5054 }
5055 newsrc += "</span>";
5056
5057 var alt = thisline.alternate;
5058 if (alt.start.line > lineNum){
5059 newsrc += escapeInvalidXmlChars(src.slice(cons.end.column-offset));
5060 branchStack.unshift([alt,thisline]);
5061 }else{
5062 newsrc += escapeInvalidXmlChars(src.slice(cons.end.column-offset,alt.start.column-offset));
5063 style = "<span class='" + (isBranchFollowed(thisline,false) ? 'branchOkay' : 'branchWarning') + "'>";
5064 newsrc += style;
5065 if (cols.length > colsIndex+1 &&
5066 cols[colsIndex+1].consequent.start.line === lineNum &&
5067 cols[colsIndex+1].consequent.start.column-offset < cols[colsIndex].alternate.end.column-offset)
5068 {
5069 var res2 = branchReport(colsIndex+1,src.slice(alt.start.column-offset,alt.end.column-offset),cols,alt.start.column-offset,lineNum);
5070 newsrc += res2.src;
5071 cols = res2.cols;
5072 cols[colsIndex+1] = cols[colsIndex+2];
5073 cols.length--;
5074 }else{
5075 newsrc += escapeInvalidXmlChars(src.slice(alt.start.column-offset,alt.end.column-offset));
5076 }
5077 newsrc += "</span>";
5078 newsrc += escapeInvalidXmlChars(src.slice(alt.end.column-offset));
5079 src = newsrc;
5080 }
5081 }
5082 return {src:src+postfix, cols:cols};
5083 }
5084
5085 var isUndefined = function(item){
5086 return typeof item !== 'undefined';
5087 };
5088
5089 var files = coverage.files;
5090 var totals = {
5091 totalSmts: 0,
5092 numberOfFilesCovered: 0,
5093 passedBranches: 0,
5094 totalBranches: 0,
5095 moduleTotalStatements : {},
5096 moduleTotalCoveredStatements : {},
5097 moduleTotalBranches : {},
5098 moduleTotalCoveredBranches : {}
5099 };
5100
5101 // check if a data-cover-modulepattern was provided for per-module coverage reporting
5102 var modulePattern = _blanket.options("modulePattern");
5103 var modulePatternRegex = ( modulePattern ? new RegExp(modulePattern) : null );
5104
5105 for(var file in files)
5106 {
5107 if (!files.hasOwnProperty(file)) {
5108 continue;
5109 }
5110
5111 fileNumber++;
5112
5113 var statsForFile = files[file],
5114 totalSmts = 0,
5115 numberOfFilesCovered = 0,
5116 code = [],
5117 i;
5118
5119
5120 var end = [];
5121 for(i = 0; i < statsForFile.source.length; i +=1){
5122 var src = statsForFile.source[i];
5123
5124 if (branchStack.length > 0 ||
5125 typeof statsForFile.branchData !== 'undefined')
5126 {
5127 if (typeof statsForFile.branchData[i+1] !== 'undefined')
5128 {
5129 var cols = statsForFile.branchData[i+1].filter(isUndefined);
5130 var colsIndex=0;
5131
5132
5133 src = branchReport(colsIndex,src,cols,0,i+1).src;
5134
5135 }else if (branchStack.length){
5136 src = branchReport(0,src,null,0,i+1).src;
5137 }else{
5138 src = escapeInvalidXmlChars(src);
5139 }
5140 }else{
5141 src = escapeInvalidXmlChars(src);
5142 }
5143 var lineClass="";
5144 if(statsForFile[i+1]) {
5145 numberOfFilesCovered += 1;
5146 totalSmts += 1;
5147 lineClass = 'hit';
5148 }else{
5149 if(statsForFile[i+1] === 0){
5150 totalSmts++;
5151 lineClass = 'miss';
5152 }
5153 }
5154 code[i + 1] = "<div class='"+lineClass+"'><span class=''>"+(i + 1)+"</span>"+src+"</div>";
5155 }
5156 totals.totalSmts += totalSmts;
5157 totals.numberOfFilesCovered += numberOfFilesCovered;
5158 var totalBranches=0;
5159 var passedBranches=0;
5160 if (typeof statsForFile.branchData !== 'undefined'){
5161 for(var j=0;j<statsForFile.branchData.length;j++){
5162 if (typeof statsForFile.branchData[j] !== 'undefined'){
5163 for(var k=0;k<statsForFile.branchData[j].length;k++){
5164 if (typeof statsForFile.branchData[j][k] !== 'undefined'){
5165 totalBranches++;
5166 if (typeof statsForFile.branchData[j][k][0] !== 'undefined' &&
5167 statsForFile.branchData[j][k][0].length > 0 &&
5168 typeof statsForFile.branchData[j][k][1] !== 'undefined' &&
5169 statsForFile.branchData[j][k][1].length > 0){
5170 passedBranches++;
5171 }
5172 }
5173 }
5174 }
5175 }
5176 }
5177 totals.passedBranches += passedBranches;
5178 totals.totalBranches += totalBranches;
5179
5180 // if "data-cover-modulepattern" was provided,
5181 // track totals per module name as well as globally
5182 if (modulePatternRegex) {
5183 var moduleName = file.match(modulePatternRegex)[1];
5184
5185 if(!totals.moduleTotalStatements.hasOwnProperty(moduleName)) {
5186 totals.moduleTotalStatements[moduleName] = 0;
5187 totals.moduleTotalCoveredStatements[moduleName] = 0;
5188 }
5189
5190 totals.moduleTotalStatements[moduleName] += totalSmts;
5191 totals.moduleTotalCoveredStatements[moduleName] += numberOfFilesCovered;
5192
5193 if(!totals.moduleTotalBranches.hasOwnProperty(moduleName)) {
5194 totals.moduleTotalBranches[moduleName] = 0;
5195 totals.moduleTotalCoveredBranches[moduleName] = 0;
5196 }
5197
5198 totals.moduleTotalBranches[moduleName] += totalBranches;
5199 totals.moduleTotalCoveredBranches[moduleName] += passedBranches;
5200 }
5201
5202 var result = percentage(numberOfFilesCovered, totalSmts);
5203
5204 var output = fileTemplate.replace("{{file}}", file)
5205 .replace("{{percentage}}",result)
5206 .replace("{{numberCovered}}", numberOfFilesCovered)
5207 .replace(/\{\{fileNumber\}\}/g, fileNumber)
5208 .replace("{{totalSmts}}", totalSmts)
5209 .replace("{{totalBranches}}", totalBranches)
5210 .replace("{{passedBranches}}", passedBranches)
5211 .replace("{{source}}", code.join(" "));
5212 if(result < successRate)
5213 {
5214 output = output.replace("{{statusclass}}", "bl-error");
5215 } else {
5216 output = output.replace("{{statusclass}}", "bl-success");
5217 }
5218 bodyContent += output;
5219 }
5220
5221 // create temporary function for use by the global totals reporter,
5222 // as well as the per-module totals reporter
5223 var createAggregateTotal = function(numSt, numCov, numBranch, numCovBr, moduleName) {
5224
5225 var totalPercent = percentage(numCov, numSt);
5226 var statusClass = totalPercent < successRate ? "bl-error" : "bl-success";
5227 var rowTitle = ( moduleName ? "Total for module: " + moduleName : "Global total" );
5228 var totalsOutput = grandTotalTemplate.replace("{{rowTitle}}", rowTitle)
5229 .replace("{{percentage}}", totalPercent)
5230 .replace("{{numberCovered}}", numCov)
5231 .replace("{{totalSmts}}", numSt)
5232 .replace("{{passedBranches}}", numCovBr)
5233 .replace("{{totalBranches}}", numBranch)
5234 .replace("{{statusclass}}", statusClass);
5235
5236 bodyContent += totalsOutput;
5237 };
5238
5239 // if "data-cover-modulepattern" was provided,
5240 // output the per-module totals alongside the global totals
5241 if (modulePatternRegex) {
5242 for (var thisModuleName in totals.moduleTotalStatements) {
5243 if (totals.moduleTotalStatements.hasOwnProperty(thisModuleName)) {
5244
5245 var moduleTotalSt = totals.moduleTotalStatements[thisModuleName];
5246 var moduleTotalCovSt = totals.moduleTotalCoveredStatements[thisModuleName];
5247
5248 var moduleTotalBr = totals.moduleTotalBranches[thisModuleName];
5249 var moduleTotalCovBr = totals.moduleTotalCoveredBranches[thisModuleName];
5250
5251 createAggregateTotal(moduleTotalSt, moduleTotalCovSt, moduleTotalBr, moduleTotalCovBr, thisModuleName);
5252 }
5253 }
5254 }
5255
5256 createAggregateTotal(totals.totalSmts, totals.numberOfFilesCovered, totals.totalBranches, totals.passedBranches, null);
5257 bodyContent += "</div>"; //closing main
5258
5259
5260 appendTag('style', head, cssSytle);
5261 //appendStyle(body, headerContent);
5262 if (document.getElementById("blanket-main")){
5263 document.getElementById("blanket-main").innerHTML=
5264 bodyContent.slice(23,-6);
5265 }else{
5266 appendTag('div', body, bodyContent);
5267 }
5268 //appendHtml(body, '</div>');
5269};
5270
5271(function(){
5272 var newOptions={};
5273 //http://stackoverflow.com/a/2954896
5274 var toArray =Array.prototype.slice;
5275 var scripts = toArray.call(document.scripts);
5276 toArray.call(scripts[scripts.length - 1].attributes)
5277 .forEach(function(es){
5278 if(es.nodeName === "data-cover-only"){
5279 newOptions.filter = es.nodeValue;
5280 }
5281 if(es.nodeName === "data-cover-never"){
5282 newOptions.antifilter = es.nodeValue;
5283 }
5284 if(es.nodeName === "data-cover-reporter"){
5285 newOptions.reporter = es.nodeValue;
5286 }
5287 if (es.nodeName === "data-cover-adapter"){
5288 newOptions.adapter = es.nodeValue;
5289 }
5290 if (es.nodeName === "data-cover-loader"){
5291 newOptions.loader = es.nodeValue;
5292 }
5293 if (es.nodeName === "data-cover-timeout"){
5294 newOptions.timeout = es.nodeValue;
5295 }
5296 if (es.nodeName === "data-cover-modulepattern") {
5297 newOptions.modulePattern = es.nodeValue;
5298 }
5299 if (es.nodeName === "data-cover-reporter-options"){
5300 try{
5301 newOptions.reporter_options = JSON.parse(es.nodeValue);
5302 }catch(e){
5303 if (blanket.options("debug")){
5304 throw new Error("Invalid reporter options. Must be a valid stringified JSON object.");
5305 }
5306 }
5307 }
5308 if (es.nodeName === "data-cover-testReadyCallback"){
5309 newOptions.testReadyCallback = es.nodeValue;
5310 }
5311 if (es.nodeName === "data-cover-customVariable"){
5312 newOptions.customVariable = es.nodeValue;
5313 }
5314 if (es.nodeName === "data-cover-flags"){
5315 var flags = " "+es.nodeValue+" ";
5316 if (flags.indexOf(" ignoreError ") > -1){
5317 newOptions.ignoreScriptError = true;
5318 }
5319 if (flags.indexOf(" autoStart ") > -1){
5320 newOptions.autoStart = true;
5321 }
5322 if (flags.indexOf(" ignoreCors ") > -1){
5323 newOptions.ignoreCors = true;
5324 }
5325 if (flags.indexOf(" branchTracking ") > -1){
5326 newOptions.branchTracking = true;
5327 }
5328 if (flags.indexOf(" sourceURL ") > -1){
5329 newOptions.sourceURL = true;
5330 }
5331 if (flags.indexOf(" debug ") > -1){
5332 newOptions.debug = true;
5333 }
5334 if (flags.indexOf(" engineOnly ") > -1){
5335 newOptions.engineOnly = true;
5336 }
5337 if (flags.indexOf(" commonJS ") > -1){
5338 newOptions.commonJS = true;
5339 }
5340 if (flags.indexOf(" instrumentCache ") > -1){
5341 newOptions.instrumentCache = true;
5342 }
5343 }
5344 });
5345 blanket.options(newOptions);
5346
5347 if (typeof requirejs !== 'undefined'){
5348 blanket.options("existingRequireJS",true);
5349 }
5350 /* setup requirejs loader, if needed */
5351
5352 if (blanket.options("commonJS")){
5353 blanket._commonjs = {};
5354 }
5355})();
5356(function(_blanket){
5357_blanket.extend({
5358 utils: {
5359 normalizeBackslashes: function(str) {
5360 return str.replace(/\\/g, '/');
5361 },
5362 matchPatternAttribute: function(filename,pattern){
5363 if (typeof pattern === 'string'){
5364 if (pattern.indexOf("[") === 0){
5365 //treat as array
5366 var pattenArr = pattern.slice(1,pattern.length-1).split(",");
5367 return pattenArr.some(function(elem){
5368 return _blanket.utils.matchPatternAttribute(filename,_blanket.utils.normalizeBackslashes(elem.slice(1,-1)));
5369 //return filename.indexOf(_blanket.utils.normalizeBackslashes(elem.slice(1,-1))) > -1;
5370 });
5371 }else if ( pattern.indexOf("//") === 0){
5372 var ex = pattern.slice(2,pattern.lastIndexOf('/'));
5373 var mods = pattern.slice(pattern.lastIndexOf('/')+1);
5374 var regex = new RegExp(ex,mods);
5375 return regex.test(filename);
5376 }else if (pattern.indexOf("#") === 0){
5377 return window[pattern.slice(1)].call(window,filename);
5378 }else{
5379 return filename.indexOf(_blanket.utils.normalizeBackslashes(pattern)) > -1;
5380 }
5381 }else if ( pattern instanceof Array ){
5382 return pattern.some(function(elem){
5383 return _blanket.utils.matchPatternAttribute(filename,elem);
5384 });
5385 }else if (pattern instanceof RegExp){
5386 return pattern.test(filename);
5387 }else if (typeof pattern === "function"){
5388 return pattern.call(window,filename);
5389 }
5390 },
5391 blanketEval: function(data){
5392 _blanket._addScript(data);
5393 },
5394 collectPageScripts: function(){
5395 var toArray = Array.prototype.slice;
5396 var scripts = toArray.call(document.scripts);
5397 var selectedScripts=[],scriptNames=[];
5398 var filter = _blanket.options("filter");
5399 if(filter != null){
5400 //global filter in place, data-cover-only
5401 var antimatch = _blanket.options("antifilter");
5402 selectedScripts = toArray.call(document.scripts)
5403 .filter(function(s){
5404 return toArray.call(s.attributes).filter(function(sn){
5405 return sn.nodeName === "src" && _blanket.utils.matchPatternAttribute(sn.nodeValue,filter) &&
5406 (typeof antimatch === "undefined" || !_blanket.utils.matchPatternAttribute(sn.nodeValue,antimatch));
5407 }).length === 1;
5408 });
5409 }else{
5410 selectedScripts = toArray.call(document.querySelectorAll("script[data-cover]"));
5411 }
5412 scriptNames = selectedScripts.map(function(s){
5413 return _blanket.utils.qualifyURL(
5414 toArray.call(s.attributes).filter(
5415 function(sn){
5416 return sn.nodeName === "src";
5417 })[0].nodeValue);
5418 });
5419 if (!filter){
5420 _blanket.options("filter","['"+scriptNames.join("','")+"']");
5421 }
5422 return scriptNames;
5423 },
5424 loadAll: function(nextScript,cb,preprocessor){
5425 /**
5426 * load dependencies
5427 * @param {nextScript} factory for priority level
5428 * @param {cb} the done callback
5429 */
5430 var currScript=nextScript();
5431 var isLoaded = _blanket.utils.scriptIsLoaded(
5432 currScript,
5433 _blanket.utils.ifOrdered,
5434 nextScript,
5435 cb
5436 );
5437
5438 if (!(_blanket.utils.cache[currScript] && _blanket.utils.cache[currScript].loaded)){
5439 var attach = function(){
5440 if (_blanket.options("debug")) {console.log("BLANKET-Mark script:"+currScript+", as loaded and move to next script.");}
5441 isLoaded();
5442 };
5443 var whenDone = function(result){
5444 if (_blanket.options("debug")) {console.log("BLANKET-File loading finished");}
5445 if (typeof result !== 'undefined'){
5446 if (_blanket.options("debug")) {console.log("BLANKET-Add file to DOM.");}
5447 _blanket._addScript(result);
5448 }
5449 attach();
5450 };
5451
5452 _blanket.utils.attachScript(
5453 {
5454 url: currScript
5455 },
5456 function (content){
5457 _blanket.utils.processFile(
5458 content,
5459 currScript,
5460 whenDone,
5461 whenDone
5462 );
5463 }
5464 );
5465 }else{
5466 isLoaded();
5467 }
5468 },
5469 attachScript: function(options,cb){
5470 var timeout = _blanket.options("timeout") || 3000;
5471 setTimeout(function(){
5472 if (!_blanket.utils.cache[options.url].loaded){
5473 throw new Error("error (timeout=" + timeout + ") loading source script: " + options.url);
5474 }
5475 },timeout);
5476 _blanket.utils.getFile(
5477 options.url,
5478 cb,
5479 function(){ throw new Error("error loading source script: " + options.url);}
5480 );
5481 },
5482 ifOrdered: function(nextScript,cb){
5483 /**
5484 * ordered loading callback
5485 * @param {nextScript} factory for priority level
5486 * @param {cb} the done callback
5487 */
5488 var currScript = nextScript(true);
5489 if (currScript){
5490 _blanket.utils.loadAll(nextScript,cb);
5491 }else{
5492 cb(new Error("Error in loading chain."));
5493 }
5494 },
5495 scriptIsLoaded: function(url,orderedCb,nextScript,cb){
5496 /**
5497 * returns a callback that checks a loading list to see if a script is loaded.
5498 * @param {orderedCb} callback if ordered loading is being done
5499 * @param {nextScript} factory for next priority level
5500 * @param {cb} the done callback
5501 */
5502 if (_blanket.options("debug")) {console.log("BLANKET-Returning function");}
5503 return function(){
5504 if (_blanket.options("debug")) {console.log("BLANKET-Marking file as loaded: "+url);}
5505
5506 _blanket.utils.cache[url].loaded=true;
5507
5508 if (_blanket.utils.allLoaded()){
5509 if (_blanket.options("debug")) {console.log("BLANKET-All files loaded");}
5510 cb();
5511 }else if (orderedCb){
5512 //if it's ordered we need to
5513 //traverse down to the next
5514 //priority level
5515 if (_blanket.options("debug")) {console.log("BLANKET-Load next file.");}
5516 orderedCb(nextScript,cb);
5517 }
5518 };
5519 },
5520 cache: {},
5521 allLoaded: function (){
5522 /**
5523 * check if depdencies are loaded in cache
5524 */
5525 var cached = Object.keys(_blanket.utils.cache);
5526 for (var i=0;i<cached.length;i++){
5527 if (!_blanket.utils.cache[cached[i]].loaded){
5528 return false;
5529 }
5530 }
5531 return true;
5532 },
5533 processFile: function (content,url,cb,oldCb) {
5534 var match = _blanket.options("filter");
5535 //we check the never matches first
5536 var antimatch = _blanket.options("antifilter");
5537 if (typeof antimatch !== "undefined" &&
5538 _blanket.utils.matchPatternAttribute(url,antimatch)
5539 ){
5540 oldCb(content);
5541 if (_blanket.options("debug")) {console.log("BLANKET-File will never be instrumented:"+url);}
5542 _blanket.requiringFile(url,true);
5543 }else if (_blanket.utils.matchPatternAttribute(url,match)){
5544 if (_blanket.options("debug")) {console.log("BLANKET-Attempting instrument of:"+url);}
5545 _blanket.instrument({
5546 inputFile: content,
5547 inputFileName: url
5548 },function(instrumented){
5549 try{
5550 if (_blanket.options("debug")) {console.log("BLANKET-instrument of:"+url+" was successfull.");}
5551 _blanket.utils.blanketEval(instrumented);
5552 cb();
5553 _blanket.requiringFile(url,true);
5554 }
5555 catch(err){
5556 if (_blanket.options("ignoreScriptError")){
5557 //we can continue like normal if
5558 //we're ignoring script errors,
5559 //but otherwise we don't want
5560 //to completeLoad or the error might be
5561 //missed.
5562 if (_blanket.options("debug")) { console.log("BLANKET-There was an error loading the file:"+url); }
5563 cb(content);
5564 _blanket.requiringFile(url,true);
5565 }else{
5566 var e = new Error("Error parsing instrumented code: "+err);
5567 e.error = err;
5568 throw e;
5569 }
5570 }
5571 });
5572 }else{
5573 if (_blanket.options("debug")) { console.log("BLANKET-Loading (without instrumenting) the file:"+url);}
5574 oldCb(content);
5575 _blanket.requiringFile(url,true);
5576 }
5577
5578 },
5579 cacheXhrConstructor: function(){
5580 var Constructor, createXhr, i, progId;
5581 if (typeof XMLHttpRequest !== "undefined") {
5582 Constructor = XMLHttpRequest;
5583 this.createXhr = function() { return new Constructor(); };
5584 } else if (typeof ActiveXObject !== "undefined") {
5585 Constructor = ActiveXObject;
5586 for (i = 0; i < 3; i += 1) {
5587 progId = progIds[i];
5588 try {
5589 new ActiveXObject(progId);
5590 break;
5591 } catch (e) {}
5592 }
5593 this.createXhr = function() { return new Constructor(progId); };
5594 }
5595 },
5596 craeteXhr: function () {
5597 throw new Error("cacheXhrConstructor is supposed to overwrite this function.");
5598 },
5599 getFile: function(url, callback, errback, onXhr){
5600 var foundInSession = false;
5601 if (_blanket.blanketSession){
5602 var files = Object.keys(_blanket.blanketSession);
5603 for (var i=0; i<files.length;i++ ){
5604 var key = files[i];
5605 if (url.indexOf(key) > -1){
5606 callback(_blanket.blanketSession[key]);
5607 foundInSession=true;
5608 return;
5609 }
5610 }
5611 }
5612 if (!foundInSession){
5613 var xhr = _blanket.utils.createXhr();
5614 xhr.open('GET', url, true);
5615
5616 //Allow overrides specified in config
5617 if (onXhr) {
5618 onXhr(xhr, url);
5619 }
5620
5621 xhr.onreadystatechange = function (evt) {
5622 var status, err;
5623
5624 //Do not explicitly handle errors, those should be
5625 //visible via console output in the browser.
5626 if (xhr.readyState === 4) {
5627 status = xhr.status;
5628 if ((status > 399 && status < 600) /*||
5629 (status === 0 &&
5630 navigator.userAgent.toLowerCase().indexOf('firefox') > -1)
5631 */ ) {
5632 //An http 4xx or 5xx error. Signal an error.
5633 err = new Error(url + ' HTTP status: ' + status);
5634 err.xhr = xhr;
5635 errback(err);
5636 } else {
5637 callback(xhr.responseText);
5638 }
5639 }
5640 };
5641 try{
5642 xhr.send(null);
5643 }catch(e){
5644 if (e.code && (e.code === 101 || e.code === 1012) && _blanket.options("ignoreCors") === false){
5645 //running locally and getting error from browser
5646 _blanket.showManualLoader();
5647 } else {
5648 throw e;
5649 }
5650 }
5651 }
5652 }
5653 }
5654});
5655
5656(function(){
5657 var require = blanket.options("commonJS") ? blanket._commonjs.require : window.require;
5658 var requirejs = blanket.options("commonJS") ? blanket._commonjs.requirejs : window.requirejs;
5659 if (!_blanket.options("engineOnly") && _blanket.options("existingRequireJS")){
5660
5661 _blanket.utils.oldloader = requirejs.load;
5662
5663 requirejs.load = function (context, moduleName, url) {
5664 _blanket.requiringFile(url);
5665 _blanket.utils.getFile(url,
5666 function(content){
5667 _blanket.utils.processFile(
5668 content,
5669 url,
5670 function newLoader(){
5671 context.completeLoad(moduleName);
5672 },
5673 function oldLoader(){
5674 _blanket.utils.oldloader(context, moduleName, url);
5675 }
5676 );
5677 }, function (err) {
5678 _blanket.requiringFile();
5679 throw err;
5680 });
5681 };
5682 }
5683 // Save the XHR constructor, just in case frameworks like Sinon would sandbox it.
5684 _blanket.utils.cacheXhrConstructor();
5685})();
5686
5687})(blanket);
5688
5689(function(){
5690if (typeof QUnit !== 'undefined'){
5691 //check to make sure requirejs is completed before we start the test runner
5692 var allLoaded = function() {
5693 return window.QUnit.config.queue.length > 0 && blanket.noConflict().requireFilesLoaded();
5694 };
5695
5696 if (!QUnit.config.urlConfig[0].tooltip){
5697 //older versions we run coverage automatically
5698 //and we change how events are binded
5699 QUnit.begin=function(){
5700 blanket.noConflict().setupCoverage();
5701 };
5702
5703 QUnit.done=function(failures, total) {
5704 blanket.noConflict().onTestsDone();
5705 };
5706 QUnit.moduleStart=function( details ) {
5707 blanket.noConflict().onModuleStart();
5708 };
5709 QUnit.testStart=function( details ) {
5710 blanket.noConflict().onTestStart();
5711 };
5712 QUnit.testDone=function( details ) {
5713 blanket.noConflict().onTestDone(details.total,details.passed);
5714 };
5715 blanket.beforeStartTestRunner({
5716 condition: allLoaded,
5717 callback: QUnit.start
5718 });
5719 }else{
5720 QUnit.config.urlConfig.push({
5721 id: "coverage",
5722 label: "Enable coverage",
5723 tooltip: "Enable code coverage."
5724 });
5725
5726 if ( QUnit.urlParams.coverage || blanket.options("autoStart") ) {
5727 QUnit.begin(function(){
5728 blanket.noConflict().setupCoverage();
5729 });
5730
5731 QUnit.done(function(failures, total) {
5732 blanket.noConflict().onTestsDone();
5733 });
5734 QUnit.moduleStart(function( details ) {
5735 blanket.noConflict().onModuleStart();
5736 });
5737 QUnit.testStart(function( details ) {
5738 blanket.noConflict().onTestStart();
5739 });
5740 QUnit.testDone(function( details ) {
5741 blanket.noConflict().onTestDone(details.total,details.passed);
5742 });
5743 blanket.noConflict().beforeStartTestRunner({
5744 condition: allLoaded,
5745 callback: function(){
5746 if (!(blanket.options("existingRequireJS") && !blanket.options("autoStart"))){
5747 QUnit.start();
5748 }
5749 }
5750 });
5751 }else{
5752 if (blanket.options("existingRequireJS")){ requirejs.load = _blanket.utils.oldloader; }
5753 blanket.noConflict().beforeStartTestRunner({
5754 condition: allLoaded,
5755 callback: function(){
5756 if (!(blanket.options("existingRequireJS") && !blanket.options("autoStart"))){
5757 QUnit.start();
5758 }
5759 },
5760 coverage:false
5761 });
5762 }
5763 }
5764}
5765})();
\No newline at end of file