Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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
8 var process = module.exports = {};
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 ;
17 if (canSetImmediate) {
18 return function (f) { return window.setImmediate(f) };
19 }
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);
33 return function nextTick(fn) {
34 queue.push(fn);
35 window.postMessage('process-tick', '*');
36 };
37 }
39 return function nextTick(fn) {
40 setTimeout(fn, 0);
41 };
42 })();
44 process.title = 'browser';
45 process.browser = true;
46 process.env = {};
47 process.argv = [];
49 process.binding = function (name) {
50 throw new Error('process.binding is not supported');
51 }
53 // TODO(shtylman)
54 process.cwd = function () { return '/' };
55 process.chdir = function (dir) {
56 throw new Error('process.chdir is not supported');
57 };
59 },{}],2:[function(require,module,exports){
60 (function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
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 }
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 };
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 }
105 if (!this._events) return false;
106 var handler = this._events[type];
107 if (!handler) return false;
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;
128 } else if (isArray(handler)) {
129 var args = Array.prototype.slice.call(arguments, 1);
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;
137 } else {
138 return false;
139 }
140 };
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 }
149 if (!this._events) this._events = {};
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);
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])) {
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 }
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 }
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 }
186 return this;
187 };
189 EventEmitter.prototype.on = EventEmitter.prototype.addListener;
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 });
198 return this;
199 };
201 EventEmitter.prototype.removeListener = function(type, listener) {
202 if ('function' !== typeof listener) {
203 throw new Error('removeListener only takes instances of Function');
204 }
206 // does not use listeners(), so no side effect of creating _events[type]
207 if (!this._events || !this._events[type]) return this;
209 var list = this._events[type];
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 }
221 return this;
222 };
224 EventEmitter.prototype.removeAllListeners = function(type) {
225 if (arguments.length === 0) {
226 this._events = {};
227 return this;
228 }
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 };
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 };
244 })(require("__browserify_process"))
245 },{"__browserify_process":1}],3:[function(require,module,exports){
246 (function(){// jshint -W001
248 "use strict";
250 // Identifiers provided by the ECMAScript standard.
252 exports.reservedVars = {
253 arguments : false,
254 NaN : false
255 };
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 };
290 // Global variables commonly provided by a web browser environment.
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 };
591 exports.devel = {
592 alert : false,
593 confirm: false,
594 console: false,
595 Debug : false,
596 opera : false,
597 prompt : false
598 };
600 exports.worker = {
601 importScripts: true,
602 postMessage : true,
603 self : true
604 };
606 // Widely adopted global names that are not part of ECMAScript standard
607 exports.nonstandard = {
608 escape : false,
609 unescape: false
610 };
612 // Globals provided by popular JavaScript environments.
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 };
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 };
648 exports.phantom = {
649 phantom : true,
650 require : true,
651 WebPage : true
652 };
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 };
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 };
690 // Globals provided by popular JavaScript libraries.
692 exports.dojo = {
693 dojo : false,
694 dijit : false,
695 dojox : false,
696 define : false,
697 "require": false
698 };
700 exports.jquery = {
701 "$" : false,
702 jQuery : false
703 };
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 };
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 };
794 exports.yui = {
795 YUI : false,
796 Y : false,
797 YUI_config: false
798 };
801 })()
802 },{}],4:[function(require,module,exports){
803 "use strict";
805 var state = {
806 syntax: {},
808 reset: function () {
809 this.tokens = {
810 prev: null,
811 next: null,
812 curr: null
813 };
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 };
826 exports.state = state;
828 },{}],5:[function(require,module,exports){
829 (function(){"use strict";
831 exports.register = function (linter) {
832 // Check for properties named __proto__. This special property was
833 // deprecated and then re-introduced for ES6.
835 linter.on("Identifier", function style_scanProto(data) {
836 if (linter.getOption("proto")) {
837 return;
838 }
840 if (data.name === "__proto__") {
841 linter.warn("W103", {
842 line: data.line,
843 char: data.char,
844 data: [ data.name ]
845 });
846 }
847 });
849 // Check for properties named __iterator__. This is a special property
850 // available only in browsers with JavaScript 1.7 implementation.
852 linter.on("Identifier", function style_scanIterator(data) {
853 if (linter.getOption("iterator")) {
854 return;
855 }
857 if (data.name === "__iterator__") {
858 linter.warn("W104", {
859 line: data.line,
860 char: data.char,
861 data: [ data.name ]
862 });
863 }
864 });
866 // Check for dangling underscores.
868 linter.on("Identifier", function style_scanDangling(data) {
869 if (!linter.getOption("nomen")) {
870 return;
871 }
873 // Underscore.js
874 if (data.name === "_") {
875 return;
876 }
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 }
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 });
894 // Check that all identifiers are using camelCase notation.
895 // Exceptions: names like MY_VAR and _myVar.
897 linter.on("Identifier", function style_scanCamelCase(data) {
898 if (!linter.getOption("camelcase")) {
899 return;
900 }
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 });
911 // Enforce consistency in style of quoting.
913 linter.on("String", function style_scanQuotes(data) {
914 var quotmark = linter.getOption("quotmark");
915 var code;
917 if (!quotmark) {
918 return;
919 }
921 // If quotmark is set to 'single' warn about all double-quotes.
923 if (quotmark === "single" && data.quote !== "'") {
924 code = "W109";
925 }
927 // If quotmark is set to 'double' warn about all single-quotes.
929 if (quotmark === "double" && data.quote !== "\"") {
930 code = "W108";
931 }
933 // If quotmark is set to true, remember the first quotation style
934 // and then warn about all others.
936 if (quotmark === true) {
937 if (!linter.getCache("quotmark")) {
938 linter.setCache("quotmark", data.quote);
939 }
941 if (linter.getCache("quotmark") !== data.quote) {
942 code = "W110";
943 }
944 }
946 if (code) {
947 linter.warn(code, {
948 line: data.line,
949 char: data.char,
950 });
951 }
952 });
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 }
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 }
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 });
983 // Warn about script URLs.
985 linter.on("String", function style_scanJavaScriptURLs(data) {
986 var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
988 if (linter.getOption("scripturl")) {
989 return;
990 }
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 */
1006 /*jshint maxlen:1000 */
1008 "use string";
1010 // Unsafe comment or string (ax)
1011 exports.unsafeString =
1012 /@cc|<\/?|script|\]\s*\]|<\s*!|</i;
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]/;
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]/;
1022 exports.needEscGlobal =
1023 /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
1025 // Star slash (lx)
1026 exports.starSlash = /\*\//;
1028 // Identifier (ix)
1029 exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
1031 // JavaScript URL (jx)
1032 exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
1034 // Catches /* falls through */ comments (ft)
1035 //exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
1036 exports.fallsThrough = /^\s*\/\/\s*Falls?\sthrough.*\s*$/;
1038 },{}],7:[function(require,module,exports){
1039 (function(global){/*global window, global*/
1040 var util = require("util")
1041 var assert = require("assert")
1043 var slice = Array.prototype.slice
1044 var console
1045 var times = {}
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 }
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 ]
1067 for (var i = 0; i < functions.length; i++) {
1068 var tuple = functions[i]
1069 var f = tuple[0]
1070 var name = tuple[1]
1072 if (!console[name]) {
1073 console[name] = f
1074 }
1075 }
1077 module.exports = console
1079 function log() {}
1081 function info() {
1082 console.log.apply(console, arguments)
1083 }
1085 function warn() {
1086 console.log.apply(console, arguments)
1087 }
1089 function error() {
1090 console.warn.apply(console, arguments)
1091 }
1093 function time(label) {
1094 times[label] = Date.now()
1095 }
1097 function timeEnd(label) {
1098 var time = times[label]
1099 if (!time) {
1100 throw new Error("No such label: " + label)
1101 }
1103 var duration = Date.now() - time
1104 console.log(label + ": " + duration + "ms")
1105 }
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 }
1114 function dir(object) {
1115 console.log(util.inspect(object) + "\n")
1116 }
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 }
1125 })(window)
1126 },{"util":8,"assert":9}],10:[function(require,module,exports){
1127 (function(){/*
1128 * Lexical analysis and token construction.
1129 */
1131 "use strict";
1133 var _ = require("underscore");
1134 var events = require("events");
1135 var reg = require("./reg.js");
1136 var state = require("./state.js").state;
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
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 };
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
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 ];
1264 var identifierStartTable = [];
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 }
1274 var identifierPartTable = [];
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 }
1282 // Object that handles postponed lexing verifications that checks the parsed
1283 // environment state.
1285 function asyncTrigger() {
1286 var _checks = [];
1288 return {
1289 push: function (fn) {
1290 _checks.push(fn);
1291 },
1293 check: function () {
1294 for (var check in _checks) {
1295 _checks[check]();
1296 }
1298 _checks.splice(0, _checks.length);
1299 }
1300 };
1301 }
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;
1332 if (typeof lines === "string") {
1333 lines = lines
1334 .replace(/\r\n/g, "\n")
1335 .replace(/\r/g, "\n")
1336 .split("\n");
1337 }
1339 // If the first line is a shebang (#!), make it a blank and move on.
1340 // Shebangs are used by Node scripts.
1342 if (lines[0] && lines[0].substr(0, 2) === "#!") {
1343 lines[0] = "";
1344 }
1346 this.emitter = new events.EventEmitter();
1347 this.source = source;
1348 this.lines = lines;
1349 this.prereg = true;
1351 this.line = 0;
1352 this.char = 1;
1353 this.from = 1;
1354 this.input = "";
1356 for (var i = 0; i < state.option.indent; i += 1) {
1357 state.tab += " ";
1358 }
1359 }
1361 Lexer.prototype = {
1362 _lines: [],
1364 get lines() {
1365 this._lines = state.lines;
1366 return this._lines;
1367 },
1369 set lines(val) {
1370 this._lines = val;
1371 state.lines = this._lines;
1372 },
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 },
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 },
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 },
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 },
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 },
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;
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 };
1469 // A pound sign (for Node shebangs)
1470 case "#":
1471 return {
1472 type: Token.Punctuator,
1473 value: ch1
1474 };
1476 // We're at the end of input
1477 case "":
1478 return null;
1479 }
1481 // Peek more characters
1483 ch2 = this.peek(1);
1484 ch3 = this.peek(2);
1485 ch4 = this.peek(3);
1487 // 4-character punctuator: >>>=
1489 if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
1490 return {
1491 type: Token.Punctuator,
1492 value: ">>>="
1493 };
1494 }
1496 // 3-character punctuators: === !== >>> <<= >>=
1498 if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
1499 return {
1500 type: Token.Punctuator,
1501 value: "==="
1502 };
1503 }
1505 if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
1506 return {
1507 type: Token.Punctuator,
1508 value: "!=="
1509 };
1510 }
1512 if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
1513 return {
1514 type: Token.Punctuator,
1515 value: ">>>"
1516 };
1517 }
1519 if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
1520 return {
1521 type: Token.Punctuator,
1522 value: "<<="
1523 };
1524 }
1526 if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
1527 return {
1528 type: Token.Punctuator,
1529 value: ">>="
1530 };
1531 }
1533 // Fat arrow punctuator
1534 if (ch1 === "=" && ch2 === ">") {
1535 return {
1536 type: Token.Punctuator,
1537 value: ch1 + ch2
1538 };
1539 }
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 }
1550 if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
1551 if (ch2 === "=") {
1552 return {
1553 type: Token.Punctuator,
1554 value: ch1 + ch2
1555 };
1556 }
1558 return {
1559 type: Token.Punctuator,
1560 value: ch1
1561 };
1562 }
1564 // Special case: /=. We need to make sure that this is an
1565 // operator and not a regular expression.
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 }
1577 return {
1578 type: Token.Punctuator,
1579 value: "/"
1580 };
1581 }
1583 return null;
1584 },
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;
1603 // Create a comment token object and make sure it
1604 // has all the data JSHint needs to work with special
1605 // comments.
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 || {};
1614 if (opt.isMultiline) {
1615 value += "*/";
1616 }
1618 special.forEach(function (str) {
1619 if (isSpecial) {
1620 return;
1621 }
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 }
1629 if (body.substr(0, str.length) === str) {
1630 isSpecial = true;
1631 label = label + str;
1632 body = body.substr(str.length);
1633 }
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 }
1641 if (!isSpecial) {
1642 return;
1643 }
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 });
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 }
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 });
1676 this.skip(2);
1677 return null;
1678 }
1680 // Comments must start either with // or /*
1681 if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
1682 return null;
1683 }
1685 // One-line comment
1686 if (ch2 === "/") {
1687 this.skip(this.input.length); // Skip to the EOL.
1688 return commentToken("//", rest);
1689 }
1691 var body = "";
1693 /* Multi-line comment */
1694 if (ch2 === "*") {
1695 this.skip(2);
1697 while (this.peek() !== "*" || this.peek(1) !== "/") {
1698 if (this.peek() === "") { // End of Line
1699 body += "\n";
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 });
1710 return commentToken("/*", body, {
1711 isMultiline: true,
1712 isMalformed: true
1713 });
1714 }
1715 } else {
1716 body += this.peek();
1717 this.skip();
1718 }
1719 }
1721 this.skip(2);
1722 return commentToken("/*", body, { isMultiline: true });
1723 }
1724 },
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 ];
1743 if (result && keywords.indexOf(result[0]) >= 0) {
1744 return {
1745 type: Token.Keyword,
1746 value: result[0]
1747 };
1748 }
1750 return null;
1751 },
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;
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.
1772 function isUnicodeLetter(code) {
1773 for (var i = 0; i < unicodeLetterTable.length;) {
1774 if (code < unicodeLetterTable[i++]) {
1775 return false;
1776 }
1778 if (code <= unicodeLetterTable[i++]) {
1779 return true;
1780 }
1781 }
1783 return false;
1784 }
1786 function isHexDigit(str) {
1787 return (/^[0-9a-fA-F]$/).test(str);
1788 }
1790 var readUnicodeEscapeSequence = function () {
1791 /*jshint validthis:true */
1792 index += 1;
1794 if (this.peek(index) !== "u") {
1795 return null;
1796 }
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;
1804 if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
1805 code = parseInt(ch1 + ch2 + ch3 + ch4, 16);
1807 if (isUnicodeLetter(code)) {
1808 index += 5;
1809 return "\\u" + ch1 + ch2 + ch3 + ch4;
1810 }
1812 return null;
1813 }
1815 return null;
1816 }.bind(this);
1818 var getIdentifierStart = function () {
1819 /*jshint validthis:true */
1820 var chr = this.peek(index);
1821 var code = chr.charCodeAt(0);
1823 if (code === 92) {
1824 return readUnicodeEscapeSequence();
1825 }
1827 if (code < 128) {
1828 if (identifierStartTable[code]) {
1829 index += 1;
1830 return chr;
1831 }
1833 return null;
1834 }
1836 if (isUnicodeLetter(code)) {
1837 index += 1;
1838 return chr;
1839 }
1841 return null;
1842 }.bind(this);
1844 var getIdentifierPart = function () {
1845 /*jshint validthis:true */
1846 var chr = this.peek(index);
1847 var code = chr.charCodeAt(0);
1849 if (code === 92) {
1850 return readUnicodeEscapeSequence();
1851 }
1853 if (code < 128) {
1854 if (identifierPartTable[code]) {
1855 index += 1;
1856 return chr;
1857 }
1859 return null;
1860 }
1862 if (isUnicodeLetter(code)) {
1863 index += 1;
1864 return chr;
1865 }
1867 return null;
1868 }.bind(this);
1870 char = getIdentifierStart();
1871 if (char === null) {
1872 return null;
1873 }
1875 id = char;
1876 for (;;) {
1877 char = getIdentifierPart();
1879 if (char === null) {
1880 break;
1881 }
1883 id += char;
1884 }
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 }
1898 return {
1899 type: type,
1900 value: id
1901 };
1902 },
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;
1920 function isDecimalDigit(str) {
1921 return (/^[0-9]$/).test(str);
1922 }
1924 function isOctalDigit(str) {
1925 return (/^[0-7]$/).test(str);
1926 }
1928 function isHexDigit(str) {
1929 return (/^[0-9a-fA-F]$/).test(str);
1930 }
1932 function isIdentifierStart(ch) {
1933 return (ch === "$") || (ch === "_") || (ch === "\\") ||
1934 (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
1935 }
1937 // Numbers must start either with a decimal digit or a point.
1939 if (char !== "." && !isDecimalDigit(char)) {
1940 return null;
1941 }
1943 if (char !== ".") {
1944 value = this.peek(index);
1945 index += 1;
1946 char = this.peek(index);
1948 if (value === "0") {
1949 // Base-16 numbers.
1950 if (char === "x" || char === "X") {
1951 index += 1;
1952 value += char;
1954 while (index < length) {
1955 char = this.peek(index);
1956 if (!isHexDigit(char)) {
1957 break;
1958 }
1959 value += char;
1960 index += 1;
1961 }
1963 if (value.length <= 2) { // 0x
1964 return {
1965 type: Token.NumericLiteral,
1966 value: value,
1967 isMalformed: true
1968 };
1969 }
1971 if (index < length) {
1972 char = this.peek(index);
1973 if (isIdentifierStart(char)) {
1974 return null;
1975 }
1976 }
1978 return {
1979 type: Token.NumericLiteral,
1980 value: value,
1981 base: 16,
1982 isMalformed: false
1983 };
1984 }
1986 // Base-8 numbers.
1987 if (isOctalDigit(char)) {
1988 index += 1;
1989 value += char;
1990 bad = false;
1992 while (index < length) {
1993 char = this.peek(index);
1995 // Numbers like '019' (note the 9) are not valid octals
1996 // but we still parse them and mark as malformed.
1998 if (isDecimalDigit(char)) {
1999 bad = true;
2000 } else if (!isOctalDigit(char)) {
2001 break;
2002 }
2003 value += char;
2004 index += 1;
2005 }
2007 if (index < length) {
2008 char = this.peek(index);
2009 if (isIdentifierStart(char)) {
2010 return null;
2011 }
2012 }
2014 return {
2015 type: Token.NumericLiteral,
2016 value: value,
2017 base: 8,
2018 isMalformed: false
2019 };
2020 }
2022 // Decimal numbers that start with '0' such as '09' are illegal
2023 // but we still parse them and return as malformed.
2025 if (isDecimalDigit(char)) {
2026 index += 1;
2027 value += char;
2028 }
2029 }
2031 while (index < length) {
2032 char = this.peek(index);
2033 if (!isDecimalDigit(char)) {
2034 break;
2035 }
2036 value += char;
2037 index += 1;
2038 }
2039 }
2041 // Decimal digits.
2043 if (char === ".") {
2044 value += char;
2045 index += 1;
2047 while (index < length) {
2048 char = this.peek(index);
2049 if (!isDecimalDigit(char)) {
2050 break;
2051 }
2052 value += char;
2053 index += 1;
2054 }
2055 }
2057 // Exponent part.
2059 if (char === "e" || char === "E") {
2060 value += char;
2061 index += 1;
2062 char = this.peek(index);
2064 if (char === "+" || char === "-") {
2065 value += this.peek(index);
2066 index += 1;
2067 }
2069 char = this.peek(index);
2070 if (isDecimalDigit(char)) {
2071 value += char;
2072 index += 1;
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 }
2087 if (index < length) {
2088 char = this.peek(index);
2089 if (isIdentifierStart(char)) {
2090 return null;
2091 }
2092 }
2094 return {
2095 type: Token.NumericLiteral,
2096 value: value,
2097 base: 10,
2098 isMalformed: !isFinite(value)
2099 };
2100 },
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();
2117 // String must start with a quote.
2118 if (quote !== "\"" && quote !== "'") {
2119 return null;
2120 }
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 !== "\""; });
2129 var value = "";
2130 var startLine = this.line;
2131 var startChar = this.char;
2132 var allowNewLine = false;
2134 this.skip();
2136 while (this.peek() !== quote) {
2137 while (this.peek() === "") { // End Of Line
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.
2146 if (!allowNewLine) {
2147 this.trigger("warning", {
2148 code: "W112",
2149 line: this.line,
2150 character: this.char
2151 });
2152 } else {
2153 allowNewLine = false;
2155 // Otherwise show a warning if multistr option was not set.
2156 // For JSON, show warning no matter what.
2158 this.triggerAsync("warning", {
2159 code: "W043",
2160 line: this.line,
2161 character: this.char
2162 }, checks, function () { return !state.option.multistr; });
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 }
2171 // If we get an EOF inside of an unclosed string, show an
2172 // error and implicitly close it at the EOF point.
2174 if (!this.nextLine()) {
2175 this.trigger("error", {
2176 code: "E029",
2177 line: startLine,
2178 character: startChar
2179 });
2181 return {
2182 type: Token.StringLiteral,
2183 value: value,
2184 isUnclosed: true,
2185 quote: quote
2186 };
2187 }
2188 }
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.
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 }
2205 // Special treatment for some escaped characters.
2207 if (char === "\\") {
2208 this.skip();
2209 char = this.peek();
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";
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; });
2260 char = "\v";
2261 break;
2262 case "x":
2263 var x = parseInt(this.input.substr(1, 2), 16);
2265 this.triggerAsync("warning", {
2266 code: "W114",
2267 line: this.line,
2268 character: this.char,
2269 data: [ "\\x-" ]
2270 }, checks, function () { return state.jsonMode; });
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 }
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 }
2299 value += char;
2300 this.skip(jump);
2301 }
2303 this.skip();
2304 return {
2305 type: Token.StringLiteral,
2306 value: value,
2307 isUnclosed: false,
2308 quote: quote
2309 };
2310 },
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;
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 }
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);
2356 // Regular expressions must start with '/'
2357 if (!this.prereg || char !== "/") {
2358 return null;
2359 }
2361 index += 1;
2362 terminated = false;
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.
2369 while (index < length) {
2370 char = this.peek(index);
2371 value += char;
2372 body += char;
2374 if (isCharSet) {
2375 if (char === "]") {
2376 if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
2377 isCharSet = false;
2378 }
2379 }
2381 if (char === "\\") {
2382 index += 1;
2383 char = this.peek(index);
2384 body += char;
2385 value += char;
2387 scanUnexpectedChars();
2388 }
2390 index += 1;
2391 continue;
2392 }
2394 if (char === "\\") {
2395 index += 1;
2396 char = this.peek(index);
2397 body += char;
2398 value += char;
2400 scanUnexpectedChars();
2402 if (char === "/") {
2403 index += 1;
2404 continue;
2405 }
2407 if (char === "[") {
2408 index += 1;
2409 continue;
2410 }
2411 }
2413 if (char === "[") {
2414 isCharSet = true;
2415 index += 1;
2416 continue;
2417 }
2419 if (char === "/") {
2420 body = body.substr(0, body.length - 1);
2421 terminated = true;
2422 index += 1;
2423 break;
2424 }
2426 index += 1;
2427 }
2429 // A regular expression that was never closed is an
2430 // error from which we cannot recover.
2432 if (!terminated) {
2433 this.trigger("error", {
2434 code: "E015",
2435 line: this.line,
2436 character: this.from
2437 });
2439 return void this.trigger("fatal", {
2440 line: this.line,
2441 from: this.from
2442 });
2443 }
2445 // Parse flags (if any).
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 }
2457 // Check regular expression for correctness.
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 }
2471 return {
2472 type: Token.RegExp,
2473 value: value,
2474 flags: flags,
2475 isMalformed: malformed
2476 };
2477 },
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;
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 }
2496 return at;
2497 },
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 },
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;
2513 // Move to the next non-space character.
2514 var start;
2515 if (/\s/.test(this.peek())) {
2516 start = this.char;
2518 while (/\s/.test(this.peek())) {
2519 this.from += 1;
2520 this.skip();
2521 }
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 }
2530 // Methods that work with multi-line structures and move the
2531 // character pointer.
2533 var match = this.scanComments() ||
2534 this.scanStringLiteral(checks);
2536 if (match) {
2537 return match;
2538 }
2540 // Methods that don't move the character pointer.
2542 match =
2543 this.scanRegExp() ||
2544 this.scanPunctuator() ||
2545 this.scanKeyword() ||
2546 this.scanIdentifier() ||
2547 this.scanNumericLiteral();
2549 if (match) {
2550 this.skip(match.value.length);
2551 return match;
2552 }
2554 // No token could be matched, give up.
2556 return null;
2557 },
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;
2567 if (this.line >= this.lines.length) {
2568 return false;
2569 }
2571 this.input = this.lines[this.line];
2572 this.line += 1;
2573 this.char = 1;
2574 this.from = 1;
2576 char = this.scanMixedSpacesAndTabs();
2577 if (char >= 0) {
2578 this.trigger("warning", { code: "W099", line: this.line, character: char + 1 });
2579 }
2581 this.input = this.input.replace(/\t/g, state.tab);
2582 char = this.scanUnsafeChars();
2584 if (char >= 0) {
2585 this.trigger("warning", { code: "W100", line: this.line, character: char });
2586 }
2588 // If there is a limit on line length, warn when lines get too
2589 // long.
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 }
2595 return true;
2596 },
2598 /*
2599 * This is simply a synonym for nextLine() method with a friendlier
2600 * public name.
2601 */
2602 start: function () {
2603 this.nextLine();
2604 },
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;
2616 function isReserved(token, isProperty) {
2617 if (!token.reserved) {
2618 return false;
2619 }
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 }
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 }
2635 if (isProperty) {
2636 return false;
2637 }
2638 }
2640 return true;
2641 }
2643 // Produce a token object.
2644 var create = function (type, value, isProperty) {
2645 /*jshint validthis:true */
2646 var obj;
2648 if (type !== "(endline)" && type !== "(end)") {
2649 this.prereg = false;
2650 }
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 }
2665 obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
2666 }
2668 if (type === "(identifier)") {
2669 if (value === "return" || value === "case" || value === "typeof") {
2670 this.prereg = true;
2671 }
2673 if (_.has(state.syntax, value)) {
2674 obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
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 }
2683 if (!obj) {
2684 obj = Object.create(state.syntax[type]);
2685 }
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;
2694 if (isProperty && obj.identifier) {
2695 obj.isProperty = isProperty;
2696 }
2698 obj.check = checks.check;
2700 return obj;
2701 }.bind(this);
2703 for (;;) {
2704 if (!this.input.length) {
2705 return create(this.nextLine() ? "(endline)" : "(end)", "");
2706 }
2708 token = this.next(checks);
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 });
2720 this.input = "";
2721 }
2723 continue;
2724 }
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; });
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 });
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 === ".");
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 }
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; });
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 });
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 });
2786 return create("(number)", token.value);
2788 case Token.RegExp:
2789 return create("(regexp)", token.value);
2791 case Token.Comment:
2792 state.tokens.curr.comment = true;
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 }
2806 break;
2808 case "":
2809 break;
2811 default:
2812 return create("(punctuator)", token.value);
2813 }
2814 }
2815 }
2816 };
2818 exports.Lexer = Lexer;
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 */
2854 /*jshint quotmark:double */
2855 /*global console:true */
2856 /*exported console */
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");
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");
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.
2876 var JSHINT = (function () {
2877 "use strict";
2879 var anonname, // The guessed name for anonymous functions.
2880 api, // Extension API
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 },
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
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 },
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 },
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,
3015 // Inverted and renamed, use JSHint name here
3016 eqeqeq : true,
3017 onevar : true,
3018 strict : true
3019 },
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 },
3030 declared, // Globals that were declared using /*global ... */ syntax.
3031 exported, // Variables that are used outside of the current file.
3033 functionicity = [
3034 "closure", "exception", "global", "label",
3035 "outer", "unused", "var"
3036 ],
3038 funct, // The current function
3039 functions, // All of the functions
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
3052 scope, // The current scope
3053 stack,
3054 unuseds,
3055 urls,
3056 warnings,
3058 extraModules = [],
3059 emitter = new events.EventEmitter();
3061 function checkOption(name, t) {
3062 name = name.trim();
3064 if (/^[+-]W\d{3}$/g.test(name)) {
3065 return true;
3066 }
3068 if (valOptions[name] === undefined && boolOptions[name] === undefined) {
3069 if (t.type !== "jslint") {
3070 error("E001", t, name);
3071 return false;
3072 }
3073 }
3075 return true;
3076 }
3078 function isString(obj) {
3079 return Object.prototype.toString.call(obj) === "[object String]";
3080 }
3082 function isIdentifier(tkn, value) {
3083 if (!tkn)
3084 return false;
3086 if (!tkn.identifier || tkn.value !== value)
3087 return false;
3089 return true;
3090 }
3092 function isReserved(token) {
3093 if (!token.reserved) {
3094 return false;
3095 }
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 }
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 }
3111 if (token.isProperty) {
3112 return false;
3113 }
3114 }
3116 return true;
3117 }
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 }
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 }
3135 function updatePredefined() {
3136 Object.keys(JSHINT.blacklist).forEach(function (key) {
3137 delete predefined[key];
3138 });
3139 }
3141 function assume() {
3142 if (state.option.es5) {
3143 warning("I003");
3144 }
3145 if (state.option.couch) {
3146 combine(predefined, vars.couch);
3147 }
3149 if (state.option.rhino) {
3150 combine(predefined, vars.rhino);
3151 }
3153 if (state.option.phantom) {
3154 combine(predefined, vars.phantom);
3155 }
3157 if (state.option.prototypejs) {
3158 combine(predefined, vars.prototypejs);
3159 }
3161 if (state.option.node) {
3162 combine(predefined, vars.node);
3163 }
3165 if (state.option.devel) {
3166 combine(predefined, vars.devel);
3167 }
3169 if (state.option.dojo) {
3170 combine(predefined, vars.dojo);
3171 }
3173 if (state.option.browser) {
3174 combine(predefined, vars.browser);
3175 }
3177 if (state.option.nonstandard) {
3178 combine(predefined, vars.nonstandard);
3179 }
3181 if (state.option.jquery) {
3182 combine(predefined, vars.jquery);
3183 }
3185 if (state.option.mootools) {
3186 combine(predefined, vars.mootools);
3187 }
3189 if (state.option.worker) {
3190 combine(predefined, vars.worker);
3191 }
3193 if (state.option.wsh) {
3194 combine(predefined, vars.wsh);
3195 }
3197 if (state.option.globalstrict && state.option.strict !== false) {
3198 state.option.strict = true;
3199 }
3201 if (state.option.yui) {
3202 combine(predefined, vars.yui);
3203 }
3205 // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
3207 state.option.inMoz = function (strict) {
3208 if (strict) {
3209 return state.option.moz && !state.option.esnext;
3210 }
3211 return state.option.moz;
3212 };
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 };
3221 state.option.inES5 = function (/* strict */) {
3222 return !state.option.es3;
3223 };
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 }
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;
3238 throw {
3239 name: "JSHintError",
3240 line: line,
3241 character: chr,
3242 message: message + " (" + percentage + "% scanned).",
3243 raw: message
3244 };
3245 }
3247 function isundef(scope, code, token, a) {
3248 return JSHINT.undefs.push([scope, code, token, a]);
3249 }
3251 function warning(code, t, a, b, c, d) {
3252 var ch, l, w, msg;
3254 if (/^W\d{3}$/.test(code)) {
3255 if (state.ignored[code])
3256 return;
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 }
3265 t = t || state.tokens.next;
3266 if (t.id === "(end)") { // `~
3267 t = state.tokens.curr;
3268 }
3270 l = t.line || 0;
3271 ch = t.from || 0;
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 };
3287 w.reason = supplant(msg.desc, w);
3288 JSHINT.errors.push(w);
3290 if (state.option.passfail) {
3291 quit("E042", l, ch);
3292 }
3294 warnings += 1;
3295 if (warnings >= state.option.maxerr) {
3296 quit("E043", l, ch);
3297 }
3299 return w;
3300 }
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 }
3309 function error(m, t, a, b, c, d) {
3310 warning(m, t, a, b, c, d);
3311 }
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 }
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 }
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 }
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 }
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 //}
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 {
3368 funct[t] = type;
3370 if (tkn) {
3371 funct["(tokens)"][t] = tkn;
3372 }
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 }
3384 delete implied[t];
3385 }
3386 } else {
3387 scope[t] = funct;
3388 }
3389 }
3390 }
3392 function doOption() {
3393 var nt = state.tokens.next;
3394 var body = nt.body.split(",").map(function (s) { return s.trim(); });
3395 var predef = {};
3397 if (nt.type === "globals") {
3398 body.forEach(function (g) {
3399 g = g.split(":");
3400 var key = g[0];
3401 var val = g[1];
3403 if (key.charAt(0) === "-") {
3404 key = key.slice(1);
3405 val = false;
3407 JSHINT.blacklist[key] = key;
3408 updatePredefined();
3409 } else {
3410 predef[key] = (val === "true");
3411 }
3412 });
3414 combine(predefined, predef);
3416 for (var key in predef) {
3417 if (_.has(predef, key)) {
3418 declared[key] = nt;
3419 }
3420 }
3421 }
3423 if (nt.type === "exported") {
3424 body.forEach(function (e) {
3425 exported[e] = true;
3426 });
3427 }
3429 if (nt.type === "members") {
3430 membersOnly = membersOnly || {};
3432 body.forEach(function (m) {
3433 var ch1 = m.charAt(0);
3434 var ch2 = m.charAt(m.length - 1);
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 }
3449 membersOnly[m] = false;
3450 });
3451 }
3453 var numvals = [
3454 "maxstatements",
3455 "maxparams",
3456 "maxdepth",
3457 "maxcomplexity",
3458 "maxerr",
3459 "maxlen",
3460 "indent"
3461 ];
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();
3469 if (!checkOption(key, nt)) {
3470 return;
3471 }
3473 if (numvals.indexOf(key) >= 0) {
3475 // GH988 - numeric options can be disabled by setting them to `false`
3476 if (val !== "false") {
3477 val = +val;
3479 if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
3480 error("E032", nt, g[1].trim());
3481 return;
3482 }
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 }
3496 return;
3497 }
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 }
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 }
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 }
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 }
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 }
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");
3577 if (invertedOptions[tn] !== undefined) {
3578 state.option[tn] = !state.option[tn];
3579 }
3580 } else {
3581 state.option[key] = (val === "true");
3582 }
3584 if (key === "newcap") {
3585 state.option["(explicitNewcap)"] = true;
3586 }
3587 return;
3588 }
3590 error("E002", nt);
3591 });
3593 assume();
3594 }
3595 }
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 = ...
3603 function peek(p) {
3604 var i = p || 0, j = 0, t;
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 }
3616 // Produce the next token. It looks for programming errors.
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 }
3637 if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
3638 anonname = state.tokens.curr.value;
3639 }
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 }
3653 state.tokens.prev = state.tokens.curr;
3654 state.tokens.curr = state.tokens.next;
3655 for (;;) {
3656 state.tokens.next = lookahead.shift() || lex.token();
3658 if (!state.tokens.next) { // No more tokens left, give up
3659 quit("E041", state.tokens.curr.line);
3660 }
3662 if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
3663 return;
3664 }
3666 if (state.tokens.next.check) {
3667 state.tokens.next.check();
3668 }
3670 if (state.tokens.next.isSpecial) {
3671 doOption();
3672 } else {
3673 if (state.tokens.next.id !== "(endline)") {
3674 break;
3675 }
3676 }
3677 }
3678 }
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.
3686 // .nud Null denotation
3687 // .fud First null denotation
3688 // .led Left denotation
3689 // lbp Left binding power
3690 // rbp Right binding power
3692 // They are elements of the parsing method called Top Down Operator Precedence.
3694 function expression(rbp, initial) {
3695 var left, isArray = false, isObject = false, isLetExpr = false;
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 }
3711 if (state.tokens.next.id === "(end)")
3712 error("E006", state.tokens.curr);
3714 advance();
3716 if (initial) {
3717 anonname = "anonymous";
3718 funct["(verb)"] = state.tokens.curr.value;
3719 }
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 }
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";
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 }
3755 advance();
3757 if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
3758 warning("W009", state.tokens.curr);
3759 }
3761 if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
3762 warning("W010", state.tokens.curr);
3763 }
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 }
3779 // Functions for conformance of style.
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 }
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 }
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 }
3810 function nonadjacent(left, right) {
3811 if (state.option.white) {
3812 left = left || state.tokens.curr;
3813 right = right || state.tokens.next;
3815 if (left.value === ";" && right.value === ";") {
3816 return;
3817 }
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 }
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 }
3841 function indentation(bias) {
3842 if (!state.option.white && !state.option["(explicitIndent)"]) {
3843 return;
3844 }
3846 if (state.tokens.next.id === "(end)") {
3847 return;
3848 }
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 }
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 }
3864 function comma(opts) {
3865 opts = opts || {};
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 }
3882 advance(",");
3883 }
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.
3889 if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") {
3890 nonadjacent(state.tokens.curr, state.tokens.next);
3891 }
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 }
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 }
3931 /* falls through */
3932 case ")":
3933 error("E024", state.tokens.next, state.tokens.next.value);
3934 return false;
3935 }
3936 }
3937 return true;
3938 }
3940 // Functional constructors for making the symbols that will be inherited by
3941 // tokens.
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 }
3955 function delim(s) {
3956 return symbol(s, 0);
3957 }
3959 function stmt(s, f) {
3960 var x = delim(s);
3961 x.identifier = x.reserved = true;
3962 x.fud = f;
3963 return x;
3964 }
3966 function blockstmt(s, f) {
3967 var x = stmt(s, f);
3968 x.block = true;
3969 return x;
3970 }
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 }
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 }
3999 function type(s, f) {
4000 var x = delim(s);
4001 x.type = s;
4002 x.nud = f;
4003 return x;
4004 }
4006 function reserve(name, func) {
4007 var x = type(name, func);
4008 x.identifier = true;
4009 x.reserved = true;
4010 return x;
4011 }
4013 function FutureReservedWord(name, meta) {
4014 var x = type(name, (meta && meta.nud) || function () {
4015 return this;
4016 });
4018 meta = meta || {};
4019 meta.isFutureReservedWord = true;
4021 x.value = name;
4022 x.identifier = true;
4023 x.reserved = true;
4024 x.meta = meta;
4026 return x;
4027 }
4029 function reservevar(s, v) {
4030 return reserve(s, function () {
4031 if (typeof v === "function") {
4032 v(this);
4033 }
4034 return this;
4035 });
4036 }
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 }
4061 function application(s) {
4062 var x = symbol(s, 42);
4064 x.led = function (left) {
4065 if (!state.option.inESNext()) {
4066 warning("W104", state.tokens.curr, "arrow function syntax (=>)");
4067 }
4069 nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
4070 nonadjacent(state.tokens.curr, state.tokens.next);
4072 this.left = left;
4073 this.right = doFunction(undefined, undefined, false, left);
4074 return this;
4075 };
4076 return x;
4077 }
4079 function relation(s, f) {
4080 var x = symbol(s, 100);
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);
4087 if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
4088 warning("W019", this);
4089 } else if (f) {
4090 f.apply(this, [left, right]);
4091 }
4093 if (!left || !right) {
4094 quit("E041", state.tokens.curr.line);
4095 }
4097 if (left.id === "!") {
4098 warning("W018", left, "!");
4099 }
4101 if (right.id === "!") {
4102 warning("W018", right, "!");
4103 }
4105 this.left = left;
4106 this.right = right;
4107 return this;
4108 };
4109 return x;
4110 }
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 }
4122 function assignop(s) {
4123 symbol(s, 20).exps = true;
4125 return infix(s, function (left, that) {
4126 that.left = left;
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 }
4136 if (funct[left.value] === "const") {
4137 error("E013", left, left.value);
4138 }
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 }
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 }
4171 if (left === state.syntax["function"]) {
4172 warning("W023", state.tokens.curr);
4173 }
4174 }
4176 error("E031", that);
4177 }, 20);
4178 }
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 }
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 }
4220 function suffix(s) {
4221 var x = symbol(s, 150);
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 }
4230 this.left = left;
4231 return this;
4232 };
4233 return x;
4234 }
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
4240 function optionalidentifier(fnparam, prop) {
4241 if (!state.tokens.next.identifier) {
4242 return;
4243 }
4245 advance();
4247 var curr = state.tokens.curr;
4248 var meta = curr.meta || {};
4249 var val = state.tokens.curr.value;
4251 if (!isReserved(curr)) {
4252 return val;
4253 }
4255 if (prop) {
4256 if (state.option.inES5() || meta.isFutureReservedWord) {
4257 return val;
4258 }
4259 }
4261 if (fnparam && val === "undefined") {
4262 return val;
4263 }
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 }
4272 warning("W024", state.tokens.curr, state.tokens.curr.id);
4273 return val;
4274 }
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 }
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 }
4308 warning("W026", t);
4309 break;
4310 }
4312 warning("W027", t, t.value, s);
4313 break;
4314 }
4315 i += 1;
4316 }
4317 }
4320 function statement(noindent) {
4321 var values;
4322 var i = indent, r, s = scope, t = state.tokens.next;
4324 if (t.id === ";") {
4325 advance(";");
4326 return;
4327 }
4329 // Is this a labelled statement?
4330 var res = isReserved(t);
4332 // We're being more tolerant here: if someone uses
4333 // a FutureReservedWord as a label, we warn but proceed
4334 // anyway.
4336 if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
4337 warning("W024", t, t.id);
4338 res = false;
4339 }
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");
4363 if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
4364 warning("W028", state.tokens.next, t.value, state.tokens.next.value);
4365 }
4367 state.tokens.next.label = t.value;
4368 t = state.tokens.next;
4369 }
4371 // Is it a lonely block?
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 }
4386 // Parse the statement.
4388 if (!noindent) {
4389 indentation();
4390 }
4391 r = expression(0, true);
4393 // Look for the final semicolon.
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 }
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 }
4419 // Restore the indentation.
4421 indent = i;
4422 scope = s;
4423 return r;
4424 }
4427 function statements(startLine) {
4428 var a = [], p;
4430 while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
4431 if (state.tokens.next.id === ";") {
4432 p = peek();
4434 if (!p || (p.id !== "(" && p.id !== "[")) {
4435 warning("W032");
4436 }
4438 advance(";");
4439 } else {
4440 a.push(statement(startLine === state.tokens.next.line));
4441 }
4442 }
4443 return a;
4444 }
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;
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)");
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 }
4482 indentation();
4483 advance();
4484 if (state.directive[state.tokens.curr.value]) {
4485 warning("W034", state.tokens.curr, state.tokens.curr.value);
4486 }
4488 if (state.tokens.curr.value === "use strict") {
4489 if (!state.option["(explicitNewcap)"])
4490 state.option.newcap = true;
4491 state.option.undef = true;
4492 }
4494 // there's no directive negation, so always set to true
4495 state.directive[state.tokens.curr.value] = true;
4497 if (p.id === ";") {
4498 advance(";");
4499 }
4500 continue;
4501 }
4502 break;
4503 }
4504 }
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;
4527 inblock = ordinary;
4529 if (!ordinary || !state.option.funcscope)
4530 scope = Object.create(scope);
4532 nonadjacent(state.tokens.curr, state.tokens.next);
4533 t = state.tokens.next;
4535 var metrics = funct["(metrics)"];
4536 metrics.nestedBlockDepth += 1;
4537 metrics.verifyMaxNestedBlockDepthPerFunction();
4539 if (state.tokens.next.id === "{") {
4540 advance("{");
4542 // create a new block scope
4543 funct["(blockscope)"].stack();
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 }
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();
4561 if (state.option.strict && funct["(context)"]["(global)"]) {
4562 if (!m["use strict"] && !state.directive["use strict"]) {
4563 warning("E007");
4564 }
4565 }
4566 }
4568 a = statements(line);
4570 metrics.statementCount += a.length;
4572 if (isfunc) {
4573 state.directive = m;
4574 }
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);
4585 funct["(blockscope)"].unstack();
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 }
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);
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 {
4614 // check to avoid let declaration not within a block
4615 funct["(nolet)"] = true;
4617 if (!stmt || state.option.curly) {
4618 warning("W116", state.tokens.next, "{", state.tokens.next.value);
4619 }
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;
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;
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 }
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 }
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 }
4661 if (!a) {
4662 a = [line];
4663 implied[name] = a;
4664 } else if (a[a.length - 1] !== line) {
4665 a.push(line);
4666 }
4667 }
4670 // Build the syntax table by declaring the syntactic elements of the language.
4672 type("(number)", function () {
4673 return this;
4674 });
4676 type("(string)", function () {
4677 return this;
4678 });
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;
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 }
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.
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 === "["))) {
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.
4745 if (!funct["(comparray)"].check(v)) {
4746 isundef(funct, "W117", state.tokens.curr, v);
4747 }
4748 }
4749 }
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.
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 === "["))) {
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 };
4821 type("(regexp)", function () {
4822 return this;
4823 });
4825 // ECMAScript parser
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("#");
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");
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);
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);
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");
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);
4918 return this;
4919 });
4920 relation("===");
4921 relation("!=", function (left, right) {
4922 var eqnull = state.option.eqnull &&
4923 (left.value === "null" || right.value === "null");
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);
4989 suffix("++", "postinc");
4990 prefix("++", "preinc");
4991 state.syntax["++"].exps = true;
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;
5005 prefix("~", function () {
5006 if (state.option.bitwise) {
5007 warning("W052", this, "~");
5008 }
5009 expression(150);
5010 return this;
5011 });
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 });
5024 prefix("!", function () {
5025 this.right = expression(150);
5026 this.arity = "unary";
5028 if (!this.right) { // '!' followed by nothing? Give up.
5029 quit("E041", this.line || 0);
5030 }
5032 if (bang[this.right.id] === true) {
5033 warning("W018", this, "!");
5034 }
5035 return this;
5036 });
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;
5086 prefix("void").exps = true;
5088 infix(".", function (left, that) {
5089 adjacent(state.tokens.prev, state.tokens.curr);
5090 nobreak();
5091 var m = identifier(false, true);
5093 if (typeof m === "string") {
5094 countMember(m);
5095 }
5097 that.left = left;
5098 that.right = m;
5100 if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
5101 warning("W001");
5102 }
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 }
5114 if (!state.option.evil && (m === "eval" || m === "execScript")) {
5115 warning("W061");
5116 }
5118 return that;
5119 }, 160, true);
5121 infix("(", function (left, that) {
5122 if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
5123 nobreak(state.tokens.prev, state.tokens.curr);
5124 }
5126 nospace();
5127 if (state.option.immed && left && !left.immed && left.id === "function") {
5128 warning("W062");
5129 }
5131 var n = 0;
5132 var p = [];
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 }
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 }
5159 advance(")");
5160 nospace(state.tokens.prev, state.tokens.curr);
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);
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);
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 }
5197 that.left = left;
5198 return that;
5199 }, 155, true).exps = true;
5201 prefix("(", function () {
5202 nospace();
5203 var bracket, brackets = [];
5204 var pn, pn1, i = 0;
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)");
5213 if (state.tokens.next.id === "function") {
5214 state.tokens.next.immed = true;
5215 }
5217 var exprs = [];
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 }
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 }
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 });
5260 application("=>");
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 }
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);
5281 if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
5282 warning("W001");
5283 }
5285 nospace(state.tokens.prev, state.tokens.curr);
5286 that.left = left;
5287 that.right = e;
5288 return that;
5289 }, 160, true);
5291 function comprehensiveArrayExpression() {
5292 var res = {};
5293 res.exps = true;
5294 funct["(comparray)"].stack();
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 }
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);
5370 function property_name() {
5371 var id = optionalidentifier(false, true);
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 }
5383 if (id === "hasOwnProperty") {
5384 warning("W001");
5385 }
5387 return id;
5388 }
5391 function functionparams(parsed) {
5392 var curr, next;
5393 var params = [];
5394 var ident;
5395 var tokens = [];
5396 var t;
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 }
5428 next = state.tokens.next;
5430 advance("(");
5431 nospace();
5433 if (state.tokens.next.id === ")") {
5434 advance(")");
5435 return;
5436 }
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 }
5473 function doFunction(name, statement, generator, fatarrowparams) {
5474 var f;
5475 var oldOption = state.option;
5476 var oldIgnored = state.ignored;
5477 var oldScope = scope;
5479 state.option = Object.create(state.option);
5480 state.ignored = Object.create(state.ignored);
5481 scope = Object.create(scope);
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 };
5498 if (generator) {
5499 funct["(generator)"] = true;
5500 }
5502 f = funct;
5503 state.tokens.curr.funct = funct;
5505 functions.push(funct);
5507 if (name) {
5508 addlabel(name, "function");
5509 }
5511 funct["(params)"] = functionparams(fatarrowparams);
5513 funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
5515 block(false, true, true, fatarrowparams ? true:false);
5517 if (generator && funct["(generator)"] !== "yielded") {
5518 error("E047", state.tokens.curr);
5519 }
5521 funct["(metrics)"].verifyMaxStatementsPerFunction();
5522 funct["(metrics)"].verifyMaxComplexityPerFunction();
5523 funct["(unusedOption)"] = state.option.unused;
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)"];
5532 return f;
5533 }
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 },
5547 verifyMaxParametersPerFunction: function (params) {
5548 params = params || [];
5550 if (state.option.maxparams && params.length > state.option.maxparams) {
5551 warning("W072", functionStartToken, params.length);
5552 }
5553 },
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 },
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 }
5573 function increaseComplexityCount() {
5574 funct["(metrics)"].ComplexityCount += 1;
5575 }
5577 // Parse assignments that were found instead of conditionals.
5578 // For example: if (a = 1) { ... }
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 }
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 = "";
5609 function saveProperty(name, tkn) {
5610 if (props[name] && _.has(props, name))
5611 warning("W075", state.tokens.next, i);
5612 else
5613 props[name] = {};
5615 props[name].basic = true;
5616 props[name].basictkn = tkn;
5617 }
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 }
5627 props[name].setter = true;
5628 props[name].setterToken = tkn;
5629 }
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 }
5639 props[name].getter = true;
5640 props[name].getterToken = state.tokens.curr;
5641 }
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 }
5651 for (;;) {
5652 if (state.tokens.next.id === "}") {
5653 break;
5654 }
5656 if (b) {
5657 indentation();
5658 }
5660 if (isclassdef && state.tokens.next.value === "static") {
5661 advance("static");
5662 tag = "static ";
5663 }
5665 if (state.tokens.next.value === "get" && peek().id !== ":") {
5666 advance("get");
5668 if (!state.option.inES5(!isclassdef)) {
5669 error("E034");
5670 }
5672 i = property_name();
5673 if (!i) {
5674 error("E035");
5675 }
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 }
5683 saveGetter(tag + i);
5684 t = state.tokens.next;
5685 adjacent(state.tokens.curr, state.tokens.next);
5686 f = doFunction();
5687 p = f["(params)"];
5689 if (p) {
5690 warning("W076", t, p[0], i);
5691 }
5693 adjacent(state.tokens.curr, state.tokens.next);
5694 } else if (state.tokens.next.value === "set" && peek().id !== ":") {
5695 advance("set");
5697 if (!state.option.inES5(!isclassdef)) {
5698 error("E034");
5699 }
5701 i = property_name();
5702 if (!i) {
5703 error("E035");
5704 }
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 }
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)"];
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);
5733 if (typeof i !== "string") {
5734 break;
5735 }
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 }
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);
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("{")));
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 }
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;
5864 if (!state.option.inESNext()) {
5865 warning("W104", state.tokens.curr, "const");
5866 }
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 }
5896 this.first = this.first.concat(names);
5898 if (state.tokens.next.id !== "=") {
5899 warning("E012", state.tokens.curr, state.tokens.curr.value);
5900 }
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 }
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;
5933 if (funct["(onevar)"] && state.option.onevar) {
5934 warning("W081");
5935 } else if (!funct["(global)"]) {
5936 funct["(onevar)"] = true;
5937 }
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 }
5967 this.first = this.first.concat(names);
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 }
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;
5998 if (!state.option.inESNext()) {
5999 warning("W104", state.tokens.curr, "let");
6000 }
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 }
6013 if (funct["(onevar)"] && state.option.onevar) {
6014 warning("W081");
6015 } else if (!funct["(global)"]) {
6016 funct["(onevar)"] = true;
6017 }
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 }
6047 this.first = this.first.concat(names);
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 }
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 }
6079 return this;
6080 });
6081 letstatement.exps = true;
6083 blockstmt("class", function () {
6084 return classdef.call(this, true);
6085 });
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 }
6104 function classtail(c) {
6105 var strictness = state.directive["use strict"];
6107 // ClassHeritage(opt)
6108 if (state.tokens.next.value === "extends") {
6109 advance("extends");
6110 c.heritage = expression(10);
6111 }
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 }
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);
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);
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 });
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 });
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 });
6195 blockstmt("try", function () {
6196 var b;
6198 function doCatch() {
6199 var oldScope = scope;
6200 var e;
6202 advance("catch");
6203 nonadjacent(state.tokens.curr, state.tokens.next);
6204 advance("(");
6206 scope = Object.create(oldScope);
6208 e = state.tokens.next.value;
6209 if (state.tokens.next.type !== "(identifier)") {
6210 e = null;
6211 warning("E030", state.tokens.next, e);
6212 }
6214 advance();
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 };
6232 if (e) {
6233 addlabel(e, "exception");
6234 }
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 }
6244 advance(")");
6246 state.tokens.curr.funct = funct;
6247 functions.push(funct);
6249 block(false);
6251 scope = oldScope;
6253 funct["(last)"] = state.tokens.curr.line;
6254 funct["(lastcharacter)"] = state.tokens.curr.character;
6255 funct = funct["(context)"];
6256 }
6258 block(false);
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 }
6269 if (state.tokens.next.id === "finally") {
6270 advance("finally");
6271 block(false);
6272 return;
6273 }
6275 if (!b) {
6276 error("E021", state.tokens.next, "catch", state.tokens.next.value);
6277 }
6279 return this;
6280 });
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;
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 }
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);
6315 return this;
6316 });
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 = [];
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;
6423 stmt("debugger", function () {
6424 if (!state.option.debug) {
6425 warning("W087");
6426 }
6427 return this;
6428 }).exps = true;
6430 (function () {
6431 var x = stmt("do", function () {
6432 funct["(breakage)"] += 1;
6433 funct["(loopage)"] += 1;
6434 increaseComplexityCount();
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 }());
6453 blockstmt("for", function () {
6454 var s, t = state.tokens.next;
6455 var letscope = false;
6456 var foreachtok = null;
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 }
6466 funct["(breakage)"] += 1;
6467 funct["(loopage)"] += 1;
6468 increaseComplexityCount();
6469 advance("(");
6470 nonadjacent(this, t);
6471 nospace();
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)");
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;
6569 }
6570 // unstack loop blockscope
6571 if (letscope) {
6572 funct["(blockscope)"].unstack();
6573 }
6574 return this;
6575 }).labelled = true;
6578 stmt("break", function () {
6579 var v = state.tokens.next.value;
6581 if (funct["(breakage)"] === 0)
6582 warning("W052", state.tokens.next, this.value);
6584 if (!state.option.asi)
6585 nolinebreak(this);
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;
6603 stmt("continue", function () {
6604 var v = state.tokens.next.value;
6606 if (funct["(breakage)"] === 0)
6607 warning("W052", state.tokens.next, this.value);
6609 if (!state.option.asi)
6610 nolinebreak(this);
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;
6630 stmt("return", function () {
6631 if (this.line === state.tokens.next.line) {
6632 if (state.tokens.next.id === "(regexp)")
6633 warning("W092");
6635 if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
6636 nonadjacent(state.tokens.curr, state.tokens.next);
6637 this.first = expression(0);
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;
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");
6665 if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
6666 nonadjacent(state.tokens.curr, state.tokens.next);
6667 this.first = expression(0);
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;
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;
6688 // Future Reserved Words
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");
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.
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 };
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
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 }
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
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 };
6872 // Parse JSON
6874 function jsonValue() {
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 }
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 }
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 }
6962 var blockScope = function () {
6963 var _current = {};
6964 var _variables = [_current];
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 }
6979 return {
6980 stack: function () {
6981 _current = {};
6982 _variables.push(_current);
6983 },
6985 unstack: function () {
6986 _checkBlockLabels();
6987 _variables.splice(_variables.length - 1, 1);
6988 _current = _.last(_variables);
6989 },
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 },
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 };
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 = {};
7018 state.reset();
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 }
7030 predefined = Object.create(null);
7031 combine(predefined, vars.ecmaIdentifiers);
7032 combine(predefined, vars.reservedVars);
7034 combine(predefined, g || {});
7036 declared = Object.create(null);
7037 exported = Object.create(null);
7039 if (o) {
7040 a = o.predef;
7041 if (a) {
7042 if (!Array.isArray(a) && typeof a === "object") {
7043 a = Object.keys(a);
7044 }
7046 a.forEach(function (item) {
7047 var slice, prop;
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 }
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]];
7066 if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
7067 newOptionObj["(explicitNewcap)"] = true;
7069 if (optionKeys[x] === "indent")
7070 newOptionObj["(explicitIndent)"] = o[optionKeys[x]] === false ? false : true;
7071 }
7072 }
7073 }
7075 state.option = newOptionObj;
7076 state.ignored = newIgnoredObj;
7078 state.option.indent = state.option.indent || 4;
7079 state.option.maxerr = state.option.maxerr || 50;
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 = [];
7106 if (!isString(s) && !Array.isArray(s)) {
7107 errorAt("E004", 0);
7108 return false;
7109 }
7111 api = {
7112 get isJSON() {
7113 return state.jsonMode;
7114 },
7116 getOption: function (name) {
7117 return state.option[name] || null;
7118 },
7120 getCache: function (name) {
7121 return state.cache[name];
7122 },
7124 setCache: function (name, value) {
7125 state.cache[name] = value;
7126 },
7128 warn: function (code, data) {
7129 warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));
7130 },
7132 on: function (names, listener) {
7133 names.split(" ").forEach(function (name) {
7134 emitter.on(name, listener);
7135 }.bind(this));
7136 }
7137 };
7139 emitter.removeAllListeners();
7140 (extraModules || []).forEach(function (func) {
7141 func(api);
7142 });
7144 state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
7146 lex = new Lexer(s);
7148 lex.on("warning", function (ev) {
7149 warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
7150 });
7152 lex.on("error", function (ev) {
7153 errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
7154 });
7156 lex.on("fatal", function (ev) {
7157 quit("E041", ev.line, ev.from);
7158 });
7160 lex.on("Identifier", function (ev) {
7161 emitter.emit("Identifier", ev);
7162 });
7164 lex.on("String", function (ev) {
7165 emitter.emit("String", ev);
7166 });
7168 lex.on("Number", function (ev) {
7169 emitter.emit("Number", ev);
7170 });
7172 lex.start();
7174 // Check options
7175 for (var name in o) {
7176 if (_.has(o, name)) {
7177 checkOption(name, state.tokens.curr);
7178 }
7179 }
7181 assume();
7183 // combine the passed globals after we've assumed all our options
7184 combine(predefined, g || {});
7186 //reset values
7187 comma.first = true;
7189 try {
7190 advance();
7191 switch (state.tokens.next.id) {
7192 case "{":
7193 case "[":
7194 destructuringAssignOrJsonValue();
7195 break;
7196 default:
7197 directives();
7199 if (state.directive["use strict"]) {
7200 if (!state.option.globalstrict && !state.option.node) {
7201 warning("W097", state.tokens.prev);
7202 }
7203 }
7205 statements();
7206 }
7207 advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined);
7208 funct["(blockscope)"].unstack();
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.
7219 if (context[name] === "unused")
7220 context[name] = "var";
7221 else if (context[name] === "unction")
7222 context[name] = "closure";
7224 return true;
7225 }
7227 context = context["(context)"];
7228 } while (context);
7230 return false;
7231 };
7233 var clearImplied = function (name, line) {
7234 if (!implied[name])
7235 return;
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 }
7243 if (newImplied.length === 0)
7244 delete implied[name];
7245 else
7246 implied[name] = newImplied;
7247 };
7249 var warnUnused = function (name, tkn, type, unused_opt) {
7250 var line = tkn.line;
7251 var chr = tkn.character;
7253 if (unused_opt === undefined) {
7254 unused_opt = state.option.unused;
7255 }
7257 if (unused_opt === true) {
7258 unused_opt = "last-param";
7259 }
7261 var warnable_types = {
7262 "vars": ["var"],
7263 "last-param": ["var", "param"],
7264 "strict": ["var", "param", "last-param"]
7265 };
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 }
7273 unuseds.push({
7274 name: name,
7275 line: line,
7276 character: chr
7277 });
7278 };
7280 var checkUnused = function (func, key) {
7281 var type = func[key];
7282 var tkn = func["(tokens)"][key];
7284 if (key.charAt(0) === "(")
7285 return;
7287 if (type !== "unused" && type !== "unction")
7288 return;
7290 // Params are checked separately from other variables.
7291 if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
7292 return;
7294 // Variable is in global scope and defined as exported.
7295 if (func["(global)"] && _.has(exported, key)) {
7296 return;
7297 }
7299 warnUnused(key, tkn, "var");
7300 };
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);
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 }
7313 functions.forEach(function (func) {
7314 if (func["(unusedOption)"] === false) {
7315 return;
7316 }
7318 for (var key in func) {
7319 if (_.has(func, key)) {
7320 checkUnused(func, key);
7321 }
7322 }
7324 if (!func["(params)"])
7325 return;
7327 var params = func["(params)"].slice();
7328 var param = params.pop();
7329 var type, unused_opt;
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;
7336 // 'undefined' is a special case for (function (window, undefined) { ... })();
7337 // patterns.
7339 if (param === "undefined")
7340 return;
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 }
7348 param = params.pop();
7349 }
7350 });
7352 for (var key in declared) {
7353 if (_.has(declared, key) && !_.has(global, key)) {
7354 warnUnused(key, declared[key], "var");
7355 }
7356 }
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 }
7373 // Loop over the listed "internals", and check them as well.
7375 if (JSHINT.scope === "(main)") {
7376 o = o || {};
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 }
7385 return JSHINT.errors.length === 0;
7386 };
7388 // Modules.
7389 itself.addModule = function (func) {
7390 extraModules.push(func);
7391 };
7393 itself.addModule(style.register);
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;
7405 if (itself.errors.length) {
7406 data.errors = itself.errors;
7407 }
7409 if (state.jsonMode) {
7410 data.json = true;
7411 }
7413 for (n in implied) {
7414 if (_.has(implied, n)) {
7415 implieds.push({
7416 name: n,
7417 line: implied[n]
7418 });
7419 }
7420 }
7422 if (implieds.length > 0) {
7423 data.implieds = implieds;
7424 }
7426 if (urls.length > 0) {
7427 data.urls = urls;
7428 }
7430 globals = Object.keys(scope);
7431 if (globals.length > 0) {
7432 data.globals = globals;
7433 }
7435 for (i = 1; i < functions.length; i += 1) {
7436 f = functions[i];
7437 fu = {};
7439 for (j = 0; j < functionicity.length; j += 1) {
7440 fu[functionicity[j]] = [];
7441 }
7443 for (j = 0; j < functionicity.length; j += 1) {
7444 if (fu[functionicity[j]].length === 0) {
7445 delete fu[functionicity[j]];
7446 }
7447 }
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 }
7458 if (unuseds.length > 0) {
7459 data.unused = unuseds;
7460 }
7462 members = [];
7463 for (n in member) {
7464 if (typeof member[n] === "number") {
7465 data.member = member;
7466 break;
7467 }
7468 }
7470 return data;
7471 };
7473 itself.jshint = itself;
7475 return itself;
7476 }());
7478 // Make JSHINT a Node module, if possible.
7479 if (typeof exports === "object" && exports) {
7480 exports.JSHINT = JSHINT;
7481 }
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";
7487 var _ = require("underscore");
7489 var errors = {
7490 // JSHint options
7491 E001: "Bad option: '{a}'.",
7492 E002: "Bad option value.",
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.",
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.",
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.",
7511 // Regular expressions
7512 E014: "A regular expression literal can be confused with '/='.",
7513 E015: "Unclosed regular expression.",
7514 E016: "Invalid regular expression.",
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.",
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 };
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 };
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 };
7685 exports.errors = {};
7686 exports.warnings = {};
7687 exports.info = {};
7689 _.each(errors, function (desc, code) {
7690 exports.errors[code] = { code: code, desc: desc };
7691 });
7693 _.each(warnings, function (desc, code) {
7694 exports.warnings[code] = { code: code, desc: desc };
7695 });
7697 _.each(info, function (desc, code) {
7698 exports.info[code] = { code: code, desc: desc };
7699 });
7701 })()
7702 },{"underscore":11}],8:[function(require,module,exports){
7703 var events = require('events');
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]'};
7710 exports.print = function () {};
7711 exports.puts = function () {};
7712 exports.debug = function() {};
7714 exports.inspect = function(obj, showHidden, depth, colors) {
7715 var seen = [];
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] };
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];
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 }
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 }
7767 // Primitive types cannot have properties
7768 switch (typeof value) {
7769 case 'undefined':
7770 return stylize('undefined', 'undefined');
7772 case 'string':
7773 var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
7774 .replace(/'/g, "\\'")
7775 .replace(/\\"/g, '"') + '\'';
7776 return stylize(simple, 'string');
7778 case 'number':
7779 return stylize('' + value, 'number');
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 }
7789 // Look up the keys of the object.
7790 var visible_keys = Object_keys(value);
7791 var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;
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 }
7803 // Dates without properties can be shortcutted
7804 if (isDate(value) && keys.length === 0) {
7805 return stylize(value.toUTCString(), 'date');
7806 }
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 }
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 }
7826 // Make dates with properties first say the date
7827 if (isDate(value)) {
7828 base = ' ' + value.toUTCString();
7829 }
7831 if (keys.length === 0) {
7832 return braces[0] + base + braces[1];
7833 }
7835 if (recurseTimes < 0) {
7836 if (isRegExp(value)) {
7837 return stylize('' + value, 'regexp');
7838 } else {
7839 return stylize('[Object]', 'special');
7840 }
7841 }
7843 seen.push(value);
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 }
7901 return name + ': ' + str;
7902 });
7904 seen.pop();
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);
7913 if (length > 50) {
7914 output = braces[0] +
7915 (base === '' ? '' : base + '\n ') +
7916 ' ' +
7917 output.join(',\n ') +
7918 ' ' +
7919 braces[1];
7921 } else {
7922 output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
7923 }
7925 return output;
7926 }
7927 return format(obj, (typeof depth === 'undefined' ? 2 : depth));
7928 };
7931 function isArray(ar) {
7932 return ar instanceof Array ||
7933 Array.isArray(ar) ||
7934 (ar && ar !== Object.prototype && isArray(ar.__proto__));
7935 }
7938 function isRegExp(re) {
7939 return re instanceof RegExp ||
7940 (typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]');
7941 }
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 }
7952 function pad(n) {
7953 return n < 10 ? '0' + n.toString(10) : n.toString(10);
7954 }
7956 var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
7957 'Oct', 'Nov', 'Dec'];
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 }
7968 exports.log = function (msg) {};
7970 exports.pump = null;
7972 var Object_keys = Object.keys || function (obj) {
7973 var res = [];
7974 for (var key in obj) res.push(key);
7975 return res;
7976 };
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 };
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 };
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 };
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 }
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 };
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;
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 }
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.
8076 var assert = module.exports = ok;
8078 // 2. The AssertionError is defined in assert.
8079 // new assert.AssertionError({ message: message,
8080 // actual: actual,
8081 // expected: expected })
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;
8091 if (Error.captureStackTrace) {
8092 Error.captureStackTrace(this, stackStartFunction);
8093 }
8094 };
8095 util.inherits(assert.AssertionError, Error);
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 }
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 }
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 };
8131 // assert.AssertionError instanceof Error
8133 assert.AssertionError.__proto__ = Error.prototype;
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.
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.
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 }
8156 // EXTENSION! allows for well behaved errors defined elsewhere.
8157 assert.fail = fail;
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);.
8166 function ok(value, message) {
8167 if (!!!value) fail(value, true, message, '==', assert.ok);
8168 }
8169 assert.ok = ok;
8171 // 5. The equality assertion tests shallow, coercive equality with
8172 // ==.
8173 // assert.equal(actual, expected, message_opt);
8175 assert.equal = function equal(actual, expected, message) {
8176 if (actual != expected) fail(actual, expected, message, '==', assert.equal);
8177 };
8179 // 6. The non-equality assertion tests for whether two objects are not equal
8180 // with != assert.notEqual(actual, expected, message_opt);
8182 assert.notEqual = function notEqual(actual, expected, message) {
8183 if (actual == expected) {
8184 fail(actual, expected, message, '!=', assert.notEqual);
8185 }
8186 };
8188 // 7. The equivalence assertion tests a deep equality relation.
8189 // assert.deepEqual(actual, expected, message_opt);
8191 assert.deepEqual = function deepEqual(actual, expected, message) {
8192 if (!_deepEqual(actual, expected)) {
8193 fail(actual, expected, message, 'deepEqual', assert.deepEqual);
8194 }
8195 };
8197 function _deepEqual(actual, expected) {
8198 // 7.1. All identical values are equivalent, as determined by ===.
8199 if (actual === expected) {
8200 return true;
8202 } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
8203 if (actual.length != expected.length) return false;
8205 for (var i = 0; i < actual.length; i++) {
8206 if (actual[i] !== expected[i]) return false;
8207 }
8209 return true;
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();
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;
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 }
8232 function isUndefinedOrNull(value) {
8233 return value === null || value === undefined;
8234 }
8236 function isArguments(object) {
8237 return Object.prototype.toString.call(object) == '[object Arguments]';
8238 }
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 }
8283 // 8. The non-equivalence assertion tests for any deep inequality.
8284 // assert.notDeepEqual(actual, expected, message_opt);
8286 assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
8287 if (_deepEqual(actual, expected)) {
8288 fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
8289 }
8290 };
8292 // 9. The strict equality assertion tests strict equality, as determined by ===.
8293 // assert.strictEqual(actual, expected, message_opt);
8295 assert.strictEqual = function strictEqual(actual, expected, message) {
8296 if (actual !== expected) {
8297 fail(actual, expected, message, '===', assert.strictEqual);
8298 }
8299 };
8301 // 10. The strict non-equality assertion tests for strict inequality, as
8302 // determined by !==. assert.notStrictEqual(actual, expected, message_opt);
8304 assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
8305 if (actual === expected) {
8306 fail(actual, expected, message, '!==', assert.notStrictEqual);
8307 }
8308 };
8310 function expectedException(actual, expected) {
8311 if (!actual || !expected) {
8312 return false;
8313 }
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 }
8323 return false;
8324 }
8326 function _throws(shouldThrow, block, expected, message) {
8327 var actual;
8329 if (typeof expected === 'string') {
8330 message = expected;
8331 expected = null;
8332 }
8334 try {
8335 block();
8336 } catch (e) {
8337 actual = e;
8338 }
8340 message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
8341 (message ? ' ' + message : '.');
8343 if (shouldThrow && !actual) {
8344 fail('Missing expected exception' + message);
8345 }
8347 if (!shouldThrow && expectedException(actual, expected)) {
8348 fail('Got unwanted exception' + message);
8349 }
8351 if ((shouldThrow && actual && expected &&
8352 !expectedException(actual, expected)) || (!shouldThrow && actual)) {
8353 throw actual;
8354 }
8355 }
8357 // 11. Expected to throw an error:
8358 // assert.throws(block, Error_opt, message_opt);
8360 assert.throws = function(block, /*optional*/error, /*optional*/message) {
8361 _throws.apply(this, [true].concat(pSlice.call(arguments)));
8362 };
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 };
8369 assert.ifError = function(err) { if (err) {throw err;}};
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.
8378 (function() {
8380 // Baseline setup
8381 // --------------
8383 // Establish the root object, `window` in the browser, or `global` on the server.
8384 var root = this;
8386 // Save the previous value of the `_` variable.
8387 var previousUnderscore = root._;
8389 // Establish the object that gets returned to break out of a loop iteration.
8390 var breaker = {};
8392 // Save bytes in the minified (but not gzipped) version:
8393 var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
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;
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;
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 };
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 }
8438 // Current version.
8439 _.VERSION = '1.4.4';
8441 // Collection Functions
8442 // --------------------
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 };
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 };
8476 var reduceError = 'Reduce of empty array with no initial value';
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
8671 // An internal function to generate lookup iterators.
8672 var lookupIterator = function(value) {
8673 return _.isFunction(value) ? value : function(obj){ return obj[value]; };
8674 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
8752 // Array Functions
8753 // ---------------
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 };
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 };
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 };
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 };
8790 // Trim out all falsy values from an array.
8791 _.compact = function(array) {
8792 return _.filter(array, _.identity);
8793 };
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 };
8807 // Return a completely flattened version of an array.
8808 _.flatten = function(array, shallow) {
8809 return flatten(array, shallow, []);
8810 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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;
8934 var len = Math.max(Math.ceil((stop - start) / step), 0);
8935 var idx = 0;
8936 var range = new Array(len);
8938 while(idx < len) {
8939 range[idx++] = start;
8940 start += step;
8941 }
8943 return range;
8944 };
8946 // Function (ahem) Functions
8947 // ------------------
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
9095 // Object Functions
9096 // ----------------
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
9287 // Perform a deep comparison to check if two objects are equal.
9288 _.isEqual = function(a, b) {
9289 return eq(a, b, [], []);
9290 };
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 };
9301 // Is a given value a DOM element?
9302 _.isElement = function(obj) {
9303 return !!(obj && obj.nodeType === 1);
9304 };
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 };
9312 // Is a given variable an object?
9313 _.isObject = function(obj) {
9314 return obj === Object(obj);
9315 };
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 });
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 }
9332 // Optimize `isFunction` if appropriate.
9333 if (typeof (/./) !== 'function') {
9334 _.isFunction = function(obj) {
9335 return typeof obj === 'function';
9336 };
9337 }
9339 // Is a given object a finite number?
9340 _.isFinite = function(obj) {
9341 return isFinite(obj) && !isNaN(parseFloat(obj));
9342 };
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 };
9349 // Is a given value a boolean?
9350 _.isBoolean = function(obj) {
9351 return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
9352 };
9354 // Is a given value equal to null?
9355 _.isNull = function(obj) {
9356 return obj === null;
9357 };
9359 // Is a given variable undefined?
9360 _.isUndefined = function(obj) {
9361 return obj === void 0;
9362 };
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 };
9370 // Utility Functions
9371 // -----------------
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 };
9380 // Keep the identity function around for default iterators.
9381 _.identity = function(value) {
9382 return value;
9383 };
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 };
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 };
9401 // List of HTML entities for escaping.
9402 var entityMap = {
9403 escape: {
9404 '&': '&',
9405 '<': '<',
9406 '>': '>',
9407 '"': '"',
9408 "'": ''',
9409 '/': '/'
9410 }
9411 };
9412 entityMap.unescape = _.invert(entityMap.escape);
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 };
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 });
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 };
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 };
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 };
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 };
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 = /(.)^/;
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 };
9483 var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
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);
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');
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]; });
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";
9520 // If a variable is not specified, place data values in local scope.
9521 if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
9523 source = "var __t,__p='',__j=Array.prototype.join," +
9524 "print=function(){__p+=__j.call(arguments,'');};\n" +
9525 source + "return __p;\n";
9527 try {
9528 render = new Function(settings.variable || 'obj', '_', source);
9529 } catch (e) {
9530 e.source = source;
9531 throw e;
9532 }
9534 if (data) return render(data, _);
9535 var template = function(data) {
9536 return render.call(this, data, _);
9537 };
9539 // Provide the compiled function source as a convenience for precompilation.
9540 template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
9542 return template;
9543 };
9545 // Add a "chain" function, which will delegate to the wrapper.
9546 _.chain = function(obj) {
9547 return _(obj).chain();
9548 };
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.
9556 // Helper function to continue chaining intermediate results.
9557 var result = function(obj) {
9558 return this._chain ? _(obj).chain() : obj;
9559 };
9561 // Add all of the Underscore functions to the wrapper object.
9562 _.mixin(_);
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 });
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 });
9583 _.extend(_.prototype, {
9585 // Start chaining a wrapped Underscore object.
9586 chain: function() {
9587 this._chain = true;
9588 return this;
9589 },
9591 // Extracts the result from a wrapped and chained object.
9592 value: function() {
9593 return this._wrapped;
9594 }
9596 });
9598 }).call(this);
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];
9612 i += d;
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);
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);
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 };
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;
9645 value = Math.abs(value);
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 }
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 }
9678 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
9680 e = (e << mLen) | m;
9681 eLen += mLen;
9682 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
9684 buffer[offset + i - d] |= s * 128;
9685 };
9687 },{}],13:[function(require,module,exports){
9688 (function(){function SlowBuffer (size) {
9689 this.length = size;
9690 };
9692 var assert = require('assert');
9694 exports.INSPECT_MAX_BYTES = 50;
9697 function toHex(n) {
9698 if (n < 16) return '0' + n.toString(16);
9699 return n.toString(16);
9700 }
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 }
9713 return byteArray;
9714 }
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 );
9722 return byteArray;
9723 }
9725 function base64ToBytes(str) {
9726 return require("base64-js").toByteArray(str);
9727 }
9729 SlowBuffer.byteLength = function (str, encoding) {
9730 switch (encoding || "utf8") {
9731 case 'hex':
9732 return str.length / 2;
9734 case 'utf8':
9735 case 'utf-8':
9736 return utf8ToBytes(str).length;
9738 case 'ascii':
9739 case 'binary':
9740 return str.length;
9742 case 'base64':
9743 return base64ToBytes(str).length;
9745 default:
9746 throw new Error('Unknown encoding');
9747 }
9748 };
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;
9756 dst[i + offset] = src[i];
9757 i++;
9758 }
9759 return i;
9760 }
9762 SlowBuffer.prototype.utf8Write = function (string, offset, length) {
9763 var bytes, pos;
9764 return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
9765 };
9767 SlowBuffer.prototype.asciiWrite = function (string, offset, length) {
9768 var bytes, pos;
9769 return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
9770 };
9772 SlowBuffer.prototype.binaryWrite = SlowBuffer.prototype.asciiWrite;
9774 SlowBuffer.prototype.base64Write = function (string, offset, length) {
9775 var bytes, pos;
9776 return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
9777 };
9779 SlowBuffer.prototype.base64Slice = function (start, end) {
9780 var bytes = Array.prototype.slice.apply(this, arguments)
9781 return require("base64-js").fromByteArray(bytes);
9782 }
9784 function decodeUtf8Char(str) {
9785 try {
9786 return decodeURIComponent(str);
9787 } catch (err) {
9788 return String.fromCharCode(0xFFFD); // UTF 8 invalid char
9789 }
9790 }
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);
9804 i++;
9805 }
9807 return res + decodeUtf8Char(tmp);
9808 }
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 }
9818 SlowBuffer.prototype.binarySlice = SlowBuffer.prototype.asciiSlice;
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 };
9834 SlowBuffer.prototype.hexSlice = function(start, end) {
9835 var len = this.length;
9837 if (!start || start < 0) start = 0;
9838 if (!end || end < 0 || end > len) end = len;
9840 var out = '';
9841 for (var i = start; i < end; i++) {
9842 out += toHex(this[i]);
9843 }
9844 return out;
9845 };
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;
9853 // Fastpath empty strings
9854 if (+end == start) {
9855 return '';
9856 }
9858 switch (encoding) {
9859 case 'hex':
9860 return this.hexSlice(start, end);
9862 case 'utf8':
9863 case 'utf-8':
9864 return this.utf8Slice(start, end);
9866 case 'ascii':
9867 return this.asciiSlice(start, end);
9869 case 'binary':
9870 return this.binarySlice(start, end);
9872 case 'base64':
9873 return this.base64Slice(start, end);
9875 case 'ucs2':
9876 case 'ucs-2':
9877 return this.ucs2Slice(start, end);
9879 default:
9880 throw new Error('Unknown encoding');
9881 }
9882 };
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 }
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 };
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 }
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();
9942 switch (encoding) {
9943 case 'hex':
9944 return this.hexWrite(string, offset, length);
9946 case 'utf8':
9947 case 'utf-8':
9948 return this.utf8Write(string, offset, length);
9950 case 'ascii':
9951 return this.asciiWrite(string, offset, length);
9953 case 'binary':
9954 return this.binaryWrite(string, offset, length);
9956 case 'base64':
9957 return this.base64Write(string, offset, length);
9959 case 'ucs2':
9960 case 'ucs-2':
9961 return this.ucs2Write(string, offset, length);
9963 default:
9964 throw new Error('Unknown encoding');
9965 }
9966 };
9969 // slice(start, end)
9970 SlowBuffer.prototype.slice = function(start, end) {
9971 if (end === undefined) end = this.length;
9973 if (end > this.length) {
9974 throw new Error('oob');
9975 }
9976 if (start > end) {
9977 throw new Error('oob');
9978 }
9980 return new Buffer(this, end - start, +start);
9981 };
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 }
9990 for (var i=targetstart; i<targetstart+temp.length; i++) {
9991 target[i] = temp[i-targetstart];
9992 }
9993 };
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 }
10003 for (var i = start; i < end; i++) {
10004 this[i] = value;
10005 }
10006 }
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 }
10017 // Buffer
10019 function Buffer(subject, encoding, offset) {
10020 if (!(this instanceof Buffer)) {
10021 return new Buffer(subject, encoding, offset);
10022 }
10024 var type;
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;
10038 case 'string':
10039 this.length = Buffer.byteLength(subject, encoding);
10040 break;
10042 case 'object': // Assume object is an array
10043 this.length = coerce(subject.length);
10044 break;
10046 default:
10047 throw new Error('First argument needs to be a number, ' +
10048 'array or string.');
10049 }
10051 if (this.length > Buffer.poolSize) {
10052 // Big buffer, just alloc one.
10053 this.parent = new SlowBuffer(this.length);
10054 this.offset = 0;
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 }
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 }
10080 }
10082 function isArrayIsh(subject) {
10083 return Array.isArray(subject) || Buffer.isBuffer(subject) ||
10084 subject && typeof subject === 'object' &&
10085 typeof subject.length === 'number';
10086 }
10088 exports.SlowBuffer = SlowBuffer;
10089 exports.Buffer = Buffer;
10091 Buffer.poolSize = 8 * 1024;
10092 var pool;
10094 function allocPool() {
10095 pool = new SlowBuffer(Buffer.poolSize);
10096 pool.used = 0;
10097 }
10100 // Static methods
10101 Buffer.isBuffer = function isBuffer(b) {
10102 return b instanceof Buffer || b instanceof SlowBuffer;
10103 };
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 }
10111 if (list.length === 0) {
10112 return new Buffer(0);
10113 } else if (list.length === 1) {
10114 return list[0];
10115 }
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 }
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 };
10135 // Inspect
10136 Buffer.prototype.inspect = function inspect() {
10137 var out = [],
10138 len = this.length;
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 }
10148 return '<Buffer ' + out.join(' ') + '>';
10149 };
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 };
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 };
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 }
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();
10192 var ret;
10193 switch (encoding) {
10194 case 'hex':
10195 ret = this.parent.hexWrite(string, this.offset + offset, length);
10196 break;
10198 case 'utf8':
10199 case 'utf-8':
10200 ret = this.parent.utf8Write(string, this.offset + offset, length);
10201 break;
10203 case 'ascii':
10204 ret = this.parent.asciiWrite(string, this.offset + offset, length);
10205 break;
10207 case 'binary':
10208 ret = this.parent.binaryWrite(string, this.offset + offset, length);
10209 break;
10211 case 'base64':
10212 // Warning: maxLength not taken into account in base64Write
10213 ret = this.parent.base64Write(string, this.offset + offset, length);
10214 break;
10216 case 'ucs2':
10217 case 'ucs-2':
10218 ret = this.parent.ucs2Write(string, this.offset + offset, length);
10219 break;
10221 default:
10222 throw new Error('Unknown encoding');
10223 }
10225 Buffer._charsWritten = SlowBuffer._charsWritten;
10227 return ret;
10228 };
10231 // toString(encoding, start=0, end=buffer.length)
10232 Buffer.prototype.toString = function(encoding, start, end) {
10233 encoding = String(encoding || 'utf8').toLowerCase();
10235 if (typeof start == 'undefined' || start < 0) {
10236 start = 0;
10237 } else if (start > this.length) {
10238 start = this.length;
10239 }
10241 if (typeof end == 'undefined' || end > this.length) {
10242 end = this.length;
10243 } else if (end < 0) {
10244 end = 0;
10245 }
10247 start = start + this.offset;
10248 end = end + this.offset;
10250 switch (encoding) {
10251 case 'hex':
10252 return this.parent.hexSlice(start, end);
10254 case 'utf8':
10255 case 'utf-8':
10256 return this.parent.utf8Slice(start, end);
10258 case 'ascii':
10259 return this.parent.asciiSlice(start, end);
10261 case 'binary':
10262 return this.parent.binarySlice(start, end);
10264 case 'base64':
10265 return this.parent.base64Slice(start, end);
10267 case 'ucs2':
10268 case 'ucs-2':
10269 return this.parent.ucs2Slice(start, end);
10271 default:
10272 throw new Error('Unknown encoding');
10273 }
10274 };
10277 // byteLength
10278 Buffer.byteLength = SlowBuffer.byteLength;
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);
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 }
10294 if (end < start) throw new Error('end < start');
10296 // Fill 0 bytes; we're done
10297 if (end === start) return 0;
10298 if (this.length == 0) return 0;
10300 if (start < 0 || start >= this.length) {
10301 throw new Error('start out of bounds');
10302 }
10304 if (end < 0 || end > this.length) {
10305 throw new Error('end out of bounds');
10306 }
10308 return this.parent.fill(value,
10309 start + this.offset,
10310 end + this.offset);
10311 };
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);
10321 if (end < start) throw new Error('sourceEnd < sourceStart');
10323 // Copy 0 bytes; we're done
10324 if (end === start) return 0;
10325 if (target.length == 0 || source.length == 0) return 0;
10327 if (target_start < 0 || target_start >= target.length) {
10328 throw new Error('targetStart out of bounds');
10329 }
10331 if (start < 0 || start >= source.length) {
10332 throw new Error('sourceStart out of bounds');
10333 }
10335 if (end < 0 || end > source.length) {
10336 throw new Error('sourceEnd out of bounds');
10337 }
10339 // Are we oob?
10340 if (end > this.length) {
10341 end = this.length;
10342 }
10344 if (target.length - target_start < end - start) {
10345 end = target.length - target_start + start;
10346 }
10348 return this.parent.copy(target.parent,
10349 target_start + target.offset,
10350 start + this.offset,
10351 end + this.offset);
10352 };
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');
10361 return new Buffer(this.parent, end - start, +start + this.offset);
10362 };
10365 // Legacy methods for backwards compatibility.
10367 Buffer.prototype.utf8Slice = function(start, end) {
10368 return this.toString('utf8', start, end);
10369 };
10371 Buffer.prototype.binarySlice = function(start, end) {
10372 return this.toString('binary', start, end);
10373 };
10375 Buffer.prototype.asciiSlice = function(start, end) {
10376 return this.toString('ascii', start, end);
10377 };
10379 Buffer.prototype.utf8Write = function(string, offset) {
10380 return this.write(string, offset, 'utf8');
10381 };
10383 Buffer.prototype.binaryWrite = function(string, offset) {
10384 return this.write(string, offset, 'binary');
10385 };
10387 Buffer.prototype.asciiWrite = function(string, offset) {
10388 return this.write(string, offset, 'ascii');
10389 };
10391 Buffer.prototype.readUInt8 = function(offset, noAssert) {
10392 var buffer = this;
10394 if (!noAssert) {
10395 assert.ok(offset !== undefined && offset !== null,
10396 'missing offset');
10398 assert.ok(offset < buffer.length,
10399 'Trying to read beyond buffer length');
10400 }
10402 if (offset >= buffer.length) return;
10404 return buffer.parent[buffer.offset + offset];
10405 };
10407 function readUInt16(buffer, offset, isBigEndian, noAssert) {
10408 var val = 0;
10411 if (!noAssert) {
10412 assert.ok(typeof (isBigEndian) === 'boolean',
10413 'missing or invalid endian');
10415 assert.ok(offset !== undefined && offset !== null,
10416 'missing offset');
10418 assert.ok(offset + 1 < buffer.length,
10419 'Trying to read beyond buffer length');
10420 }
10422 if (offset >= buffer.length) return 0;
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 }
10436 return val;
10437 }
10439 Buffer.prototype.readUInt16LE = function(offset, noAssert) {
10440 return readUInt16(this, offset, false, noAssert);
10441 };
10443 Buffer.prototype.readUInt16BE = function(offset, noAssert) {
10444 return readUInt16(this, offset, true, noAssert);
10445 };
10447 function readUInt32(buffer, offset, isBigEndian, noAssert) {
10448 var val = 0;
10450 if (!noAssert) {
10451 assert.ok(typeof (isBigEndian) === 'boolean',
10452 'missing or invalid endian');
10454 assert.ok(offset !== undefined && offset !== null,
10455 'missing offset');
10457 assert.ok(offset + 3 < buffer.length,
10458 'Trying to read beyond buffer length');
10459 }
10461 if (offset >= buffer.length) return 0;
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 }
10481 return val;
10482 }
10484 Buffer.prototype.readUInt32LE = function(offset, noAssert) {
10485 return readUInt32(this, offset, false, noAssert);
10486 };
10488 Buffer.prototype.readUInt32BE = function(offset, noAssert) {
10489 return readUInt32(this, offset, true, noAssert);
10490 };
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;
10542 if (!noAssert) {
10543 assert.ok(offset !== undefined && offset !== null,
10544 'missing offset');
10546 assert.ok(offset < buffer.length,
10547 'Trying to read beyond buffer length');
10548 }
10550 if (offset >= buffer.length) return;
10552 neg = buffer.parent[buffer.offset + offset] & 0x80;
10553 if (!neg) {
10554 return (buffer.parent[buffer.offset + offset]);
10555 }
10557 return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);
10558 };
10560 function readInt16(buffer, offset, isBigEndian, noAssert) {
10561 var neg, val;
10563 if (!noAssert) {
10564 assert.ok(typeof (isBigEndian) === 'boolean',
10565 'missing or invalid endian');
10567 assert.ok(offset !== undefined && offset !== null,
10568 'missing offset');
10570 assert.ok(offset + 1 < buffer.length,
10571 'Trying to read beyond buffer length');
10572 }
10574 val = readUInt16(buffer, offset, isBigEndian, noAssert);
10575 neg = val & 0x8000;
10576 if (!neg) {
10577 return val;
10578 }
10580 return (0xffff - val + 1) * -1;
10581 }
10583 Buffer.prototype.readInt16LE = function(offset, noAssert) {
10584 return readInt16(this, offset, false, noAssert);
10585 };
10587 Buffer.prototype.readInt16BE = function(offset, noAssert) {
10588 return readInt16(this, offset, true, noAssert);
10589 };
10591 function readInt32(buffer, offset, isBigEndian, noAssert) {
10592 var neg, val;
10594 if (!noAssert) {
10595 assert.ok(typeof (isBigEndian) === 'boolean',
10596 'missing or invalid endian');
10598 assert.ok(offset !== undefined && offset !== null,
10599 'missing offset');
10601 assert.ok(offset + 3 < buffer.length,
10602 'Trying to read beyond buffer length');
10603 }
10605 val = readUInt32(buffer, offset, isBigEndian, noAssert);
10606 neg = val & 0x80000000;
10607 if (!neg) {
10608 return (val);
10609 }
10611 return (0xffffffff - val + 1) * -1;
10612 }
10614 Buffer.prototype.readInt32LE = function(offset, noAssert) {
10615 return readInt32(this, offset, false, noAssert);
10616 };
10618 Buffer.prototype.readInt32BE = function(offset, noAssert) {
10619 return readInt32(this, offset, true, noAssert);
10620 };
10622 function readFloat(buffer, offset, isBigEndian, noAssert) {
10623 if (!noAssert) {
10624 assert.ok(typeof (isBigEndian) === 'boolean',
10625 'missing or invalid endian');
10627 assert.ok(offset + 3 < buffer.length,
10628 'Trying to read beyond buffer length');
10629 }
10631 return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
10632 23, 4);
10633 }
10635 Buffer.prototype.readFloatLE = function(offset, noAssert) {
10636 return readFloat(this, offset, false, noAssert);
10637 };
10639 Buffer.prototype.readFloatBE = function(offset, noAssert) {
10640 return readFloat(this, offset, true, noAssert);
10641 };
10643 function readDouble(buffer, offset, isBigEndian, noAssert) {
10644 if (!noAssert) {
10645 assert.ok(typeof (isBigEndian) === 'boolean',
10646 'missing or invalid endian');
10648 assert.ok(offset + 7 < buffer.length,
10649 'Trying to read beyond buffer length');
10650 }
10652 return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
10653 52, 8);
10654 }
10656 Buffer.prototype.readDoubleLE = function(offset, noAssert) {
10657 return readDouble(this, offset, false, noAssert);
10658 };
10660 Buffer.prototype.readDoubleBE = function(offset, noAssert) {
10661 return readDouble(this, offset, true, noAssert);
10662 };
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');
10678 assert.ok(value >= 0,
10679 'specified a negative value for writing an unsigned value');
10681 assert.ok(value <= max, 'value is larger than maximum value for type');
10683 assert.ok(Math.floor(value) === value, 'value has a fractional component');
10684 }
10686 Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
10687 var buffer = this;
10689 if (!noAssert) {
10690 assert.ok(value !== undefined && value !== null,
10691 'missing value');
10693 assert.ok(offset !== undefined && offset !== null,
10694 'missing offset');
10696 assert.ok(offset < buffer.length,
10697 'trying to write beyond buffer length');
10699 verifuint(value, 0xff);
10700 }
10702 if (offset < buffer.length) {
10703 buffer.parent[buffer.offset + offset] = value;
10704 }
10705 };
10707 function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
10708 if (!noAssert) {
10709 assert.ok(value !== undefined && value !== null,
10710 'missing value');
10712 assert.ok(typeof (isBigEndian) === 'boolean',
10713 'missing or invalid endian');
10715 assert.ok(offset !== undefined && offset !== null,
10716 'missing offset');
10718 assert.ok(offset + 1 < buffer.length,
10719 'trying to write beyond buffer length');
10721 verifuint(value, 0xffff);
10722 }
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 }
10730 }
10732 Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
10733 writeUInt16(this, value, offset, false, noAssert);
10734 };
10736 Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
10737 writeUInt16(this, value, offset, true, noAssert);
10738 };
10740 function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
10741 if (!noAssert) {
10742 assert.ok(value !== undefined && value !== null,
10743 'missing value');
10745 assert.ok(typeof (isBigEndian) === 'boolean',
10746 'missing or invalid endian');
10748 assert.ok(offset !== undefined && offset !== null,
10749 'missing offset');
10751 assert.ok(offset + 3 < buffer.length,
10752 'trying to write beyond buffer length');
10754 verifuint(value, 0xffffffff);
10755 }
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 }
10763 Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
10764 writeUInt32(this, value, offset, false, noAssert);
10765 };
10767 Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
10768 writeUInt32(this, value, offset, true, noAssert);
10769 };
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 */
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');
10816 assert.ok(value <= max, 'value larger than maximum allowed value');
10818 assert.ok(value >= min, 'value smaller than minimum allowed value');
10820 assert.ok(Math.floor(value) === value, 'value has a fractional component');
10821 }
10823 function verifIEEE754(value, max, min) {
10824 assert.ok(typeof (value) == 'number',
10825 'cannot write a non-number as a number');
10827 assert.ok(value <= max, 'value larger than maximum allowed value');
10829 assert.ok(value >= min, 'value smaller than minimum allowed value');
10830 }
10832 Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
10833 var buffer = this;
10835 if (!noAssert) {
10836 assert.ok(value !== undefined && value !== null,
10837 'missing value');
10839 assert.ok(offset !== undefined && offset !== null,
10840 'missing offset');
10842 assert.ok(offset < buffer.length,
10843 'Trying to write beyond buffer length');
10845 verifsint(value, 0x7f, -0x80);
10846 }
10848 if (value >= 0) {
10849 buffer.writeUInt8(value, offset, noAssert);
10850 } else {
10851 buffer.writeUInt8(0xff + value + 1, offset, noAssert);
10852 }
10853 };
10855 function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
10856 if (!noAssert) {
10857 assert.ok(value !== undefined && value !== null,
10858 'missing value');
10860 assert.ok(typeof (isBigEndian) === 'boolean',
10861 'missing or invalid endian');
10863 assert.ok(offset !== undefined && offset !== null,
10864 'missing offset');
10866 assert.ok(offset + 1 < buffer.length,
10867 'Trying to write beyond buffer length');
10869 verifsint(value, 0x7fff, -0x8000);
10870 }
10872 if (value >= 0) {
10873 writeUInt16(buffer, value, offset, isBigEndian, noAssert);
10874 } else {
10875 writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
10876 }
10877 }
10879 Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
10880 writeInt16(this, value, offset, false, noAssert);
10881 };
10883 Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
10884 writeInt16(this, value, offset, true, noAssert);
10885 };
10887 function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
10888 if (!noAssert) {
10889 assert.ok(value !== undefined && value !== null,
10890 'missing value');
10892 assert.ok(typeof (isBigEndian) === 'boolean',
10893 'missing or invalid endian');
10895 assert.ok(offset !== undefined && offset !== null,
10896 'missing offset');
10898 assert.ok(offset + 3 < buffer.length,
10899 'Trying to write beyond buffer length');
10901 verifsint(value, 0x7fffffff, -0x80000000);
10902 }
10904 if (value >= 0) {
10905 writeUInt32(buffer, value, offset, isBigEndian, noAssert);
10906 } else {
10907 writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
10908 }
10909 }
10911 Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
10912 writeInt32(this, value, offset, false, noAssert);
10913 };
10915 Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
10916 writeInt32(this, value, offset, true, noAssert);
10917 };
10919 function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
10920 if (!noAssert) {
10921 assert.ok(value !== undefined && value !== null,
10922 'missing value');
10924 assert.ok(typeof (isBigEndian) === 'boolean',
10925 'missing or invalid endian');
10927 assert.ok(offset !== undefined && offset !== null,
10928 'missing offset');
10930 assert.ok(offset + 3 < buffer.length,
10931 'Trying to write beyond buffer length');
10933 verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
10934 }
10936 require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
10937 23, 4);
10938 }
10940 Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
10941 writeFloat(this, value, offset, false, noAssert);
10942 };
10944 Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
10945 writeFloat(this, value, offset, true, noAssert);
10946 };
10948 function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
10949 if (!noAssert) {
10950 assert.ok(value !== undefined && value !== null,
10951 'missing value');
10953 assert.ok(typeof (isBigEndian) === 'boolean',
10954 'missing or invalid endian');
10956 assert.ok(offset !== undefined && offset !== null,
10957 'missing offset');
10959 assert.ok(offset + 7 < buffer.length,
10960 'Trying to write beyond buffer length');
10962 verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
10963 }
10965 require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
10966 52, 8);
10967 }
10969 Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
10970 writeDouble(this, value, offset, false, noAssert);
10971 };
10973 Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
10974 writeDouble(this, value, offset, true, noAssert);
10975 };
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;
11006 })()
11007 },{"assert":9,"./buffer_ieee754":14,"base64-js":15}],15:[function(require,module,exports){
11008 (function (exports) {
11009 'use strict';
11011 var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
11013 function b64ToByteArray(b64) {
11014 var i, j, l, tmp, placeHolders, arr;
11016 if (b64.length % 4 > 0) {
11017 throw 'Invalid string. Length must be a multiple of 4';
11018 }
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;
11028 // base64 is 4/3 + up to two characters of the original data
11029 arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
11031 // if there are placeholders, only get up to the last complete 4 chars
11032 l = placeHolders > 0 ? b64.length - 4 : b64.length;
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 }
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 }
11050 return arr;
11051 }
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;
11059 function tripletToBase64 (num) {
11060 return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
11061 };
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 }
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 }
11086 return output;
11087 }
11089 module.exports.toByteArray = b64ToByteArray;
11090 module.exports.fromByteArray = uint8ToBase64;
11091 }());
11093 },{}]},{},["E/GbHF"])
11094 ;
11095 JSHINT = require('jshint').JSHINT;
11096 }());