dom/system/gonk/tests/marionette/ril_jshint/jshint.js

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:2e10dafe5fc4
1 //2.1.3
2 var JSHINT;
3 (function () {
4 var require;
5 require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
6 // shim for using process in browser
7
8 var process = module.exports = {};
9
10 process.nextTick = (function () {
11 var canSetImmediate = typeof window !== 'undefined'
12 && window.setImmediate;
13 var canPost = typeof window !== 'undefined'
14 && window.postMessage && window.addEventListener
15 ;
16
17 if (canSetImmediate) {
18 return function (f) { return window.setImmediate(f) };
19 }
20
21 if (canPost) {
22 var queue = [];
23 window.addEventListener('message', function (ev) {
24 if (ev.source === window && ev.data === 'process-tick') {
25 ev.stopPropagation();
26 if (queue.length > 0) {
27 var fn = queue.shift();
28 fn();
29 }
30 }
31 }, true);
32
33 return function nextTick(fn) {
34 queue.push(fn);
35 window.postMessage('process-tick', '*');
36 };
37 }
38
39 return function nextTick(fn) {
40 setTimeout(fn, 0);
41 };
42 })();
43
44 process.title = 'browser';
45 process.browser = true;
46 process.env = {};
47 process.argv = [];
48
49 process.binding = function (name) {
50 throw new Error('process.binding is not supported');
51 }
52
53 // TODO(shtylman)
54 process.cwd = function () { return '/' };
55 process.chdir = function (dir) {
56 throw new Error('process.chdir is not supported');
57 };
58
59 },{}],2:[function(require,module,exports){
60 (function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
61
62 var EventEmitter = exports.EventEmitter = process.EventEmitter;
63 var isArray = typeof Array.isArray === 'function'
64 ? Array.isArray
65 : function (xs) {
66 return Object.prototype.toString.call(xs) === '[object Array]'
67 }
68 ;
69 function indexOf (xs, x) {
70 if (xs.indexOf) return xs.indexOf(x);
71 for (var i = 0; i < xs.length; i++) {
72 if (x === xs[i]) return i;
73 }
74 return -1;
75 }
76
77 // By default EventEmitters will print a warning if more than
78 // 10 listeners are added to it. This is a useful default which
79 // helps finding memory leaks.
80 //
81 // Obviously not all Emitters should be limited to 10. This function allows
82 // that to be increased. Set to zero for unlimited.
83 var defaultMaxListeners = 10;
84 EventEmitter.prototype.setMaxListeners = function(n) {
85 if (!this._events) this._events = {};
86 this._events.maxListeners = n;
87 };
88
89
90 EventEmitter.prototype.emit = function(type) {
91 // If there is no 'error' event listener then throw.
92 if (type === 'error') {
93 if (!this._events || !this._events.error ||
94 (isArray(this._events.error) && !this._events.error.length))
95 {
96 if (arguments[1] instanceof Error) {
97 throw arguments[1]; // Unhandled 'error' event
98 } else {
99 throw new Error("Uncaught, unspecified 'error' event.");
100 }
101 return false;
102 }
103 }
104
105 if (!this._events) return false;
106 var handler = this._events[type];
107 if (!handler) return false;
108
109 if (typeof handler == 'function') {
110 switch (arguments.length) {
111 // fast cases
112 case 1:
113 handler.call(this);
114 break;
115 case 2:
116 handler.call(this, arguments[1]);
117 break;
118 case 3:
119 handler.call(this, arguments[1], arguments[2]);
120 break;
121 // slower
122 default:
123 var args = Array.prototype.slice.call(arguments, 1);
124 handler.apply(this, args);
125 }
126 return true;
127
128 } else if (isArray(handler)) {
129 var args = Array.prototype.slice.call(arguments, 1);
130
131 var listeners = handler.slice();
132 for (var i = 0, l = listeners.length; i < l; i++) {
133 listeners[i].apply(this, args);
134 }
135 return true;
136
137 } else {
138 return false;
139 }
140 };
141
142 // EventEmitter is defined in src/node_events.cc
143 // EventEmitter.prototype.emit() is also defined there.
144 EventEmitter.prototype.addListener = function(type, listener) {
145 if ('function' !== typeof listener) {
146 throw new Error('addListener only takes instances of Function');
147 }
148
149 if (!this._events) this._events = {};
150
151 // To avoid recursion in the case that type == "newListeners"! Before
152 // adding it to the listeners, first emit "newListeners".
153 this.emit('newListener', type, listener);
154
155 if (!this._events[type]) {
156 // Optimize the case of one listener. Don't need the extra array object.
157 this._events[type] = listener;
158 } else if (isArray(this._events[type])) {
159
160 // Check for listener leak
161 if (!this._events[type].warned) {
162 var m;
163 if (this._events.maxListeners !== undefined) {
164 m = this._events.maxListeners;
165 } else {
166 m = defaultMaxListeners;
167 }
168
169 if (m && m > 0 && this._events[type].length > m) {
170 this._events[type].warned = true;
171 console.error('(node) warning: possible EventEmitter memory ' +
172 'leak detected. %d listeners added. ' +
173 'Use emitter.setMaxListeners() to increase limit.',
174 this._events[type].length);
175 console.trace();
176 }
177 }
178
179 // If we've already got an array, just append.
180 this._events[type].push(listener);
181 } else {
182 // Adding the second element, need to change to array.
183 this._events[type] = [this._events[type], listener];
184 }
185
186 return this;
187 };
188
189 EventEmitter.prototype.on = EventEmitter.prototype.addListener;
190
191 EventEmitter.prototype.once = function(type, listener) {
192 var self = this;
193 self.on(type, function g() {
194 self.removeListener(type, g);
195 listener.apply(this, arguments);
196 });
197
198 return this;
199 };
200
201 EventEmitter.prototype.removeListener = function(type, listener) {
202 if ('function' !== typeof listener) {
203 throw new Error('removeListener only takes instances of Function');
204 }
205
206 // does not use listeners(), so no side effect of creating _events[type]
207 if (!this._events || !this._events[type]) return this;
208
209 var list = this._events[type];
210
211 if (isArray(list)) {
212 var i = indexOf(list, listener);
213 if (i < 0) return this;
214 list.splice(i, 1);
215 if (list.length == 0)
216 delete this._events[type];
217 } else if (this._events[type] === listener) {
218 delete this._events[type];
219 }
220
221 return this;
222 };
223
224 EventEmitter.prototype.removeAllListeners = function(type) {
225 if (arguments.length === 0) {
226 this._events = {};
227 return this;
228 }
229
230 // does not use listeners(), so no side effect of creating _events[type]
231 if (type && this._events && this._events[type]) this._events[type] = null;
232 return this;
233 };
234
235 EventEmitter.prototype.listeners = function(type) {
236 if (!this._events) this._events = {};
237 if (!this._events[type]) this._events[type] = [];
238 if (!isArray(this._events[type])) {
239 this._events[type] = [this._events[type]];
240 }
241 return this._events[type];
242 };
243
244 })(require("__browserify_process"))
245 },{"__browserify_process":1}],3:[function(require,module,exports){
246 (function(){// jshint -W001
247
248 "use strict";
249
250 // Identifiers provided by the ECMAScript standard.
251
252 exports.reservedVars = {
253 arguments : false,
254 NaN : false
255 };
256
257 exports.ecmaIdentifiers = {
258 Array : false,
259 Boolean : false,
260 Date : false,
261 decodeURI : false,
262 decodeURIComponent : false,
263 encodeURI : false,
264 encodeURIComponent : false,
265 Error : false,
266 "eval" : false,
267 EvalError : false,
268 Function : false,
269 hasOwnProperty : false,
270 isFinite : false,
271 isNaN : false,
272 JSON : false,
273 Math : false,
274 Map : false,
275 Number : false,
276 Object : false,
277 parseInt : false,
278 parseFloat : false,
279 RangeError : false,
280 ReferenceError : false,
281 RegExp : false,
282 Set : false,
283 String : false,
284 SyntaxError : false,
285 TypeError : false,
286 URIError : false,
287 WeakMap : false
288 };
289
290 // Global variables commonly provided by a web browser environment.
291
292 exports.browser = {
293 ArrayBuffer : false,
294 ArrayBufferView : false,
295 Audio : false,
296 Blob : false,
297 addEventListener : false,
298 applicationCache : false,
299 atob : false,
300 blur : false,
301 btoa : false,
302 clearInterval : false,
303 clearTimeout : false,
304 close : false,
305 closed : false,
306 DataView : false,
307 DOMParser : false,
308 defaultStatus : false,
309 document : false,
310 Element : false,
311 ElementTimeControl : false,
312 event : false,
313 FileReader : false,
314 Float32Array : false,
315 Float64Array : false,
316 FormData : false,
317 focus : false,
318 frames : false,
319 getComputedStyle : false,
320 HTMLElement : false,
321 HTMLAnchorElement : false,
322 HTMLBaseElement : false,
323 HTMLBlockquoteElement: false,
324 HTMLBodyElement : false,
325 HTMLBRElement : false,
326 HTMLButtonElement : false,
327 HTMLCanvasElement : false,
328 HTMLDirectoryElement : false,
329 HTMLDivElement : false,
330 HTMLDListElement : false,
331 HTMLFieldSetElement : false,
332 HTMLFontElement : false,
333 HTMLFormElement : false,
334 HTMLFrameElement : false,
335 HTMLFrameSetElement : false,
336 HTMLHeadElement : false,
337 HTMLHeadingElement : false,
338 HTMLHRElement : false,
339 HTMLHtmlElement : false,
340 HTMLIFrameElement : false,
341 HTMLImageElement : false,
342 HTMLInputElement : false,
343 HTMLIsIndexElement : false,
344 HTMLLabelElement : false,
345 HTMLLayerElement : false,
346 HTMLLegendElement : false,
347 HTMLLIElement : false,
348 HTMLLinkElement : false,
349 HTMLMapElement : false,
350 HTMLMenuElement : false,
351 HTMLMetaElement : false,
352 HTMLModElement : false,
353 HTMLObjectElement : false,
354 HTMLOListElement : false,
355 HTMLOptGroupElement : false,
356 HTMLOptionElement : false,
357 HTMLParagraphElement : false,
358 HTMLParamElement : false,
359 HTMLPreElement : false,
360 HTMLQuoteElement : false,
361 HTMLScriptElement : false,
362 HTMLSelectElement : false,
363 HTMLStyleElement : false,
364 HTMLTableCaptionElement: false,
365 HTMLTableCellElement : false,
366 HTMLTableColElement : false,
367 HTMLTableElement : false,
368 HTMLTableRowElement : false,
369 HTMLTableSectionElement: false,
370 HTMLTextAreaElement : false,
371 HTMLTitleElement : false,
372 HTMLUListElement : false,
373 HTMLVideoElement : false,
374 history : false,
375 Int16Array : false,
376 Int32Array : false,
377 Int8Array : false,
378 Image : false,
379 length : false,
380 localStorage : false,
381 location : false,
382 MessageChannel : false,
383 MessageEvent : false,
384 MessagePort : false,
385 moveBy : false,
386 moveTo : false,
387 MutationObserver : false,
388 name : false,
389 Node : false,
390 NodeFilter : false,
391 navigator : false,
392 onbeforeunload : true,
393 onblur : true,
394 onerror : true,
395 onfocus : true,
396 onload : true,
397 onresize : true,
398 onunload : true,
399 open : false,
400 openDatabase : false,
401 opener : false,
402 Option : false,
403 parent : false,
404 print : false,
405 removeEventListener : false,
406 resizeBy : false,
407 resizeTo : false,
408 screen : false,
409 scroll : false,
410 scrollBy : false,
411 scrollTo : false,
412 sessionStorage : false,
413 setInterval : false,
414 setTimeout : false,
415 SharedWorker : false,
416 status : false,
417 SVGAElement : false,
418 SVGAltGlyphDefElement: false,
419 SVGAltGlyphElement : false,
420 SVGAltGlyphItemElement: false,
421 SVGAngle : false,
422 SVGAnimateColorElement: false,
423 SVGAnimateElement : false,
424 SVGAnimateMotionElement: false,
425 SVGAnimateTransformElement: false,
426 SVGAnimatedAngle : false,
427 SVGAnimatedBoolean : false,
428 SVGAnimatedEnumeration: false,
429 SVGAnimatedInteger : false,
430 SVGAnimatedLength : false,
431 SVGAnimatedLengthList: false,
432 SVGAnimatedNumber : false,
433 SVGAnimatedNumberList: false,
434 SVGAnimatedPathData : false,
435 SVGAnimatedPoints : false,
436 SVGAnimatedPreserveAspectRatio: false,
437 SVGAnimatedRect : false,
438 SVGAnimatedString : false,
439 SVGAnimatedTransformList: false,
440 SVGAnimationElement : false,
441 SVGCSSRule : false,
442 SVGCircleElement : false,
443 SVGClipPathElement : false,
444 SVGColor : false,
445 SVGColorProfileElement: false,
446 SVGColorProfileRule : false,
447 SVGComponentTransferFunctionElement: false,
448 SVGCursorElement : false,
449 SVGDefsElement : false,
450 SVGDescElement : false,
451 SVGDocument : false,
452 SVGElement : false,
453 SVGElementInstance : false,
454 SVGElementInstanceList: false,
455 SVGEllipseElement : false,
456 SVGExternalResourcesRequired: false,
457 SVGFEBlendElement : false,
458 SVGFEColorMatrixElement: false,
459 SVGFEComponentTransferElement: false,
460 SVGFECompositeElement: false,
461 SVGFEConvolveMatrixElement: false,
462 SVGFEDiffuseLightingElement: false,
463 SVGFEDisplacementMapElement: false,
464 SVGFEDistantLightElement: false,
465 SVGFEDropShadowElement: false,
466 SVGFEFloodElement : false,
467 SVGFEFuncAElement : false,
468 SVGFEFuncBElement : false,
469 SVGFEFuncGElement : false,
470 SVGFEFuncRElement : false,
471 SVGFEGaussianBlurElement: false,
472 SVGFEImageElement : false,
473 SVGFEMergeElement : false,
474 SVGFEMergeNodeElement: false,
475 SVGFEMorphologyElement: false,
476 SVGFEOffsetElement : false,
477 SVGFEPointLightElement: false,
478 SVGFESpecularLightingElement: false,
479 SVGFESpotLightElement: false,
480 SVGFETileElement : false,
481 SVGFETurbulenceElement: false,
482 SVGFilterElement : false,
483 SVGFilterPrimitiveStandardAttributes: false,
484 SVGFitToViewBox : false,
485 SVGFontElement : false,
486 SVGFontFaceElement : false,
487 SVGFontFaceFormatElement: false,
488 SVGFontFaceNameElement: false,
489 SVGFontFaceSrcElement: false,
490 SVGFontFaceUriElement: false,
491 SVGForeignObjectElement: false,
492 SVGGElement : false,
493 SVGGlyphElement : false,
494 SVGGlyphRefElement : false,
495 SVGGradientElement : false,
496 SVGHKernElement : false,
497 SVGICCColor : false,
498 SVGImageElement : false,
499 SVGLangSpace : false,
500 SVGLength : false,
501 SVGLengthList : false,
502 SVGLineElement : false,
503 SVGLinearGradientElement: false,
504 SVGLocatable : false,
505 SVGMPathElement : false,
506 SVGMarkerElement : false,
507 SVGMaskElement : false,
508 SVGMatrix : false,
509 SVGMetadataElement : false,
510 SVGMissingGlyphElement: false,
511 SVGNumber : false,
512 SVGNumberList : false,
513 SVGPaint : false,
514 SVGPathElement : false,
515 SVGPathSeg : false,
516 SVGPathSegArcAbs : false,
517 SVGPathSegArcRel : false,
518 SVGPathSegClosePath : false,
519 SVGPathSegCurvetoCubicAbs: false,
520 SVGPathSegCurvetoCubicRel: false,
521 SVGPathSegCurvetoCubicSmoothAbs: false,
522 SVGPathSegCurvetoCubicSmoothRel: false,
523 SVGPathSegCurvetoQuadraticAbs: false,
524 SVGPathSegCurvetoQuadraticRel: false,
525 SVGPathSegCurvetoQuadraticSmoothAbs: false,
526 SVGPathSegCurvetoQuadraticSmoothRel: false,
527 SVGPathSegLinetoAbs : false,
528 SVGPathSegLinetoHorizontalAbs: false,
529 SVGPathSegLinetoHorizontalRel: false,
530 SVGPathSegLinetoRel : false,
531 SVGPathSegLinetoVerticalAbs: false,
532 SVGPathSegLinetoVerticalRel: false,
533 SVGPathSegList : false,
534 SVGPathSegMovetoAbs : false,
535 SVGPathSegMovetoRel : false,
536 SVGPatternElement : false,
537 SVGPoint : false,
538 SVGPointList : false,
539 SVGPolygonElement : false,
540 SVGPolylineElement : false,
541 SVGPreserveAspectRatio: false,
542 SVGRadialGradientElement: false,
543 SVGRect : false,
544 SVGRectElement : false,
545 SVGRenderingIntent : false,
546 SVGSVGElement : false,
547 SVGScriptElement : false,
548 SVGSetElement : false,
549 SVGStopElement : false,
550 SVGStringList : false,
551 SVGStylable : false,
552 SVGStyleElement : false,
553 SVGSwitchElement : false,
554 SVGSymbolElement : false,
555 SVGTRefElement : false,
556 SVGTSpanElement : false,
557 SVGTests : false,
558 SVGTextContentElement: false,
559 SVGTextElement : false,
560 SVGTextPathElement : false,
561 SVGTextPositioningElement: false,
562 SVGTitleElement : false,
563 SVGTransform : false,
564 SVGTransformList : false,
565 SVGTransformable : false,
566 SVGURIReference : false,
567 SVGUnitTypes : false,
568 SVGUseElement : false,
569 SVGVKernElement : false,
570 SVGViewElement : false,
571 SVGViewSpec : false,
572 SVGZoomAndPan : false,
573 TimeEvent : false,
574 top : false,
575 Uint16Array : false,
576 Uint32Array : false,
577 Uint8Array : false,
578 Uint8ClampedArray : false,
579 WebSocket : false,
580 window : false,
581 Worker : false,
582 XMLHttpRequest : false,
583 XMLSerializer : false,
584 XPathEvaluator : false,
585 XPathException : false,
586 XPathExpression : false,
587 XPathNSResolver : false,
588 XPathResult : false
589 };
590
591 exports.devel = {
592 alert : false,
593 confirm: false,
594 console: false,
595 Debug : false,
596 opera : false,
597 prompt : false
598 };
599
600 exports.worker = {
601 importScripts: true,
602 postMessage : true,
603 self : true
604 };
605
606 // Widely adopted global names that are not part of ECMAScript standard
607 exports.nonstandard = {
608 escape : false,
609 unescape: false
610 };
611
612 // Globals provided by popular JavaScript environments.
613
614 exports.couch = {
615 "require" : false,
616 respond : false,
617 getRow : false,
618 emit : false,
619 send : false,
620 start : false,
621 sum : false,
622 log : false,
623 exports : false,
624 module : false,
625 provides : false
626 };
627
628 exports.node = {
629 __filename : false,
630 __dirname : false,
631 Buffer : false,
632 DataView : false,
633 console : false,
634 exports : true, // In Node it is ok to exports = module.exports = foo();
635 GLOBAL : false,
636 global : false,
637 module : false,
638 process : false,
639 require : false,
640 setTimeout : false,
641 clearTimeout : false,
642 setInterval : false,
643 clearInterval : false,
644 setImmediate : false, // v0.9.1+
645 clearImmediate: false // v0.9.1+
646 };
647
648 exports.phantom = {
649 phantom : true,
650 require : true,
651 WebPage : true
652 };
653
654 exports.rhino = {
655 defineClass : false,
656 deserialize : false,
657 gc : false,
658 help : false,
659 importPackage: false,
660 "java" : false,
661 load : false,
662 loadClass : false,
663 print : false,
664 quit : false,
665 readFile : false,
666 readUrl : false,
667 runCommand : false,
668 seal : false,
669 serialize : false,
670 spawn : false,
671 sync : false,
672 toint32 : false,
673 version : false
674 };
675
676 exports.wsh = {
677 ActiveXObject : true,
678 Enumerator : true,
679 GetObject : true,
680 ScriptEngine : true,
681 ScriptEngineBuildVersion : true,
682 ScriptEngineMajorVersion : true,
683 ScriptEngineMinorVersion : true,
684 VBArray : true,
685 WSH : true,
686 WScript : true,
687 XDomainRequest : true
688 };
689
690 // Globals provided by popular JavaScript libraries.
691
692 exports.dojo = {
693 dojo : false,
694 dijit : false,
695 dojox : false,
696 define : false,
697 "require": false
698 };
699
700 exports.jquery = {
701 "$" : false,
702 jQuery : false
703 };
704
705 exports.mootools = {
706 "$" : false,
707 "$$" : false,
708 Asset : false,
709 Browser : false,
710 Chain : false,
711 Class : false,
712 Color : false,
713 Cookie : false,
714 Core : false,
715 Document : false,
716 DomReady : false,
717 DOMEvent : false,
718 DOMReady : false,
719 Drag : false,
720 Element : false,
721 Elements : false,
722 Event : false,
723 Events : false,
724 Fx : false,
725 Group : false,
726 Hash : false,
727 HtmlTable : false,
728 Iframe : false,
729 IframeShim : false,
730 InputValidator: false,
731 instanceOf : false,
732 Keyboard : false,
733 Locale : false,
734 Mask : false,
735 MooTools : false,
736 Native : false,
737 Options : false,
738 OverText : false,
739 Request : false,
740 Scroller : false,
741 Slick : false,
742 Slider : false,
743 Sortables : false,
744 Spinner : false,
745 Swiff : false,
746 Tips : false,
747 Type : false,
748 typeOf : false,
749 URI : false,
750 Window : false
751 };
752
753 exports.prototypejs = {
754 "$" : false,
755 "$$" : false,
756 "$A" : false,
757 "$F" : false,
758 "$H" : false,
759 "$R" : false,
760 "$break" : false,
761 "$continue" : false,
762 "$w" : false,
763 Abstract : false,
764 Ajax : false,
765 Class : false,
766 Enumerable : false,
767 Element : false,
768 Event : false,
769 Field : false,
770 Form : false,
771 Hash : false,
772 Insertion : false,
773 ObjectRange : false,
774 PeriodicalExecuter: false,
775 Position : false,
776 Prototype : false,
777 Selector : false,
778 Template : false,
779 Toggle : false,
780 Try : false,
781 Autocompleter : false,
782 Builder : false,
783 Control : false,
784 Draggable : false,
785 Draggables : false,
786 Droppables : false,
787 Effect : false,
788 Sortable : false,
789 SortableObserver : false,
790 Sound : false,
791 Scriptaculous : false
792 };
793
794 exports.yui = {
795 YUI : false,
796 Y : false,
797 YUI_config: false
798 };
799
800
801 })()
802 },{}],4:[function(require,module,exports){
803 "use strict";
804
805 var state = {
806 syntax: {},
807
808 reset: function () {
809 this.tokens = {
810 prev: null,
811 next: null,
812 curr: null
813 };
814
815 this.option = {};
816 this.ignored = {};
817 this.directive = {};
818 this.jsonMode = false;
819 this.jsonWarnings = [];
820 this.lines = [];
821 this.tab = "";
822 this.cache = {}; // Node.JS doesn't have Map. Sniff.
823 }
824 };
825
826 exports.state = state;
827
828 },{}],5:[function(require,module,exports){
829 (function(){"use strict";
830
831 exports.register = function (linter) {
832 // Check for properties named __proto__. This special property was
833 // deprecated and then re-introduced for ES6.
834
835 linter.on("Identifier", function style_scanProto(data) {
836 if (linter.getOption("proto")) {
837 return;
838 }
839
840 if (data.name === "__proto__") {
841 linter.warn("W103", {
842 line: data.line,
843 char: data.char,
844 data: [ data.name ]
845 });
846 }
847 });
848
849 // Check for properties named __iterator__. This is a special property
850 // available only in browsers with JavaScript 1.7 implementation.
851
852 linter.on("Identifier", function style_scanIterator(data) {
853 if (linter.getOption("iterator")) {
854 return;
855 }
856
857 if (data.name === "__iterator__") {
858 linter.warn("W104", {
859 line: data.line,
860 char: data.char,
861 data: [ data.name ]
862 });
863 }
864 });
865
866 // Check for dangling underscores.
867
868 linter.on("Identifier", function style_scanDangling(data) {
869 if (!linter.getOption("nomen")) {
870 return;
871 }
872
873 // Underscore.js
874 if (data.name === "_") {
875 return;
876 }
877
878 // In Node, __dirname and __filename should be ignored.
879 if (linter.getOption("node")) {
880 if (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) {
881 return;
882 }
883 }
884
885 if (/^(_+.*|.*_+)$/.test(data.name)) {
886 linter.warn("W105", {
887 line: data.line,
888 char: data.from,
889 data: [ "dangling '_'", data.name ]
890 });
891 }
892 });
893
894 // Check that all identifiers are using camelCase notation.
895 // Exceptions: names like MY_VAR and _myVar.
896
897 linter.on("Identifier", function style_scanCamelCase(data) {
898 if (!linter.getOption("camelcase")) {
899 return;
900 }
901
902 if (data.name.replace(/^_+/, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
903 linter.warn("W106", {
904 line: data.line,
905 char: data.from,
906 data: [ data.name ]
907 });
908 }
909 });
910
911 // Enforce consistency in style of quoting.
912
913 linter.on("String", function style_scanQuotes(data) {
914 var quotmark = linter.getOption("quotmark");
915 var code;
916
917 if (!quotmark) {
918 return;
919 }
920
921 // If quotmark is set to 'single' warn about all double-quotes.
922
923 if (quotmark === "single" && data.quote !== "'") {
924 code = "W109";
925 }
926
927 // If quotmark is set to 'double' warn about all single-quotes.
928
929 if (quotmark === "double" && data.quote !== "\"") {
930 code = "W108";
931 }
932
933 // If quotmark is set to true, remember the first quotation style
934 // and then warn about all others.
935
936 if (quotmark === true) {
937 if (!linter.getCache("quotmark")) {
938 linter.setCache("quotmark", data.quote);
939 }
940
941 if (linter.getCache("quotmark") !== data.quote) {
942 code = "W110";
943 }
944 }
945
946 if (code) {
947 linter.warn(code, {
948 line: data.line,
949 char: data.char,
950 });
951 }
952 });
953
954 linter.on("Number", function style_scanNumbers(data) {
955 if (data.value.charAt(0) === ".") {
956 // Warn about a leading decimal point.
957 linter.warn("W008", {
958 line: data.line,
959 char: data.char,
960 data: [ data.value ]
961 });
962 }
963
964 if (data.value.substr(data.value.length - 1) === ".") {
965 // Warn about a trailing decimal point.
966 linter.warn("W047", {
967 line: data.line,
968 char: data.char,
969 data: [ data.value ]
970 });
971 }
972
973 if (/^00+/.test(data.value)) {
974 // Multiple leading zeroes.
975 linter.warn("W046", {
976 line: data.line,
977 char: data.char,
978 data: [ data.value ]
979 });
980 }
981 });
982
983 // Warn about script URLs.
984
985 linter.on("String", function style_scanJavaScriptURLs(data) {
986 var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
987
988 if (linter.getOption("scripturl")) {
989 return;
990 }
991
992 if (re.test(data.value)) {
993 linter.warn("W107", {
994 line: data.line,
995 char: data.char
996 });
997 }
998 });
999 };
1000 })()
1001 },{}],6:[function(require,module,exports){
1002 /*
1003 * Regular expressions. Some of these are stupidly long.
1004 */
1005
1006 /*jshint maxlen:1000 */
1007
1008 "use string";
1009
1010 // Unsafe comment or string (ax)
1011 exports.unsafeString =
1012 /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
1013
1014 // Unsafe characters that are silently deleted by one or more browsers (cx)
1015 exports.unsafeChars =
1016 /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
1017
1018 // Characters in strings that need escaping (nx and nxg)
1019 exports.needEsc =
1020 /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
1021
1022 exports.needEscGlobal =
1023 /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
1024
1025 // Star slash (lx)
1026 exports.starSlash = /\*\//;
1027
1028 // Identifier (ix)
1029 exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
1030
1031 // JavaScript URL (jx)
1032 exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
1033
1034 // Catches /* falls through */ comments (ft)
1035 //exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
1036 exports.fallsThrough = /^\s*\/\/\s*Falls?\sthrough.*\s*$/;
1037
1038 },{}],7:[function(require,module,exports){
1039 (function(global){/*global window, global*/
1040 var util = require("util")
1041 var assert = require("assert")
1042
1043 var slice = Array.prototype.slice
1044 var console
1045 var times = {}
1046
1047 if (typeof global !== "undefined" && global.console) {
1048 console = global.console
1049 } else if (typeof window !== "undefined" && window.console) {
1050 console = window.console
1051 } else {
1052 console = window.console = {}
1053 }
1054
1055 var functions = [
1056 [log, "log"]
1057 , [info, "info"]
1058 , [warn, "warn"]
1059 , [error, "error"]
1060 , [time, "time"]
1061 , [timeEnd, "timeEnd"]
1062 , [trace, "trace"]
1063 , [dir, "dir"]
1064 , [assert, "assert"]
1065 ]
1066
1067 for (var i = 0; i < functions.length; i++) {
1068 var tuple = functions[i]
1069 var f = tuple[0]
1070 var name = tuple[1]
1071
1072 if (!console[name]) {
1073 console[name] = f
1074 }
1075 }
1076
1077 module.exports = console
1078
1079 function log() {}
1080
1081 function info() {
1082 console.log.apply(console, arguments)
1083 }
1084
1085 function warn() {
1086 console.log.apply(console, arguments)
1087 }
1088
1089 function error() {
1090 console.warn.apply(console, arguments)
1091 }
1092
1093 function time(label) {
1094 times[label] = Date.now()
1095 }
1096
1097 function timeEnd(label) {
1098 var time = times[label]
1099 if (!time) {
1100 throw new Error("No such label: " + label)
1101 }
1102
1103 var duration = Date.now() - time
1104 console.log(label + ": " + duration + "ms")
1105 }
1106
1107 function trace() {
1108 var err = new Error()
1109 err.name = "Trace"
1110 err.message = util.format.apply(null, arguments)
1111 console.error(err.stack)
1112 }
1113
1114 function dir(object) {
1115 console.log(util.inspect(object) + "\n")
1116 }
1117
1118 function assert(expression) {
1119 if (!expression) {
1120 var arr = slice.call(arguments, 1)
1121 assert.ok(false, util.format.apply(null, arr))
1122 }
1123 }
1124
1125 })(window)
1126 },{"util":8,"assert":9}],10:[function(require,module,exports){
1127 (function(){/*
1128 * Lexical analysis and token construction.
1129 */
1130
1131 "use strict";
1132
1133 var _ = require("underscore");
1134 var events = require("events");
1135 var reg = require("./reg.js");
1136 var state = require("./state.js").state;
1137
1138 // Some of these token types are from JavaScript Parser API
1139 // while others are specific to JSHint parser.
1140 // JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
1141
1142 var Token = {
1143 Identifier: 1,
1144 Punctuator: 2,
1145 NumericLiteral: 3,
1146 StringLiteral: 4,
1147 Comment: 5,
1148 Keyword: 6,
1149 NullLiteral: 7,
1150 BooleanLiteral: 8,
1151 RegExp: 9
1152 };
1153
1154 // This is auto generated from the unicode tables.
1155 // The tables are at:
1156 // http://www.fileformat.info/info/unicode/category/Lu/list.htm
1157 // http://www.fileformat.info/info/unicode/category/Ll/list.htm
1158 // http://www.fileformat.info/info/unicode/category/Lt/list.htm
1159 // http://www.fileformat.info/info/unicode/category/Lm/list.htm
1160 // http://www.fileformat.info/info/unicode/category/Lo/list.htm
1161 // http://www.fileformat.info/info/unicode/category/Nl/list.htm
1162
1163 var unicodeLetterTable = [
1164 170, 170, 181, 181, 186, 186, 192, 214,
1165 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,
1166 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,
1167 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,
1168 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,
1169 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,
1170 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,
1171 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,
1172 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,
1173 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,
1174 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,
1175 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,
1176 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,
1177 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,
1178 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,
1179 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,
1180 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,
1181 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,
1182 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,
1183 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,
1184 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,
1185 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,
1186 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,
1187 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,
1188 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,
1189 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,
1190 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,
1191 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
1192 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,
1193 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,
1194 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,
1195 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,
1196 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,
1197 4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,
1198 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,
1199 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,
1200 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,
1201 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,
1202 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,
1203 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,
1204 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,
1205 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,
1206 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,
1207 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,
1208 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,
1209 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,
1210 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,
1211 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,
1212 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,
1213 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,
1214 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
1215 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,
1216 11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,
1217 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,
1218 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,
1219 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,
1220 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,
1221 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,
1222 12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,
1223 19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,
1224 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,
1225 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,
1226 42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,
1227 43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,
1228 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,
1229 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,
1230 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,
1231 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,
1232 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,
1233 43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,
1234 43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,
1235 55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,
1236 64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,
1237 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,
1238 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,
1239 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,
1240 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,
1241 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,
1242 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,
1243 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,
1244 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,
1245 66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,
1246 66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,
1247 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,
1248 67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,
1249 68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,
1250 68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,
1251 69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,
1252 92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,
1253 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,
1254 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,
1255 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,
1256 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,
1257 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,
1258 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,
1259 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,
1260 131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,
1261 177984, 177984, 178205, 178205, 194560, 195101
1262 ];
1263
1264 var identifierStartTable = [];
1265
1266 for (var i = 0; i < 128; i++) {
1267 identifierStartTable[i] =
1268 i === 36 || // $
1269 i >= 65 && i <= 90 || // A-Z
1270 i === 95 || // _
1271 i >= 97 && i <= 122; // a-z
1272 }
1273
1274 var identifierPartTable = [];
1275
1276 for (var i = 0; i < 128; i++) {
1277 identifierPartTable[i] =
1278 identifierStartTable[i] || // $, _, A-Z, a-z
1279 i >= 48 && i <= 57; // 0-9
1280 }
1281
1282 // Object that handles postponed lexing verifications that checks the parsed
1283 // environment state.
1284
1285 function asyncTrigger() {
1286 var _checks = [];
1287
1288 return {
1289 push: function (fn) {
1290 _checks.push(fn);
1291 },
1292
1293 check: function () {
1294 for (var check in _checks) {
1295 _checks[check]();
1296 }
1297
1298 _checks.splice(0, _checks.length);
1299 }
1300 };
1301 }
1302
1303 /*
1304 * Lexer for JSHint.
1305 *
1306 * This object does a char-by-char scan of the provided source code
1307 * and produces a sequence of tokens.
1308 *
1309 * var lex = new Lexer("var i = 0;");
1310 * lex.start();
1311 * lex.token(); // returns the next token
1312 *
1313 * You have to use the token() method to move the lexer forward
1314 * but you don't have to use its return value to get tokens. In addition
1315 * to token() method returning the next token, the Lexer object also
1316 * emits events.
1317 *
1318 * lex.on("Identifier", function (data) {
1319 * if (data.name.indexOf("_") >= 0) {
1320 * // Produce a warning.
1321 * }
1322 * });
1323 *
1324 * Note that the token() method returns tokens in a JSLint-compatible
1325 * format while the event emitter uses a slightly modified version of
1326 * Mozilla's JavaScript Parser API. Eventually, we will move away from
1327 * JSLint format.
1328 */
1329 function Lexer(source) {
1330 var lines = source;
1331
1332 if (typeof lines === "string") {
1333 lines = lines
1334 .replace(/\r\n/g, "\n")
1335 .replace(/\r/g, "\n")
1336 .split("\n");
1337 }
1338
1339 // If the first line is a shebang (#!), make it a blank and move on.
1340 // Shebangs are used by Node scripts.
1341
1342 if (lines[0] && lines[0].substr(0, 2) === "#!") {
1343 lines[0] = "";
1344 }
1345
1346 this.emitter = new events.EventEmitter();
1347 this.source = source;
1348 this.lines = lines;
1349 this.prereg = true;
1350
1351 this.line = 0;
1352 this.char = 1;
1353 this.from = 1;
1354 this.input = "";
1355
1356 for (var i = 0; i < state.option.indent; i += 1) {
1357 state.tab += " ";
1358 }
1359 }
1360
1361 Lexer.prototype = {
1362 _lines: [],
1363
1364 get lines() {
1365 this._lines = state.lines;
1366 return this._lines;
1367 },
1368
1369 set lines(val) {
1370 this._lines = val;
1371 state.lines = this._lines;
1372 },
1373
1374 /*
1375 * Return the next i character without actually moving the
1376 * char pointer.
1377 */
1378 peek: function (i) {
1379 return this.input.charAt(i || 0);
1380 },
1381
1382 /*
1383 * Move the char pointer forward i times.
1384 */
1385 skip: function (i) {
1386 i = i || 1;
1387 this.char += i;
1388 this.input = this.input.slice(i);
1389 },
1390
1391 /*
1392 * Subscribe to a token event. The API for this method is similar
1393 * Underscore.js i.e. you can subscribe to multiple events with
1394 * one call:
1395 *
1396 * lex.on("Identifier Number", function (data) {
1397 * // ...
1398 * });
1399 */
1400 on: function (names, listener) {
1401 names.split(" ").forEach(function (name) {
1402 this.emitter.on(name, listener);
1403 }.bind(this));
1404 },
1405
1406 /*
1407 * Trigger a token event. All arguments will be passed to each
1408 * listener.
1409 */
1410 trigger: function () {
1411 this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
1412 },
1413
1414 /*
1415 * Postpone a token event. the checking condition is set as
1416 * last parameter, and the trigger function is called in a
1417 * stored callback. To be later called using the check() function
1418 * by the parser. This avoids parser's peek() to give the lexer
1419 * a false context.
1420 */
1421 triggerAsync: function (type, args, checks, fn) {
1422 checks.push(function () {
1423 if (fn()) {
1424 this.trigger(type, args);
1425 }
1426 }.bind(this));
1427 },
1428
1429 /*
1430 * Extract a punctuator out of the next sequence of characters
1431 * or return 'null' if its not possible.
1432 *
1433 * This method's implementation was heavily influenced by the
1434 * scanPunctuator function in the Esprima parser's source code.
1435 */
1436 scanPunctuator: function () {
1437 var ch1 = this.peek();
1438 var ch2, ch3, ch4;
1439
1440 switch (ch1) {
1441 // Most common single-character punctuators
1442 case ".":
1443 if ((/^[0-9]$/).test(this.peek(1))) {
1444 return null;
1445 }
1446 if (this.peek(1) === "." && this.peek(2) === ".") {
1447 return {
1448 type: Token.Punctuator,
1449 value: "..."
1450 };
1451 }
1452 /* falls through */
1453 case "(":
1454 case ")":
1455 case ";":
1456 case ",":
1457 case "{":
1458 case "}":
1459 case "[":
1460 case "]":
1461 case ":":
1462 case "~":
1463 case "?":
1464 return {
1465 type: Token.Punctuator,
1466 value: ch1
1467 };
1468
1469 // A pound sign (for Node shebangs)
1470 case "#":
1471 return {
1472 type: Token.Punctuator,
1473 value: ch1
1474 };
1475
1476 // We're at the end of input
1477 case "":
1478 return null;
1479 }
1480
1481 // Peek more characters
1482
1483 ch2 = this.peek(1);
1484 ch3 = this.peek(2);
1485 ch4 = this.peek(3);
1486
1487 // 4-character punctuator: >>>=
1488
1489 if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
1490 return {
1491 type: Token.Punctuator,
1492 value: ">>>="
1493 };
1494 }
1495
1496 // 3-character punctuators: === !== >>> <<= >>=
1497
1498 if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
1499 return {
1500 type: Token.Punctuator,
1501 value: "==="
1502 };
1503 }
1504
1505 if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
1506 return {
1507 type: Token.Punctuator,
1508 value: "!=="
1509 };
1510 }
1511
1512 if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
1513 return {
1514 type: Token.Punctuator,
1515 value: ">>>"
1516 };
1517 }
1518
1519 if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
1520 return {
1521 type: Token.Punctuator,
1522 value: "<<="
1523 };
1524 }
1525
1526 if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
1527 return {
1528 type: Token.Punctuator,
1529 value: ">>="
1530 };
1531 }
1532
1533 // Fat arrow punctuator
1534 if (ch1 === "=" && ch2 === ">") {
1535 return {
1536 type: Token.Punctuator,
1537 value: ch1 + ch2
1538 };
1539 }
1540
1541 // 2-character punctuators: <= >= == != ++ -- << >> && ||
1542 // += -= *= %= &= |= ^= (but not /=, see below)
1543 if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
1544 return {
1545 type: Token.Punctuator,
1546 value: ch1 + ch2
1547 };
1548 }
1549
1550 if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
1551 if (ch2 === "=") {
1552 return {
1553 type: Token.Punctuator,
1554 value: ch1 + ch2
1555 };
1556 }
1557
1558 return {
1559 type: Token.Punctuator,
1560 value: ch1
1561 };
1562 }
1563
1564 // Special case: /=. We need to make sure that this is an
1565 // operator and not a regular expression.
1566
1567 if (ch1 === "/") {
1568 if (ch2 === "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input)) {
1569 // /= is not a part of a regular expression, return it as a
1570 // punctuator.
1571 return {
1572 type: Token.Punctuator,
1573 value: "/="
1574 };
1575 }
1576
1577 return {
1578 type: Token.Punctuator,
1579 value: "/"
1580 };
1581 }
1582
1583 return null;
1584 },
1585
1586 /*
1587 * Extract a comment out of the next sequence of characters and/or
1588 * lines or return 'null' if its not possible. Since comments can
1589 * span across multiple lines this method has to move the char
1590 * pointer.
1591 *
1592 * In addition to normal JavaScript comments (// and /*) this method
1593 * also recognizes JSHint- and JSLint-specific comments such as
1594 * /*jshint, /*jslint, /*globals and so on.
1595 */
1596 scanComments: function () {
1597 var ch1 = this.peek();
1598 var ch2 = this.peek(1);
1599 var rest = this.input.substr(2);
1600 var startLine = this.line;
1601 var startChar = this.char;
1602
1603 // Create a comment token object and make sure it
1604 // has all the data JSHint needs to work with special
1605 // comments.
1606
1607 function commentToken(label, body, opt) {
1608 var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
1609 var isSpecial = false;
1610 var value = label + body;
1611 var commentType = "plain";
1612 opt = opt || {};
1613
1614 if (opt.isMultiline) {
1615 value += "*/";
1616 }
1617
1618 special.forEach(function (str) {
1619 if (isSpecial) {
1620 return;
1621 }
1622
1623 // Don't recognize any special comments other than jshint for single-line
1624 // comments. This introduced many problems with legit comments.
1625 if (label === "//" && str !== "jshint") {
1626 return;
1627 }
1628
1629 if (body.substr(0, str.length) === str) {
1630 isSpecial = true;
1631 label = label + str;
1632 body = body.substr(str.length);
1633 }
1634
1635 if (!isSpecial && body.charAt(0) === " " && body.substr(1, str.length) === str) {
1636 isSpecial = true;
1637 label = label + " " + str;
1638 body = body.substr(str.length + 1);
1639 }
1640
1641 if (!isSpecial) {
1642 return;
1643 }
1644
1645 switch (str) {
1646 case "member":
1647 commentType = "members";
1648 break;
1649 case "global":
1650 commentType = "globals";
1651 break;
1652 default:
1653 commentType = str;
1654 }
1655 });
1656
1657 return {
1658 type: Token.Comment,
1659 commentType: commentType,
1660 value: value,
1661 body: body,
1662 isSpecial: isSpecial,
1663 isMultiline: opt.isMultiline || false,
1664 isMalformed: opt.isMalformed || false
1665 };
1666 }
1667
1668 // End of unbegun comment. Raise an error and skip that input.
1669 if (ch1 === "*" && ch2 === "/") {
1670 this.trigger("error", {
1671 code: "E018",
1672 line: startLine,
1673 character: startChar
1674 });
1675
1676 this.skip(2);
1677 return null;
1678 }
1679
1680 // Comments must start either with // or /*
1681 if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
1682 return null;
1683 }
1684
1685 // One-line comment
1686 if (ch2 === "/") {
1687 this.skip(this.input.length); // Skip to the EOL.
1688 return commentToken("//", rest);
1689 }
1690
1691 var body = "";
1692
1693 /* Multi-line comment */
1694 if (ch2 === "*") {
1695 this.skip(2);
1696
1697 while (this.peek() !== "*" || this.peek(1) !== "/") {
1698 if (this.peek() === "") { // End of Line
1699 body += "\n";
1700
1701 // If we hit EOF and our comment is still unclosed,
1702 // trigger an error and end the comment implicitly.
1703 if (!this.nextLine()) {
1704 this.trigger("error", {
1705 code: "E017",
1706 line: startLine,
1707 character: startChar
1708 });
1709
1710 return commentToken("/*", body, {
1711 isMultiline: true,
1712 isMalformed: true
1713 });
1714 }
1715 } else {
1716 body += this.peek();
1717 this.skip();
1718 }
1719 }
1720
1721 this.skip(2);
1722 return commentToken("/*", body, { isMultiline: true });
1723 }
1724 },
1725
1726 /*
1727 * Extract a keyword out of the next sequence of characters or
1728 * return 'null' if its not possible.
1729 */
1730 scanKeyword: function () {
1731 var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
1732 var keywords = [
1733 "if", "in", "do", "var", "for", "new",
1734 "try", "let", "this", "else", "case",
1735 "void", "with", "enum", "while", "break",
1736 "catch", "throw", "const", "yield", "class",
1737 "super", "return", "typeof", "delete",
1738 "switch", "export", "import", "default",
1739 "finally", "extends", "function", "continue",
1740 "debugger", "instanceof"
1741 ];
1742
1743 if (result && keywords.indexOf(result[0]) >= 0) {
1744 return {
1745 type: Token.Keyword,
1746 value: result[0]
1747 };
1748 }
1749
1750 return null;
1751 },
1752
1753 /*
1754 * Extract a JavaScript identifier out of the next sequence of
1755 * characters or return 'null' if its not possible. In addition,
1756 * to Identifier this method can also produce BooleanLiteral
1757 * (true/false) and NullLiteral (null).
1758 */
1759 scanIdentifier: function () {
1760 var id = "";
1761 var index = 0;
1762 var type, char;
1763
1764 // Detects any character in the Unicode categories "Uppercase
1765 // letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter
1766 // (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or
1767 // "Letter number (Nl)".
1768 //
1769 // Both approach and unicodeLetterTable were borrowed from
1770 // Google's Traceur.
1771
1772 function isUnicodeLetter(code) {
1773 for (var i = 0; i < unicodeLetterTable.length;) {
1774 if (code < unicodeLetterTable[i++]) {
1775 return false;
1776 }
1777
1778 if (code <= unicodeLetterTable[i++]) {
1779 return true;
1780 }
1781 }
1782
1783 return false;
1784 }
1785
1786 function isHexDigit(str) {
1787 return (/^[0-9a-fA-F]$/).test(str);
1788 }
1789
1790 var readUnicodeEscapeSequence = function () {
1791 /*jshint validthis:true */
1792 index += 1;
1793
1794 if (this.peek(index) !== "u") {
1795 return null;
1796 }
1797
1798 var ch1 = this.peek(index + 1);
1799 var ch2 = this.peek(index + 2);
1800 var ch3 = this.peek(index + 3);
1801 var ch4 = this.peek(index + 4);
1802 var code;
1803
1804 if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
1805 code = parseInt(ch1 + ch2 + ch3 + ch4, 16);
1806
1807 if (isUnicodeLetter(code)) {
1808 index += 5;
1809 return "\\u" + ch1 + ch2 + ch3 + ch4;
1810 }
1811
1812 return null;
1813 }
1814
1815 return null;
1816 }.bind(this);
1817
1818 var getIdentifierStart = function () {
1819 /*jshint validthis:true */
1820 var chr = this.peek(index);
1821 var code = chr.charCodeAt(0);
1822
1823 if (code === 92) {
1824 return readUnicodeEscapeSequence();
1825 }
1826
1827 if (code < 128) {
1828 if (identifierStartTable[code]) {
1829 index += 1;
1830 return chr;
1831 }
1832
1833 return null;
1834 }
1835
1836 if (isUnicodeLetter(code)) {
1837 index += 1;
1838 return chr;
1839 }
1840
1841 return null;
1842 }.bind(this);
1843
1844 var getIdentifierPart = function () {
1845 /*jshint validthis:true */
1846 var chr = this.peek(index);
1847 var code = chr.charCodeAt(0);
1848
1849 if (code === 92) {
1850 return readUnicodeEscapeSequence();
1851 }
1852
1853 if (code < 128) {
1854 if (identifierPartTable[code]) {
1855 index += 1;
1856 return chr;
1857 }
1858
1859 return null;
1860 }
1861
1862 if (isUnicodeLetter(code)) {
1863 index += 1;
1864 return chr;
1865 }
1866
1867 return null;
1868 }.bind(this);
1869
1870 char = getIdentifierStart();
1871 if (char === null) {
1872 return null;
1873 }
1874
1875 id = char;
1876 for (;;) {
1877 char = getIdentifierPart();
1878
1879 if (char === null) {
1880 break;
1881 }
1882
1883 id += char;
1884 }
1885
1886 switch (id) {
1887 case "true":
1888 case "false":
1889 type = Token.BooleanLiteral;
1890 break;
1891 case "null":
1892 type = Token.NullLiteral;
1893 break;
1894 default:
1895 type = Token.Identifier;
1896 }
1897
1898 return {
1899 type: type,
1900 value: id
1901 };
1902 },
1903
1904 /*
1905 * Extract a numeric literal out of the next sequence of
1906 * characters or return 'null' if its not possible. This method
1907 * supports all numeric literals described in section 7.8.3
1908 * of the EcmaScript 5 specification.
1909 *
1910 * This method's implementation was heavily influenced by the
1911 * scanNumericLiteral function in the Esprima parser's source code.
1912 */
1913 scanNumericLiteral: function () {
1914 var index = 0;
1915 var value = "";
1916 var length = this.input.length;
1917 var char = this.peek(index);
1918 var bad;
1919
1920 function isDecimalDigit(str) {
1921 return (/^[0-9]$/).test(str);
1922 }
1923
1924 function isOctalDigit(str) {
1925 return (/^[0-7]$/).test(str);
1926 }
1927
1928 function isHexDigit(str) {
1929 return (/^[0-9a-fA-F]$/).test(str);
1930 }
1931
1932 function isIdentifierStart(ch) {
1933 return (ch === "$") || (ch === "_") || (ch === "\\") ||
1934 (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
1935 }
1936
1937 // Numbers must start either with a decimal digit or a point.
1938
1939 if (char !== "." && !isDecimalDigit(char)) {
1940 return null;
1941 }
1942
1943 if (char !== ".") {
1944 value = this.peek(index);
1945 index += 1;
1946 char = this.peek(index);
1947
1948 if (value === "0") {
1949 // Base-16 numbers.
1950 if (char === "x" || char === "X") {
1951 index += 1;
1952 value += char;
1953
1954 while (index < length) {
1955 char = this.peek(index);
1956 if (!isHexDigit(char)) {
1957 break;
1958 }
1959 value += char;
1960 index += 1;
1961 }
1962
1963 if (value.length <= 2) { // 0x
1964 return {
1965 type: Token.NumericLiteral,
1966 value: value,
1967 isMalformed: true
1968 };
1969 }
1970
1971 if (index < length) {
1972 char = this.peek(index);
1973 if (isIdentifierStart(char)) {
1974 return null;
1975 }
1976 }
1977
1978 return {
1979 type: Token.NumericLiteral,
1980 value: value,
1981 base: 16,
1982 isMalformed: false
1983 };
1984 }
1985
1986 // Base-8 numbers.
1987 if (isOctalDigit(char)) {
1988 index += 1;
1989 value += char;
1990 bad = false;
1991
1992 while (index < length) {
1993 char = this.peek(index);
1994
1995 // Numbers like '019' (note the 9) are not valid octals
1996 // but we still parse them and mark as malformed.
1997
1998 if (isDecimalDigit(char)) {
1999 bad = true;
2000 } else if (!isOctalDigit(char)) {
2001 break;
2002 }
2003 value += char;
2004 index += 1;
2005 }
2006
2007 if (index < length) {
2008 char = this.peek(index);
2009 if (isIdentifierStart(char)) {
2010 return null;
2011 }
2012 }
2013
2014 return {
2015 type: Token.NumericLiteral,
2016 value: value,
2017 base: 8,
2018 isMalformed: false
2019 };
2020 }
2021
2022 // Decimal numbers that start with '0' such as '09' are illegal
2023 // but we still parse them and return as malformed.
2024
2025 if (isDecimalDigit(char)) {
2026 index += 1;
2027 value += char;
2028 }
2029 }
2030
2031 while (index < length) {
2032 char = this.peek(index);
2033 if (!isDecimalDigit(char)) {
2034 break;
2035 }
2036 value += char;
2037 index += 1;
2038 }
2039 }
2040
2041 // Decimal digits.
2042
2043 if (char === ".") {
2044 value += char;
2045 index += 1;
2046
2047 while (index < length) {
2048 char = this.peek(index);
2049 if (!isDecimalDigit(char)) {
2050 break;
2051 }
2052 value += char;
2053 index += 1;
2054 }
2055 }
2056
2057 // Exponent part.
2058
2059 if (char === "e" || char === "E") {
2060 value += char;
2061 index += 1;
2062 char = this.peek(index);
2063
2064 if (char === "+" || char === "-") {
2065 value += this.peek(index);
2066 index += 1;
2067 }
2068
2069 char = this.peek(index);
2070 if (isDecimalDigit(char)) {
2071 value += char;
2072 index += 1;
2073
2074 while (index < length) {
2075 char = this.peek(index);
2076 if (!isDecimalDigit(char)) {
2077 break;
2078 }
2079 value += char;
2080 index += 1;
2081 }
2082 } else {
2083 return null;
2084 }
2085 }
2086
2087 if (index < length) {
2088 char = this.peek(index);
2089 if (isIdentifierStart(char)) {
2090 return null;
2091 }
2092 }
2093
2094 return {
2095 type: Token.NumericLiteral,
2096 value: value,
2097 base: 10,
2098 isMalformed: !isFinite(value)
2099 };
2100 },
2101
2102 /*
2103 * Extract a string out of the next sequence of characters and/or
2104 * lines or return 'null' if its not possible. Since strings can
2105 * span across multiple lines this method has to move the char
2106 * pointer.
2107 *
2108 * This method recognizes pseudo-multiline JavaScript strings:
2109 *
2110 * var str = "hello\
2111 * world";
2112 */
2113 scanStringLiteral: function (checks) {
2114 /*jshint loopfunc:true */
2115 var quote = this.peek();
2116
2117 // String must start with a quote.
2118 if (quote !== "\"" && quote !== "'") {
2119 return null;
2120 }
2121
2122 // In JSON strings must always use double quotes.
2123 this.triggerAsync("warning", {
2124 code: "W108",
2125 line: this.line,
2126 character: this.char // +1?
2127 }, checks, function () { return state.jsonMode && quote !== "\""; });
2128
2129 var value = "";
2130 var startLine = this.line;
2131 var startChar = this.char;
2132 var allowNewLine = false;
2133
2134 this.skip();
2135
2136 while (this.peek() !== quote) {
2137 while (this.peek() === "") { // End Of Line
2138
2139 // If an EOL is not preceded by a backslash, show a warning
2140 // and proceed like it was a legit multi-line string where
2141 // author simply forgot to escape the newline symbol.
2142 //
2143 // Another approach is to implicitly close a string on EOL
2144 // but it generates too many false positives.
2145
2146 if (!allowNewLine) {
2147 this.trigger("warning", {
2148 code: "W112",
2149 line: this.line,
2150 character: this.char
2151 });
2152 } else {
2153 allowNewLine = false;
2154
2155 // Otherwise show a warning if multistr option was not set.
2156 // For JSON, show warning no matter what.
2157
2158 this.triggerAsync("warning", {
2159 code: "W043",
2160 line: this.line,
2161 character: this.char
2162 }, checks, function () { return !state.option.multistr; });
2163
2164 this.triggerAsync("warning", {
2165 code: "W042",
2166 line: this.line,
2167 character: this.char
2168 }, checks, function () { return state.jsonMode && state.option.multistr; });
2169 }
2170
2171 // If we get an EOF inside of an unclosed string, show an
2172 // error and implicitly close it at the EOF point.
2173
2174 if (!this.nextLine()) {
2175 this.trigger("error", {
2176 code: "E029",
2177 line: startLine,
2178 character: startChar
2179 });
2180
2181 return {
2182 type: Token.StringLiteral,
2183 value: value,
2184 isUnclosed: true,
2185 quote: quote
2186 };
2187 }
2188 }
2189
2190 allowNewLine = false;
2191 var char = this.peek();
2192 var jump = 1; // A length of a jump, after we're done
2193 // parsing this character.
2194
2195 if (char < " ") {
2196 // Warn about a control character in a string.
2197 this.trigger("warning", {
2198 code: "W113",
2199 line: this.line,
2200 character: this.char,
2201 data: [ "<non-printable>" ]
2202 });
2203 }
2204
2205 // Special treatment for some escaped characters.
2206
2207 if (char === "\\") {
2208 this.skip();
2209 char = this.peek();
2210
2211 switch (char) {
2212 case "'":
2213 this.triggerAsync("warning", {
2214 code: "W114",
2215 line: this.line,
2216 character: this.char,
2217 data: [ "\\'" ]
2218 }, checks, function () {return state.jsonMode; });
2219 break;
2220 case "b":
2221 char = "\b";
2222 break;
2223 case "f":
2224 char = "\f";
2225 break;
2226 case "n":
2227 char = "\n";
2228 break;
2229 case "r":
2230 char = "\r";
2231 break;
2232 case "t":
2233 char = "\t";
2234 break;
2235 case "0":
2236 char = "\0";
2237
2238 // Octal literals fail in strict mode.
2239 // Check if the number is between 00 and 07.
2240 var n = parseInt(this.peek(1), 10);
2241 this.triggerAsync("warning", {
2242 code: "W115",
2243 line: this.line,
2244 character: this.char
2245 }, checks,
2246 function () { return n >= 0 && n <= 7 && state.directive["use strict"]; });
2247 break;
2248 case "u":
2249 char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));
2250 jump = 5;
2251 break;
2252 case "v":
2253 this.triggerAsync("warning", {
2254 code: "W114",
2255 line: this.line,
2256 character: this.char,
2257 data: [ "\\v" ]
2258 }, checks, function () { return state.jsonMode; });
2259
2260 char = "\v";
2261 break;
2262 case "x":
2263 var x = parseInt(this.input.substr(1, 2), 16);
2264
2265 this.triggerAsync("warning", {
2266 code: "W114",
2267 line: this.line,
2268 character: this.char,
2269 data: [ "\\x-" ]
2270 }, checks, function () { return state.jsonMode; });
2271
2272 char = String.fromCharCode(x);
2273 jump = 3;
2274 break;
2275 case "\\":
2276 case "\"":
2277 case "/":
2278 break;
2279 case "":
2280 allowNewLine = true;
2281 char = "";
2282 break;
2283 case "!":
2284 if (value.slice(value.length - 2) === "<") {
2285 break;
2286 }
2287
2288 /*falls through */
2289 default:
2290 // Weird escaping.
2291 this.trigger("warning", {
2292 code: "W044",
2293 line: this.line,
2294 character: this.char
2295 });
2296 }
2297 }
2298
2299 value += char;
2300 this.skip(jump);
2301 }
2302
2303 this.skip();
2304 return {
2305 type: Token.StringLiteral,
2306 value: value,
2307 isUnclosed: false,
2308 quote: quote
2309 };
2310 },
2311
2312 /*
2313 * Extract a regular expression out of the next sequence of
2314 * characters and/or lines or return 'null' if its not possible.
2315 *
2316 * This method is platform dependent: it accepts almost any
2317 * regular expression values but then tries to compile and run
2318 * them using system's RegExp object. This means that there are
2319 * rare edge cases where one JavaScript engine complains about
2320 * your regular expression while others don't.
2321 */
2322 scanRegExp: function () {
2323 var index = 0;
2324 var length = this.input.length;
2325 var char = this.peek();
2326 var value = char;
2327 var body = "";
2328 var flags = [];
2329 var malformed = false;
2330 var isCharSet = false;
2331 var terminated;
2332
2333 var scanUnexpectedChars = function () {
2334 // Unexpected control character
2335 if (char < " ") {
2336 malformed = true;
2337 this.trigger("warning", {
2338 code: "W048",
2339 line: this.line,
2340 character: this.char
2341 });
2342 }
2343
2344 // Unexpected escaped character
2345 if (char === "<") {
2346 malformed = true;
2347 this.trigger("warning", {
2348 code: "W049",
2349 line: this.line,
2350 character: this.char,
2351 data: [ char ]
2352 });
2353 }
2354 }.bind(this);
2355
2356 // Regular expressions must start with '/'
2357 if (!this.prereg || char !== "/") {
2358 return null;
2359 }
2360
2361 index += 1;
2362 terminated = false;
2363
2364 // Try to get everything in between slashes. A couple of
2365 // cases aside (see scanUnexpectedChars) we don't really
2366 // care whether the resulting expression is valid or not.
2367 // We will check that later using the RegExp object.
2368
2369 while (index < length) {
2370 char = this.peek(index);
2371 value += char;
2372 body += char;
2373
2374 if (isCharSet) {
2375 if (char === "]") {
2376 if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
2377 isCharSet = false;
2378 }
2379 }
2380
2381 if (char === "\\") {
2382 index += 1;
2383 char = this.peek(index);
2384 body += char;
2385 value += char;
2386
2387 scanUnexpectedChars();
2388 }
2389
2390 index += 1;
2391 continue;
2392 }
2393
2394 if (char === "\\") {
2395 index += 1;
2396 char = this.peek(index);
2397 body += char;
2398 value += char;
2399
2400 scanUnexpectedChars();
2401
2402 if (char === "/") {
2403 index += 1;
2404 continue;
2405 }
2406
2407 if (char === "[") {
2408 index += 1;
2409 continue;
2410 }
2411 }
2412
2413 if (char === "[") {
2414 isCharSet = true;
2415 index += 1;
2416 continue;
2417 }
2418
2419 if (char === "/") {
2420 body = body.substr(0, body.length - 1);
2421 terminated = true;
2422 index += 1;
2423 break;
2424 }
2425
2426 index += 1;
2427 }
2428
2429 // A regular expression that was never closed is an
2430 // error from which we cannot recover.
2431
2432 if (!terminated) {
2433 this.trigger("error", {
2434 code: "E015",
2435 line: this.line,
2436 character: this.from
2437 });
2438
2439 return void this.trigger("fatal", {
2440 line: this.line,
2441 from: this.from
2442 });
2443 }
2444
2445 // Parse flags (if any).
2446
2447 while (index < length) {
2448 char = this.peek(index);
2449 if (!/[gim]/.test(char)) {
2450 break;
2451 }
2452 flags.push(char);
2453 value += char;
2454 index += 1;
2455 }
2456
2457 // Check regular expression for correctness.
2458
2459 try {
2460 new RegExp(body, flags.join(""));
2461 } catch (err) {
2462 malformed = true;
2463 this.trigger("error", {
2464 code: "E016",
2465 line: this.line,
2466 character: this.char,
2467 data: [ err.message ] // Platform dependent!
2468 });
2469 }
2470
2471 return {
2472 type: Token.RegExp,
2473 value: value,
2474 flags: flags,
2475 isMalformed: malformed
2476 };
2477 },
2478
2479 /*
2480 * Scan for any occurence of mixed tabs and spaces. If smarttabs option
2481 * is on, ignore tabs followed by spaces.
2482 *
2483 * Tabs followed by one space followed by a block comment are allowed.
2484 */
2485 scanMixedSpacesAndTabs: function () {
2486 var at, match;
2487
2488 if (state.option.smarttabs) {
2489 // Negative look-behind for "//"
2490 match = this.input.match(/(\/\/|^\s?\*)? \t/);
2491 at = match && !match[1] ? 0 : -1;
2492 } else {
2493 at = this.input.search(/ \t|\t [^\*]/);
2494 }
2495
2496 return at;
2497 },
2498
2499 /*
2500 * Scan for characters that get silently deleted by one or more browsers.
2501 */
2502 scanUnsafeChars: function () {
2503 return this.input.search(reg.unsafeChars);
2504 },
2505
2506 /*
2507 * Produce the next raw token or return 'null' if no tokens can be matched.
2508 * This method skips over all space characters.
2509 */
2510 next: function (checks) {
2511 this.from = this.char;
2512
2513 // Move to the next non-space character.
2514 var start;
2515 if (/\s/.test(this.peek())) {
2516 start = this.char;
2517
2518 while (/\s/.test(this.peek())) {
2519 this.from += 1;
2520 this.skip();
2521 }
2522
2523 if (this.peek() === "") { // EOL
2524 if (!/^\s*$/.test(this.lines[this.line - 1]) && state.option.trailing) {
2525 this.trigger("warning", { code: "W102", line: this.line, character: start });
2526 }
2527 }
2528 }
2529
2530 // Methods that work with multi-line structures and move the
2531 // character pointer.
2532
2533 var match = this.scanComments() ||
2534 this.scanStringLiteral(checks);
2535
2536 if (match) {
2537 return match;
2538 }
2539
2540 // Methods that don't move the character pointer.
2541
2542 match =
2543 this.scanRegExp() ||
2544 this.scanPunctuator() ||
2545 this.scanKeyword() ||
2546 this.scanIdentifier() ||
2547 this.scanNumericLiteral();
2548
2549 if (match) {
2550 this.skip(match.value.length);
2551 return match;
2552 }
2553
2554 // No token could be matched, give up.
2555
2556 return null;
2557 },
2558
2559 /*
2560 * Switch to the next line and reset all char pointers. Once
2561 * switched, this method also checks for mixed spaces and tabs
2562 * and other minor warnings.
2563 */
2564 nextLine: function () {
2565 var char;
2566
2567 if (this.line >= this.lines.length) {
2568 return false;
2569 }
2570
2571 this.input = this.lines[this.line];
2572 this.line += 1;
2573 this.char = 1;
2574 this.from = 1;
2575
2576 char = this.scanMixedSpacesAndTabs();
2577 if (char >= 0) {
2578 this.trigger("warning", { code: "W099", line: this.line, character: char + 1 });
2579 }
2580
2581 this.input = this.input.replace(/\t/g, state.tab);
2582 char = this.scanUnsafeChars();
2583
2584 if (char >= 0) {
2585 this.trigger("warning", { code: "W100", line: this.line, character: char });
2586 }
2587
2588 // If there is a limit on line length, warn when lines get too
2589 // long.
2590
2591 if (state.option.maxlen && state.option.maxlen < this.input.length) {
2592 this.trigger("warning", { code: "W101", line: this.line, character: this.input.length });
2593 }
2594
2595 return true;
2596 },
2597
2598 /*
2599 * This is simply a synonym for nextLine() method with a friendlier
2600 * public name.
2601 */
2602 start: function () {
2603 this.nextLine();
2604 },
2605
2606 /*
2607 * Produce the next token. This function is called by advance() to get
2608 * the next token. It retuns a token in a JSLint-compatible format.
2609 */
2610 token: function () {
2611 /*jshint loopfunc:true */
2612 var checks = asyncTrigger();
2613 var token;
2614
2615
2616 function isReserved(token, isProperty) {
2617 if (!token.reserved) {
2618 return false;
2619 }
2620
2621 if (token.meta && token.meta.isFutureReservedWord) {
2622 // ES3 FutureReservedWord in an ES5 environment.
2623 if (state.option.inES5(true) && !token.meta.es5) {
2624 return false;
2625 }
2626
2627 // Some ES5 FutureReservedWord identifiers are active only
2628 // within a strict mode environment.
2629 if (token.meta.strictOnly) {
2630 if (!state.option.strict && !state.directive["use strict"]) {
2631 return false;
2632 }
2633 }
2634
2635 if (isProperty) {
2636 return false;
2637 }
2638 }
2639
2640 return true;
2641 }
2642
2643 // Produce a token object.
2644 var create = function (type, value, isProperty) {
2645 /*jshint validthis:true */
2646 var obj;
2647
2648 if (type !== "(endline)" && type !== "(end)") {
2649 this.prereg = false;
2650 }
2651
2652 if (type === "(punctuator)") {
2653 switch (value) {
2654 case ".":
2655 case ")":
2656 case "~":
2657 case "#":
2658 case "]":
2659 this.prereg = false;
2660 break;
2661 default:
2662 this.prereg = true;
2663 }
2664
2665 obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
2666 }
2667
2668 if (type === "(identifier)") {
2669 if (value === "return" || value === "case" || value === "typeof") {
2670 this.prereg = true;
2671 }
2672
2673 if (_.has(state.syntax, value)) {
2674 obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
2675
2676 // If this can't be a reserved keyword, reset the object.
2677 if (!isReserved(obj, isProperty && type === "(identifier)")) {
2678 obj = null;
2679 }
2680 }
2681 }
2682
2683 if (!obj) {
2684 obj = Object.create(state.syntax[type]);
2685 }
2686
2687 obj.identifier = (type === "(identifier)");
2688 obj.type = obj.type || type;
2689 obj.value = value;
2690 obj.line = this.line;
2691 obj.character = this.char;
2692 obj.from = this.from;
2693
2694 if (isProperty && obj.identifier) {
2695 obj.isProperty = isProperty;
2696 }
2697
2698 obj.check = checks.check;
2699
2700 return obj;
2701 }.bind(this);
2702
2703 for (;;) {
2704 if (!this.input.length) {
2705 return create(this.nextLine() ? "(endline)" : "(end)", "");
2706 }
2707
2708 token = this.next(checks);
2709
2710 if (!token) {
2711 if (this.input.length) {
2712 // Unexpected character.
2713 this.trigger("error", {
2714 code: "E024",
2715 line: this.line,
2716 character: this.char,
2717 data: [ this.peek() ]
2718 });
2719
2720 this.input = "";
2721 }
2722
2723 continue;
2724 }
2725
2726 switch (token.type) {
2727 case Token.StringLiteral:
2728 this.triggerAsync("String", {
2729 line: this.line,
2730 char: this.char,
2731 from: this.from,
2732 value: token.value,
2733 quote: token.quote
2734 }, checks, function () { return true; });
2735
2736 return create("(string)", token.value);
2737 case Token.Identifier:
2738 this.trigger("Identifier", {
2739 line: this.line,
2740 char: this.char,
2741 from: this.form,
2742 name: token.value,
2743 isProperty: state.tokens.curr.id === "."
2744 });
2745
2746 /* falls through */
2747 case Token.Keyword:
2748 case Token.NullLiteral:
2749 case Token.BooleanLiteral:
2750 return create("(identifier)", token.value, state.tokens.curr.id === ".");
2751
2752 case Token.NumericLiteral:
2753 if (token.isMalformed) {
2754 this.trigger("warning", {
2755 code: "W045",
2756 line: this.line,
2757 character: this.char,
2758 data: [ token.value ]
2759 });
2760 }
2761
2762 this.triggerAsync("warning", {
2763 code: "W114",
2764 line: this.line,
2765 character: this.char,
2766 data: [ "0x-" ]
2767 }, checks, function () { return token.base === 16 && state.jsonMode; });
2768
2769 this.triggerAsync("warning", {
2770 code: "W115",
2771 line: this.line,
2772 character: this.char
2773 }, checks, function () {
2774 return state.directive["use strict"] && token.base === 8;
2775 });
2776
2777 this.trigger("Number", {
2778 line: this.line,
2779 char: this.char,
2780 from: this.from,
2781 value: token.value,
2782 base: token.base,
2783 isMalformed: token.malformed
2784 });
2785
2786 return create("(number)", token.value);
2787
2788 case Token.RegExp:
2789 return create("(regexp)", token.value);
2790
2791 case Token.Comment:
2792 state.tokens.curr.comment = true;
2793
2794 if (token.isSpecial) {
2795 return {
2796 value: token.value,
2797 body: token.body,
2798 type: token.commentType,
2799 isSpecial: token.isSpecial,
2800 line: this.line,
2801 character: this.char,
2802 from: this.from
2803 };
2804 }
2805
2806 break;
2807
2808 case "":
2809 break;
2810
2811 default:
2812 return create("(punctuator)", token.value);
2813 }
2814 }
2815 }
2816 };
2817
2818 exports.Lexer = Lexer;
2819
2820 })()
2821 },{"events":2,"./reg.js":6,"./state.js":4,"underscore":11}],"jshint":[function(require,module,exports){
2822 module.exports=require('E/GbHF');
2823 },{}],"E/GbHF":[function(require,module,exports){
2824 (function(){/*!
2825 * JSHint, by JSHint Community.
2826 *
2827 * This file (and this file only) is licensed under the same slightly modified
2828 * MIT license that JSLint is. It stops evil-doers everywhere:
2829 *
2830 * Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
2831 *
2832 * Permission is hereby granted, free of charge, to any person obtaining
2833 * a copy of this software and associated documentation files (the "Software"),
2834 * to deal in the Software without restriction, including without limitation
2835 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2836 * and/or sell copies of the Software, and to permit persons to whom
2837 * the Software is furnished to do so, subject to the following conditions:
2838 *
2839 * The above copyright notice and this permission notice shall be included
2840 * in all copies or substantial portions of the Software.
2841 *
2842 * The Software shall be used for Good, not Evil.
2843 *
2844 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2845 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2846 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2847 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2848 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2849 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2850 * DEALINGS IN THE SOFTWARE.
2851 *
2852 */
2853
2854 /*jshint quotmark:double */
2855 /*global console:true */
2856 /*exported console */
2857
2858 var _ = require("underscore");
2859 var events = require("events");
2860 var vars = require("../shared/vars.js");
2861 var messages = require("../shared/messages.js");
2862 var Lexer = require("./lex.js").Lexer;
2863 var reg = require("./reg.js");
2864 var state = require("./state.js").state;
2865 var style = require("./style.js");
2866
2867 // We need this module here because environments such as IE and Rhino
2868 // don't necessarilly expose the 'console' API and browserify uses
2869 // it to log things. It's a sad state of affair, really.
2870 var console = require("console-browserify");
2871
2872 // We build the application inside a function so that we produce only a singleton
2873 // variable. That function will be invoked immediately, and its return value is
2874 // the JSHINT function itself.
2875
2876 var JSHINT = (function () {
2877 "use strict";
2878
2879 var anonname, // The guessed name for anonymous functions.
2880 api, // Extension API
2881
2882 // These are operators that should not be used with the ! operator.
2883 bang = {
2884 "<" : true,
2885 "<=" : true,
2886 "==" : true,
2887 "===": true,
2888 "!==": true,
2889 "!=" : true,
2890 ">" : true,
2891 ">=" : true,
2892 "+" : true,
2893 "-" : true,
2894 "*" : true,
2895 "/" : true,
2896 "%" : true
2897 },
2898
2899 // These are the JSHint boolean options.
2900 boolOptions = {
2901 asi : true, // if automatic semicolon insertion should be tolerated
2902 bitwise : true, // if bitwise operators should not be allowed
2903 boss : true, // if advanced usage of assignments should be allowed
2904 browser : true, // if the standard browser globals should be predefined
2905 camelcase : true, // if identifiers should be required in camel case
2906 couch : true, // if CouchDB globals should be predefined
2907 curly : true, // if curly braces around all blocks should be required
2908 debug : true, // if debugger statements should be allowed
2909 devel : true, // if logging globals should be predefined (console, alert, etc.)
2910 dojo : true, // if Dojo Toolkit globals should be predefined
2911 eqeqeq : true, // if === should be required
2912 eqnull : true, // if == null comparisons should be tolerated
2913 es3 : true, // if ES3 syntax should be allowed
2914 es5 : true, // if ES5 syntax should be allowed (is now set per default)
2915 esnext : true, // if es.next specific syntax should be allowed
2916 moz : true, // if mozilla specific syntax should be allowed
2917 evil : true, // if eval should be allowed
2918 expr : true, // if ExpressionStatement should be allowed as Programs
2919 forin : true, // if for in statements must filter
2920 funcscope : true, // if only function scope should be used for scope tests
2921 gcl : true, // if JSHint should be compatible with Google Closure Linter
2922 globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
2923 immed : true, // if immediate invocations must be wrapped in parens
2924 iterator : true, // if the `__iterator__` property should be allowed
2925 jquery : true, // if jQuery globals should be predefined
2926 lastsemic : true, // if semicolons may be ommitted for the trailing
2927 // statements inside of a one-line blocks.
2928 laxbreak : true, // if line breaks should not be checked
2929 laxcomma : true, // if line breaks should not be checked around commas
2930 loopfunc : true, // if functions should be allowed to be defined within
2931 // loops
2932 mootools : true, // if MooTools globals should be predefined
2933 multistr : true, // allow multiline strings
2934 newcap : true, // if constructor names must be capitalized
2935 noarg : true, // if arguments.caller and arguments.callee should be
2936 // disallowed
2937 node : true, // if the Node.js environment globals should be
2938 // predefined
2939 noempty : true, // if empty blocks should be disallowed
2940 nonew : true, // if using `new` for side-effects should be disallowed
2941 nonstandard : true, // if non-standard (but widely adopted) globals should
2942 // be predefined
2943 nomen : true, // if names should be checked
2944 onevar : true, // if only one var statement per function should be
2945 // allowed
2946 passfail : true, // if the scan should stop on first error
2947 phantom : true, // if PhantomJS symbols should be allowed
2948 plusplus : true, // if increment/decrement should not be allowed
2949 proto : true, // if the `__proto__` property should be allowed
2950 prototypejs : true, // if Prototype and Scriptaculous globals should be
2951 // predefined
2952 rhino : true, // if the Rhino environment globals should be predefined
2953 undef : true, // if variables should be declared before used
2954 scripturl : true, // if script-targeted URLs should be tolerated
2955 shadow : true, // if variable shadowing should be tolerated
2956 smarttabs : true, // if smarttabs should be tolerated
2957 // (http://www.emacswiki.org/emacs/SmartTabs)
2958 strict : true, // require the "use strict"; pragma
2959 sub : true, // if all forms of subscript notation are tolerated
2960 supernew : true, // if `new function () { ... };` and `new Object;`
2961 // should be tolerated
2962 trailing : true, // if trailing whitespace rules apply
2963 validthis : true, // if 'this' inside a non-constructor function is valid.
2964 // This is a function scoped option only.
2965 withstmt : true, // if with statements should be allowed
2966 white : true, // if strict whitespace rules apply
2967 worker : true, // if Web Worker script symbols should be allowed
2968 wsh : true, // if the Windows Scripting Host environment globals
2969 // should be predefined
2970 yui : true, // YUI variables should be predefined
2971
2972 // Obsolete options
2973 onecase : true, // if one case switch statements should be allowed
2974 regexp : true, // if the . should not be allowed in regexp literals
2975 regexdash : true // if unescaped first/last dash (-) inside brackets
2976 // should be tolerated
2977 },
2978
2979 // These are the JSHint options that can take any value
2980 // (we use this object to detect invalid options)
2981 valOptions = {
2982 maxlen : false,
2983 indent : false,
2984 maxerr : false,
2985 predef : false,
2986 quotmark : false, //'single'|'double'|true
2987 scope : false,
2988 maxstatements: false, // {int} max statements per function
2989 maxdepth : false, // {int} max nested block depth per function
2990 maxparams : false, // {int} max params per function
2991 maxcomplexity: false, // {int} max cyclomatic complexity per function
2992 unused : true, // warn if variables are unused. Available options:
2993 // false - don't check for unused variables
2994 // true - "vars" + check last function param
2995 // "vars" - skip checking unused function params
2996 // "strict" - "vars" + check all function params
2997 latedef : false // warn if the variable is used before its definition
2998 // false - don't emit any warnings
2999 // true - warn if any variable is used before its definition
3000 // "nofunc" - warn for any variable but function declarations
3001 },
3002
3003 // These are JSHint boolean options which are shared with JSLint
3004 // where the definition in JSHint is opposite JSLint
3005 invertedOptions = {
3006 bitwise : true,
3007 forin : true,
3008 newcap : true,
3009 nomen : true,
3010 plusplus: true,
3011 regexp : true,
3012 undef : true,
3013 white : true,
3014
3015 // Inverted and renamed, use JSHint name here
3016 eqeqeq : true,
3017 onevar : true,
3018 strict : true
3019 },
3020
3021 // These are JSHint boolean options which are shared with JSLint
3022 // where the name has been changed but the effect is unchanged
3023 renamedOptions = {
3024 eqeq : "eqeqeq",
3025 vars : "onevar",
3026 windows: "wsh",
3027 sloppy : "strict"
3028 },
3029
3030 declared, // Globals that were declared using /*global ... */ syntax.
3031 exported, // Variables that are used outside of the current file.
3032
3033 functionicity = [
3034 "closure", "exception", "global", "label",
3035 "outer", "unused", "var"
3036 ],
3037
3038 funct, // The current function
3039 functions, // All of the functions
3040
3041 global, // The global scope
3042 implied, // Implied globals
3043 inblock,
3044 indent,
3045 lookahead,
3046 lex,
3047 member,
3048 membersOnly,
3049 noreach,
3050 predefined, // Global variables defined by option
3051
3052 scope, // The current scope
3053 stack,
3054 unuseds,
3055 urls,
3056 warnings,
3057
3058 extraModules = [],
3059 emitter = new events.EventEmitter();
3060
3061 function checkOption(name, t) {
3062 name = name.trim();
3063
3064 if (/^[+-]W\d{3}$/g.test(name)) {
3065 return true;
3066 }
3067
3068 if (valOptions[name] === undefined && boolOptions[name] === undefined) {
3069 if (t.type !== "jslint") {
3070 error("E001", t, name);
3071 return false;
3072 }
3073 }
3074
3075 return true;
3076 }
3077
3078 function isString(obj) {
3079 return Object.prototype.toString.call(obj) === "[object String]";
3080 }
3081
3082 function isIdentifier(tkn, value) {
3083 if (!tkn)
3084 return false;
3085
3086 if (!tkn.identifier || tkn.value !== value)
3087 return false;
3088
3089 return true;
3090 }
3091
3092 function isReserved(token) {
3093 if (!token.reserved) {
3094 return false;
3095 }
3096
3097 if (token.meta && token.meta.isFutureReservedWord) {
3098 // ES3 FutureReservedWord in an ES5 environment.
3099 if (state.option.inES5(true) && !token.meta.es5) {
3100 return false;
3101 }
3102
3103 // Some ES5 FutureReservedWord identifiers are active only
3104 // within a strict mode environment.
3105 if (token.meta.strictOnly) {
3106 if (!state.option.strict && !state.directive["use strict"]) {
3107 return false;
3108 }
3109 }
3110
3111 if (token.isProperty) {
3112 return false;
3113 }
3114 }
3115
3116 return true;
3117 }
3118
3119 function supplant(str, data) {
3120 return str.replace(/\{([^{}]*)\}/g, function (a, b) {
3121 var r = data[b];
3122 return typeof r === "string" || typeof r === "number" ? r : a;
3123 });
3124 }
3125
3126 function combine(t, o) {
3127 var n;
3128 for (n in o) {
3129 if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {
3130 t[n] = o[n];
3131 }
3132 }
3133 }
3134
3135 function updatePredefined() {
3136 Object.keys(JSHINT.blacklist).forEach(function (key) {
3137 delete predefined[key];
3138 });
3139 }
3140
3141 function assume() {
3142 if (state.option.es5) {
3143 warning("I003");
3144 }
3145 if (state.option.couch) {
3146 combine(predefined, vars.couch);
3147 }
3148
3149 if (state.option.rhino) {
3150 combine(predefined, vars.rhino);
3151 }
3152
3153 if (state.option.phantom) {
3154 combine(predefined, vars.phantom);
3155 }
3156
3157 if (state.option.prototypejs) {
3158 combine(predefined, vars.prototypejs);
3159 }
3160
3161 if (state.option.node) {
3162 combine(predefined, vars.node);
3163 }
3164
3165 if (state.option.devel) {
3166 combine(predefined, vars.devel);
3167 }
3168
3169 if (state.option.dojo) {
3170 combine(predefined, vars.dojo);
3171 }
3172
3173 if (state.option.browser) {
3174 combine(predefined, vars.browser);
3175 }
3176
3177 if (state.option.nonstandard) {
3178 combine(predefined, vars.nonstandard);
3179 }
3180
3181 if (state.option.jquery) {
3182 combine(predefined, vars.jquery);
3183 }
3184
3185 if (state.option.mootools) {
3186 combine(predefined, vars.mootools);
3187 }
3188
3189 if (state.option.worker) {
3190 combine(predefined, vars.worker);
3191 }
3192
3193 if (state.option.wsh) {
3194 combine(predefined, vars.wsh);
3195 }
3196
3197 if (state.option.globalstrict && state.option.strict !== false) {
3198 state.option.strict = true;
3199 }
3200
3201 if (state.option.yui) {
3202 combine(predefined, vars.yui);
3203 }
3204
3205 // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
3206
3207 state.option.inMoz = function (strict) {
3208 if (strict) {
3209 return state.option.moz && !state.option.esnext;
3210 }
3211 return state.option.moz;
3212 };
3213
3214 state.option.inESNext = function (strict) {
3215 if (strict) {
3216 return !state.option.moz && state.option.esnext;
3217 }
3218 return state.option.moz || state.option.esnext;
3219 };
3220
3221 state.option.inES5 = function (/* strict */) {
3222 return !state.option.es3;
3223 };
3224
3225 state.option.inES3 = function (strict) {
3226 if (strict) {
3227 return !state.option.moz && !state.option.esnext && state.option.es3;
3228 }
3229 return state.option.es3;
3230 };
3231 }
3232
3233 // Produce an error warning.
3234 function quit(code, line, chr) {
3235 var percentage = Math.floor((line / state.lines.length) * 100);
3236 var message = messages.errors[code].desc;
3237
3238 throw {
3239 name: "JSHintError",
3240 line: line,
3241 character: chr,
3242 message: message + " (" + percentage + "% scanned).",
3243 raw: message
3244 };
3245 }
3246
3247 function isundef(scope, code, token, a) {
3248 return JSHINT.undefs.push([scope, code, token, a]);
3249 }
3250
3251 function warning(code, t, a, b, c, d) {
3252 var ch, l, w, msg;
3253
3254 if (/^W\d{3}$/.test(code)) {
3255 if (state.ignored[code])
3256 return;
3257
3258 msg = messages.warnings[code];
3259 } else if (/E\d{3}/.test(code)) {
3260 msg = messages.errors[code];
3261 } else if (/I\d{3}/.test(code)) {
3262 msg = messages.info[code];
3263 }
3264
3265 t = t || state.tokens.next;
3266 if (t.id === "(end)") { // `~
3267 t = state.tokens.curr;
3268 }
3269
3270 l = t.line || 0;
3271 ch = t.from || 0;
3272
3273 w = {
3274 id: "(error)",
3275 raw: msg.desc,
3276 code: msg.code,
3277 evidence: state.lines[l - 1] || "",
3278 line: l,
3279 character: ch,
3280 scope: JSHINT.scope,
3281 a: a,
3282 b: b,
3283 c: c,
3284 d: d
3285 };
3286
3287 w.reason = supplant(msg.desc, w);
3288 JSHINT.errors.push(w);
3289
3290 if (state.option.passfail) {
3291 quit("E042", l, ch);
3292 }
3293
3294 warnings += 1;
3295 if (warnings >= state.option.maxerr) {
3296 quit("E043", l, ch);
3297 }
3298
3299 return w;
3300 }
3301
3302 function warningAt(m, l, ch, a, b, c, d) {
3303 return warning(m, {
3304 line: l,
3305 from: ch
3306 }, a, b, c, d);
3307 }
3308
3309 function error(m, t, a, b, c, d) {
3310 warning(m, t, a, b, c, d);
3311 }
3312
3313 function errorAt(m, l, ch, a, b, c, d) {
3314 return error(m, {
3315 line: l,
3316 from: ch
3317 }, a, b, c, d);
3318 }
3319
3320 // Tracking of "internal" scripts, like eval containing a static string
3321 function addInternalSrc(elem, src) {
3322 var i;
3323 i = {
3324 id: "(internal)",
3325 elem: elem,
3326 value: src
3327 };
3328 JSHINT.internals.push(i);
3329 return i;
3330 }
3331
3332 function addlabel(t, type, tkn, islet) {
3333 // Define t in the current function in the current scope.
3334 if (type === "exception") {
3335 if (_.has(funct["(context)"], t)) {
3336 if (funct[t] !== true && !state.option.node) {
3337 warning("W002", state.tokens.next, t);
3338 }
3339 }
3340 }
3341
3342 if (_.has(funct, t) && !funct["(global)"]) {
3343 if (funct[t] === true) {
3344 if (state.option.latedef) {
3345 if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
3346 !_.contains([funct[t], type], "unction")) {
3347 warning("W003", state.tokens.next, t);
3348 }
3349 }
3350 } else {
3351 if (!state.option.shadow && type !== "exception" ||
3352 (funct["(blockscope)"].getlabel(t))) {
3353 warning("W004", state.tokens.next, t);
3354 }
3355 }
3356 }
3357
3358 // a double definition of a let variable in same block throws a TypeError
3359 //if (funct["(blockscope)"] && funct["(blockscope)"].current.has(t)) {
3360 // error("E044", state.tokens.next, t);
3361 //}
3362
3363 // if the identifier is from a let, adds it only to the current blockscope
3364 if (islet) {
3365 funct["(blockscope)"].current.add(t, type, state.tokens.curr);
3366 } else {
3367
3368 funct[t] = type;
3369
3370 if (tkn) {
3371 funct["(tokens)"][t] = tkn;
3372 }
3373
3374 if (funct["(global)"]) {
3375 global[t] = funct;
3376 if (_.has(implied, t)) {
3377 if (state.option.latedef) {
3378 if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
3379 !_.contains([funct[t], type], "unction")) {
3380 warning("W003", state.tokens.next, t);
3381 }
3382 }
3383
3384 delete implied[t];
3385 }
3386 } else {
3387 scope[t] = funct;
3388 }
3389 }
3390 }
3391
3392 function doOption() {
3393 var nt = state.tokens.next;
3394 var body = nt.body.split(",").map(function (s) { return s.trim(); });
3395 var predef = {};
3396
3397 if (nt.type === "globals") {
3398 body.forEach(function (g) {
3399 g = g.split(":");
3400 var key = g[0];
3401 var val = g[1];
3402
3403 if (key.charAt(0) === "-") {
3404 key = key.slice(1);
3405 val = false;
3406
3407 JSHINT.blacklist[key] = key;
3408 updatePredefined();
3409 } else {
3410 predef[key] = (val === "true");
3411 }
3412 });
3413
3414 combine(predefined, predef);
3415
3416 for (var key in predef) {
3417 if (_.has(predef, key)) {
3418 declared[key] = nt;
3419 }
3420 }
3421 }
3422
3423 if (nt.type === "exported") {
3424 body.forEach(function (e) {
3425 exported[e] = true;
3426 });
3427 }
3428
3429 if (nt.type === "members") {
3430 membersOnly = membersOnly || {};
3431
3432 body.forEach(function (m) {
3433 var ch1 = m.charAt(0);
3434 var ch2 = m.charAt(m.length - 1);
3435
3436 if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
3437 m = m
3438 .substr(1, m.length - 2)
3439 .replace("\\b", "\b")
3440 .replace("\\t", "\t")
3441 .replace("\\n", "\n")
3442 .replace("\\v", "\v")
3443 .replace("\\f", "\f")
3444 .replace("\\r", "\r")
3445 .replace("\\\\", "\\")
3446 .replace("\\\"", "\"");
3447 }
3448
3449 membersOnly[m] = false;
3450 });
3451 }
3452
3453 var numvals = [
3454 "maxstatements",
3455 "maxparams",
3456 "maxdepth",
3457 "maxcomplexity",
3458 "maxerr",
3459 "maxlen",
3460 "indent"
3461 ];
3462
3463 if (nt.type === "jshint" || nt.type === "jslint") {
3464 body.forEach(function (g) {
3465 g = g.split(":");
3466 var key = (g[0] || "").trim();
3467 var val = (g[1] || "").trim();
3468
3469 if (!checkOption(key, nt)) {
3470 return;
3471 }
3472
3473 if (numvals.indexOf(key) >= 0) {
3474
3475 // GH988 - numeric options can be disabled by setting them to `false`
3476 if (val !== "false") {
3477 val = +val;
3478
3479 if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
3480 error("E032", nt, g[1].trim());
3481 return;
3482 }
3483
3484 if (key === "indent") {
3485 state.option["(explicitIndent)"] = true;
3486 }
3487 state.option[key] = val;
3488 } else {
3489 if (key === "indent") {
3490 state.option["(explicitIndent)"] = false;
3491 } else {
3492 state.option[key] = false;
3493 }
3494 }
3495
3496 return;
3497 }
3498
3499 if (key === "validthis") {
3500 // `validthis` is valid only within a function scope.
3501 if (funct["(global)"]) {
3502 error("E009");
3503 } else {
3504 if (val === "true" || val === "false") {
3505 state.option.validthis = (val === "true");
3506 } else {
3507 error("E002", nt);
3508 }
3509 }
3510 return;
3511 }
3512
3513 if (key === "quotmark") {
3514 switch (val) {
3515 case "true":
3516 case "false":
3517 state.option.quotmark = (val === "true");
3518 break;
3519 case "double":
3520 case "single":
3521 state.option.quotmark = val;
3522 break;
3523 default:
3524 error("E002", nt);
3525 }
3526 return;
3527 }
3528
3529 if (key === "unused") {
3530 switch (val) {
3531 case "true":
3532 state.option.unused = true;
3533 break;
3534 case "false":
3535 state.option.unused = false;
3536 break;
3537 case "vars":
3538 case "strict":
3539 state.option.unused = val;
3540 break;
3541 default:
3542 error("E002", nt);
3543 }
3544 return;
3545 }
3546
3547 if (key === "latedef") {
3548 switch (val) {
3549 case "true":
3550 state.option.latedef = true;
3551 break;
3552 case "false":
3553 state.option.latedef = false;
3554 break;
3555 case "nofunc":
3556 state.option.latedef = "nofunc";
3557 break;
3558 default:
3559 error("E002", nt);
3560 }
3561 return;
3562 }
3563
3564 var match = /^([+-])(W\d{3})$/g.exec(key);
3565 if (match) {
3566 // ignore for -W..., unignore for +W...
3567 state.ignored[match[2]] = (match[1] === "-");
3568 return;
3569 }
3570
3571 var tn;
3572 if (val === "true" || val === "false") {
3573 if (nt.type === "jslint") {
3574 tn = renamedOptions[key] || key;
3575 state.option[tn] = (val === "true");
3576
3577 if (invertedOptions[tn] !== undefined) {
3578 state.option[tn] = !state.option[tn];
3579 }
3580 } else {
3581 state.option[key] = (val === "true");
3582 }
3583
3584 if (key === "newcap") {
3585 state.option["(explicitNewcap)"] = true;
3586 }
3587 return;
3588 }
3589
3590 error("E002", nt);
3591 });
3592
3593 assume();
3594 }
3595 }
3596
3597 // We need a peek function. If it has an argument, it peeks that much farther
3598 // ahead. It is used to distinguish
3599 // for ( var i in ...
3600 // from
3601 // for ( var i = ...
3602
3603 function peek(p) {
3604 var i = p || 0, j = 0, t;
3605
3606 while (j <= i) {
3607 t = lookahead[j];
3608 if (!t) {
3609 t = lookahead[j] = lex.token();
3610 }
3611 j += 1;
3612 }
3613 return t;
3614 }
3615
3616 // Produce the next token. It looks for programming errors.
3617
3618 function advance(id, t) {
3619 switch (state.tokens.curr.id) {
3620 case "(number)":
3621 if (state.tokens.next.id === ".") {
3622 warning("W005", state.tokens.curr);
3623 }
3624 break;
3625 case "-":
3626 if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
3627 warning("W006");
3628 }
3629 break;
3630 case "+":
3631 if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
3632 warning("W007");
3633 }
3634 break;
3635 }
3636
3637 if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
3638 anonname = state.tokens.curr.value;
3639 }
3640
3641 if (id && state.tokens.next.id !== id) {
3642 if (t) {
3643 if (state.tokens.next.id === "(end)") {
3644 error("E019", t, t.id);
3645 } else {
3646 error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
3647 }
3648 } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
3649 warning("W116", state.tokens.next, id, state.tokens.next.value);
3650 }
3651 }
3652
3653 state.tokens.prev = state.tokens.curr;
3654 state.tokens.curr = state.tokens.next;
3655 for (;;) {
3656 state.tokens.next = lookahead.shift() || lex.token();
3657
3658 if (!state.tokens.next) { // No more tokens left, give up
3659 quit("E041", state.tokens.curr.line);
3660 }
3661
3662 if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
3663 return;
3664 }
3665
3666 if (state.tokens.next.check) {
3667 state.tokens.next.check();
3668 }
3669
3670 if (state.tokens.next.isSpecial) {
3671 doOption();
3672 } else {
3673 if (state.tokens.next.id !== "(endline)") {
3674 break;
3675 }
3676 }
3677 }
3678 }
3679
3680 // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
3681 // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
3682 // like .nud except that it is only used on the first token of a statement.
3683 // Having .fud makes it much easier to define statement-oriented languages like
3684 // JavaScript. I retained Pratt's nomenclature.
3685
3686 // .nud Null denotation
3687 // .fud First null denotation
3688 // .led Left denotation
3689 // lbp Left binding power
3690 // rbp Right binding power
3691
3692 // They are elements of the parsing method called Top Down Operator Precedence.
3693
3694 function expression(rbp, initial) {
3695 var left, isArray = false, isObject = false, isLetExpr = false;
3696
3697 // if current expression is a let expression
3698 if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
3699 if (!state.option.inMoz(true)) {
3700 warning("W118", state.tokens.next, "let expressions");
3701 }
3702 isLetExpr = true;
3703 // create a new block scope we use only for the current expression
3704 funct["(blockscope)"].stack();
3705 advance("let");
3706 advance("(");
3707 state.syntax["let"].fud.call(state.syntax["let"].fud, false);
3708 advance(")");
3709 }
3710
3711 if (state.tokens.next.id === "(end)")
3712 error("E006", state.tokens.curr);
3713
3714 advance();
3715
3716 if (initial) {
3717 anonname = "anonymous";
3718 funct["(verb)"] = state.tokens.curr.value;
3719 }
3720
3721 if (initial === true && state.tokens.curr.fud) {
3722 left = state.tokens.curr.fud();
3723 } else {
3724 if (state.tokens.curr.nud) {
3725 left = state.tokens.curr.nud();
3726 } else {
3727 error("E030", state.tokens.curr, state.tokens.curr.id);
3728 }
3729
3730 var end_of_expr = state.tokens.next.identifier &&
3731 !state.tokens.curr.led &&
3732 state.tokens.curr.line !== state.tokens.next.line;
3733 while (rbp < state.tokens.next.lbp && !end_of_expr) {
3734 isArray = state.tokens.curr.value === "Array";
3735 isObject = state.tokens.curr.value === "Object";
3736
3737 // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
3738 // Line breaks in IfStatement heads exist to satisfy the checkJSHint
3739 // "Line too long." error.
3740 if (left && (left.value || (left.first && left.first.value))) {
3741 // If the left.value is not "new", or the left.first.value is a "."
3742 // then safely assume that this is not "new Array()" and possibly
3743 // not "new Object()"...
3744 if (left.value !== "new" ||
3745 (left.first && left.first.value && left.first.value === ".")) {
3746 isArray = false;
3747 // ...In the case of Object, if the left.value and state.tokens.curr.value
3748 // are not equal, then safely assume that this not "new Object()"
3749 if (left.value !== state.tokens.curr.value) {
3750 isObject = false;
3751 }
3752 }
3753 }
3754
3755 advance();
3756
3757 if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
3758 warning("W009", state.tokens.curr);
3759 }
3760
3761 if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
3762 warning("W010", state.tokens.curr);
3763 }
3764
3765 if (left && state.tokens.curr.led) {
3766 left = state.tokens.curr.led(left);
3767 } else {
3768 error("E033", state.tokens.curr, state.tokens.curr.id);
3769 }
3770 }
3771 }
3772 if (isLetExpr) {
3773 funct["(blockscope)"].unstack();
3774 }
3775 return left;
3776 }
3777
3778
3779 // Functions for conformance of style.
3780
3781 function adjacent(left, right) {
3782 left = left || state.tokens.curr;
3783 right = right || state.tokens.next;
3784 if (state.option.white) {
3785 if (left.character !== right.from && left.line === right.line) {
3786 left.from += (left.character - left.from);
3787 warning("W011", left, left.value);
3788 }
3789 }
3790 }
3791
3792 function nobreak(left, right) {
3793 left = left || state.tokens.curr;
3794 right = right || state.tokens.next;
3795 if (state.option.white && (left.character !== right.from || left.line !== right.line)) {
3796 warning("W012", right, right.value);
3797 }
3798 }
3799
3800 function nospace(left, right) {
3801 left = left || state.tokens.curr;
3802 right = right || state.tokens.next;
3803 if (state.option.white && !left.comment) {
3804 if (left.line === right.line) {
3805 adjacent(left, right);
3806 }
3807 }
3808 }
3809
3810 function nonadjacent(left, right) {
3811 if (state.option.white) {
3812 left = left || state.tokens.curr;
3813 right = right || state.tokens.next;
3814
3815 if (left.value === ";" && right.value === ";") {
3816 return;
3817 }
3818
3819 if (left.line === right.line && left.character === right.from) {
3820 left.from += (left.character - left.from);
3821 warning("W013", left, left.value);
3822 }
3823 }
3824 }
3825
3826 function nobreaknonadjacent(left, right) {
3827 left = left || state.tokens.curr;
3828 right = right || state.tokens.next;
3829 if (!state.option.laxbreak && left.line !== right.line) {
3830 warning("W014", right, right.id);
3831 } else if (state.option.white) {
3832 left = left || state.tokens.curr;
3833 right = right || state.tokens.next;
3834 if (left.character === right.from) {
3835 left.from += (left.character - left.from);
3836 warning("W013", left, left.value);
3837 }
3838 }
3839 }
3840
3841 function indentation(bias) {
3842 if (!state.option.white && !state.option["(explicitIndent)"]) {
3843 return;
3844 }
3845
3846 if (state.tokens.next.id === "(end)") {
3847 return;
3848 }
3849
3850 var i = indent + (bias || 0);
3851 if (state.tokens.next.from !== i) {
3852 warning("W015", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);
3853 }
3854 }
3855
3856 function nolinebreak(t) {
3857 t = t || state.tokens.curr;
3858 if (t.line !== state.tokens.next.line) {
3859 warning("E022", t, t.value);
3860 }
3861 }
3862
3863
3864 function comma(opts) {
3865 opts = opts || {};
3866
3867 if (!opts.peek) {
3868 if (state.tokens.curr.line !== state.tokens.next.line) {
3869 if (!state.option.laxcomma) {
3870 if (comma.first) {
3871 warning("I001");
3872 comma.first = false;
3873 }
3874 warning("W014", state.tokens.curr, state.tokens.next.value);
3875 }
3876 } else if (!state.tokens.curr.comment &&
3877 state.tokens.curr.character !== state.tokens.next.from && state.option.white) {
3878 state.tokens.curr.from += (state.tokens.curr.character - state.tokens.curr.from);
3879 warning("W011", state.tokens.curr, state.tokens.curr.value);
3880 }
3881
3882 advance(",");
3883 }
3884
3885 // TODO: This is a temporary solution to fight against false-positives in
3886 // arrays and objects with trailing commas (see GH-363). The best solution
3887 // would be to extract all whitespace rules out of parser.
3888
3889 if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") {
3890 nonadjacent(state.tokens.curr, state.tokens.next);
3891 }
3892
3893 if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {
3894 // Keywords that cannot follow a comma operator.
3895 switch (state.tokens.next.value) {
3896 case "break":
3897 case "case":
3898 case "catch":
3899 case "continue":
3900 case "default":
3901 case "do":
3902 case "else":
3903 case "finally":
3904 case "for":
3905 case "if":
3906 case "in":
3907 case "instanceof":
3908 case "return":
3909 case "yield":
3910 case "switch":
3911 case "throw":
3912 case "try":
3913 case "var":
3914 case "let":
3915 case "while":
3916 case "with":
3917 error("E024", state.tokens.next, state.tokens.next.value);
3918 return false;
3919 }
3920 }
3921
3922 if (state.tokens.next.type === "(punctuator)") {
3923 switch (state.tokens.next.value) {
3924 case "}":
3925 case "]":
3926 case ",":
3927 if (opts.allowTrailing) {
3928 return true;
3929 }
3930
3931 /* falls through */
3932 case ")":
3933 error("E024", state.tokens.next, state.tokens.next.value);
3934 return false;
3935 }
3936 }
3937 return true;
3938 }
3939
3940 // Functional constructors for making the symbols that will be inherited by
3941 // tokens.
3942
3943 function symbol(s, p) {
3944 var x = state.syntax[s];
3945 if (!x || typeof x !== "object") {
3946 state.syntax[s] = x = {
3947 id: s,
3948 lbp: p,
3949 value: s
3950 };
3951 }
3952 return x;
3953 }
3954
3955 function delim(s) {
3956 return symbol(s, 0);
3957 }
3958
3959 function stmt(s, f) {
3960 var x = delim(s);
3961 x.identifier = x.reserved = true;
3962 x.fud = f;
3963 return x;
3964 }
3965
3966 function blockstmt(s, f) {
3967 var x = stmt(s, f);
3968 x.block = true;
3969 return x;
3970 }
3971
3972 function reserveName(x) {
3973 var c = x.id.charAt(0);
3974 if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
3975 x.identifier = x.reserved = true;
3976 }
3977 return x;
3978 }
3979
3980 function prefix(s, f) {
3981 var x = symbol(s, 150);
3982 reserveName(x);
3983 x.nud = (typeof f === "function") ? f : function () {
3984 this.right = expression(150);
3985 this.arity = "unary";
3986 if (this.id === "++" || this.id === "--") {
3987 if (state.option.plusplus) {
3988 warning("W016", this, this.id);
3989 } else if ((!this.right.identifier || isReserved(this.right)) &&
3990 this.right.id !== "." && this.right.id !== "[") {
3991 warning("W017", this);
3992 }
3993 }
3994 return this;
3995 };
3996 return x;
3997 }
3998
3999 function type(s, f) {
4000 var x = delim(s);
4001 x.type = s;
4002 x.nud = f;
4003 return x;
4004 }
4005
4006 function reserve(name, func) {
4007 var x = type(name, func);
4008 x.identifier = true;
4009 x.reserved = true;
4010 return x;
4011 }
4012
4013 function FutureReservedWord(name, meta) {
4014 var x = type(name, (meta && meta.nud) || function () {
4015 return this;
4016 });
4017
4018 meta = meta || {};
4019 meta.isFutureReservedWord = true;
4020
4021 x.value = name;
4022 x.identifier = true;
4023 x.reserved = true;
4024 x.meta = meta;
4025
4026 return x;
4027 }
4028
4029 function reservevar(s, v) {
4030 return reserve(s, function () {
4031 if (typeof v === "function") {
4032 v(this);
4033 }
4034 return this;
4035 });
4036 }
4037
4038 function infix(s, f, p, w) {
4039 var x = symbol(s, p);
4040 reserveName(x);
4041 x.led = function (left) {
4042 if (!w) {
4043 nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
4044 nonadjacent(state.tokens.curr, state.tokens.next);
4045 }
4046 if (s === "in" && left.id === "!") {
4047 warning("W018", left, "!");
4048 }
4049 if (typeof f === "function") {
4050 return f(left, this);
4051 } else {
4052 this.left = left;
4053 this.right = expression(p);
4054 return this;
4055 }
4056 };
4057 return x;
4058 }
4059
4060
4061 function application(s) {
4062 var x = symbol(s, 42);
4063
4064 x.led = function (left) {
4065 if (!state.option.inESNext()) {
4066 warning("W104", state.tokens.curr, "arrow function syntax (=>)");
4067 }
4068
4069 nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
4070 nonadjacent(state.tokens.curr, state.tokens.next);
4071
4072 this.left = left;
4073 this.right = doFunction(undefined, undefined, false, left);
4074 return this;
4075 };
4076 return x;
4077 }
4078
4079 function relation(s, f) {
4080 var x = symbol(s, 100);
4081
4082 x.led = function (left) {
4083 nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
4084 nonadjacent(state.tokens.curr, state.tokens.next);
4085 var right = expression(100);
4086
4087 if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
4088 warning("W019", this);
4089 } else if (f) {
4090 f.apply(this, [left, right]);
4091 }
4092
4093 if (!left || !right) {
4094 quit("E041", state.tokens.curr.line);
4095 }
4096
4097 if (left.id === "!") {
4098 warning("W018", left, "!");
4099 }
4100
4101 if (right.id === "!") {
4102 warning("W018", right, "!");
4103 }
4104
4105 this.left = left;
4106 this.right = right;
4107 return this;
4108 };
4109 return x;
4110 }
4111
4112 function isPoorRelation(node) {
4113 return node &&
4114 ((node.type === "(number)" && +node.value === 0) ||
4115 (node.type === "(string)" && node.value === "") ||
4116 (node.type === "null" && !state.option.eqnull) ||
4117 node.type === "true" ||
4118 node.type === "false" ||
4119 node.type === "undefined");
4120 }
4121
4122 function assignop(s) {
4123 symbol(s, 20).exps = true;
4124
4125 return infix(s, function (left, that) {
4126 that.left = left;
4127
4128 if (left) {
4129 if (predefined[left.value] === false &&
4130 scope[left.value]["(global)"] === true) {
4131 warning("W020", left);
4132 } else if (left["function"]) {
4133 warning("W021", left, left.value);
4134 }
4135
4136 if (funct[left.value] === "const") {
4137 error("E013", left, left.value);
4138 }
4139
4140 if (left.id === ".") {
4141 if (!left.left) {
4142 warning("E031", that);
4143 } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
4144 warning("E031", that);
4145 }
4146
4147 that.right = expression(19);
4148 return that;
4149 } else if (left.id === "[") {
4150 if (state.tokens.curr.left.first) {
4151 state.tokens.curr.left.first.forEach(function (t) {
4152 if (funct[t.value] === "const") {
4153 error("E013", t, t.value);
4154 }
4155 });
4156 } else if (!left.left) {
4157 warning("E031", that);
4158 } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
4159 warning("E031", that);
4160 }
4161 that.right = expression(19);
4162 return that;
4163 } else if (left.identifier && !isReserved(left)) {
4164 if (funct[left.value] === "exception") {
4165 warning("W022", left);
4166 }
4167 that.right = expression(19);
4168 return that;
4169 }
4170
4171 if (left === state.syntax["function"]) {
4172 warning("W023", state.tokens.curr);
4173 }
4174 }
4175
4176 error("E031", that);
4177 }, 20);
4178 }
4179
4180
4181 function bitwise(s, f, p) {
4182 var x = symbol(s, p);
4183 reserveName(x);
4184 x.led = (typeof f === "function") ? f : function (left) {
4185 if (state.option.bitwise) {
4186 warning("W016", this, this.id);
4187 }
4188 this.left = left;
4189 this.right = expression(p);
4190 return this;
4191 };
4192 return x;
4193 }
4194
4195
4196 function bitwiseassignop(s) {
4197 symbol(s, 20).exps = true;
4198 return infix(s, function (left, that) {
4199 if (state.option.bitwise) {
4200 warning("W016", that, that.id);
4201 }
4202 nonadjacent(state.tokens.prev, state.tokens.curr);
4203 nonadjacent(state.tokens.curr, state.tokens.next);
4204 if (left) {
4205 if (left.id === "." || left.id === "[" ||
4206 (left.identifier && !isReserved(left))) {
4207 expression(19);
4208 return that;
4209 }
4210 if (left === state.syntax["function"]) {
4211 warning("W023", state.tokens.curr);
4212 }
4213 return that;
4214 }
4215 error("E031", that);
4216 }, 20);
4217 }
4218
4219
4220 function suffix(s) {
4221 var x = symbol(s, 150);
4222
4223 x.led = function (left) {
4224 if (state.option.plusplus) {
4225 warning("W016", this, this.id);
4226 } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
4227 warning("W017", this);
4228 }
4229
4230 this.left = left;
4231 return this;
4232 };
4233 return x;
4234 }
4235
4236 // fnparam means that this identifier is being defined as a function
4237 // argument (see identifier())
4238 // prop means that this identifier is that of an object property
4239
4240 function optionalidentifier(fnparam, prop) {
4241 if (!state.tokens.next.identifier) {
4242 return;
4243 }
4244
4245 advance();
4246
4247 var curr = state.tokens.curr;
4248 var meta = curr.meta || {};
4249 var val = state.tokens.curr.value;
4250
4251 if (!isReserved(curr)) {
4252 return val;
4253 }
4254
4255 if (prop) {
4256 if (state.option.inES5() || meta.isFutureReservedWord) {
4257 return val;
4258 }
4259 }
4260
4261 if (fnparam && val === "undefined") {
4262 return val;
4263 }
4264
4265 // Display an info message about reserved words as properties
4266 // and ES5 but do it only once.
4267 if (prop && !api.getCache("displayed:I002")) {
4268 api.setCache("displayed:I002", true);
4269 warning("I002");
4270 }
4271
4272 warning("W024", state.tokens.curr, state.tokens.curr.id);
4273 return val;
4274 }
4275
4276 // fnparam means that this identifier is being defined as a function
4277 // argument
4278 // prop means that this identifier is that of an object property
4279 function identifier(fnparam, prop) {
4280 var i = optionalidentifier(fnparam, prop);
4281 if (i) {
4282 return i;
4283 }
4284 if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
4285 warning("W025");
4286 } else {
4287 error("E030", state.tokens.next, state.tokens.next.value);
4288 }
4289 }
4290
4291
4292 function reachable(s) {
4293 var i = 0, t;
4294 if (state.tokens.next.id !== ";" || noreach) {
4295 return;
4296 }
4297 for (;;) {
4298 t = peek(i);
4299 if (t.reach) {
4300 return;
4301 }
4302 if (t.id !== "(endline)") {
4303 if (t.id === "function") {
4304 if (!state.option.latedef) {
4305 break;
4306 }
4307
4308 warning("W026", t);
4309 break;
4310 }
4311
4312 warning("W027", t, t.value, s);
4313 break;
4314 }
4315 i += 1;
4316 }
4317 }
4318
4319
4320 function statement(noindent) {
4321 var values;
4322 var i = indent, r, s = scope, t = state.tokens.next;
4323
4324 if (t.id === ";") {
4325 advance(";");
4326 return;
4327 }
4328
4329 // Is this a labelled statement?
4330 var res = isReserved(t);
4331
4332 // We're being more tolerant here: if someone uses
4333 // a FutureReservedWord as a label, we warn but proceed
4334 // anyway.
4335
4336 if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
4337 warning("W024", t, t.id);
4338 res = false;
4339 }
4340
4341 // detect a destructuring assignment
4342 if (_.has(["[", "{"], t.value)) {
4343 if (lookupBlockType().isDestAssign) {
4344 if (!state.option.inESNext()) {
4345 warning("W104", state.tokens.curr, "destructuring expression");
4346 }
4347 values = destructuringExpression();
4348 values.forEach(function (tok) {
4349 isundef(funct, "W117", tok.token, tok.id);
4350 });
4351 advance("=");
4352 destructuringExpressionMatch(values, expression(5, true));
4353 advance(";");
4354 return;
4355 }
4356 }
4357 if (t.identifier && !res && peek().id === ":") {
4358 advance();
4359 advance(":");
4360 scope = Object.create(s);
4361 addlabel(t.value, "label");
4362
4363 if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
4364 warning("W028", state.tokens.next, t.value, state.tokens.next.value);
4365 }
4366
4367 state.tokens.next.label = t.value;
4368 t = state.tokens.next;
4369 }
4370
4371 // Is it a lonely block?
4372
4373 if (t.id === "{") {
4374 // Is it a switch case block?
4375 //
4376 // switch (foo) {
4377 // case bar: { <= here.
4378 // ...
4379 // }
4380 // }
4381 var iscase = (funct["(verb)"] === "case" && state.tokens.curr.value === ":");
4382 block(true, true, false, false, iscase);
4383 return;
4384 }
4385
4386 // Parse the statement.
4387
4388 if (!noindent) {
4389 indentation();
4390 }
4391 r = expression(0, true);
4392
4393 // Look for the final semicolon.
4394
4395 if (!t.block) {
4396 if (!state.option.expr && (!r || !r.exps)) {
4397 warning("W030", state.tokens.curr);
4398 } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
4399 warning("W031", t);
4400 }
4401
4402 if (state.tokens.next.id !== ";") {
4403 if (!state.option.asi) {
4404 // If this is the last statement in a block that ends on
4405 // the same line *and* option lastsemic is on, ignore the warning.
4406 // Otherwise, complain about missing semicolon.
4407 if (!state.option.lastsemic || state.tokens.next.id !== "}" ||
4408 state.tokens.next.line !== state.tokens.curr.line) {
4409 warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
4410 }
4411 }
4412 } else {
4413 adjacent(state.tokens.curr, state.tokens.next);
4414 advance(";");
4415 nonadjacent(state.tokens.curr, state.tokens.next);
4416 }
4417 }
4418
4419 // Restore the indentation.
4420
4421 indent = i;
4422 scope = s;
4423 return r;
4424 }
4425
4426
4427 function statements(startLine) {
4428 var a = [], p;
4429
4430 while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
4431 if (state.tokens.next.id === ";") {
4432 p = peek();
4433
4434 if (!p || (p.id !== "(" && p.id !== "[")) {
4435 warning("W032");
4436 }
4437
4438 advance(";");
4439 } else {
4440 a.push(statement(startLine === state.tokens.next.line));
4441 }
4442 }
4443 return a;
4444 }
4445
4446
4447 /*
4448 * read all directives
4449 * recognizes a simple form of asi, but always
4450 * warns, if it is used
4451 */
4452 function directives() {
4453 var i, p, pn;
4454
4455 for (;;) {
4456 if (state.tokens.next.id === "(string)") {
4457 p = peek(0);
4458 if (p.id === "(endline)") {
4459 i = 1;
4460 do {
4461 pn = peek(i);
4462 i = i + 1;
4463 } while (pn.id === "(endline)");
4464
4465 if (pn.id !== ";") {
4466 if (pn.id !== "(string)" && pn.id !== "(number)" &&
4467 pn.id !== "(regexp)" && pn.identifier !== true &&
4468 pn.id !== "}") {
4469 break;
4470 }
4471 warning("W033", state.tokens.next);
4472 } else {
4473 p = pn;
4474 }
4475 } else if (p.id === "}") {
4476 // Directive with no other statements, warn about missing semicolon
4477 warning("W033", p);
4478 } else if (p.id !== ";") {
4479 break;
4480 }
4481
4482 indentation();
4483 advance();
4484 if (state.directive[state.tokens.curr.value]) {
4485 warning("W034", state.tokens.curr, state.tokens.curr.value);
4486 }
4487
4488 if (state.tokens.curr.value === "use strict") {
4489 if (!state.option["(explicitNewcap)"])
4490 state.option.newcap = true;
4491 state.option.undef = true;
4492 }
4493
4494 // there's no directive negation, so always set to true
4495 state.directive[state.tokens.curr.value] = true;
4496
4497 if (p.id === ";") {
4498 advance(";");
4499 }
4500 continue;
4501 }
4502 break;
4503 }
4504 }
4505
4506
4507 /*
4508 * Parses a single block. A block is a sequence of statements wrapped in
4509 * braces.
4510 *
4511 * ordinary - true for everything but function bodies and try blocks.
4512 * stmt - true if block can be a single statement (e.g. in if/for/while).
4513 * isfunc - true if block is a function body
4514 * isfatarrow -
4515 * iscase - true if block is a switch case block
4516 */
4517 function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
4518 var a,
4519 b = inblock,
4520 old_indent = indent,
4521 m,
4522 s = scope,
4523 t,
4524 line,
4525 d;
4526
4527 inblock = ordinary;
4528
4529 if (!ordinary || !state.option.funcscope)
4530 scope = Object.create(scope);
4531
4532 nonadjacent(state.tokens.curr, state.tokens.next);
4533 t = state.tokens.next;
4534
4535 var metrics = funct["(metrics)"];
4536 metrics.nestedBlockDepth += 1;
4537 metrics.verifyMaxNestedBlockDepthPerFunction();
4538
4539 if (state.tokens.next.id === "{") {
4540 advance("{");
4541
4542 // create a new block scope
4543 funct["(blockscope)"].stack();
4544
4545 line = state.tokens.curr.line;
4546 if (state.tokens.next.id !== "}") {
4547 indent += state.option.indent;
4548 while (!ordinary && state.tokens.next.from > indent) {
4549 indent += state.option.indent;
4550 }
4551
4552 if (isfunc) {
4553 m = {};
4554 for (d in state.directive) {
4555 if (_.has(state.directive, d)) {
4556 m[d] = state.directive[d];
4557 }
4558 }
4559 directives();
4560
4561 if (state.option.strict && funct["(context)"]["(global)"]) {
4562 if (!m["use strict"] && !state.directive["use strict"]) {
4563 warning("E007");
4564 }
4565 }
4566 }
4567
4568 a = statements(line);
4569
4570 metrics.statementCount += a.length;
4571
4572 if (isfunc) {
4573 state.directive = m;
4574 }
4575
4576 indent -= state.option.indent;
4577 if (line !== state.tokens.next.line) {
4578 indentation();
4579 }
4580 } else if (line !== state.tokens.next.line) {
4581 indentation();
4582 }
4583 advance("}", t);
4584
4585 funct["(blockscope)"].unstack();
4586
4587 indent = old_indent;
4588 } else if (!ordinary) {
4589 if (isfunc) {
4590 m = {};
4591 if (stmt && !isfatarrow && !state.option.inMoz(true)) {
4592 error("W118", state.tokens.curr, "function closure expressions");
4593 }
4594
4595 if (!stmt) {
4596 for (d in state.directive) {
4597 if (_.has(state.directive, d)) {
4598 m[d] = state.directive[d];
4599 }
4600 }
4601 }
4602 expression(5);
4603
4604 if (state.option.strict && funct["(context)"]["(global)"]) {
4605 if (!m["use strict"] && !state.directive["use strict"]) {
4606 warning("E007");
4607 }
4608 }
4609 } else {
4610 error("E021", state.tokens.next, "{", state.tokens.next.value);
4611 }
4612 } else {
4613
4614 // check to avoid let declaration not within a block
4615 funct["(nolet)"] = true;
4616
4617 if (!stmt || state.option.curly) {
4618 warning("W116", state.tokens.next, "{", state.tokens.next.value);
4619 }
4620
4621 noreach = true;
4622 indent += state.option.indent;
4623 // test indentation only if statement is in new line
4624 a = [statement(state.tokens.next.line === state.tokens.curr.line)];
4625 indent -= state.option.indent;
4626 noreach = false;
4627
4628 delete funct["(nolet)"];
4629 }
4630 // If it is a "break" in switch case, don't clear and let it propagate out.
4631 if (!(iscase && funct["(verb)"] === "break")) funct["(verb)"] = null;
4632
4633 if (!ordinary || !state.option.funcscope) scope = s;
4634 inblock = b;
4635 if (ordinary && state.option.noempty && (!a || a.length === 0)) {
4636 warning("W035");
4637 }
4638 metrics.nestedBlockDepth -= 1;
4639 return a;
4640 }
4641
4642
4643 function countMember(m) {
4644 if (membersOnly && typeof membersOnly[m] !== "boolean") {
4645 warning("W036", state.tokens.curr, m);
4646 }
4647 if (typeof member[m] === "number") {
4648 member[m] += 1;
4649 } else {
4650 member[m] = 1;
4651 }
4652 }
4653
4654
4655 function note_implied(tkn) {
4656 var name = tkn.value, line = tkn.line, a = implied[name];
4657 if (typeof a === "function") {
4658 a = false;
4659 }
4660
4661 if (!a) {
4662 a = [line];
4663 implied[name] = a;
4664 } else if (a[a.length - 1] !== line) {
4665 a.push(line);
4666 }
4667 }
4668
4669
4670 // Build the syntax table by declaring the syntactic elements of the language.
4671
4672 type("(number)", function () {
4673 return this;
4674 });
4675
4676 type("(string)", function () {
4677 return this;
4678 });
4679
4680 state.syntax["(identifier)"] = {
4681 type: "(identifier)",
4682 lbp: 0,
4683 identifier: true,
4684 nud: function () {
4685 var v = this.value,
4686 s = scope[v],
4687 f;
4688
4689 if (typeof s === "function") {
4690 // Protection against accidental inheritance.
4691 s = undefined;
4692 } else if (typeof s === "boolean") {
4693 f = funct;
4694 funct = functions[0];
4695 addlabel(v, "var");
4696 s = funct;
4697 funct = f;
4698 }
4699 var block;
4700 if (_.has(funct, "(blockscope)")) {
4701 block = funct["(blockscope)"].getlabel(v);
4702 }
4703
4704 // The name is in scope and defined in the current function.
4705 if (funct === s || block) {
4706 // Change 'unused' to 'var', and reject labels.
4707 // the name is in a block scope
4708 switch (block ? block[v]["(type)"] : funct[v]) {
4709 case "unused":
4710 if (block) block[v]["(type)"] = "var";
4711 else funct[v] = "var";
4712 break;
4713 case "unction":
4714 if (block) block[v]["(type)"] = "function";
4715 else funct[v] = "function";
4716 this["function"] = true;
4717 break;
4718 case "function":
4719 this["function"] = true;
4720 break;
4721 case "label":
4722 warning("W037", state.tokens.curr, v);
4723 break;
4724 }
4725 } else if (funct["(global)"]) {
4726 // The name is not defined in the function. If we are in the global
4727 // scope, then we have an undefined variable.
4728 //
4729 // Operators typeof and delete do not raise runtime errors even if
4730 // the base object of a reference is null so no need to display warning
4731 // if we're inside of typeof or delete.
4732
4733 if (typeof predefined[v] !== "boolean") {
4734 // Attempting to subscript a null reference will throw an
4735 // error, even within the typeof and delete operators
4736 if (!(anonname === "typeof" || anonname === "delete") ||
4737 (state.tokens.next && (state.tokens.next.value === "." ||
4738 state.tokens.next.value === "["))) {
4739
4740 // if we're in a list comprehension, variables are declared
4741 // locally and used before being defined. So we check
4742 // the presence of the given variable in the comp array
4743 // before declaring it undefined.
4744
4745 if (!funct["(comparray)"].check(v)) {
4746 isundef(funct, "W117", state.tokens.curr, v);
4747 }
4748 }
4749 }
4750
4751 note_implied(state.tokens.curr);
4752 } else {
4753 // If the name is already defined in the current
4754 // function, but not as outer, then there is a scope error.
4755
4756 switch (funct[v]) {
4757 case "closure":
4758 case "function":
4759 case "var":
4760 case "unused":
4761 warning("W038", state.tokens.curr, v);
4762 break;
4763 case "label":
4764 warning("W037", state.tokens.curr, v);
4765 break;
4766 case "outer":
4767 case "global":
4768 break;
4769 default:
4770 // If the name is defined in an outer function, make an outer entry,
4771 // and if it was unused, make it var.
4772 if (s === true) {
4773 funct[v] = true;
4774 } else if (s === null) {
4775 warning("W039", state.tokens.curr, v);
4776 note_implied(state.tokens.curr);
4777 } else if (typeof s !== "object") {
4778 // Operators typeof and delete do not raise runtime errors even
4779 // if the base object of a reference is null so no need to
4780 //
4781 // display warning if we're inside of typeof or delete.
4782 // Attempting to subscript a null reference will throw an
4783 // error, even within the typeof and delete operators
4784 if (!(anonname === "typeof" || anonname === "delete") ||
4785 (state.tokens.next &&
4786 (state.tokens.next.value === "." || state.tokens.next.value === "["))) {
4787
4788 isundef(funct, "W117", state.tokens.curr, v);
4789 }
4790 funct[v] = true;
4791 note_implied(state.tokens.curr);
4792 } else {
4793 switch (s[v]) {
4794 case "function":
4795 case "unction":
4796 this["function"] = true;
4797 s[v] = "closure";
4798 funct[v] = s["(global)"] ? "global" : "outer";
4799 break;
4800 case "var":
4801 case "unused":
4802 s[v] = "closure";
4803 funct[v] = s["(global)"] ? "global" : "outer";
4804 break;
4805 case "closure":
4806 funct[v] = s["(global)"] ? "global" : "outer";
4807 break;
4808 case "label":
4809 warning("W037", state.tokens.curr, v);
4810 }
4811 }
4812 }
4813 }
4814 return this;
4815 },
4816 led: function () {
4817 error("E033", state.tokens.next, state.tokens.next.value);
4818 }
4819 };
4820
4821 type("(regexp)", function () {
4822 return this;
4823 });
4824
4825 // ECMAScript parser
4826
4827 delim("(endline)");
4828 delim("(begin)");
4829 delim("(end)").reach = true;
4830 delim("(error)").reach = true;
4831 delim("}").reach = true;
4832 delim(")");
4833 delim("]");
4834 delim("\"").reach = true;
4835 delim("'").reach = true;
4836 delim(";");
4837 delim(":").reach = true;
4838 delim("#");
4839
4840 reserve("else");
4841 reserve("case").reach = true;
4842 reserve("catch");
4843 reserve("default").reach = true;
4844 reserve("finally");
4845 reservevar("arguments", function (x) {
4846 if (state.directive["use strict"] && funct["(global)"]) {
4847 warning("E008", x);
4848 }
4849 });
4850 reservevar("eval");
4851 reservevar("false");
4852 reservevar("Infinity");
4853 reservevar("null");
4854 reservevar("this", function (x) {
4855 if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
4856 funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
4857 warning("W040", x);
4858 }
4859 });
4860 reservevar("true");
4861 reservevar("undefined");
4862
4863 assignop("=", "assign", 20);
4864 assignop("+=", "assignadd", 20);
4865 assignop("-=", "assignsub", 20);
4866 assignop("*=", "assignmult", 20);
4867 assignop("/=", "assigndiv", 20).nud = function () {
4868 error("E014");
4869 };
4870 assignop("%=", "assignmod", 20);
4871
4872 bitwiseassignop("&=", "assignbitand", 20);
4873 bitwiseassignop("|=", "assignbitor", 20);
4874 bitwiseassignop("^=", "assignbitxor", 20);
4875 bitwiseassignop("<<=", "assignshiftleft", 20);
4876 bitwiseassignop(">>=", "assignshiftright", 20);
4877 bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
4878 infix(",", function (left, that) {
4879 var expr;
4880 that.exprs = [left];
4881 if (!comma({peek: true})) {
4882 return that;
4883 }
4884 while (true) {
4885 if (!(expr = expression(5))) {
4886 break;
4887 }
4888 that.exprs.push(expr);
4889 if (state.tokens.next.value !== "," || !comma()) {
4890 break;
4891 }
4892 }
4893 return that;
4894 }, 5, true);
4895 infix("?", function (left, that) {
4896 that.left = left;
4897 that.right = expression(10);
4898 advance(":");
4899 that["else"] = expression(10);
4900 return that;
4901 }, 30);
4902
4903 infix("||", "or", 40);
4904 infix("&&", "and", 50);
4905 bitwise("|", "bitor", 70);
4906 bitwise("^", "bitxor", 80);
4907 bitwise("&", "bitand", 90);
4908 relation("==", function (left, right) {
4909 var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
4910
4911 if (!eqnull && state.option.eqeqeq)
4912 warning("W116", this, "===", "==");
4913 else if (isPoorRelation(left))
4914 warning("W041", this, "===", left.value);
4915 else if (isPoorRelation(right))
4916 warning("W041", this, "===", right.value);
4917
4918 return this;
4919 });
4920 relation("===");
4921 relation("!=", function (left, right) {
4922 var eqnull = state.option.eqnull &&
4923 (left.value === "null" || right.value === "null");
4924
4925 if (!eqnull && state.option.eqeqeq) {
4926 warning("W116", this, "!==", "!=");
4927 } else if (isPoorRelation(left)) {
4928 warning("W041", this, "!==", left.value);
4929 } else if (isPoorRelation(right)) {
4930 warning("W041", this, "!==", right.value);
4931 }
4932 return this;
4933 });
4934 relation("!==");
4935 relation("<");
4936 relation(">");
4937 relation("<=");
4938 relation(">=");
4939 bitwise("<<", "shiftleft", 120);
4940 bitwise(">>", "shiftright", 120);
4941 bitwise(">>>", "shiftrightunsigned", 120);
4942 infix("in", "in", 120);
4943 infix("instanceof", "instanceof", 120);
4944 infix("+", function (left, that) {
4945 var right = expression(130);
4946 if (left && right && left.id === "(string)" && right.id === "(string)") {
4947 left.value += right.value;
4948 left.character = right.character;
4949 if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
4950 warning("W050", left);
4951 }
4952 return left;
4953 }
4954 that.left = left;
4955 that.right = right;
4956 return that;
4957 }, 130);
4958 prefix("+", "num");
4959 prefix("+++", function () {
4960 warning("W007");
4961 this.right = expression(150);
4962 this.arity = "unary";
4963 return this;
4964 });
4965 infix("+++", function (left) {
4966 warning("W007");
4967 this.left = left;
4968 this.right = expression(130);
4969 return this;
4970 }, 130);
4971 infix("-", "sub", 130);
4972 prefix("-", "neg");
4973 prefix("---", function () {
4974 warning("W006");
4975 this.right = expression(150);
4976 this.arity = "unary";
4977 return this;
4978 });
4979 infix("---", function (left) {
4980 warning("W006");
4981 this.left = left;
4982 this.right = expression(130);
4983 return this;
4984 }, 130);
4985 infix("*", "mult", 140);
4986 infix("/", "div", 140);
4987 infix("%", "mod", 140);
4988
4989 suffix("++", "postinc");
4990 prefix("++", "preinc");
4991 state.syntax["++"].exps = true;
4992
4993 suffix("--", "postdec");
4994 prefix("--", "predec");
4995 state.syntax["--"].exps = true;
4996 prefix("delete", function () {
4997 var p = expression(5);
4998 if (!p || (p.id !== "." && p.id !== "[")) {
4999 warning("W051");
5000 }
5001 this.first = p;
5002 return this;
5003 }).exps = true;
5004
5005 prefix("~", function () {
5006 if (state.option.bitwise) {
5007 warning("W052", this, "~");
5008 }
5009 expression(150);
5010 return this;
5011 });
5012
5013 prefix("...", function () {
5014 if (!state.option.inESNext()) {
5015 warning("W104", this, "spread/rest operator");
5016 }
5017 if (!state.tokens.next.identifier) {
5018 error("E030", state.tokens.next, state.tokens.next.value);
5019 }
5020 expression(150);
5021 return this;
5022 });
5023
5024 prefix("!", function () {
5025 this.right = expression(150);
5026 this.arity = "unary";
5027
5028 if (!this.right) { // '!' followed by nothing? Give up.
5029 quit("E041", this.line || 0);
5030 }
5031
5032 if (bang[this.right.id] === true) {
5033 warning("W018", this, "!");
5034 }
5035 return this;
5036 });
5037
5038 prefix("typeof", "typeof");
5039 prefix("new", function () {
5040 var c = expression(155), i;
5041 if (c && c.id !== "function") {
5042 if (c.identifier) {
5043 c["new"] = true;
5044 switch (c.value) {
5045 case "Number":
5046 case "String":
5047 case "Boolean":
5048 case "Math":
5049 case "JSON":
5050 warning("W053", state.tokens.prev, c.value);
5051 break;
5052 case "Function":
5053 if (!state.option.evil) {
5054 warning("W054");
5055 }
5056 break;
5057 case "Date":
5058 case "RegExp":
5059 break;
5060 default:
5061 if (c.id !== "function") {
5062 i = c.value.substr(0, 1);
5063 if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) {
5064 warning("W055", state.tokens.curr);
5065 }
5066 }
5067 }
5068 } else {
5069 if (c.id !== "." && c.id !== "[" && c.id !== "(") {
5070 warning("W056", state.tokens.curr);
5071 }
5072 }
5073 } else {
5074 if (!state.option.supernew)
5075 warning("W057", this);
5076 }
5077 adjacent(state.tokens.curr, state.tokens.next);
5078 if (state.tokens.next.id !== "(" && !state.option.supernew) {
5079 warning("W058", state.tokens.curr, state.tokens.curr.value);
5080 }
5081 this.first = c;
5082 return this;
5083 });
5084 state.syntax["new"].exps = true;
5085
5086 prefix("void").exps = true;
5087
5088 infix(".", function (left, that) {
5089 adjacent(state.tokens.prev, state.tokens.curr);
5090 nobreak();
5091 var m = identifier(false, true);
5092
5093 if (typeof m === "string") {
5094 countMember(m);
5095 }
5096
5097 that.left = left;
5098 that.right = m;
5099
5100 if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
5101 warning("W001");
5102 }
5103
5104 if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
5105 if (state.option.noarg)
5106 warning("W059", left, m);
5107 else if (state.directive["use strict"])
5108 error("E008");
5109 } else if (!state.option.evil && left && left.value === "document" &&
5110 (m === "write" || m === "writeln")) {
5111 warning("W060", left);
5112 }
5113
5114 if (!state.option.evil && (m === "eval" || m === "execScript")) {
5115 warning("W061");
5116 }
5117
5118 return that;
5119 }, 160, true);
5120
5121 infix("(", function (left, that) {
5122 if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
5123 nobreak(state.tokens.prev, state.tokens.curr);
5124 }
5125
5126 nospace();
5127 if (state.option.immed && left && !left.immed && left.id === "function") {
5128 warning("W062");
5129 }
5130
5131 var n = 0;
5132 var p = [];
5133
5134 if (left) {
5135 if (left.type === "(identifier)") {
5136 if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
5137 if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
5138 if (left.value === "Math") {
5139 warning("W063", left);
5140 } else if (state.option.newcap) {
5141 warning("W064", left);
5142 }
5143 }
5144 }
5145 }
5146 }
5147
5148 if (state.tokens.next.id !== ")") {
5149 for (;;) {
5150 p[p.length] = expression(10);
5151 n += 1;
5152 if (state.tokens.next.id !== ",") {
5153 break;
5154 }
5155 comma();
5156 }
5157 }
5158
5159 advance(")");
5160 nospace(state.tokens.prev, state.tokens.curr);
5161
5162 if (typeof left === "object") {
5163 if (left.value === "parseInt" && n === 1) {
5164 warning("W065", state.tokens.curr);
5165 }
5166 if (!state.option.evil) {
5167 if (left.value === "eval" || left.value === "Function" ||
5168 left.value === "execScript") {
5169 warning("W061", left);
5170
5171 if (p[0] && [0].id === "(string)") {
5172 addInternalSrc(left, p[0].value);
5173 }
5174 } else if (p[0] && p[0].id === "(string)" &&
5175 (left.value === "setTimeout" ||
5176 left.value === "setInterval")) {
5177 warning("W066", left);
5178 addInternalSrc(left, p[0].value);
5179
5180 // window.setTimeout/setInterval
5181 } else if (p[0] && p[0].id === "(string)" &&
5182 left.value === "." &&
5183 left.left.value === "window" &&
5184 (left.right === "setTimeout" ||
5185 left.right === "setInterval")) {
5186 warning("W066", left);
5187 addInternalSrc(left, p[0].value);
5188 }
5189 }
5190 if (!left.identifier && left.id !== "." && left.id !== "[" &&
5191 left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
5192 left.id !== "?") {
5193 warning("W067", left);
5194 }
5195 }
5196
5197 that.left = left;
5198 return that;
5199 }, 155, true).exps = true;
5200
5201 prefix("(", function () {
5202 nospace();
5203 var bracket, brackets = [];
5204 var pn, pn1, i = 0;
5205
5206 do {
5207 pn = peek(i);
5208 i += 1;
5209 pn1 = peek(i);
5210 i += 1;
5211 } while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");
5212
5213 if (state.tokens.next.id === "function") {
5214 state.tokens.next.immed = true;
5215 }
5216
5217 var exprs = [];
5218
5219 if (state.tokens.next.id !== ")") {
5220 for (;;) {
5221 if (pn1.value === "=>" && state.tokens.next.value === "{") {
5222 bracket = state.tokens.next;
5223 bracket.left = destructuringExpression();
5224 brackets.push(bracket);
5225 for (var t in bracket.left) {
5226 exprs.push(bracket.left[t].token);
5227 }
5228 } else {
5229 exprs.push(expression(5));
5230 }
5231 if (state.tokens.next.id !== ",") {
5232 break;
5233 }
5234 comma();
5235 }
5236 }
5237
5238 advance(")", this);
5239 nospace(state.tokens.prev, state.tokens.curr);
5240 if (state.option.immed && exprs[0] && exprs[0].id === "function") {
5241 if (state.tokens.next.id !== "(" &&
5242 (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
5243 warning("W068", this);
5244 }
5245 }
5246
5247 if (state.tokens.next.value === "=>") {
5248 return exprs;
5249 }
5250 if (!exprs.length) {
5251 return;
5252 }
5253 exprs[exprs.length - 1].paren = true;
5254 if (exprs.length > 1) {
5255 return Object.create(state.syntax[","], { exprs: { value: exprs } });
5256 }
5257 return exprs[0];
5258 });
5259
5260 application("=>");
5261
5262 infix("[", function (left, that) {
5263 nobreak(state.tokens.prev, state.tokens.curr);
5264 nospace();
5265 var e = expression(5), s;
5266 if (e && e.type === "(string)") {
5267 if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
5268 warning("W061", that);
5269 }
5270
5271 countMember(e.value);
5272 if (!state.option.sub && reg.identifier.test(e.value)) {
5273 s = state.syntax[e.value];
5274 if (!s || !isReserved(s)) {
5275 warning("W069", state.tokens.prev, e.value);
5276 }
5277 }
5278 }
5279 advance("]", that);
5280
5281 if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
5282 warning("W001");
5283 }
5284
5285 nospace(state.tokens.prev, state.tokens.curr);
5286 that.left = left;
5287 that.right = e;
5288 return that;
5289 }, 160, true);
5290
5291 function comprehensiveArrayExpression() {
5292 var res = {};
5293 res.exps = true;
5294 funct["(comparray)"].stack();
5295
5296 res.right = expression(5);
5297 advance("for");
5298 if (state.tokens.next.value === "each") {
5299 advance("each");
5300 if (!state.option.inMoz(true)) {
5301 warning("W118", state.tokens.curr, "for each");
5302 }
5303 }
5304 advance("(");
5305 funct["(comparray)"].setState("define");
5306 res.left = expression(5);
5307 advance(")");
5308 if (state.tokens.next.value === "if") {
5309 advance("if");
5310 advance("(");
5311 funct["(comparray)"].setState("filter");
5312 res.filter = expression(5);
5313 advance(")");
5314 }
5315 advance("]");
5316 funct["(comparray)"].unstack();
5317 return res;
5318 }
5319
5320 prefix("[", function () {
5321 var blocktype = lookupBlockType(true);
5322 if (blocktype.isCompArray) {
5323 if (!state.option.inMoz(true)) {
5324 warning("W118", state.tokens.curr, "array comprehension");
5325 }
5326 return comprehensiveArrayExpression();
5327 } else if (blocktype.isDestAssign && !state.option.inESNext()) {
5328 warning("W104", state.tokens.curr, "destructuring assignment");
5329 }
5330 var b = state.tokens.curr.line !== state.tokens.next.line;
5331 this.first = [];
5332 if (b) {
5333 indent += state.option.indent;
5334 if (state.tokens.next.from === indent + state.option.indent) {
5335 indent += state.option.indent;
5336 }
5337 }
5338 while (state.tokens.next.id !== "(end)") {
5339 while (state.tokens.next.id === ",") {
5340 if (!state.option.inES5())
5341 warning("W070");
5342 advance(",");
5343 }
5344 if (state.tokens.next.id === "]") {
5345 break;
5346 }
5347 if (b && state.tokens.curr.line !== state.tokens.next.line) {
5348 indentation();
5349 }
5350 this.first.push(expression(10));
5351 if (state.tokens.next.id === ",") {
5352 comma({ allowTrailing: true });
5353 if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
5354 warning("W070", state.tokens.curr);
5355 break;
5356 }
5357 } else {
5358 break;
5359 }
5360 }
5361 if (b) {
5362 indent -= state.option.indent;
5363 indentation();
5364 }
5365 advance("]", this);
5366 return this;
5367 }, 160);
5368
5369
5370 function property_name() {
5371 var id = optionalidentifier(false, true);
5372
5373 if (!id) {
5374 if (state.tokens.next.id === "(string)") {
5375 id = state.tokens.next.value;
5376 advance();
5377 } else if (state.tokens.next.id === "(number)") {
5378 id = state.tokens.next.value.toString();
5379 advance();
5380 }
5381 }
5382
5383 if (id === "hasOwnProperty") {
5384 warning("W001");
5385 }
5386
5387 return id;
5388 }
5389
5390
5391 function functionparams(parsed) {
5392 var curr, next;
5393 var params = [];
5394 var ident;
5395 var tokens = [];
5396 var t;
5397
5398 if (parsed) {
5399 if (parsed instanceof Array) {
5400 for (var i in parsed) {
5401 curr = parsed[i];
5402 if (_.contains(["{", "["], curr.id)) {
5403 for (t in curr.left) {
5404 t = tokens[t];
5405 if (t.id) {
5406 params.push(t.id);
5407 addlabel(t.id, "unused", t.token);
5408 }
5409 }
5410 } else if (curr.value === "...") {
5411 if (!state.option.inESNext()) {
5412 warning("W104", curr, "spread/rest operator");
5413 }
5414 continue;
5415 } else {
5416 addlabel(curr.value, "unused", curr);
5417 }
5418 }
5419 return params;
5420 } else {
5421 if (parsed.identifier === true) {
5422 addlabel(parsed.value, "unused", parsed);
5423 return [parsed];
5424 }
5425 }
5426 }
5427
5428 next = state.tokens.next;
5429
5430 advance("(");
5431 nospace();
5432
5433 if (state.tokens.next.id === ")") {
5434 advance(")");
5435 return;
5436 }
5437
5438 for (;;) {
5439 if (_.contains(["{", "["], state.tokens.next.id)) {
5440 tokens = destructuringExpression();
5441 for (t in tokens) {
5442 t = tokens[t];
5443 if (t.id) {
5444 params.push(t.id);
5445 addlabel(t.id, "unused", t.token);
5446 }
5447 }
5448 } else if (state.tokens.next.value === "...") {
5449 if (!state.option.inESNext()) {
5450 warning("W104", state.tokens.next, "spread/rest operator");
5451 }
5452 advance("...");
5453 nospace();
5454 ident = identifier(true);
5455 params.push(ident);
5456 addlabel(ident, "unused", state.tokens.curr);
5457 } else {
5458 ident = identifier(true);
5459 params.push(ident);
5460 addlabel(ident, "unused", state.tokens.curr);
5461 }
5462 if (state.tokens.next.id === ",") {
5463 comma();
5464 } else {
5465 advance(")", next);
5466 nospace(state.tokens.prev, state.tokens.curr);
5467 return params;
5468 }
5469 }
5470 }
5471
5472
5473 function doFunction(name, statement, generator, fatarrowparams) {
5474 var f;
5475 var oldOption = state.option;
5476 var oldIgnored = state.ignored;
5477 var oldScope = scope;
5478
5479 state.option = Object.create(state.option);
5480 state.ignored = Object.create(state.ignored);
5481 scope = Object.create(scope);
5482
5483 funct = {
5484 "(name)" : name || "\"" + anonname + "\"",
5485 "(line)" : state.tokens.next.line,
5486 "(character)" : state.tokens.next.character,
5487 "(context)" : funct,
5488 "(breakage)" : 0,
5489 "(loopage)" : 0,
5490 "(metrics)" : createMetrics(state.tokens.next),
5491 "(scope)" : scope,
5492 "(statement)" : statement,
5493 "(tokens)" : {},
5494 "(blockscope)": funct["(blockscope)"],
5495 "(comparray)" : funct["(comparray)"]
5496 };
5497
5498 if (generator) {
5499 funct["(generator)"] = true;
5500 }
5501
5502 f = funct;
5503 state.tokens.curr.funct = funct;
5504
5505 functions.push(funct);
5506
5507 if (name) {
5508 addlabel(name, "function");
5509 }
5510
5511 funct["(params)"] = functionparams(fatarrowparams);
5512
5513 funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
5514
5515 block(false, true, true, fatarrowparams ? true:false);
5516
5517 if (generator && funct["(generator)"] !== "yielded") {
5518 error("E047", state.tokens.curr);
5519 }
5520
5521 funct["(metrics)"].verifyMaxStatementsPerFunction();
5522 funct["(metrics)"].verifyMaxComplexityPerFunction();
5523 funct["(unusedOption)"] = state.option.unused;
5524
5525 scope = oldScope;
5526 state.option = oldOption;
5527 state.ignored = oldIgnored;
5528 funct["(last)"] = state.tokens.curr.line;
5529 funct["(lastcharacter)"] = state.tokens.curr.character;
5530 funct = funct["(context)"];
5531
5532 return f;
5533 }
5534
5535 function createMetrics(functionStartToken) {
5536 return {
5537 statementCount: 0,
5538 nestedBlockDepth: -1,
5539 ComplexityCount: 1,
5540 verifyMaxStatementsPerFunction: function () {
5541 if (state.option.maxstatements &&
5542 this.statementCount > state.option.maxstatements) {
5543 warning("W071", functionStartToken, this.statementCount);
5544 }
5545 },
5546
5547 verifyMaxParametersPerFunction: function (params) {
5548 params = params || [];
5549
5550 if (state.option.maxparams && params.length > state.option.maxparams) {
5551 warning("W072", functionStartToken, params.length);
5552 }
5553 },
5554
5555 verifyMaxNestedBlockDepthPerFunction: function () {
5556 if (state.option.maxdepth &&
5557 this.nestedBlockDepth > 0 &&
5558 this.nestedBlockDepth === state.option.maxdepth + 1) {
5559 warning("W073", null, this.nestedBlockDepth);
5560 }
5561 },
5562
5563 verifyMaxComplexityPerFunction: function () {
5564 var max = state.option.maxcomplexity;
5565 var cc = this.ComplexityCount;
5566 if (max && cc > max) {
5567 warning("W074", functionStartToken, cc);
5568 }
5569 }
5570 };
5571 }
5572
5573 function increaseComplexityCount() {
5574 funct["(metrics)"].ComplexityCount += 1;
5575 }
5576
5577 // Parse assignments that were found instead of conditionals.
5578 // For example: if (a = 1) { ... }
5579
5580 function checkCondAssignment(expr) {
5581 var id = expr.id;
5582 if (id === ",") {
5583 expr = expr.exprs[expr.exprs.length - 1];
5584 id = expr.id;
5585 }
5586 switch (id) {
5587 case "=":
5588 case "+=":
5589 case "-=":
5590 case "*=":
5591 case "%=":
5592 case "&=":
5593 case "|=":
5594 case "^=":
5595 case "/=":
5596 if (!expr.paren && !state.option.boss) {
5597 warning("W084");
5598 }
5599 }
5600 }
5601
5602
5603 (function (x) {
5604 x.nud = function (isclassdef) {
5605 var b, f, i, p, t, g;
5606 var props = {}; // All properties, including accessors
5607 var tag = "";
5608
5609 function saveProperty(name, tkn) {
5610 if (props[name] && _.has(props, name))
5611 warning("W075", state.tokens.next, i);
5612 else
5613 props[name] = {};
5614
5615 props[name].basic = true;
5616 props[name].basictkn = tkn;
5617 }
5618
5619 function saveSetter(name, tkn) {
5620 if (props[name] && _.has(props, name)) {
5621 if (props[name].basic || props[name].setter)
5622 warning("W075", state.tokens.next, i);
5623 } else {
5624 props[name] = {};
5625 }
5626
5627 props[name].setter = true;
5628 props[name].setterToken = tkn;
5629 }
5630
5631 function saveGetter(name) {
5632 if (props[name] && _.has(props, name)) {
5633 if (props[name].basic || props[name].getter)
5634 warning("W075", state.tokens.next, i);
5635 } else {
5636 props[name] = {};
5637 }
5638
5639 props[name].getter = true;
5640 props[name].getterToken = state.tokens.curr;
5641 }
5642
5643 b = state.tokens.curr.line !== state.tokens.next.line;
5644 if (b) {
5645 indent += state.option.indent;
5646 if (state.tokens.next.from === indent + state.option.indent) {
5647 indent += state.option.indent;
5648 }
5649 }
5650
5651 for (;;) {
5652 if (state.tokens.next.id === "}") {
5653 break;
5654 }
5655
5656 if (b) {
5657 indentation();
5658 }
5659
5660 if (isclassdef && state.tokens.next.value === "static") {
5661 advance("static");
5662 tag = "static ";
5663 }
5664
5665 if (state.tokens.next.value === "get" && peek().id !== ":") {
5666 advance("get");
5667
5668 if (!state.option.inES5(!isclassdef)) {
5669 error("E034");
5670 }
5671
5672 i = property_name();
5673 if (!i) {
5674 error("E035");
5675 }
5676
5677 // It is a Syntax Error if PropName of MethodDefinition is
5678 // "constructor" and SpecialMethod of MethodDefinition is true.
5679 if (isclassdef && i === "constructor") {
5680 error("E049", state.tokens.next, "class getter method", i);
5681 }
5682
5683 saveGetter(tag + i);
5684 t = state.tokens.next;
5685 adjacent(state.tokens.curr, state.tokens.next);
5686 f = doFunction();
5687 p = f["(params)"];
5688
5689 if (p) {
5690 warning("W076", t, p[0], i);
5691 }
5692
5693 adjacent(state.tokens.curr, state.tokens.next);
5694 } else if (state.tokens.next.value === "set" && peek().id !== ":") {
5695 advance("set");
5696
5697 if (!state.option.inES5(!isclassdef)) {
5698 error("E034");
5699 }
5700
5701 i = property_name();
5702 if (!i) {
5703 error("E035");
5704 }
5705
5706 // It is a Syntax Error if PropName of MethodDefinition is
5707 // "constructor" and SpecialMethod of MethodDefinition is true.
5708 if (isclassdef && i === "constructor") {
5709 error("E049", state.tokens.next, "class setter method", i);
5710 }
5711
5712 saveSetter(tag + i, state.tokens.next);
5713 t = state.tokens.next;
5714 adjacent(state.tokens.curr, state.tokens.next);
5715 f = doFunction();
5716 p = f["(params)"];
5717
5718 if (!p || p.length !== 1) {
5719 warning("W077", t, i);
5720 }
5721 } else {
5722 g = false;
5723 if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
5724 if (!state.option.inESNext()) {
5725 warning("W104", state.tokens.next, "generator functions");
5726 }
5727 advance("*");
5728 g = true;
5729 }
5730 i = property_name();
5731 saveProperty(tag + i, state.tokens.next);
5732
5733 if (typeof i !== "string") {
5734 break;
5735 }
5736
5737 if (state.tokens.next.value === "(") {
5738 if (!state.option.inESNext()) {
5739 warning("W104", state.tokens.curr, "concise methods");
5740 }
5741 doFunction(i, undefined, g);
5742 } else if (!isclassdef) {
5743 advance(":");
5744 nonadjacent(state.tokens.curr, state.tokens.next);
5745 expression(10);
5746 }
5747 }
5748 // It is a Syntax Error if PropName of MethodDefinition is "prototype".
5749 if (isclassdef && i === "prototype") {
5750 error("E049", state.tokens.next, "class method", i);
5751 }
5752
5753 countMember(i);
5754 if (isclassdef) {
5755 tag = "";
5756 continue;
5757 }
5758 if (state.tokens.next.id === ",") {
5759 comma({ allowTrailing: true, property: true });
5760 if (state.tokens.next.id === ",") {
5761 warning("W070", state.tokens.curr);
5762 } else if (state.tokens.next.id === "}" && !state.option.inES5(true)) {
5763 warning("W070", state.tokens.curr);
5764 }
5765 } else {
5766 break;
5767 }
5768 }
5769 if (b) {
5770 indent -= state.option.indent;
5771 indentation();
5772 }
5773 advance("}", this);
5774
5775 // Check for lonely setters if in the ES5 mode.
5776 if (state.option.inES5()) {
5777 for (var name in props) {
5778 if (_.has(props, name) && props[name].setter && !props[name].getter) {
5779 warning("W078", props[name].setterToken);
5780 }
5781 }
5782 }
5783 return this;
5784 };
5785 x.fud = function () {
5786 error("E036", state.tokens.curr);
5787 };
5788 }(delim("{")));
5789
5790 function destructuringExpression() {
5791 var id, ids;
5792 var identifiers = [];
5793 if (!state.option.inESNext()) {
5794 warning("W104", state.tokens.curr, "destructuring expression");
5795 }
5796 var nextInnerDE = function () {
5797 var ident;
5798 if (_.contains(["[", "{"], state.tokens.next.value)) {
5799 ids = destructuringExpression();
5800 for (var id in ids) {
5801 id = ids[id];
5802 identifiers.push({ id: id.id, token: id.token });
5803 }
5804 } else if (state.tokens.next.value === ",") {
5805 identifiers.push({ id: null, token: state.tokens.curr });
5806 } else {
5807 ident = identifier();
5808 if (ident)
5809 identifiers.push({ id: ident, token: state.tokens.curr });
5810 }
5811 };
5812 if (state.tokens.next.value === "[") {
5813 advance("[");
5814 nextInnerDE();
5815 while (state.tokens.next.value !== "]") {
5816 advance(",");
5817 nextInnerDE();
5818 }
5819 advance("]");
5820 } else if (state.tokens.next.value === "{") {
5821 advance("{");
5822 id = identifier();
5823 if (state.tokens.next.value === ":") {
5824 advance(":");
5825 nextInnerDE();
5826 } else {
5827 identifiers.push({ id: id, token: state.tokens.curr });
5828 }
5829 while (state.tokens.next.value !== "}") {
5830 advance(",");
5831 id = identifier();
5832 if (state.tokens.next.value === ":") {
5833 advance(":");
5834 nextInnerDE();
5835 } else {
5836 identifiers.push({ id: id, token: state.tokens.curr });
5837 }
5838 }
5839 advance("}");
5840 }
5841 return identifiers;
5842 }
5843 function destructuringExpressionMatch(tokens, value) {
5844 if (value.first) {
5845 _.zip(tokens, value.first).forEach(function (val) {
5846 var token = val[0];
5847 var value = val[1];
5848 if (token && value) {
5849 token.first = value;
5850 } else if (token && token.first && !value) {
5851 warning("W080", token.first, token.first.value);
5852 } /* else {
5853 XXX value is discarded: wouldn't it need a warning ?
5854 } */
5855 });
5856 }
5857 }
5858
5859 var conststatement = stmt("const", function (prefix) {
5860 var tokens, value;
5861 // state variable to know if it is a lone identifier, or a destructuring statement.
5862 var lone;
5863
5864 if (!state.option.inESNext()) {
5865 warning("W104", state.tokens.curr, "const");
5866 }
5867
5868 this.first = [];
5869 for (;;) {
5870 var names = [];
5871 nonadjacent(state.tokens.curr, state.tokens.next);
5872 if (_.contains(["{", "["], state.tokens.next.value)) {
5873 tokens = destructuringExpression();
5874 lone = false;
5875 } else {
5876 tokens = [ { id: identifier(), token: state.tokens.curr } ];
5877 lone = true;
5878 }
5879 for (var t in tokens) {
5880 t = tokens[t];
5881 if (funct[t.id] === "const") {
5882 warning("E011", null, t.id);
5883 }
5884 if (funct["(global)"] && predefined[t.id] === false) {
5885 warning("W079", t.token, t.id);
5886 }
5887 if (t.id) {
5888 addlabel(t.id, "const");
5889 names.push(t.token);
5890 }
5891 }
5892 if (prefix) {
5893 break;
5894 }
5895
5896 this.first = this.first.concat(names);
5897
5898 if (state.tokens.next.id !== "=") {
5899 warning("E012", state.tokens.curr, state.tokens.curr.value);
5900 }
5901
5902 if (state.tokens.next.id === "=") {
5903 nonadjacent(state.tokens.curr, state.tokens.next);
5904 advance("=");
5905 nonadjacent(state.tokens.curr, state.tokens.next);
5906 if (state.tokens.next.id === "undefined") {
5907 warning("W080", state.tokens.prev, state.tokens.prev.value);
5908 }
5909 if (peek(0).id === "=" && state.tokens.next.identifier) {
5910 error("E037", state.tokens.next, state.tokens.next.value);
5911 }
5912 value = expression(5);
5913 if (lone) {
5914 tokens[0].first = value;
5915 } else {
5916 destructuringExpressionMatch(names, value);
5917 }
5918 }
5919
5920 if (state.tokens.next.id !== ",") {
5921 break;
5922 }
5923 comma();
5924 }
5925 return this;
5926 });
5927 conststatement.exps = true;
5928 var varstatement = stmt("var", function (prefix) {
5929 // JavaScript does not have block scope. It only has function scope. So,
5930 // declaring a variable in a block can have unexpected consequences.
5931 var tokens, lone, value;
5932
5933 if (funct["(onevar)"] && state.option.onevar) {
5934 warning("W081");
5935 } else if (!funct["(global)"]) {
5936 funct["(onevar)"] = true;
5937 }
5938
5939 this.first = [];
5940 for (;;) {
5941 var names = [];
5942 nonadjacent(state.tokens.curr, state.tokens.next);
5943 if (_.contains(["{", "["], state.tokens.next.value)) {
5944 tokens = destructuringExpression();
5945 lone = false;
5946 } else {
5947 tokens = [ { id: identifier(), token: state.tokens.curr } ];
5948 lone = true;
5949 }
5950 for (var t in tokens) {
5951 t = tokens[t];
5952 if (state.option.inESNext() && funct[t.id] === "const") {
5953 warning("E011", null, t.id);
5954 }
5955 if (funct["(global)"] && predefined[t.id] === false) {
5956 warning("W079", t.token, t.id);
5957 }
5958 if (t.id) {
5959 addlabel(t.id, "unused", t.token);
5960 names.push(t.token);
5961 }
5962 }
5963 if (prefix) {
5964 break;
5965 }
5966
5967 this.first = this.first.concat(names);
5968
5969 if (state.tokens.next.id === "=") {
5970 nonadjacent(state.tokens.curr, state.tokens.next);
5971 advance("=");
5972 nonadjacent(state.tokens.curr, state.tokens.next);
5973 if (state.tokens.next.id === "undefined") {
5974 warning("W080", state.tokens.prev, state.tokens.prev.value);
5975 }
5976 if (peek(0).id === "=" && state.tokens.next.identifier) {
5977 error("E038", state.tokens.next, state.tokens.next.value);
5978 }
5979 value = expression(5);
5980 if (lone) {
5981 tokens[0].first = value;
5982 } else {
5983 destructuringExpressionMatch(names, value);
5984 }
5985 }
5986
5987 if (state.tokens.next.id !== ",") {
5988 break;
5989 }
5990 comma();
5991 }
5992 return this;
5993 });
5994 varstatement.exps = true;
5995 var letstatement = stmt("let", function (prefix) {
5996 var tokens, lone, value, letblock;
5997
5998 if (!state.option.inESNext()) {
5999 warning("W104", state.tokens.curr, "let");
6000 }
6001
6002 if (state.tokens.next.value === "(") {
6003 if (!state.option.inMoz(true)) {
6004 warning("W118", state.tokens.next, "let block");
6005 }
6006 advance("(");
6007 funct["(blockscope)"].stack();
6008 letblock = true;
6009 } else if (funct["(nolet)"]) {
6010 error("E048", state.tokens.curr);
6011 }
6012
6013 if (funct["(onevar)"] && state.option.onevar) {
6014 warning("W081");
6015 } else if (!funct["(global)"]) {
6016 funct["(onevar)"] = true;
6017 }
6018
6019 this.first = [];
6020 for (;;) {
6021 var names = [];
6022 nonadjacent(state.tokens.curr, state.tokens.next);
6023 if (_.contains(["{", "["], state.tokens.next.value)) {
6024 tokens = destructuringExpression();
6025 lone = false;
6026 } else {
6027 tokens = [ { id: identifier(), token: state.tokens.curr.value } ];
6028 lone = true;
6029 }
6030 for (var t in tokens) {
6031 t = tokens[t];
6032 if (state.option.inESNext() && funct[t.id] === "const") {
6033 warning("E011", null, t.id);
6034 }
6035 if (funct["(global)"] && predefined[t.id] === false) {
6036 warning("W079", t.token, t.id);
6037 }
6038 if (t.id && !funct["(nolet)"]) {
6039 addlabel(t.id, "unused", t.token, true);
6040 names.push(t.token);
6041 }
6042 }
6043 if (prefix) {
6044 break;
6045 }
6046
6047 this.first = this.first.concat(names);
6048
6049 if (state.tokens.next.id === "=") {
6050 nonadjacent(state.tokens.curr, state.tokens.next);
6051 advance("=");
6052 nonadjacent(state.tokens.curr, state.tokens.next);
6053 if (state.tokens.next.id === "undefined") {
6054 warning("W080", state.tokens.prev, state.tokens.prev.value);
6055 }
6056 if (peek(0).id === "=" && state.tokens.next.identifier) {
6057 error("E037", state.tokens.next, state.tokens.next.value);
6058 }
6059 value = expression(5);
6060 if (lone) {
6061 tokens[0].first = value;
6062 } else {
6063 destructuringExpressionMatch(names, value);
6064 }
6065 }
6066
6067 if (state.tokens.next.id !== ",") {
6068 break;
6069 }
6070 comma();
6071 }
6072 if (letblock) {
6073 advance(")");
6074 block(true, true);
6075 this.block = true;
6076 funct["(blockscope)"].unstack();
6077 }
6078
6079 return this;
6080 });
6081 letstatement.exps = true;
6082
6083 blockstmt("class", function () {
6084 return classdef.call(this, true);
6085 });
6086
6087 function classdef(stmt) {
6088 /*jshint validthis:true */
6089 if (!state.option.inESNext()) {
6090 warning("W104", state.tokens.curr, "class");
6091 }
6092 if (stmt) {
6093 // BindingIdentifier
6094 this.name = identifier();
6095 addlabel(this.name, "unused", state.tokens.curr);
6096 } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
6097 // BindingIdentifier(opt)
6098 this.name = identifier();
6099 }
6100 classtail(this);
6101 return this;
6102 }
6103
6104 function classtail(c) {
6105 var strictness = state.directive["use strict"];
6106
6107 // ClassHeritage(opt)
6108 if (state.tokens.next.value === "extends") {
6109 advance("extends");
6110 c.heritage = expression(10);
6111 }
6112
6113 // A ClassBody is always strict code.
6114 state.directive["use strict"] = true;
6115 advance("{");
6116 // ClassBody(opt)
6117 c.body = state.syntax["{"].nud(true);
6118 state.directive["use strict"] = strictness;
6119 }
6120
6121 blockstmt("function", function () {
6122 var generator = false;
6123 if (state.tokens.next.value === "*") {
6124 advance("*");
6125 if (state.option.inESNext(true)) {
6126 generator = true;
6127 } else {
6128 warning("W119", state.tokens.curr, "function*");
6129 }
6130 }
6131 if (inblock) {
6132 warning("W082", state.tokens.curr);
6133
6134 }
6135 var i = identifier();
6136 if (funct[i] === "const") {
6137 warning("E011", null, i);
6138 }
6139 adjacent(state.tokens.curr, state.tokens.next);
6140 addlabel(i, "unction", state.tokens.curr);
6141
6142 doFunction(i, { statement: true }, generator);
6143 if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {
6144 error("E039");
6145 }
6146 return this;
6147 });
6148
6149 prefix("function", function () {
6150 var generator = false;
6151 if (state.tokens.next.value === "*") {
6152 if (!state.option.inESNext()) {
6153 warning("W119", state.tokens.curr, "function*");
6154 }
6155 advance("*");
6156 generator = true;
6157 }
6158 var i = optionalidentifier();
6159 if (i || state.option.gcl) {
6160 adjacent(state.tokens.curr, state.tokens.next);
6161 } else {
6162 nonadjacent(state.tokens.curr, state.tokens.next);
6163 }
6164 doFunction(i, undefined, generator);
6165 if (!state.option.loopfunc && funct["(loopage)"]) {
6166 warning("W083");
6167 }
6168 return this;
6169 });
6170
6171 blockstmt("if", function () {
6172 var t = state.tokens.next;
6173 increaseComplexityCount();
6174 state.condition = true;
6175 advance("(");
6176 nonadjacent(this, t);
6177 nospace();
6178 checkCondAssignment(expression(0));
6179 advance(")", t);
6180 state.condition = false;
6181 nospace(state.tokens.prev, state.tokens.curr);
6182 block(true, true);
6183 if (state.tokens.next.id === "else") {
6184 nonadjacent(state.tokens.curr, state.tokens.next);
6185 advance("else");
6186 if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
6187 statement(true);
6188 } else {
6189 block(true, true);
6190 }
6191 }
6192 return this;
6193 });
6194
6195 blockstmt("try", function () {
6196 var b;
6197
6198 function doCatch() {
6199 var oldScope = scope;
6200 var e;
6201
6202 advance("catch");
6203 nonadjacent(state.tokens.curr, state.tokens.next);
6204 advance("(");
6205
6206 scope = Object.create(oldScope);
6207
6208 e = state.tokens.next.value;
6209 if (state.tokens.next.type !== "(identifier)") {
6210 e = null;
6211 warning("E030", state.tokens.next, e);
6212 }
6213
6214 advance();
6215
6216 funct = {
6217 "(name)" : "(catch)",
6218 "(line)" : state.tokens.next.line,
6219 "(character)": state.tokens.next.character,
6220 "(context)" : funct,
6221 "(breakage)" : funct["(breakage)"],
6222 "(loopage)" : funct["(loopage)"],
6223 "(scope)" : scope,
6224 "(statement)": false,
6225 "(metrics)" : createMetrics(state.tokens.next),
6226 "(catch)" : true,
6227 "(tokens)" : {},
6228 "(blockscope)": funct["(blockscope)"],
6229 "(comparray)": funct["(comparray)"]
6230 };
6231
6232 if (e) {
6233 addlabel(e, "exception");
6234 }
6235
6236 if (state.tokens.next.value === "if") {
6237 if (!state.option.inMoz(true)) {
6238 warning("W118", state.tokens.curr, "catch filter");
6239 }
6240 advance("if");
6241 expression(0);
6242 }
6243
6244 advance(")");
6245
6246 state.tokens.curr.funct = funct;
6247 functions.push(funct);
6248
6249 block(false);
6250
6251 scope = oldScope;
6252
6253 funct["(last)"] = state.tokens.curr.line;
6254 funct["(lastcharacter)"] = state.tokens.curr.character;
6255 funct = funct["(context)"];
6256 }
6257
6258 block(false);
6259
6260 while (state.tokens.next.id === "catch") {
6261 increaseComplexityCount();
6262 if (b && (!state.option.inMoz(true))) {
6263 warning("W118", state.tokens.next, "multiple catch blocks");
6264 }
6265 doCatch();
6266 b = true;
6267 }
6268
6269 if (state.tokens.next.id === "finally") {
6270 advance("finally");
6271 block(false);
6272 return;
6273 }
6274
6275 if (!b) {
6276 error("E021", state.tokens.next, "catch", state.tokens.next.value);
6277 }
6278
6279 return this;
6280 });
6281
6282 blockstmt("while", function () {
6283 var t = state.tokens.next;
6284 funct["(breakage)"] += 1;
6285 funct["(loopage)"] += 1;
6286 increaseComplexityCount();
6287 advance("(");
6288 nonadjacent(this, t);
6289 nospace();
6290 checkCondAssignment(expression(0));
6291 advance(")", t);
6292 nospace(state.tokens.prev, state.tokens.curr);
6293 block(true, true);
6294 funct["(breakage)"] -= 1;
6295 funct["(loopage)"] -= 1;
6296 return this;
6297 }).labelled = true;
6298
6299 blockstmt("with", function () {
6300 var t = state.tokens.next;
6301 if (state.directive["use strict"]) {
6302 error("E010", state.tokens.curr);
6303 } else if (!state.option.withstmt) {
6304 warning("W085", state.tokens.curr);
6305 }
6306
6307 advance("(");
6308 nonadjacent(this, t);
6309 nospace();
6310 expression(0);
6311 advance(")", t);
6312 nospace(state.tokens.prev, state.tokens.curr);
6313 block(true, true);
6314
6315 return this;
6316 });
6317
6318 blockstmt("switch", function () {
6319 var t = state.tokens.next,
6320 g = false;
6321 funct["(breakage)"] += 1;
6322 advance("(");
6323 nonadjacent(this, t);
6324 nospace();
6325 checkCondAssignment(expression(0));
6326 advance(")", t);
6327 nospace(state.tokens.prev, state.tokens.curr);
6328 nonadjacent(state.tokens.curr, state.tokens.next);
6329 t = state.tokens.next;
6330 advance("{");
6331 nonadjacent(state.tokens.curr, state.tokens.next);
6332 indent += state.option.indent;
6333 this.cases = [];
6334
6335 for (;;) {
6336 switch (state.tokens.next.id) {
6337 case "case":
6338 switch (funct["(verb)"]) {
6339 case "yield":
6340 case "break":
6341 case "case":
6342 case "continue":
6343 case "return":
6344 case "switch":
6345 case "throw":
6346 break;
6347 default:
6348 // You can tell JSHint that you don't use break intentionally by
6349 // adding a comment /* falls through */ on a line just before
6350 // the next `case`.
6351 if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
6352 warning("W086", state.tokens.curr, "case");
6353 }
6354 }
6355 indentation(-state.option.indent);
6356 advance("case");
6357 this.cases.push(expression(20));
6358 increaseComplexityCount();
6359 g = true;
6360 advance(":");
6361 funct["(verb)"] = "case";
6362 break;
6363 case "default":
6364 switch (funct["(verb)"]) {
6365 case "yield":
6366 case "break":
6367 case "continue":
6368 case "return":
6369 case "throw":
6370 break;
6371 default:
6372 // Do not display a warning if 'default' is the first statement or if
6373 // there is a special /* falls through */ comment.
6374 if (this.cases.length) {
6375 if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
6376 warning("W086", state.tokens.curr, "default");
6377 }
6378 }
6379 }
6380 indentation(-state.option.indent);
6381 advance("default");
6382 g = true;
6383 advance(":");
6384 break;
6385 case "}":
6386 indent -= state.option.indent;
6387 indentation();
6388 advance("}", t);
6389 funct["(breakage)"] -= 1;
6390 funct["(verb)"] = undefined;
6391 return;
6392 case "(end)":
6393 error("E023", state.tokens.next, "}");
6394 return;
6395 default:
6396 if (g) {
6397 switch (state.tokens.curr.id) {
6398 case ",":
6399 error("E040");
6400 return;
6401 case ":":
6402 g = false;
6403 statements();
6404 break;
6405 default:
6406 error("E025", state.tokens.curr);
6407 return;
6408 }
6409 } else {
6410 if (state.tokens.curr.id === ":") {
6411 advance(":");
6412 error("E024", state.tokens.curr, ":");
6413 statements();
6414 } else {
6415 error("E021", state.tokens.next, "case", state.tokens.next.value);
6416 return;
6417 }
6418 }
6419 }
6420 }
6421 }).labelled = true;
6422
6423 stmt("debugger", function () {
6424 if (!state.option.debug) {
6425 warning("W087");
6426 }
6427 return this;
6428 }).exps = true;
6429
6430 (function () {
6431 var x = stmt("do", function () {
6432 funct["(breakage)"] += 1;
6433 funct["(loopage)"] += 1;
6434 increaseComplexityCount();
6435
6436 this.first = block(true, true);
6437 advance("while");
6438 var t = state.tokens.next;
6439 nonadjacent(state.tokens.curr, t);
6440 advance("(");
6441 nospace();
6442 checkCondAssignment(expression(0));
6443 advance(")", t);
6444 nospace(state.tokens.prev, state.tokens.curr);
6445 funct["(breakage)"] -= 1;
6446 funct["(loopage)"] -= 1;
6447 return this;
6448 });
6449 x.labelled = true;
6450 x.exps = true;
6451 }());
6452
6453 blockstmt("for", function () {
6454 var s, t = state.tokens.next;
6455 var letscope = false;
6456 var foreachtok = null;
6457
6458 if (t.value === "each") {
6459 foreachtok = t;
6460 advance("each");
6461 if (!state.option.inMoz(true)) {
6462 warning("W118", state.tokens.curr, "for each");
6463 }
6464 }
6465
6466 funct["(breakage)"] += 1;
6467 funct["(loopage)"] += 1;
6468 increaseComplexityCount();
6469 advance("(");
6470 nonadjacent(this, t);
6471 nospace();
6472
6473 // what kind of for(…) statement it is? for(…of…)? for(…in…)? for(…;…;…)?
6474 var nextop; // contains the token of the "in" or "of" operator
6475 var i = 0;
6476 var inof = ["in", "of"];
6477 do {
6478 nextop = peek(i);
6479 ++i;
6480 } while (!_.contains(inof, nextop.value) && nextop.value !== ";" &&
6481 nextop.type !== "(end)");
6482
6483 // if we're in a for (… in|of …) statement
6484 if (_.contains(inof, nextop.value)) {
6485 if (!state.option.inESNext() && nextop.value === "of") {
6486 error("W104", nextop, "for of");
6487 }
6488 if (state.tokens.next.id === "var") {
6489 advance("var");
6490 state.syntax["var"].fud.call(state.syntax["var"].fud, true);
6491 } else if (state.tokens.next.id === "let") {
6492 advance("let");
6493 // create a new block scope
6494 letscope = true;
6495 funct["(blockscope)"].stack();
6496 state.syntax["let"].fud.call(state.syntax["let"].fud, true);
6497 } else {
6498 switch (funct[state.tokens.next.value]) {
6499 case "unused":
6500 funct[state.tokens.next.value] = "var";
6501 break;
6502 case "var":
6503 break;
6504 default:
6505 if (!funct["(blockscope)"].getlabel(state.tokens.next.value))
6506 warning("W088", state.tokens.next, state.tokens.next.value);
6507 }
6508 advance();
6509 }
6510 advance(nextop.value);
6511 expression(20);
6512 advance(")", t);
6513 s = block(true, true);
6514 if (state.option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
6515 s[0].value !== "if")) {
6516 warning("W089", this);
6517 }
6518 funct["(breakage)"] -= 1;
6519 funct["(loopage)"] -= 1;
6520 } else {
6521 if (foreachtok) {
6522 error("E045", foreachtok);
6523 }
6524 if (state.tokens.next.id !== ";") {
6525 if (state.tokens.next.id === "var") {
6526 advance("var");
6527 state.syntax["var"].fud.call(state.syntax["var"].fud);
6528 } else if (state.tokens.next.id === "let") {
6529 advance("let");
6530 // create a new block scope
6531 letscope = true;
6532 funct["(blockscope)"].stack();
6533 state.syntax["let"].fud.call(state.syntax["let"].fud);
6534 } else {
6535 for (;;) {
6536 expression(0, "for");
6537 if (state.tokens.next.id !== ",") {
6538 break;
6539 }
6540 comma();
6541 }
6542 }
6543 }
6544 nolinebreak(state.tokens.curr);
6545 advance(";");
6546 if (state.tokens.next.id !== ";") {
6547 checkCondAssignment(expression(0));
6548 }
6549 nolinebreak(state.tokens.curr);
6550 advance(";");
6551 if (state.tokens.next.id === ";") {
6552 error("E021", state.tokens.next, ")", ";");
6553 }
6554 if (state.tokens.next.id !== ")") {
6555 for (;;) {
6556 expression(0, "for");
6557 if (state.tokens.next.id !== ",") {
6558 break;
6559 }
6560 comma();
6561 }
6562 }
6563 advance(")", t);
6564 nospace(state.tokens.prev, state.tokens.curr);
6565 block(true, true);
6566 funct["(breakage)"] -= 1;
6567 funct["(loopage)"] -= 1;
6568
6569 }
6570 // unstack loop blockscope
6571 if (letscope) {
6572 funct["(blockscope)"].unstack();
6573 }
6574 return this;
6575 }).labelled = true;
6576
6577
6578 stmt("break", function () {
6579 var v = state.tokens.next.value;
6580
6581 if (funct["(breakage)"] === 0)
6582 warning("W052", state.tokens.next, this.value);
6583
6584 if (!state.option.asi)
6585 nolinebreak(this);
6586
6587 if (state.tokens.next.id !== ";") {
6588 if (state.tokens.curr.line === state.tokens.next.line) {
6589 if (funct[v] !== "label") {
6590 warning("W090", state.tokens.next, v);
6591 } else if (scope[v] !== funct) {
6592 warning("W091", state.tokens.next, v);
6593 }
6594 this.first = state.tokens.next;
6595 advance();
6596 }
6597 }
6598 reachable("break");
6599 return this;
6600 }).exps = true;
6601
6602
6603 stmt("continue", function () {
6604 var v = state.tokens.next.value;
6605
6606 if (funct["(breakage)"] === 0)
6607 warning("W052", state.tokens.next, this.value);
6608
6609 if (!state.option.asi)
6610 nolinebreak(this);
6611
6612 if (state.tokens.next.id !== ";") {
6613 if (state.tokens.curr.line === state.tokens.next.line) {
6614 if (funct[v] !== "label") {
6615 warning("W090", state.tokens.next, v);
6616 } else if (scope[v] !== funct) {
6617 warning("W091", state.tokens.next, v);
6618 }
6619 this.first = state.tokens.next;
6620 advance();
6621 }
6622 } else if (!funct["(loopage)"]) {
6623 warning("W052", state.tokens.next, this.value);
6624 }
6625 reachable("continue");
6626 return this;
6627 }).exps = true;
6628
6629
6630 stmt("return", function () {
6631 if (this.line === state.tokens.next.line) {
6632 if (state.tokens.next.id === "(regexp)")
6633 warning("W092");
6634
6635 if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
6636 nonadjacent(state.tokens.curr, state.tokens.next);
6637 this.first = expression(0);
6638
6639 if (this.first &&
6640 this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
6641 warningAt("W093", this.first.line, this.first.character);
6642 }
6643 }
6644 } else {
6645 if (state.tokens.next.type === "(punctuator)" &&
6646 ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) {
6647 nolinebreak(this); // always warn (Line breaking error)
6648 }
6649 }
6650 reachable("return");
6651 return this;
6652 }).exps = true;
6653
6654 stmt("yield", function () {
6655 if (state.option.inESNext(true) && funct["(generator)"] !== true) {
6656 error("E046", state.tokens.curr, "yield");
6657 } else if (!state.option.inESNext()) {
6658 warning("W104", state.tokens.curr, "yield");
6659 }
6660 funct["(generator)"] = "yielded";
6661 if (this.line === state.tokens.next.line) {
6662 if (state.tokens.next.id === "(regexp)")
6663 warning("W092");
6664
6665 if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
6666 nonadjacent(state.tokens.curr, state.tokens.next);
6667 this.first = expression(0);
6668
6669 if (this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
6670 warningAt("W093", this.first.line, this.first.character);
6671 }
6672 }
6673 } else if (!state.option.asi) {
6674 nolinebreak(this); // always warn (Line breaking error)
6675 }
6676 return this;
6677 }).exps = true;
6678
6679
6680 stmt("throw", function () {
6681 nolinebreak(this);
6682 nonadjacent(state.tokens.curr, state.tokens.next);
6683 this.first = expression(20);
6684 reachable("throw");
6685 return this;
6686 }).exps = true;
6687
6688 // Future Reserved Words
6689
6690 FutureReservedWord("abstract");
6691 FutureReservedWord("boolean");
6692 FutureReservedWord("byte");
6693 FutureReservedWord("char");
6694 FutureReservedWord("class", { es5: true, nud: classdef });
6695 FutureReservedWord("double");
6696 FutureReservedWord("enum", { es5: true });
6697 FutureReservedWord("export", { es5: true });
6698 FutureReservedWord("extends", { es5: true });
6699 FutureReservedWord("final");
6700 FutureReservedWord("float");
6701 FutureReservedWord("goto");
6702 FutureReservedWord("implements", { es5: true, strictOnly: true });
6703 FutureReservedWord("import", { es5: true });
6704 FutureReservedWord("int");
6705 FutureReservedWord("interface", { es5: true, strictOnly: true });
6706 FutureReservedWord("long");
6707 FutureReservedWord("native");
6708 FutureReservedWord("package", { es5: true, strictOnly: true });
6709 FutureReservedWord("private", { es5: true, strictOnly: true });
6710 FutureReservedWord("protected", { es5: true, strictOnly: true });
6711 FutureReservedWord("public", { es5: true, strictOnly: true });
6712 FutureReservedWord("short");
6713 FutureReservedWord("static", { es5: true, strictOnly: true });
6714 FutureReservedWord("super", { es5: true });
6715 FutureReservedWord("synchronized");
6716 FutureReservedWord("throws");
6717 FutureReservedWord("transient");
6718 FutureReservedWord("volatile");
6719
6720 // this function is used to determine wether a squarebracket or a curlybracket
6721 // expression is a comprehension array, destructuring assignment or a json value.
6722
6723 var lookupBlockType = function () {
6724 var pn, pn1;
6725 var i = 0;
6726 var bracketStack = 0;
6727 var ret = {};
6728 if (_.contains(["[", "{"], state.tokens.curr.value))
6729 bracketStack += 1;
6730 if (_.contains(["[", "{"], state.tokens.next.value))
6731 bracketStack += 1;
6732 if (_.contains(["]", "}"], state.tokens.next.value))
6733 bracketStack -= 1;
6734 do {
6735 pn = peek(i);
6736 pn1 = peek(i + 1);
6737 i = i + 1;
6738 if (_.contains(["[", "{"], pn.value)) {
6739 bracketStack += 1;
6740 } else if (_.contains(["]", "}"], pn.value)) {
6741 bracketStack -= 1;
6742 }
6743 if (pn.identifier && pn.value === "for" && bracketStack === 1) {
6744 ret.isCompArray = true;
6745 ret.notJson = true;
6746 break;
6747 }
6748 if (_.contains(["}", "]"], pn.value) && pn1.value === "=") {
6749 ret.isDestAssign = true;
6750 ret.notJson = true;
6751 break;
6752 }
6753 if (pn.value === ";") {
6754 ret.isBlock = true;
6755 ret.notJson = true;
6756 }
6757 } while (bracketStack > 0 && pn.id !== "(end)" && i < 15);
6758 return ret;
6759 };
6760
6761 // Check whether this function has been reached for a destructuring assign with undeclared values
6762 function destructuringAssignOrJsonValue() {
6763 // lookup for the assignment (esnext only)
6764 // if it has semicolons, it is a block, so go parse it as a block
6765 // or it's not a block, but there are assignments, check for undeclared variables
6766
6767 var block = lookupBlockType();
6768 if (block.notJson) {
6769 if (!state.option.inESNext() && block.isDestAssign) {
6770 warning("W104", state.tokens.curr, "destructuring assignment");
6771 }
6772 statements();
6773 // otherwise parse json value
6774 } else {
6775 state.option.laxbreak = true;
6776 state.jsonMode = true;
6777 jsonValue();
6778 }
6779 }
6780
6781 // array comprehension parsing function
6782 // parses and defines the three states of the list comprehension in order
6783 // to avoid defining global variables, but keeping them to the list comprehension scope
6784 // only. The order of the states are as follows:
6785 // * "use" which will be the returned iterative part of the list comprehension
6786 // * "define" which will define the variables local to the list comprehension
6787 // * "filter" which will help filter out values
6788
6789 var arrayComprehension = function () {
6790 var CompArray = function () {
6791 this.mode = "use";
6792 this.variables = [];
6793 };
6794 var _carrays = [];
6795 var _current;
6796 function declare(v) {
6797 var l = _current.variables.filter(function (elt) {
6798 // if it has, change its undef state
6799 if (elt.value === v) {
6800 elt.undef = false;
6801 return v;
6802 }
6803 }).length;
6804 return l !== 0;
6805 }
6806 function use(v) {
6807 var l = _current.variables.filter(function (elt) {
6808 // and if it has been defined
6809 if (elt.value === v && !elt.undef) {
6810 if (elt.unused === true) {
6811 elt.unused = false;
6812 }
6813 return v;
6814 }
6815 }).length;
6816 // otherwise we warn about it
6817 return (l === 0);
6818 }
6819 return {stack: function () {
6820 _current = new CompArray();
6821 _carrays.push(_current);
6822 },
6823 unstack: function () {
6824 _current.variables.filter(function (v) {
6825 if (v.unused)
6826 warning("W098", v.token, v.value);
6827 if (v.undef)
6828 isundef(v.funct, "W117", v.token, v.value);
6829 });
6830 _carrays.splice(_carrays[_carrays.length - 1], 1);
6831 _current = _carrays[_carrays.length - 1];
6832 },
6833 setState: function (s) {
6834 if (_.contains(["use", "define", "filter"], s))
6835 _current.mode = s;
6836 },
6837 check: function (v) {
6838 // When we are in "use" state of the list comp, we enqueue that var
6839 if (_current && _current.mode === "use") {
6840 _current.variables.push({funct: funct,
6841 token: state.tokens.curr,
6842 value: v,
6843 undef: true,
6844 unused: false});
6845 return true;
6846 // When we are in "define" state of the list comp,
6847 } else if (_current && _current.mode === "define") {
6848 // check if the variable has been used previously
6849 if (!declare(v)) {
6850 _current.variables.push({funct: funct,
6851 token: state.tokens.curr,
6852 value: v,
6853 undef: false,
6854 unused: true});
6855 }
6856 return true;
6857 // When we are in "filter" state,
6858 } else if (_current && _current.mode === "filter") {
6859 // we check whether current variable has been declared
6860 if (use(v)) {
6861 // if not we warn about it
6862 isundef(funct, "W117", state.tokens.curr, v);
6863 }
6864 return true;
6865 }
6866 return false;
6867 }
6868 };
6869 };
6870
6871
6872 // Parse JSON
6873
6874 function jsonValue() {
6875
6876 function jsonObject() {
6877 var o = {}, t = state.tokens.next;
6878 advance("{");
6879 if (state.tokens.next.id !== "}") {
6880 for (;;) {
6881 if (state.tokens.next.id === "(end)") {
6882 error("E026", state.tokens.next, t.line);
6883 } else if (state.tokens.next.id === "}") {
6884 warning("W094", state.tokens.curr);
6885 break;
6886 } else if (state.tokens.next.id === ",") {
6887 error("E028", state.tokens.next);
6888 } else if (state.tokens.next.id !== "(string)") {
6889 warning("W095", state.tokens.next, state.tokens.next.value);
6890 }
6891 if (o[state.tokens.next.value] === true) {
6892 warning("W075", state.tokens.next, state.tokens.next.value);
6893 } else if ((state.tokens.next.value === "__proto__" &&
6894 !state.option.proto) || (state.tokens.next.value === "__iterator__" &&
6895 !state.option.iterator)) {
6896 warning("W096", state.tokens.next, state.tokens.next.value);
6897 } else {
6898 o[state.tokens.next.value] = true;
6899 }
6900 advance();
6901 advance(":");
6902 jsonValue();
6903 if (state.tokens.next.id !== ",") {
6904 break;
6905 }
6906 advance(",");
6907 }
6908 }
6909 advance("}");
6910 }
6911
6912 function jsonArray() {
6913 var t = state.tokens.next;
6914 advance("[");
6915 if (state.tokens.next.id !== "]") {
6916 for (;;) {
6917 if (state.tokens.next.id === "(end)") {
6918 error("E027", state.tokens.next, t.line);
6919 } else if (state.tokens.next.id === "]") {
6920 warning("W094", state.tokens.curr);
6921 break;
6922 } else if (state.tokens.next.id === ",") {
6923 error("E028", state.tokens.next);
6924 }
6925 jsonValue();
6926 if (state.tokens.next.id !== ",") {
6927 break;
6928 }
6929 advance(",");
6930 }
6931 }
6932 advance("]");
6933 }
6934
6935 switch (state.tokens.next.id) {
6936 case "{":
6937 jsonObject();
6938 break;
6939 case "[":
6940 jsonArray();
6941 break;
6942 case "true":
6943 case "false":
6944 case "null":
6945 case "(number)":
6946 case "(string)":
6947 advance();
6948 break;
6949 case "-":
6950 advance("-");
6951 if (state.tokens.curr.character !== state.tokens.next.from) {
6952 warning("W011", state.tokens.curr);
6953 }
6954 adjacent(state.tokens.curr, state.tokens.next);
6955 advance("(number)");
6956 break;
6957 default:
6958 error("E003", state.tokens.next);
6959 }
6960 }
6961
6962 var blockScope = function () {
6963 var _current = {};
6964 var _variables = [_current];
6965
6966 function _checkBlockLabels() {
6967 for (var t in _current) {
6968 if (_current[t]["(type)"] === "unused") {
6969 if (state.option.unused) {
6970 var tkn = _current[t]["(token)"];
6971 var line = tkn.line;
6972 var chr = tkn.character;
6973 warningAt("W098", line, chr, t);
6974 }
6975 }
6976 }
6977 }
6978
6979 return {
6980 stack: function () {
6981 _current = {};
6982 _variables.push(_current);
6983 },
6984
6985 unstack: function () {
6986 _checkBlockLabels();
6987 _variables.splice(_variables.length - 1, 1);
6988 _current = _.last(_variables);
6989 },
6990
6991 getlabel: function (l) {
6992 for (var i = _variables.length - 1 ; i >= 0; --i) {
6993 if (_.has(_variables[i], l)) {
6994 return _variables[i];
6995 }
6996 }
6997 },
6998
6999 current: {
7000 has: function (t) {
7001 return _.has(_current, t);
7002 },
7003 add: function (t, type, tok) {
7004 _current[t] = { "(type)" : type,
7005 "(token)": tok };
7006 }
7007 }
7008 };
7009 };
7010
7011 // The actual JSHINT function itself.
7012 var itself = function (s, o, g) {
7013 var a, i, k, x;
7014 var optionKeys;
7015 var newOptionObj = {};
7016 var newIgnoredObj = {};
7017
7018 state.reset();
7019
7020 if (o && o.scope) {
7021 JSHINT.scope = o.scope;
7022 } else {
7023 JSHINT.errors = [];
7024 JSHINT.undefs = [];
7025 JSHINT.internals = [];
7026 JSHINT.blacklist = {};
7027 JSHINT.scope = "(main)";
7028 }
7029
7030 predefined = Object.create(null);
7031 combine(predefined, vars.ecmaIdentifiers);
7032 combine(predefined, vars.reservedVars);
7033
7034 combine(predefined, g || {});
7035
7036 declared = Object.create(null);
7037 exported = Object.create(null);
7038
7039 if (o) {
7040 a = o.predef;
7041 if (a) {
7042 if (!Array.isArray(a) && typeof a === "object") {
7043 a = Object.keys(a);
7044 }
7045
7046 a.forEach(function (item) {
7047 var slice, prop;
7048
7049 if (item[0] === "-") {
7050 slice = item.slice(1);
7051 JSHINT.blacklist[slice] = slice;
7052 } else {
7053 prop = Object.getOwnPropertyDescriptor(o.predef, item);
7054 predefined[item] = prop ? prop.value : false;
7055 }
7056 });
7057 }
7058
7059 optionKeys = Object.keys(o);
7060 for (x = 0; x < optionKeys.length; x++) {
7061 if (/^-W\d{3}$/g.test(optionKeys[x])) {
7062 newIgnoredObj[optionKeys[x].slice(1)] = true;
7063 } else {
7064 newOptionObj[optionKeys[x]] = o[optionKeys[x]];
7065
7066 if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
7067 newOptionObj["(explicitNewcap)"] = true;
7068
7069 if (optionKeys[x] === "indent")
7070 newOptionObj["(explicitIndent)"] = o[optionKeys[x]] === false ? false : true;
7071 }
7072 }
7073 }
7074
7075 state.option = newOptionObj;
7076 state.ignored = newIgnoredObj;
7077
7078 state.option.indent = state.option.indent || 4;
7079 state.option.maxerr = state.option.maxerr || 50;
7080
7081 indent = 1;
7082 global = Object.create(predefined);
7083 scope = global;
7084 funct = {
7085 "(global)": true,
7086 "(name)": "(global)",
7087 "(scope)": scope,
7088 "(breakage)": 0,
7089 "(loopage)": 0,
7090 "(tokens)": {},
7091 "(metrics)": createMetrics(state.tokens.next),
7092 "(blockscope)": blockScope(),
7093 "(comparray)": arrayComprehension()
7094 };
7095 functions = [funct];
7096 urls = [];
7097 stack = null;
7098 member = {};
7099 membersOnly = null;
7100 implied = {};
7101 inblock = false;
7102 lookahead = [];
7103 warnings = 0;
7104 unuseds = [];
7105
7106 if (!isString(s) && !Array.isArray(s)) {
7107 errorAt("E004", 0);
7108 return false;
7109 }
7110
7111 api = {
7112 get isJSON() {
7113 return state.jsonMode;
7114 },
7115
7116 getOption: function (name) {
7117 return state.option[name] || null;
7118 },
7119
7120 getCache: function (name) {
7121 return state.cache[name];
7122 },
7123
7124 setCache: function (name, value) {
7125 state.cache[name] = value;
7126 },
7127
7128 warn: function (code, data) {
7129 warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));
7130 },
7131
7132 on: function (names, listener) {
7133 names.split(" ").forEach(function (name) {
7134 emitter.on(name, listener);
7135 }.bind(this));
7136 }
7137 };
7138
7139 emitter.removeAllListeners();
7140 (extraModules || []).forEach(function (func) {
7141 func(api);
7142 });
7143
7144 state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
7145
7146 lex = new Lexer(s);
7147
7148 lex.on("warning", function (ev) {
7149 warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
7150 });
7151
7152 lex.on("error", function (ev) {
7153 errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
7154 });
7155
7156 lex.on("fatal", function (ev) {
7157 quit("E041", ev.line, ev.from);
7158 });
7159
7160 lex.on("Identifier", function (ev) {
7161 emitter.emit("Identifier", ev);
7162 });
7163
7164 lex.on("String", function (ev) {
7165 emitter.emit("String", ev);
7166 });
7167
7168 lex.on("Number", function (ev) {
7169 emitter.emit("Number", ev);
7170 });
7171
7172 lex.start();
7173
7174 // Check options
7175 for (var name in o) {
7176 if (_.has(o, name)) {
7177 checkOption(name, state.tokens.curr);
7178 }
7179 }
7180
7181 assume();
7182
7183 // combine the passed globals after we've assumed all our options
7184 combine(predefined, g || {});
7185
7186 //reset values
7187 comma.first = true;
7188
7189 try {
7190 advance();
7191 switch (state.tokens.next.id) {
7192 case "{":
7193 case "[":
7194 destructuringAssignOrJsonValue();
7195 break;
7196 default:
7197 directives();
7198
7199 if (state.directive["use strict"]) {
7200 if (!state.option.globalstrict && !state.option.node) {
7201 warning("W097", state.tokens.prev);
7202 }
7203 }
7204
7205 statements();
7206 }
7207 advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined);
7208 funct["(blockscope)"].unstack();
7209
7210 var markDefined = function (name, context) {
7211 do {
7212 if (typeof context[name] === "string") {
7213 // JSHINT marks unused variables as 'unused' and
7214 // unused function declaration as 'unction'. This
7215 // code changes such instances back 'var' and
7216 // 'closure' so that the code in JSHINT.data()
7217 // doesn't think they're unused.
7218
7219 if (context[name] === "unused")
7220 context[name] = "var";
7221 else if (context[name] === "unction")
7222 context[name] = "closure";
7223
7224 return true;
7225 }
7226
7227 context = context["(context)"];
7228 } while (context);
7229
7230 return false;
7231 };
7232
7233 var clearImplied = function (name, line) {
7234 if (!implied[name])
7235 return;
7236
7237 var newImplied = [];
7238 for (var i = 0; i < implied[name].length; i += 1) {
7239 if (implied[name][i] !== line)
7240 newImplied.push(implied[name][i]);
7241 }
7242
7243 if (newImplied.length === 0)
7244 delete implied[name];
7245 else
7246 implied[name] = newImplied;
7247 };
7248
7249 var warnUnused = function (name, tkn, type, unused_opt) {
7250 var line = tkn.line;
7251 var chr = tkn.character;
7252
7253 if (unused_opt === undefined) {
7254 unused_opt = state.option.unused;
7255 }
7256
7257 if (unused_opt === true) {
7258 unused_opt = "last-param";
7259 }
7260
7261 var warnable_types = {
7262 "vars": ["var"],
7263 "last-param": ["var", "param"],
7264 "strict": ["var", "param", "last-param"]
7265 };
7266
7267 if (unused_opt) {
7268 if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
7269 warningAt("W098", line, chr, name);
7270 }
7271 }
7272
7273 unuseds.push({
7274 name: name,
7275 line: line,
7276 character: chr
7277 });
7278 };
7279
7280 var checkUnused = function (func, key) {
7281 var type = func[key];
7282 var tkn = func["(tokens)"][key];
7283
7284 if (key.charAt(0) === "(")
7285 return;
7286
7287 if (type !== "unused" && type !== "unction")
7288 return;
7289
7290 // Params are checked separately from other variables.
7291 if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
7292 return;
7293
7294 // Variable is in global scope and defined as exported.
7295 if (func["(global)"] && _.has(exported, key)) {
7296 return;
7297 }
7298
7299 warnUnused(key, tkn, "var");
7300 };
7301
7302 // Check queued 'x is not defined' instances to see if they're still undefined.
7303 for (i = 0; i < JSHINT.undefs.length; i += 1) {
7304 k = JSHINT.undefs[i].slice(0);
7305
7306 if (markDefined(k[2].value, k[0])) {
7307 clearImplied(k[2].value, k[2].line);
7308 } else if (state.option.undef) {
7309 warning.apply(warning, k.slice(1));
7310 }
7311 }
7312
7313 functions.forEach(function (func) {
7314 if (func["(unusedOption)"] === false) {
7315 return;
7316 }
7317
7318 for (var key in func) {
7319 if (_.has(func, key)) {
7320 checkUnused(func, key);
7321 }
7322 }
7323
7324 if (!func["(params)"])
7325 return;
7326
7327 var params = func["(params)"].slice();
7328 var param = params.pop();
7329 var type, unused_opt;
7330
7331 while (param) {
7332 type = func[param];
7333 unused_opt = func["(unusedOption)"] || state.option.unused;
7334 unused_opt = unused_opt === true ? "last-param" : unused_opt;
7335
7336 // 'undefined' is a special case for (function (window, undefined) { ... })();
7337 // patterns.
7338
7339 if (param === "undefined")
7340 return;
7341
7342 if (type === "unused" || type === "unction") {
7343 warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]);
7344 } else if (unused_opt === "last-param") {
7345 return;
7346 }
7347
7348 param = params.pop();
7349 }
7350 });
7351
7352 for (var key in declared) {
7353 if (_.has(declared, key) && !_.has(global, key)) {
7354 warnUnused(key, declared[key], "var");
7355 }
7356 }
7357
7358 } catch (err) {
7359 if (err && err.name === "JSHintError") {
7360 var nt = state.tokens.next || {};
7361 JSHINT.errors.push({
7362 scope : "(main)",
7363 raw : err.raw,
7364 reason : err.message,
7365 line : err.line || nt.line,
7366 character : err.character || nt.from
7367 }, null);
7368 } else {
7369 throw err;
7370 }
7371 }
7372
7373 // Loop over the listed "internals", and check them as well.
7374
7375 if (JSHINT.scope === "(main)") {
7376 o = o || {};
7377
7378 for (i = 0; i < JSHINT.internals.length; i += 1) {
7379 k = JSHINT.internals[i];
7380 o.scope = k.elem;
7381 itself(k.value, o, g);
7382 }
7383 }
7384
7385 return JSHINT.errors.length === 0;
7386 };
7387
7388 // Modules.
7389 itself.addModule = function (func) {
7390 extraModules.push(func);
7391 };
7392
7393 itself.addModule(style.register);
7394
7395 // Data summary.
7396 itself.data = function () {
7397 var data = {
7398 functions: [],
7399 options: state.option
7400 };
7401 var implieds = [];
7402 var members = [];
7403 var fu, f, i, j, n, globals;
7404
7405 if (itself.errors.length) {
7406 data.errors = itself.errors;
7407 }
7408
7409 if (state.jsonMode) {
7410 data.json = true;
7411 }
7412
7413 for (n in implied) {
7414 if (_.has(implied, n)) {
7415 implieds.push({
7416 name: n,
7417 line: implied[n]
7418 });
7419 }
7420 }
7421
7422 if (implieds.length > 0) {
7423 data.implieds = implieds;
7424 }
7425
7426 if (urls.length > 0) {
7427 data.urls = urls;
7428 }
7429
7430 globals = Object.keys(scope);
7431 if (globals.length > 0) {
7432 data.globals = globals;
7433 }
7434
7435 for (i = 1; i < functions.length; i += 1) {
7436 f = functions[i];
7437 fu = {};
7438
7439 for (j = 0; j < functionicity.length; j += 1) {
7440 fu[functionicity[j]] = [];
7441 }
7442
7443 for (j = 0; j < functionicity.length; j += 1) {
7444 if (fu[functionicity[j]].length === 0) {
7445 delete fu[functionicity[j]];
7446 }
7447 }
7448
7449 fu.name = f["(name)"];
7450 fu.param = f["(params)"];
7451 fu.line = f["(line)"];
7452 fu.character = f["(character)"];
7453 fu.last = f["(last)"];
7454 fu.lastcharacter = f["(lastcharacter)"];
7455 data.functions.push(fu);
7456 }
7457
7458 if (unuseds.length > 0) {
7459 data.unused = unuseds;
7460 }
7461
7462 members = [];
7463 for (n in member) {
7464 if (typeof member[n] === "number") {
7465 data.member = member;
7466 break;
7467 }
7468 }
7469
7470 return data;
7471 };
7472
7473 itself.jshint = itself;
7474
7475 return itself;
7476 }());
7477
7478 // Make JSHINT a Node module, if possible.
7479 if (typeof exports === "object" && exports) {
7480 exports.JSHINT = JSHINT;
7481 }
7482
7483 })()
7484 },{"events":2,"../shared/vars.js":3,"./lex.js":10,"./reg.js":6,"./state.js":4,"../shared/messages.js":12,"./style.js":5,"console-browserify":7,"underscore":11}],12:[function(require,module,exports){
7485 (function(){"use strict";
7486
7487 var _ = require("underscore");
7488
7489 var errors = {
7490 // JSHint options
7491 E001: "Bad option: '{a}'.",
7492 E002: "Bad option value.",
7493
7494 // JSHint input
7495 E003: "Expected a JSON value.",
7496 E004: "Input is neither a string nor an array of strings.",
7497 E005: "Input is empty.",
7498 E006: "Unexpected early end of program.",
7499
7500 // Strict mode
7501 E007: "Missing \"use strict\" statement.",
7502 E008: "Strict violation.",
7503 E009: "Option 'validthis' can't be used in a global scope.",
7504 E010: "'with' is not allowed in strict mode.",
7505
7506 // Constants
7507 E011: "const '{a}' has already been declared.",
7508 E012: "const '{a}' is initialized to 'undefined'.",
7509 E013: "Attempting to override '{a}' which is a constant.",
7510
7511 // Regular expressions
7512 E014: "A regular expression literal can be confused with '/='.",
7513 E015: "Unclosed regular expression.",
7514 E016: "Invalid regular expression.",
7515
7516 // Tokens
7517 E017: "Unclosed comment.",
7518 E018: "Unbegun comment.",
7519 E019: "Unmatched '{a}'.",
7520 E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
7521 E021: "Expected '{a}' and instead saw '{b}'.",
7522 E022: "Line breaking error '{a}'.",
7523 E023: "Missing '{a}'.",
7524 E024: "Unexpected '{a}'.",
7525 E025: "Missing ':' on a case clause.",
7526 E026: "Missing '}' to match '{' from line {a}.",
7527 E027: "Missing ']' to match '[' form line {a}.",
7528 E028: "Illegal comma.",
7529 E029: "Unclosed string.",
7530
7531 // Everything else
7532 E030: "Expected an identifier and instead saw '{a}'.",
7533 E031: "Bad assignment.", // FIXME: Rephrase
7534 E032: "Expected a small integer or 'false' and instead saw '{a}'.",
7535 E033: "Expected an operator and instead saw '{a}'.",
7536 E034: "get/set are ES5 features.",
7537 E035: "Missing property name.",
7538 E036: "Expected to see a statement and instead saw a block.",
7539 E037: "Constant {a} was not declared correctly.",
7540 E038: "Variable {a} was not declared correctly.",
7541 E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
7542 E040: "Each value should have its own case label.",
7543 E041: "Unrecoverable syntax error.",
7544 E042: "Stopping.",
7545 E043: "Too many errors.",
7546 E044: "'{a}' is already defined and can't be redefined.",
7547 E045: "Invalid for each loop.",
7548 E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
7549 E047: "A generator function shall contain a yield statement.",
7550 E048: "Let declaration not directly within block.",
7551 E049: "A {a} cannot be named '{b}'."
7552 };
7553
7554 var warnings = {
7555 W001: "'hasOwnProperty' is a really bad name.",
7556 W002: "Value of '{a}' may be overwritten in IE.",
7557 W003: "'{a}' was used before it was defined.",
7558 W004: "'{a}' is already defined.",
7559 W005: "A dot following a number can be confused with a decimal point.",
7560 W006: "Confusing minuses.",
7561 W007: "Confusing pluses.",
7562 W008: "A leading decimal point can be confused with a dot: '{a}'.",
7563 W009: "The array literal notation [] is preferrable.",
7564 W010: "The object literal notation {} is preferrable.",
7565 W011: "Unexpected space after '{a}'.",
7566 W012: "Unexpected space before '{a}'.",
7567 W013: "Missing space after '{a}'.",
7568 W014: "Bad line breaking before '{a}'.",
7569 W015: "Expected '{a}' to have an indentation at {b} instead at {c}.",
7570 W016: "Unexpected use of '{a}'.",
7571 W017: "Bad operand.",
7572 W018: "Confusing use of '{a}'.",
7573 W019: "Use the isNaN function to compare with NaN.",
7574 W020: "Read only.",
7575 W021: "'{a}' is a function.",
7576 W022: "Do not assign to the exception parameter.",
7577 W023: "Expected an identifier in an assignment and instead saw a function invocation.",
7578 W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
7579 W025: "Missing name in function declaration.",
7580 W026: "Inner functions should be listed at the top of the outer function.",
7581 W027: "Unreachable '{a}' after '{b}'.",
7582 W028: "Label '{a}' on {b} statement.",
7583 W030: "Expected an assignment or function call and instead saw an expression.",
7584 W031: "Do not use 'new' for side effects.",
7585 W032: "Unnecessary semicolon.",
7586 W033: "Missing semicolon.",
7587 W034: "Unnecessary directive \"{a}\".",
7588 W035: "Empty block.",
7589 W036: "Unexpected /*member '{a}'.",
7590 W037: "'{a}' is a statement label.",
7591 W038: "'{a}' used out of scope.",
7592 W039: "'{a}' is not allowed.",
7593 W040: "Possible strict violation.",
7594 W041: "Use '{a}' to compare with '{b}'.",
7595 W042: "Avoid EOL escaping.",
7596 W043: "Bad escaping of EOL. Use option multistr if needed.",
7597 W044: "Bad or unnecessary escaping.",
7598 W045: "Bad number '{a}'.",
7599 W046: "Don't use extra leading zeros '{a}'.",
7600 W047: "A trailing decimal point can be confused with a dot: '{a}'.",
7601 W048: "Unexpected control character in regular expression.",
7602 W049: "Unexpected escaped character '{a}' in regular expression.",
7603 W050: "JavaScript URL.",
7604 W051: "Variables should not be deleted.",
7605 W052: "Unexpected '{a}'.",
7606 W053: "Do not use {a} as a constructor.",
7607 W054: "The Function constructor is a form of eval.",
7608 W055: "A constructor name should start with an uppercase letter.",
7609 W056: "Bad constructor.",
7610 W057: "Weird construction. Is 'new' unnecessary?",
7611 W058: "Missing '()' invoking a constructor.",
7612 W059: "Avoid arguments.{a}.",
7613 W060: "document.write can be a form of eval.",
7614 W061: "eval can be harmful.",
7615 W062: "Wrap an immediate function invocation in parens " +
7616 "to assist the reader in understanding that the expression " +
7617 "is the result of a function, and not the function itself.",
7618 W063: "Math is not a function.",
7619 W064: "Missing 'new' prefix when invoking a constructor.",
7620 W065: "Missing radix parameter.",
7621 W066: "Implied eval. Consider passing a function instead of a string.",
7622 W067: "Bad invocation.",
7623 W068: "Wrapping non-IIFE function literals in parens is unnecessary.",
7624 W069: "['{a}'] is better written in dot notation.",
7625 W070: "Extra comma. (it breaks older versions of IE)",
7626 W071: "This function has too many statements. ({a})",
7627 W072: "This function has too many parameters. ({a})",
7628 W073: "Blocks are nested too deeply. ({a})",
7629 W074: "This function's cyclomatic complexity is too high. ({a})",
7630 W075: "Duplicate key '{a}'.",
7631 W076: "Unexpected parameter '{a}' in get {b} function.",
7632 W077: "Expected a single parameter in set {a} function.",
7633 W078: "Setter is defined without getter.",
7634 W079: "Redefinition of '{a}'.",
7635 W080: "It's not necessary to initialize '{a}' to 'undefined'.",
7636 W081: "Too many var statements.",
7637 W082: "Function declarations should not be placed in blocks. " +
7638 "Use a function expression or move the statement to the top of " +
7639 "the outer function.",
7640 W083: "Don't make functions within a loop.",
7641 W084: "Expected a conditional expression and instead saw an assignment.",
7642 W085: "Don't use 'with'.",
7643 W086: "Expected a 'break' statement before '{a}'.",
7644 W087: "Forgotten 'debugger' statement?",
7645 W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
7646 W089: "The body of a for in should be wrapped in an if statement to filter " +
7647 "unwanted properties from the prototype.",
7648 W090: "'{a}' is not a statement label.",
7649 W091: "'{a}' is out of scope.",
7650 W092: "Wrap the /regexp/ literal in parens to disambiguate the slash operator.",
7651 W093: "Did you mean to return a conditional instead of an assignment?",
7652 W094: "Unexpected comma.",
7653 W095: "Expected a string and instead saw {a}.",
7654 W096: "The '{a}' key may produce unexpected results.",
7655 W097: "Use the function form of \"use strict\".",
7656 W098: "'{a}' is defined but never used.",
7657 W099: "Mixed spaces and tabs.",
7658 W100: "This character may get silently deleted by one or more browsers.",
7659 W101: "Line is too long.",
7660 W102: "Trailing whitespace.",
7661 W103: "The '{a}' property is deprecated.",
7662 W104: "'{a}' is only available in JavaScript 1.7.",
7663 W105: "Unexpected {a} in '{b}'.",
7664 W106: "Identifier '{a}' is not in camel case.",
7665 W107: "Script URL.",
7666 W108: "Strings must use doublequote.",
7667 W109: "Strings must use singlequote.",
7668 W110: "Mixed double and single quotes.",
7669 W112: "Unclosed string.",
7670 W113: "Control character in string: {a}.",
7671 W114: "Avoid {a}.",
7672 W115: "Octal literals are not allowed in strict mode.",
7673 W116: "Expected '{a}' and instead saw '{b}'.",
7674 W117: "'{a}' is not defined.",
7675 W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
7676 W119: "'{a}' is only available in ES6 (use esnext option)."
7677 };
7678
7679 var info = {
7680 I001: "Comma warnings can be turned off with 'laxcomma'.",
7681 I002: "Reserved words as properties can be used under the 'es5' option.",
7682 I003: "ES5 option is now set per default"
7683 };
7684
7685 exports.errors = {};
7686 exports.warnings = {};
7687 exports.info = {};
7688
7689 _.each(errors, function (desc, code) {
7690 exports.errors[code] = { code: code, desc: desc };
7691 });
7692
7693 _.each(warnings, function (desc, code) {
7694 exports.warnings[code] = { code: code, desc: desc };
7695 });
7696
7697 _.each(info, function (desc, code) {
7698 exports.info[code] = { code: code, desc: desc };
7699 });
7700
7701 })()
7702 },{"underscore":11}],8:[function(require,module,exports){
7703 var events = require('events');
7704
7705 exports.isArray = isArray;
7706 exports.isDate = function(obj){return Object.prototype.toString.call(obj) === '[object Date]'};
7707 exports.isRegExp = function(obj){return Object.prototype.toString.call(obj) === '[object RegExp]'};
7708
7709
7710 exports.print = function () {};
7711 exports.puts = function () {};
7712 exports.debug = function() {};
7713
7714 exports.inspect = function(obj, showHidden, depth, colors) {
7715 var seen = [];
7716
7717 var stylize = function(str, styleType) {
7718 // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
7719 var styles =
7720 { 'bold' : [1, 22],
7721 'italic' : [3, 23],
7722 'underline' : [4, 24],
7723 'inverse' : [7, 27],
7724 'white' : [37, 39],
7725 'grey' : [90, 39],
7726 'black' : [30, 39],
7727 'blue' : [34, 39],
7728 'cyan' : [36, 39],
7729 'green' : [32, 39],
7730 'magenta' : [35, 39],
7731 'red' : [31, 39],
7732 'yellow' : [33, 39] };
7733
7734 var style =
7735 { 'special': 'cyan',
7736 'number': 'blue',
7737 'boolean': 'yellow',
7738 'undefined': 'grey',
7739 'null': 'bold',
7740 'string': 'green',
7741 'date': 'magenta',
7742 // "name": intentionally not styling
7743 'regexp': 'red' }[styleType];
7744
7745 if (style) {
7746 return '\033[' + styles[style][0] + 'm' + str +
7747 '\033[' + styles[style][1] + 'm';
7748 } else {
7749 return str;
7750 }
7751 };
7752 if (! colors) {
7753 stylize = function(str, styleType) { return str; };
7754 }
7755
7756 function format(value, recurseTimes) {
7757 // Provide a hook for user-specified inspect functions.
7758 // Check that value is an object with an inspect function on it
7759 if (value && typeof value.inspect === 'function' &&
7760 // Filter out the util module, it's inspect function is special
7761 value !== exports &&
7762 // Also filter out any prototype objects using the circular check.
7763 !(value.constructor && value.constructor.prototype === value)) {
7764 return value.inspect(recurseTimes);
7765 }
7766
7767 // Primitive types cannot have properties
7768 switch (typeof value) {
7769 case 'undefined':
7770 return stylize('undefined', 'undefined');
7771
7772 case 'string':
7773 var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
7774 .replace(/'/g, "\\'")
7775 .replace(/\\"/g, '"') + '\'';
7776 return stylize(simple, 'string');
7777
7778 case 'number':
7779 return stylize('' + value, 'number');
7780
7781 case 'boolean':
7782 return stylize('' + value, 'boolean');
7783 }
7784 // For some reason typeof null is "object", so special case here.
7785 if (value === null) {
7786 return stylize('null', 'null');
7787 }
7788
7789 // Look up the keys of the object.
7790 var visible_keys = Object_keys(value);
7791 var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;
7792
7793 // Functions without properties can be shortcutted.
7794 if (typeof value === 'function' && keys.length === 0) {
7795 if (isRegExp(value)) {
7796 return stylize('' + value, 'regexp');
7797 } else {
7798 var name = value.name ? ': ' + value.name : '';
7799 return stylize('[Function' + name + ']', 'special');
7800 }
7801 }
7802
7803 // Dates without properties can be shortcutted
7804 if (isDate(value) && keys.length === 0) {
7805 return stylize(value.toUTCString(), 'date');
7806 }
7807
7808 var base, type, braces;
7809 // Determine the object type
7810 if (isArray(value)) {
7811 type = 'Array';
7812 braces = ['[', ']'];
7813 } else {
7814 type = 'Object';
7815 braces = ['{', '}'];
7816 }
7817
7818 // Make functions say that they are functions
7819 if (typeof value === 'function') {
7820 var n = value.name ? ': ' + value.name : '';
7821 base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
7822 } else {
7823 base = '';
7824 }
7825
7826 // Make dates with properties first say the date
7827 if (isDate(value)) {
7828 base = ' ' + value.toUTCString();
7829 }
7830
7831 if (keys.length === 0) {
7832 return braces[0] + base + braces[1];
7833 }
7834
7835 if (recurseTimes < 0) {
7836 if (isRegExp(value)) {
7837 return stylize('' + value, 'regexp');
7838 } else {
7839 return stylize('[Object]', 'special');
7840 }
7841 }
7842
7843 seen.push(value);
7844
7845 var output = keys.map(function(key) {
7846 var name, str;
7847 if (value.__lookupGetter__) {
7848 if (value.__lookupGetter__(key)) {
7849 if (value.__lookupSetter__(key)) {
7850 str = stylize('[Getter/Setter]', 'special');
7851 } else {
7852 str = stylize('[Getter]', 'special');
7853 }
7854 } else {
7855 if (value.__lookupSetter__(key)) {
7856 str = stylize('[Setter]', 'special');
7857 }
7858 }
7859 }
7860 if (visible_keys.indexOf(key) < 0) {
7861 name = '[' + key + ']';
7862 }
7863 if (!str) {
7864 if (seen.indexOf(value[key]) < 0) {
7865 if (recurseTimes === null) {
7866 str = format(value[key]);
7867 } else {
7868 str = format(value[key], recurseTimes - 1);
7869 }
7870 if (str.indexOf('\n') > -1) {
7871 if (isArray(value)) {
7872 str = str.split('\n').map(function(line) {
7873 return ' ' + line;
7874 }).join('\n').substr(2);
7875 } else {
7876 str = '\n' + str.split('\n').map(function(line) {
7877 return ' ' + line;
7878 }).join('\n');
7879 }
7880 }
7881 } else {
7882 str = stylize('[Circular]', 'special');
7883 }
7884 }
7885 if (typeof name === 'undefined') {
7886 if (type === 'Array' && key.match(/^\d+$/)) {
7887 return str;
7888 }
7889 name = JSON.stringify('' + key);
7890 if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
7891 name = name.substr(1, name.length - 2);
7892 name = stylize(name, 'name');
7893 } else {
7894 name = name.replace(/'/g, "\\'")
7895 .replace(/\\"/g, '"')
7896 .replace(/(^"|"$)/g, "'");
7897 name = stylize(name, 'string');
7898 }
7899 }
7900
7901 return name + ': ' + str;
7902 });
7903
7904 seen.pop();
7905
7906 var numLinesEst = 0;
7907 var length = output.reduce(function(prev, cur) {
7908 numLinesEst++;
7909 if (cur.indexOf('\n') >= 0) numLinesEst++;
7910 return prev + cur.length + 1;
7911 }, 0);
7912
7913 if (length > 50) {
7914 output = braces[0] +
7915 (base === '' ? '' : base + '\n ') +
7916 ' ' +
7917 output.join(',\n ') +
7918 ' ' +
7919 braces[1];
7920
7921 } else {
7922 output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
7923 }
7924
7925 return output;
7926 }
7927 return format(obj, (typeof depth === 'undefined' ? 2 : depth));
7928 };
7929
7930
7931 function isArray(ar) {
7932 return ar instanceof Array ||
7933 Array.isArray(ar) ||
7934 (ar && ar !== Object.prototype && isArray(ar.__proto__));
7935 }
7936
7937
7938 function isRegExp(re) {
7939 return re instanceof RegExp ||
7940 (typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]');
7941 }
7942
7943
7944 function isDate(d) {
7945 if (d instanceof Date) return true;
7946 if (typeof d !== 'object') return false;
7947 var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype);
7948 var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__);
7949 return JSON.stringify(proto) === JSON.stringify(properties);
7950 }
7951
7952 function pad(n) {
7953 return n < 10 ? '0' + n.toString(10) : n.toString(10);
7954 }
7955
7956 var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
7957 'Oct', 'Nov', 'Dec'];
7958
7959 // 26 Feb 16:19:34
7960 function timestamp() {
7961 var d = new Date();
7962 var time = [pad(d.getHours()),
7963 pad(d.getMinutes()),
7964 pad(d.getSeconds())].join(':');
7965 return [d.getDate(), months[d.getMonth()], time].join(' ');
7966 }
7967
7968 exports.log = function (msg) {};
7969
7970 exports.pump = null;
7971
7972 var Object_keys = Object.keys || function (obj) {
7973 var res = [];
7974 for (var key in obj) res.push(key);
7975 return res;
7976 };
7977
7978 var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) {
7979 var res = [];
7980 for (var key in obj) {
7981 if (Object.hasOwnProperty.call(obj, key)) res.push(key);
7982 }
7983 return res;
7984 };
7985
7986 var Object_create = Object.create || function (prototype, properties) {
7987 // from es5-shim
7988 var object;
7989 if (prototype === null) {
7990 object = { '__proto__' : null };
7991 }
7992 else {
7993 if (typeof prototype !== 'object') {
7994 throw new TypeError(
7995 'typeof prototype[' + (typeof prototype) + '] != \'object\''
7996 );
7997 }
7998 var Type = function () {};
7999 Type.prototype = prototype;
8000 object = new Type();
8001 object.__proto__ = prototype;
8002 }
8003 if (typeof properties !== 'undefined' && Object.defineProperties) {
8004 Object.defineProperties(object, properties);
8005 }
8006 return object;
8007 };
8008
8009 exports.inherits = function(ctor, superCtor) {
8010 ctor.super_ = superCtor;
8011 ctor.prototype = Object_create(superCtor.prototype, {
8012 constructor: {
8013 value: ctor,
8014 enumerable: false,
8015 writable: true,
8016 configurable: true
8017 }
8018 });
8019 };
8020
8021 var formatRegExp = /%[sdj%]/g;
8022 exports.format = function(f) {
8023 if (typeof f !== 'string') {
8024 var objects = [];
8025 for (var i = 0; i < arguments.length; i++) {
8026 objects.push(exports.inspect(arguments[i]));
8027 }
8028 return objects.join(' ');
8029 }
8030
8031 var i = 1;
8032 var args = arguments;
8033 var len = args.length;
8034 var str = String(f).replace(formatRegExp, function(x) {
8035 if (x === '%%') return '%';
8036 if (i >= len) return x;
8037 switch (x) {
8038 case '%s': return String(args[i++]);
8039 case '%d': return Number(args[i++]);
8040 case '%j': return JSON.stringify(args[i++]);
8041 default:
8042 return x;
8043 }
8044 });
8045 for(var x = args[i]; i < len; x = args[++i]){
8046 if (x === null || typeof x !== 'object') {
8047 str += ' ' + x;
8048 } else {
8049 str += ' ' + exports.inspect(x);
8050 }
8051 }
8052 return str;
8053 };
8054
8055 },{"events":2}],9:[function(require,module,exports){
8056 (function(){// UTILITY
8057 var util = require('util');
8058 var Buffer = require("buffer").Buffer;
8059 var pSlice = Array.prototype.slice;
8060
8061 function objectKeys(object) {
8062 if (Object.keys) return Object.keys(object);
8063 var result = [];
8064 for (var name in object) {
8065 if (Object.prototype.hasOwnProperty.call(object, name)) {
8066 result.push(name);
8067 }
8068 }
8069 return result;
8070 }
8071
8072 // 1. The assert module provides functions that throw
8073 // AssertionError's when particular conditions are not met. The
8074 // assert module must conform to the following interface.
8075
8076 var assert = module.exports = ok;
8077
8078 // 2. The AssertionError is defined in assert.
8079 // new assert.AssertionError({ message: message,
8080 // actual: actual,
8081 // expected: expected })
8082
8083 assert.AssertionError = function AssertionError(options) {
8084 this.name = 'AssertionError';
8085 this.message = options.message;
8086 this.actual = options.actual;
8087 this.expected = options.expected;
8088 this.operator = options.operator;
8089 var stackStartFunction = options.stackStartFunction || fail;
8090
8091 if (Error.captureStackTrace) {
8092 Error.captureStackTrace(this, stackStartFunction);
8093 }
8094 };
8095 util.inherits(assert.AssertionError, Error);
8096
8097 function replacer(key, value) {
8098 if (value === undefined) {
8099 return '' + value;
8100 }
8101 if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
8102 return value.toString();
8103 }
8104 if (typeof value === 'function' || value instanceof RegExp) {
8105 return value.toString();
8106 }
8107 return value;
8108 }
8109
8110 function truncate(s, n) {
8111 if (typeof s == 'string') {
8112 return s.length < n ? s : s.slice(0, n);
8113 } else {
8114 return s;
8115 }
8116 }
8117
8118 assert.AssertionError.prototype.toString = function() {
8119 if (this.message) {
8120 return [this.name + ':', this.message].join(' ');
8121 } else {
8122 return [
8123 this.name + ':',
8124 truncate(JSON.stringify(this.actual, replacer), 128),
8125 this.operator,
8126 truncate(JSON.stringify(this.expected, replacer), 128)
8127 ].join(' ');
8128 }
8129 };
8130
8131 // assert.AssertionError instanceof Error
8132
8133 assert.AssertionError.__proto__ = Error.prototype;
8134
8135 // At present only the three keys mentioned above are used and
8136 // understood by the spec. Implementations or sub modules can pass
8137 // other keys to the AssertionError's constructor - they will be
8138 // ignored.
8139
8140 // 3. All of the following functions must throw an AssertionError
8141 // when a corresponding condition is not met, with a message that
8142 // may be undefined if not provided. All assertion methods provide
8143 // both the actual and expected values to the assertion error for
8144 // display purposes.
8145
8146 function fail(actual, expected, message, operator, stackStartFunction) {
8147 throw new assert.AssertionError({
8148 message: message,
8149 actual: actual,
8150 expected: expected,
8151 operator: operator,
8152 stackStartFunction: stackStartFunction
8153 });
8154 }
8155
8156 // EXTENSION! allows for well behaved errors defined elsewhere.
8157 assert.fail = fail;
8158
8159 // 4. Pure assertion tests whether a value is truthy, as determined
8160 // by !!guard.
8161 // assert.ok(guard, message_opt);
8162 // This statement is equivalent to assert.equal(true, guard,
8163 // message_opt);. To test strictly for the value true, use
8164 // assert.strictEqual(true, guard, message_opt);.
8165
8166 function ok(value, message) {
8167 if (!!!value) fail(value, true, message, '==', assert.ok);
8168 }
8169 assert.ok = ok;
8170
8171 // 5. The equality assertion tests shallow, coercive equality with
8172 // ==.
8173 // assert.equal(actual, expected, message_opt);
8174
8175 assert.equal = function equal(actual, expected, message) {
8176 if (actual != expected) fail(actual, expected, message, '==', assert.equal);
8177 };
8178
8179 // 6. The non-equality assertion tests for whether two objects are not equal
8180 // with != assert.notEqual(actual, expected, message_opt);
8181
8182 assert.notEqual = function notEqual(actual, expected, message) {
8183 if (actual == expected) {
8184 fail(actual, expected, message, '!=', assert.notEqual);
8185 }
8186 };
8187
8188 // 7. The equivalence assertion tests a deep equality relation.
8189 // assert.deepEqual(actual, expected, message_opt);
8190
8191 assert.deepEqual = function deepEqual(actual, expected, message) {
8192 if (!_deepEqual(actual, expected)) {
8193 fail(actual, expected, message, 'deepEqual', assert.deepEqual);
8194 }
8195 };
8196
8197 function _deepEqual(actual, expected) {
8198 // 7.1. All identical values are equivalent, as determined by ===.
8199 if (actual === expected) {
8200 return true;
8201
8202 } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
8203 if (actual.length != expected.length) return false;
8204
8205 for (var i = 0; i < actual.length; i++) {
8206 if (actual[i] !== expected[i]) return false;
8207 }
8208
8209 return true;
8210
8211 // 7.2. If the expected value is a Date object, the actual value is
8212 // equivalent if it is also a Date object that refers to the same time.
8213 } else if (actual instanceof Date && expected instanceof Date) {
8214 return actual.getTime() === expected.getTime();
8215
8216 // 7.3. Other pairs that do not both pass typeof value == 'object',
8217 // equivalence is determined by ==.
8218 } else if (typeof actual != 'object' && typeof expected != 'object') {
8219 return actual == expected;
8220
8221 // 7.4. For all other Object pairs, including Array objects, equivalence is
8222 // determined by having the same number of owned properties (as verified
8223 // with Object.prototype.hasOwnProperty.call), the same set of keys
8224 // (although not necessarily the same order), equivalent values for every
8225 // corresponding key, and an identical 'prototype' property. Note: this
8226 // accounts for both named and indexed properties on Arrays.
8227 } else {
8228 return objEquiv(actual, expected);
8229 }
8230 }
8231
8232 function isUndefinedOrNull(value) {
8233 return value === null || value === undefined;
8234 }
8235
8236 function isArguments(object) {
8237 return Object.prototype.toString.call(object) == '[object Arguments]';
8238 }
8239
8240 function objEquiv(a, b) {
8241 if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
8242 return false;
8243 // an identical 'prototype' property.
8244 if (a.prototype !== b.prototype) return false;
8245 //~~~I've managed to break Object.keys through screwy arguments passing.
8246 // Converting to array solves the problem.
8247 if (isArguments(a)) {
8248 if (!isArguments(b)) {
8249 return false;
8250 }
8251 a = pSlice.call(a);
8252 b = pSlice.call(b);
8253 return _deepEqual(a, b);
8254 }
8255 try {
8256 var ka = objectKeys(a),
8257 kb = objectKeys(b),
8258 key, i;
8259 } catch (e) {//happens when one is a string literal and the other isn't
8260 return false;
8261 }
8262 // having the same number of owned properties (keys incorporates
8263 // hasOwnProperty)
8264 if (ka.length != kb.length)
8265 return false;
8266 //the same set of keys (although not necessarily the same order),
8267 ka.sort();
8268 kb.sort();
8269 //~~~cheap key test
8270 for (i = ka.length - 1; i >= 0; i--) {
8271 if (ka[i] != kb[i])
8272 return false;
8273 }
8274 //equivalent values for every corresponding key, and
8275 //~~~possibly expensive deep test
8276 for (i = ka.length - 1; i >= 0; i--) {
8277 key = ka[i];
8278 if (!_deepEqual(a[key], b[key])) return false;
8279 }
8280 return true;
8281 }
8282
8283 // 8. The non-equivalence assertion tests for any deep inequality.
8284 // assert.notDeepEqual(actual, expected, message_opt);
8285
8286 assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
8287 if (_deepEqual(actual, expected)) {
8288 fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
8289 }
8290 };
8291
8292 // 9. The strict equality assertion tests strict equality, as determined by ===.
8293 // assert.strictEqual(actual, expected, message_opt);
8294
8295 assert.strictEqual = function strictEqual(actual, expected, message) {
8296 if (actual !== expected) {
8297 fail(actual, expected, message, '===', assert.strictEqual);
8298 }
8299 };
8300
8301 // 10. The strict non-equality assertion tests for strict inequality, as
8302 // determined by !==. assert.notStrictEqual(actual, expected, message_opt);
8303
8304 assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
8305 if (actual === expected) {
8306 fail(actual, expected, message, '!==', assert.notStrictEqual);
8307 }
8308 };
8309
8310 function expectedException(actual, expected) {
8311 if (!actual || !expected) {
8312 return false;
8313 }
8314
8315 if (expected instanceof RegExp) {
8316 return expected.test(actual);
8317 } else if (actual instanceof expected) {
8318 return true;
8319 } else if (expected.call({}, actual) === true) {
8320 return true;
8321 }
8322
8323 return false;
8324 }
8325
8326 function _throws(shouldThrow, block, expected, message) {
8327 var actual;
8328
8329 if (typeof expected === 'string') {
8330 message = expected;
8331 expected = null;
8332 }
8333
8334 try {
8335 block();
8336 } catch (e) {
8337 actual = e;
8338 }
8339
8340 message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
8341 (message ? ' ' + message : '.');
8342
8343 if (shouldThrow && !actual) {
8344 fail('Missing expected exception' + message);
8345 }
8346
8347 if (!shouldThrow && expectedException(actual, expected)) {
8348 fail('Got unwanted exception' + message);
8349 }
8350
8351 if ((shouldThrow && actual && expected &&
8352 !expectedException(actual, expected)) || (!shouldThrow && actual)) {
8353 throw actual;
8354 }
8355 }
8356
8357 // 11. Expected to throw an error:
8358 // assert.throws(block, Error_opt, message_opt);
8359
8360 assert.throws = function(block, /*optional*/error, /*optional*/message) {
8361 _throws.apply(this, [true].concat(pSlice.call(arguments)));
8362 };
8363
8364 // EXTENSION! This is annoying to write outside this module.
8365 assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
8366 _throws.apply(this, [false].concat(pSlice.call(arguments)));
8367 };
8368
8369 assert.ifError = function(err) { if (err) {throw err;}};
8370
8371 })()
8372 },{"util":8,"buffer":13}],11:[function(require,module,exports){
8373 (function(){// Underscore.js 1.4.4
8374 // http://underscorejs.org
8375 // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
8376 // Underscore may be freely distributed under the MIT license.
8377
8378 (function() {
8379
8380 // Baseline setup
8381 // --------------
8382
8383 // Establish the root object, `window` in the browser, or `global` on the server.
8384 var root = this;
8385
8386 // Save the previous value of the `_` variable.
8387 var previousUnderscore = root._;
8388
8389 // Establish the object that gets returned to break out of a loop iteration.
8390 var breaker = {};
8391
8392 // Save bytes in the minified (but not gzipped) version:
8393 var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
8394
8395 // Create quick reference variables for speed access to core prototypes.
8396 var push = ArrayProto.push,
8397 slice = ArrayProto.slice,
8398 concat = ArrayProto.concat,
8399 toString = ObjProto.toString,
8400 hasOwnProperty = ObjProto.hasOwnProperty;
8401
8402 // All **ECMAScript 5** native function implementations that we hope to use
8403 // are declared here.
8404 var
8405 nativeForEach = ArrayProto.forEach,
8406 nativeMap = ArrayProto.map,
8407 nativeReduce = ArrayProto.reduce,
8408 nativeReduceRight = ArrayProto.reduceRight,
8409 nativeFilter = ArrayProto.filter,
8410 nativeEvery = ArrayProto.every,
8411 nativeSome = ArrayProto.some,
8412 nativeIndexOf = ArrayProto.indexOf,
8413 nativeLastIndexOf = ArrayProto.lastIndexOf,
8414 nativeIsArray = Array.isArray,
8415 nativeKeys = Object.keys,
8416 nativeBind = FuncProto.bind;
8417
8418 // Create a safe reference to the Underscore object for use below.
8419 var _ = function(obj) {
8420 if (obj instanceof _) return obj;
8421 if (!(this instanceof _)) return new _(obj);
8422 this._wrapped = obj;
8423 };
8424
8425 // Export the Underscore object for **Node.js**, with
8426 // backwards-compatibility for the old `require()` API. If we're in
8427 // the browser, add `_` as a global object via a string identifier,
8428 // for Closure Compiler "advanced" mode.
8429 if (typeof exports !== 'undefined') {
8430 if (typeof module !== 'undefined' && module.exports) {
8431 exports = module.exports = _;
8432 }
8433 exports._ = _;
8434 } else {
8435 root._ = _;
8436 }
8437
8438 // Current version.
8439 _.VERSION = '1.4.4';
8440
8441 // Collection Functions
8442 // --------------------
8443
8444 // The cornerstone, an `each` implementation, aka `forEach`.
8445 // Handles objects with the built-in `forEach`, arrays, and raw objects.
8446 // Delegates to **ECMAScript 5**'s native `forEach` if available.
8447 var each = _.each = _.forEach = function(obj, iterator, context) {
8448 if (obj == null) return;
8449 if (nativeForEach && obj.forEach === nativeForEach) {
8450 obj.forEach(iterator, context);
8451 } else if (obj.length === +obj.length) {
8452 for (var i = 0, l = obj.length; i < l; i++) {
8453 if (iterator.call(context, obj[i], i, obj) === breaker) return;
8454 }
8455 } else {
8456 for (var key in obj) {
8457 if (_.has(obj, key)) {
8458 if (iterator.call(context, obj[key], key, obj) === breaker) return;
8459 }
8460 }
8461 }
8462 };
8463
8464 // Return the results of applying the iterator to each element.
8465 // Delegates to **ECMAScript 5**'s native `map` if available.
8466 _.map = _.collect = function(obj, iterator, context) {
8467 var results = [];
8468 if (obj == null) return results;
8469 if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
8470 each(obj, function(value, index, list) {
8471 results[results.length] = iterator.call(context, value, index, list);
8472 });
8473 return results;
8474 };
8475
8476 var reduceError = 'Reduce of empty array with no initial value';
8477
8478 // **Reduce** builds up a single result from a list of values, aka `inject`,
8479 // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
8480 _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
8481 var initial = arguments.length > 2;
8482 if (obj == null) obj = [];
8483 if (nativeReduce && obj.reduce === nativeReduce) {
8484 if (context) iterator = _.bind(iterator, context);
8485 return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
8486 }
8487 each(obj, function(value, index, list) {
8488 if (!initial) {
8489 memo = value;
8490 initial = true;
8491 } else {
8492 memo = iterator.call(context, memo, value, index, list);
8493 }
8494 });
8495 if (!initial) throw new TypeError(reduceError);
8496 return memo;
8497 };
8498
8499 // The right-associative version of reduce, also known as `foldr`.
8500 // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
8501 _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
8502 var initial = arguments.length > 2;
8503 if (obj == null) obj = [];
8504 if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
8505 if (context) iterator = _.bind(iterator, context);
8506 return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
8507 }
8508 var length = obj.length;
8509 if (length !== +length) {
8510 var keys = _.keys(obj);
8511 length = keys.length;
8512 }
8513 each(obj, function(value, index, list) {
8514 index = keys ? keys[--length] : --length;
8515 if (!initial) {
8516 memo = obj[index];
8517 initial = true;
8518 } else {
8519 memo = iterator.call(context, memo, obj[index], index, list);
8520 }
8521 });
8522 if (!initial) throw new TypeError(reduceError);
8523 return memo;
8524 };
8525
8526 // Return the first value which passes a truth test. Aliased as `detect`.
8527 _.find = _.detect = function(obj, iterator, context) {
8528 var result;
8529 any(obj, function(value, index, list) {
8530 if (iterator.call(context, value, index, list)) {
8531 result = value;
8532 return true;
8533 }
8534 });
8535 return result;
8536 };
8537
8538 // Return all the elements that pass a truth test.
8539 // Delegates to **ECMAScript 5**'s native `filter` if available.
8540 // Aliased as `select`.
8541 _.filter = _.select = function(obj, iterator, context) {
8542 var results = [];
8543 if (obj == null) return results;
8544 if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
8545 each(obj, function(value, index, list) {
8546 if (iterator.call(context, value, index, list)) results[results.length] = value;
8547 });
8548 return results;
8549 };
8550
8551 // Return all the elements for which a truth test fails.
8552 _.reject = function(obj, iterator, context) {
8553 return _.filter(obj, function(value, index, list) {
8554 return !iterator.call(context, value, index, list);
8555 }, context);
8556 };
8557
8558 // Determine whether all of the elements match a truth test.
8559 // Delegates to **ECMAScript 5**'s native `every` if available.
8560 // Aliased as `all`.
8561 _.every = _.all = function(obj, iterator, context) {
8562 iterator || (iterator = _.identity);
8563 var result = true;
8564 if (obj == null) return result;
8565 if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
8566 each(obj, function(value, index, list) {
8567 if (!(result = result && iterator.call(context, value, index, list))) return breaker;
8568 });
8569 return !!result;
8570 };
8571
8572 // Determine if at least one element in the object matches a truth test.
8573 // Delegates to **ECMAScript 5**'s native `some` if available.
8574 // Aliased as `any`.
8575 var any = _.some = _.any = function(obj, iterator, context) {
8576 iterator || (iterator = _.identity);
8577 var result = false;
8578 if (obj == null) return result;
8579 if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
8580 each(obj, function(value, index, list) {
8581 if (result || (result = iterator.call(context, value, index, list))) return breaker;
8582 });
8583 return !!result;
8584 };
8585
8586 // Determine if the array or object contains a given value (using `===`).
8587 // Aliased as `include`.
8588 _.contains = _.include = function(obj, target) {
8589 if (obj == null) return false;
8590 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
8591 return any(obj, function(value) {
8592 return value === target;
8593 });
8594 };
8595
8596 // Invoke a method (with arguments) on every item in a collection.
8597 _.invoke = function(obj, method) {
8598 var args = slice.call(arguments, 2);
8599 var isFunc = _.isFunction(method);
8600 return _.map(obj, function(value) {
8601 return (isFunc ? method : value[method]).apply(value, args);
8602 });
8603 };
8604
8605 // Convenience version of a common use case of `map`: fetching a property.
8606 _.pluck = function(obj, key) {
8607 return _.map(obj, function(value){ return value[key]; });
8608 };
8609
8610 // Convenience version of a common use case of `filter`: selecting only objects
8611 // containing specific `key:value` pairs.
8612 _.where = function(obj, attrs, first) {
8613 if (_.isEmpty(attrs)) return first ? null : [];
8614 return _[first ? 'find' : 'filter'](obj, function(value) {
8615 for (var key in attrs) {
8616 if (attrs[key] !== value[key]) return false;
8617 }
8618 return true;
8619 });
8620 };
8621
8622 // Convenience version of a common use case of `find`: getting the first object
8623 // containing specific `key:value` pairs.
8624 _.findWhere = function(obj, attrs) {
8625 return _.where(obj, attrs, true);
8626 };
8627
8628 // Return the maximum element or (element-based computation).
8629 // Can't optimize arrays of integers longer than 65,535 elements.
8630 // See: https://bugs.webkit.org/show_bug.cgi?id=80797
8631 _.max = function(obj, iterator, context) {
8632 if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
8633 return Math.max.apply(Math, obj);
8634 }
8635 if (!iterator && _.isEmpty(obj)) return -Infinity;
8636 var result = {computed : -Infinity, value: -Infinity};
8637 each(obj, function(value, index, list) {
8638 var computed = iterator ? iterator.call(context, value, index, list) : value;
8639 computed >= result.computed && (result = {value : value, computed : computed});
8640 });
8641 return result.value;
8642 };
8643
8644 // Return the minimum element (or element-based computation).
8645 _.min = function(obj, iterator, context) {
8646 if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
8647 return Math.min.apply(Math, obj);
8648 }
8649 if (!iterator && _.isEmpty(obj)) return Infinity;
8650 var result = {computed : Infinity, value: Infinity};
8651 each(obj, function(value, index, list) {
8652 var computed = iterator ? iterator.call(context, value, index, list) : value;
8653 computed < result.computed && (result = {value : value, computed : computed});
8654 });
8655 return result.value;
8656 };
8657
8658 // Shuffle an array.
8659 _.shuffle = function(obj) {
8660 var rand;
8661 var index = 0;
8662 var shuffled = [];
8663 each(obj, function(value) {
8664 rand = _.random(index++);
8665 shuffled[index - 1] = shuffled[rand];
8666 shuffled[rand] = value;
8667 });
8668 return shuffled;
8669 };
8670
8671 // An internal function to generate lookup iterators.
8672 var lookupIterator = function(value) {
8673 return _.isFunction(value) ? value : function(obj){ return obj[value]; };
8674 };
8675
8676 // Sort the object's values by a criterion produced by an iterator.
8677 _.sortBy = function(obj, value, context) {
8678 var iterator = lookupIterator(value);
8679 return _.pluck(_.map(obj, function(value, index, list) {
8680 return {
8681 value : value,
8682 index : index,
8683 criteria : iterator.call(context, value, index, list)
8684 };
8685 }).sort(function(left, right) {
8686 var a = left.criteria;
8687 var b = right.criteria;
8688 if (a !== b) {
8689 if (a > b || a === void 0) return 1;
8690 if (a < b || b === void 0) return -1;
8691 }
8692 return left.index < right.index ? -1 : 1;
8693 }), 'value');
8694 };
8695
8696 // An internal function used for aggregate "group by" operations.
8697 var group = function(obj, value, context, behavior) {
8698 var result = {};
8699 var iterator = lookupIterator(value || _.identity);
8700 each(obj, function(value, index) {
8701 var key = iterator.call(context, value, index, obj);
8702 behavior(result, key, value);
8703 });
8704 return result;
8705 };
8706
8707 // Groups the object's values by a criterion. Pass either a string attribute
8708 // to group by, or a function that returns the criterion.
8709 _.groupBy = function(obj, value, context) {
8710 return group(obj, value, context, function(result, key, value) {
8711 (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
8712 });
8713 };
8714
8715 // Counts instances of an object that group by a certain criterion. Pass
8716 // either a string attribute to count by, or a function that returns the
8717 // criterion.
8718 _.countBy = function(obj, value, context) {
8719 return group(obj, value, context, function(result, key) {
8720 if (!_.has(result, key)) result[key] = 0;
8721 result[key]++;
8722 });
8723 };
8724
8725 // Use a comparator function to figure out the smallest index at which
8726 // an object should be inserted so as to maintain order. Uses binary search.
8727 _.sortedIndex = function(array, obj, iterator, context) {
8728 iterator = iterator == null ? _.identity : lookupIterator(iterator);
8729 var value = iterator.call(context, obj);
8730 var low = 0, high = array.length;
8731 while (low < high) {
8732 var mid = (low + high) >>> 1;
8733 iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
8734 }
8735 return low;
8736 };
8737
8738 // Safely convert anything iterable into a real, live array.
8739 _.toArray = function(obj) {
8740 if (!obj) return [];
8741 if (_.isArray(obj)) return slice.call(obj);
8742 if (obj.length === +obj.length) return _.map(obj, _.identity);
8743 return _.values(obj);
8744 };
8745
8746 // Return the number of elements in an object.
8747 _.size = function(obj) {
8748 if (obj == null) return 0;
8749 return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
8750 };
8751
8752 // Array Functions
8753 // ---------------
8754
8755 // Get the first element of an array. Passing **n** will return the first N
8756 // values in the array. Aliased as `head` and `take`. The **guard** check
8757 // allows it to work with `_.map`.
8758 _.first = _.head = _.take = function(array, n, guard) {
8759 if (array == null) return void 0;
8760 return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
8761 };
8762
8763 // Returns everything but the last entry of the array. Especially useful on
8764 // the arguments object. Passing **n** will return all the values in
8765 // the array, excluding the last N. The **guard** check allows it to work with
8766 // `_.map`.
8767 _.initial = function(array, n, guard) {
8768 return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
8769 };
8770
8771 // Get the last element of an array. Passing **n** will return the last N
8772 // values in the array. The **guard** check allows it to work with `_.map`.
8773 _.last = function(array, n, guard) {
8774 if (array == null) return void 0;
8775 if ((n != null) && !guard) {
8776 return slice.call(array, Math.max(array.length - n, 0));
8777 } else {
8778 return array[array.length - 1];
8779 }
8780 };
8781
8782 // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
8783 // Especially useful on the arguments object. Passing an **n** will return
8784 // the rest N values in the array. The **guard**
8785 // check allows it to work with `_.map`.
8786 _.rest = _.tail = _.drop = function(array, n, guard) {
8787 return slice.call(array, (n == null) || guard ? 1 : n);
8788 };
8789
8790 // Trim out all falsy values from an array.
8791 _.compact = function(array) {
8792 return _.filter(array, _.identity);
8793 };
8794
8795 // Internal implementation of a recursive `flatten` function.
8796 var flatten = function(input, shallow, output) {
8797 each(input, function(value) {
8798 if (_.isArray(value)) {
8799 shallow ? push.apply(output, value) : flatten(value, shallow, output);
8800 } else {
8801 output.push(value);
8802 }
8803 });
8804 return output;
8805 };
8806
8807 // Return a completely flattened version of an array.
8808 _.flatten = function(array, shallow) {
8809 return flatten(array, shallow, []);
8810 };
8811
8812 // Return a version of the array that does not contain the specified value(s).
8813 _.without = function(array) {
8814 return _.difference(array, slice.call(arguments, 1));
8815 };
8816
8817 // Produce a duplicate-free version of the array. If the array has already
8818 // been sorted, you have the option of using a faster algorithm.
8819 // Aliased as `unique`.
8820 _.uniq = _.unique = function(array, isSorted, iterator, context) {
8821 if (_.isFunction(isSorted)) {
8822 context = iterator;
8823 iterator = isSorted;
8824 isSorted = false;
8825 }
8826 var initial = iterator ? _.map(array, iterator, context) : array;
8827 var results = [];
8828 var seen = [];
8829 each(initial, function(value, index) {
8830 if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
8831 seen.push(value);
8832 results.push(array[index]);
8833 }
8834 });
8835 return results;
8836 };
8837
8838 // Produce an array that contains the union: each distinct element from all of
8839 // the passed-in arrays.
8840 _.union = function() {
8841 return _.uniq(concat.apply(ArrayProto, arguments));
8842 };
8843
8844 // Produce an array that contains every item shared between all the
8845 // passed-in arrays.
8846 _.intersection = function(array) {
8847 var rest = slice.call(arguments, 1);
8848 return _.filter(_.uniq(array), function(item) {
8849 return _.every(rest, function(other) {
8850 return _.indexOf(other, item) >= 0;
8851 });
8852 });
8853 };
8854
8855 // Take the difference between one array and a number of other arrays.
8856 // Only the elements present in just the first array will remain.
8857 _.difference = function(array) {
8858 var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
8859 return _.filter(array, function(value){ return !_.contains(rest, value); });
8860 };
8861
8862 // Zip together multiple lists into a single array -- elements that share
8863 // an index go together.
8864 _.zip = function() {
8865 var args = slice.call(arguments);
8866 var length = _.max(_.pluck(args, 'length'));
8867 var results = new Array(length);
8868 for (var i = 0; i < length; i++) {
8869 results[i] = _.pluck(args, "" + i);
8870 }
8871 return results;
8872 };
8873
8874 // Converts lists into objects. Pass either a single array of `[key, value]`
8875 // pairs, or two parallel arrays of the same length -- one of keys, and one of
8876 // the corresponding values.
8877 _.object = function(list, values) {
8878 if (list == null) return {};
8879 var result = {};
8880 for (var i = 0, l = list.length; i < l; i++) {
8881 if (values) {
8882 result[list[i]] = values[i];
8883 } else {
8884 result[list[i][0]] = list[i][1];
8885 }
8886 }
8887 return result;
8888 };
8889
8890 // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
8891 // we need this function. Return the position of the first occurrence of an
8892 // item in an array, or -1 if the item is not included in the array.
8893 // Delegates to **ECMAScript 5**'s native `indexOf` if available.
8894 // If the array is large and already in sort order, pass `true`
8895 // for **isSorted** to use binary search.
8896 _.indexOf = function(array, item, isSorted) {
8897 if (array == null) return -1;
8898 var i = 0, l = array.length;
8899 if (isSorted) {
8900 if (typeof isSorted == 'number') {
8901 i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
8902 } else {
8903 i = _.sortedIndex(array, item);
8904 return array[i] === item ? i : -1;
8905 }
8906 }
8907 if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
8908 for (; i < l; i++) if (array[i] === item) return i;
8909 return -1;
8910 };
8911
8912 // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
8913 _.lastIndexOf = function(array, item, from) {
8914 if (array == null) return -1;
8915 var hasIndex = from != null;
8916 if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
8917 return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
8918 }
8919 var i = (hasIndex ? from : array.length);
8920 while (i--) if (array[i] === item) return i;
8921 return -1;
8922 };
8923
8924 // Generate an integer Array containing an arithmetic progression. A port of
8925 // the native Python `range()` function. See
8926 // [the Python documentation](http://docs.python.org/library/functions.html#range).
8927 _.range = function(start, stop, step) {
8928 if (arguments.length <= 1) {
8929 stop = start || 0;
8930 start = 0;
8931 }
8932 step = arguments[2] || 1;
8933
8934 var len = Math.max(Math.ceil((stop - start) / step), 0);
8935 var idx = 0;
8936 var range = new Array(len);
8937
8938 while(idx < len) {
8939 range[idx++] = start;
8940 start += step;
8941 }
8942
8943 return range;
8944 };
8945
8946 // Function (ahem) Functions
8947 // ------------------
8948
8949 // Create a function bound to a given object (assigning `this`, and arguments,
8950 // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
8951 // available.
8952 _.bind = function(func, context) {
8953 if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
8954 var args = slice.call(arguments, 2);
8955 return function() {
8956 return func.apply(context, args.concat(slice.call(arguments)));
8957 };
8958 };
8959
8960 // Partially apply a function by creating a version that has had some of its
8961 // arguments pre-filled, without changing its dynamic `this` context.
8962 _.partial = function(func) {
8963 var args = slice.call(arguments, 1);
8964 return function() {
8965 return func.apply(this, args.concat(slice.call(arguments)));
8966 };
8967 };
8968
8969 // Bind all of an object's methods to that object. Useful for ensuring that
8970 // all callbacks defined on an object belong to it.
8971 _.bindAll = function(obj) {
8972 var funcs = slice.call(arguments, 1);
8973 if (funcs.length === 0) funcs = _.functions(obj);
8974 each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
8975 return obj;
8976 };
8977
8978 // Memoize an expensive function by storing its results.
8979 _.memoize = function(func, hasher) {
8980 var memo = {};
8981 hasher || (hasher = _.identity);
8982 return function() {
8983 var key = hasher.apply(this, arguments);
8984 return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
8985 };
8986 };
8987
8988 // Delays a function for the given number of milliseconds, and then calls
8989 // it with the arguments supplied.
8990 _.delay = function(func, wait) {
8991 var args = slice.call(arguments, 2);
8992 return setTimeout(function(){ return func.apply(null, args); }, wait);
8993 };
8994
8995 // Defers a function, scheduling it to run after the current call stack has
8996 // cleared.
8997 _.defer = function(func) {
8998 return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
8999 };
9000
9001 // Returns a function, that, when invoked, will only be triggered at most once
9002 // during a given window of time.
9003 _.throttle = function(func, wait) {
9004 var context, args, timeout, result;
9005 var previous = 0;
9006 var later = function() {
9007 previous = new Date;
9008 timeout = null;
9009 result = func.apply(context, args);
9010 };
9011 return function() {
9012 var now = new Date;
9013 var remaining = wait - (now - previous);
9014 context = this;
9015 args = arguments;
9016 if (remaining <= 0) {
9017 clearTimeout(timeout);
9018 timeout = null;
9019 previous = now;
9020 result = func.apply(context, args);
9021 } else if (!timeout) {
9022 timeout = setTimeout(later, remaining);
9023 }
9024 return result;
9025 };
9026 };
9027
9028 // Returns a function, that, as long as it continues to be invoked, will not
9029 // be triggered. The function will be called after it stops being called for
9030 // N milliseconds. If `immediate` is passed, trigger the function on the
9031 // leading edge, instead of the trailing.
9032 _.debounce = function(func, wait, immediate) {
9033 var timeout, result;
9034 return function() {
9035 var context = this, args = arguments;
9036 var later = function() {
9037 timeout = null;
9038 if (!immediate) result = func.apply(context, args);
9039 };
9040 var callNow = immediate && !timeout;
9041 clearTimeout(timeout);
9042 timeout = setTimeout(later, wait);
9043 if (callNow) result = func.apply(context, args);
9044 return result;
9045 };
9046 };
9047
9048 // Returns a function that will be executed at most one time, no matter how
9049 // often you call it. Useful for lazy initialization.
9050 _.once = function(func) {
9051 var ran = false, memo;
9052 return function() {
9053 if (ran) return memo;
9054 ran = true;
9055 memo = func.apply(this, arguments);
9056 func = null;
9057 return memo;
9058 };
9059 };
9060
9061 // Returns the first function passed as an argument to the second,
9062 // allowing you to adjust arguments, run code before and after, and
9063 // conditionally execute the original function.
9064 _.wrap = function(func, wrapper) {
9065 return function() {
9066 var args = [func];
9067 push.apply(args, arguments);
9068 return wrapper.apply(this, args);
9069 };
9070 };
9071
9072 // Returns a function that is the composition of a list of functions, each
9073 // consuming the return value of the function that follows.
9074 _.compose = function() {
9075 var funcs = arguments;
9076 return function() {
9077 var args = arguments;
9078 for (var i = funcs.length - 1; i >= 0; i--) {
9079 args = [funcs[i].apply(this, args)];
9080 }
9081 return args[0];
9082 };
9083 };
9084
9085 // Returns a function that will only be executed after being called N times.
9086 _.after = function(times, func) {
9087 if (times <= 0) return func();
9088 return function() {
9089 if (--times < 1) {
9090 return func.apply(this, arguments);
9091 }
9092 };
9093 };
9094
9095 // Object Functions
9096 // ----------------
9097
9098 // Retrieve the names of an object's properties.
9099 // Delegates to **ECMAScript 5**'s native `Object.keys`
9100 _.keys = nativeKeys || function(obj) {
9101 if (obj !== Object(obj)) throw new TypeError('Invalid object');
9102 var keys = [];
9103 for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
9104 return keys;
9105 };
9106
9107 // Retrieve the values of an object's properties.
9108 _.values = function(obj) {
9109 var values = [];
9110 for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
9111 return values;
9112 };
9113
9114 // Convert an object into a list of `[key, value]` pairs.
9115 _.pairs = function(obj) {
9116 var pairs = [];
9117 for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
9118 return pairs;
9119 };
9120
9121 // Invert the keys and values of an object. The values must be serializable.
9122 _.invert = function(obj) {
9123 var result = {};
9124 for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
9125 return result;
9126 };
9127
9128 // Return a sorted list of the function names available on the object.
9129 // Aliased as `methods`
9130 _.functions = _.methods = function(obj) {
9131 var names = [];
9132 for (var key in obj) {
9133 if (_.isFunction(obj[key])) names.push(key);
9134 }
9135 return names.sort();
9136 };
9137
9138 // Extend a given object with all the properties in passed-in object(s).
9139 _.extend = function(obj) {
9140 each(slice.call(arguments, 1), function(source) {
9141 if (source) {
9142 for (var prop in source) {
9143 obj[prop] = source[prop];
9144 }
9145 }
9146 });
9147 return obj;
9148 };
9149
9150 // Return a copy of the object only containing the whitelisted properties.
9151 _.pick = function(obj) {
9152 var copy = {};
9153 var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
9154 each(keys, function(key) {
9155 if (key in obj) copy[key] = obj[key];
9156 });
9157 return copy;
9158 };
9159
9160 // Return a copy of the object without the blacklisted properties.
9161 _.omit = function(obj) {
9162 var copy = {};
9163 var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
9164 for (var key in obj) {
9165 if (!_.contains(keys, key)) copy[key] = obj[key];
9166 }
9167 return copy;
9168 };
9169
9170 // Fill in a given object with default properties.
9171 _.defaults = function(obj) {
9172 each(slice.call(arguments, 1), function(source) {
9173 if (source) {
9174 for (var prop in source) {
9175 if (obj[prop] == null) obj[prop] = source[prop];
9176 }
9177 }
9178 });
9179 return obj;
9180 };
9181
9182 // Create a (shallow-cloned) duplicate of an object.
9183 _.clone = function(obj) {
9184 if (!_.isObject(obj)) return obj;
9185 return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
9186 };
9187
9188 // Invokes interceptor with the obj, and then returns obj.
9189 // The primary purpose of this method is to "tap into" a method chain, in
9190 // order to perform operations on intermediate results within the chain.
9191 _.tap = function(obj, interceptor) {
9192 interceptor(obj);
9193 return obj;
9194 };
9195
9196 // Internal recursive comparison function for `isEqual`.
9197 var eq = function(a, b, aStack, bStack) {
9198 // Identical objects are equal. `0 === -0`, but they aren't identical.
9199 // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
9200 if (a === b) return a !== 0 || 1 / a == 1 / b;
9201 // A strict comparison is necessary because `null == undefined`.
9202 if (a == null || b == null) return a === b;
9203 // Unwrap any wrapped objects.
9204 if (a instanceof _) a = a._wrapped;
9205 if (b instanceof _) b = b._wrapped;
9206 // Compare `[[Class]]` names.
9207 var className = toString.call(a);
9208 if (className != toString.call(b)) return false;
9209 switch (className) {
9210 // Strings, numbers, dates, and booleans are compared by value.
9211 case '[object String]':
9212 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
9213 // equivalent to `new String("5")`.
9214 return a == String(b);
9215 case '[object Number]':
9216 // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
9217 // other numeric values.
9218 return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
9219 case '[object Date]':
9220 case '[object Boolean]':
9221 // Coerce dates and booleans to numeric primitive values. Dates are compared by their
9222 // millisecond representations. Note that invalid dates with millisecond representations
9223 // of `NaN` are not equivalent.
9224 return +a == +b;
9225 // RegExps are compared by their source patterns and flags.
9226 case '[object RegExp]':
9227 return a.source == b.source &&
9228 a.global == b.global &&
9229 a.multiline == b.multiline &&
9230 a.ignoreCase == b.ignoreCase;
9231 }
9232 if (typeof a != 'object' || typeof b != 'object') return false;
9233 // Assume equality for cyclic structures. The algorithm for detecting cyclic
9234 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
9235 var length = aStack.length;
9236 while (length--) {
9237 // Linear search. Performance is inversely proportional to the number of
9238 // unique nested structures.
9239 if (aStack[length] == a) return bStack[length] == b;
9240 }
9241 // Add the first object to the stack of traversed objects.
9242 aStack.push(a);
9243 bStack.push(b);
9244 var size = 0, result = true;
9245 // Recursively compare objects and arrays.
9246 if (className == '[object Array]') {
9247 // Compare array lengths to determine if a deep comparison is necessary.
9248 size = a.length;
9249 result = size == b.length;
9250 if (result) {
9251 // Deep compare the contents, ignoring non-numeric properties.
9252 while (size--) {
9253 if (!(result = eq(a[size], b[size], aStack, bStack))) break;
9254 }
9255 }
9256 } else {
9257 // Objects with different constructors are not equivalent, but `Object`s
9258 // from different frames are.
9259 var aCtor = a.constructor, bCtor = b.constructor;
9260 if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
9261 _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
9262 return false;
9263 }
9264 // Deep compare objects.
9265 for (var key in a) {
9266 if (_.has(a, key)) {
9267 // Count the expected number of properties.
9268 size++;
9269 // Deep compare each member.
9270 if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
9271 }
9272 }
9273 // Ensure that both objects contain the same number of properties.
9274 if (result) {
9275 for (key in b) {
9276 if (_.has(b, key) && !(size--)) break;
9277 }
9278 result = !size;
9279 }
9280 }
9281 // Remove the first object from the stack of traversed objects.
9282 aStack.pop();
9283 bStack.pop();
9284 return result;
9285 };
9286
9287 // Perform a deep comparison to check if two objects are equal.
9288 _.isEqual = function(a, b) {
9289 return eq(a, b, [], []);
9290 };
9291
9292 // Is a given array, string, or object empty?
9293 // An "empty" object has no enumerable own-properties.
9294 _.isEmpty = function(obj) {
9295 if (obj == null) return true;
9296 if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
9297 for (var key in obj) if (_.has(obj, key)) return false;
9298 return true;
9299 };
9300
9301 // Is a given value a DOM element?
9302 _.isElement = function(obj) {
9303 return !!(obj && obj.nodeType === 1);
9304 };
9305
9306 // Is a given value an array?
9307 // Delegates to ECMA5's native Array.isArray
9308 _.isArray = nativeIsArray || function(obj) {
9309 return toString.call(obj) == '[object Array]';
9310 };
9311
9312 // Is a given variable an object?
9313 _.isObject = function(obj) {
9314 return obj === Object(obj);
9315 };
9316
9317 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
9318 each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
9319 _['is' + name] = function(obj) {
9320 return toString.call(obj) == '[object ' + name + ']';
9321 };
9322 });
9323
9324 // Define a fallback version of the method in browsers (ahem, IE), where
9325 // there isn't any inspectable "Arguments" type.
9326 if (!_.isArguments(arguments)) {
9327 _.isArguments = function(obj) {
9328 return !!(obj && _.has(obj, 'callee'));
9329 };
9330 }
9331
9332 // Optimize `isFunction` if appropriate.
9333 if (typeof (/./) !== 'function') {
9334 _.isFunction = function(obj) {
9335 return typeof obj === 'function';
9336 };
9337 }
9338
9339 // Is a given object a finite number?
9340 _.isFinite = function(obj) {
9341 return isFinite(obj) && !isNaN(parseFloat(obj));
9342 };
9343
9344 // Is the given value `NaN`? (NaN is the only number which does not equal itself).
9345 _.isNaN = function(obj) {
9346 return _.isNumber(obj) && obj != +obj;
9347 };
9348
9349 // Is a given value a boolean?
9350 _.isBoolean = function(obj) {
9351 return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
9352 };
9353
9354 // Is a given value equal to null?
9355 _.isNull = function(obj) {
9356 return obj === null;
9357 };
9358
9359 // Is a given variable undefined?
9360 _.isUndefined = function(obj) {
9361 return obj === void 0;
9362 };
9363
9364 // Shortcut function for checking if an object has a given property directly
9365 // on itself (in other words, not on a prototype).
9366 _.has = function(obj, key) {
9367 return hasOwnProperty.call(obj, key);
9368 };
9369
9370 // Utility Functions
9371 // -----------------
9372
9373 // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
9374 // previous owner. Returns a reference to the Underscore object.
9375 _.noConflict = function() {
9376 root._ = previousUnderscore;
9377 return this;
9378 };
9379
9380 // Keep the identity function around for default iterators.
9381 _.identity = function(value) {
9382 return value;
9383 };
9384
9385 // Run a function **n** times.
9386 _.times = function(n, iterator, context) {
9387 var accum = Array(n);
9388 for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
9389 return accum;
9390 };
9391
9392 // Return a random integer between min and max (inclusive).
9393 _.random = function(min, max) {
9394 if (max == null) {
9395 max = min;
9396 min = 0;
9397 }
9398 return min + Math.floor(Math.random() * (max - min + 1));
9399 };
9400
9401 // List of HTML entities for escaping.
9402 var entityMap = {
9403 escape: {
9404 '&': '&amp;',
9405 '<': '&lt;',
9406 '>': '&gt;',
9407 '"': '&quot;',
9408 "'": '&#x27;',
9409 '/': '&#x2F;'
9410 }
9411 };
9412 entityMap.unescape = _.invert(entityMap.escape);
9413
9414 // Regexes containing the keys and values listed immediately above.
9415 var entityRegexes = {
9416 escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
9417 unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
9418 };
9419
9420 // Functions for escaping and unescaping strings to/from HTML interpolation.
9421 _.each(['escape', 'unescape'], function(method) {
9422 _[method] = function(string) {
9423 if (string == null) return '';
9424 return ('' + string).replace(entityRegexes[method], function(match) {
9425 return entityMap[method][match];
9426 });
9427 };
9428 });
9429
9430 // If the value of the named property is a function then invoke it;
9431 // otherwise, return it.
9432 _.result = function(object, property) {
9433 if (object == null) return null;
9434 var value = object[property];
9435 return _.isFunction(value) ? value.call(object) : value;
9436 };
9437
9438 // Add your own custom functions to the Underscore object.
9439 _.mixin = function(obj) {
9440 each(_.functions(obj), function(name){
9441 var func = _[name] = obj[name];
9442 _.prototype[name] = function() {
9443 var args = [this._wrapped];
9444 push.apply(args, arguments);
9445 return result.call(this, func.apply(_, args));
9446 };
9447 });
9448 };
9449
9450 // Generate a unique integer id (unique within the entire client session).
9451 // Useful for temporary DOM ids.
9452 var idCounter = 0;
9453 _.uniqueId = function(prefix) {
9454 var id = ++idCounter + '';
9455 return prefix ? prefix + id : id;
9456 };
9457
9458 // By default, Underscore uses ERB-style template delimiters, change the
9459 // following template settings to use alternative delimiters.
9460 _.templateSettings = {
9461 evaluate : /<%([\s\S]+?)%>/g,
9462 interpolate : /<%=([\s\S]+?)%>/g,
9463 escape : /<%-([\s\S]+?)%>/g
9464 };
9465
9466 // When customizing `templateSettings`, if you don't want to define an
9467 // interpolation, evaluation or escaping regex, we need one that is
9468 // guaranteed not to match.
9469 var noMatch = /(.)^/;
9470
9471 // Certain characters need to be escaped so that they can be put into a
9472 // string literal.
9473 var escapes = {
9474 "'": "'",
9475 '\\': '\\',
9476 '\r': 'r',
9477 '\n': 'n',
9478 '\t': 't',
9479 '\u2028': 'u2028',
9480 '\u2029': 'u2029'
9481 };
9482
9483 var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
9484
9485 // JavaScript micro-templating, similar to John Resig's implementation.
9486 // Underscore templating handles arbitrary delimiters, preserves whitespace,
9487 // and correctly escapes quotes within interpolated code.
9488 _.template = function(text, data, settings) {
9489 var render;
9490 settings = _.defaults({}, settings, _.templateSettings);
9491
9492 // Combine delimiters into one regular expression via alternation.
9493 var matcher = new RegExp([
9494 (settings.escape || noMatch).source,
9495 (settings.interpolate || noMatch).source,
9496 (settings.evaluate || noMatch).source
9497 ].join('|') + '|$', 'g');
9498
9499 // Compile the template source, escaping string literals appropriately.
9500 var index = 0;
9501 var source = "__p+='";
9502 text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
9503 source += text.slice(index, offset)
9504 .replace(escaper, function(match) { return '\\' + escapes[match]; });
9505
9506 if (escape) {
9507 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
9508 }
9509 if (interpolate) {
9510 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
9511 }
9512 if (evaluate) {
9513 source += "';\n" + evaluate + "\n__p+='";
9514 }
9515 index = offset + match.length;
9516 return match;
9517 });
9518 source += "';\n";
9519
9520 // If a variable is not specified, place data values in local scope.
9521 if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
9522
9523 source = "var __t,__p='',__j=Array.prototype.join," +
9524 "print=function(){__p+=__j.call(arguments,'');};\n" +
9525 source + "return __p;\n";
9526
9527 try {
9528 render = new Function(settings.variable || 'obj', '_', source);
9529 } catch (e) {
9530 e.source = source;
9531 throw e;
9532 }
9533
9534 if (data) return render(data, _);
9535 var template = function(data) {
9536 return render.call(this, data, _);
9537 };
9538
9539 // Provide the compiled function source as a convenience for precompilation.
9540 template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
9541
9542 return template;
9543 };
9544
9545 // Add a "chain" function, which will delegate to the wrapper.
9546 _.chain = function(obj) {
9547 return _(obj).chain();
9548 };
9549
9550 // OOP
9551 // ---------------
9552 // If Underscore is called as a function, it returns a wrapped object that
9553 // can be used OO-style. This wrapper holds altered versions of all the
9554 // underscore functions. Wrapped objects may be chained.
9555
9556 // Helper function to continue chaining intermediate results.
9557 var result = function(obj) {
9558 return this._chain ? _(obj).chain() : obj;
9559 };
9560
9561 // Add all of the Underscore functions to the wrapper object.
9562 _.mixin(_);
9563
9564 // Add all mutator Array functions to the wrapper.
9565 each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
9566 var method = ArrayProto[name];
9567 _.prototype[name] = function() {
9568 var obj = this._wrapped;
9569 method.apply(obj, arguments);
9570 if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
9571 return result.call(this, obj);
9572 };
9573 });
9574
9575 // Add all accessor Array functions to the wrapper.
9576 each(['concat', 'join', 'slice'], function(name) {
9577 var method = ArrayProto[name];
9578 _.prototype[name] = function() {
9579 return result.call(this, method.apply(this._wrapped, arguments));
9580 };
9581 });
9582
9583 _.extend(_.prototype, {
9584
9585 // Start chaining a wrapped Underscore object.
9586 chain: function() {
9587 this._chain = true;
9588 return this;
9589 },
9590
9591 // Extracts the result from a wrapped and chained object.
9592 value: function() {
9593 return this._wrapped;
9594 }
9595
9596 });
9597
9598 }).call(this);
9599
9600 })()
9601 },{}],14:[function(require,module,exports){
9602 exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
9603 var e, m,
9604 eLen = nBytes * 8 - mLen - 1,
9605 eMax = (1 << eLen) - 1,
9606 eBias = eMax >> 1,
9607 nBits = -7,
9608 i = isBE ? 0 : (nBytes - 1),
9609 d = isBE ? 1 : -1,
9610 s = buffer[offset + i];
9611
9612 i += d;
9613
9614 e = s & ((1 << (-nBits)) - 1);
9615 s >>= (-nBits);
9616 nBits += eLen;
9617 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
9618
9619 m = e & ((1 << (-nBits)) - 1);
9620 e >>= (-nBits);
9621 nBits += mLen;
9622 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
9623
9624 if (e === 0) {
9625 e = 1 - eBias;
9626 } else if (e === eMax) {
9627 return m ? NaN : ((s ? -1 : 1) * Infinity);
9628 } else {
9629 m = m + Math.pow(2, mLen);
9630 e = e - eBias;
9631 }
9632 return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
9633 };
9634
9635 exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
9636 var e, m, c,
9637 eLen = nBytes * 8 - mLen - 1,
9638 eMax = (1 << eLen) - 1,
9639 eBias = eMax >> 1,
9640 rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
9641 i = isBE ? (nBytes - 1) : 0,
9642 d = isBE ? -1 : 1,
9643 s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
9644
9645 value = Math.abs(value);
9646
9647 if (isNaN(value) || value === Infinity) {
9648 m = isNaN(value) ? 1 : 0;
9649 e = eMax;
9650 } else {
9651 e = Math.floor(Math.log(value) / Math.LN2);
9652 if (value * (c = Math.pow(2, -e)) < 1) {
9653 e--;
9654 c *= 2;
9655 }
9656 if (e + eBias >= 1) {
9657 value += rt / c;
9658 } else {
9659 value += rt * Math.pow(2, 1 - eBias);
9660 }
9661 if (value * c >= 2) {
9662 e++;
9663 c /= 2;
9664 }
9665
9666 if (e + eBias >= eMax) {
9667 m = 0;
9668 e = eMax;
9669 } else if (e + eBias >= 1) {
9670 m = (value * c - 1) * Math.pow(2, mLen);
9671 e = e + eBias;
9672 } else {
9673 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
9674 e = 0;
9675 }
9676 }
9677
9678 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
9679
9680 e = (e << mLen) | m;
9681 eLen += mLen;
9682 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
9683
9684 buffer[offset + i - d] |= s * 128;
9685 };
9686
9687 },{}],13:[function(require,module,exports){
9688 (function(){function SlowBuffer (size) {
9689 this.length = size;
9690 };
9691
9692 var assert = require('assert');
9693
9694 exports.INSPECT_MAX_BYTES = 50;
9695
9696
9697 function toHex(n) {
9698 if (n < 16) return '0' + n.toString(16);
9699 return n.toString(16);
9700 }
9701
9702 function utf8ToBytes(str) {
9703 var byteArray = [];
9704 for (var i = 0; i < str.length; i++)
9705 if (str.charCodeAt(i) <= 0x7F)
9706 byteArray.push(str.charCodeAt(i));
9707 else {
9708 var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
9709 for (var j = 0; j < h.length; j++)
9710 byteArray.push(parseInt(h[j], 16));
9711 }
9712
9713 return byteArray;
9714 }
9715
9716 function asciiToBytes(str) {
9717 var byteArray = []
9718 for (var i = 0; i < str.length; i++ )
9719 // Node's code seems to be doing this and not & 0x7F..
9720 byteArray.push( str.charCodeAt(i) & 0xFF );
9721
9722 return byteArray;
9723 }
9724
9725 function base64ToBytes(str) {
9726 return require("base64-js").toByteArray(str);
9727 }
9728
9729 SlowBuffer.byteLength = function (str, encoding) {
9730 switch (encoding || "utf8") {
9731 case 'hex':
9732 return str.length / 2;
9733
9734 case 'utf8':
9735 case 'utf-8':
9736 return utf8ToBytes(str).length;
9737
9738 case 'ascii':
9739 case 'binary':
9740 return str.length;
9741
9742 case 'base64':
9743 return base64ToBytes(str).length;
9744
9745 default:
9746 throw new Error('Unknown encoding');
9747 }
9748 };
9749
9750 function blitBuffer(src, dst, offset, length) {
9751 var pos, i = 0;
9752 while (i < length) {
9753 if ((i+offset >= dst.length) || (i >= src.length))
9754 break;
9755
9756 dst[i + offset] = src[i];
9757 i++;
9758 }
9759 return i;
9760 }
9761
9762 SlowBuffer.prototype.utf8Write = function (string, offset, length) {
9763 var bytes, pos;
9764 return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
9765 };
9766
9767 SlowBuffer.prototype.asciiWrite = function (string, offset, length) {
9768 var bytes, pos;
9769 return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
9770 };
9771
9772 SlowBuffer.prototype.binaryWrite = SlowBuffer.prototype.asciiWrite;
9773
9774 SlowBuffer.prototype.base64Write = function (string, offset, length) {
9775 var bytes, pos;
9776 return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
9777 };
9778
9779 SlowBuffer.prototype.base64Slice = function (start, end) {
9780 var bytes = Array.prototype.slice.apply(this, arguments)
9781 return require("base64-js").fromByteArray(bytes);
9782 }
9783
9784 function decodeUtf8Char(str) {
9785 try {
9786 return decodeURIComponent(str);
9787 } catch (err) {
9788 return String.fromCharCode(0xFFFD); // UTF 8 invalid char
9789 }
9790 }
9791
9792 SlowBuffer.prototype.utf8Slice = function () {
9793 var bytes = Array.prototype.slice.apply(this, arguments);
9794 var res = "";
9795 var tmp = "";
9796 var i = 0;
9797 while (i < bytes.length) {
9798 if (bytes[i] <= 0x7F) {
9799 res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
9800 tmp = "";
9801 } else
9802 tmp += "%" + bytes[i].toString(16);
9803
9804 i++;
9805 }
9806
9807 return res + decodeUtf8Char(tmp);
9808 }
9809
9810 SlowBuffer.prototype.asciiSlice = function () {
9811 var bytes = Array.prototype.slice.apply(this, arguments);
9812 var ret = "";
9813 for (var i = 0; i < bytes.length; i++)
9814 ret += String.fromCharCode(bytes[i]);
9815 return ret;
9816 }
9817
9818 SlowBuffer.prototype.binarySlice = SlowBuffer.prototype.asciiSlice;
9819
9820 SlowBuffer.prototype.inspect = function() {
9821 var out = [],
9822 len = this.length;
9823 for (var i = 0; i < len; i++) {
9824 out[i] = toHex(this[i]);
9825 if (i == exports.INSPECT_MAX_BYTES) {
9826 out[i + 1] = '...';
9827 break;
9828 }
9829 }
9830 return '<SlowBuffer ' + out.join(' ') + '>';
9831 };
9832
9833
9834 SlowBuffer.prototype.hexSlice = function(start, end) {
9835 var len = this.length;
9836
9837 if (!start || start < 0) start = 0;
9838 if (!end || end < 0 || end > len) end = len;
9839
9840 var out = '';
9841 for (var i = start; i < end; i++) {
9842 out += toHex(this[i]);
9843 }
9844 return out;
9845 };
9846
9847
9848 SlowBuffer.prototype.toString = function(encoding, start, end) {
9849 encoding = String(encoding || 'utf8').toLowerCase();
9850 start = +start || 0;
9851 if (typeof end == 'undefined') end = this.length;
9852
9853 // Fastpath empty strings
9854 if (+end == start) {
9855 return '';
9856 }
9857
9858 switch (encoding) {
9859 case 'hex':
9860 return this.hexSlice(start, end);
9861
9862 case 'utf8':
9863 case 'utf-8':
9864 return this.utf8Slice(start, end);
9865
9866 case 'ascii':
9867 return this.asciiSlice(start, end);
9868
9869 case 'binary':
9870 return this.binarySlice(start, end);
9871
9872 case 'base64':
9873 return this.base64Slice(start, end);
9874
9875 case 'ucs2':
9876 case 'ucs-2':
9877 return this.ucs2Slice(start, end);
9878
9879 default:
9880 throw new Error('Unknown encoding');
9881 }
9882 };
9883
9884
9885 SlowBuffer.prototype.hexWrite = function(string, offset, length) {
9886 offset = +offset || 0;
9887 var remaining = this.length - offset;
9888 if (!length) {
9889 length = remaining;
9890 } else {
9891 length = +length;
9892 if (length > remaining) {
9893 length = remaining;
9894 }
9895 }
9896
9897 // must be an even number of digits
9898 var strLen = string.length;
9899 if (strLen % 2) {
9900 throw new Error('Invalid hex string');
9901 }
9902 if (length > strLen / 2) {
9903 length = strLen / 2;
9904 }
9905 for (var i = 0; i < length; i++) {
9906 var byte = parseInt(string.substr(i * 2, 2), 16);
9907 if (isNaN(byte)) throw new Error('Invalid hex string');
9908 this[offset + i] = byte;
9909 }
9910 SlowBuffer._charsWritten = i * 2;
9911 return i;
9912 };
9913
9914
9915 SlowBuffer.prototype.write = function(string, offset, length, encoding) {
9916 // Support both (string, offset, length, encoding)
9917 // and the legacy (string, encoding, offset, length)
9918 if (isFinite(offset)) {
9919 if (!isFinite(length)) {
9920 encoding = length;
9921 length = undefined;
9922 }
9923 } else { // legacy
9924 var swap = encoding;
9925 encoding = offset;
9926 offset = length;
9927 length = swap;
9928 }
9929
9930 offset = +offset || 0;
9931 var remaining = this.length - offset;
9932 if (!length) {
9933 length = remaining;
9934 } else {
9935 length = +length;
9936 if (length > remaining) {
9937 length = remaining;
9938 }
9939 }
9940 encoding = String(encoding || 'utf8').toLowerCase();
9941
9942 switch (encoding) {
9943 case 'hex':
9944 return this.hexWrite(string, offset, length);
9945
9946 case 'utf8':
9947 case 'utf-8':
9948 return this.utf8Write(string, offset, length);
9949
9950 case 'ascii':
9951 return this.asciiWrite(string, offset, length);
9952
9953 case 'binary':
9954 return this.binaryWrite(string, offset, length);
9955
9956 case 'base64':
9957 return this.base64Write(string, offset, length);
9958
9959 case 'ucs2':
9960 case 'ucs-2':
9961 return this.ucs2Write(string, offset, length);
9962
9963 default:
9964 throw new Error('Unknown encoding');
9965 }
9966 };
9967
9968
9969 // slice(start, end)
9970 SlowBuffer.prototype.slice = function(start, end) {
9971 if (end === undefined) end = this.length;
9972
9973 if (end > this.length) {
9974 throw new Error('oob');
9975 }
9976 if (start > end) {
9977 throw new Error('oob');
9978 }
9979
9980 return new Buffer(this, end - start, +start);
9981 };
9982
9983 SlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) {
9984 var temp = [];
9985 for (var i=sourcestart; i<sourceend; i++) {
9986 assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
9987 temp.push(this[i]);
9988 }
9989
9990 for (var i=targetstart; i<targetstart+temp.length; i++) {
9991 target[i] = temp[i-targetstart];
9992 }
9993 };
9994
9995 SlowBuffer.prototype.fill = function(value, start, end) {
9996 if (end > this.length) {
9997 throw new Error('oob');
9998 }
9999 if (start > end) {
10000 throw new Error('oob');
10001 }
10002
10003 for (var i = start; i < end; i++) {
10004 this[i] = value;
10005 }
10006 }
10007
10008 function coerce(length) {
10009 // Coerce length to a number (possibly NaN), round up
10010 // in case it's fractional (e.g. 123.456) then do a
10011 // double negate to coerce a NaN to 0. Easy, right?
10012 length = ~~Math.ceil(+length);
10013 return length < 0 ? 0 : length;
10014 }
10015
10016
10017 // Buffer
10018
10019 function Buffer(subject, encoding, offset) {
10020 if (!(this instanceof Buffer)) {
10021 return new Buffer(subject, encoding, offset);
10022 }
10023
10024 var type;
10025
10026 // Are we slicing?
10027 if (typeof offset === 'number') {
10028 this.length = coerce(encoding);
10029 this.parent = subject;
10030 this.offset = offset;
10031 } else {
10032 // Find the length
10033 switch (type = typeof subject) {
10034 case 'number':
10035 this.length = coerce(subject);
10036 break;
10037
10038 case 'string':
10039 this.length = Buffer.byteLength(subject, encoding);
10040 break;
10041
10042 case 'object': // Assume object is an array
10043 this.length = coerce(subject.length);
10044 break;
10045
10046 default:
10047 throw new Error('First argument needs to be a number, ' +
10048 'array or string.');
10049 }
10050
10051 if (this.length > Buffer.poolSize) {
10052 // Big buffer, just alloc one.
10053 this.parent = new SlowBuffer(this.length);
10054 this.offset = 0;
10055
10056 } else {
10057 // Small buffer.
10058 if (!pool || pool.length - pool.used < this.length) allocPool();
10059 this.parent = pool;
10060 this.offset = pool.used;
10061 pool.used += this.length;
10062 }
10063
10064 // Treat array-ish objects as a byte array.
10065 if (isArrayIsh(subject)) {
10066 for (var i = 0; i < this.length; i++) {
10067 if (subject instanceof Buffer) {
10068 this.parent[i + this.offset] = subject.readUInt8(i);
10069 }
10070 else {
10071 this.parent[i + this.offset] = subject[i];
10072 }
10073 }
10074 } else if (type == 'string') {
10075 // We are a string
10076 this.length = this.write(subject, 0, encoding);
10077 }
10078 }
10079
10080 }
10081
10082 function isArrayIsh(subject) {
10083 return Array.isArray(subject) || Buffer.isBuffer(subject) ||
10084 subject && typeof subject === 'object' &&
10085 typeof subject.length === 'number';
10086 }
10087
10088 exports.SlowBuffer = SlowBuffer;
10089 exports.Buffer = Buffer;
10090
10091 Buffer.poolSize = 8 * 1024;
10092 var pool;
10093
10094 function allocPool() {
10095 pool = new SlowBuffer(Buffer.poolSize);
10096 pool.used = 0;
10097 }
10098
10099
10100 // Static methods
10101 Buffer.isBuffer = function isBuffer(b) {
10102 return b instanceof Buffer || b instanceof SlowBuffer;
10103 };
10104
10105 Buffer.concat = function (list, totalLength) {
10106 if (!Array.isArray(list)) {
10107 throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
10108 list should be an Array.");
10109 }
10110
10111 if (list.length === 0) {
10112 return new Buffer(0);
10113 } else if (list.length === 1) {
10114 return list[0];
10115 }
10116
10117 if (typeof totalLength !== 'number') {
10118 totalLength = 0;
10119 for (var i = 0; i < list.length; i++) {
10120 var buf = list[i];
10121 totalLength += buf.length;
10122 }
10123 }
10124
10125 var buffer = new Buffer(totalLength);
10126 var pos = 0;
10127 for (var i = 0; i < list.length; i++) {
10128 var buf = list[i];
10129 buf.copy(buffer, pos);
10130 pos += buf.length;
10131 }
10132 return buffer;
10133 };
10134
10135 // Inspect
10136 Buffer.prototype.inspect = function inspect() {
10137 var out = [],
10138 len = this.length;
10139
10140 for (var i = 0; i < len; i++) {
10141 out[i] = toHex(this.parent[i + this.offset]);
10142 if (i == exports.INSPECT_MAX_BYTES) {
10143 out[i + 1] = '...';
10144 break;
10145 }
10146 }
10147
10148 return '<Buffer ' + out.join(' ') + '>';
10149 };
10150
10151
10152 Buffer.prototype.get = function get(i) {
10153 if (i < 0 || i >= this.length) throw new Error('oob');
10154 return this.parent[this.offset + i];
10155 };
10156
10157
10158 Buffer.prototype.set = function set(i, v) {
10159 if (i < 0 || i >= this.length) throw new Error('oob');
10160 return this.parent[this.offset + i] = v;
10161 };
10162
10163
10164 // write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
10165 Buffer.prototype.write = function(string, offset, length, encoding) {
10166 // Support both (string, offset, length, encoding)
10167 // and the legacy (string, encoding, offset, length)
10168 if (isFinite(offset)) {
10169 if (!isFinite(length)) {
10170 encoding = length;
10171 length = undefined;
10172 }
10173 } else { // legacy
10174 var swap = encoding;
10175 encoding = offset;
10176 offset = length;
10177 length = swap;
10178 }
10179
10180 offset = +offset || 0;
10181 var remaining = this.length - offset;
10182 if (!length) {
10183 length = remaining;
10184 } else {
10185 length = +length;
10186 if (length > remaining) {
10187 length = remaining;
10188 }
10189 }
10190 encoding = String(encoding || 'utf8').toLowerCase();
10191
10192 var ret;
10193 switch (encoding) {
10194 case 'hex':
10195 ret = this.parent.hexWrite(string, this.offset + offset, length);
10196 break;
10197
10198 case 'utf8':
10199 case 'utf-8':
10200 ret = this.parent.utf8Write(string, this.offset + offset, length);
10201 break;
10202
10203 case 'ascii':
10204 ret = this.parent.asciiWrite(string, this.offset + offset, length);
10205 break;
10206
10207 case 'binary':
10208 ret = this.parent.binaryWrite(string, this.offset + offset, length);
10209 break;
10210
10211 case 'base64':
10212 // Warning: maxLength not taken into account in base64Write
10213 ret = this.parent.base64Write(string, this.offset + offset, length);
10214 break;
10215
10216 case 'ucs2':
10217 case 'ucs-2':
10218 ret = this.parent.ucs2Write(string, this.offset + offset, length);
10219 break;
10220
10221 default:
10222 throw new Error('Unknown encoding');
10223 }
10224
10225 Buffer._charsWritten = SlowBuffer._charsWritten;
10226
10227 return ret;
10228 };
10229
10230
10231 // toString(encoding, start=0, end=buffer.length)
10232 Buffer.prototype.toString = function(encoding, start, end) {
10233 encoding = String(encoding || 'utf8').toLowerCase();
10234
10235 if (typeof start == 'undefined' || start < 0) {
10236 start = 0;
10237 } else if (start > this.length) {
10238 start = this.length;
10239 }
10240
10241 if (typeof end == 'undefined' || end > this.length) {
10242 end = this.length;
10243 } else if (end < 0) {
10244 end = 0;
10245 }
10246
10247 start = start + this.offset;
10248 end = end + this.offset;
10249
10250 switch (encoding) {
10251 case 'hex':
10252 return this.parent.hexSlice(start, end);
10253
10254 case 'utf8':
10255 case 'utf-8':
10256 return this.parent.utf8Slice(start, end);
10257
10258 case 'ascii':
10259 return this.parent.asciiSlice(start, end);
10260
10261 case 'binary':
10262 return this.parent.binarySlice(start, end);
10263
10264 case 'base64':
10265 return this.parent.base64Slice(start, end);
10266
10267 case 'ucs2':
10268 case 'ucs-2':
10269 return this.parent.ucs2Slice(start, end);
10270
10271 default:
10272 throw new Error('Unknown encoding');
10273 }
10274 };
10275
10276
10277 // byteLength
10278 Buffer.byteLength = SlowBuffer.byteLength;
10279
10280
10281 // fill(value, start=0, end=buffer.length)
10282 Buffer.prototype.fill = function fill(value, start, end) {
10283 value || (value = 0);
10284 start || (start = 0);
10285 end || (end = this.length);
10286
10287 if (typeof value === 'string') {
10288 value = value.charCodeAt(0);
10289 }
10290 if (!(typeof value === 'number') || isNaN(value)) {
10291 throw new Error('value is not a number');
10292 }
10293
10294 if (end < start) throw new Error('end < start');
10295
10296 // Fill 0 bytes; we're done
10297 if (end === start) return 0;
10298 if (this.length == 0) return 0;
10299
10300 if (start < 0 || start >= this.length) {
10301 throw new Error('start out of bounds');
10302 }
10303
10304 if (end < 0 || end > this.length) {
10305 throw new Error('end out of bounds');
10306 }
10307
10308 return this.parent.fill(value,
10309 start + this.offset,
10310 end + this.offset);
10311 };
10312
10313
10314 // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
10315 Buffer.prototype.copy = function(target, target_start, start, end) {
10316 var source = this;
10317 start || (start = 0);
10318 end || (end = this.length);
10319 target_start || (target_start = 0);
10320
10321 if (end < start) throw new Error('sourceEnd < sourceStart');
10322
10323 // Copy 0 bytes; we're done
10324 if (end === start) return 0;
10325 if (target.length == 0 || source.length == 0) return 0;
10326
10327 if (target_start < 0 || target_start >= target.length) {
10328 throw new Error('targetStart out of bounds');
10329 }
10330
10331 if (start < 0 || start >= source.length) {
10332 throw new Error('sourceStart out of bounds');
10333 }
10334
10335 if (end < 0 || end > source.length) {
10336 throw new Error('sourceEnd out of bounds');
10337 }
10338
10339 // Are we oob?
10340 if (end > this.length) {
10341 end = this.length;
10342 }
10343
10344 if (target.length - target_start < end - start) {
10345 end = target.length - target_start + start;
10346 }
10347
10348 return this.parent.copy(target.parent,
10349 target_start + target.offset,
10350 start + this.offset,
10351 end + this.offset);
10352 };
10353
10354
10355 // slice(start, end)
10356 Buffer.prototype.slice = function(start, end) {
10357 if (end === undefined) end = this.length;
10358 if (end > this.length) throw new Error('oob');
10359 if (start > end) throw new Error('oob');
10360
10361 return new Buffer(this.parent, end - start, +start + this.offset);
10362 };
10363
10364
10365 // Legacy methods for backwards compatibility.
10366
10367 Buffer.prototype.utf8Slice = function(start, end) {
10368 return this.toString('utf8', start, end);
10369 };
10370
10371 Buffer.prototype.binarySlice = function(start, end) {
10372 return this.toString('binary', start, end);
10373 };
10374
10375 Buffer.prototype.asciiSlice = function(start, end) {
10376 return this.toString('ascii', start, end);
10377 };
10378
10379 Buffer.prototype.utf8Write = function(string, offset) {
10380 return this.write(string, offset, 'utf8');
10381 };
10382
10383 Buffer.prototype.binaryWrite = function(string, offset) {
10384 return this.write(string, offset, 'binary');
10385 };
10386
10387 Buffer.prototype.asciiWrite = function(string, offset) {
10388 return this.write(string, offset, 'ascii');
10389 };
10390
10391 Buffer.prototype.readUInt8 = function(offset, noAssert) {
10392 var buffer = this;
10393
10394 if (!noAssert) {
10395 assert.ok(offset !== undefined && offset !== null,
10396 'missing offset');
10397
10398 assert.ok(offset < buffer.length,
10399 'Trying to read beyond buffer length');
10400 }
10401
10402 if (offset >= buffer.length) return;
10403
10404 return buffer.parent[buffer.offset + offset];
10405 };
10406
10407 function readUInt16(buffer, offset, isBigEndian, noAssert) {
10408 var val = 0;
10409
10410
10411 if (!noAssert) {
10412 assert.ok(typeof (isBigEndian) === 'boolean',
10413 'missing or invalid endian');
10414
10415 assert.ok(offset !== undefined && offset !== null,
10416 'missing offset');
10417
10418 assert.ok(offset + 1 < buffer.length,
10419 'Trying to read beyond buffer length');
10420 }
10421
10422 if (offset >= buffer.length) return 0;
10423
10424 if (isBigEndian) {
10425 val = buffer.parent[buffer.offset + offset] << 8;
10426 if (offset + 1 < buffer.length) {
10427 val |= buffer.parent[buffer.offset + offset + 1];
10428 }
10429 } else {
10430 val = buffer.parent[buffer.offset + offset];
10431 if (offset + 1 < buffer.length) {
10432 val |= buffer.parent[buffer.offset + offset + 1] << 8;
10433 }
10434 }
10435
10436 return val;
10437 }
10438
10439 Buffer.prototype.readUInt16LE = function(offset, noAssert) {
10440 return readUInt16(this, offset, false, noAssert);
10441 };
10442
10443 Buffer.prototype.readUInt16BE = function(offset, noAssert) {
10444 return readUInt16(this, offset, true, noAssert);
10445 };
10446
10447 function readUInt32(buffer, offset, isBigEndian, noAssert) {
10448 var val = 0;
10449
10450 if (!noAssert) {
10451 assert.ok(typeof (isBigEndian) === 'boolean',
10452 'missing or invalid endian');
10453
10454 assert.ok(offset !== undefined && offset !== null,
10455 'missing offset');
10456
10457 assert.ok(offset + 3 < buffer.length,
10458 'Trying to read beyond buffer length');
10459 }
10460
10461 if (offset >= buffer.length) return 0;
10462
10463 if (isBigEndian) {
10464 if (offset + 1 < buffer.length)
10465 val = buffer.parent[buffer.offset + offset + 1] << 16;
10466 if (offset + 2 < buffer.length)
10467 val |= buffer.parent[buffer.offset + offset + 2] << 8;
10468 if (offset + 3 < buffer.length)
10469 val |= buffer.parent[buffer.offset + offset + 3];
10470 val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);
10471 } else {
10472 if (offset + 2 < buffer.length)
10473 val = buffer.parent[buffer.offset + offset + 2] << 16;
10474 if (offset + 1 < buffer.length)
10475 val |= buffer.parent[buffer.offset + offset + 1] << 8;
10476 val |= buffer.parent[buffer.offset + offset];
10477 if (offset + 3 < buffer.length)
10478 val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
10479 }
10480
10481 return val;
10482 }
10483
10484 Buffer.prototype.readUInt32LE = function(offset, noAssert) {
10485 return readUInt32(this, offset, false, noAssert);
10486 };
10487
10488 Buffer.prototype.readUInt32BE = function(offset, noAssert) {
10489 return readUInt32(this, offset, true, noAssert);
10490 };
10491
10492
10493 /*
10494 * Signed integer types, yay team! A reminder on how two's complement actually
10495 * works. The first bit is the signed bit, i.e. tells us whether or not the
10496 * number should be positive or negative. If the two's complement value is
10497 * positive, then we're done, as it's equivalent to the unsigned representation.
10498 *
10499 * Now if the number is positive, you're pretty much done, you can just leverage
10500 * the unsigned translations and return those. Unfortunately, negative numbers
10501 * aren't quite that straightforward.
10502 *
10503 * At first glance, one might be inclined to use the traditional formula to
10504 * translate binary numbers between the positive and negative values in two's
10505 * complement. (Though it doesn't quite work for the most negative value)
10506 * Mainly:
10507 * - invert all the bits
10508 * - add one to the result
10509 *
10510 * Of course, this doesn't quite work in Javascript. Take for example the value
10511 * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
10512 * course, Javascript will do the following:
10513 *
10514 * > ~0xff80
10515 * -65409
10516 *
10517 * Whoh there, Javascript, that's not quite right. But wait, according to
10518 * Javascript that's perfectly correct. When Javascript ends up seeing the
10519 * constant 0xff80, it has no notion that it is actually a signed number. It
10520 * assumes that we've input the unsigned value 0xff80. Thus, when it does the
10521 * binary negation, it casts it into a signed value, (positive 0xff80). Then
10522 * when you perform binary negation on that, it turns it into a negative number.
10523 *
10524 * Instead, we're going to have to use the following general formula, that works
10525 * in a rather Javascript friendly way. I'm glad we don't support this kind of
10526 * weird numbering scheme in the kernel.
10527 *
10528 * (BIT-MAX - (unsigned)val + 1) * -1
10529 *
10530 * The astute observer, may think that this doesn't make sense for 8-bit numbers
10531 * (really it isn't necessary for them). However, when you get 16-bit numbers,
10532 * you do. Let's go back to our prior example and see how this will look:
10533 *
10534 * (0xffff - 0xff80 + 1) * -1
10535 * (0x007f + 1) * -1
10536 * (0x0080) * -1
10537 */
10538 Buffer.prototype.readInt8 = function(offset, noAssert) {
10539 var buffer = this;
10540 var neg;
10541
10542 if (!noAssert) {
10543 assert.ok(offset !== undefined && offset !== null,
10544 'missing offset');
10545
10546 assert.ok(offset < buffer.length,
10547 'Trying to read beyond buffer length');
10548 }
10549
10550 if (offset >= buffer.length) return;
10551
10552 neg = buffer.parent[buffer.offset + offset] & 0x80;
10553 if (!neg) {
10554 return (buffer.parent[buffer.offset + offset]);
10555 }
10556
10557 return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);
10558 };
10559
10560 function readInt16(buffer, offset, isBigEndian, noAssert) {
10561 var neg, val;
10562
10563 if (!noAssert) {
10564 assert.ok(typeof (isBigEndian) === 'boolean',
10565 'missing or invalid endian');
10566
10567 assert.ok(offset !== undefined && offset !== null,
10568 'missing offset');
10569
10570 assert.ok(offset + 1 < buffer.length,
10571 'Trying to read beyond buffer length');
10572 }
10573
10574 val = readUInt16(buffer, offset, isBigEndian, noAssert);
10575 neg = val & 0x8000;
10576 if (!neg) {
10577 return val;
10578 }
10579
10580 return (0xffff - val + 1) * -1;
10581 }
10582
10583 Buffer.prototype.readInt16LE = function(offset, noAssert) {
10584 return readInt16(this, offset, false, noAssert);
10585 };
10586
10587 Buffer.prototype.readInt16BE = function(offset, noAssert) {
10588 return readInt16(this, offset, true, noAssert);
10589 };
10590
10591 function readInt32(buffer, offset, isBigEndian, noAssert) {
10592 var neg, val;
10593
10594 if (!noAssert) {
10595 assert.ok(typeof (isBigEndian) === 'boolean',
10596 'missing or invalid endian');
10597
10598 assert.ok(offset !== undefined && offset !== null,
10599 'missing offset');
10600
10601 assert.ok(offset + 3 < buffer.length,
10602 'Trying to read beyond buffer length');
10603 }
10604
10605 val = readUInt32(buffer, offset, isBigEndian, noAssert);
10606 neg = val & 0x80000000;
10607 if (!neg) {
10608 return (val);
10609 }
10610
10611 return (0xffffffff - val + 1) * -1;
10612 }
10613
10614 Buffer.prototype.readInt32LE = function(offset, noAssert) {
10615 return readInt32(this, offset, false, noAssert);
10616 };
10617
10618 Buffer.prototype.readInt32BE = function(offset, noAssert) {
10619 return readInt32(this, offset, true, noAssert);
10620 };
10621
10622 function readFloat(buffer, offset, isBigEndian, noAssert) {
10623 if (!noAssert) {
10624 assert.ok(typeof (isBigEndian) === 'boolean',
10625 'missing or invalid endian');
10626
10627 assert.ok(offset + 3 < buffer.length,
10628 'Trying to read beyond buffer length');
10629 }
10630
10631 return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
10632 23, 4);
10633 }
10634
10635 Buffer.prototype.readFloatLE = function(offset, noAssert) {
10636 return readFloat(this, offset, false, noAssert);
10637 };
10638
10639 Buffer.prototype.readFloatBE = function(offset, noAssert) {
10640 return readFloat(this, offset, true, noAssert);
10641 };
10642
10643 function readDouble(buffer, offset, isBigEndian, noAssert) {
10644 if (!noAssert) {
10645 assert.ok(typeof (isBigEndian) === 'boolean',
10646 'missing or invalid endian');
10647
10648 assert.ok(offset + 7 < buffer.length,
10649 'Trying to read beyond buffer length');
10650 }
10651
10652 return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
10653 52, 8);
10654 }
10655
10656 Buffer.prototype.readDoubleLE = function(offset, noAssert) {
10657 return readDouble(this, offset, false, noAssert);
10658 };
10659
10660 Buffer.prototype.readDoubleBE = function(offset, noAssert) {
10661 return readDouble(this, offset, true, noAssert);
10662 };
10663
10664
10665 /*
10666 * We have to make sure that the value is a valid integer. This means that it is
10667 * non-negative. It has no fractional component and that it does not exceed the
10668 * maximum allowed value.
10669 *
10670 * value The number to check for validity
10671 *
10672 * max The maximum value
10673 */
10674 function verifuint(value, max) {
10675 assert.ok(typeof (value) == 'number',
10676 'cannot write a non-number as a number');
10677
10678 assert.ok(value >= 0,
10679 'specified a negative value for writing an unsigned value');
10680
10681 assert.ok(value <= max, 'value is larger than maximum value for type');
10682
10683 assert.ok(Math.floor(value) === value, 'value has a fractional component');
10684 }
10685
10686 Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
10687 var buffer = this;
10688
10689 if (!noAssert) {
10690 assert.ok(value !== undefined && value !== null,
10691 'missing value');
10692
10693 assert.ok(offset !== undefined && offset !== null,
10694 'missing offset');
10695
10696 assert.ok(offset < buffer.length,
10697 'trying to write beyond buffer length');
10698
10699 verifuint(value, 0xff);
10700 }
10701
10702 if (offset < buffer.length) {
10703 buffer.parent[buffer.offset + offset] = value;
10704 }
10705 };
10706
10707 function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
10708 if (!noAssert) {
10709 assert.ok(value !== undefined && value !== null,
10710 'missing value');
10711
10712 assert.ok(typeof (isBigEndian) === 'boolean',
10713 'missing or invalid endian');
10714
10715 assert.ok(offset !== undefined && offset !== null,
10716 'missing offset');
10717
10718 assert.ok(offset + 1 < buffer.length,
10719 'trying to write beyond buffer length');
10720
10721 verifuint(value, 0xffff);
10722 }
10723
10724 for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
10725 buffer.parent[buffer.offset + offset + i] =
10726 (value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
10727 (isBigEndian ? 1 - i : i) * 8;
10728 }
10729
10730 }
10731
10732 Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
10733 writeUInt16(this, value, offset, false, noAssert);
10734 };
10735
10736 Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
10737 writeUInt16(this, value, offset, true, noAssert);
10738 };
10739
10740 function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
10741 if (!noAssert) {
10742 assert.ok(value !== undefined && value !== null,
10743 'missing value');
10744
10745 assert.ok(typeof (isBigEndian) === 'boolean',
10746 'missing or invalid endian');
10747
10748 assert.ok(offset !== undefined && offset !== null,
10749 'missing offset');
10750
10751 assert.ok(offset + 3 < buffer.length,
10752 'trying to write beyond buffer length');
10753
10754 verifuint(value, 0xffffffff);
10755 }
10756
10757 for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
10758 buffer.parent[buffer.offset + offset + i] =
10759 (value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
10760 }
10761 }
10762
10763 Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
10764 writeUInt32(this, value, offset, false, noAssert);
10765 };
10766
10767 Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
10768 writeUInt32(this, value, offset, true, noAssert);
10769 };
10770
10771
10772 /*
10773 * We now move onto our friends in the signed number category. Unlike unsigned
10774 * numbers, we're going to have to worry a bit more about how we put values into
10775 * arrays. Since we are only worrying about signed 32-bit values, we're in
10776 * slightly better shape. Unfortunately, we really can't do our favorite binary
10777 * & in this system. It really seems to do the wrong thing. For example:
10778 *
10779 * > -32 & 0xff
10780 * 224
10781 *
10782 * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
10783 * this aren't treated as a signed number. Ultimately a bad thing.
10784 *
10785 * What we're going to want to do is basically create the unsigned equivalent of
10786 * our representation and pass that off to the wuint* functions. To do that
10787 * we're going to do the following:
10788 *
10789 * - if the value is positive
10790 * we can pass it directly off to the equivalent wuint
10791 * - if the value is negative
10792 * we do the following computation:
10793 * mb + val + 1, where
10794 * mb is the maximum unsigned value in that byte size
10795 * val is the Javascript negative integer
10796 *
10797 *
10798 * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
10799 * you do out the computations:
10800 *
10801 * 0xffff - 128 + 1
10802 * 0xffff - 127
10803 * 0xff80
10804 *
10805 * You can then encode this value as the signed version. This is really rather
10806 * hacky, but it should work and get the job done which is our goal here.
10807 */
10808
10809 /*
10810 * A series of checks to make sure we actually have a signed 32-bit number
10811 */
10812 function verifsint(value, max, min) {
10813 assert.ok(typeof (value) == 'number',
10814 'cannot write a non-number as a number');
10815
10816 assert.ok(value <= max, 'value larger than maximum allowed value');
10817
10818 assert.ok(value >= min, 'value smaller than minimum allowed value');
10819
10820 assert.ok(Math.floor(value) === value, 'value has a fractional component');
10821 }
10822
10823 function verifIEEE754(value, max, min) {
10824 assert.ok(typeof (value) == 'number',
10825 'cannot write a non-number as a number');
10826
10827 assert.ok(value <= max, 'value larger than maximum allowed value');
10828
10829 assert.ok(value >= min, 'value smaller than minimum allowed value');
10830 }
10831
10832 Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
10833 var buffer = this;
10834
10835 if (!noAssert) {
10836 assert.ok(value !== undefined && value !== null,
10837 'missing value');
10838
10839 assert.ok(offset !== undefined && offset !== null,
10840 'missing offset');
10841
10842 assert.ok(offset < buffer.length,
10843 'Trying to write beyond buffer length');
10844
10845 verifsint(value, 0x7f, -0x80);
10846 }
10847
10848 if (value >= 0) {
10849 buffer.writeUInt8(value, offset, noAssert);
10850 } else {
10851 buffer.writeUInt8(0xff + value + 1, offset, noAssert);
10852 }
10853 };
10854
10855 function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
10856 if (!noAssert) {
10857 assert.ok(value !== undefined && value !== null,
10858 'missing value');
10859
10860 assert.ok(typeof (isBigEndian) === 'boolean',
10861 'missing or invalid endian');
10862
10863 assert.ok(offset !== undefined && offset !== null,
10864 'missing offset');
10865
10866 assert.ok(offset + 1 < buffer.length,
10867 'Trying to write beyond buffer length');
10868
10869 verifsint(value, 0x7fff, -0x8000);
10870 }
10871
10872 if (value >= 0) {
10873 writeUInt16(buffer, value, offset, isBigEndian, noAssert);
10874 } else {
10875 writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
10876 }
10877 }
10878
10879 Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
10880 writeInt16(this, value, offset, false, noAssert);
10881 };
10882
10883 Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
10884 writeInt16(this, value, offset, true, noAssert);
10885 };
10886
10887 function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
10888 if (!noAssert) {
10889 assert.ok(value !== undefined && value !== null,
10890 'missing value');
10891
10892 assert.ok(typeof (isBigEndian) === 'boolean',
10893 'missing or invalid endian');
10894
10895 assert.ok(offset !== undefined && offset !== null,
10896 'missing offset');
10897
10898 assert.ok(offset + 3 < buffer.length,
10899 'Trying to write beyond buffer length');
10900
10901 verifsint(value, 0x7fffffff, -0x80000000);
10902 }
10903
10904 if (value >= 0) {
10905 writeUInt32(buffer, value, offset, isBigEndian, noAssert);
10906 } else {
10907 writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
10908 }
10909 }
10910
10911 Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
10912 writeInt32(this, value, offset, false, noAssert);
10913 };
10914
10915 Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
10916 writeInt32(this, value, offset, true, noAssert);
10917 };
10918
10919 function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
10920 if (!noAssert) {
10921 assert.ok(value !== undefined && value !== null,
10922 'missing value');
10923
10924 assert.ok(typeof (isBigEndian) === 'boolean',
10925 'missing or invalid endian');
10926
10927 assert.ok(offset !== undefined && offset !== null,
10928 'missing offset');
10929
10930 assert.ok(offset + 3 < buffer.length,
10931 'Trying to write beyond buffer length');
10932
10933 verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
10934 }
10935
10936 require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
10937 23, 4);
10938 }
10939
10940 Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
10941 writeFloat(this, value, offset, false, noAssert);
10942 };
10943
10944 Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
10945 writeFloat(this, value, offset, true, noAssert);
10946 };
10947
10948 function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
10949 if (!noAssert) {
10950 assert.ok(value !== undefined && value !== null,
10951 'missing value');
10952
10953 assert.ok(typeof (isBigEndian) === 'boolean',
10954 'missing or invalid endian');
10955
10956 assert.ok(offset !== undefined && offset !== null,
10957 'missing offset');
10958
10959 assert.ok(offset + 7 < buffer.length,
10960 'Trying to write beyond buffer length');
10961
10962 verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
10963 }
10964
10965 require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
10966 52, 8);
10967 }
10968
10969 Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
10970 writeDouble(this, value, offset, false, noAssert);
10971 };
10972
10973 Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
10974 writeDouble(this, value, offset, true, noAssert);
10975 };
10976
10977 SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;
10978 SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;
10979 SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;
10980 SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;
10981 SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;
10982 SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;
10983 SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;
10984 SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;
10985 SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;
10986 SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;
10987 SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;
10988 SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;
10989 SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;
10990 SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;
10991 SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;
10992 SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;
10993 SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;
10994 SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;
10995 SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;
10996 SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;
10997 SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;
10998 SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;
10999 SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;
11000 SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;
11001 SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;
11002 SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;
11003 SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;
11004 SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;
11005
11006 })()
11007 },{"assert":9,"./buffer_ieee754":14,"base64-js":15}],15:[function(require,module,exports){
11008 (function (exports) {
11009 'use strict';
11010
11011 var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
11012
11013 function b64ToByteArray(b64) {
11014 var i, j, l, tmp, placeHolders, arr;
11015
11016 if (b64.length % 4 > 0) {
11017 throw 'Invalid string. Length must be a multiple of 4';
11018 }
11019
11020 // the number of equal signs (place holders)
11021 // if there are two placeholders, than the two characters before it
11022 // represent one byte
11023 // if there is only one, then the three characters before it represent 2 bytes
11024 // this is just a cheap hack to not do indexOf twice
11025 placeHolders = b64.indexOf('=');
11026 placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
11027
11028 // base64 is 4/3 + up to two characters of the original data
11029 arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
11030
11031 // if there are placeholders, only get up to the last complete 4 chars
11032 l = placeHolders > 0 ? b64.length - 4 : b64.length;
11033
11034 for (i = 0, j = 0; i < l; i += 4, j += 3) {
11035 tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
11036 arr.push((tmp & 0xFF0000) >> 16);
11037 arr.push((tmp & 0xFF00) >> 8);
11038 arr.push(tmp & 0xFF);
11039 }
11040
11041 if (placeHolders === 2) {
11042 tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
11043 arr.push(tmp & 0xFF);
11044 } else if (placeHolders === 1) {
11045 tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
11046 arr.push((tmp >> 8) & 0xFF);
11047 arr.push(tmp & 0xFF);
11048 }
11049
11050 return arr;
11051 }
11052
11053 function uint8ToBase64(uint8) {
11054 var i,
11055 extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
11056 output = "",
11057 temp, length;
11058
11059 function tripletToBase64 (num) {
11060 return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
11061 };
11062
11063 // go through the array every three bytes, we'll deal with trailing stuff later
11064 for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
11065 temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
11066 output += tripletToBase64(temp);
11067 }
11068
11069 // pad the end with zeros, but make sure to not forget the extra bytes
11070 switch (extraBytes) {
11071 case 1:
11072 temp = uint8[uint8.length - 1];
11073 output += lookup[temp >> 2];
11074 output += lookup[(temp << 4) & 0x3F];
11075 output += '==';
11076 break;
11077 case 2:
11078 temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
11079 output += lookup[temp >> 10];
11080 output += lookup[(temp >> 4) & 0x3F];
11081 output += lookup[(temp << 2) & 0x3F];
11082 output += '=';
11083 break;
11084 }
11085
11086 return output;
11087 }
11088
11089 module.exports.toByteArray = b64ToByteArray;
11090 module.exports.fromByteArray = uint8ToBase64;
11091 }());
11092
11093 },{}]},{},["E/GbHF"])
11094 ;
11095 JSHINT = require('jshint').JSHINT;
11096 }());

mercurial