UNPKG

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