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
17 if (canSetImmediate
) {
18 return function (f
) { return window
.setImmediate(f
) };
23 window
.addEventListener('message', function (ev
) {
24 if (ev
.source
=== window
&& ev
.data
=== 'process-tick') {
26 if (queue
.length
> 0) {
27 var fn
= queue
.shift();
33 return function nextTick(fn
) {
35 window
.postMessage('process-tick', '*');
39 return function nextTick(fn
) {
44 process
.title
= 'browser';
45 process
.browser
= true;
49 process
.binding = function (name
) {
50 throw new Error('process.binding is not supported');
54 process
.cwd = function () { return '/' };
55 process
.chdir = function (dir
) {
56 throw new Error('process.chdir is not supported');
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'
66 return Object
.prototype.toString
.call(xs
) === '[object Array]'
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
;
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.
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
;
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
))
96 if (arguments
[1] instanceof Error
) {
97 throw arguments
[1]; // Unhandled 'error' event
99 throw new Error("Uncaught, unspecified 'error' event.");
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
) {
116 handler
.call(this, arguments
[1]);
119 handler
.call(this, arguments
[1], arguments
[2]);
123 var args
= Array
.prototype.slice
.call(arguments
, 1);
124 handler
.apply(this, args
);
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
);
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');
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
) {
163 if (this._events
.maxListeners
!== undefined) {
164 m
= this._events
.maxListeners
;
166 m
= defaultMaxListeners
;
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
);
179 // If we've already got an array, just append.
180 this._events
[type
].push(listener
);
182 // Adding the second element, need to change to array.
183 this._events
[type
] = [this._events
[type
], listener
];
189 EventEmitter
.prototype.on
= EventEmitter
.prototype.addListener
;
191 EventEmitter
.prototype.once = function(type
, listener
) {
193 self
.on(type
, function g() {
194 self
.removeListener(type
, g
);
195 listener
.apply(this, arguments
);
201 EventEmitter
.prototype.removeListener = function(type
, listener
) {
202 if ('function' !== typeof listener
) {
203 throw new Error('removeListener only takes instances of Function');
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
];
212 var i
= indexOf(list
, listener
);
213 if (i
< 0) return this;
215 if (list
.length
== 0)
216 delete this._events
[type
];
217 } else if (this._events
[type
] === listener
) {
218 delete this._events
[type
];
224 EventEmitter
.prototype.removeAllListeners = function(type
) {
225 if (arguments
.length
=== 0) {
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;
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
]];
241 return this._events
[type
];
244 })(require("__browserify_process"))
245 },{"__browserify_process":1}],3:[function(require
,module
,exports
){
246 (function(){// jshint -W001
250 // Identifiers provided by the ECMAScript standard.
252 exports
.reservedVars
= {
257 exports
.ecmaIdentifiers
= {
262 decodeURIComponent
: false,
264 encodeURIComponent
: false,
269 hasOwnProperty
: false,
280 ReferenceError
: false,
290 // Global variables commonly provided by a web browser environment.
294 ArrayBufferView
: false,
297 addEventListener
: false,
298 applicationCache
: false,
302 clearInterval
: false,
303 clearTimeout
: false,
309 defaultStatus
: false,
312 ElementTimeControl
: false,
315 Float32Array
: false,
316 Float64Array
: false,
320 getComputedStyle
: false,
322 HTMLAnchorElement
: false,
323 HTMLBaseElement
: false,
324 HTMLBlockquoteElement
: false,
325 HTMLBodyElement
: false,
326 HTMLBRElement
: false,
327 HTMLButtonElement
: false,
328 HTMLCanvasElement
: false,
329 HTMLDirectoryElement
: false,
330 HTMLDivElement
: false,
331 HTMLDListElement
: false,
332 HTMLFieldSetElement
: false,
333 HTMLFontElement
: false,
334 HTMLFormElement
: false,
335 HTMLFrameElement
: false,
336 HTMLFrameSetElement
: false,
337 HTMLHeadElement
: false,
338 HTMLHeadingElement
: false,
339 HTMLHRElement
: false,
340 HTMLHtmlElement
: false,
341 HTMLIFrameElement
: false,
342 HTMLImageElement
: false,
343 HTMLInputElement
: false,
344 HTMLIsIndexElement
: false,
345 HTMLLabelElement
: false,
346 HTMLLayerElement
: false,
347 HTMLLegendElement
: false,
348 HTMLLIElement
: false,
349 HTMLLinkElement
: false,
350 HTMLMapElement
: false,
351 HTMLMenuElement
: false,
352 HTMLMetaElement
: false,
353 HTMLModElement
: false,
354 HTMLObjectElement
: false,
355 HTMLOListElement
: false,
356 HTMLOptGroupElement
: false,
357 HTMLOptionElement
: false,
358 HTMLParagraphElement
: false,
359 HTMLParamElement
: false,
360 HTMLPreElement
: false,
361 HTMLQuoteElement
: false,
362 HTMLScriptElement
: false,
363 HTMLSelectElement
: false,
364 HTMLStyleElement
: false,
365 HTMLTableCaptionElement
: false,
366 HTMLTableCellElement
: false,
367 HTMLTableColElement
: false,
368 HTMLTableElement
: false,
369 HTMLTableRowElement
: false,
370 HTMLTableSectionElement
: false,
371 HTMLTextAreaElement
: false,
372 HTMLTitleElement
: false,
373 HTMLUListElement
: false,
374 HTMLVideoElement
: false,
381 localStorage
: false,
383 MessageChannel
: false,
384 MessageEvent
: false,
389 MutationObserver
: false,
394 onbeforeunload
: true,
402 openDatabase
: false,
407 removeEventListener
: false,
414 sessionStorage
: false,
417 SharedWorker
: false,
420 SVGAltGlyphDefElement
: false,
421 SVGAltGlyphElement
: false,
422 SVGAltGlyphItemElement
: false,
424 SVGAnimateColorElement
: false,
425 SVGAnimateElement
: false,
426 SVGAnimateMotionElement
: false,
427 SVGAnimateTransformElement
: false,
428 SVGAnimatedAngle
: false,
429 SVGAnimatedBoolean
: false,
430 SVGAnimatedEnumeration
: false,
431 SVGAnimatedInteger
: false,
432 SVGAnimatedLength
: false,
433 SVGAnimatedLengthList
: false,
434 SVGAnimatedNumber
: false,
435 SVGAnimatedNumberList
: false,
436 SVGAnimatedPathData
: false,
437 SVGAnimatedPoints
: false,
438 SVGAnimatedPreserveAspectRatio
: false,
439 SVGAnimatedRect
: false,
440 SVGAnimatedString
: false,
441 SVGAnimatedTransformList
: false,
442 SVGAnimationElement
: false,
444 SVGCircleElement
: false,
445 SVGClipPathElement
: false,
447 SVGColorProfileElement
: false,
448 SVGColorProfileRule
: false,
449 SVGComponentTransferFunctionElement
: false,
450 SVGCursorElement
: false,
451 SVGDefsElement
: false,
452 SVGDescElement
: false,
455 SVGElementInstance
: false,
456 SVGElementInstanceList
: false,
457 SVGEllipseElement
: false,
458 SVGExternalResourcesRequired
: false,
459 SVGFEBlendElement
: false,
460 SVGFEColorMatrixElement
: false,
461 SVGFEComponentTransferElement
: false,
462 SVGFECompositeElement
: false,
463 SVGFEConvolveMatrixElement
: false,
464 SVGFEDiffuseLightingElement
: false,
465 SVGFEDisplacementMapElement
: false,
466 SVGFEDistantLightElement
: false,
467 SVGFEFloodElement
: false,
468 SVGFEFuncAElement
: false,
469 SVGFEFuncBElement
: false,
470 SVGFEFuncGElement
: false,
471 SVGFEFuncRElement
: false,
472 SVGFEGaussianBlurElement
: false,
473 SVGFEImageElement
: false,
474 SVGFEMergeElement
: false,
475 SVGFEMergeNodeElement
: false,
476 SVGFEMorphologyElement
: false,
477 SVGFEOffsetElement
: false,
478 SVGFEPointLightElement
: false,
479 SVGFESpecularLightingElement
: false,
480 SVGFESpotLightElement
: false,
481 SVGFETileElement
: false,
482 SVGFETurbulenceElement
: false,
483 SVGFilterElement
: false,
484 SVGFilterPrimitiveStandardAttributes
: false,
485 SVGFitToViewBox
: false,
486 SVGFontElement
: false,
487 SVGFontFaceElement
: false,
488 SVGFontFaceFormatElement
: false,
489 SVGFontFaceNameElement
: false,
490 SVGFontFaceSrcElement
: false,
491 SVGFontFaceUriElement
: false,
492 SVGForeignObjectElement
: false,
494 SVGGlyphElement
: false,
495 SVGGlyphRefElement
: false,
496 SVGGradientElement
: false,
497 SVGHKernElement
: false,
499 SVGImageElement
: false,
500 SVGLangSpace
: false,
502 SVGLengthList
: false,
503 SVGLineElement
: false,
504 SVGLinearGradientElement
: false,
505 SVGLocatable
: false,
506 SVGMPathElement
: false,
507 SVGMarkerElement
: false,
508 SVGMaskElement
: false,
510 SVGMetadataElement
: false,
511 SVGMissingGlyphElement
: false,
513 SVGNumberList
: false,
515 SVGPathElement
: false,
517 SVGPathSegArcAbs
: false,
518 SVGPathSegArcRel
: false,
519 SVGPathSegClosePath
: false,
520 SVGPathSegCurvetoCubicAbs
: false,
521 SVGPathSegCurvetoCubicRel
: false,
522 SVGPathSegCurvetoCubicSmoothAbs
: false,
523 SVGPathSegCurvetoCubicSmoothRel
: false,
524 SVGPathSegCurvetoQuadraticAbs
: false,
525 SVGPathSegCurvetoQuadraticRel
: false,
526 SVGPathSegCurvetoQuadraticSmoothAbs
: false,
527 SVGPathSegCurvetoQuadraticSmoothRel
: false,
528 SVGPathSegLinetoAbs
: false,
529 SVGPathSegLinetoHorizontalAbs
: false,
530 SVGPathSegLinetoHorizontalRel
: false,
531 SVGPathSegLinetoRel
: false,
532 SVGPathSegLinetoVerticalAbs
: false,
533 SVGPathSegLinetoVerticalRel
: false,
534 SVGPathSegList
: false,
535 SVGPathSegMovetoAbs
: false,
536 SVGPathSegMovetoRel
: false,
537 SVGPatternElement
: false,
539 SVGPointList
: false,
540 SVGPolygonElement
: false,
541 SVGPolylineElement
: false,
542 SVGPreserveAspectRatio
: false,
543 SVGRadialGradientElement
: false,
545 SVGRectElement
: false,
546 SVGRenderingIntent
: false,
547 SVGSVGElement
: false,
548 SVGScriptElement
: false,
549 SVGSetElement
: false,
550 SVGStopElement
: false,
551 SVGStringList
: false,
553 SVGStyleElement
: false,
554 SVGSwitchElement
: false,
555 SVGSymbolElement
: false,
556 SVGTRefElement
: false,
557 SVGTSpanElement
: false,
559 SVGTextContentElement
: false,
560 SVGTextElement
: false,
561 SVGTextPathElement
: false,
562 SVGTextPositioningElement
: false,
563 SVGTitleElement
: false,
564 SVGTransform
: false,
565 SVGTransformList
: false,
566 SVGTransformable
: false,
567 SVGURIReference
: false,
568 SVGUnitTypes
: false,
569 SVGUseElement
: false,
570 SVGVKernElement
: false,
571 SVGViewElement
: false,
573 SVGZoomAndPan
: false,
579 Uint8ClampedArray
: false,
583 XMLHttpRequest
: false,
584 XMLSerializer
: false,
585 XPathEvaluator
: false,
586 XPathException
: false,
587 XPathExpression
: false,
588 XPathNamespace
: false,
589 XPathNSResolver
: false,
608 // Widely adopted global names that are not part of ECMAScript standard
609 exports
.nonstandard
= {
614 // Globals provided by popular JavaScript environments.
636 exports
: true, // In Node it is ok to exports = module.exports = foo();
643 clearTimeout
: false,
645 clearInterval
: false,
646 setImmediate
: false, // v0.9.1+
647 clearImmediate
: false // v0.9.1+
661 importPackage
: false,
707 ActiveXObject
: true,
711 ScriptEngineBuildVersion
: true,
712 ScriptEngineMajorVersion
: true,
713 ScriptEngineMinorVersion
: true,
717 XDomainRequest
: true
720 // Globals provided by popular JavaScript libraries.
760 InputValidator
: false,
783 exports
.prototypejs
= {
804 PeriodicalExecuter
: false,
811 Autocompleter
: false,
819 SortableObserver
: false,
821 Scriptaculous
: false
832 },{}],4:[function(require
,module
,exports
){
834 * Regular expressions. Some of these are stupidly long.
837 /*jshint maxlen:1000 */
841 // Unsafe comment or string (ax)
842 exports
.unsafeString
=
843 /@cc|<\/?|script|\]\s*\]|<\s*!|</i;
845 // Unsafe characters that are silently deleted by one or more browsers (cx)
846 exports
.unsafeChars
=
847 /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
849 // Characters in strings that need escaping (nx and nxg)
851 /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
853 exports
.needEscGlobal
=
854 /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
857 exports
.starSlash
= /\*\//;
860 exports
.identifier
= /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
862 // JavaScript URL (jx)
863 exports
.javascriptURL
= /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
865 // Catches /* falls through */ comments (ft)
866 exports
.fallsThrough
= /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
868 },{}],5:[function(require
,module
,exports
){
869 (function(){"use strict";
871 exports
.register = function (linter
) {
872 // Check for properties named __proto__. This special property was
873 // deprecated and then re-introduced for ES6.
875 linter
.on("Identifier", function style_scanProto(data
) {
876 if (linter
.getOption("proto")) {
880 if (data
.name
=== "__proto__") {
881 linter
.warn("W103", {
889 // Check for properties named __iterator__. This is a special property
890 // available only in browsers with JavaScript 1.7 implementation.
892 linter
.on("Identifier", function style_scanIterator(data
) {
893 if (linter
.getOption("iterator")) {
897 if (data
.name
=== "__iterator__") {
898 linter
.warn("W104", {
906 // Check for dangling underscores.
908 linter
.on("Identifier", function style_scanDangling(data
) {
909 if (!linter
.getOption("nomen")) {
914 if (data
.name
=== "_") {
918 // In Node, __dirname and __filename should be ignored.
919 if (linter
.getOption("node")) {
920 if (/^(__dirname|__filename)$/.test(data
.name
) && !data
.isProperty
) {
925 if (/^(_+.*|.*_+)$/.test(data
.name
)) {
926 linter
.warn("W105", {
929 data
: [ "dangling '_'", data
.name
]
934 // Check that all identifiers are using camelCase notation.
935 // Exceptions: names like MY_VAR and _myVar.
937 linter
.on("Identifier", function style_scanCamelCase(data
) {
938 if (!linter
.getOption("camelcase")) {
942 if (data
.name
.replace(/^_+/, "").indexOf("_") > -1 && !data
.name
.match(/^[A-Z0-9_]*$/)) {
943 linter
.warn("W106", {
951 // Enforce consistency in style of quoting.
953 linter
.on("String", function style_scanQuotes(data
) {
954 var quotmark
= linter
.getOption("quotmark");
961 // If quotmark is set to 'single' warn about all double-quotes.
963 if (quotmark
=== "single" && data
.quote
!== "'") {
967 // If quotmark is set to 'double' warn about all single-quotes.
969 if (quotmark
=== "double" && data
.quote
!== "\"") {
973 // If quotmark is set to true, remember the first quotation style
974 // and then warn about all others.
976 if (quotmark
=== true) {
977 if (!linter
.getCache("quotmark")) {
978 linter
.setCache("quotmark", data
.quote
);
981 if (linter
.getCache("quotmark") !== data
.quote
) {
994 linter
.on("Number", function style_scanNumbers(data
) {
995 if (data
.value
.charAt(0) === ".") {
996 // Warn about a leading decimal point.
997 linter
.warn("W008", {
1000 data
: [ data
.value
]
1004 if (data
.value
.substr(data
.value
.length
- 1) === ".") {
1005 // Warn about a trailing decimal point.
1006 linter
.warn("W047", {
1009 data
: [ data
.value
]
1013 if (/^00+/.test(data
.value
)) {
1014 // Multiple leading zeroes.
1015 linter
.warn("W046", {
1018 data
: [ data
.value
]
1023 // Warn about script URLs.
1025 linter
.on("String", function style_scanJavaScriptURLs(data
) {
1026 var re
= /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
1028 if (linter
.getOption("scripturl")) {
1032 if (re
.test(data
.value
)) {
1033 linter
.warn("W107", {
1041 },{}],6:[function(require
,module
,exports
){
1047 reset: function () {
1056 this.directive
= {};
1057 this.jsonMode
= false;
1058 this.jsonWarnings
= [];
1061 this.cache
= {}; // Node.JS doesn't have Map. Sniff.
1065 exports
.state
= state
;
1067 },{}],"jshint":[function(require
,module
,exports
){
1068 module
.exports
=require('E/GbHF');
1069 },{}],"E/GbHF":[function(require
,module
,exports
){
1071 * JSHint, by JSHint Community.
1073 * This file (and this file only) is licensed under the same slightly modified
1074 * MIT license that JSLint is. It stops evil-doers everywhere:
1076 * Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
1078 * Permission is hereby granted, free of charge, to any person obtaining
1079 * a copy of this software and associated documentation files (the "Software"),
1080 * to deal in the Software without restriction, including without limitation
1081 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1082 * and/or sell copies of the Software, and to permit persons to whom
1083 * the Software is furnished to do so, subject to the following conditions:
1085 * The above copyright notice and this permission notice shall be included
1086 * in all copies or substantial portions of the Software.
1088 * The Software shall be used for Good, not Evil.
1090 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1091 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1092 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1093 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1094 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1095 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1096 * DEALINGS IN THE SOFTWARE.
1100 /*jshint quotmark:double */
1101 /*global console:true */
1102 /*exported console */
1104 var _
= require("underscore");
1105 var events
= require("events");
1106 var vars
= require("../shared/vars.js");
1107 var messages
= require("../shared/messages.js");
1108 var Lexer
= require("./lex.js").Lexer
;
1109 var reg
= require("./reg.js");
1110 var state
= require("./state.js").state
;
1111 var style
= require("./style.js");
1113 // We need this module here because environments such as IE and Rhino
1114 // don't necessarilly expose the 'console' API and browserify uses
1115 // it to log things. It's a sad state of affair, really.
1116 var console
= require("console-browserify");
1118 // We build the application inside a function so that we produce only a singleton
1119 // variable. That function will be invoked immediately, and its return value is
1120 // the JSHINT function itself.
1122 var JSHINT
= (function () {
1125 var anonname
, // The guessed name for anonymous functions.
1126 api
, // Extension API
1128 // These are operators that should not be used with the ! operator.
1145 // These are the JSHint boolean options.
1147 asi
: true, // if automatic semicolon insertion should be tolerated
1148 bitwise
: true, // if bitwise operators should not be allowed
1149 boss
: true, // if advanced usage of assignments should be allowed
1150 browser
: true, // if the standard browser globals should be predefined
1151 camelcase
: true, // if identifiers should be required in camel case
1152 couch
: true, // if CouchDB globals should be predefined
1153 curly
: true, // if curly braces around all blocks should be required
1154 debug
: true, // if debugger statements should be allowed
1155 devel
: true, // if logging globals should be predefined (console, alert, etc.)
1156 dojo
: true, // if Dojo Toolkit globals should be predefined
1157 eqeqeq
: true, // if === should be required
1158 eqnull
: true, // if == null comparisons should be tolerated
1159 es3
: true, // if ES3 syntax should be allowed
1160 es5
: true, // if ES5 syntax should be allowed (is now set per default)
1161 esnext
: true, // if es.next specific syntax should be allowed
1162 moz
: true, // if mozilla specific syntax should be allowed
1163 evil
: true, // if eval should be allowed
1164 expr
: true, // if ExpressionStatement should be allowed as Programs
1165 forin
: true, // if for in statements must filter
1166 funcscope
: true, // if only function scope should be used for scope tests
1167 gcl
: true, // if JSHint should be compatible with Google Closure Linter
1168 globalstrict
: true, // if global "use strict"; should be allowed (also enables 'strict')
1169 immed
: true, // if immediate invocations must be wrapped in parens
1170 iterator
: true, // if the `__iterator__` property should be allowed
1171 jquery
: true, // if jQuery globals should be predefined
1172 lastsemic
: true, // if semicolons may be ommitted for the trailing
1173 // statements inside of a one-line blocks.
1174 laxbreak
: true, // if line breaks should not be checked
1175 laxcomma
: true, // if line breaks should not be checked around commas
1176 loopfunc
: true, // if functions should be allowed to be defined within
1178 mootools
: true, // if MooTools globals should be predefined
1179 multistr
: true, // allow multiline strings
1180 newcap
: true, // if constructor names must be capitalized
1181 noarg
: true, // if arguments.caller and arguments.callee should be
1183 node
: true, // if the Node.js environment globals should be
1185 noempty
: true, // if empty blocks should be disallowed
1186 nonew
: true, // if using `new` for side-effects should be disallowed
1187 nonstandard
: true, // if non-standard (but widely adopted) globals should
1189 nomen
: true, // if names should be checked
1190 onevar
: true, // if only one var statement per function should be
1192 passfail
: true, // if the scan should stop on first error
1193 phantom
: true, // if PhantomJS symbols should be allowed
1194 plusplus
: true, // if increment/decrement should not be allowed
1195 proto
: true, // if the `__proto__` property should be allowed
1196 prototypejs
: true, // if Prototype and Scriptaculous globals should be
1198 rhino
: true, // if the Rhino environment globals should be predefined
1199 shelljs
: true, // if ShellJS globals should be predefined
1200 undef
: true, // if variables should be declared before used
1201 scripturl
: true, // if script-targeted URLs should be tolerated
1202 shadow
: true, // if variable shadowing should be tolerated
1203 smarttabs
: true, // if smarttabs should be tolerated
1204 // (http://www.emacswiki.org/emacs/SmartTabs)
1205 strict
: true, // require the "use strict"; pragma
1206 sub
: true, // if all forms of subscript notation are tolerated
1207 supernew
: true, // if `new function () { ... };` and `new Object;`
1208 // should be tolerated
1209 trailing
: true, // if trailing whitespace rules apply
1210 validthis
: true, // if 'this' inside a non-constructor function is valid.
1211 // This is a function scoped option only.
1212 withstmt
: true, // if with statements should be allowed
1213 white
: true, // if strict whitespace rules apply
1214 worker
: true, // if Web Worker script symbols should be allowed
1215 wsh
: true, // if the Windows Scripting Host environment globals
1216 // should be predefined
1217 yui
: true, // YUI variables should be predefined
1220 onecase
: true, // if one case switch statements should be allowed
1221 regexp
: true, // if the . should not be allowed in regexp literals
1222 regexdash
: true // if unescaped first/last dash (-) inside brackets
1223 // should be tolerated
1226 // These are the JSHint options that can take any value
1227 // (we use this object to detect invalid options)
1233 quotmark
: false, //'single'|'double'|true
1235 maxstatements
: false, // {int} max statements per function
1236 maxdepth
: false, // {int} max nested block depth per function
1237 maxparams
: false, // {int} max params per function
1238 maxcomplexity
: false, // {int} max cyclomatic complexity per function
1239 unused
: true, // warn if variables are unused. Available options:
1240 // false - don't check for unused variables
1241 // true - "vars" + check last function param
1242 // "vars" - skip checking unused function params
1243 // "strict" - "vars" + check all function params
1244 latedef
: false // warn if the variable is used before its definition
1245 // false - don't emit any warnings
1246 // true - warn if any variable is used before its definition
1247 // "nofunc" - warn for any variable but function declarations
1250 // These are JSHint boolean options which are shared with JSLint
1251 // where the definition in JSHint is opposite JSLint
1262 // Inverted and renamed, use JSHint name here
1268 // These are JSHint boolean options which are shared with JSLint
1269 // where the name has been changed but the effect is unchanged
1277 declared
, // Globals that were declared using /*global ... */ syntax.
1278 exported
, // Variables that are used outside of the current file.
1281 "closure", "exception", "global", "label",
1282 "outer", "unused", "var"
1285 funct
, // The current function
1286 functions
, // All of the functions
1288 global
, // The global scope
1289 implied
, // Implied globals
1297 predefined
, // Global variables defined by option
1299 scope
, // The current scope
1306 emitter
= new events
.EventEmitter();
1308 function checkOption(name
, t
) {
1311 if (/^[+-]W\d{3}$/g.test(name
)) {
1315 if (valOptions
[name
] === undefined && boolOptions
[name
] === undefined) {
1316 if (t
.type
!== "jslint") {
1317 error("E001", t
, name
);
1325 function isString(obj
) {
1326 return Object
.prototype.toString
.call(obj
) === "[object String]";
1329 function isIdentifier(tkn
, value
) {
1333 if (!tkn
.identifier
|| tkn
.value
!== value
)
1339 function isReserved(token
) {
1340 if (!token
.reserved
) {
1343 var meta
= token
.meta
;
1345 if (meta
&& meta
.isFutureReservedWord
&& state
.option
.inES5()) {
1346 // ES3 FutureReservedWord in an ES5 environment.
1351 // Some ES5 FutureReservedWord identifiers are active only
1352 // within a strict mode environment.
1353 if (meta
.strictOnly
) {
1354 if (!state
.option
.strict
&& !state
.directive
["use strict"]) {
1359 if (token
.isProperty
) {
1367 function supplant(str
, data
) {
1368 return str
.replace(/\{([^{}]*)\}/g, function (a
, b
) {
1370 return typeof r
=== "string" || typeof r
=== "number" ? r
: a
;
1374 function combine(t
, o
) {
1377 if (_
.has(o
, n
) && !_
.has(JSHINT
.blacklist
, n
)) {
1383 function updatePredefined() {
1384 Object
.keys(JSHINT
.blacklist
).forEach(function (key
) {
1385 delete predefined
[key
];
1390 if (state
.option
.es5
) {
1393 if (state
.option
.couch
) {
1394 combine(predefined
, vars
.couch
);
1397 if (state
.option
.rhino
) {
1398 combine(predefined
, vars
.rhino
);
1401 if (state
.option
.shelljs
) {
1402 combine(predefined
, vars
.shelljs
);
1403 combine(predefined
, vars
.node
);
1406 if (state
.option
.phantom
) {
1407 combine(predefined
, vars
.phantom
);
1410 if (state
.option
.prototypejs
) {
1411 combine(predefined
, vars
.prototypejs
);
1414 if (state
.option
.node
) {
1415 combine(predefined
, vars
.node
);
1418 if (state
.option
.devel
) {
1419 combine(predefined
, vars
.devel
);
1422 if (state
.option
.dojo
) {
1423 combine(predefined
, vars
.dojo
);
1426 if (state
.option
.browser
) {
1427 combine(predefined
, vars
.browser
);
1430 if (state
.option
.nonstandard
) {
1431 combine(predefined
, vars
.nonstandard
);
1434 if (state
.option
.jquery
) {
1435 combine(predefined
, vars
.jquery
);
1438 if (state
.option
.mootools
) {
1439 combine(predefined
, vars
.mootools
);
1442 if (state
.option
.worker
) {
1443 combine(predefined
, vars
.worker
);
1446 if (state
.option
.wsh
) {
1447 combine(predefined
, vars
.wsh
);
1450 if (state
.option
.globalstrict
&& state
.option
.strict
!== false) {
1451 state
.option
.strict
= true;
1454 if (state
.option
.yui
) {
1455 combine(predefined
, vars
.yui
);
1458 // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
1460 state
.option
.inMoz = function (strict
) {
1462 return state
.option
.moz
&& !state
.option
.esnext
;
1464 return state
.option
.moz
;
1467 state
.option
.inESNext = function (strict
) {
1469 return !state
.option
.moz
&& state
.option
.esnext
;
1471 return state
.option
.moz
|| state
.option
.esnext
;
1474 state
.option
.inES5 = function (/* strict */) {
1475 return !state
.option
.es3
;
1478 state
.option
.inES3 = function (strict
) {
1480 return !state
.option
.moz
&& !state
.option
.esnext
&& state
.option
.es3
;
1482 return state
.option
.es3
;
1486 // Produce an error warning.
1487 function quit(code
, line
, chr
) {
1488 var percentage
= Math
.floor((line
/ state
.lines
.length
) * 100);
1489 var message
= messages
.errors
[code
].desc
;
1492 name
: "JSHintError",
1495 message
: message
+ " (" + percentage
+ "% scanned).",
1501 function isundef(scope
, code
, token
, a
) {
1502 return JSHINT
.undefs
.push([scope
, code
, token
, a
]);
1505 function warning(code
, t
, a
, b
, c
, d
) {
1508 if (/^W\d{3}$/.test(code
)) {
1509 if (state
.ignored
[code
])
1512 msg
= messages
.warnings
[code
];
1513 } else if (/E\d{3}/.test(code
)) {
1514 msg
= messages
.errors
[code
];
1515 } else if (/I\d{3}/.test(code
)) {
1516 msg
= messages
.info
[code
];
1519 t
= t
|| state
.tokens
.next
;
1520 if (t
.id
=== "(end)") { // `~
1521 t
= state
.tokens
.curr
;
1531 evidence
: state
.lines
[l
- 1] || "",
1534 scope
: JSHINT
.scope
,
1541 w
.reason
= supplant(msg
.desc
, w
);
1542 JSHINT
.errors
.push(w
);
1544 if (state
.option
.passfail
) {
1545 quit("E042", l
, ch
);
1549 if (warnings
>= state
.option
.maxerr
) {
1550 quit("E043", l
, ch
);
1556 function warningAt(m
, l
, ch
, a
, b
, c
, d
) {
1563 function error(m
, t
, a
, b
, c
, d
) {
1564 warning(m
, t
, a
, b
, c
, d
);
1567 function errorAt(m
, l
, ch
, a
, b
, c
, d
) {
1574 // Tracking of "internal" scripts, like eval containing a static string
1575 function addInternalSrc(elem
, src
) {
1582 JSHINT
.internals
.push(i
);
1586 function addlabel(t
, type
, tkn
, islet
) {
1587 // Define t in the current function in the current scope.
1588 if (type
=== "exception") {
1589 if (_
.has(funct
["(context)"], t
)) {
1590 if (funct
[t
] !== true && !state
.option
.node
) {
1591 warning("W002", state
.tokens
.next
, t
);
1596 if (_
.has(funct
, t
) && !funct
["(global)"]) {
1597 if (funct
[t
] === true) {
1598 if (state
.option
.latedef
) {
1599 if ((state
.option
.latedef
=== true && _
.contains([funct
[t
], type
], "unction")) ||
1600 !_
.contains([funct
[t
], type
], "unction")) {
1601 warning("W003", state
.tokens
.next
, t
);
1605 if (!state
.option
.shadow
&& type
!== "exception" ||
1606 (funct
["(blockscope)"].getlabel(t
))) {
1607 warning("W004", state
.tokens
.next
, t
);
1612 // a double definition of a let variable in same block throws a TypeError
1613 if (funct
["(blockscope)"] && funct
["(blockscope)"].current
.has(t
)) {
1614 error("E044", state
.tokens
.next
, t
);
1617 // if the identifier is from a let, adds it only to the current blockscope
1619 funct
["(blockscope)"].current
.add(t
, type
, state
.tokens
.curr
);
1625 funct
["(tokens)"][t
] = tkn
;
1628 if (funct
["(global)"]) {
1630 if (_
.has(implied
, t
)) {
1631 if (state
.option
.latedef
) {
1632 if ((state
.option
.latedef
=== true && _
.contains([funct
[t
], type
], "unction")) ||
1633 !_
.contains([funct
[t
], type
], "unction")) {
1634 warning("W003", state
.tokens
.next
, t
);
1646 function doOption() {
1647 var nt
= state
.tokens
.next
;
1648 var body
= nt
.body
.split(",").map(function (s
) { return s
.trim(); });
1651 if (nt
.type
=== "globals") {
1652 body
.forEach(function (g
) {
1657 if (key
.charAt(0) === "-") {
1661 JSHINT
.blacklist
[key
] = key
;
1664 predef
[key
] = (val
=== "true");
1668 combine(predefined
, predef
);
1670 for (var key
in predef
) {
1671 if (_
.has(predef
, key
)) {
1677 if (nt
.type
=== "exported") {
1678 body
.forEach(function (e
) {
1683 if (nt
.type
=== "members") {
1684 membersOnly
= membersOnly
|| {};
1686 body
.forEach(function (m
) {
1687 var ch1
= m
.charAt(0);
1688 var ch2
= m
.charAt(m
.length
- 1);
1690 if (ch1
=== ch2
&& (ch1
=== "\"" || ch1
=== "'")) {
1692 .substr(1, m
.length
- 2)
1693 .replace("\\b", "\b")
1694 .replace("\\t", "\t")
1695 .replace("\\n", "\n")
1696 .replace("\\v", "\v")
1697 .replace("\\f", "\f")
1698 .replace("\\r", "\r")
1699 .replace("\\\\", "\\")
1700 .replace("\\\"", "\"");
1703 membersOnly
[m
] = false;
1717 if (nt
.type
=== "jshint" || nt
.type
=== "jslint") {
1718 body
.forEach(function (g
) {
1720 var key
= (g
[0] || "").trim();
1721 var val
= (g
[1] || "").trim();
1723 if (!checkOption(key
, nt
)) {
1727 if (numvals
.indexOf(key
) >= 0) {
1729 // GH988 - numeric options can be disabled by setting them to `false`
1730 if (val
!== "false") {
1733 if (typeof val
!== "number" || !isFinite(val
) || val
<= 0 || Math
.floor(val
) !== val
) {
1734 error("E032", nt
, g
[1].trim());
1738 if (key
=== "indent") {
1739 state
.option
["(explicitIndent)"] = true;
1741 state
.option
[key
] = val
;
1743 if (key
=== "indent") {
1744 state
.option
["(explicitIndent)"] = false;
1746 state
.option
[key
] = false;
1753 if (key
=== "validthis") {
1754 // `validthis` is valid only within a function scope.
1755 if (funct
["(global)"]) {
1758 if (val
=== "true" || val
=== "false") {
1759 state
.option
.validthis
= (val
=== "true");
1767 if (key
=== "quotmark") {
1771 state
.option
.quotmark
= (val
=== "true");
1775 state
.option
.quotmark
= val
;
1783 if (key
=== "unused") {
1786 state
.option
.unused
= true;
1789 state
.option
.unused
= false;
1793 state
.option
.unused
= val
;
1801 if (key
=== "latedef") {
1804 state
.option
.latedef
= true;
1807 state
.option
.latedef
= false;
1810 state
.option
.latedef
= "nofunc";
1818 var match
= /^([+-])(W\d{3})$/g.exec(key
);
1820 // ignore for -W..., unignore for +W...
1821 state
.ignored
[match
[2]] = (match
[1] === "-");
1826 if (val
=== "true" || val
=== "false") {
1827 if (nt
.type
=== "jslint") {
1828 tn
= renamedOptions
[key
] || key
;
1829 state
.option
[tn
] = (val
=== "true");
1831 if (invertedOptions
[tn
] !== undefined) {
1832 state
.option
[tn
] = !state
.option
[tn
];
1835 state
.option
[key
] = (val
=== "true");
1838 if (key
=== "newcap") {
1839 state
.option
["(explicitNewcap)"] = true;
1851 // We need a peek function. If it has an argument, it peeks that much farther
1852 // ahead. It is used to distinguish
1853 // for ( var i in ...
1855 // for ( var i = ...
1858 var i
= p
|| 0, j
= 0, t
;
1863 t
= lookahead
[j
] = lex
.token();
1870 // Produce the next token. It looks for programming errors.
1872 function advance(id
, t
) {
1873 switch (state
.tokens
.curr
.id
) {
1875 if (state
.tokens
.next
.id
=== ".") {
1876 warning("W005", state
.tokens
.curr
);
1880 if (state
.tokens
.next
.id
=== "-" || state
.tokens
.next
.id
=== "--") {
1885 if (state
.tokens
.next
.id
=== "+" || state
.tokens
.next
.id
=== "++") {
1891 if (state
.tokens
.curr
.type
=== "(string)" || state
.tokens
.curr
.identifier
) {
1892 anonname
= state
.tokens
.curr
.value
;
1895 if (id
&& state
.tokens
.next
.id
!== id
) {
1897 if (state
.tokens
.next
.id
=== "(end)") {
1898 error("E019", t
, t
.id
);
1900 error("E020", state
.tokens
.next
, id
, t
.id
, t
.line
, state
.tokens
.next
.value
);
1902 } else if (state
.tokens
.next
.type
!== "(identifier)" || state
.tokens
.next
.value
!== id
) {
1903 warning("W116", state
.tokens
.next
, id
, state
.tokens
.next
.value
);
1907 state
.tokens
.prev
= state
.tokens
.curr
;
1908 state
.tokens
.curr
= state
.tokens
.next
;
1910 state
.tokens
.next
= lookahead
.shift() || lex
.token();
1912 if (!state
.tokens
.next
) { // No more tokens left, give up
1913 quit("E041", state
.tokens
.curr
.line
);
1916 if (state
.tokens
.next
.id
=== "(end)" || state
.tokens
.next
.id
=== "(error)") {
1920 if (state
.tokens
.next
.check
) {
1921 state
.tokens
.next
.check();
1924 if (state
.tokens
.next
.isSpecial
) {
1927 if (state
.tokens
.next
.id
!== "(endline)") {
1934 function isInfix(token
) {
1935 return token
.infix
|| (!token
.identifier
&& !!token
.led
);
1938 function isEndOfExpr() {
1939 var curr
= state
.tokens
.curr
;
1940 var next
= state
.tokens
.next
;
1941 if (next
.id
=== ";" || next
.id
=== "}" || next
.id
=== ":") {
1944 if (isInfix(next
) === isInfix(curr
) || (curr
.id
=== "yield" && state
.option
.inMoz(true))) {
1945 return curr
.line
!== next
.line
;
1950 // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
1951 // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
1952 // like .nud except that it is only used on the first token of a statement.
1953 // Having .fud makes it much easier to define statement-oriented languages like
1954 // JavaScript. I retained Pratt's nomenclature.
1956 // .nud Null denotation
1957 // .fud First null denotation
1958 // .led Left denotation
1959 // lbp Left binding power
1960 // rbp Right binding power
1962 // They are elements of the parsing method called Top Down Operator Precedence.
1964 function expression(rbp
, initial
) {
1965 var left
, isArray
= false, isObject
= false, isLetExpr
= false;
1967 // if current expression is a let expression
1968 if (!initial
&& state
.tokens
.next
.value
=== "let" && peek(0).value
=== "(") {
1969 if (!state
.option
.inMoz(true)) {
1970 warning("W118", state
.tokens
.next
, "let expressions");
1973 // create a new block scope we use only for the current expression
1974 funct
["(blockscope)"].stack();
1977 state
.syntax
["let"].fud
.call(state
.syntax
["let"].fud
, false);
1981 if (state
.tokens
.next
.id
=== "(end)")
1982 error("E006", state
.tokens
.curr
);
1987 anonname
= "anonymous";
1988 funct
["(verb)"] = state
.tokens
.curr
.value
;
1991 if (initial
=== true && state
.tokens
.curr
.fud
) {
1992 left
= state
.tokens
.curr
.fud();
1994 if (state
.tokens
.curr
.nud
) {
1995 left
= state
.tokens
.curr
.nud();
1997 error("E030", state
.tokens
.curr
, state
.tokens
.curr
.id
);
2000 while (rbp
< state
.tokens
.next
.lbp
&& !isEndOfExpr()) {
2001 isArray
= state
.tokens
.curr
.value
=== "Array";
2002 isObject
= state
.tokens
.curr
.value
=== "Object";
2004 // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
2005 // Line breaks in IfStatement heads exist to satisfy the checkJSHint
2006 // "Line too long." error.
2007 if (left
&& (left
.value
|| (left
.first
&& left
.first
.value
))) {
2008 // If the left.value is not "new", or the left.first.value is a "."
2009 // then safely assume that this is not "new Array()" and possibly
2010 // not "new Object()"...
2011 if (left
.value
!== "new" ||
2012 (left
.first
&& left
.first
.value
&& left
.first
.value
=== ".")) {
2014 // ...In the case of Object, if the left.value and state.tokens.curr.value
2015 // are not equal, then safely assume that this not "new Object()"
2016 if (left
.value
!== state
.tokens
.curr
.value
) {
2024 if (isArray
&& state
.tokens
.curr
.id
=== "(" && state
.tokens
.next
.id
=== ")") {
2025 warning("W009", state
.tokens
.curr
);
2028 if (isObject
&& state
.tokens
.curr
.id
=== "(" && state
.tokens
.next
.id
=== ")") {
2029 warning("W010", state
.tokens
.curr
);
2032 if (left
&& state
.tokens
.curr
.led
) {
2033 left
= state
.tokens
.curr
.led(left
);
2035 error("E033", state
.tokens
.curr
, state
.tokens
.curr
.id
);
2040 funct
["(blockscope)"].unstack();
2046 // Functions for conformance of style.
2048 function adjacent(left
, right
) {
2049 left
= left
|| state
.tokens
.curr
;
2050 right
= right
|| state
.tokens
.next
;
2051 if (state
.option
.white
) {
2052 if (left
.character
!== right
.from && left
.line
=== right
.line
) {
2053 left
.from += (left
.character
- left
.from);
2054 warning("W011", left
, left
.value
);
2059 function nobreak(left
, right
) {
2060 left
= left
|| state
.tokens
.curr
;
2061 right
= right
|| state
.tokens
.next
;
2062 if (state
.option
.white
&& (left
.character
!== right
.from || left
.line
!== right
.line
)) {
2063 warning("W012", right
, right
.value
);
2067 function nospace(left
, right
) {
2068 left
= left
|| state
.tokens
.curr
;
2069 right
= right
|| state
.tokens
.next
;
2070 if (state
.option
.white
&& !left
.comment
) {
2071 if (left
.line
=== right
.line
) {
2072 adjacent(left
, right
);
2077 function nonadjacent(left
, right
) {
2078 if (state
.option
.white
) {
2079 left
= left
|| state
.tokens
.curr
;
2080 right
= right
|| state
.tokens
.next
;
2082 if (left
.value
=== ";" && right
.value
=== ";") {
2086 if (left
.line
=== right
.line
&& left
.character
=== right
.from) {
2087 left
.from += (left
.character
- left
.from);
2088 warning("W013", left
, left
.value
);
2093 function nobreaknonadjacent(left
, right
) {
2094 left
= left
|| state
.tokens
.curr
;
2095 right
= right
|| state
.tokens
.next
;
2096 if (!state
.option
.laxbreak
&& left
.line
!== right
.line
) {
2097 warning("W014", right
, right
.value
);
2098 } else if (state
.option
.white
) {
2099 left
= left
|| state
.tokens
.curr
;
2100 right
= right
|| state
.tokens
.next
;
2101 if (left
.character
=== right
.from) {
2102 left
.from += (left
.character
- left
.from);
2103 warning("W013", left
, left
.value
);
2108 function indentation(bias
) {
2109 if (!state
.option
.white
&& !state
.option
["(explicitIndent)"]) {
2113 if (state
.tokens
.next
.id
=== "(end)") {
2117 var i
= indent
+ (bias
|| 0);
2118 if (state
.tokens
.next
.from !== i
) {
2119 warning("W015", state
.tokens
.next
, state
.tokens
.next
.value
, i
, state
.tokens
.next
.from);
2123 function nolinebreak(t
) {
2124 t
= t
|| state
.tokens
.curr
;
2125 if (t
.line
!== state
.tokens
.next
.line
) {
2126 warning("E022", t
, t
.value
);
2130 function nobreakcomma(left
, right
) {
2131 if (left
.line
!== right
.line
) {
2132 if (!state
.option
.laxcomma
) {
2135 comma
.first
= false;
2137 warning("W014", left
, right
.value
);
2139 } else if (!left
.comment
&& left
.character
!== right
.from && state
.option
.white
) {
2140 left
.from += (left
.character
- left
.from);
2141 warning("W011", left
, left
.value
);
2145 function comma(opts
) {
2149 nobreakcomma(state
.tokens
.curr
, state
.tokens
.next
);
2152 nobreakcomma(state
.tokens
.prev
, state
.tokens
.curr
);
2155 // TODO: This is a temporary solution to fight against false-positives in
2156 // arrays and objects with trailing commas (see GH-363). The best solution
2157 // would be to extract all whitespace rules out of parser.
2159 if (state
.tokens
.next
.value
!== "]" && state
.tokens
.next
.value
!== "}") {
2160 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
2163 if (state
.tokens
.next
.identifier
&& !(opts
.property
&& state
.option
.inES5())) {
2164 // Keywords that cannot follow a comma operator.
2165 switch (state
.tokens
.next
.value
) {
2186 error("E024", state
.tokens
.next
, state
.tokens
.next
.value
);
2191 if (state
.tokens
.next
.type
=== "(punctuator)") {
2192 switch (state
.tokens
.next
.value
) {
2196 if (opts
.allowTrailing
) {
2202 error("E024", state
.tokens
.next
, state
.tokens
.next
.value
);
2209 // Functional constructors for making the symbols that will be inherited by
2212 function symbol(s
, p
) {
2213 var x
= state
.syntax
[s
];
2214 if (!x
|| typeof x
!== "object") {
2215 state
.syntax
[s
] = x
= {
2225 return symbol(s
, 0);
2228 function stmt(s
, f
) {
2230 x
.identifier
= x
.reserved
= true;
2235 function blockstmt(s
, f
) {
2241 function reserveName(x
) {
2242 var c
= x
.id
.charAt(0);
2243 if ((c
>= "a" && c
<= "z") || (c
>= "A" && c
<= "Z")) {
2244 x
.identifier
= x
.reserved
= true;
2249 function prefix(s
, f
) {
2250 var x
= symbol(s
, 150);
2252 x
.nud
= (typeof f
=== "function") ? f : function () {
2253 this.right
= expression(150);
2254 this.arity
= "unary";
2255 if (this.id
=== "++" || this.id
=== "--") {
2256 if (state
.option
.plusplus
) {
2257 warning("W016", this, this.id
);
2258 } else if ((!this.right
.identifier
|| isReserved(this.right
)) &&
2259 this.right
.id
!== "." && this.right
.id
!== "[") {
2260 warning("W017", this);
2268 function type(s
, f
) {
2275 function reserve(name
, func
) {
2276 var x
= type(name
, func
);
2277 x
.identifier
= true;
2282 function FutureReservedWord(name
, meta
) {
2283 var x
= type(name
, (meta
&& meta
.nud
) || function () {
2288 meta
.isFutureReservedWord
= true;
2291 x
.identifier
= true;
2298 function reservevar(s
, v
) {
2299 return reserve(s
, function () {
2300 if (typeof v
=== "function") {
2307 function infix(s
, f
, p
, w
) {
2308 var x
= symbol(s
, p
);
2311 x
.led = function (left
) {
2313 nobreaknonadjacent(state
.tokens
.prev
, state
.tokens
.curr
);
2314 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
2316 if (s
=== "in" && left
.id
=== "!") {
2317 warning("W018", left
, "!");
2319 if (typeof f
=== "function") {
2320 return f(left
, this);
2323 this.right
= expression(p
);
2331 function application(s
) {
2332 var x
= symbol(s
, 42);
2334 x
.led = function (left
) {
2335 if (!state
.option
.inESNext()) {
2336 warning("W104", state
.tokens
.curr
, "arrow function syntax (=>)");
2339 nobreaknonadjacent(state
.tokens
.prev
, state
.tokens
.curr
);
2340 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
2343 this.right
= doFunction(undefined, undefined, false, left
);
2349 function relation(s
, f
) {
2350 var x
= symbol(s
, 100);
2352 x
.led = function (left
) {
2353 nobreaknonadjacent(state
.tokens
.prev
, state
.tokens
.curr
);
2354 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
2355 var right
= expression(100);
2357 if (isIdentifier(left
, "NaN") || isIdentifier(right
, "NaN")) {
2358 warning("W019", this);
2360 f
.apply(this, [left
, right
]);
2363 if (!left
|| !right
) {
2364 quit("E041", state
.tokens
.curr
.line
);
2367 if (left
.id
=== "!") {
2368 warning("W018", left
, "!");
2371 if (right
.id
=== "!") {
2372 warning("W018", right
, "!");
2382 function isPoorRelation(node
) {
2384 ((node
.type
=== "(number)" && +node
.value
=== 0) ||
2385 (node
.type
=== "(string)" && node
.value
=== "") ||
2386 (node
.type
=== "null" && !state
.option
.eqnull
) ||
2387 node
.type
=== "true" ||
2388 node
.type
=== "false" ||
2389 node
.type
=== "undefined");
2392 function assignop(s
, f
, p
) {
2393 var x
= infix(s
, typeof f
=== "function" ? f : function (left
, that
) {
2397 if (predefined
[left
.value
] === false &&
2398 scope
[left
.value
]["(global)"] === true) {
2399 warning("W020", left
);
2400 } else if (left
["function"]) {
2401 warning("W021", left
, left
.value
);
2404 if (funct
[left
.value
] === "const") {
2405 error("E013", left
, left
.value
);
2408 if (left
.id
=== ".") {
2410 warning("E031", that
);
2411 } else if (left
.left
.value
=== "arguments" && !state
.directive
["use strict"]) {
2412 warning("E031", that
);
2415 that
.right
= expression(10);
2417 } else if (left
.id
=== "[") {
2418 if (state
.tokens
.curr
.left
.first
) {
2419 state
.tokens
.curr
.left
.first
.forEach(function (t
) {
2420 if (funct
[t
.value
] === "const") {
2421 error("E013", t
, t
.value
);
2424 } else if (!left
.left
) {
2425 warning("E031", that
);
2426 } else if (left
.left
.value
=== "arguments" && !state
.directive
["use strict"]) {
2427 warning("E031", that
);
2429 that
.right
= expression(10);
2431 } else if (left
.identifier
&& !isReserved(left
)) {
2432 if (funct
[left
.value
] === "exception") {
2433 warning("W022", left
);
2435 that
.right
= expression(10);
2439 if (left
=== state
.syntax
["function"]) {
2440 warning("W023", state
.tokens
.curr
);
2444 error("E031", that
);
2453 function bitwise(s
, f
, p
) {
2454 var x
= symbol(s
, p
);
2456 x
.led
= (typeof f
=== "function") ? f : function (left
) {
2457 if (state
.option
.bitwise
) {
2458 warning("W016", this, this.id
);
2461 this.right
= expression(p
);
2468 function bitwiseassignop(s
) {
2469 return assignop(s
, function (left
, that
) {
2470 if (state
.option
.bitwise
) {
2471 warning("W016", that
, that
.id
);
2473 nonadjacent(state
.tokens
.prev
, state
.tokens
.curr
);
2474 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
2476 if (left
.id
=== "." || left
.id
=== "[" ||
2477 (left
.identifier
&& !isReserved(left
))) {
2481 if (left
=== state
.syntax
["function"]) {
2482 warning("W023", state
.tokens
.curr
);
2486 error("E031", that
);
2491 function suffix(s
) {
2492 var x
= symbol(s
, 150);
2494 x
.led = function (left
) {
2495 if (state
.option
.plusplus
) {
2496 warning("W016", this, this.id
);
2497 } else if ((!left
.identifier
|| isReserved(left
)) && left
.id
!== "." && left
.id
!== "[") {
2498 warning("W017", this);
2507 // fnparam means that this identifier is being defined as a function
2508 // argument (see identifier())
2509 // prop means that this identifier is that of an object property
2511 function optionalidentifier(fnparam
, prop
) {
2512 if (!state
.tokens
.next
.identifier
) {
2518 var curr
= state
.tokens
.curr
;
2519 var val
= state
.tokens
.curr
.value
;
2521 if (!isReserved(curr
)) {
2526 if (state
.option
.inES5()) {
2531 if (fnparam
&& val
=== "undefined") {
2535 // Display an info message about reserved words as properties
2536 // and ES5 but do it only once.
2537 if (prop
&& !api
.getCache("displayed:I002")) {
2538 api
.setCache("displayed:I002", true);
2542 warning("W024", state
.tokens
.curr
, state
.tokens
.curr
.id
);
2546 // fnparam means that this identifier is being defined as a function
2548 // prop means that this identifier is that of an object property
2549 function identifier(fnparam
, prop
) {
2550 var i
= optionalidentifier(fnparam
, prop
);
2554 if (state
.tokens
.curr
.id
=== "function" && state
.tokens
.next
.id
=== "(") {
2557 error("E030", state
.tokens
.next
, state
.tokens
.next
.value
);
2562 function reachable(s
) {
2564 if (state
.tokens
.next
.id
!== ";" || noreach
) {
2572 if (t
.id
!== "(endline)") {
2573 if (t
.id
=== "function") {
2574 if (!state
.option
.latedef
) {
2582 warning("W027", t
, t
.value
, s
);
2590 function statement(noindent
) {
2592 var i
= indent
, r
, s
= scope
, t
= state
.tokens
.next
;
2599 // Is this a labelled statement?
2600 var res
= isReserved(t
);
2602 // We're being more tolerant here: if someone uses
2603 // a FutureReservedWord as a label, we warn but proceed
2606 if (res
&& t
.meta
&& t
.meta
.isFutureReservedWord
&& peek().id
=== ":") {
2607 warning("W024", t
, t
.id
);
2611 // detect a destructuring assignment
2612 if (_
.has(["[", "{"], t
.value
)) {
2613 if (lookupBlockType().isDestAssign
) {
2614 if (!state
.option
.inESNext()) {
2615 warning("W104", state
.tokens
.curr
, "destructuring expression");
2617 values
= destructuringExpression();
2618 values
.forEach(function (tok
) {
2619 isundef(funct
, "W117", tok
.token
, tok
.id
);
2622 destructuringExpressionMatch(values
, expression(10, true));
2627 if (t
.identifier
&& !res
&& peek().id
=== ":") {
2630 scope
= Object
.create(s
);
2631 addlabel(t
.value
, "label");
2633 if (!state
.tokens
.next
.labelled
&& state
.tokens
.next
.value
!== "{") {
2634 warning("W028", state
.tokens
.next
, t
.value
, state
.tokens
.next
.value
);
2637 state
.tokens
.next
.label
= t
.value
;
2638 t
= state
.tokens
.next
;
2641 // Is it a lonely block?
2648 // Parse the statement.
2653 r
= expression(0, true);
2655 // Look for the final semicolon.
2658 if (!state
.option
.expr
&& (!r
|| !r
.exps
)) {
2659 warning("W030", state
.tokens
.curr
);
2660 } else if (state
.option
.nonew
&& r
&& r
.left
&& r
.id
=== "(" && r
.left
.id
=== "new") {
2664 if (state
.tokens
.next
.id
!== ";") {
2665 if (!state
.option
.asi
) {
2666 // If this is the last statement in a block that ends on
2667 // the same line *and* option lastsemic is on, ignore the warning.
2668 // Otherwise, complain about missing semicolon.
2669 if (!state
.option
.lastsemic
|| state
.tokens
.next
.id
!== "}" ||
2670 state
.tokens
.next
.line
!== state
.tokens
.curr
.line
) {
2671 warningAt("W033", state
.tokens
.curr
.line
, state
.tokens
.curr
.character
);
2675 adjacent(state
.tokens
.curr
, state
.tokens
.next
);
2677 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
2681 // Restore the indentation.
2689 function statements(startLine
) {
2692 while (!state
.tokens
.next
.reach
&& state
.tokens
.next
.id
!== "(end)") {
2693 if (state
.tokens
.next
.id
=== ";") {
2696 if (!p
|| (p
.id
!== "(" && p
.id
!== "[")) {
2702 a
.push(statement(startLine
=== state
.tokens
.next
.line
));
2710 * read all directives
2711 * recognizes a simple form of asi, but always
2712 * warns, if it is used
2714 function directives() {
2718 if (state
.tokens
.next
.id
=== "(string)") {
2720 if (p
.id
=== "(endline)") {
2725 } while (pn
.id
=== "(endline)");
2727 if (pn
.id
!== ";") {
2728 if (pn
.id
!== "(string)" && pn
.id
!== "(number)" &&
2729 pn
.id
!== "(regexp)" && pn
.identifier
!== true &&
2733 warning("W033", state
.tokens
.next
);
2737 } else if (p
.id
=== "}") {
2738 // Directive with no other statements, warn about missing semicolon
2740 } else if (p
.id
!== ";") {
2746 if (state
.directive
[state
.tokens
.curr
.value
]) {
2747 warning("W034", state
.tokens
.curr
, state
.tokens
.curr
.value
);
2750 if (state
.tokens
.curr
.value
=== "use strict") {
2751 if (!state
.option
["(explicitNewcap)"])
2752 state
.option
.newcap
= true;
2753 state
.option
.undef
= true;
2756 // there's no directive negation, so always set to true
2757 state
.directive
[state
.tokens
.curr
.value
] = true;
2770 * Parses a single block. A block is a sequence of statements wrapped in
2773 * ordinary - true for everything but function bodies and try blocks.
2774 * stmt - true if block can be a single statement (e.g. in if/for/while).
2775 * isfunc - true if block is a function body
2777 function block(ordinary
, stmt
, isfunc
, isfatarrow
) {
2780 old_indent
= indent
,
2789 if (!ordinary
|| !state
.option
.funcscope
)
2790 scope
= Object
.create(scope
);
2792 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
2793 t
= state
.tokens
.next
;
2795 var metrics
= funct
["(metrics)"];
2796 metrics
.nestedBlockDepth
+= 1;
2797 metrics
.verifyMaxNestedBlockDepthPerFunction();
2799 if (state
.tokens
.next
.id
=== "{") {
2802 // create a new block scope
2803 funct
["(blockscope)"].stack();
2805 line
= state
.tokens
.curr
.line
;
2806 if (state
.tokens
.next
.id
!== "}") {
2807 indent
+= state
.option
.indent
;
2808 while (!ordinary
&& state
.tokens
.next
.from > indent
) {
2809 indent
+= state
.option
.indent
;
2814 for (d
in state
.directive
) {
2815 if (_
.has(state
.directive
, d
)) {
2816 m
[d
] = state
.directive
[d
];
2821 if (state
.option
.strict
&& funct
["(context)"]["(global)"]) {
2822 if (!m
["use strict"] && !state
.directive
["use strict"]) {
2828 a
= statements(line
);
2830 metrics
.statementCount
+= a
.length
;
2833 state
.directive
= m
;
2836 indent
-= state
.option
.indent
;
2837 if (line
!== state
.tokens
.next
.line
) {
2840 } else if (line
!== state
.tokens
.next
.line
) {
2845 funct
["(blockscope)"].unstack();
2847 indent
= old_indent
;
2848 } else if (!ordinary
) {
2851 if (stmt
&& !isfatarrow
&& !state
.option
.inMoz(true)) {
2852 error("W118", state
.tokens
.curr
, "function closure expressions");
2856 for (d
in state
.directive
) {
2857 if (_
.has(state
.directive
, d
)) {
2858 m
[d
] = state
.directive
[d
];
2864 if (state
.option
.strict
&& funct
["(context)"]["(global)"]) {
2865 if (!m
["use strict"] && !state
.directive
["use strict"]) {
2870 error("E021", state
.tokens
.next
, "{", state
.tokens
.next
.value
);
2874 // check to avoid let declaration not within a block
2875 funct
["(nolet)"] = true;
2877 if (!stmt
|| state
.option
.curly
) {
2878 warning("W116", state
.tokens
.next
, "{", state
.tokens
.next
.value
);
2882 indent
+= state
.option
.indent
;
2883 // test indentation only if statement is in new line
2884 a
= [statement(state
.tokens
.next
.line
=== state
.tokens
.curr
.line
)];
2885 indent
-= state
.option
.indent
;
2888 delete funct
["(nolet)"];
2890 funct
["(verb)"] = null;
2891 if (!ordinary
|| !state
.option
.funcscope
) scope
= s
;
2893 if (ordinary
&& state
.option
.noempty
&& (!a
|| a
.length
=== 0)) {
2896 metrics
.nestedBlockDepth
-= 1;
2901 function countMember(m
) {
2902 if (membersOnly
&& typeof membersOnly
[m
] !== "boolean") {
2903 warning("W036", state
.tokens
.curr
, m
);
2905 if (typeof member
[m
] === "number") {
2913 function note_implied(tkn
) {
2914 var name
= tkn
.value
, line
= tkn
.line
, a
= implied
[name
];
2915 if (typeof a
=== "function") {
2922 } else if (a
[a
.length
- 1] !== line
) {
2928 // Build the syntax table by declaring the syntactic elements of the language.
2930 type("(number)", function () {
2934 type("(string)", function () {
2938 state
.syntax
["(identifier)"] = {
2939 type
: "(identifier)",
2947 if (typeof s
=== "function") {
2948 // Protection against accidental inheritance.
2950 } else if (typeof s
=== "boolean") {
2952 funct
= functions
[0];
2958 if (_
.has(funct
, "(blockscope)")) {
2959 block
= funct
["(blockscope)"].getlabel(v
);
2962 // The name is in scope and defined in the current function.
2963 if (funct
=== s
|| block
) {
2964 // Change 'unused' to 'var', and reject labels.
2965 // the name is in a block scope
2966 switch (block
? block
[v
]["(type)"] : funct
[v
]) {
2968 if (block
) block
[v
]["(type)"] = "var";
2969 else funct
[v
] = "var";
2972 if (block
) block
[v
]["(type)"] = "function";
2973 else funct
[v
] = "function";
2974 this["function"] = true;
2977 this["function"] = true;
2980 warning("W037", state
.tokens
.curr
, v
);
2983 } else if (funct
["(global)"]) {
2984 // The name is not defined in the function. If we are in the global
2985 // scope, then we have an undefined variable.
2987 // Operators typeof and delete do not raise runtime errors even if
2988 // the base object of a reference is null so no need to display warning
2989 // if we're inside of typeof or delete.
2991 if (typeof predefined
[v
] !== "boolean") {
2992 // Attempting to subscript a null reference will throw an
2993 // error, even within the typeof and delete operators
2994 if (!(anonname
=== "typeof" || anonname
=== "delete") ||
2995 (state
.tokens
.next
&& (state
.tokens
.next
.value
=== "." ||
2996 state
.tokens
.next
.value
=== "["))) {
2998 // if we're in a list comprehension, variables are declared
2999 // locally and used before being defined. So we check
3000 // the presence of the given variable in the comp array
3001 // before declaring it undefined.
3003 if (!funct
["(comparray)"].check(v
)) {
3004 isundef(funct
, "W117", state
.tokens
.curr
, v
);
3009 note_implied(state
.tokens
.curr
);
3011 // If the name is already defined in the current
3012 // function, but not as outer, then there is a scope error.
3019 warning("W038", state
.tokens
.curr
, v
);
3022 warning("W037", state
.tokens
.curr
, v
);
3028 // If the name is defined in an outer function, make an outer entry,
3029 // and if it was unused, make it var.
3032 } else if (s
=== null) {
3033 warning("W039", state
.tokens
.curr
, v
);
3034 note_implied(state
.tokens
.curr
);
3035 } else if (typeof s
!== "object") {
3036 // Operators typeof and delete do not raise runtime errors even
3037 // if the base object of a reference is null so no need to
3039 // display warning if we're inside of typeof or delete.
3040 // Attempting to subscript a null reference will throw an
3041 // error, even within the typeof and delete operators
3042 if (!(anonname
=== "typeof" || anonname
=== "delete") ||
3043 (state
.tokens
.next
&&
3044 (state
.tokens
.next
.value
=== "." || state
.tokens
.next
.value
=== "["))) {
3046 isundef(funct
, "W117", state
.tokens
.curr
, v
);
3049 note_implied(state
.tokens
.curr
);
3054 this["function"] = true;
3056 funct
[v
] = s
["(global)"] ? "global" : "outer";
3061 funct
[v
] = s
["(global)"] ? "global" : "outer";
3064 funct
[v
] = s
["(global)"] ? "global" : "outer";
3067 warning("W037", state
.tokens
.curr
, v
);
3075 error("E033", state
.tokens
.next
, state
.tokens
.next
.value
);
3079 type("(regexp)", function () {
3083 // ECMAScript parser
3087 delim("(end)").reach
= true;
3088 delim("(error)").reach
= true;
3089 delim("}").reach
= true;
3092 delim("\"").reach
= true;
3093 delim("'").reach
= true;
3095 delim(":").reach
= true;
3099 reserve("case").reach
= true;
3101 reserve("default").reach
= true;
3103 reservevar("arguments", function (x
) {
3104 if (state
.directive
["use strict"] && funct
["(global)"]) {
3109 reservevar("false");
3110 reservevar("Infinity");
3112 reservevar("this", function (x
) {
3113 if (state
.directive
["use strict"] && !state
.option
.validthis
&& ((funct
["(statement)"] &&
3114 funct
["(name)"].charAt(0) > "Z") || funct
["(global)"])) {
3119 reservevar("undefined");
3121 assignop("=", "assign", 20);
3122 assignop("+=", "assignadd", 20);
3123 assignop("-=", "assignsub", 20);
3124 assignop("*=", "assignmult", 20);
3125 assignop("/=", "assigndiv", 20).nud = function () {
3128 assignop("%=", "assignmod", 20);
3130 bitwiseassignop("&=", "assignbitand", 20);
3131 bitwiseassignop("|=", "assignbitor", 20);
3132 bitwiseassignop("^=", "assignbitxor", 20);
3133 bitwiseassignop("<<=", "assignshiftleft", 20);
3134 bitwiseassignop(">>=", "assignshiftright", 20);
3135 bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
3136 infix(",", function (left
, that
) {
3138 that
.exprs
= [left
];
3139 if (!comma({peek
: true})) {
3143 if (!(expr
= expression(10))) {
3146 that
.exprs
.push(expr
);
3147 if (state
.tokens
.next
.value
!== "," || !comma()) {
3154 infix("?", function (left
, that
) {
3155 increaseComplexityCount();
3157 that
.right
= expression(10);
3159 that
["else"] = expression(10);
3163 var orPrecendence
= 40;
3164 infix("||", function (left
, that
) {
3165 increaseComplexityCount();
3167 that
.right
= expression(orPrecendence
);
3170 infix("&&", "and", 50);
3171 bitwise("|", "bitor", 70);
3172 bitwise("^", "bitxor", 80);
3173 bitwise("&", "bitand", 90);
3174 relation("==", function (left
, right
) {
3175 var eqnull
= state
.option
.eqnull
&& (left
.value
=== "null" || right
.value
=== "null");
3177 if (!eqnull
&& state
.option
.eqeqeq
)
3178 warning("W116", this, "===", "==");
3179 else if (isPoorRelation(left
))
3180 warning("W041", this, "===", left
.value
);
3181 else if (isPoorRelation(right
))
3182 warning("W041", this, "===", right
.value
);
3187 relation("!=", function (left
, right
) {
3188 var eqnull
= state
.option
.eqnull
&&
3189 (left
.value
=== "null" || right
.value
=== "null");
3191 if (!eqnull
&& state
.option
.eqeqeq
) {
3192 warning("W116", this, "!==", "!=");
3193 } else if (isPoorRelation(left
)) {
3194 warning("W041", this, "!==", left
.value
);
3195 } else if (isPoorRelation(right
)) {
3196 warning("W041", this, "!==", right
.value
);
3205 bitwise("<<", "shiftleft", 120);
3206 bitwise(">>", "shiftright", 120);
3207 bitwise(">>>", "shiftrightunsigned", 120);
3208 infix("in", "in", 120);
3209 infix("instanceof", "instanceof", 120);
3210 infix("+", function (left
, that
) {
3211 var right
= expression(130);
3212 if (left
&& right
&& left
.id
=== "(string)" && right
.id
=== "(string)") {
3213 left
.value
+= right
.value
;
3214 left
.character
= right
.character
;
3215 if (!state
.option
.scripturl
&& reg
.javascriptURL
.test(left
.value
)) {
3216 warning("W050", left
);
3225 prefix("+++", function () {
3227 this.right
= expression(150);
3228 this.arity
= "unary";
3231 infix("+++", function (left
) {
3234 this.right
= expression(130);
3237 infix("-", "sub", 130);
3239 prefix("---", function () {
3241 this.right
= expression(150);
3242 this.arity
= "unary";
3245 infix("---", function (left
) {
3248 this.right
= expression(130);
3251 infix("*", "mult", 140);
3252 infix("/", "div", 140);
3253 infix("%", "mod", 140);
3255 suffix("++", "postinc");
3256 prefix("++", "preinc");
3257 state
.syntax
["++"].exps
= true;
3259 suffix("--", "postdec");
3260 prefix("--", "predec");
3261 state
.syntax
["--"].exps
= true;
3262 prefix("delete", function () {
3263 var p
= expression(10);
3264 if (!p
|| (p
.id
!== "." && p
.id
!== "[")) {
3271 prefix("~", function () {
3272 if (state
.option
.bitwise
) {
3273 warning("W052", this, "~");
3279 prefix("...", function () {
3280 if (!state
.option
.inESNext()) {
3281 warning("W104", this, "spread/rest operator");
3283 if (!state
.tokens
.next
.identifier
) {
3284 error("E030", state
.tokens
.next
, state
.tokens
.next
.value
);
3290 prefix("!", function () {
3291 this.right
= expression(150);
3292 this.arity
= "unary";
3294 if (!this.right
) { // '!' followed by nothing? Give up.
3295 quit("E041", this.line
|| 0);
3298 if (bang
[this.right
.id
] === true) {
3299 warning("W018", this, "!");
3304 prefix("typeof", "typeof");
3305 prefix("new", function () {
3306 var c
= expression(155), i
;
3307 if (c
&& c
.id
!== "function") {
3316 warning("W053", state
.tokens
.prev
, c
.value
);
3319 if (!state
.option
.evil
) {
3327 if (c
.id
!== "function") {
3328 i
= c
.value
.substr(0, 1);
3329 if (state
.option
.newcap
&& (i
< "A" || i
> "Z") && !_
.has(global
, c
.value
)) {
3330 warning("W055", state
.tokens
.curr
);
3335 if (c
.id
!== "." && c
.id
!== "[" && c
.id
!== "(") {
3336 warning("W056", state
.tokens
.curr
);
3340 if (!state
.option
.supernew
)
3341 warning("W057", this);
3343 adjacent(state
.tokens
.curr
, state
.tokens
.next
);
3344 if (state
.tokens
.next
.id
!== "(" && !state
.option
.supernew
) {
3345 warning("W058", state
.tokens
.curr
, state
.tokens
.curr
.value
);
3350 state
.syntax
["new"].exps
= true;
3352 prefix("void").exps
= true;
3354 infix(".", function (left
, that
) {
3355 adjacent(state
.tokens
.prev
, state
.tokens
.curr
);
3357 var m
= identifier(false, true);
3359 if (typeof m
=== "string") {
3366 if (m
&& m
=== "hasOwnProperty" && state
.tokens
.next
.value
=== "=") {
3370 if (left
&& left
.value
=== "arguments" && (m
=== "callee" || m
=== "caller")) {
3371 if (state
.option
.noarg
)
3372 warning("W059", left
, m
);
3373 else if (state
.directive
["use strict"])
3375 } else if (!state
.option
.evil
&& left
&& left
.value
=== "document" &&
3376 (m
=== "write" || m
=== "writeln")) {
3377 warning("W060", left
);
3380 if (!state
.option
.evil
&& (m
=== "eval" || m
=== "execScript")) {
3387 infix("(", function (left
, that
) {
3388 if (state
.tokens
.prev
.id
!== "}" && state
.tokens
.prev
.id
!== ")") {
3389 nobreak(state
.tokens
.prev
, state
.tokens
.curr
);
3393 if (state
.option
.immed
&& left
&& !left
.immed
&& left
.id
=== "function") {
3401 if (left
.type
=== "(identifier)") {
3402 if (left
.value
.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
3403 if ("Number String Boolean Date Object".indexOf(left
.value
) === -1) {
3404 if (left
.value
=== "Math") {
3405 warning("W063", left
);
3406 } else if (state
.option
.newcap
) {
3407 warning("W064", left
);
3414 if (state
.tokens
.next
.id
!== ")") {
3416 p
[p
.length
] = expression(10);
3418 if (state
.tokens
.next
.id
!== ",") {
3426 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
3428 if (typeof left
=== "object") {
3429 if (left
.value
=== "parseInt" && n
=== 1) {
3430 warning("W065", state
.tokens
.curr
);
3432 if (!state
.option
.evil
) {
3433 if (left
.value
=== "eval" || left
.value
=== "Function" ||
3434 left
.value
=== "execScript") {
3435 warning("W061", left
);
3437 if (p
[0] && [0].id
=== "(string)") {
3438 addInternalSrc(left
, p
[0].value
);
3440 } else if (p
[0] && p
[0].id
=== "(string)" &&
3441 (left
.value
=== "setTimeout" ||
3442 left
.value
=== "setInterval")) {
3443 warning("W066", left
);
3444 addInternalSrc(left
, p
[0].value
);
3446 // window.setTimeout/setInterval
3447 } else if (p
[0] && p
[0].id
=== "(string)" &&
3448 left
.value
=== "." &&
3449 left
.left
.value
=== "window" &&
3450 (left
.right
=== "setTimeout" ||
3451 left
.right
=== "setInterval")) {
3452 warning("W066", left
);
3453 addInternalSrc(left
, p
[0].value
);
3456 if (!left
.identifier
&& left
.id
!== "." && left
.id
!== "[" &&
3457 left
.id
!== "(" && left
.id
!== "&&" && left
.id
!== "||" &&
3459 warning("W067", left
);
3465 }, 155, true).exps
= true;
3467 prefix("(", function () {
3469 var bracket
, brackets
= [];
3478 } while (pn
.value
!== ")" && pn1
.value
!== "=>" && pn1
.value
!== ";" && pn1
.type
!== "(end)");
3480 if (state
.tokens
.next
.id
=== "function") {
3481 state
.tokens
.next
.immed
= true;
3486 if (state
.tokens
.next
.id
!== ")") {
3488 if (pn1
.value
=== "=>" && state
.tokens
.next
.value
=== "{") {
3489 bracket
= state
.tokens
.next
;
3490 bracket
.left
= destructuringExpression();
3491 brackets
.push(bracket
);
3492 for (var t
in bracket
.left
) {
3493 exprs
.push(bracket
.left
[t
].token
);
3496 exprs
.push(expression(10));
3498 if (state
.tokens
.next
.id
!== ",") {
3506 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
3507 if (state
.option
.immed
&& exprs
[0] && exprs
[0].id
=== "function") {
3508 if (state
.tokens
.next
.id
!== "(" &&
3509 (state
.tokens
.next
.id
!== "." || (peek().value
!== "call" && peek().value
!== "apply"))) {
3510 warning("W068", this);
3514 if (state
.tokens
.next
.value
=== "=>") {
3517 if (!exprs
.length
) {
3520 if (exprs
.length
> 1) {
3521 ret
= Object
.create(state
.syntax
[","]);
3534 infix("[", function (left
, that
) {
3535 nobreak(state
.tokens
.prev
, state
.tokens
.curr
);
3537 var e
= expression(10), s
;
3538 if (e
&& e
.type
=== "(string)") {
3539 if (!state
.option
.evil
&& (e
.value
=== "eval" || e
.value
=== "execScript")) {
3540 warning("W061", that
);
3543 countMember(e
.value
);
3544 if (!state
.option
.sub
&& reg
.identifier
.test(e
.value
)) {
3545 s
= state
.syntax
[e
.value
];
3546 if (!s
|| !isReserved(s
)) {
3547 warning("W069", state
.tokens
.prev
, e
.value
);
3553 if (e
&& e
.value
=== "hasOwnProperty" && state
.tokens
.next
.value
=== "=") {
3557 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
3563 function comprehensiveArrayExpression() {
3566 funct
["(comparray)"].stack();
3568 res
.right
= expression(10);
3570 if (state
.tokens
.next
.value
=== "each") {
3572 if (!state
.option
.inMoz(true)) {
3573 warning("W118", state
.tokens
.curr
, "for each");
3577 funct
["(comparray)"].setState("define");
3578 res
.left
= expression(10);
3580 if (state
.tokens
.next
.value
=== "if") {
3583 funct
["(comparray)"].setState("filter");
3584 res
.filter
= expression(10);
3588 funct
["(comparray)"].unstack();
3592 prefix("[", function () {
3593 var blocktype
= lookupBlockType(true);
3594 if (blocktype
.isCompArray
) {
3595 if (!state
.option
.inMoz(true)) {
3596 warning("W118", state
.tokens
.curr
, "array comprehension");
3598 return comprehensiveArrayExpression();
3599 } else if (blocktype
.isDestAssign
&& !state
.option
.inESNext()) {
3600 warning("W104", state
.tokens
.curr
, "destructuring assignment");
3602 var b
= state
.tokens
.curr
.line
!== state
.tokens
.next
.line
;
3605 indent
+= state
.option
.indent
;
3606 if (state
.tokens
.next
.from === indent
+ state
.option
.indent
) {
3607 indent
+= state
.option
.indent
;
3610 while (state
.tokens
.next
.id
!== "(end)") {
3611 while (state
.tokens
.next
.id
=== ",") {
3612 if (!state
.option
.inES5())
3616 if (state
.tokens
.next
.id
=== "]") {
3619 if (b
&& state
.tokens
.curr
.line
!== state
.tokens
.next
.line
) {
3622 this.first
.push(expression(10));
3623 if (state
.tokens
.next
.id
=== ",") {
3624 comma({ allowTrailing
: true });
3625 if (state
.tokens
.next
.id
=== "]" && !state
.option
.inES5(true)) {
3626 warning("W070", state
.tokens
.curr
);
3634 indent
-= state
.option
.indent
;
3642 function property_name() {
3643 var id
= optionalidentifier(false, true);
3646 if (state
.tokens
.next
.id
=== "(string)") {
3647 id
= state
.tokens
.next
.value
;
3649 } else if (state
.tokens
.next
.id
=== "(number)") {
3650 id
= state
.tokens
.next
.value
.toString();
3655 if (id
=== "hasOwnProperty") {
3663 function functionparams(parsed
) {
3669 var pastDefault
= false;
3672 if (parsed
instanceof Array
) {
3673 for (var i
in parsed
) {
3675 if (_
.contains(["{", "["], curr
.id
)) {
3676 for (t
in curr
.left
) {
3680 addlabel(t
.id
, "unused", t
.token
);
3683 } else if (curr
.value
=== "...") {
3684 if (!state
.option
.inESNext()) {
3685 warning("W104", curr
, "spread/rest operator");
3689 addlabel(curr
.value
, "unused", curr
);
3694 if (parsed
.identifier
=== true) {
3695 addlabel(parsed
.value
, "unused", parsed
);
3701 next
= state
.tokens
.next
;
3706 if (state
.tokens
.next
.id
=== ")") {
3712 if (_
.contains(["{", "["], state
.tokens
.next
.id
)) {
3713 tokens
= destructuringExpression();
3718 addlabel(t
.id
, "unused", t
.token
);
3721 } else if (state
.tokens
.next
.value
=== "...") {
3722 if (!state
.option
.inESNext()) {
3723 warning("W104", state
.tokens
.next
, "spread/rest operator");
3727 ident
= identifier(true);
3729 addlabel(ident
, "unused", state
.tokens
.curr
);
3731 ident
= identifier(true);
3733 addlabel(ident
, "unused", state
.tokens
.curr
);
3736 // it is a syntax error to have a regular argument after a default argument
3738 if (state
.tokens
.next
.id
!== "=") {
3739 error("E051", state
.tokens
.current
);
3742 if (state
.tokens
.next
.id
=== "=") {
3743 if (!state
.option
.inESNext()) {
3744 warning("W119", state
.tokens
.next
, "default parameters");
3750 if (state
.tokens
.next
.id
=== ",") {
3754 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
3761 function doFunction(name
, statement
, generator
, fatarrowparams
) {
3763 var oldOption
= state
.option
;
3764 var oldIgnored
= state
.ignored
;
3765 var oldScope
= scope
;
3767 state
.option
= Object
.create(state
.option
);
3768 state
.ignored
= Object
.create(state
.ignored
);
3769 scope
= Object
.create(scope
);
3772 "(name)" : name
|| "\"" + anonname
+ "\"",
3773 "(line)" : state
.tokens
.next
.line
,
3774 "(character)" : state
.tokens
.next
.character
,
3775 "(context)" : funct
,
3778 "(metrics)" : createMetrics(state
.tokens
.next
),
3780 "(statement)" : statement
,
3782 "(blockscope)": funct
["(blockscope)"],
3783 "(comparray)" : funct
["(comparray)"]
3787 funct
["(generator)"] = true;
3791 state
.tokens
.curr
.funct
= funct
;
3793 functions
.push(funct
);
3796 addlabel(name
, "function");
3799 funct
["(params)"] = functionparams(fatarrowparams
);
3801 funct
["(metrics)"].verifyMaxParametersPerFunction(funct
["(params)"]);
3803 block(false, true, true, fatarrowparams
? true:false);
3805 if (generator
&& funct
["(generator)"] !== "yielded") {
3806 error("E047", state
.tokens
.curr
);
3809 funct
["(metrics)"].verifyMaxStatementsPerFunction();
3810 funct
["(metrics)"].verifyMaxComplexityPerFunction();
3811 funct
["(unusedOption)"] = state
.option
.unused
;
3814 state
.option
= oldOption
;
3815 state
.ignored
= oldIgnored
;
3816 funct
["(last)"] = state
.tokens
.curr
.line
;
3817 funct
["(lastcharacter)"] = state
.tokens
.curr
.character
;
3818 funct
= funct
["(context)"];
3823 function createMetrics(functionStartToken
) {
3826 nestedBlockDepth
: -1,
3828 verifyMaxStatementsPerFunction: function () {
3829 if (state
.option
.maxstatements
&&
3830 this.statementCount
> state
.option
.maxstatements
) {
3831 warning("W071", functionStartToken
, this.statementCount
);
3835 verifyMaxParametersPerFunction: function (params
) {
3836 params
= params
|| [];
3838 if (state
.option
.maxparams
&& params
.length
> state
.option
.maxparams
) {
3839 warning("W072", functionStartToken
, params
.length
);
3843 verifyMaxNestedBlockDepthPerFunction: function () {
3844 if (state
.option
.maxdepth
&&
3845 this.nestedBlockDepth
> 0 &&
3846 this.nestedBlockDepth
=== state
.option
.maxdepth
+ 1) {
3847 warning("W073", null, this.nestedBlockDepth
);
3851 verifyMaxComplexityPerFunction: function () {
3852 var max
= state
.option
.maxcomplexity
;
3853 var cc
= this.ComplexityCount
;
3854 if (max
&& cc
> max
) {
3855 warning("W074", functionStartToken
, cc
);
3861 function increaseComplexityCount() {
3862 funct
["(metrics)"].ComplexityCount
+= 1;
3865 // Parse assignments that were found instead of conditionals.
3866 // For example: if (a = 1) { ... }
3868 function checkCondAssignment(expr
) {
3873 if (id
=== "," && (expr
= expr
.exprs
[expr
.exprs
.length
- 1])) {
3875 paren
= paren
|| expr
.paren
;
3888 if (!paren
&& !state
.option
.boss
) {
3896 x
.nud = function (isclassdef
) {
3897 var b
, f
, i
, p
, t
, g
;
3898 var props
= {}; // All properties, including accessors
3901 function saveProperty(name
, tkn
) {
3902 if (props
[name
] && _
.has(props
, name
))
3903 warning("W075", state
.tokens
.next
, i
);
3907 props
[name
].basic
= true;
3908 props
[name
].basictkn
= tkn
;
3911 function saveSetter(name
, tkn
) {
3912 if (props
[name
] && _
.has(props
, name
)) {
3913 if (props
[name
].basic
|| props
[name
].setter
)
3914 warning("W075", state
.tokens
.next
, i
);
3919 props
[name
].setter
= true;
3920 props
[name
].setterToken
= tkn
;
3923 function saveGetter(name
) {
3924 if (props
[name
] && _
.has(props
, name
)) {
3925 if (props
[name
].basic
|| props
[name
].getter
)
3926 warning("W075", state
.tokens
.next
, i
);
3931 props
[name
].getter
= true;
3932 props
[name
].getterToken
= state
.tokens
.curr
;
3935 b
= state
.tokens
.curr
.line
!== state
.tokens
.next
.line
;
3937 indent
+= state
.option
.indent
;
3938 if (state
.tokens
.next
.from === indent
+ state
.option
.indent
) {
3939 indent
+= state
.option
.indent
;
3944 if (state
.tokens
.next
.id
=== "}") {
3952 if (isclassdef
&& state
.tokens
.next
.value
=== "static") {
3957 if (state
.tokens
.next
.value
=== "get" && peek().id
!== ":") {
3960 if (!state
.option
.inES5(!isclassdef
)) {
3964 i
= property_name();
3969 // It is a Syntax Error if PropName of MethodDefinition is
3970 // "constructor" and SpecialMethod of MethodDefinition is true.
3971 if (isclassdef
&& i
=== "constructor") {
3972 error("E049", state
.tokens
.next
, "class getter method", i
);
3975 saveGetter(tag
+ i
);
3976 t
= state
.tokens
.next
;
3977 adjacent(state
.tokens
.curr
, state
.tokens
.next
);
3982 warning("W076", t
, p
[0], i
);
3985 adjacent(state
.tokens
.curr
, state
.tokens
.next
);
3986 } else if (state
.tokens
.next
.value
=== "set" && peek().id
!== ":") {
3989 if (!state
.option
.inES5(!isclassdef
)) {
3993 i
= property_name();
3998 // It is a Syntax Error if PropName of MethodDefinition is
3999 // "constructor" and SpecialMethod of MethodDefinition is true.
4000 if (isclassdef
&& i
=== "constructor") {
4001 error("E049", state
.tokens
.next
, "class setter method", i
);
4004 saveSetter(tag
+ i
, state
.tokens
.next
);
4005 t
= state
.tokens
.next
;
4006 adjacent(state
.tokens
.curr
, state
.tokens
.next
);
4010 if (!p
|| p
.length
!== 1) {
4011 warning("W077", t
, i
);
4015 if (state
.tokens
.next
.value
=== "*" && state
.tokens
.next
.type
=== "(punctuator)") {
4016 if (!state
.option
.inESNext()) {
4017 warning("W104", state
.tokens
.next
, "generator functions");
4022 i
= property_name();
4023 saveProperty(tag
+ i
, state
.tokens
.next
);
4025 if (typeof i
!== "string") {
4029 if (state
.tokens
.next
.value
=== "(") {
4030 if (!state
.option
.inESNext()) {
4031 warning("W104", state
.tokens
.curr
, "concise methods");
4033 doFunction(i
, undefined, g
);
4034 } else if (!isclassdef
) {
4036 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4040 // It is a Syntax Error if PropName of MethodDefinition is "prototype".
4041 if (isclassdef
&& i
=== "prototype") {
4042 error("E049", state
.tokens
.next
, "class method", i
);
4050 if (state
.tokens
.next
.id
=== ",") {
4051 comma({ allowTrailing
: true, property
: true });
4052 if (state
.tokens
.next
.id
=== ",") {
4053 warning("W070", state
.tokens
.curr
);
4054 } else if (state
.tokens
.next
.id
=== "}" && !state
.option
.inES5(true)) {
4055 warning("W070", state
.tokens
.curr
);
4062 indent
-= state
.option
.indent
;
4067 // Check for lonely setters if in the ES5 mode.
4068 if (state
.option
.inES5()) {
4069 for (var name
in props
) {
4070 if (_
.has(props
, name
) && props
[name
].setter
&& !props
[name
].getter
) {
4071 warning("W078", props
[name
].setterToken
);
4077 x
.fud = function () {
4078 error("E036", state
.tokens
.curr
);
4082 function destructuringExpression() {
4084 var identifiers
= [];
4085 if (!state
.option
.inESNext()) {
4086 warning("W104", state
.tokens
.curr
, "destructuring expression");
4088 var nextInnerDE = function () {
4090 if (_
.contains(["[", "{"], state
.tokens
.next
.value
)) {
4091 ids
= destructuringExpression();
4092 for (var id
in ids
) {
4094 identifiers
.push({ id
: id
.id
, token
: id
.token
});
4096 } else if (state
.tokens
.next
.value
=== ",") {
4097 identifiers
.push({ id
: null, token
: state
.tokens
.curr
});
4099 ident
= identifier();
4101 identifiers
.push({ id
: ident
, token
: state
.tokens
.curr
});
4104 if (state
.tokens
.next
.value
=== "[") {
4107 while (state
.tokens
.next
.value
!== "]") {
4112 } else if (state
.tokens
.next
.value
=== "{") {
4115 if (state
.tokens
.next
.value
=== ":") {
4119 identifiers
.push({ id
: id
, token
: state
.tokens
.curr
});
4121 while (state
.tokens
.next
.value
!== "}") {
4124 if (state
.tokens
.next
.value
=== ":") {
4128 identifiers
.push({ id
: id
, token
: state
.tokens
.curr
});
4135 function destructuringExpressionMatch(tokens
, value
) {
4137 _
.zip(tokens
, value
.first
).forEach(function (val
) {
4140 if (token
&& value
) {
4141 token
.first
= value
;
4142 } else if (token
&& token
.first
&& !value
) {
4143 warning("W080", token
.first
, token
.first
.value
);
4145 XXX value is discarded: wouldn't it need a warning ?
4151 var conststatement
= stmt("const", function (prefix
) {
4153 // state variable to know if it is a lone identifier, or a destructuring statement.
4156 if (!state
.option
.inESNext()) {
4157 warning("W104", state
.tokens
.curr
, "const");
4163 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4164 if (_
.contains(["{", "["], state
.tokens
.next
.value
)) {
4165 tokens
= destructuringExpression();
4168 tokens
= [ { id
: identifier(), token
: state
.tokens
.curr
} ];
4171 for (var t
in tokens
) {
4173 if (funct
[t
.id
] === "const") {
4174 warning("E011", null, t
.id
);
4176 if (funct
["(global)"] && predefined
[t
.id
] === false) {
4177 warning("W079", t
.token
, t
.id
);
4180 addlabel(t
.id
, "const");
4181 names
.push(t
.token
);
4188 this.first
= this.first
.concat(names
);
4190 if (state
.tokens
.next
.id
!== "=") {
4191 warning("E012", state
.tokens
.curr
, state
.tokens
.curr
.value
);
4194 if (state
.tokens
.next
.id
=== "=") {
4195 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4197 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4198 if (state
.tokens
.next
.id
=== "undefined") {
4199 warning("W080", state
.tokens
.prev
, state
.tokens
.prev
.value
);
4201 if (peek(0).id
=== "=" && state
.tokens
.next
.identifier
) {
4202 warning("W120", state
.tokens
.next
, state
.tokens
.next
.value
);
4204 value
= expression(10);
4206 tokens
[0].first
= value
;
4208 destructuringExpressionMatch(names
, value
);
4212 if (state
.tokens
.next
.id
!== ",") {
4219 conststatement
.exps
= true;
4220 var varstatement
= stmt("var", function (prefix
) {
4221 // JavaScript does not have block scope. It only has function scope. So,
4222 // declaring a variable in a block can have unexpected consequences.
4223 var tokens
, lone
, value
;
4225 if (funct
["(onevar)"] && state
.option
.onevar
) {
4227 } else if (!funct
["(global)"]) {
4228 funct
["(onevar)"] = true;
4234 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4235 if (_
.contains(["{", "["], state
.tokens
.next
.value
)) {
4236 tokens
= destructuringExpression();
4239 tokens
= [ { id
: identifier(), token
: state
.tokens
.curr
} ];
4242 for (var t
in tokens
) {
4244 if (state
.option
.inESNext() && funct
[t
.id
] === "const") {
4245 warning("E011", null, t
.id
);
4247 if (funct
["(global)"] && predefined
[t
.id
] === false) {
4248 warning("W079", t
.token
, t
.id
);
4251 addlabel(t
.id
, "unused", t
.token
);
4252 names
.push(t
.token
);
4259 this.first
= this.first
.concat(names
);
4261 if (state
.tokens
.next
.id
=== "=") {
4262 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4264 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4265 if (state
.tokens
.next
.id
=== "undefined") {
4266 warning("W080", state
.tokens
.prev
, state
.tokens
.prev
.value
);
4268 if (peek(0).id
=== "=" && state
.tokens
.next
.identifier
) {
4269 warning("W120", state
.tokens
.next
, state
.tokens
.next
.value
);
4271 value
= expression(10);
4273 tokens
[0].first
= value
;
4275 destructuringExpressionMatch(names
, value
);
4279 if (state
.tokens
.next
.id
!== ",") {
4286 varstatement
.exps
= true;
4287 var letstatement
= stmt("let", function (prefix
) {
4288 var tokens
, lone
, value
, letblock
;
4290 if (!state
.option
.inESNext()) {
4291 warning("W104", state
.tokens
.curr
, "let");
4294 if (state
.tokens
.next
.value
=== "(") {
4295 if (!state
.option
.inMoz(true)) {
4296 warning("W118", state
.tokens
.next
, "let block");
4299 funct
["(blockscope)"].stack();
4301 } else if (funct
["(nolet)"]) {
4302 error("E048", state
.tokens
.curr
);
4305 if (funct
["(onevar)"] && state
.option
.onevar
) {
4307 } else if (!funct
["(global)"]) {
4308 funct
["(onevar)"] = true;
4314 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4315 if (_
.contains(["{", "["], state
.tokens
.next
.value
)) {
4316 tokens
= destructuringExpression();
4319 tokens
= [ { id
: identifier(), token
: state
.tokens
.curr
.value
} ];
4322 for (var t
in tokens
) {
4324 if (state
.option
.inESNext() && funct
[t
.id
] === "const") {
4325 warning("E011", null, t
.id
);
4327 if (funct
["(global)"] && predefined
[t
.id
] === false) {
4328 warning("W079", t
.token
, t
.id
);
4330 if (t
.id
&& !funct
["(nolet)"]) {
4331 addlabel(t
.id
, "unused", t
.token
, true);
4332 names
.push(t
.token
);
4339 this.first
= this.first
.concat(names
);
4341 if (state
.tokens
.next
.id
=== "=") {
4342 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4344 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4345 if (state
.tokens
.next
.id
=== "undefined") {
4346 warning("W080", state
.tokens
.prev
, state
.tokens
.prev
.value
);
4348 if (peek(0).id
=== "=" && state
.tokens
.next
.identifier
) {
4349 warning("W120", state
.tokens
.next
, state
.tokens
.next
.value
);
4351 value
= expression(10);
4353 tokens
[0].first
= value
;
4355 destructuringExpressionMatch(names
, value
);
4359 if (state
.tokens
.next
.id
!== ",") {
4368 funct
["(blockscope)"].unstack();
4373 letstatement
.exps
= true;
4375 blockstmt("class", function () {
4376 return classdef
.call(this, true);
4379 function classdef(stmt
) {
4380 /*jshint validthis:true */
4381 if (!state
.option
.inESNext()) {
4382 warning("W104", state
.tokens
.curr
, "class");
4385 // BindingIdentifier
4386 this.name
= identifier();
4387 addlabel(this.name
, "unused", state
.tokens
.curr
);
4388 } else if (state
.tokens
.next
.identifier
&& state
.tokens
.next
.value
!== "extends") {
4389 // BindingIdentifier(opt)
4390 this.name
= identifier();
4396 function classtail(c
) {
4397 var strictness
= state
.directive
["use strict"];
4399 // ClassHeritage(opt)
4400 if (state
.tokens
.next
.value
=== "extends") {
4402 c
.heritage
= expression(10);
4405 // A ClassBody is always strict code.
4406 state
.directive
["use strict"] = true;
4409 c
.body
= state
.syntax
["{"].nud(true);
4410 state
.directive
["use strict"] = strictness
;
4413 blockstmt("function", function () {
4414 var generator
= false;
4415 if (state
.tokens
.next
.value
=== "*") {
4417 if (state
.option
.inESNext(true)) {
4420 warning("W119", state
.tokens
.curr
, "function*");
4424 warning("W082", state
.tokens
.curr
);
4427 var i
= identifier();
4428 if (funct
[i
] === "const") {
4429 warning("E011", null, i
);
4431 adjacent(state
.tokens
.curr
, state
.tokens
.next
);
4432 addlabel(i
, "unction", state
.tokens
.curr
);
4434 doFunction(i
, { statement
: true }, generator
);
4435 if (state
.tokens
.next
.id
=== "(" && state
.tokens
.next
.line
=== state
.tokens
.curr
.line
) {
4441 prefix("function", function () {
4442 var generator
= false;
4443 if (state
.tokens
.next
.value
=== "*") {
4444 if (!state
.option
.inESNext()) {
4445 warning("W119", state
.tokens
.curr
, "function*");
4450 var i
= optionalidentifier();
4451 if (i
|| state
.option
.gcl
) {
4452 adjacent(state
.tokens
.curr
, state
.tokens
.next
);
4454 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4456 doFunction(i
, undefined, generator
);
4457 if (!state
.option
.loopfunc
&& funct
["(loopage)"]) {
4463 blockstmt("if", function () {
4464 var t
= state
.tokens
.next
;
4465 increaseComplexityCount();
4466 state
.condition
= true;
4468 nonadjacent(this, t
);
4470 checkCondAssignment(expression(0));
4472 state
.condition
= false;
4473 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
4475 if (state
.tokens
.next
.id
=== "else") {
4476 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4478 if (state
.tokens
.next
.id
=== "if" || state
.tokens
.next
.id
=== "switch") {
4487 blockstmt("try", function () {
4490 function doCatch() {
4491 var oldScope
= scope
;
4495 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4498 scope
= Object
.create(oldScope
);
4500 e
= state
.tokens
.next
.value
;
4501 if (state
.tokens
.next
.type
!== "(identifier)") {
4503 warning("E030", state
.tokens
.next
, e
);
4509 "(name)" : "(catch)",
4510 "(line)" : state
.tokens
.next
.line
,
4511 "(character)": state
.tokens
.next
.character
,
4512 "(context)" : funct
,
4513 "(breakage)" : funct
["(breakage)"],
4514 "(loopage)" : funct
["(loopage)"],
4516 "(statement)": false,
4517 "(metrics)" : createMetrics(state
.tokens
.next
),
4520 "(blockscope)": funct
["(blockscope)"],
4521 "(comparray)": funct
["(comparray)"]
4525 addlabel(e
, "exception");
4528 if (state
.tokens
.next
.value
=== "if") {
4529 if (!state
.option
.inMoz(true)) {
4530 warning("W118", state
.tokens
.curr
, "catch filter");
4538 state
.tokens
.curr
.funct
= funct
;
4539 functions
.push(funct
);
4545 funct
["(last)"] = state
.tokens
.curr
.line
;
4546 funct
["(lastcharacter)"] = state
.tokens
.curr
.character
;
4547 funct
= funct
["(context)"];
4552 while (state
.tokens
.next
.id
=== "catch") {
4553 increaseComplexityCount();
4554 if (b
&& (!state
.option
.inMoz(true))) {
4555 warning("W118", state
.tokens
.next
, "multiple catch blocks");
4561 if (state
.tokens
.next
.id
=== "finally") {
4568 error("E021", state
.tokens
.next
, "catch", state
.tokens
.next
.value
);
4574 blockstmt("while", function () {
4575 var t
= state
.tokens
.next
;
4576 funct
["(breakage)"] += 1;
4577 funct
["(loopage)"] += 1;
4578 increaseComplexityCount();
4580 nonadjacent(this, t
);
4582 checkCondAssignment(expression(0));
4584 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
4586 funct
["(breakage)"] -= 1;
4587 funct
["(loopage)"] -= 1;
4591 blockstmt("with", function () {
4592 var t
= state
.tokens
.next
;
4593 if (state
.directive
["use strict"]) {
4594 error("E010", state
.tokens
.curr
);
4595 } else if (!state
.option
.withstmt
) {
4596 warning("W085", state
.tokens
.curr
);
4600 nonadjacent(this, t
);
4604 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
4610 blockstmt("switch", function () {
4611 var t
= state
.tokens
.next
,
4613 funct
["(breakage)"] += 1;
4615 nonadjacent(this, t
);
4617 checkCondAssignment(expression(0));
4619 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
4620 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4621 t
= state
.tokens
.next
;
4623 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4624 indent
+= state
.option
.indent
;
4628 switch (state
.tokens
.next
.id
) {
4630 switch (funct
["(verb)"]) {
4640 // You can tell JSHint that you don't use break intentionally by
4641 // adding a comment /* falls through */ on a line just before
4643 if (!reg
.fallsThrough
.test(state
.lines
[state
.tokens
.next
.line
- 2])) {
4644 warning("W086", state
.tokens
.curr
, "case");
4647 indentation(-state
.option
.indent
);
4649 this.cases
.push(expression(20));
4650 increaseComplexityCount();
4653 funct
["(verb)"] = "case";
4656 switch (funct
["(verb)"]) {
4664 // Do not display a warning if 'default' is the first statement or if
4665 // there is a special /* falls through */ comment.
4666 if (this.cases
.length
) {
4667 if (!reg
.fallsThrough
.test(state
.lines
[state
.tokens
.next
.line
- 2])) {
4668 warning("W086", state
.tokens
.curr
, "default");
4672 indentation(-state
.option
.indent
);
4678 indent
-= state
.option
.indent
;
4681 funct
["(breakage)"] -= 1;
4682 funct
["(verb)"] = undefined;
4685 error("E023", state
.tokens
.next
, "}");
4689 switch (state
.tokens
.curr
.id
) {
4698 error("E025", state
.tokens
.curr
);
4702 if (state
.tokens
.curr
.id
=== ":") {
4704 error("E024", state
.tokens
.curr
, ":");
4707 error("E021", state
.tokens
.next
, "case", state
.tokens
.next
.value
);
4715 stmt("debugger", function () {
4716 if (!state
.option
.debug
) {
4723 var x
= stmt("do", function () {
4724 funct
["(breakage)"] += 1;
4725 funct
["(loopage)"] += 1;
4726 increaseComplexityCount();
4728 this.first
= block(true, true);
4730 var t
= state
.tokens
.next
;
4731 nonadjacent(state
.tokens
.curr
, t
);
4734 checkCondAssignment(expression(0));
4736 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
4737 funct
["(breakage)"] -= 1;
4738 funct
["(loopage)"] -= 1;
4745 blockstmt("for", function () {
4746 var s
, t
= state
.tokens
.next
;
4747 var letscope
= false;
4748 var foreachtok
= null;
4750 if (t
.value
=== "each") {
4753 if (!state
.option
.inMoz(true)) {
4754 warning("W118", state
.tokens
.curr
, "for each");
4758 funct
["(breakage)"] += 1;
4759 funct
["(loopage)"] += 1;
4760 increaseComplexityCount();
4762 nonadjacent(this, t
);
4765 // what kind of for(…) statement it is? for(…of…)? for(…in…)? for(…;…;…)?
4766 var nextop
; // contains the token of the "in" or "of" operator
4768 var inof
= ["in", "of"];
4772 } while (!_
.contains(inof
, nextop
.value
) && nextop
.value
!== ";" &&
4773 nextop
.type
!== "(end)");
4775 // if we're in a for (… in|of …) statement
4776 if (_
.contains(inof
, nextop
.value
)) {
4777 if (!state
.option
.inESNext() && nextop
.value
=== "of") {
4778 error("W104", nextop
, "for of");
4780 if (state
.tokens
.next
.id
=== "var") {
4782 state
.syntax
["var"].fud
.call(state
.syntax
["var"].fud
, true);
4783 } else if (state
.tokens
.next
.id
=== "let") {
4785 // create a new block scope
4787 funct
["(blockscope)"].stack();
4788 state
.syntax
["let"].fud
.call(state
.syntax
["let"].fud
, true);
4790 switch (funct
[state
.tokens
.next
.value
]) {
4792 funct
[state
.tokens
.next
.value
] = "var";
4797 if (!funct
["(blockscope)"].getlabel(state
.tokens
.next
.value
))
4798 warning("W088", state
.tokens
.next
, state
.tokens
.next
.value
);
4802 advance(nextop
.value
);
4805 s
= block(true, true);
4806 if (state
.option
.forin
&& s
&& (s
.length
> 1 || typeof s
[0] !== "object" ||
4807 s
[0].value
!== "if")) {
4808 warning("W089", this);
4810 funct
["(breakage)"] -= 1;
4811 funct
["(loopage)"] -= 1;
4814 error("E045", foreachtok
);
4816 if (state
.tokens
.next
.id
!== ";") {
4817 if (state
.tokens
.next
.id
=== "var") {
4819 state
.syntax
["var"].fud
.call(state
.syntax
["var"].fud
);
4820 } else if (state
.tokens
.next
.id
=== "let") {
4822 // create a new block scope
4824 funct
["(blockscope)"].stack();
4825 state
.syntax
["let"].fud
.call(state
.syntax
["let"].fud
);
4828 expression(0, "for");
4829 if (state
.tokens
.next
.id
!== ",") {
4836 nolinebreak(state
.tokens
.curr
);
4838 if (state
.tokens
.next
.id
!== ";") {
4839 checkCondAssignment(expression(0));
4841 nolinebreak(state
.tokens
.curr
);
4843 if (state
.tokens
.next
.id
=== ";") {
4844 error("E021", state
.tokens
.next
, ")", ";");
4846 if (state
.tokens
.next
.id
!== ")") {
4848 expression(0, "for");
4849 if (state
.tokens
.next
.id
!== ",") {
4856 nospace(state
.tokens
.prev
, state
.tokens
.curr
);
4858 funct
["(breakage)"] -= 1;
4859 funct
["(loopage)"] -= 1;
4862 // unstack loop blockscope
4864 funct
["(blockscope)"].unstack();
4870 stmt("break", function () {
4871 var v
= state
.tokens
.next
.value
;
4873 if (funct
["(breakage)"] === 0)
4874 warning("W052", state
.tokens
.next
, this.value
);
4876 if (!state
.option
.asi
)
4879 if (state
.tokens
.next
.id
!== ";" && !state
.tokens
.next
.reach
) {
4880 if (state
.tokens
.curr
.line
=== state
.tokens
.next
.line
) {
4881 if (funct
[v
] !== "label") {
4882 warning("W090", state
.tokens
.next
, v
);
4883 } else if (scope
[v
] !== funct
) {
4884 warning("W091", state
.tokens
.next
, v
);
4886 this.first
= state
.tokens
.next
;
4895 stmt("continue", function () {
4896 var v
= state
.tokens
.next
.value
;
4898 if (funct
["(breakage)"] === 0)
4899 warning("W052", state
.tokens
.next
, this.value
);
4901 if (!state
.option
.asi
)
4904 if (state
.tokens
.next
.id
!== ";" && !state
.tokens
.next
.reach
) {
4905 if (state
.tokens
.curr
.line
=== state
.tokens
.next
.line
) {
4906 if (funct
[v
] !== "label") {
4907 warning("W090", state
.tokens
.next
, v
);
4908 } else if (scope
[v
] !== funct
) {
4909 warning("W091", state
.tokens
.next
, v
);
4911 this.first
= state
.tokens
.next
;
4914 } else if (!funct
["(loopage)"]) {
4915 warning("W052", state
.tokens
.next
, this.value
);
4917 reachable("continue");
4922 stmt("return", function () {
4923 if (this.line
=== state
.tokens
.next
.line
) {
4924 if (state
.tokens
.next
.id
=== "(regexp)")
4927 if (state
.tokens
.next
.id
!== ";" && !state
.tokens
.next
.reach
) {
4928 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4929 this.first
= expression(0);
4932 this.first
.type
=== "(punctuator)" && this.first
.value
=== "=" && !state
.option
.boss
) {
4933 warningAt("W093", this.first
.line
, this.first
.character
);
4937 if (state
.tokens
.next
.type
=== "(punctuator)" &&
4938 ["[", "{", "+", "-"].indexOf(state
.tokens
.next
.value
) > -1) {
4939 nolinebreak(this); // always warn (Line breaking error)
4942 reachable("return");
4949 }(prefix("yield", function () {
4950 var prev
= state
.tokens
.prev
;
4951 if (state
.option
.inESNext(true) && !funct
["(generator)"]) {
4952 error("E046", state
.tokens
.curr
, "yield");
4953 } else if (!state
.option
.inESNext()) {
4954 warning("W104", state
.tokens
.curr
, "yield");
4956 funct
["(generator)"] = "yielded";
4957 if (this.line
=== state
.tokens
.next
.line
|| !state
.option
.inMoz(true)) {
4958 if (state
.tokens
.next
.id
=== "(regexp)")
4961 if (state
.tokens
.next
.id
!== ";" && !state
.tokens
.next
.reach
&& state
.tokens
.next
.nud
) {
4962 nobreaknonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4963 this.first
= expression(10);
4965 if (this.first
.type
=== "(punctuator)" && this.first
.value
=== "=" && !state
.option
.boss
) {
4966 warningAt("W093", this.first
.line
, this.first
.character
);
4970 if (state
.option
.inMoz(true) && state
.tokens
.next
.id
!== ")" &&
4971 (prev
.lbp
> 30 || (!prev
.assign
&& !isEndOfExpr()) || prev
.id
=== "yield")) {
4972 error("E050", this);
4974 } else if (!state
.option
.asi
) {
4975 nolinebreak(this); // always warn (Line breaking error)
4981 stmt("throw", function () {
4983 nonadjacent(state
.tokens
.curr
, state
.tokens
.next
);
4984 this.first
= expression(20);
4989 stmt("import", function () {
4990 if (!state
.option
.inESNext()) {
4991 warning("W119", state
.tokens
.curr
, "import");
4994 if (state
.tokens
.next
.identifier
) {
4995 this.name
= identifier();
4996 addlabel(this.name
, "unused", state
.tokens
.curr
);
5001 if (state
.tokens
.next
.type
=== "default") {
5002 importName
= "default";
5005 importName
= identifier();
5007 if (state
.tokens
.next
.value
=== "as") {
5009 importName
= identifier();
5011 addlabel(importName
, "unused", state
.tokens
.curr
);
5013 if (state
.tokens
.next
.value
=== ",") {
5015 } else if (state
.tokens
.next
.value
=== "}") {
5019 error("E024", state
.tokens
.next
, state
.tokens
.next
.value
);
5026 advance("(string)");
5030 stmt("export", function () {
5031 if (!state
.option
.inESNext()) {
5032 warning("W119", state
.tokens
.curr
, "export");
5035 if (state
.tokens
.next
.type
=== "default") {
5037 if (state
.tokens
.next
.id
=== "function" || state
.tokens
.next
.id
=== "class") {
5040 this.exportee
= expression(10);
5045 if (state
.tokens
.next
.value
=== "{") {
5050 if (state
.tokens
.next
.value
=== ",") {
5052 } else if (state
.tokens
.next
.value
=== "}") {
5056 error("E024", state
.tokens
.next
, state
.tokens
.next
.value
);
5063 if (state
.tokens
.next
.id
=== "var") {
5065 state
.syntax
["var"].fud
.call(state
.syntax
["var"].fud
);
5066 } else if (state
.tokens
.next
.id
=== "let") {
5068 state
.syntax
["let"].fud
.call(state
.syntax
["let"].fud
);
5069 } else if (state
.tokens
.next
.id
=== "const") {
5071 state
.syntax
["const"].fud
.call(state
.syntax
["const"].fud
);
5072 } else if (state
.tokens
.next
.id
=== "function") {
5074 advance("function");
5075 state
.syntax
["function"].fud();
5076 } else if (state
.tokens
.next
.id
=== "class") {
5079 state
.syntax
["class"].fud();
5081 error("E024", state
.tokens
.next
, state
.tokens
.next
.value
);
5087 // Future Reserved Words
5089 FutureReservedWord("abstract");
5090 FutureReservedWord("boolean");
5091 FutureReservedWord("byte");
5092 FutureReservedWord("char");
5093 FutureReservedWord("class", { es5
: true, nud
: classdef
});
5094 FutureReservedWord("double");
5095 FutureReservedWord("enum", { es5
: true });
5096 FutureReservedWord("export", { es5
: true });
5097 FutureReservedWord("extends", { es5
: true });
5098 FutureReservedWord("final");
5099 FutureReservedWord("float");
5100 FutureReservedWord("goto");
5101 FutureReservedWord("implements", { es5
: true, strictOnly
: true });
5102 FutureReservedWord("import", { es5
: true });
5103 FutureReservedWord("int");
5104 FutureReservedWord("interface", { es5
: true, strictOnly
: true });
5105 FutureReservedWord("long");
5106 FutureReservedWord("native");
5107 FutureReservedWord("package", { es5
: true, strictOnly
: true });
5108 FutureReservedWord("private", { es5
: true, strictOnly
: true });
5109 FutureReservedWord("protected", { es5
: true, strictOnly
: true });
5110 FutureReservedWord("public", { es5
: true, strictOnly
: true });
5111 FutureReservedWord("short");
5112 FutureReservedWord("static", { es5
: true, strictOnly
: true });
5113 FutureReservedWord("super", { es5
: true });
5114 FutureReservedWord("synchronized");
5115 FutureReservedWord("throws");
5116 FutureReservedWord("transient");
5117 FutureReservedWord("volatile");
5119 // this function is used to determine wether a squarebracket or a curlybracket
5120 // expression is a comprehension array, destructuring assignment or a json value.
5122 var lookupBlockType = function () {
5125 var bracketStack
= 0;
5127 if (_
.contains(["[", "{"], state
.tokens
.curr
.value
))
5129 if (_
.contains(["[", "{"], state
.tokens
.next
.value
))
5131 if (_
.contains(["]", "}"], state
.tokens
.next
.value
))
5137 if (_
.contains(["[", "{"], pn
.value
)) {
5139 } else if (_
.contains(["]", "}"], pn
.value
)) {
5142 if (pn
.identifier
&& pn
.value
=== "for" && bracketStack
=== 1) {
5143 ret
.isCompArray
= true;
5147 if (_
.contains(["}", "]"], pn
.value
) && pn1
.value
=== "=") {
5148 ret
.isDestAssign
= true;
5152 if (pn
.value
=== ";") {
5156 } while (bracketStack
> 0 && pn
.id
!== "(end)" && i
< 15);
5160 // Check whether this function has been reached for a destructuring assign with undeclared values
5161 function destructuringAssignOrJsonValue() {
5162 // lookup for the assignment (esnext only)
5163 // if it has semicolons, it is a block, so go parse it as a block
5164 // or it's not a block, but there are assignments, check for undeclared variables
5166 var block
= lookupBlockType();
5167 if (block
.notJson
) {
5168 if (!state
.option
.inESNext() && block
.isDestAssign
) {
5169 warning("W104", state
.tokens
.curr
, "destructuring assignment");
5172 // otherwise parse json value
5174 state
.option
.laxbreak
= true;
5175 state
.jsonMode
= true;
5180 // array comprehension parsing function
5181 // parses and defines the three states of the list comprehension in order
5182 // to avoid defining global variables, but keeping them to the list comprehension scope
5183 // only. The order of the states are as follows:
5184 // * "use" which will be the returned iterative part of the list comprehension
5185 // * "define" which will define the variables local to the list comprehension
5186 // * "filter" which will help filter out values
5188 var arrayComprehension = function () {
5189 var CompArray = function () {
5191 this.variables
= [];
5195 function declare(v
) {
5196 var l
= _current
.variables
.filter(function (elt
) {
5197 // if it has, change its undef state
5198 if (elt
.value
=== v
) {
5206 var l
= _current
.variables
.filter(function (elt
) {
5207 // and if it has been defined
5208 if (elt
.value
=== v
&& !elt
.undef
) {
5209 if (elt
.unused
=== true) {
5215 // otherwise we warn about it
5218 return {stack: function () {
5219 _current
= new CompArray();
5220 _carrays
.push(_current
);
5222 unstack: function () {
5223 _current
.variables
.filter(function (v
) {
5225 warning("W098", v
.token
, v
.value
);
5227 isundef(v
.funct
, "W117", v
.token
, v
.value
);
5229 _carrays
.splice(_carrays
[_carrays
.length
- 1], 1);
5230 _current
= _carrays
[_carrays
.length
- 1];
5232 setState: function (s
) {
5233 if (_
.contains(["use", "define", "filter"], s
))
5236 check: function (v
) {
5237 // When we are in "use" state of the list comp, we enqueue that var
5238 if (_current
&& _current
.mode
=== "use") {
5239 _current
.variables
.push({funct
: funct
,
5240 token
: state
.tokens
.curr
,
5245 // When we are in "define" state of the list comp,
5246 } else if (_current
&& _current
.mode
=== "define") {
5247 // check if the variable has been used previously
5249 _current
.variables
.push({funct
: funct
,
5250 token
: state
.tokens
.curr
,
5256 // When we are in "filter" state,
5257 } else if (_current
&& _current
.mode
=== "filter") {
5258 // we check whether current variable has been declared
5260 // if not we warn about it
5261 isundef(funct
, "W117", state
.tokens
.curr
, v
);
5273 function jsonValue() {
5275 function jsonObject() {
5276 var o
= {}, t
= state
.tokens
.next
;
5278 if (state
.tokens
.next
.id
!== "}") {
5280 if (state
.tokens
.next
.id
=== "(end)") {
5281 error("E026", state
.tokens
.next
, t
.line
);
5282 } else if (state
.tokens
.next
.id
=== "}") {
5283 warning("W094", state
.tokens
.curr
);
5285 } else if (state
.tokens
.next
.id
=== ",") {
5286 error("E028", state
.tokens
.next
);
5287 } else if (state
.tokens
.next
.id
!== "(string)") {
5288 warning("W095", state
.tokens
.next
, state
.tokens
.next
.value
);
5290 if (o
[state
.tokens
.next
.value
] === true) {
5291 warning("W075", state
.tokens
.next
, state
.tokens
.next
.value
);
5292 } else if ((state
.tokens
.next
.value
=== "__proto__" &&
5293 !state
.option
.proto
) || (state
.tokens
.next
.value
=== "__iterator__" &&
5294 !state
.option
.iterator
)) {
5295 warning("W096", state
.tokens
.next
, state
.tokens
.next
.value
);
5297 o
[state
.tokens
.next
.value
] = true;
5302 if (state
.tokens
.next
.id
!== ",") {
5311 function jsonArray() {
5312 var t
= state
.tokens
.next
;
5314 if (state
.tokens
.next
.id
!== "]") {
5316 if (state
.tokens
.next
.id
=== "(end)") {
5317 error("E027", state
.tokens
.next
, t
.line
);
5318 } else if (state
.tokens
.next
.id
=== "]") {
5319 warning("W094", state
.tokens
.curr
);
5321 } else if (state
.tokens
.next
.id
=== ",") {
5322 error("E028", state
.tokens
.next
);
5325 if (state
.tokens
.next
.id
!== ",") {
5334 switch (state
.tokens
.next
.id
) {
5350 if (state
.tokens
.curr
.character
!== state
.tokens
.next
.from) {
5351 warning("W011", state
.tokens
.curr
);
5353 adjacent(state
.tokens
.curr
, state
.tokens
.next
);
5354 advance("(number)");
5357 error("E003", state
.tokens
.next
);
5361 var blockScope = function () {
5363 var _variables
= [_current
];
5365 function _checkBlockLabels() {
5366 for (var t
in _current
) {
5367 if (_current
[t
]["(type)"] === "unused") {
5368 if (state
.option
.unused
) {
5369 var tkn
= _current
[t
]["(token)"];
5370 var line
= tkn
.line
;
5371 var chr
= tkn
.character
;
5372 warningAt("W098", line
, chr
, t
);
5379 stack: function () {
5381 _variables
.push(_current
);
5384 unstack: function () {
5385 _checkBlockLabels();
5386 _variables
.splice(_variables
.length
- 1, 1);
5387 _current
= _
.last(_variables
);
5390 getlabel: function (l
) {
5391 for (var i
= _variables
.length
- 1 ; i
>= 0; --i
) {
5392 if (_
.has(_variables
[i
], l
)) {
5393 return _variables
[i
];
5400 return _
.has(_current
, t
);
5402 add: function (t
, type
, tok
) {
5403 _current
[t
] = { "(type)" : type
,
5410 // The actual JSHINT function itself.
5411 var itself = function (s
, o
, g
) {
5414 var newOptionObj
= {};
5415 var newIgnoredObj
= {};
5420 JSHINT
.scope
= o
.scope
;
5424 JSHINT
.internals
= [];
5425 JSHINT
.blacklist
= {};
5426 JSHINT
.scope
= "(main)";
5429 predefined
= Object
.create(null);
5430 combine(predefined
, vars
.ecmaIdentifiers
);
5431 combine(predefined
, vars
.reservedVars
);
5433 combine(predefined
, g
|| {});
5435 declared
= Object
.create(null);
5436 exported
= Object
.create(null);
5438 function each(obj
, cb
) {
5442 if (!Array
.isArray(obj
) && typeof obj
=== "object")
5443 obj
= Object
.keys(obj
);
5449 each(o
.predef
|| null, function (item
) {
5452 if (item
[0] === "-") {
5453 slice
= item
.slice(1);
5454 JSHINT
.blacklist
[slice
] = slice
;
5456 prop
= Object
.getOwnPropertyDescriptor(o
.predef
, item
);
5457 predefined
[item
] = prop
? prop
.value
: false;
5461 each(o
.exported
|| null, function (item
) {
5462 exported
[item
] = true;
5468 optionKeys
= Object
.keys(o
);
5469 for (x
= 0; x
< optionKeys
.length
; x
++) {
5470 if (/^-W\d{3}$/g.test(optionKeys
[x
])) {
5471 newIgnoredObj
[optionKeys
[x
].slice(1)] = true;
5473 newOptionObj
[optionKeys
[x
]] = o
[optionKeys
[x
]];
5475 if (optionKeys
[x
] === "newcap" && o
[optionKeys
[x
]] === false)
5476 newOptionObj
["(explicitNewcap)"] = true;
5478 if (optionKeys
[x
] === "indent")
5479 newOptionObj
["(explicitIndent)"] = o
[optionKeys
[x
]] === false ? false : true;
5484 state
.option
= newOptionObj
;
5485 state
.ignored
= newIgnoredObj
;
5487 state
.option
.indent
= state
.option
.indent
|| 4;
5488 state
.option
.maxerr
= state
.option
.maxerr
|| 50;
5491 global
= Object
.create(predefined
);
5495 "(name)": "(global)",
5500 "(metrics)": createMetrics(state
.tokens
.next
),
5501 "(blockscope)": blockScope(),
5502 "(comparray)": arrayComprehension()
5504 functions
= [funct
];
5515 if (!isString(s
) && !Array
.isArray(s
)) {
5522 return state
.jsonMode
;
5525 getOption: function (name
) {
5526 return state
.option
[name
] || null;
5529 getCache: function (name
) {
5530 return state
.cache
[name
];
5533 setCache: function (name
, value
) {
5534 state
.cache
[name
] = value
;
5537 warn: function (code
, data
) {
5538 warningAt
.apply(null, [ code
, data
.line
, data
.char ].concat(data
.data
));
5541 on: function (names
, listener
) {
5542 names
.split(" ").forEach(function (name
) {
5543 emitter
.on(name
, listener
);
5548 emitter
.removeAllListeners();
5549 (extraModules
|| []).forEach(function (func
) {
5553 state
.tokens
.prev
= state
.tokens
.curr
= state
.tokens
.next
= state
.syntax
["(begin)"];
5557 lex
.on("warning", function (ev
) {
5558 warningAt
.apply(null, [ ev
.code
, ev
.line
, ev
.character
].concat(ev
.data
));
5561 lex
.on("error", function (ev
) {
5562 errorAt
.apply(null, [ ev
.code
, ev
.line
, ev
.character
].concat(ev
.data
));
5565 lex
.on("fatal", function (ev
) {
5566 quit("E041", ev
.line
, ev
.from);
5569 lex
.on("Identifier", function (ev
) {
5570 emitter
.emit("Identifier", ev
);
5573 lex
.on("String", function (ev
) {
5574 emitter
.emit("String", ev
);
5577 lex
.on("Number", function (ev
) {
5578 emitter
.emit("Number", ev
);
5584 for (var name
in o
) {
5585 if (_
.has(o
, name
)) {
5586 checkOption(name
, state
.tokens
.curr
);
5592 // combine the passed globals after we've assumed all our options
5593 combine(predefined
, g
|| {});
5600 switch (state
.tokens
.next
.id
) {
5603 destructuringAssignOrJsonValue();
5608 if (state
.directive
["use strict"]) {
5609 if (!state
.option
.globalstrict
&& !state
.option
.node
) {
5610 warning("W097", state
.tokens
.prev
);
5616 advance((state
.tokens
.next
&& state
.tokens
.next
.value
!== ".") ? "(end)" : undefined);
5617 funct
["(blockscope)"].unstack();
5619 var markDefined = function (name
, context
) {
5621 if (typeof context
[name
] === "string") {
5622 // JSHINT marks unused variables as 'unused' and
5623 // unused function declaration as 'unction'. This
5624 // code changes such instances back 'var' and
5625 // 'closure' so that the code in JSHINT.data()
5626 // doesn't think they're unused.
5628 if (context
[name
] === "unused")
5629 context
[name
] = "var";
5630 else if (context
[name
] === "unction")
5631 context
[name
] = "closure";
5636 context
= context
["(context)"];
5642 var clearImplied = function (name
, line
) {
5646 var newImplied
= [];
5647 for (var i
= 0; i
< implied
[name
].length
; i
+= 1) {
5648 if (implied
[name
][i
] !== line
)
5649 newImplied
.push(implied
[name
][i
]);
5652 if (newImplied
.length
=== 0)
5653 delete implied
[name
];
5655 implied
[name
] = newImplied
;
5658 var warnUnused = function (name
, tkn
, type
, unused_opt
) {
5659 var line
= tkn
.line
;
5660 var chr
= tkn
.character
;
5662 if (unused_opt
=== undefined) {
5663 unused_opt
= state
.option
.unused
;
5666 if (unused_opt
=== true) {
5667 unused_opt
= "last-param";
5670 var warnable_types
= {
5672 "last-param": ["var", "param"],
5673 "strict": ["var", "param", "last-param"]
5677 if (warnable_types
[unused_opt
] && warnable_types
[unused_opt
].indexOf(type
) !== -1) {
5678 warningAt("W098", line
, chr
, name
);
5689 var checkUnused = function (func
, key
) {
5690 var type
= func
[key
];
5691 var tkn
= func
["(tokens)"][key
];
5693 if (key
.charAt(0) === "(")
5696 if (type
!== "unused" && type
!== "unction")
5699 // Params are checked separately from other variables.
5700 if (func
["(params)"] && func
["(params)"].indexOf(key
) !== -1)
5703 // Variable is in global scope and defined as exported.
5704 if (func
["(global)"] && _
.has(exported
, key
)) {
5708 warnUnused(key
, tkn
, "var");
5711 // Check queued 'x is not defined' instances to see if they're still undefined.
5712 for (i
= 0; i
< JSHINT
.undefs
.length
; i
+= 1) {
5713 k
= JSHINT
.undefs
[i
].slice(0);
5715 if (markDefined(k
[2].value
, k
[0])) {
5716 clearImplied(k
[2].value
, k
[2].line
);
5717 } else if (state
.option
.undef
) {
5718 warning
.apply(warning
, k
.slice(1));
5722 functions
.forEach(function (func
) {
5723 if (func
["(unusedOption)"] === false) {
5727 for (var key
in func
) {
5728 if (_
.has(func
, key
)) {
5729 checkUnused(func
, key
);
5733 if (!func
["(params)"])
5736 var params
= func
["(params)"].slice();
5737 var param
= params
.pop();
5738 var type
, unused_opt
;
5742 unused_opt
= func
["(unusedOption)"] || state
.option
.unused
;
5743 unused_opt
= unused_opt
=== true ? "last-param" : unused_opt
;
5745 // 'undefined' is a special case for (function (window, undefined) { ... })();
5748 if (param
=== "undefined")
5751 if (type
=== "unused" || type
=== "unction") {
5752 warnUnused(param
, func
["(tokens)"][param
], "param", func
["(unusedOption)"]);
5753 } else if (unused_opt
=== "last-param") {
5757 param
= params
.pop();
5761 for (var key
in declared
) {
5762 if (_
.has(declared
, key
) && !_
.has(global
, key
)) {
5763 warnUnused(key
, declared
[key
], "var");
5768 if (err
&& err
.name
=== "JSHintError") {
5769 var nt
= state
.tokens
.next
|| {};
5770 JSHINT
.errors
.push({
5774 reason
: err
.message
,
5775 line
: err
.line
|| nt
.line
,
5776 character
: err
.character
|| nt
.from
5783 // Loop over the listed "internals", and check them as well.
5785 if (JSHINT
.scope
=== "(main)") {
5788 for (i
= 0; i
< JSHINT
.internals
.length
; i
+= 1) {
5789 k
= JSHINT
.internals
[i
];
5791 itself(k
.value
, o
, g
);
5795 return JSHINT
.errors
.length
=== 0;
5799 itself
.addModule = function (func
) {
5800 extraModules
.push(func
);
5803 itself
.addModule(style
.register
);
5806 itself
.data = function () {
5809 options
: state
.option
5813 var fu
, f
, i
, j
, n
, globals
;
5815 if (itself
.errors
.length
) {
5816 data
.errors
= itself
.errors
;
5819 if (state
.jsonMode
) {
5823 for (n
in implied
) {
5824 if (_
.has(implied
, n
)) {
5832 if (implieds
.length
> 0) {
5833 data
.implieds
= implieds
;
5836 if (urls
.length
> 0) {
5840 globals
= Object
.keys(scope
);
5841 if (globals
.length
> 0) {
5842 data
.globals
= globals
;
5845 for (i
= 1; i
< functions
.length
; i
+= 1) {
5849 for (j
= 0; j
< functionicity
.length
; j
+= 1) {
5850 fu
[functionicity
[j
]] = [];
5853 for (j
= 0; j
< functionicity
.length
; j
+= 1) {
5854 if (fu
[functionicity
[j
]].length
=== 0) {
5855 delete fu
[functionicity
[j
]];
5859 fu
.name
= f
["(name)"];
5860 fu
.param
= f
["(params)"];
5861 fu
.line
= f
["(line)"];
5862 fu
.character
= f
["(character)"];
5863 fu
.last
= f
["(last)"];
5864 fu
.lastcharacter
= f
["(lastcharacter)"];
5865 data
.functions
.push(fu
);
5868 if (unuseds
.length
> 0) {
5869 data
.unused
= unuseds
;
5874 if (typeof member
[n
] === "number") {
5875 data
.member
= member
;
5883 itself
.jshint
= itself
;
5888 // Make JSHINT a Node module, if possible.
5889 if (typeof exports
=== "object" && exports
) {
5890 exports
.JSHINT
= JSHINT
;
5894 },{"events":2,"../shared/vars.js":3,"../shared/messages.js":7,"./reg.js":4,"./state.js":6,"./style.js":5,"./lex.js":8,"console-browserify":9,"underscore":10}],7:[function(require
,module
,exports
){
5895 (function(){"use strict";
5897 var _
= require("underscore");
5901 E001
: "Bad option: '{a}'.",
5902 E002
: "Bad option value.",
5905 E003
: "Expected a JSON value.",
5906 E004
: "Input is neither a string nor an array of strings.",
5907 E005
: "Input is empty.",
5908 E006
: "Unexpected early end of program.",
5911 E007
: "Missing \"use strict\" statement.",
5912 E008
: "Strict violation.",
5913 E009
: "Option 'validthis' can't be used in a global scope.",
5914 E010
: "'with' is not allowed in strict mode.",
5917 E011
: "const '{a}' has already been declared.",
5918 E012
: "const '{a}' is initialized to 'undefined'.",
5919 E013
: "Attempting to override '{a}' which is a constant.",
5921 // Regular expressions
5922 E014
: "A regular expression literal can be confused with '/='.",
5923 E015
: "Unclosed regular expression.",
5924 E016
: "Invalid regular expression.",
5927 E017
: "Unclosed comment.",
5928 E018
: "Unbegun comment.",
5929 E019
: "Unmatched '{a}'.",
5930 E020
: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
5931 E021
: "Expected '{a}' and instead saw '{b}'.",
5932 E022
: "Line breaking error '{a}'.",
5933 E023
: "Missing '{a}'.",
5934 E024
: "Unexpected '{a}'.",
5935 E025
: "Missing ':' on a case clause.",
5936 E026
: "Missing '}' to match '{' from line {a}.",
5937 E027
: "Missing ']' to match '[' form line {a}.",
5938 E028
: "Illegal comma.",
5939 E029
: "Unclosed string.",
5942 E030
: "Expected an identifier and instead saw '{a}'.",
5943 E031
: "Bad assignment.", // FIXME: Rephrase
5944 E032
: "Expected a small integer or 'false' and instead saw '{a}'.",
5945 E033
: "Expected an operator and instead saw '{a}'.",
5946 E034
: "get/set are ES5 features.",
5947 E035
: "Missing property name.",
5948 E036
: "Expected to see a statement and instead saw a block.",
5949 E037
: null, // Vacant
5950 E038
: null, // Vacant
5951 E039
: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
5952 E040
: "Each value should have its own case label.",
5953 E041
: "Unrecoverable syntax error.",
5955 E043
: "Too many errors.",
5956 E044
: "'{a}' is already defined and can't be redefined.",
5957 E045
: "Invalid for each loop.",
5958 E046
: "A yield statement shall be within a generator function (with syntax: `function*`)",
5959 E047
: "A generator function shall contain a yield statement.",
5960 E048
: "Let declaration not directly within block.",
5961 E049
: "A {a} cannot be named '{b}'.",
5962 E050
: "Mozilla requires the yield expression to be parenthesized here.",
5963 E051
: "Regular parameters cannot come after default parameters."
5967 W001
: "'hasOwnProperty' is a really bad name.",
5968 W002
: "Value of '{a}' may be overwritten in IE 8 and earlier.",
5969 W003
: "'{a}' was used before it was defined.",
5970 W004
: "'{a}' is already defined.",
5971 W005
: "A dot following a number can be confused with a decimal point.",
5972 W006
: "Confusing minuses.",
5973 W007
: "Confusing pluses.",
5974 W008
: "A leading decimal point can be confused with a dot: '{a}'.",
5975 W009
: "The array literal notation [] is preferrable.",
5976 W010
: "The object literal notation {} is preferrable.",
5977 W011
: "Unexpected space after '{a}'.",
5978 W012
: "Unexpected space before '{a}'.",
5979 W013
: "Missing space after '{a}'.",
5980 W014
: "Bad line breaking before '{a}'.",
5981 W015
: "Expected '{a}' to have an indentation at {b} instead at {c}.",
5982 W016
: "Unexpected use of '{a}'.",
5983 W017
: "Bad operand.",
5984 W018
: "Confusing use of '{a}'.",
5985 W019
: "Use the isNaN function to compare with NaN.",
5987 W021
: "'{a}' is a function.",
5988 W022
: "Do not assign to the exception parameter.",
5989 W023
: "Expected an identifier in an assignment and instead saw a function invocation.",
5990 W024
: "Expected an identifier and instead saw '{a}' (a reserved word).",
5991 W025
: "Missing name in function declaration.",
5992 W026
: "Inner functions should be listed at the top of the outer function.",
5993 W027
: "Unreachable '{a}' after '{b}'.",
5994 W028
: "Label '{a}' on {b} statement.",
5995 W030
: "Expected an assignment or function call and instead saw an expression.",
5996 W031
: "Do not use 'new' for side effects.",
5997 W032
: "Unnecessary semicolon.",
5998 W033
: "Missing semicolon.",
5999 W034
: "Unnecessary directive \"{a}\".",
6000 W035
: "Empty block.",
6001 W036
: "Unexpected /*member '{a}'.",
6002 W037
: "'{a}' is a statement label.",
6003 W038
: "'{a}' used out of scope.",
6004 W039
: "'{a}' is not allowed.",
6005 W040
: "Possible strict violation.",
6006 W041
: "Use '{a}' to compare with '{b}'.",
6007 W042
: "Avoid EOL escaping.",
6008 W043
: "Bad escaping of EOL. Use option multistr if needed.",
6009 W044
: "Bad or unnecessary escaping.",
6010 W045
: "Bad number '{a}'.",
6011 W046
: "Don't use extra leading zeros '{a}'.",
6012 W047
: "A trailing decimal point can be confused with a dot: '{a}'.",
6013 W048
: "Unexpected control character in regular expression.",
6014 W049
: "Unexpected escaped character '{a}' in regular expression.",
6015 W050
: "JavaScript URL.",
6016 W051
: "Variables should not be deleted.",
6017 W052
: "Unexpected '{a}'.",
6018 W053
: "Do not use {a} as a constructor.",
6019 W054
: "The Function constructor is a form of eval.",
6020 W055
: "A constructor name should start with an uppercase letter.",
6021 W056
: "Bad constructor.",
6022 W057
: "Weird construction. Is 'new' unnecessary?",
6023 W058
: "Missing '()' invoking a constructor.",
6024 W059
: "Avoid arguments.{a}.",
6025 W060
: "document.write can be a form of eval.",
6026 W061
: "eval can be harmful.",
6027 W062
: "Wrap an immediate function invocation in parens " +
6028 "to assist the reader in understanding that the expression " +
6029 "is the result of a function, and not the function itself.",
6030 W063
: "Math is not a function.",
6031 W064
: "Missing 'new' prefix when invoking a constructor.",
6032 W065
: "Missing radix parameter.",
6033 W066
: "Implied eval. Consider passing a function instead of a string.",
6034 W067
: "Bad invocation.",
6035 W068
: "Wrapping non-IIFE function literals in parens is unnecessary.",
6036 W069
: "['{a}'] is better written in dot notation.",
6037 W070
: "Extra comma. (it breaks older versions of IE)",
6038 W071
: "This function has too many statements. ({a})",
6039 W072
: "This function has too many parameters. ({a})",
6040 W073
: "Blocks are nested too deeply. ({a})",
6041 W074
: "This function's cyclomatic complexity is too high. ({a})",
6042 W075
: "Duplicate key '{a}'.",
6043 W076
: "Unexpected parameter '{a}' in get {b} function.",
6044 W077
: "Expected a single parameter in set {a} function.",
6045 W078
: "Setter is defined without getter.",
6046 W079
: "Redefinition of '{a}'.",
6047 W080
: "It's not necessary to initialize '{a}' to 'undefined'.",
6048 W081
: "Too many var statements.",
6049 W082
: "Function declarations should not be placed in blocks. " +
6050 "Use a function expression or move the statement to the top of " +
6051 "the outer function.",
6052 W083
: "Don't make functions within a loop.",
6053 W084
: "Expected a conditional expression and instead saw an assignment.",
6054 W085
: "Don't use 'with'.",
6055 W086
: "Expected a 'break' statement before '{a}'.",
6056 W087
: "Forgotten 'debugger' statement?",
6057 W088
: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
6058 W089
: "The body of a for in should be wrapped in an if statement to filter " +
6059 "unwanted properties from the prototype.",
6060 W090
: "'{a}' is not a statement label.",
6061 W091
: "'{a}' is out of scope.",
6062 W092
: "Wrap the /regexp/ literal in parens to disambiguate the slash operator.",
6063 W093
: "Did you mean to return a conditional instead of an assignment?",
6064 W094
: "Unexpected comma.",
6065 W095
: "Expected a string and instead saw {a}.",
6066 W096
: "The '{a}' key may produce unexpected results.",
6067 W097
: "Use the function form of \"use strict\".",
6068 W098
: "'{a}' is defined but never used.",
6069 W099
: "Mixed spaces and tabs.",
6070 W100
: "This character may get silently deleted by one or more browsers.",
6071 W101
: "Line is too long.",
6072 W102
: "Trailing whitespace.",
6073 W103
: "The '{a}' property is deprecated.",
6074 W104
: "'{a}' is only available in JavaScript 1.7.",
6075 W105
: "Unexpected {a} in '{b}'.",
6076 W106
: "Identifier '{a}' is not in camel case.",
6077 W107
: "Script URL.",
6078 W108
: "Strings must use doublequote.",
6079 W109
: "Strings must use singlequote.",
6080 W110
: "Mixed double and single quotes.",
6081 W112
: "Unclosed string.",
6082 W113
: "Control character in string: {a}.",
6084 W115
: "Octal literals are not allowed in strict mode.",
6085 W116
: "Expected '{a}' and instead saw '{b}'.",
6086 W117
: "'{a}' is not defined.",
6087 W118
: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
6088 W119
: "'{a}' is only available in ES6 (use esnext option).",
6089 W120
: "You might be leaking a variable ({a}) here."
6093 I001
: "Comma warnings can be turned off with 'laxcomma'.",
6094 I002
: "Reserved words as properties can be used under the 'es5' option.",
6095 I003
: "ES5 option is now set per default"
6098 exports
.errors
= {};
6099 exports
.warnings
= {};
6102 _
.each(errors
, function (desc
, code
) {
6103 exports
.errors
[code
] = { code
: code
, desc
: desc
};
6106 _
.each(warnings
, function (desc
, code
) {
6107 exports
.warnings
[code
] = { code
: code
, desc
: desc
};
6110 _
.each(info
, function (desc
, code
) {
6111 exports
.info
[code
] = { code
: code
, desc
: desc
};
6115 },{"underscore":10}],8:[function(require
,module
,exports
){
6117 * Lexical analysis and token construction.
6122 var _
= require("underscore");
6123 var events
= require("events");
6124 var reg
= require("./reg.js");
6125 var state
= require("./state.js").state
;
6127 // Some of these token types are from JavaScript Parser API
6128 // while others are specific to JSHint parser.
6129 // JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
6143 // This is auto generated from the unicode tables.
6144 // The tables are at:
6145 // http://www.fileformat.info/info/unicode/category/Lu/list.htm
6146 // http://www.fileformat.info/info/unicode/category/Ll/list.htm
6147 // http://www.fileformat.info/info/unicode/category/Lt/list.htm
6148 // http://www.fileformat.info/info/unicode/category/Lm/list.htm
6149 // http://www.fileformat.info/info/unicode/category/Lo/list.htm
6150 // http://www.fileformat.info/info/unicode/category/Nl/list.htm
6152 var unicodeLetterTable
= [
6153 170, 170, 181, 181, 186, 186, 192, 214,
6154 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,
6155 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,
6156 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,
6157 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,
6158 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,
6159 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,
6160 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,
6161 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,
6162 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,
6163 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,
6164 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,
6165 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,
6166 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,
6167 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,
6168 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,
6169 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,
6170 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,
6171 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,
6172 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,
6173 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,
6174 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,
6175 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,
6176 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,
6177 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,
6178 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,
6179 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,
6180 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
6181 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,
6182 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,
6183 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,
6184 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,
6185 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,
6186 4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,
6187 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,
6188 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,
6189 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,
6190 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,
6191 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,
6192 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,
6193 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,
6194 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,
6195 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,
6196 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,
6197 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,
6198 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,
6199 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,
6200 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,
6201 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,
6202 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,
6203 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
6204 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,
6205 11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,
6206 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,
6207 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,
6208 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,
6209 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,
6210 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,
6211 12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,
6212 19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,
6213 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,
6214 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,
6215 42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,
6216 43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,
6217 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,
6218 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,
6219 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,
6220 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,
6221 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,
6222 43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,
6223 43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,
6224 55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,
6225 64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,
6226 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,
6227 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,
6228 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,
6229 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,
6230 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,
6231 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,
6232 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,
6233 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,
6234 66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,
6235 66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,
6236 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,
6237 67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,
6238 68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,
6239 68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,
6240 69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,
6241 92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,
6242 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,
6243 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,
6244 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,
6245 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,
6246 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,
6247 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,
6248 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,
6249 131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,
6250 177984, 177984, 178205, 178205, 194560, 195101
6253 var identifierStartTable
= [];
6255 for (var i
= 0; i
< 128; i
++) {
6256 identifierStartTable
[i
] =
6258 i
>= 65 && i
<= 90 || // A-Z
6260 i
>= 97 && i
<= 122; // a-z
6263 var identifierPartTable
= [];
6265 for (var i
= 0; i
< 128; i
++) {
6266 identifierPartTable
[i
] =
6267 identifierStartTable
[i
] || // $, _, A-Z, a-z
6268 i
>= 48 && i
<= 57; // 0-9
6271 // Object that handles postponed lexing verifications that checks the parsed
6272 // environment state.
6274 function asyncTrigger() {
6278 push: function (fn
) {
6282 check: function () {
6283 for (var check
= 0; check
< _checks
.length
; ++check
) {
6287 _checks
.splice(0, _checks
.length
);
6295 * This object does a char-by-char scan of the provided source code
6296 * and produces a sequence of tokens.
6298 * var lex = new Lexer("var i = 0;");
6300 * lex.token(); // returns the next token
6302 * You have to use the token() method to move the lexer forward
6303 * but you don't have to use its return value to get tokens. In addition
6304 * to token() method returning the next token, the Lexer object also
6307 * lex.on("Identifier", function (data) {
6308 * if (data.name.indexOf("_") >= 0) {
6309 * // Produce a warning.
6313 * Note that the token() method returns tokens in a JSLint-compatible
6314 * format while the event emitter uses a slightly modified version of
6315 * Mozilla's JavaScript Parser API. Eventually, we will move away from
6318 function Lexer(source
) {
6321 if (typeof lines
=== "string") {
6323 .replace(/\r\n/g, "\n")
6324 .replace(/\r/g, "\n")
6328 // If the first line is a shebang (#!), make it a blank and move on.
6329 // Shebangs are used by Node scripts.
6331 if (lines
[0] && lines
[0].substr(0, 2) === "#!") {
6335 this.emitter
= new events
.EventEmitter();
6336 this.source
= source
;
6337 this.setLines(lines
);
6345 for (var i
= 0; i
< state
.option
.indent
; i
+= 1) {
6353 getLines: function () {
6354 this._lines
= state
.lines
;
6358 setLines: function (val
) {
6360 state
.lines
= this._lines
;
6364 * Return the next i character without actually moving the
6367 peek: function (i
) {
6368 return this.input
.charAt(i
|| 0);
6372 * Move the char pointer forward i times.
6374 skip: function (i
) {
6377 this.input
= this.input
.slice(i
);
6381 * Subscribe to a token event. The API for this method is similar
6382 * Underscore.js i.e. you can subscribe to multiple events with
6385 * lex.on("Identifier Number", function (data) {
6389 on: function (names
, listener
) {
6390 names
.split(" ").forEach(function (name
) {
6391 this.emitter
.on(name
, listener
);
6396 * Trigger a token event. All arguments will be passed to each
6399 trigger: function () {
6400 this.emitter
.emit
.apply(this.emitter
, Array
.prototype.slice
.call(arguments
));
6404 * Postpone a token event. the checking condition is set as
6405 * last parameter, and the trigger function is called in a
6406 * stored callback. To be later called using the check() function
6407 * by the parser. This avoids parser's peek() to give the lexer
6410 triggerAsync: function (type
, args
, checks
, fn
) {
6411 checks
.push(function () {
6413 this.trigger(type
, args
);
6419 * Extract a punctuator out of the next sequence of characters
6420 * or return 'null' if its not possible.
6422 * This method's implementation was heavily influenced by the
6423 * scanPunctuator function in the Esprima parser's source code.
6425 scanPunctuator: function () {
6426 var ch1
= this.peek();
6430 // Most common single-character punctuators
6432 if ((/^[0-9]$/).test(this.peek(1))) {
6435 if (this.peek(1) === "." && this.peek(2) === ".") {
6437 type
: Token
.Punctuator
,
6454 type
: Token
.Punctuator
,
6458 // A pound sign (for Node shebangs)
6461 type
: Token
.Punctuator
,
6465 // We're at the end of input
6470 // Peek more characters
6476 // 4-character punctuator: >>>=
6478 if (ch1
=== ">" && ch2
=== ">" && ch3
=== ">" && ch4
=== "=") {
6480 type
: Token
.Punctuator
,
6485 // 3-character punctuators: === !== >>> <<= >>=
6487 if (ch1
=== "=" && ch2
=== "=" && ch3
=== "=") {
6489 type
: Token
.Punctuator
,
6494 if (ch1
=== "!" && ch2
=== "=" && ch3
=== "=") {
6496 type
: Token
.Punctuator
,
6501 if (ch1
=== ">" && ch2
=== ">" && ch3
=== ">") {
6503 type
: Token
.Punctuator
,
6508 if (ch1
=== "<" && ch2
=== "<" && ch3
=== "=") {
6510 type
: Token
.Punctuator
,
6515 if (ch1
=== ">" && ch2
=== ">" && ch3
=== "=") {
6517 type
: Token
.Punctuator
,
6522 // Fat arrow punctuator
6523 if (ch1
=== "=" && ch2
=== ">") {
6525 type
: Token
.Punctuator
,
6530 // 2-character punctuators: <= >= == != ++ -- << >> && ||
6531 // += -= *= %= &= |= ^= (but not /=, see below)
6532 if (ch1
=== ch2
&& ("+-<>&|".indexOf(ch1
) >= 0)) {
6534 type
: Token
.Punctuator
,
6539 if ("<>=!+-*%&|^".indexOf(ch1
) >= 0) {
6542 type
: Token
.Punctuator
,
6548 type
: Token
.Punctuator
,
6553 // Special case: /=. We need to make sure that this is an
6554 // operator and not a regular expression.
6557 if (ch2
=== "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input
)) {
6558 // /= is not a part of a regular expression, return it as a
6561 type
: Token
.Punctuator
,
6567 type
: Token
.Punctuator
,
6576 * Extract a comment out of the next sequence of characters and/or
6577 * lines or return 'null' if its not possible. Since comments can
6578 * span across multiple lines this method has to move the char
6581 * In addition to normal JavaScript comments (// and /*) this method
6582 * also recognizes JSHint- and JSLint-specific comments such as
6583 * /*jshint, /*jslint, /*globals and so on.
6585 scanComments: function () {
6586 var ch1
= this.peek();
6587 var ch2
= this.peek(1);
6588 var rest
= this.input
.substr(2);
6589 var startLine
= this.line
;
6590 var startChar
= this.char;
6592 // Create a comment token object and make sure it
6593 // has all the data JSHint needs to work with special
6596 function commentToken(label
, body
, opt
) {
6597 var special
= ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
6598 var isSpecial
= false;
6599 var value
= label
+ body
;
6600 var commentType
= "plain";
6603 if (opt
.isMultiline
) {
6607 special
.forEach(function (str
) {
6612 // Don't recognize any special comments other than jshint for single-line
6613 // comments. This introduced many problems with legit comments.
6614 if (label
=== "//" && str
!== "jshint") {
6618 if (body
.substr(0, str
.length
) === str
) {
6620 label
= label
+ str
;
6621 body
= body
.substr(str
.length
);
6624 if (!isSpecial
&& body
.charAt(0) === " " && body
.substr(1, str
.length
) === str
) {
6626 label
= label
+ " " + str
;
6627 body
= body
.substr(str
.length
+ 1);
6636 commentType
= "members";
6639 commentType
= "globals";
6647 type
: Token
.Comment
,
6648 commentType
: commentType
,
6651 isSpecial
: isSpecial
,
6652 isMultiline
: opt
.isMultiline
|| false,
6653 isMalformed
: opt
.isMalformed
|| false
6657 // End of unbegun comment. Raise an error and skip that input.
6658 if (ch1
=== "*" && ch2
=== "/") {
6659 this.trigger("error", {
6662 character
: startChar
6669 // Comments must start either with // or /*
6670 if (ch1
!== "/" || (ch2
!== "*" && ch2
!== "/")) {
6676 this.skip(this.input
.length
); // Skip to the EOL.
6677 return commentToken("//", rest
);
6682 /* Multi-line comment */
6686 while (this.peek() !== "*" || this.peek(1) !== "/") {
6687 if (this.peek() === "") { // End of Line
6690 // If we hit EOF and our comment is still unclosed,
6691 // trigger an error and end the comment implicitly.
6692 if (!this.nextLine()) {
6693 this.trigger("error", {
6696 character
: startChar
6699 return commentToken("/*", body
, {
6705 body
+= this.peek();
6711 return commentToken("/*", body
, { isMultiline
: true });
6716 * Extract a keyword out of the next sequence of characters or
6717 * return 'null' if its not possible.
6719 scanKeyword: function () {
6720 var result
= /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input
);
6722 "if", "in", "do", "var", "for", "new",
6723 "try", "let", "this", "else", "case",
6724 "void", "with", "enum", "while", "break",
6725 "catch", "throw", "const", "yield", "class",
6726 "super", "return", "typeof", "delete",
6727 "switch", "export", "import", "default",
6728 "finally", "extends", "function", "continue",
6729 "debugger", "instanceof"
6732 if (result
&& keywords
.indexOf(result
[0]) >= 0) {
6734 type
: Token
.Keyword
,
6743 * Extract a JavaScript identifier out of the next sequence of
6744 * characters or return 'null' if its not possible. In addition,
6745 * to Identifier this method can also produce BooleanLiteral
6746 * (true/false) and NullLiteral (null).
6748 scanIdentifier: function () {
6753 // Detects any character in the Unicode categories "Uppercase
6754 // letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter
6755 // (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or
6756 // "Letter number (Nl)".
6758 // Both approach and unicodeLetterTable were borrowed from
6759 // Google's Traceur.
6761 function isUnicodeLetter(code
) {
6762 for (var i
= 0; i
< unicodeLetterTable
.length
;) {
6763 if (code
< unicodeLetterTable
[i
++]) {
6767 if (code
<= unicodeLetterTable
[i
++]) {
6775 function isHexDigit(str
) {
6776 return (/^[0-9a-fA-F]$/).test(str
);
6779 var readUnicodeEscapeSequence = function () {
6780 /*jshint validthis:true */
6783 if (this.peek(index
) !== "u") {
6787 var ch1
= this.peek(index
+ 1);
6788 var ch2
= this.peek(index
+ 2);
6789 var ch3
= this.peek(index
+ 3);
6790 var ch4
= this.peek(index
+ 4);
6793 if (isHexDigit(ch1
) && isHexDigit(ch2
) && isHexDigit(ch3
) && isHexDigit(ch4
)) {
6794 code
= parseInt(ch1
+ ch2
+ ch3
+ ch4
, 16);
6796 if (isUnicodeLetter(code
)) {
6798 return "\\u" + ch1
+ ch2
+ ch3
+ ch4
;
6807 var getIdentifierStart = function () {
6808 /*jshint validthis:true */
6809 var chr
= this.peek(index
);
6810 var code
= chr
.charCodeAt(0);
6813 return readUnicodeEscapeSequence();
6817 if (identifierStartTable
[code
]) {
6825 if (isUnicodeLetter(code
)) {
6833 var getIdentifierPart = function () {
6834 /*jshint validthis:true */
6835 var chr
= this.peek(index
);
6836 var code
= chr
.charCodeAt(0);
6839 return readUnicodeEscapeSequence();
6843 if (identifierPartTable
[code
]) {
6851 if (isUnicodeLetter(code
)) {
6859 char = getIdentifierStart();
6860 if (char === null) {
6866 char = getIdentifierPart();
6868 if (char === null) {
6878 type
= Token
.BooleanLiteral
;
6881 type
= Token
.NullLiteral
;
6884 type
= Token
.Identifier
;
6894 * Extract a numeric literal out of the next sequence of
6895 * characters or return 'null' if its not possible. This method
6896 * supports all numeric literals described in section 7.8.3
6897 * of the EcmaScript 5 specification.
6899 * This method's implementation was heavily influenced by the
6900 * scanNumericLiteral function in the Esprima parser's source code.
6902 scanNumericLiteral: function () {
6905 var length
= this.input
.length
;
6906 var char = this.peek(index
);
6909 function isDecimalDigit(str
) {
6910 return (/^[0-9]$/).test(str
);
6913 function isOctalDigit(str
) {
6914 return (/^[0-7]$/).test(str
);
6917 function isHexDigit(str
) {
6918 return (/^[0-9a-fA-F]$/).test(str
);
6921 function isIdentifierStart(ch
) {
6922 return (ch
=== "$") || (ch
=== "_") || (ch
=== "\\") ||
6923 (ch
>= "a" && ch
<= "z") || (ch
>= "A" && ch
<= "Z");
6926 // Numbers must start either with a decimal digit or a point.
6928 if (char !== "." && !isDecimalDigit(char)) {
6933 value
= this.peek(index
);
6935 char = this.peek(index
);
6937 if (value
=== "0") {
6939 if (char === "x" || char === "X") {
6943 while (index
< length
) {
6944 char = this.peek(index
);
6945 if (!isHexDigit(char)) {
6952 if (value
.length
<= 2) { // 0x
6954 type
: Token
.NumericLiteral
,
6960 if (index
< length
) {
6961 char = this.peek(index
);
6962 if (isIdentifierStart(char)) {
6968 type
: Token
.NumericLiteral
,
6976 if (isOctalDigit(char)) {
6981 while (index
< length
) {
6982 char = this.peek(index
);
6984 // Numbers like '019' (note the 9) are not valid octals
6985 // but we still parse them and mark as malformed.
6987 if (isDecimalDigit(char)) {
6989 } else if (!isOctalDigit(char)) {
6996 if (index
< length
) {
6997 char = this.peek(index
);
6998 if (isIdentifierStart(char)) {
7004 type
: Token
.NumericLiteral
,
7011 // Decimal numbers that start with '0' such as '09' are illegal
7012 // but we still parse them and return as malformed.
7014 if (isDecimalDigit(char)) {
7020 while (index
< length
) {
7021 char = this.peek(index
);
7022 if (!isDecimalDigit(char)) {
7036 while (index
< length
) {
7037 char = this.peek(index
);
7038 if (!isDecimalDigit(char)) {
7048 if (char === "e" || char === "E") {
7051 char = this.peek(index
);
7053 if (char === "+" || char === "-") {
7054 value
+= this.peek(index
);
7058 char = this.peek(index
);
7059 if (isDecimalDigit(char)) {
7063 while (index
< length
) {
7064 char = this.peek(index
);
7065 if (!isDecimalDigit(char)) {
7076 if (index
< length
) {
7077 char = this.peek(index
);
7078 if (isIdentifierStart(char)) {
7084 type
: Token
.NumericLiteral
,
7087 isMalformed
: !isFinite(value
)
7092 * Extract a string out of the next sequence of characters and/or
7093 * lines or return 'null' if its not possible. Since strings can
7094 * span across multiple lines this method has to move the char
7097 * This method recognizes pseudo-multiline JavaScript strings:
7102 scanStringLiteral: function (checks
) {
7103 /*jshint loopfunc:true */
7104 var quote
= this.peek();
7106 // String must start with a quote.
7107 if (quote
!== "\"" && quote
!== "'") {
7111 // In JSON strings must always use double quotes.
7112 this.triggerAsync("warning", {
7115 character
: this.char // +1?
7116 }, checks
, function () { return state
.jsonMode
&& quote
!== "\""; });
7119 var startLine
= this.line
;
7120 var startChar
= this.char;
7121 var allowNewLine
= false;
7125 while (this.peek() !== quote
) {
7126 while (this.peek() === "") { // End Of Line
7128 // If an EOL is not preceded by a backslash, show a warning
7129 // and proceed like it was a legit multi-line string where
7130 // author simply forgot to escape the newline symbol.
7132 // Another approach is to implicitly close a string on EOL
7133 // but it generates too many false positives.
7135 if (!allowNewLine
) {
7136 this.trigger("warning", {
7139 character
: this.char
7142 allowNewLine
= false;
7144 // Otherwise show a warning if multistr option was not set.
7145 // For JSON, show warning no matter what.
7147 this.triggerAsync("warning", {
7150 character
: this.char
7151 }, checks
, function () { return !state
.option
.multistr
; });
7153 this.triggerAsync("warning", {
7156 character
: this.char
7157 }, checks
, function () { return state
.jsonMode
&& state
.option
.multistr
; });
7160 // If we get an EOF inside of an unclosed string, show an
7161 // error and implicitly close it at the EOF point.
7163 if (!this.nextLine()) {
7164 this.trigger("error", {
7167 character
: startChar
7171 type
: Token
.StringLiteral
,
7179 allowNewLine
= false;
7180 var char = this.peek();
7181 var jump
= 1; // A length of a jump, after we're done
7182 // parsing this character.
7185 // Warn about a control character in a string.
7186 this.trigger("warning", {
7189 character
: this.char,
7190 data
: [ "<non-printable>" ]
7194 // Special treatment for some escaped characters.
7196 if (char === "\\") {
7202 this.triggerAsync("warning", {
7205 character
: this.char,
7207 }, checks
, function () {return state
.jsonMode
; });
7227 // Octal literals fail in strict mode.
7228 // Check if the number is between 00 and 07.
7229 var n
= parseInt(this.peek(1), 10);
7230 this.triggerAsync("warning", {
7233 character
: this.char
7235 function () { return n
>= 0 && n
<= 7 && state
.directive
["use strict"]; });
7238 char = String
.fromCharCode(parseInt(this.input
.substr(1, 4), 16));
7242 this.triggerAsync("warning", {
7245 character
: this.char,
7247 }, checks
, function () { return state
.jsonMode
; });
7252 var x
= parseInt(this.input
.substr(1, 2), 16);
7254 this.triggerAsync("warning", {
7257 character
: this.char,
7259 }, checks
, function () { return state
.jsonMode
; });
7261 char = String
.fromCharCode(x
);
7269 allowNewLine
= true;
7273 if (value
.slice(value
.length
- 2) === "<") {
7280 this.trigger("warning", {
7283 character
: this.char
7294 type
: Token
.StringLiteral
,
7302 * Extract a regular expression out of the next sequence of
7303 * characters and/or lines or return 'null' if its not possible.
7305 * This method is platform dependent: it accepts almost any
7306 * regular expression values but then tries to compile and run
7307 * them using system's RegExp object. This means that there are
7308 * rare edge cases where one JavaScript engine complains about
7309 * your regular expression while others don't.
7311 scanRegExp: function () {
7313 var length
= this.input
.length
;
7314 var char = this.peek();
7318 var malformed
= false;
7319 var isCharSet
= false;
7322 var scanUnexpectedChars = function () {
7323 // Unexpected control character
7326 this.trigger("warning", {
7329 character
: this.char
7333 // Unexpected escaped character
7336 this.trigger("warning", {
7339 character
: this.char,
7345 // Regular expressions must start with '/'
7346 if (!this.prereg
|| char !== "/") {
7353 // Try to get everything in between slashes. A couple of
7354 // cases aside (see scanUnexpectedChars) we don't really
7355 // care whether the resulting expression is valid or not.
7356 // We will check that later using the RegExp object.
7358 while (index
< length
) {
7359 char = this.peek(index
);
7365 if (this.peek(index
- 1) !== "\\" || this.peek(index
- 2) === "\\") {
7370 if (char === "\\") {
7372 char = this.peek(index
);
7376 scanUnexpectedChars();
7383 if (char === "\\") {
7385 char = this.peek(index
);
7389 scanUnexpectedChars();
7409 body
= body
.substr(0, body
.length
- 1);
7418 // A regular expression that was never closed is an
7419 // error from which we cannot recover.
7422 this.trigger("error", {
7425 character
: this.from
7428 return void this.trigger("fatal", {
7434 // Parse flags (if any).
7436 while (index
< length
) {
7437 char = this.peek(index
);
7438 if (!/[gim]/.test(char)) {
7446 // Check regular expression for correctness.
7449 new RegExp(body
, flags
.join(""));
7452 this.trigger("error", {
7455 character
: this.char,
7456 data
: [ err
.message
] // Platform dependent!
7464 isMalformed
: malformed
7469 * Scan for any occurence of mixed tabs and spaces. If smarttabs option
7470 * is on, ignore tabs followed by spaces.
7472 * Tabs followed by one space followed by a block comment are allowed.
7474 scanMixedSpacesAndTabs: function () {
7477 if (state
.option
.smarttabs
) {
7478 // Negative look-behind for "//"
7479 match
= this.input
.match(/(\/\/|^\s?\*)? \t/);
7480 at
= match
&& !match
[1] ? 0 : -1;
7482 at
= this.input
.search(/ \t|\t [^\*]/);
7489 * Scan for characters that get silently deleted by one or more browsers.
7491 scanUnsafeChars: function () {
7492 return this.input
.search(reg
.unsafeChars
);
7496 * Produce the next raw token or return 'null' if no tokens can be matched.
7497 * This method skips over all space characters.
7499 next: function (checks
) {
7500 this.from = this.char;
7502 // Move to the next non-space character.
7504 if (/\s/.test(this.peek())) {
7507 while (/\s/.test(this.peek())) {
7512 if (this.peek() === "") { // EOL
7513 if (!/^\s*$/.test(this.getLines()[this.line
- 1]) && state
.option
.trailing
) {
7514 this.trigger("warning", { code
: "W102", line
: this.line
, character
: start
});
7519 // Methods that work with multi-line structures and move the
7520 // character pointer.
7522 var match
= this.scanComments() ||
7523 this.scanStringLiteral(checks
);
7529 // Methods that don't move the character pointer.
7532 this.scanRegExp() ||
7533 this.scanPunctuator() ||
7534 this.scanKeyword() ||
7535 this.scanIdentifier() ||
7536 this.scanNumericLiteral();
7539 this.skip(match
.value
.length
);
7543 // No token could be matched, give up.
7549 * Switch to the next line and reset all char pointers. Once
7550 * switched, this method also checks for mixed spaces and tabs
7551 * and other minor warnings.
7553 nextLine: function () {
7556 if (this.line
>= this.getLines().length
) {
7560 this.input
= this.getLines()[this.line
];
7565 char = this.scanMixedSpacesAndTabs();
7567 this.trigger("warning", { code
: "W099", line
: this.line
, character
: char + 1 });
7570 this.input
= this.input
.replace(/\t/g, state
.tab
);
7571 char = this.scanUnsafeChars();
7574 this.trigger("warning", { code
: "W100", line
: this.line
, character
: char });
7577 // If there is a limit on line length, warn when lines get too
7580 if (state
.option
.maxlen
&& state
.option
.maxlen
< this.input
.length
) {
7581 this.trigger("warning", { code
: "W101", line
: this.line
, character
: this.input
.length
});
7588 * This is simply a synonym for nextLine() method with a friendlier
7591 start: function () {
7596 * Produce the next token. This function is called by advance() to get
7597 * the next token. It retuns a token in a JSLint-compatible format.
7599 token: function () {
7600 /*jshint loopfunc:true */
7601 var checks
= asyncTrigger();
7605 function isReserved(token
, isProperty
) {
7606 if (!token
.reserved
) {
7609 var meta
= token
.meta
;
7611 if (meta
&& meta
.isFutureReservedWord
&& state
.option
.inES5()) {
7612 // ES3 FutureReservedWord in an ES5 environment.
7617 // Some ES5 FutureReservedWord identifiers are active only
7618 // within a strict mode environment.
7619 if (meta
.strictOnly
) {
7620 if (!state
.option
.strict
&& !state
.directive
["use strict"]) {
7633 // Produce a token object.
7634 var create = function (type
, value
, isProperty
) {
7635 /*jshint validthis:true */
7638 if (type
!== "(endline)" && type
!== "(end)") {
7639 this.prereg
= false;
7642 if (type
=== "(punctuator)") {
7649 this.prereg
= false;
7655 obj
= Object
.create(state
.syntax
[value
] || state
.syntax
["(error)"]);
7658 if (type
=== "(identifier)") {
7659 if (value
=== "return" || value
=== "case" || value
=== "typeof") {
7663 if (_
.has(state
.syntax
, value
)) {
7664 obj
= Object
.create(state
.syntax
[value
] || state
.syntax
["(error)"]);
7666 // If this can't be a reserved keyword, reset the object.
7667 if (!isReserved(obj
, isProperty
&& type
=== "(identifier)")) {
7674 obj
= Object
.create(state
.syntax
[type
]);
7677 obj
.identifier
= (type
=== "(identifier)");
7678 obj
.type
= obj
.type
|| type
;
7680 obj
.line
= this.line
;
7681 obj
.character
= this.char;
7682 obj
.from = this.from;
7684 if (isProperty
&& obj
.identifier
) {
7685 obj
.isProperty
= isProperty
;
7688 obj
.check
= checks
.check
;
7694 if (!this.input
.length
) {
7695 return create(this.nextLine() ? "(endline)" : "(end)", "");
7698 token
= this.next(checks
);
7701 if (this.input
.length
) {
7702 // Unexpected character.
7703 this.trigger("error", {
7706 character
: this.char,
7707 data
: [ this.peek() ]
7716 switch (token
.type
) {
7717 case Token
.StringLiteral
:
7718 this.triggerAsync("String", {
7724 }, checks
, function () { return true; });
7726 return create("(string)", token
.value
);
7727 case Token
.Identifier
:
7728 this.trigger("Identifier", {
7733 isProperty
: state
.tokens
.curr
.id
=== "."
7738 case Token
.NullLiteral
:
7739 case Token
.BooleanLiteral
:
7740 return create("(identifier)", token
.value
, state
.tokens
.curr
.id
=== ".");
7742 case Token
.NumericLiteral
:
7743 if (token
.isMalformed
) {
7744 this.trigger("warning", {
7747 character
: this.char,
7748 data
: [ token
.value
]
7752 this.triggerAsync("warning", {
7755 character
: this.char,
7757 }, checks
, function () { return token
.base
=== 16 && state
.jsonMode
; });
7759 this.triggerAsync("warning", {
7762 character
: this.char
7763 }, checks
, function () {
7764 return state
.directive
["use strict"] && token
.base
=== 8;
7767 this.trigger("Number", {
7773 isMalformed
: token
.malformed
7776 return create("(number)", token
.value
);
7779 return create("(regexp)", token
.value
);
7782 state
.tokens
.curr
.comment
= true;
7784 if (token
.isSpecial
) {
7788 type
: token
.commentType
,
7789 isSpecial
: token
.isSpecial
,
7791 character
: this.char,
7802 return create("(punctuator)", token
.value
);
7808 exports
.Lexer
= Lexer
;
7811 },{"events":2,"./state.js":6,"./reg.js":4,"underscore":10}],9:[function(require
,module
,exports
){
7812 (function(global
){/*global window, global*/
7813 var util
= require("util")
7814 var assert
= require("assert")
7816 var slice
= Array
.prototype.slice
7820 if (typeof global
!== "undefined" && global
.console
) {
7821 console
= global
.console
7822 } else if (typeof window
!== "undefined" && window
.console
) {
7823 console
= window
.console
7825 console
= window
.console
= {}
7834 , [timeEnd
, "timeEnd"]
7837 , [assert
, "assert"]
7840 for (var i
= 0; i
< functions
.length
; i
++) {
7841 var tuple
= functions
[i
]
7845 if (!console
[name
]) {
7850 module
.exports
= console
7855 console
.log
.apply(console
, arguments
)
7859 console
.log
.apply(console
, arguments
)
7863 console
.warn
.apply(console
, arguments
)
7866 function time(label
) {
7867 times
[label
] = Date
.now()
7870 function timeEnd(label
) {
7871 var time
= times
[label
]
7873 throw new Error("No such label: " + label
)
7876 var duration
= Date
.now() - time
7877 console
.log(label
+ ": " + duration
+ "ms")
7881 var err
= new Error()
7883 err
.message
= util
.format
.apply(null, arguments
)
7884 console
.error(err
.stack
)
7887 function dir(object
) {
7888 console
.log(util
.inspect(object
) + "\n")
7891 function assert(expression
) {
7893 var arr
= slice
.call(arguments
, 1)
7894 assert
.ok(false, util
.format
.apply(null, arr
))
7899 },{"util":11,"assert":12}],10:[function(require
,module
,exports
){
7900 (function(){// Underscore.js 1.4.4
7901 // http://underscorejs.org
7902 // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
7903 // Underscore may be freely distributed under the MIT license.
7910 // Establish the root object, `window` in the browser, or `global` on the server.
7913 // Save the previous value of the `_` variable.
7914 var previousUnderscore
= root
._
;
7916 // Establish the object that gets returned to break out of a loop iteration.
7919 // Save bytes in the minified (but not gzipped) version:
7920 var ArrayProto
= Array
.prototype, ObjProto
= Object
.prototype, FuncProto
= Function
.prototype;
7922 // Create quick reference variables for speed access to core prototypes.
7923 var push
= ArrayProto
.push
,
7924 slice
= ArrayProto
.slice
,
7925 concat
= ArrayProto
.concat
,
7926 toString
= ObjProto
.toString
,
7927 hasOwnProperty
= ObjProto
.hasOwnProperty
;
7929 // All **ECMAScript 5** native function implementations that we hope to use
7930 // are declared here.
7932 nativeForEach
= ArrayProto
.forEach
,
7933 nativeMap
= ArrayProto
.map
,
7934 nativeReduce
= ArrayProto
.reduce
,
7935 nativeReduceRight
= ArrayProto
.reduceRight
,
7936 nativeFilter
= ArrayProto
.filter
,
7937 nativeEvery
= ArrayProto
.every
,
7938 nativeSome
= ArrayProto
.some
,
7939 nativeIndexOf
= ArrayProto
.indexOf
,
7940 nativeLastIndexOf
= ArrayProto
.lastIndexOf
,
7941 nativeIsArray
= Array
.isArray
,
7942 nativeKeys
= Object
.keys
,
7943 nativeBind
= FuncProto
.bind
;
7945 // Create a safe reference to the Underscore object for use below.
7946 var _ = function(obj
) {
7947 if (obj
instanceof _
) return obj
;
7948 if (!(this instanceof _
)) return new _(obj
);
7949 this._wrapped
= obj
;
7952 // Export the Underscore object for **Node.js**, with
7953 // backwards-compatibility for the old `require()` API. If we're in
7954 // the browser, add `_` as a global object via a string identifier,
7955 // for Closure Compiler "advanced" mode.
7956 if (typeof exports
!== 'undefined') {
7957 if (typeof module
!== 'undefined' && module
.exports
) {
7958 exports
= module
.exports
= _
;
7966 _
.VERSION
= '1.4.4';
7968 // Collection Functions
7969 // --------------------
7971 // The cornerstone, an `each` implementation, aka `forEach`.
7972 // Handles objects with the built-in `forEach`, arrays, and raw objects.
7973 // Delegates to **ECMAScript 5**'s native `forEach` if available.
7974 var each
= _
.each
= _
.forEach = function(obj
, iterator
, context
) {
7975 if (obj
== null) return;
7976 if (nativeForEach
&& obj
.forEach
=== nativeForEach
) {
7977 obj
.forEach(iterator
, context
);
7978 } else if (obj
.length
=== +obj
.length
) {
7979 for (var i
= 0, l
= obj
.length
; i
< l
; i
++) {
7980 if (iterator
.call(context
, obj
[i
], i
, obj
) === breaker
) return;
7983 for (var key
in obj
) {
7984 if (_
.has(obj
, key
)) {
7985 if (iterator
.call(context
, obj
[key
], key
, obj
) === breaker
) return;
7991 // Return the results of applying the iterator to each element.
7992 // Delegates to **ECMAScript 5**'s native `map` if available.
7993 _
.map
= _
.collect = function(obj
, iterator
, context
) {
7995 if (obj
== null) return results
;
7996 if (nativeMap
&& obj
.map
=== nativeMap
) return obj
.map(iterator
, context
);
7997 each(obj
, function(value
, index
, list
) {
7998 results
[results
.length
] = iterator
.call(context
, value
, index
, list
);
8003 var reduceError
= 'Reduce of empty array with no initial value';
8005 // **Reduce** builds up a single result from a list of values, aka `inject`,
8006 // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
8007 _
.reduce
= _
.foldl
= _
.inject = function(obj
, iterator
, memo
, context
) {
8008 var initial
= arguments
.length
> 2;
8009 if (obj
== null) obj
= [];
8010 if (nativeReduce
&& obj
.reduce
=== nativeReduce
) {
8011 if (context
) iterator
= _
.bind(iterator
, context
);
8012 return initial
? obj
.reduce(iterator
, memo
) : obj
.reduce(iterator
);
8014 each(obj
, function(value
, index
, list
) {
8019 memo
= iterator
.call(context
, memo
, value
, index
, list
);
8022 if (!initial
) throw new TypeError(reduceError
);
8026 // The right-associative version of reduce, also known as `foldr`.
8027 // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
8028 _
.reduceRight
= _
.foldr = function(obj
, iterator
, memo
, context
) {
8029 var initial
= arguments
.length
> 2;
8030 if (obj
== null) obj
= [];
8031 if (nativeReduceRight
&& obj
.reduceRight
=== nativeReduceRight
) {
8032 if (context
) iterator
= _
.bind(iterator
, context
);
8033 return initial
? obj
.reduceRight(iterator
, memo
) : obj
.reduceRight(iterator
);
8035 var length
= obj
.length
;
8036 if (length
!== +length
) {
8037 var keys
= _
.keys(obj
);
8038 length
= keys
.length
;
8040 each(obj
, function(value
, index
, list
) {
8041 index
= keys
? keys
[--length
] : --length
;
8046 memo
= iterator
.call(context
, memo
, obj
[index
], index
, list
);
8049 if (!initial
) throw new TypeError(reduceError
);
8053 // Return the first value which passes a truth test. Aliased as `detect`.
8054 _
.find
= _
.detect = function(obj
, iterator
, context
) {
8056 any(obj
, function(value
, index
, list
) {
8057 if (iterator
.call(context
, value
, index
, list
)) {
8065 // Return all the elements that pass a truth test.
8066 // Delegates to **ECMAScript 5**'s native `filter` if available.
8067 // Aliased as `select`.
8068 _
.filter
= _
.select = function(obj
, iterator
, context
) {
8070 if (obj
== null) return results
;
8071 if (nativeFilter
&& obj
.filter
=== nativeFilter
) return obj
.filter(iterator
, context
);
8072 each(obj
, function(value
, index
, list
) {
8073 if (iterator
.call(context
, value
, index
, list
)) results
[results
.length
] = value
;
8078 // Return all the elements for which a truth test fails.
8079 _
.reject = function(obj
, iterator
, context
) {
8080 return _
.filter(obj
, function(value
, index
, list
) {
8081 return !iterator
.call(context
, value
, index
, list
);
8085 // Determine whether all of the elements match a truth test.
8086 // Delegates to **ECMAScript 5**'s native `every` if available.
8087 // Aliased as `all`.
8088 _
.every
= _
.all = function(obj
, iterator
, context
) {
8089 iterator
|| (iterator
= _
.identity
);
8091 if (obj
== null) return result
;
8092 if (nativeEvery
&& obj
.every
=== nativeEvery
) return obj
.every(iterator
, context
);
8093 each(obj
, function(value
, index
, list
) {
8094 if (!(result
= result
&& iterator
.call(context
, value
, index
, list
))) return breaker
;
8099 // Determine if at least one element in the object matches a truth test.
8100 // Delegates to **ECMAScript 5**'s native `some` if available.
8101 // Aliased as `any`.
8102 var any
= _
.some
= _
.any = function(obj
, iterator
, context
) {
8103 iterator
|| (iterator
= _
.identity
);
8105 if (obj
== null) return result
;
8106 if (nativeSome
&& obj
.some
=== nativeSome
) return obj
.some(iterator
, context
);
8107 each(obj
, function(value
, index
, list
) {
8108 if (result
|| (result
= iterator
.call(context
, value
, index
, list
))) return breaker
;
8113 // Determine if the array or object contains a given value (using `===`).
8114 // Aliased as `include`.
8115 _
.contains
= _
.include = function(obj
, target
) {
8116 if (obj
== null) return false;
8117 if (nativeIndexOf
&& obj
.indexOf
=== nativeIndexOf
) return obj
.indexOf(target
) != -1;
8118 return any(obj
, function(value
) {
8119 return value
=== target
;
8123 // Invoke a method (with arguments) on every item in a collection.
8124 _
.invoke = function(obj
, method
) {
8125 var args
= slice
.call(arguments
, 2);
8126 var isFunc
= _
.isFunction(method
);
8127 return _
.map(obj
, function(value
) {
8128 return (isFunc
? method
: value
[method
]).apply(value
, args
);
8132 // Convenience version of a common use case of `map`: fetching a property.
8133 _
.pluck = function(obj
, key
) {
8134 return _
.map(obj
, function(value
){ return value
[key
]; });
8137 // Convenience version of a common use case of `filter`: selecting only objects
8138 // containing specific `key:value` pairs.
8139 _
.where = function(obj
, attrs
, first
) {
8140 if (_
.isEmpty(attrs
)) return first
? null : [];
8141 return _
[first
? 'find' : 'filter'](obj
, function(value
) {
8142 for (var key
in attrs
) {
8143 if (attrs
[key
] !== value
[key
]) return false;
8149 // Convenience version of a common use case of `find`: getting the first object
8150 // containing specific `key:value` pairs.
8151 _
.findWhere = function(obj
, attrs
) {
8152 return _
.where(obj
, attrs
, true);
8155 // Return the maximum element or (element-based computation).
8156 // Can't optimize arrays of integers longer than 65,535 elements.
8157 // See: https://bugs.webkit.org/show_bug.cgi?id=80797
8158 _
.max = function(obj
, iterator
, context
) {
8159 if (!iterator
&& _
.isArray(obj
) && obj
[0] === +obj
[0] && obj
.length
< 65535) {
8160 return Math
.max
.apply(Math
, obj
);
8162 if (!iterator
&& _
.isEmpty(obj
)) return -Infinity
;
8163 var result
= {computed
: -Infinity
, value
: -Infinity
};
8164 each(obj
, function(value
, index
, list
) {
8165 var computed
= iterator
? iterator
.call(context
, value
, index
, list
) : value
;
8166 computed
>= result
.computed
&& (result
= {value
: value
, computed
: computed
});
8168 return result
.value
;
8171 // Return the minimum element (or element-based computation).
8172 _
.min = function(obj
, iterator
, context
) {
8173 if (!iterator
&& _
.isArray(obj
) && obj
[0] === +obj
[0] && obj
.length
< 65535) {
8174 return Math
.min
.apply(Math
, obj
);
8176 if (!iterator
&& _
.isEmpty(obj
)) return Infinity
;
8177 var result
= {computed
: Infinity
, value
: Infinity
};
8178 each(obj
, function(value
, index
, list
) {
8179 var computed
= iterator
? iterator
.call(context
, value
, index
, list
) : value
;
8180 computed
< result
.computed
&& (result
= {value
: value
, computed
: computed
});
8182 return result
.value
;
8185 // Shuffle an array.
8186 _
.shuffle = function(obj
) {
8190 each(obj
, function(value
) {
8191 rand
= _
.random(index
++);
8192 shuffled
[index
- 1] = shuffled
[rand
];
8193 shuffled
[rand
] = value
;
8198 // An internal function to generate lookup iterators.
8199 var lookupIterator = function(value
) {
8200 return _
.isFunction(value
) ? value : function(obj
){ return obj
[value
]; };
8203 // Sort the object's values by a criterion produced by an iterator.
8204 _
.sortBy = function(obj
, value
, context
) {
8205 var iterator
= lookupIterator(value
);
8206 return _
.pluck(_
.map(obj
, function(value
, index
, list
) {
8210 criteria
: iterator
.call(context
, value
, index
, list
)
8212 }).sort(function(left
, right
) {
8213 var a
= left
.criteria
;
8214 var b
= right
.criteria
;
8216 if (a
> b
|| a
=== void 0) return 1;
8217 if (a
< b
|| b
=== void 0) return -1;
8219 return left
.index
< right
.index
? -1 : 1;
8223 // An internal function used for aggregate "group by" operations.
8224 var group = function(obj
, value
, context
, behavior
) {
8226 var iterator
= lookupIterator(value
|| _
.identity
);
8227 each(obj
, function(value
, index
) {
8228 var key
= iterator
.call(context
, value
, index
, obj
);
8229 behavior(result
, key
, value
);
8234 // Groups the object's values by a criterion. Pass either a string attribute
8235 // to group by, or a function that returns the criterion.
8236 _
.groupBy = function(obj
, value
, context
) {
8237 return group(obj
, value
, context
, function(result
, key
, value
) {
8238 (_
.has(result
, key
) ? result
[key
] : (result
[key
] = [])).push(value
);
8242 // Counts instances of an object that group by a certain criterion. Pass
8243 // either a string attribute to count by, or a function that returns the
8245 _
.countBy = function(obj
, value
, context
) {
8246 return group(obj
, value
, context
, function(result
, key
) {
8247 if (!_
.has(result
, key
)) result
[key
] = 0;
8252 // Use a comparator function to figure out the smallest index at which
8253 // an object should be inserted so as to maintain order. Uses binary search.
8254 _
.sortedIndex = function(array
, obj
, iterator
, context
) {
8255 iterator
= iterator
== null ? _
.identity
: lookupIterator(iterator
);
8256 var value
= iterator
.call(context
, obj
);
8257 var low
= 0, high
= array
.length
;
8258 while (low
< high
) {
8259 var mid
= (low
+ high
) >>> 1;
8260 iterator
.call(context
, array
[mid
]) < value
? low
= mid
+ 1 : high
= mid
;
8265 // Safely convert anything iterable into a real, live array.
8266 _
.toArray = function(obj
) {
8267 if (!obj
) return [];
8268 if (_
.isArray(obj
)) return slice
.call(obj
);
8269 if (obj
.length
=== +obj
.length
) return _
.map(obj
, _
.identity
);
8270 return _
.values(obj
);
8273 // Return the number of elements in an object.
8274 _
.size = function(obj
) {
8275 if (obj
== null) return 0;
8276 return (obj
.length
=== +obj
.length
) ? obj
.length
: _
.keys(obj
).length
;
8282 // Get the first element of an array. Passing **n** will return the first N
8283 // values in the array. Aliased as `head` and `take`. The **guard** check
8284 // allows it to work with `_.map`.
8285 _
.first
= _
.head
= _
.take = function(array
, n
, guard
) {
8286 if (array
== null) return void 0;
8287 return (n
!= null) && !guard
? slice
.call(array
, 0, n
) : array
[0];
8290 // Returns everything but the last entry of the array. Especially useful on
8291 // the arguments object. Passing **n** will return all the values in
8292 // the array, excluding the last N. The **guard** check allows it to work with
8294 _
.initial = function(array
, n
, guard
) {
8295 return slice
.call(array
, 0, array
.length
- ((n
== null) || guard
? 1 : n
));
8298 // Get the last element of an array. Passing **n** will return the last N
8299 // values in the array. The **guard** check allows it to work with `_.map`.
8300 _
.last = function(array
, n
, guard
) {
8301 if (array
== null) return void 0;
8302 if ((n
!= null) && !guard
) {
8303 return slice
.call(array
, Math
.max(array
.length
- n
, 0));
8305 return array
[array
.length
- 1];
8309 // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
8310 // Especially useful on the arguments object. Passing an **n** will return
8311 // the rest N values in the array. The **guard**
8312 // check allows it to work with `_.map`.
8313 _
.rest
= _
.tail
= _
.drop = function(array
, n
, guard
) {
8314 return slice
.call(array
, (n
== null) || guard
? 1 : n
);
8317 // Trim out all falsy values from an array.
8318 _
.compact = function(array
) {
8319 return _
.filter(array
, _
.identity
);
8322 // Internal implementation of a recursive `flatten` function.
8323 var flatten = function(input
, shallow
, output
) {
8324 each(input
, function(value
) {
8325 if (_
.isArray(value
)) {
8326 shallow
? push
.apply(output
, value
) : flatten(value
, shallow
, output
);
8334 // Return a completely flattened version of an array.
8335 _
.flatten = function(array
, shallow
) {
8336 return flatten(array
, shallow
, []);
8339 // Return a version of the array that does not contain the specified value(s).
8340 _
.without = function(array
) {
8341 return _
.difference(array
, slice
.call(arguments
, 1));
8344 // Produce a duplicate-free version of the array. If the array has already
8345 // been sorted, you have the option of using a faster algorithm.
8346 // Aliased as `unique`.
8347 _
.uniq
= _
.unique = function(array
, isSorted
, iterator
, context
) {
8348 if (_
.isFunction(isSorted
)) {
8350 iterator
= isSorted
;
8353 var initial
= iterator
? _
.map(array
, iterator
, context
) : array
;
8356 each(initial
, function(value
, index
) {
8357 if (isSorted
? (!index
|| seen
[seen
.length
- 1] !== value
) : !_
.contains(seen
, value
)) {
8359 results
.push(array
[index
]);
8365 // Produce an array that contains the union: each distinct element from all of
8366 // the passed-in arrays.
8367 _
.union = function() {
8368 return _
.uniq(concat
.apply(ArrayProto
, arguments
));
8371 // Produce an array that contains every item shared between all the
8372 // passed-in arrays.
8373 _
.intersection = function(array
) {
8374 var rest
= slice
.call(arguments
, 1);
8375 return _
.filter(_
.uniq(array
), function(item
) {
8376 return _
.every(rest
, function(other
) {
8377 return _
.indexOf(other
, item
) >= 0;
8382 // Take the difference between one array and a number of other arrays.
8383 // Only the elements present in just the first array will remain.
8384 _
.difference = function(array
) {
8385 var rest
= concat
.apply(ArrayProto
, slice
.call(arguments
, 1));
8386 return _
.filter(array
, function(value
){ return !_
.contains(rest
, value
); });
8389 // Zip together multiple lists into a single array -- elements that share
8390 // an index go together.
8391 _
.zip = function() {
8392 var args
= slice
.call(arguments
);
8393 var length
= _
.max(_
.pluck(args
, 'length'));
8394 var results
= new Array(length
);
8395 for (var i
= 0; i
< length
; i
++) {
8396 results
[i
] = _
.pluck(args
, "" + i
);
8401 // Converts lists into objects. Pass either a single array of `[key, value]`
8402 // pairs, or two parallel arrays of the same length -- one of keys, and one of
8403 // the corresponding values.
8404 _
.object = function(list
, values
) {
8405 if (list
== null) return {};
8407 for (var i
= 0, l
= list
.length
; i
< l
; i
++) {
8409 result
[list
[i
]] = values
[i
];
8411 result
[list
[i
][0]] = list
[i
][1];
8417 // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
8418 // we need this function. Return the position of the first occurrence of an
8419 // item in an array, or -1 if the item is not included in the array.
8420 // Delegates to **ECMAScript 5**'s native `indexOf` if available.
8421 // If the array is large and already in sort order, pass `true`
8422 // for **isSorted** to use binary search.
8423 _
.indexOf = function(array
, item
, isSorted
) {
8424 if (array
== null) return -1;
8425 var i
= 0, l
= array
.length
;
8427 if (typeof isSorted
== 'number') {
8428 i
= (isSorted
< 0 ? Math
.max(0, l
+ isSorted
) : isSorted
);
8430 i
= _
.sortedIndex(array
, item
);
8431 return array
[i
] === item
? i
: -1;
8434 if (nativeIndexOf
&& array
.indexOf
=== nativeIndexOf
) return array
.indexOf(item
, isSorted
);
8435 for (; i
< l
; i
++) if (array
[i
] === item
) return i
;
8439 // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
8440 _
.lastIndexOf = function(array
, item
, from) {
8441 if (array
== null) return -1;
8442 var hasIndex
= from != null;
8443 if (nativeLastIndexOf
&& array
.lastIndexOf
=== nativeLastIndexOf
) {
8444 return hasIndex
? array
.lastIndexOf(item
, from) : array
.lastIndexOf(item
);
8446 var i
= (hasIndex
? from : array
.length
);
8447 while (i
--) if (array
[i
] === item
) return i
;
8451 // Generate an integer Array containing an arithmetic progression. A port of
8452 // the native Python `range()` function. See
8453 // [the Python documentation](http://docs.python.org/library/functions.html#range).
8454 _
.range = function(start
, stop
, step
) {
8455 if (arguments
.length
<= 1) {
8459 step
= arguments
[2] || 1;
8461 var len
= Math
.max(Math
.ceil((stop
- start
) / step
), 0);
8463 var range
= new Array(len
);
8466 range
[idx
++] = start
;
8473 // Function (ahem) Functions
8474 // ------------------
8476 // Create a function bound to a given object (assigning `this`, and arguments,
8477 // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
8479 _
.bind = function(func
, context
) {
8480 if (func
.bind
=== nativeBind
&& nativeBind
) return nativeBind
.apply(func
, slice
.call(arguments
, 1));
8481 var args
= slice
.call(arguments
, 2);
8483 return func
.apply(context
, args
.concat(slice
.call(arguments
)));
8487 // Partially apply a function by creating a version that has had some of its
8488 // arguments pre-filled, without changing its dynamic `this` context.
8489 _
.partial = function(func
) {
8490 var args
= slice
.call(arguments
, 1);
8492 return func
.apply(this, args
.concat(slice
.call(arguments
)));
8496 // Bind all of an object's methods to that object. Useful for ensuring that
8497 // all callbacks defined on an object belong to it.
8498 _
.bindAll = function(obj
) {
8499 var funcs
= slice
.call(arguments
, 1);
8500 if (funcs
.length
=== 0) funcs
= _
.functions(obj
);
8501 each(funcs
, function(f
) { obj
[f
] = _
.bind(obj
[f
], obj
); });
8505 // Memoize an expensive function by storing its results.
8506 _
.memoize = function(func
, hasher
) {
8508 hasher
|| (hasher
= _
.identity
);
8510 var key
= hasher
.apply(this, arguments
);
8511 return _
.has(memo
, key
) ? memo
[key
] : (memo
[key
] = func
.apply(this, arguments
));
8515 // Delays a function for the given number of milliseconds, and then calls
8516 // it with the arguments supplied.
8517 _
.delay = function(func
, wait
) {
8518 var args
= slice
.call(arguments
, 2);
8519 return setTimeout(function(){ return func
.apply(null, args
); }, wait
);
8522 // Defers a function, scheduling it to run after the current call stack has
8524 _
.defer = function(func
) {
8525 return _
.delay
.apply(_
, [func
, 1].concat(slice
.call(arguments
, 1)));
8528 // Returns a function, that, when invoked, will only be triggered at most once
8529 // during a given window of time.
8530 _
.throttle = function(func
, wait
) {
8531 var context
, args
, timeout
, result
;
8533 var later = function() {
8534 previous
= new Date
;
8536 result
= func
.apply(context
, args
);
8540 var remaining
= wait
- (now
- previous
);
8543 if (remaining
<= 0) {
8544 clearTimeout(timeout
);
8547 result
= func
.apply(context
, args
);
8548 } else if (!timeout
) {
8549 timeout
= setTimeout(later
, remaining
);
8555 // Returns a function, that, as long as it continues to be invoked, will not
8556 // be triggered. The function will be called after it stops being called for
8557 // N milliseconds. If `immediate` is passed, trigger the function on the
8558 // leading edge, instead of the trailing.
8559 _
.debounce = function(func
, wait
, immediate
) {
8560 var timeout
, result
;
8562 var context
= this, args
= arguments
;
8563 var later = function() {
8565 if (!immediate
) result
= func
.apply(context
, args
);
8567 var callNow
= immediate
&& !timeout
;
8568 clearTimeout(timeout
);
8569 timeout
= setTimeout(later
, wait
);
8570 if (callNow
) result
= func
.apply(context
, args
);
8575 // Returns a function that will be executed at most one time, no matter how
8576 // often you call it. Useful for lazy initialization.
8577 _
.once = function(func
) {
8578 var ran
= false, memo
;
8580 if (ran
) return memo
;
8582 memo
= func
.apply(this, arguments
);
8588 // Returns the first function passed as an argument to the second,
8589 // allowing you to adjust arguments, run code before and after, and
8590 // conditionally execute the original function.
8591 _
.wrap = function(func
, wrapper
) {
8594 push
.apply(args
, arguments
);
8595 return wrapper
.apply(this, args
);
8599 // Returns a function that is the composition of a list of functions, each
8600 // consuming the return value of the function that follows.
8601 _
.compose = function() {
8602 var funcs
= arguments
;
8604 var args
= arguments
;
8605 for (var i
= funcs
.length
- 1; i
>= 0; i
--) {
8606 args
= [funcs
[i
].apply(this, args
)];
8612 // Returns a function that will only be executed after being called N times.
8613 _
.after = function(times
, func
) {
8614 if (times
<= 0) return func();
8617 return func
.apply(this, arguments
);
8625 // Retrieve the names of an object's properties.
8626 // Delegates to **ECMAScript 5**'s native `Object.keys`
8627 _
.keys
= nativeKeys
|| function(obj
) {
8628 if (obj
!== Object(obj
)) throw new TypeError('Invalid object');
8630 for (var key
in obj
) if (_
.has(obj
, key
)) keys
[keys
.length
] = key
;
8634 // Retrieve the values of an object's properties.
8635 _
.values = function(obj
) {
8637 for (var key
in obj
) if (_
.has(obj
, key
)) values
.push(obj
[key
]);
8641 // Convert an object into a list of `[key, value]` pairs.
8642 _
.pairs = function(obj
) {
8644 for (var key
in obj
) if (_
.has(obj
, key
)) pairs
.push([key
, obj
[key
]]);
8648 // Invert the keys and values of an object. The values must be serializable.
8649 _
.invert = function(obj
) {
8651 for (var key
in obj
) if (_
.has(obj
, key
)) result
[obj
[key
]] = key
;
8655 // Return a sorted list of the function names available on the object.
8656 // Aliased as `methods`
8657 _
.functions
= _
.methods = function(obj
) {
8659 for (var key
in obj
) {
8660 if (_
.isFunction(obj
[key
])) names
.push(key
);
8662 return names
.sort();
8665 // Extend a given object with all the properties in passed-in object(s).
8666 _
.extend = function(obj
) {
8667 each(slice
.call(arguments
, 1), function(source
) {
8669 for (var prop
in source
) {
8670 obj
[prop
] = source
[prop
];
8677 // Return a copy of the object only containing the whitelisted properties.
8678 _
.pick = function(obj
) {
8680 var keys
= concat
.apply(ArrayProto
, slice
.call(arguments
, 1));
8681 each(keys
, function(key
) {
8682 if (key
in obj
) copy
[key
] = obj
[key
];
8687 // Return a copy of the object without the blacklisted properties.
8688 _
.omit = function(obj
) {
8690 var keys
= concat
.apply(ArrayProto
, slice
.call(arguments
, 1));
8691 for (var key
in obj
) {
8692 if (!_
.contains(keys
, key
)) copy
[key
] = obj
[key
];
8697 // Fill in a given object with default properties.
8698 _
.defaults = function(obj
) {
8699 each(slice
.call(arguments
, 1), function(source
) {
8701 for (var prop
in source
) {
8702 if (obj
[prop
] == null) obj
[prop
] = source
[prop
];
8709 // Create a (shallow-cloned) duplicate of an object.
8710 _
.clone = function(obj
) {
8711 if (!_
.isObject(obj
)) return obj
;
8712 return _
.isArray(obj
) ? obj
.slice() : _
.extend({}, obj
);
8715 // Invokes interceptor with the obj, and then returns obj.
8716 // The primary purpose of this method is to "tap into" a method chain, in
8717 // order to perform operations on intermediate results within the chain.
8718 _
.tap = function(obj
, interceptor
) {
8723 // Internal recursive comparison function for `isEqual`.
8724 var eq = function(a
, b
, aStack
, bStack
) {
8725 // Identical objects are equal. `0 === -0`, but they aren't identical.
8726 // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
8727 if (a
=== b
) return a
!== 0 || 1 / a
== 1 / b
;
8728 // A strict comparison is necessary because `null == undefined`.
8729 if (a
== null || b
== null) return a
=== b
;
8730 // Unwrap any wrapped objects.
8731 if (a
instanceof _
) a
= a
._wrapped
;
8732 if (b
instanceof _
) b
= b
._wrapped
;
8733 // Compare `[[Class]]` names.
8734 var className
= toString
.call(a
);
8735 if (className
!= toString
.call(b
)) return false;
8736 switch (className
) {
8737 // Strings, numbers, dates, and booleans are compared by value.
8738 case '[object String]':
8739 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
8740 // equivalent to `new String("5")`.
8741 return a
== String(b
);
8742 case '[object Number]':
8743 // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
8744 // other numeric values.
8745 return a
!= +a
? b
!= +b
: (a
== 0 ? 1 / a
== 1 / b
: a
== +b
);
8746 case '[object Date]':
8747 case '[object Boolean]':
8748 // Coerce dates and booleans to numeric primitive values. Dates are compared by their
8749 // millisecond representations. Note that invalid dates with millisecond representations
8750 // of `NaN` are not equivalent.
8752 // RegExps are compared by their source patterns and flags.
8753 case '[object RegExp]':
8754 return a
.source
== b
.source
&&
8755 a
.global
== b
.global
&&
8756 a
.multiline
== b
.multiline
&&
8757 a
.ignoreCase
== b
.ignoreCase
;
8759 if (typeof a
!= 'object' || typeof b
!= 'object') return false;
8760 // Assume equality for cyclic structures. The algorithm for detecting cyclic
8761 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
8762 var length
= aStack
.length
;
8764 // Linear search. Performance is inversely proportional to the number of
8765 // unique nested structures.
8766 if (aStack
[length
] == a
) return bStack
[length
] == b
;
8768 // Add the first object to the stack of traversed objects.
8771 var size
= 0, result
= true;
8772 // Recursively compare objects and arrays.
8773 if (className
== '[object Array]') {
8774 // Compare array lengths to determine if a deep comparison is necessary.
8776 result
= size
== b
.length
;
8778 // Deep compare the contents, ignoring non-numeric properties.
8780 if (!(result
= eq(a
[size
], b
[size
], aStack
, bStack
))) break;
8784 // Objects with different constructors are not equivalent, but `Object`s
8785 // from different frames are.
8786 var aCtor
= a
.constructor, bCtor
= b
.constructor;
8787 if (aCtor
!== bCtor
&& !(_
.isFunction(aCtor
) && (aCtor
instanceof aCtor
) &&
8788 _
.isFunction(bCtor
) && (bCtor
instanceof bCtor
))) {
8791 // Deep compare objects.
8792 for (var key
in a
) {
8793 if (_
.has(a
, key
)) {
8794 // Count the expected number of properties.
8796 // Deep compare each member.
8797 if (!(result
= _
.has(b
, key
) && eq(a
[key
], b
[key
], aStack
, bStack
))) break;
8800 // Ensure that both objects contain the same number of properties.
8803 if (_
.has(b
, key
) && !(size
--)) break;
8808 // Remove the first object from the stack of traversed objects.
8814 // Perform a deep comparison to check if two objects are equal.
8815 _
.isEqual = function(a
, b
) {
8816 return eq(a
, b
, [], []);
8819 // Is a given array, string, or object empty?
8820 // An "empty" object has no enumerable own-properties.
8821 _
.isEmpty = function(obj
) {
8822 if (obj
== null) return true;
8823 if (_
.isArray(obj
) || _
.isString(obj
)) return obj
.length
=== 0;
8824 for (var key
in obj
) if (_
.has(obj
, key
)) return false;
8828 // Is a given value a DOM element?
8829 _
.isElement = function(obj
) {
8830 return !!(obj
&& obj
.nodeType
=== 1);
8833 // Is a given value an array?
8834 // Delegates to ECMA5's native Array.isArray
8835 _
.isArray
= nativeIsArray
|| function(obj
) {
8836 return toString
.call(obj
) == '[object Array]';
8839 // Is a given variable an object?
8840 _
.isObject = function(obj
) {
8841 return obj
=== Object(obj
);
8844 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
8845 each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name
) {
8846 _
['is' + name
] = function(obj
) {
8847 return toString
.call(obj
) == '[object ' + name
+ ']';
8851 // Define a fallback version of the method in browsers (ahem, IE), where
8852 // there isn't any inspectable "Arguments" type.
8853 if (!_
.isArguments(arguments
)) {
8854 _
.isArguments = function(obj
) {
8855 return !!(obj
&& _
.has(obj
, 'callee'));
8859 // Optimize `isFunction` if appropriate.
8860 if (typeof (/./) !== 'function') {
8861 _
.isFunction = function(obj
) {
8862 return typeof obj
=== 'function';
8866 // Is a given object a finite number?
8867 _
.isFinite = function(obj
) {
8868 return isFinite(obj
) && !isNaN(parseFloat(obj
));
8871 // Is the given value `NaN`? (NaN is the only number which does not equal itself).
8872 _
.isNaN = function(obj
) {
8873 return _
.isNumber(obj
) && obj
!= +obj
;
8876 // Is a given value a boolean?
8877 _
.isBoolean = function(obj
) {
8878 return obj
=== true || obj
=== false || toString
.call(obj
) == '[object Boolean]';
8881 // Is a given value equal to null?
8882 _
.isNull = function(obj
) {
8883 return obj
=== null;
8886 // Is a given variable undefined?
8887 _
.isUndefined = function(obj
) {
8888 return obj
=== void 0;
8891 // Shortcut function for checking if an object has a given property directly
8892 // on itself (in other words, not on a prototype).
8893 _
.has = function(obj
, key
) {
8894 return hasOwnProperty
.call(obj
, key
);
8897 // Utility Functions
8898 // -----------------
8900 // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
8901 // previous owner. Returns a reference to the Underscore object.
8902 _
.noConflict = function() {
8903 root
._
= previousUnderscore
;
8907 // Keep the identity function around for default iterators.
8908 _
.identity = function(value
) {
8912 // Run a function **n** times.
8913 _
.times = function(n
, iterator
, context
) {
8914 var accum
= Array(n
);
8915 for (var i
= 0; i
< n
; i
++) accum
[i
] = iterator
.call(context
, i
);
8919 // Return a random integer between min and max (inclusive).
8920 _
.random = function(min
, max
) {
8925 return min
+ Math
.floor(Math
.random() * (max
- min
+ 1));
8928 // List of HTML entities for escaping.
8939 entityMap
.unescape
= _
.invert(entityMap
.escape
);
8941 // Regexes containing the keys and values listed immediately above.
8942 var entityRegexes
= {
8943 escape
: new RegExp('[' + _
.keys(entityMap
.escape
).join('') + ']', 'g'),
8944 unescape
: new RegExp('(' + _
.keys(entityMap
.unescape
).join('|') + ')', 'g')
8947 // Functions for escaping and unescaping strings to/from HTML interpolation.
8948 _
.each(['escape', 'unescape'], function(method
) {
8949 _
[method
] = function(string
) {
8950 if (string
== null) return '';
8951 return ('' + string
).replace(entityRegexes
[method
], function(match
) {
8952 return entityMap
[method
][match
];
8957 // If the value of the named property is a function then invoke it;
8958 // otherwise, return it.
8959 _
.result = function(object
, property
) {
8960 if (object
== null) return null;
8961 var value
= object
[property
];
8962 return _
.isFunction(value
) ? value
.call(object
) : value
;
8965 // Add your own custom functions to the Underscore object.
8966 _
.mixin = function(obj
) {
8967 each(_
.functions(obj
), function(name
){
8968 var func
= _
[name
] = obj
[name
];
8969 _
.prototype[name
] = function() {
8970 var args
= [this._wrapped
];
8971 push
.apply(args
, arguments
);
8972 return result
.call(this, func
.apply(_
, args
));
8977 // Generate a unique integer id (unique within the entire client session).
8978 // Useful for temporary DOM ids.
8980 _
.uniqueId = function(prefix
) {
8981 var id
= ++idCounter
+ '';
8982 return prefix
? prefix
+ id
: id
;
8985 // By default, Underscore uses ERB-style template delimiters, change the
8986 // following template settings to use alternative delimiters.
8987 _
.templateSettings
= {
8988 evaluate
: /<%([\s\S]+?)%>/g,
8989 interpolate
: /<%=([\s\S]+?)%>/g,
8990 escape
: /<%-([\s\S]+?)%>/g
8993 // When customizing `templateSettings`, if you don't want to define an
8994 // interpolation, evaluation or escaping regex, we need one that is
8995 // guaranteed not to match.
8996 var noMatch
= /(.)^/;
8998 // Certain characters need to be escaped so that they can be put into a
9010 var escaper
= /\\|'|\r|\n|\t|\u2028|\u2029/g;
9012 // JavaScript micro-templating, similar to John Resig's implementation.
9013 // Underscore templating handles arbitrary delimiters, preserves whitespace,
9014 // and correctly escapes quotes within interpolated code.
9015 _
.template = function(text
, data
, settings
) {
9017 settings
= _
.defaults({}, settings
, _
.templateSettings
);
9019 // Combine delimiters into one regular expression via alternation.
9020 var matcher
= new RegExp([
9021 (settings
.escape
|| noMatch
).source
,
9022 (settings
.interpolate
|| noMatch
).source
,
9023 (settings
.evaluate
|| noMatch
).source
9024 ].join('|') + '|$', 'g');
9026 // Compile the template source, escaping string literals appropriately.
9028 var source
= "__p+='";
9029 text
.replace(matcher
, function(match
, escape
, interpolate
, evaluate
, offset
) {
9030 source
+= text
.slice(index
, offset
)
9031 .replace(escaper
, function(match
) { return '\\' + escapes
[match
]; });
9034 source
+= "'+\n((__t=(" + escape
+ "))==null?'':_.escape(__t))+\n'";
9037 source
+= "'+\n((__t=(" + interpolate
+ "))==null?'':__t)+\n'";
9040 source
+= "';\n" + evaluate
+ "\n__p+='";
9042 index
= offset
+ match
.length
;
9047 // If a variable is not specified, place data values in local scope.
9048 if (!settings
.variable
) source
= 'with(obj||{}){\n' + source
+ '}\n';
9050 source
= "var __t,__p='',__j=Array.prototype.join," +
9051 "print=function(){__p+=__j.call(arguments,'');};\n" +
9052 source
+ "return __p;\n";
9055 render
= new Function(settings
.variable
|| 'obj', '_', source
);
9061 if (data
) return render(data
, _
);
9062 var template = function(data
) {
9063 return render
.call(this, data
, _
);
9066 // Provide the compiled function source as a convenience for precompilation.
9067 template
.source
= 'function(' + (settings
.variable
|| 'obj') + '){\n' + source
+ '}';
9072 // Add a "chain" function, which will delegate to the wrapper.
9073 _
.chain = function(obj
) {
9074 return _(obj
).chain();
9079 // If Underscore is called as a function, it returns a wrapped object that
9080 // can be used OO-style. This wrapper holds altered versions of all the
9081 // underscore functions. Wrapped objects may be chained.
9083 // Helper function to continue chaining intermediate results.
9084 var result = function(obj
) {
9085 return this._chain
? _(obj
).chain() : obj
;
9088 // Add all of the Underscore functions to the wrapper object.
9091 // Add all mutator Array functions to the wrapper.
9092 each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name
) {
9093 var method
= ArrayProto
[name
];
9094 _
.prototype[name
] = function() {
9095 var obj
= this._wrapped
;
9096 method
.apply(obj
, arguments
);
9097 if ((name
== 'shift' || name
== 'splice') && obj
.length
=== 0) delete obj
[0];
9098 return result
.call(this, obj
);
9102 // Add all accessor Array functions to the wrapper.
9103 each(['concat', 'join', 'slice'], function(name
) {
9104 var method
= ArrayProto
[name
];
9105 _
.prototype[name
] = function() {
9106 return result
.call(this, method
.apply(this._wrapped
, arguments
));
9110 _
.extend(_
.prototype, {
9112 // Start chaining a wrapped Underscore object.
9118 // Extracts the result from a wrapped and chained object.
9120 return this._wrapped
;
9128 },{}],11:[function(require
,module
,exports
){
9129 var events
= require('events');
9131 exports
.isArray
= isArray
;
9132 exports
.isDate = function(obj
){return Object
.prototype.toString
.call(obj
) === '[object Date]'};
9133 exports
.isRegExp = function(obj
){return Object
.prototype.toString
.call(obj
) === '[object RegExp]'};
9136 exports
.print = function () {};
9137 exports
.puts = function () {};
9138 exports
.debug = function() {};
9140 exports
.inspect = function(obj
, showHidden
, depth
, colors
) {
9143 var stylize = function(str
, styleType
) {
9144 // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
9148 'underline' : [4, 24],
9149 'inverse' : [7, 27],
9156 'magenta' : [35, 39],
9158 'yellow' : [33, 39] };
9161 { 'special': 'cyan',
9163 'boolean': 'yellow',
9164 'undefined': 'grey',
9168 // "name": intentionally not styling
9169 'regexp': 'red' }[styleType
];
9172 return '\033[' + styles
[style
][0] + 'm' + str
+
9173 '\033[' + styles
[style
][1] + 'm';
9179 stylize = function(str
, styleType
) { return str
; };
9182 function format(value
, recurseTimes
) {
9183 // Provide a hook for user-specified inspect functions.
9184 // Check that value is an object with an inspect function on it
9185 if (value
&& typeof value
.inspect
=== 'function' &&
9186 // Filter out the util module, it's inspect function is special
9187 value
!== exports
&&
9188 // Also filter out any prototype objects using the circular check.
9189 !(value
.constructor && value
.constructor.prototype === value
)) {
9190 return value
.inspect(recurseTimes
);
9193 // Primitive types cannot have properties
9194 switch (typeof value
) {
9196 return stylize('undefined', 'undefined');
9199 var simple
= '\'' + JSON
.stringify(value
).replace(/^"|"$/g, '')
9200 .replace(/'/g, "\\'")
9201 .replace(/\\"/g
, '"') + '\'';
9202 return stylize(simple
, 'string');
9205 return stylize('' + value
, 'number');
9208 return stylize('' + value
, 'boolean');
9210 // For some reason typeof null is "object", so special case here.
9211 if (value
=== null) {
9212 return stylize('null', 'null');
9215 // Look up the keys of the object.
9216 var visible_keys
= Object_keys(value
);
9217 var keys
= showHidden
? Object_getOwnPropertyNames(value
) : visible_keys
;
9219 // Functions without properties can be shortcutted.
9220 if (typeof value
=== 'function' && keys
.length
=== 0) {
9221 if (isRegExp(value
)) {
9222 return stylize('' + value
, 'regexp');
9224 var name
= value
.name
? ': ' + value
.name
: '';
9225 return stylize('[Function' + name
+ ']', 'special');
9229 // Dates without properties can be shortcutted
9230 if (isDate(value
) && keys
.length
=== 0) {
9231 return stylize(value
.toUTCString(), 'date');
9234 var base
, type
, braces
;
9235 // Determine the object type
9236 if (isArray(value
)) {
9238 braces
= ['[', ']'];
9241 braces
= ['{', '}'];
9244 // Make functions say that they are functions
9245 if (typeof value
=== 'function') {
9246 var n
= value
.name
? ': ' + value
.name
: '';
9247 base
= (isRegExp(value
)) ? ' ' + value
: ' [Function' + n
+ ']';
9252 // Make dates with properties first say the date
9253 if (isDate(value
)) {
9254 base
= ' ' + value
.toUTCString();
9257 if (keys
.length
=== 0) {
9258 return braces
[0] + base
+ braces
[1];
9261 if (recurseTimes
< 0) {
9262 if (isRegExp(value
)) {
9263 return stylize('' + value
, 'regexp');
9265 return stylize('[Object]', 'special');
9271 var output
= keys
.map(function(key
) {
9273 if (value
.__lookupGetter__
) {
9274 if (value
.__lookupGetter__(key
)) {
9275 if (value
.__lookupSetter__(key
)) {
9276 str
= stylize('[Getter/Setter]', 'special');
9278 str
= stylize('[Getter]', 'special');
9281 if (value
.__lookupSetter__(key
)) {
9282 str
= stylize('[Setter]', 'special');
9286 if (visible_keys
.indexOf(key
) < 0) {
9287 name
= '[' + key
+ ']';
9290 if (seen
.indexOf(value
[key
]) < 0) {
9291 if (recurseTimes
=== null) {
9292 str
= format(value
[key
]);
9294 str
= format(value
[key
], recurseTimes
- 1);
9296 if (str
.indexOf('\n') > -1) {
9297 if (isArray(value
)) {
9298 str
= str
.split('\n').map(function(line
) {
9300 }).join('\n').substr(2);
9302 str
= '\n' + str
.split('\n').map(function(line
) {
9308 str
= stylize('[Circular]', 'special');
9311 if (typeof name
=== 'undefined') {
9312 if (type
=== 'Array' && key
.match(/^\d+$/)) {
9315 name
= JSON
.stringify('' + key
);
9316 if (name
.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
9317 name
= name
.substr(1, name
.length
- 2);
9318 name
= stylize(name
, 'name');
9320 name
= name
.replace(/'/g, "\\'")
9321 .replace(/\\"/g
, '"')
9322 .replace(/(^"|"$)/g, "'");
9323 name
= stylize(name
, 'string');
9327 return name
+ ': ' + str
;
9332 var numLinesEst
= 0;
9333 var length
= output
.reduce(function(prev
, cur
) {
9335 if (cur
.indexOf('\n') >= 0) numLinesEst
++;
9336 return prev
+ cur
.length
+ 1;
9340 output
= braces
[0] +
9341 (base
=== '' ? '' : base
+ '\n ') +
9343 output
.join(',\n ') +
9348 output
= braces
[0] + base
+ ' ' + output
.join(', ') + ' ' + braces
[1];
9353 return format(obj
, (typeof depth
=== 'undefined' ? 2 : depth
));
9357 function isArray(ar
) {
9358 return ar
instanceof Array
||
9359 Array
.isArray(ar
) ||
9360 (ar
&& ar
!== Object
.prototype && isArray(ar
.__proto__
));
9364 function isRegExp(re
) {
9365 return re
instanceof RegExp
||
9366 (typeof re
=== 'object' && Object
.prototype.toString
.call(re
) === '[object RegExp]');
9370 function isDate(d
) {
9371 if (d
instanceof Date
) return true;
9372 if (typeof d
!== 'object') return false;
9373 var properties
= Date
.prototype && Object_getOwnPropertyNames(Date
.prototype);
9374 var proto
= d
.__proto__
&& Object_getOwnPropertyNames(d
.__proto__
);
9375 return JSON
.stringify(proto
) === JSON
.stringify(properties
);
9379 return n
< 10 ? '0' + n
.toString(10) : n
.toString(10);
9382 var months
= ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
9383 'Oct', 'Nov', 'Dec'];
9386 function timestamp() {
9388 var time
= [pad(d
.getHours()),
9389 pad(d
.getMinutes()),
9390 pad(d
.getSeconds())].join(':');
9391 return [d
.getDate(), months
[d
.getMonth()], time
].join(' ');
9394 exports
.log = function (msg
) {};
9396 exports
.pump
= null;
9398 var Object_keys
= Object
.keys
|| function (obj
) {
9400 for (var key
in obj
) res
.push(key
);
9404 var Object_getOwnPropertyNames
= Object
.getOwnPropertyNames
|| function (obj
) {
9406 for (var key
in obj
) {
9407 if (Object
.hasOwnProperty
.call(obj
, key
)) res
.push(key
);
9412 var Object_create
= Object
.create
|| function (prototype, properties
) {
9415 if (prototype === null) {
9416 object
= { '__proto__' : null };
9419 if (typeof prototype !== 'object') {
9420 throw new TypeError(
9421 'typeof prototype[' + (typeof prototype) + '] != \'object\''
9424 var Type = function () {};
9425 Type
.prototype = prototype;
9426 object
= new Type();
9427 object
.__proto__
= prototype;
9429 if (typeof properties
!== 'undefined' && Object
.defineProperties
) {
9430 Object
.defineProperties(object
, properties
);
9435 exports
.inherits = function(ctor
, superCtor
) {
9436 ctor
.super_
= superCtor
;
9437 ctor
.prototype = Object_create(superCtor
.prototype, {
9447 var formatRegExp
= /%[sdj%]/g;
9448 exports
.format = function(f
) {
9449 if (typeof f
!== 'string') {
9451 for (var i
= 0; i
< arguments
.length
; i
++) {
9452 objects
.push(exports
.inspect(arguments
[i
]));
9454 return objects
.join(' ');
9458 var args
= arguments
;
9459 var len
= args
.length
;
9460 var str
= String(f
).replace(formatRegExp
, function(x
) {
9461 if (x
=== '%%') return '%';
9462 if (i
>= len
) return x
;
9464 case '%s': return String(args
[i
++]);
9465 case '%d': return Number(args
[i
++]);
9466 case '%j': return JSON
.stringify(args
[i
++]);
9471 for(var x
= args
[i
]; i
< len
; x
= args
[++i
]){
9472 if (x
=== null || typeof x
!== 'object') {
9475 str
+= ' ' + exports
.inspect(x
);
9481 },{"events":2}],12:[function(require
,module
,exports
){
9482 (function(){// UTILITY
9483 var util
= require('util');
9484 var Buffer
= require("buffer").Buffer
;
9485 var pSlice
= Array
.prototype.slice
;
9487 function objectKeys(object
) {
9488 if (Object
.keys
) return Object
.keys(object
);
9490 for (var name
in object
) {
9491 if (Object
.prototype.hasOwnProperty
.call(object
, name
)) {
9498 // 1. The assert module provides functions that throw
9499 // AssertionError's when particular conditions are not met. The
9500 // assert module must conform to the following interface.
9502 var assert
= module
.exports
= ok
;
9504 // 2. The AssertionError is defined in assert.
9505 // new assert.AssertionError({ message: message,
9507 // expected: expected })
9509 assert
.AssertionError
= function AssertionError(options
) {
9510 this.name
= 'AssertionError';
9511 this.message
= options
.message
;
9512 this.actual
= options
.actual
;
9513 this.expected
= options
.expected
;
9514 this.operator
= options
.operator
;
9515 var stackStartFunction
= options
.stackStartFunction
|| fail
;
9517 if (Error
.captureStackTrace
) {
9518 Error
.captureStackTrace(this, stackStartFunction
);
9521 util
.inherits(assert
.AssertionError
, Error
);
9523 function replacer(key
, value
) {
9524 if (value
=== undefined) {
9527 if (typeof value
=== 'number' && (isNaN(value
) || !isFinite(value
))) {
9528 return value
.toString();
9530 if (typeof value
=== 'function' || value
instanceof RegExp
) {
9531 return value
.toString();
9536 function truncate(s
, n
) {
9537 if (typeof s
== 'string') {
9538 return s
.length
< n
? s
: s
.slice(0, n
);
9544 assert
.AssertionError
.prototype.toString = function() {
9546 return [this.name
+ ':', this.message
].join(' ');
9550 truncate(JSON
.stringify(this.actual
, replacer
), 128),
9552 truncate(JSON
.stringify(this.expected
, replacer
), 128)
9557 // assert.AssertionError instanceof Error
9559 assert
.AssertionError
.__proto__
= Error
.prototype;
9561 // At present only the three keys mentioned above are used and
9562 // understood by the spec. Implementations or sub modules can pass
9563 // other keys to the AssertionError's constructor - they will be
9566 // 3. All of the following functions must throw an AssertionError
9567 // when a corresponding condition is not met, with a message that
9568 // may be undefined if not provided. All assertion methods provide
9569 // both the actual and expected values to the assertion error for
9570 // display purposes.
9572 function fail(actual
, expected
, message
, operator
, stackStartFunction
) {
9573 throw new assert
.AssertionError({
9578 stackStartFunction
: stackStartFunction
9582 // EXTENSION! allows for well behaved errors defined elsewhere.
9585 // 4. Pure assertion tests whether a value is truthy, as determined
9587 // assert.ok(guard, message_opt);
9588 // This statement is equivalent to assert.equal(true, guard,
9589 // message_opt);. To test strictly for the value true, use
9590 // assert.strictEqual(true, guard, message_opt);.
9592 function ok(value
, message
) {
9593 if (!!!value
) fail(value
, true, message
, '==', assert
.ok
);
9597 // 5. The equality assertion tests shallow, coercive equality with
9599 // assert.equal(actual, expected, message_opt);
9601 assert
.equal
= function equal(actual
, expected
, message
) {
9602 if (actual
!= expected
) fail(actual
, expected
, message
, '==', assert
.equal
);
9605 // 6. The non-equality assertion tests for whether two objects are not equal
9606 // with != assert.notEqual(actual, expected, message_opt);
9608 assert
.notEqual
= function notEqual(actual
, expected
, message
) {
9609 if (actual
== expected
) {
9610 fail(actual
, expected
, message
, '!=', assert
.notEqual
);
9614 // 7. The equivalence assertion tests a deep equality relation.
9615 // assert.deepEqual(actual, expected, message_opt);
9617 assert
.deepEqual
= function deepEqual(actual
, expected
, message
) {
9618 if (!_deepEqual(actual
, expected
)) {
9619 fail(actual
, expected
, message
, 'deepEqual', assert
.deepEqual
);
9623 function _deepEqual(actual
, expected
) {
9624 // 7.1. All identical values are equivalent, as determined by ===.
9625 if (actual
=== expected
) {
9628 } else if (Buffer
.isBuffer(actual
) && Buffer
.isBuffer(expected
)) {
9629 if (actual
.length
!= expected
.length
) return false;
9631 for (var i
= 0; i
< actual
.length
; i
++) {
9632 if (actual
[i
] !== expected
[i
]) return false;
9637 // 7.2. If the expected value is a Date object, the actual value is
9638 // equivalent if it is also a Date object that refers to the same time.
9639 } else if (actual
instanceof Date
&& expected
instanceof Date
) {
9640 return actual
.getTime() === expected
.getTime();
9642 // 7.3. Other pairs that do not both pass typeof value == 'object',
9643 // equivalence is determined by ==.
9644 } else if (typeof actual
!= 'object' && typeof expected
!= 'object') {
9645 return actual
== expected
;
9647 // 7.4. For all other Object pairs, including Array objects, equivalence is
9648 // determined by having the same number of owned properties (as verified
9649 // with Object.prototype.hasOwnProperty.call), the same set of keys
9650 // (although not necessarily the same order), equivalent values for every
9651 // corresponding key, and an identical 'prototype' property. Note: this
9652 // accounts for both named and indexed properties on Arrays.
9654 return objEquiv(actual
, expected
);
9658 function isUndefinedOrNull(value
) {
9659 return value
=== null || value
=== undefined;
9662 function isArguments(object
) {
9663 return Object
.prototype.toString
.call(object
) == '[object Arguments]';
9666 function objEquiv(a
, b
) {
9667 if (isUndefinedOrNull(a
) || isUndefinedOrNull(b
))
9669 // an identical 'prototype' property.
9670 if (a
.prototype !== b
.prototype) return false;
9671 //~~~I've managed to break Object.keys through screwy arguments passing.
9672 // Converting to array solves the problem.
9673 if (isArguments(a
)) {
9674 if (!isArguments(b
)) {
9679 return _deepEqual(a
, b
);
9682 var ka
= objectKeys(a
),
9685 } catch (e
) {//happens when one is a string literal and the other isn't
9688 // having the same number of owned properties (keys incorporates
9690 if (ka
.length
!= kb
.length
)
9692 //the same set of keys (although not necessarily the same order),
9696 for (i
= ka
.length
- 1; i
>= 0; i
--) {
9700 //equivalent values for every corresponding key, and
9701 //~~~possibly expensive deep test
9702 for (i
= ka
.length
- 1; i
>= 0; i
--) {
9704 if (!_deepEqual(a
[key
], b
[key
])) return false;
9709 // 8. The non-equivalence assertion tests for any deep inequality.
9710 // assert.notDeepEqual(actual, expected, message_opt);
9712 assert
.notDeepEqual
= function notDeepEqual(actual
, expected
, message
) {
9713 if (_deepEqual(actual
, expected
)) {
9714 fail(actual
, expected
, message
, 'notDeepEqual', assert
.notDeepEqual
);
9718 // 9. The strict equality assertion tests strict equality, as determined by ===.
9719 // assert.strictEqual(actual, expected, message_opt);
9721 assert
.strictEqual
= function strictEqual(actual
, expected
, message
) {
9722 if (actual
!== expected
) {
9723 fail(actual
, expected
, message
, '===', assert
.strictEqual
);
9727 // 10. The strict non-equality assertion tests for strict inequality, as
9728 // determined by !==. assert.notStrictEqual(actual, expected, message_opt);
9730 assert
.notStrictEqual
= function notStrictEqual(actual
, expected
, message
) {
9731 if (actual
=== expected
) {
9732 fail(actual
, expected
, message
, '!==', assert
.notStrictEqual
);
9736 function expectedException(actual
, expected
) {
9737 if (!actual
|| !expected
) {
9741 if (expected
instanceof RegExp
) {
9742 return expected
.test(actual
);
9743 } else if (actual
instanceof expected
) {
9745 } else if (expected
.call({}, actual
) === true) {
9752 function _throws(shouldThrow
, block
, expected
, message
) {
9755 if (typeof expected
=== 'string') {
9766 message
= (expected
&& expected
.name
? ' (' + expected
.name
+ ').' : '.') +
9767 (message
? ' ' + message
: '.');
9769 if (shouldThrow
&& !actual
) {
9770 fail('Missing expected exception' + message
);
9773 if (!shouldThrow
&& expectedException(actual
, expected
)) {
9774 fail('Got unwanted exception' + message
);
9777 if ((shouldThrow
&& actual
&& expected
&&
9778 !expectedException(actual
, expected
)) || (!shouldThrow
&& actual
)) {
9783 // 11. Expected to throw an error:
9784 // assert.throws(block, Error_opt, message_opt);
9786 assert
.throws = function(block
, /*optional*/error
, /*optional*/message
) {
9787 _throws
.apply(this, [true].concat(pSlice
.call(arguments
)));
9790 // EXTENSION! This is annoying to write outside this module.
9791 assert
.doesNotThrow = function(block
, /*optional*/error
, /*optional*/message
) {
9792 _throws
.apply(this, [false].concat(pSlice
.call(arguments
)));
9795 assert
.ifError = function(err
) { if (err
) {throw err
;}};
9798 },{"util":11,"buffer":13}],14:[function(require
,module
,exports
){
9799 exports
.readIEEE754 = function(buffer
, offset
, isBE
, mLen
, nBytes
) {
9801 eLen
= nBytes
* 8 - mLen
- 1,
9802 eMax
= (1 << eLen
) - 1,
9805 i
= isBE
? 0 : (nBytes
- 1),
9807 s
= buffer
[offset
+ i
];
9811 e
= s
& ((1 << (-nBits
)) - 1);
9814 for (; nBits
> 0; e
= e
* 256 + buffer
[offset
+ i
], i
+= d
, nBits
-= 8);
9816 m
= e
& ((1 << (-nBits
)) - 1);
9819 for (; nBits
> 0; m
= m
* 256 + buffer
[offset
+ i
], i
+= d
, nBits
-= 8);
9823 } else if (e
=== eMax
) {
9824 return m
? NaN
: ((s
? -1 : 1) * Infinity
);
9826 m
= m
+ Math
.pow(2, mLen
);
9829 return (s
? -1 : 1) * m
* Math
.pow(2, e
- mLen
);
9832 exports
.writeIEEE754 = function(buffer
, value
, offset
, isBE
, mLen
, nBytes
) {
9834 eLen
= nBytes
* 8 - mLen
- 1,
9835 eMax
= (1 << eLen
) - 1,
9837 rt
= (mLen
=== 23 ? Math
.pow(2, -24) - Math
.pow(2, -77) : 0),
9838 i
= isBE
? (nBytes
- 1) : 0,
9840 s
= value
< 0 || (value
=== 0 && 1 / value
< 0) ? 1 : 0;
9842 value
= Math
.abs(value
);
9844 if (isNaN(value
) || value
=== Infinity
) {
9845 m
= isNaN(value
) ? 1 : 0;
9848 e
= Math
.floor(Math
.log(value
) / Math
.LN2
);
9849 if (value
* (c
= Math
.pow(2, -e
)) < 1) {
9853 if (e
+ eBias
>= 1) {
9856 value
+= rt
* Math
.pow(2, 1 - eBias
);
9858 if (value
* c
>= 2) {
9863 if (e
+ eBias
>= eMax
) {
9866 } else if (e
+ eBias
>= 1) {
9867 m
= (value
* c
- 1) * Math
.pow(2, mLen
);
9870 m
= value
* Math
.pow(2, eBias
- 1) * Math
.pow(2, mLen
);
9875 for (; mLen
>= 8; buffer
[offset
+ i
] = m
& 0xff, i
+= d
, m
/= 256, mLen
-= 8);
9877 e
= (e
<< mLen
) | m
;
9879 for (; eLen
> 0; buffer
[offset
+ i
] = e
& 0xff, i
+= d
, e
/= 256, eLen
-= 8);
9881 buffer
[offset
+ i
- d
] |= s
* 128;
9884 },{}],13:[function(require
,module
,exports
){
9885 (function(){function SlowBuffer (size
) {
9889 var assert
= require('assert');
9891 exports
.INSPECT_MAX_BYTES
= 50;
9895 if (n
< 16) return '0' + n
.toString(16);
9896 return n
.toString(16);
9899 function utf8ToBytes(str
) {
9901 for (var i
= 0; i
< str
.length
; i
++)
9902 if (str
.charCodeAt(i
) <= 0x7F)
9903 byteArray
.push(str
.charCodeAt(i
));
9905 var h
= encodeURIComponent(str
.charAt(i
)).substr(1).split('%');
9906 for (var j
= 0; j
< h
.length
; j
++)
9907 byteArray
.push(parseInt(h
[j
], 16));
9913 function asciiToBytes(str
) {
9915 for (var i
= 0; i
< str
.length
; i
++ )
9916 // Node's code seems to be doing this and not & 0x7F..
9917 byteArray
.push( str
.charCodeAt(i
) & 0xFF );
9922 function base64ToBytes(str
) {
9923 return require("base64-js").toByteArray(str
);
9926 SlowBuffer
.byteLength = function (str
, encoding
) {
9927 switch (encoding
|| "utf8") {
9929 return str
.length
/ 2;
9933 return utf8ToBytes(str
).length
;
9940 return base64ToBytes(str
).length
;
9943 throw new Error('Unknown encoding');
9947 function blitBuffer(src
, dst
, offset
, length
) {
9949 while (i
< length
) {
9950 if ((i
+offset
>= dst
.length
) || (i
>= src
.length
))
9953 dst
[i
+ offset
] = src
[i
];
9959 SlowBuffer
.prototype.utf8Write = function (string
, offset
, length
) {
9961 return SlowBuffer
._charsWritten
= blitBuffer(utf8ToBytes(string
), this, offset
, length
);
9964 SlowBuffer
.prototype.asciiWrite = function (string
, offset
, length
) {
9966 return SlowBuffer
._charsWritten
= blitBuffer(asciiToBytes(string
), this, offset
, length
);
9969 SlowBuffer
.prototype.binaryWrite
= SlowBuffer
.prototype.asciiWrite
;
9971 SlowBuffer
.prototype.base64Write = function (string
, offset
, length
) {
9973 return SlowBuffer
._charsWritten
= blitBuffer(base64ToBytes(string
), this, offset
, length
);
9976 SlowBuffer
.prototype.base64Slice = function (start
, end
) {
9977 var bytes
= Array
.prototype.slice
.apply(this, arguments
)
9978 return require("base64-js").fromByteArray(bytes
);
9981 function decodeUtf8Char(str
) {
9983 return decodeURIComponent(str
);
9985 return String
.fromCharCode(0xFFFD); // UTF 8 invalid char
9989 SlowBuffer
.prototype.utf8Slice = function () {
9990 var bytes
= Array
.prototype.slice
.apply(this, arguments
);
9994 while (i
< bytes
.length
) {
9995 if (bytes
[i
] <= 0x7F) {
9996 res
+= decodeUtf8Char(tmp
) + String
.fromCharCode(bytes
[i
]);
9999 tmp
+= "%" + bytes
[i
].toString(16);
10004 return res
+ decodeUtf8Char(tmp
);
10007 SlowBuffer
.prototype.asciiSlice = function () {
10008 var bytes
= Array
.prototype.slice
.apply(this, arguments
);
10010 for (var i
= 0; i
< bytes
.length
; i
++)
10011 ret
+= String
.fromCharCode(bytes
[i
]);
10015 SlowBuffer
.prototype.binarySlice
= SlowBuffer
.prototype.asciiSlice
;
10017 SlowBuffer
.prototype.inspect = function() {
10020 for (var i
= 0; i
< len
; i
++) {
10021 out
[i
] = toHex(this[i
]);
10022 if (i
== exports
.INSPECT_MAX_BYTES
) {
10023 out
[i
+ 1] = '...';
10027 return '<SlowBuffer ' + out
.join(' ') + '>';
10031 SlowBuffer
.prototype.hexSlice = function(start
, end
) {
10032 var len
= this.length
;
10034 if (!start
|| start
< 0) start
= 0;
10035 if (!end
|| end
< 0 || end
> len
) end
= len
;
10038 for (var i
= start
; i
< end
; i
++) {
10039 out
+= toHex(this[i
]);
10045 SlowBuffer
.prototype.toString = function(encoding
, start
, end
) {
10046 encoding
= String(encoding
|| 'utf8').toLowerCase();
10047 start
= +start
|| 0;
10048 if (typeof end
== 'undefined') end
= this.length
;
10050 // Fastpath empty strings
10051 if (+end
== start
) {
10055 switch (encoding
) {
10057 return this.hexSlice(start
, end
);
10061 return this.utf8Slice(start
, end
);
10064 return this.asciiSlice(start
, end
);
10067 return this.binarySlice(start
, end
);
10070 return this.base64Slice(start
, end
);
10074 return this.ucs2Slice(start
, end
);
10077 throw new Error('Unknown encoding');
10082 SlowBuffer
.prototype.hexWrite = function(string
, offset
, length
) {
10083 offset
= +offset
|| 0;
10084 var remaining
= this.length
- offset
;
10086 length
= remaining
;
10089 if (length
> remaining
) {
10090 length
= remaining
;
10094 // must be an even number of digits
10095 var strLen
= string
.length
;
10097 throw new Error('Invalid hex string');
10099 if (length
> strLen
/ 2) {
10100 length
= strLen
/ 2;
10102 for (var i
= 0; i
< length
; i
++) {
10103 var byte = parseInt(string
.substr(i
* 2, 2), 16);
10104 if (isNaN(byte)) throw new Error('Invalid hex string');
10105 this[offset
+ i
] = byte;
10107 SlowBuffer
._charsWritten
= i
* 2;
10112 SlowBuffer
.prototype.write = function(string
, offset
, length
, encoding
) {
10113 // Support both (string, offset, length, encoding)
10114 // and the legacy (string, encoding, offset, length)
10115 if (isFinite(offset
)) {
10116 if (!isFinite(length
)) {
10118 length
= undefined;
10121 var swap
= encoding
;
10127 offset
= +offset
|| 0;
10128 var remaining
= this.length
- offset
;
10130 length
= remaining
;
10133 if (length
> remaining
) {
10134 length
= remaining
;
10137 encoding
= String(encoding
|| 'utf8').toLowerCase();
10139 switch (encoding
) {
10141 return this.hexWrite(string
, offset
, length
);
10145 return this.utf8Write(string
, offset
, length
);
10148 return this.asciiWrite(string
, offset
, length
);
10151 return this.binaryWrite(string
, offset
, length
);
10154 return this.base64Write(string
, offset
, length
);
10158 return this.ucs2Write(string
, offset
, length
);
10161 throw new Error('Unknown encoding');
10166 // slice(start, end)
10167 SlowBuffer
.prototype.slice = function(start
, end
) {
10168 if (end
=== undefined) end
= this.length
;
10170 if (end
> this.length
) {
10171 throw new Error('oob');
10174 throw new Error('oob');
10177 return new Buffer(this, end
- start
, +start
);
10180 SlowBuffer
.prototype.copy = function(target
, targetstart
, sourcestart
, sourceend
) {
10182 for (var i
=sourcestart
; i
<sourceend
; i
++) {
10183 assert
.ok(typeof this[i
] !== 'undefined', "copying undefined buffer bytes!");
10184 temp
.push(this[i
]);
10187 for (var i
=targetstart
; i
<targetstart
+temp
.length
; i
++) {
10188 target
[i
] = temp
[i
-targetstart
];
10192 SlowBuffer
.prototype.fill = function(value
, start
, end
) {
10193 if (end
> this.length
) {
10194 throw new Error('oob');
10197 throw new Error('oob');
10200 for (var i
= start
; i
< end
; i
++) {
10205 function coerce(length
) {
10206 // Coerce length to a number (possibly NaN), round up
10207 // in case it's fractional (e.g. 123.456) then do a
10208 // double negate to coerce a NaN to 0. Easy, right?
10209 length
= ~~Math
.ceil(+length
);
10210 return length
< 0 ? 0 : length
;
10216 function Buffer(subject
, encoding
, offset
) {
10217 if (!(this instanceof Buffer
)) {
10218 return new Buffer(subject
, encoding
, offset
);
10224 if (typeof offset
=== 'number') {
10225 this.length
= coerce(encoding
);
10226 this.parent
= subject
;
10227 this.offset
= offset
;
10230 switch (type
= typeof subject
) {
10232 this.length
= coerce(subject
);
10236 this.length
= Buffer
.byteLength(subject
, encoding
);
10239 case 'object': // Assume object is an array
10240 this.length
= coerce(subject
.length
);
10244 throw new Error('First argument needs to be a number, ' +
10245 'array or string.');
10248 if (this.length
> Buffer
.poolSize
) {
10249 // Big buffer, just alloc one.
10250 this.parent
= new SlowBuffer(this.length
);
10255 if (!pool
|| pool
.length
- pool
.used
< this.length
) allocPool();
10256 this.parent
= pool
;
10257 this.offset
= pool
.used
;
10258 pool
.used
+= this.length
;
10261 // Treat array-ish objects as a byte array.
10262 if (isArrayIsh(subject
)) {
10263 for (var i
= 0; i
< this.length
; i
++) {
10264 if (subject
instanceof Buffer
) {
10265 this.parent
[i
+ this.offset
] = subject
.readUInt8(i
);
10268 this.parent
[i
+ this.offset
] = subject
[i
];
10271 } else if (type
== 'string') {
10273 this.length
= this.write(subject
, 0, encoding
);
10279 function isArrayIsh(subject
) {
10280 return Array
.isArray(subject
) || Buffer
.isBuffer(subject
) ||
10281 subject
&& typeof subject
=== 'object' &&
10282 typeof subject
.length
=== 'number';
10285 exports
.SlowBuffer
= SlowBuffer
;
10286 exports
.Buffer
= Buffer
;
10288 Buffer
.poolSize
= 8 * 1024;
10291 function allocPool() {
10292 pool
= new SlowBuffer(Buffer
.poolSize
);
10298 Buffer
.isBuffer
= function isBuffer(b
) {
10299 return b
instanceof Buffer
|| b
instanceof SlowBuffer
;
10302 Buffer
.concat = function (list
, totalLength
) {
10303 if (!Array
.isArray(list
)) {
10304 throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
10305 list should be an Array.");
10308 if (list
.length
=== 0) {
10309 return new Buffer(0);
10310 } else if (list
.length
=== 1) {
10314 if (typeof totalLength
!== 'number') {
10316 for (var i
= 0; i
< list
.length
; i
++) {
10318 totalLength
+= buf
.length
;
10322 var buffer
= new Buffer(totalLength
);
10324 for (var i
= 0; i
< list
.length
; i
++) {
10326 buf
.copy(buffer
, pos
);
10333 Buffer
.prototype.inspect
= function inspect() {
10337 for (var i
= 0; i
< len
; i
++) {
10338 out
[i
] = toHex(this.parent
[i
+ this.offset
]);
10339 if (i
== exports
.INSPECT_MAX_BYTES
) {
10340 out
[i
+ 1] = '...';
10345 return '<Buffer ' + out
.join(' ') + '>';
10349 Buffer
.prototype.get = function get(i
) {
10350 if (i
< 0 || i
>= this.length
) throw new Error('oob');
10351 return this.parent
[this.offset
+ i
];
10355 Buffer
.prototype.set = function set(i
, v
) {
10356 if (i
< 0 || i
>= this.length
) throw new Error('oob');
10357 return this.parent
[this.offset
+ i
] = v
;
10361 // write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
10362 Buffer
.prototype.write = function(string
, offset
, length
, encoding
) {
10363 // Support both (string, offset, length, encoding)
10364 // and the legacy (string, encoding, offset, length)
10365 if (isFinite(offset
)) {
10366 if (!isFinite(length
)) {
10368 length
= undefined;
10371 var swap
= encoding
;
10377 offset
= +offset
|| 0;
10378 var remaining
= this.length
- offset
;
10380 length
= remaining
;
10383 if (length
> remaining
) {
10384 length
= remaining
;
10387 encoding
= String(encoding
|| 'utf8').toLowerCase();
10390 switch (encoding
) {
10392 ret
= this.parent
.hexWrite(string
, this.offset
+ offset
, length
);
10397 ret
= this.parent
.utf8Write(string
, this.offset
+ offset
, length
);
10401 ret
= this.parent
.asciiWrite(string
, this.offset
+ offset
, length
);
10405 ret
= this.parent
.binaryWrite(string
, this.offset
+ offset
, length
);
10409 // Warning: maxLength not taken into account in base64Write
10410 ret
= this.parent
.base64Write(string
, this.offset
+ offset
, length
);
10415 ret
= this.parent
.ucs2Write(string
, this.offset
+ offset
, length
);
10419 throw new Error('Unknown encoding');
10422 Buffer
._charsWritten
= SlowBuffer
._charsWritten
;
10428 // toString(encoding, start=0, end=buffer.length)
10429 Buffer
.prototype.toString = function(encoding
, start
, end
) {
10430 encoding
= String(encoding
|| 'utf8').toLowerCase();
10432 if (typeof start
== 'undefined' || start
< 0) {
10434 } else if (start
> this.length
) {
10435 start
= this.length
;
10438 if (typeof end
== 'undefined' || end
> this.length
) {
10440 } else if (end
< 0) {
10444 start
= start
+ this.offset
;
10445 end
= end
+ this.offset
;
10447 switch (encoding
) {
10449 return this.parent
.hexSlice(start
, end
);
10453 return this.parent
.utf8Slice(start
, end
);
10456 return this.parent
.asciiSlice(start
, end
);
10459 return this.parent
.binarySlice(start
, end
);
10462 return this.parent
.base64Slice(start
, end
);
10466 return this.parent
.ucs2Slice(start
, end
);
10469 throw new Error('Unknown encoding');
10475 Buffer
.byteLength
= SlowBuffer
.byteLength
;
10478 // fill(value, start=0, end=buffer.length)
10479 Buffer
.prototype.fill
= function fill(value
, start
, end
) {
10480 value
|| (value
= 0);
10481 start
|| (start
= 0);
10482 end
|| (end
= this.length
);
10484 if (typeof value
=== 'string') {
10485 value
= value
.charCodeAt(0);
10487 if (!(typeof value
=== 'number') || isNaN(value
)) {
10488 throw new Error('value is not a number');
10491 if (end
< start
) throw new Error('end < start');
10493 // Fill 0 bytes; we're done
10494 if (end
=== start
) return 0;
10495 if (this.length
== 0) return 0;
10497 if (start
< 0 || start
>= this.length
) {
10498 throw new Error('start out of bounds');
10501 if (end
< 0 || end
> this.length
) {
10502 throw new Error('end out of bounds');
10505 return this.parent
.fill(value
,
10506 start
+ this.offset
,
10507 end
+ this.offset
);
10511 // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
10512 Buffer
.prototype.copy = function(target
, target_start
, start
, end
) {
10514 start
|| (start
= 0);
10515 end
|| (end
= this.length
);
10516 target_start
|| (target_start
= 0);
10518 if (end
< start
) throw new Error('sourceEnd < sourceStart');
10520 // Copy 0 bytes; we're done
10521 if (end
=== start
) return 0;
10522 if (target
.length
== 0 || source
.length
== 0) return 0;
10524 if (target_start
< 0 || target_start
>= target
.length
) {
10525 throw new Error('targetStart out of bounds');
10528 if (start
< 0 || start
>= source
.length
) {
10529 throw new Error('sourceStart out of bounds');
10532 if (end
< 0 || end
> source
.length
) {
10533 throw new Error('sourceEnd out of bounds');
10537 if (end
> this.length
) {
10541 if (target
.length
- target_start
< end
- start
) {
10542 end
= target
.length
- target_start
+ start
;
10545 return this.parent
.copy(target
.parent
,
10546 target_start
+ target
.offset
,
10547 start
+ this.offset
,
10548 end
+ this.offset
);
10552 // slice(start, end)
10553 Buffer
.prototype.slice = function(start
, end
) {
10554 if (end
=== undefined) end
= this.length
;
10555 if (end
> this.length
) throw new Error('oob');
10556 if (start
> end
) throw new Error('oob');
10558 return new Buffer(this.parent
, end
- start
, +start
+ this.offset
);
10562 // Legacy methods for backwards compatibility.
10564 Buffer
.prototype.utf8Slice = function(start
, end
) {
10565 return this.toString('utf8', start
, end
);
10568 Buffer
.prototype.binarySlice = function(start
, end
) {
10569 return this.toString('binary', start
, end
);
10572 Buffer
.prototype.asciiSlice = function(start
, end
) {
10573 return this.toString('ascii', start
, end
);
10576 Buffer
.prototype.utf8Write = function(string
, offset
) {
10577 return this.write(string
, offset
, 'utf8');
10580 Buffer
.prototype.binaryWrite = function(string
, offset
) {
10581 return this.write(string
, offset
, 'binary');
10584 Buffer
.prototype.asciiWrite = function(string
, offset
) {
10585 return this.write(string
, offset
, 'ascii');
10588 Buffer
.prototype.readUInt8 = function(offset
, noAssert
) {
10592 assert
.ok(offset
!== undefined && offset
!== null,
10595 assert
.ok(offset
< buffer
.length
,
10596 'Trying to read beyond buffer length');
10599 if (offset
>= buffer
.length
) return;
10601 return buffer
.parent
[buffer
.offset
+ offset
];
10604 function readUInt16(buffer
, offset
, isBigEndian
, noAssert
) {
10609 assert
.ok(typeof (isBigEndian
) === 'boolean',
10610 'missing or invalid endian');
10612 assert
.ok(offset
!== undefined && offset
!== null,
10615 assert
.ok(offset
+ 1 < buffer
.length
,
10616 'Trying to read beyond buffer length');
10619 if (offset
>= buffer
.length
) return 0;
10622 val
= buffer
.parent
[buffer
.offset
+ offset
] << 8;
10623 if (offset
+ 1 < buffer
.length
) {
10624 val
|= buffer
.parent
[buffer
.offset
+ offset
+ 1];
10627 val
= buffer
.parent
[buffer
.offset
+ offset
];
10628 if (offset
+ 1 < buffer
.length
) {
10629 val
|= buffer
.parent
[buffer
.offset
+ offset
+ 1] << 8;
10636 Buffer
.prototype.readUInt16LE = function(offset
, noAssert
) {
10637 return readUInt16(this, offset
, false, noAssert
);
10640 Buffer
.prototype.readUInt16BE = function(offset
, noAssert
) {
10641 return readUInt16(this, offset
, true, noAssert
);
10644 function readUInt32(buffer
, offset
, isBigEndian
, noAssert
) {
10648 assert
.ok(typeof (isBigEndian
) === 'boolean',
10649 'missing or invalid endian');
10651 assert
.ok(offset
!== undefined && offset
!== null,
10654 assert
.ok(offset
+ 3 < buffer
.length
,
10655 'Trying to read beyond buffer length');
10658 if (offset
>= buffer
.length
) return 0;
10661 if (offset
+ 1 < buffer
.length
)
10662 val
= buffer
.parent
[buffer
.offset
+ offset
+ 1] << 16;
10663 if (offset
+ 2 < buffer
.length
)
10664 val
|= buffer
.parent
[buffer
.offset
+ offset
+ 2] << 8;
10665 if (offset
+ 3 < buffer
.length
)
10666 val
|= buffer
.parent
[buffer
.offset
+ offset
+ 3];
10667 val
= val
+ (buffer
.parent
[buffer
.offset
+ offset
] << 24 >>> 0);
10669 if (offset
+ 2 < buffer
.length
)
10670 val
= buffer
.parent
[buffer
.offset
+ offset
+ 2] << 16;
10671 if (offset
+ 1 < buffer
.length
)
10672 val
|= buffer
.parent
[buffer
.offset
+ offset
+ 1] << 8;
10673 val
|= buffer
.parent
[buffer
.offset
+ offset
];
10674 if (offset
+ 3 < buffer
.length
)
10675 val
= val
+ (buffer
.parent
[buffer
.offset
+ offset
+ 3] << 24 >>> 0);
10681 Buffer
.prototype.readUInt32LE = function(offset
, noAssert
) {
10682 return readUInt32(this, offset
, false, noAssert
);
10685 Buffer
.prototype.readUInt32BE = function(offset
, noAssert
) {
10686 return readUInt32(this, offset
, true, noAssert
);
10691 * Signed integer types, yay team! A reminder on how two's complement actually
10692 * works. The first bit is the signed bit, i.e. tells us whether or not the
10693 * number should be positive or negative. If the two's complement value is
10694 * positive, then we're done, as it's equivalent to the unsigned representation.
10696 * Now if the number is positive, you're pretty much done, you can just leverage
10697 * the unsigned translations and return those. Unfortunately, negative numbers
10698 * aren't quite that straightforward.
10700 * At first glance, one might be inclined to use the traditional formula to
10701 * translate binary numbers between the positive and negative values in two's
10702 * complement. (Though it doesn't quite work for the most negative value)
10704 * - invert all the bits
10705 * - add one to the result
10707 * Of course, this doesn't quite work in Javascript. Take for example the value
10708 * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
10709 * course, Javascript will do the following:
10714 * Whoh there, Javascript, that's not quite right. But wait, according to
10715 * Javascript that's perfectly correct. When Javascript ends up seeing the
10716 * constant 0xff80, it has no notion that it is actually a signed number. It
10717 * assumes that we've input the unsigned value 0xff80. Thus, when it does the
10718 * binary negation, it casts it into a signed value, (positive 0xff80). Then
10719 * when you perform binary negation on that, it turns it into a negative number.
10721 * Instead, we're going to have to use the following general formula, that works
10722 * in a rather Javascript friendly way. I'm glad we don't support this kind of
10723 * weird numbering scheme in the kernel.
10725 * (BIT-MAX - (unsigned)val + 1) * -1
10727 * The astute observer, may think that this doesn't make sense for 8-bit numbers
10728 * (really it isn't necessary for them). However, when you get 16-bit numbers,
10729 * you do. Let's go back to our prior example and see how this will look:
10731 * (0xffff - 0xff80 + 1) * -1
10732 * (0x007f + 1) * -1
10735 Buffer
.prototype.readInt8 = function(offset
, noAssert
) {
10740 assert
.ok(offset
!== undefined && offset
!== null,
10743 assert
.ok(offset
< buffer
.length
,
10744 'Trying to read beyond buffer length');
10747 if (offset
>= buffer
.length
) return;
10749 neg
= buffer
.parent
[buffer
.offset
+ offset
] & 0x80;
10751 return (buffer
.parent
[buffer
.offset
+ offset
]);
10754 return ((0xff - buffer
.parent
[buffer
.offset
+ offset
] + 1) * -1);
10757 function readInt16(buffer
, offset
, isBigEndian
, noAssert
) {
10761 assert
.ok(typeof (isBigEndian
) === 'boolean',
10762 'missing or invalid endian');
10764 assert
.ok(offset
!== undefined && offset
!== null,
10767 assert
.ok(offset
+ 1 < buffer
.length
,
10768 'Trying to read beyond buffer length');
10771 val
= readUInt16(buffer
, offset
, isBigEndian
, noAssert
);
10772 neg
= val
& 0x8000;
10777 return (0xffff - val
+ 1) * -1;
10780 Buffer
.prototype.readInt16LE = function(offset
, noAssert
) {
10781 return readInt16(this, offset
, false, noAssert
);
10784 Buffer
.prototype.readInt16BE = function(offset
, noAssert
) {
10785 return readInt16(this, offset
, true, noAssert
);
10788 function readInt32(buffer
, offset
, isBigEndian
, noAssert
) {
10792 assert
.ok(typeof (isBigEndian
) === 'boolean',
10793 'missing or invalid endian');
10795 assert
.ok(offset
!== undefined && offset
!== null,
10798 assert
.ok(offset
+ 3 < buffer
.length
,
10799 'Trying to read beyond buffer length');
10802 val
= readUInt32(buffer
, offset
, isBigEndian
, noAssert
);
10803 neg
= val
& 0x80000000;
10808 return (0xffffffff - val
+ 1) * -1;
10811 Buffer
.prototype.readInt32LE = function(offset
, noAssert
) {
10812 return readInt32(this, offset
, false, noAssert
);
10815 Buffer
.prototype.readInt32BE = function(offset
, noAssert
) {
10816 return readInt32(this, offset
, true, noAssert
);
10819 function readFloat(buffer
, offset
, isBigEndian
, noAssert
) {
10821 assert
.ok(typeof (isBigEndian
) === 'boolean',
10822 'missing or invalid endian');
10824 assert
.ok(offset
+ 3 < buffer
.length
,
10825 'Trying to read beyond buffer length');
10828 return require('./buffer_ieee754').readIEEE754(buffer
, offset
, isBigEndian
,
10832 Buffer
.prototype.readFloatLE = function(offset
, noAssert
) {
10833 return readFloat(this, offset
, false, noAssert
);
10836 Buffer
.prototype.readFloatBE = function(offset
, noAssert
) {
10837 return readFloat(this, offset
, true, noAssert
);
10840 function readDouble(buffer
, offset
, isBigEndian
, noAssert
) {
10842 assert
.ok(typeof (isBigEndian
) === 'boolean',
10843 'missing or invalid endian');
10845 assert
.ok(offset
+ 7 < buffer
.length
,
10846 'Trying to read beyond buffer length');
10849 return require('./buffer_ieee754').readIEEE754(buffer
, offset
, isBigEndian
,
10853 Buffer
.prototype.readDoubleLE = function(offset
, noAssert
) {
10854 return readDouble(this, offset
, false, noAssert
);
10857 Buffer
.prototype.readDoubleBE = function(offset
, noAssert
) {
10858 return readDouble(this, offset
, true, noAssert
);
10863 * We have to make sure that the value is a valid integer. This means that it is
10864 * non-negative. It has no fractional component and that it does not exceed the
10865 * maximum allowed value.
10867 * value The number to check for validity
10869 * max The maximum value
10871 function verifuint(value
, max
) {
10872 assert
.ok(typeof (value
) == 'number',
10873 'cannot write a non-number as a number');
10875 assert
.ok(value
>= 0,
10876 'specified a negative value for writing an unsigned value');
10878 assert
.ok(value
<= max
, 'value is larger than maximum value for type');
10880 assert
.ok(Math
.floor(value
) === value
, 'value has a fractional component');
10883 Buffer
.prototype.writeUInt8 = function(value
, offset
, noAssert
) {
10887 assert
.ok(value
!== undefined && value
!== null,
10890 assert
.ok(offset
!== undefined && offset
!== null,
10893 assert
.ok(offset
< buffer
.length
,
10894 'trying to write beyond buffer length');
10896 verifuint(value
, 0xff);
10899 if (offset
< buffer
.length
) {
10900 buffer
.parent
[buffer
.offset
+ offset
] = value
;
10904 function writeUInt16(buffer
, value
, offset
, isBigEndian
, noAssert
) {
10906 assert
.ok(value
!== undefined && value
!== null,
10909 assert
.ok(typeof (isBigEndian
) === 'boolean',
10910 'missing or invalid endian');
10912 assert
.ok(offset
!== undefined && offset
!== null,
10915 assert
.ok(offset
+ 1 < buffer
.length
,
10916 'trying to write beyond buffer length');
10918 verifuint(value
, 0xffff);
10921 for (var i
= 0; i
< Math
.min(buffer
.length
- offset
, 2); i
++) {
10922 buffer
.parent
[buffer
.offset
+ offset
+ i
] =
10923 (value
& (0xff << (8 * (isBigEndian
? 1 - i
: i
)))) >>>
10924 (isBigEndian
? 1 - i
: i
) * 8;
10929 Buffer
.prototype.writeUInt16LE = function(value
, offset
, noAssert
) {
10930 writeUInt16(this, value
, offset
, false, noAssert
);
10933 Buffer
.prototype.writeUInt16BE = function(value
, offset
, noAssert
) {
10934 writeUInt16(this, value
, offset
, true, noAssert
);
10937 function writeUInt32(buffer
, value
, offset
, isBigEndian
, noAssert
) {
10939 assert
.ok(value
!== undefined && value
!== null,
10942 assert
.ok(typeof (isBigEndian
) === 'boolean',
10943 'missing or invalid endian');
10945 assert
.ok(offset
!== undefined && offset
!== null,
10948 assert
.ok(offset
+ 3 < buffer
.length
,
10949 'trying to write beyond buffer length');
10951 verifuint(value
, 0xffffffff);
10954 for (var i
= 0; i
< Math
.min(buffer
.length
- offset
, 4); i
++) {
10955 buffer
.parent
[buffer
.offset
+ offset
+ i
] =
10956 (value
>>> (isBigEndian
? 3 - i
: i
) * 8) & 0xff;
10960 Buffer
.prototype.writeUInt32LE = function(value
, offset
, noAssert
) {
10961 writeUInt32(this, value
, offset
, false, noAssert
);
10964 Buffer
.prototype.writeUInt32BE = function(value
, offset
, noAssert
) {
10965 writeUInt32(this, value
, offset
, true, noAssert
);
10970 * We now move onto our friends in the signed number category. Unlike unsigned
10971 * numbers, we're going to have to worry a bit more about how we put values into
10972 * arrays. Since we are only worrying about signed 32-bit values, we're in
10973 * slightly better shape. Unfortunately, we really can't do our favorite binary
10974 * & in this system. It really seems to do the wrong thing. For example:
10979 * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
10980 * this aren't treated as a signed number. Ultimately a bad thing.
10982 * What we're going to want to do is basically create the unsigned equivalent of
10983 * our representation and pass that off to the wuint* functions. To do that
10984 * we're going to do the following:
10986 * - if the value is positive
10987 * we can pass it directly off to the equivalent wuint
10988 * - if the value is negative
10989 * we do the following computation:
10990 * mb + val + 1, where
10991 * mb is the maximum unsigned value in that byte size
10992 * val is the Javascript negative integer
10995 * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
10996 * you do out the computations:
11002 * You can then encode this value as the signed version. This is really rather
11003 * hacky, but it should work and get the job done which is our goal here.
11007 * A series of checks to make sure we actually have a signed 32-bit number
11009 function verifsint(value
, max
, min
) {
11010 assert
.ok(typeof (value
) == 'number',
11011 'cannot write a non-number as a number');
11013 assert
.ok(value
<= max
, 'value larger than maximum allowed value');
11015 assert
.ok(value
>= min
, 'value smaller than minimum allowed value');
11017 assert
.ok(Math
.floor(value
) === value
, 'value has a fractional component');
11020 function verifIEEE754(value
, max
, min
) {
11021 assert
.ok(typeof (value
) == 'number',
11022 'cannot write a non-number as a number');
11024 assert
.ok(value
<= max
, 'value larger than maximum allowed value');
11026 assert
.ok(value
>= min
, 'value smaller than minimum allowed value');
11029 Buffer
.prototype.writeInt8 = function(value
, offset
, noAssert
) {
11033 assert
.ok(value
!== undefined && value
!== null,
11036 assert
.ok(offset
!== undefined && offset
!== null,
11039 assert
.ok(offset
< buffer
.length
,
11040 'Trying to write beyond buffer length');
11042 verifsint(value
, 0x7f, -0x80);
11046 buffer
.writeUInt8(value
, offset
, noAssert
);
11048 buffer
.writeUInt8(0xff + value
+ 1, offset
, noAssert
);
11052 function writeInt16(buffer
, value
, offset
, isBigEndian
, noAssert
) {
11054 assert
.ok(value
!== undefined && value
!== null,
11057 assert
.ok(typeof (isBigEndian
) === 'boolean',
11058 'missing or invalid endian');
11060 assert
.ok(offset
!== undefined && offset
!== null,
11063 assert
.ok(offset
+ 1 < buffer
.length
,
11064 'Trying to write beyond buffer length');
11066 verifsint(value
, 0x7fff, -0x8000);
11070 writeUInt16(buffer
, value
, offset
, isBigEndian
, noAssert
);
11072 writeUInt16(buffer
, 0xffff + value
+ 1, offset
, isBigEndian
, noAssert
);
11076 Buffer
.prototype.writeInt16LE = function(value
, offset
, noAssert
) {
11077 writeInt16(this, value
, offset
, false, noAssert
);
11080 Buffer
.prototype.writeInt16BE = function(value
, offset
, noAssert
) {
11081 writeInt16(this, value
, offset
, true, noAssert
);
11084 function writeInt32(buffer
, value
, offset
, isBigEndian
, noAssert
) {
11086 assert
.ok(value
!== undefined && value
!== null,
11089 assert
.ok(typeof (isBigEndian
) === 'boolean',
11090 'missing or invalid endian');
11092 assert
.ok(offset
!== undefined && offset
!== null,
11095 assert
.ok(offset
+ 3 < buffer
.length
,
11096 'Trying to write beyond buffer length');
11098 verifsint(value
, 0x7fffffff, -0x80000000);
11102 writeUInt32(buffer
, value
, offset
, isBigEndian
, noAssert
);
11104 writeUInt32(buffer
, 0xffffffff + value
+ 1, offset
, isBigEndian
, noAssert
);
11108 Buffer
.prototype.writeInt32LE = function(value
, offset
, noAssert
) {
11109 writeInt32(this, value
, offset
, false, noAssert
);
11112 Buffer
.prototype.writeInt32BE = function(value
, offset
, noAssert
) {
11113 writeInt32(this, value
, offset
, true, noAssert
);
11116 function writeFloat(buffer
, value
, offset
, isBigEndian
, noAssert
) {
11118 assert
.ok(value
!== undefined && value
!== null,
11121 assert
.ok(typeof (isBigEndian
) === 'boolean',
11122 'missing or invalid endian');
11124 assert
.ok(offset
!== undefined && offset
!== null,
11127 assert
.ok(offset
+ 3 < buffer
.length
,
11128 'Trying to write beyond buffer length');
11130 verifIEEE754(value
, 3.4028234663852886e+38, -3.4028234663852886e+38);
11133 require('./buffer_ieee754').writeIEEE754(buffer
, value
, offset
, isBigEndian
,
11137 Buffer
.prototype.writeFloatLE = function(value
, offset
, noAssert
) {
11138 writeFloat(this, value
, offset
, false, noAssert
);
11141 Buffer
.prototype.writeFloatBE = function(value
, offset
, noAssert
) {
11142 writeFloat(this, value
, offset
, true, noAssert
);
11145 function writeDouble(buffer
, value
, offset
, isBigEndian
, noAssert
) {
11147 assert
.ok(value
!== undefined && value
!== null,
11150 assert
.ok(typeof (isBigEndian
) === 'boolean',
11151 'missing or invalid endian');
11153 assert
.ok(offset
!== undefined && offset
!== null,
11156 assert
.ok(offset
+ 7 < buffer
.length
,
11157 'Trying to write beyond buffer length');
11159 verifIEEE754(value
, 1.7976931348623157E+308, -1.7976931348623157E+308);
11162 require('./buffer_ieee754').writeIEEE754(buffer
, value
, offset
, isBigEndian
,
11166 Buffer
.prototype.writeDoubleLE = function(value
, offset
, noAssert
) {
11167 writeDouble(this, value
, offset
, false, noAssert
);
11170 Buffer
.prototype.writeDoubleBE = function(value
, offset
, noAssert
) {
11171 writeDouble(this, value
, offset
, true, noAssert
);
11174 SlowBuffer
.prototype.readUInt8
= Buffer
.prototype.readUInt8
;
11175 SlowBuffer
.prototype.readUInt16LE
= Buffer
.prototype.readUInt16LE
;
11176 SlowBuffer
.prototype.readUInt16BE
= Buffer
.prototype.readUInt16BE
;
11177 SlowBuffer
.prototype.readUInt32LE
= Buffer
.prototype.readUInt32LE
;
11178 SlowBuffer
.prototype.readUInt32BE
= Buffer
.prototype.readUInt32BE
;
11179 SlowBuffer
.prototype.readInt8
= Buffer
.prototype.readInt8
;
11180 SlowBuffer
.prototype.readInt16LE
= Buffer
.prototype.readInt16LE
;
11181 SlowBuffer
.prototype.readInt16BE
= Buffer
.prototype.readInt16BE
;
11182 SlowBuffer
.prototype.readInt32LE
= Buffer
.prototype.readInt32LE
;
11183 SlowBuffer
.prototype.readInt32BE
= Buffer
.prototype.readInt32BE
;
11184 SlowBuffer
.prototype.readFloatLE
= Buffer
.prototype.readFloatLE
;
11185 SlowBuffer
.prototype.readFloatBE
= Buffer
.prototype.readFloatBE
;
11186 SlowBuffer
.prototype.readDoubleLE
= Buffer
.prototype.readDoubleLE
;
11187 SlowBuffer
.prototype.readDoubleBE
= Buffer
.prototype.readDoubleBE
;
11188 SlowBuffer
.prototype.writeUInt8
= Buffer
.prototype.writeUInt8
;
11189 SlowBuffer
.prototype.writeUInt16LE
= Buffer
.prototype.writeUInt16LE
;
11190 SlowBuffer
.prototype.writeUInt16BE
= Buffer
.prototype.writeUInt16BE
;
11191 SlowBuffer
.prototype.writeUInt32LE
= Buffer
.prototype.writeUInt32LE
;
11192 SlowBuffer
.prototype.writeUInt32BE
= Buffer
.prototype.writeUInt32BE
;
11193 SlowBuffer
.prototype.writeInt8
= Buffer
.prototype.writeInt8
;
11194 SlowBuffer
.prototype.writeInt16LE
= Buffer
.prototype.writeInt16LE
;
11195 SlowBuffer
.prototype.writeInt16BE
= Buffer
.prototype.writeInt16BE
;
11196 SlowBuffer
.prototype.writeInt32LE
= Buffer
.prototype.writeInt32LE
;
11197 SlowBuffer
.prototype.writeInt32BE
= Buffer
.prototype.writeInt32BE
;
11198 SlowBuffer
.prototype.writeFloatLE
= Buffer
.prototype.writeFloatLE
;
11199 SlowBuffer
.prototype.writeFloatBE
= Buffer
.prototype.writeFloatBE
;
11200 SlowBuffer
.prototype.writeDoubleLE
= Buffer
.prototype.writeDoubleLE
;
11201 SlowBuffer
.prototype.writeDoubleBE
= Buffer
.prototype.writeDoubleBE
;
11204 },{"assert":12,"./buffer_ieee754":14,"base64-js":15}],15:[function(require
,module
,exports
){
11205 (function (exports
) {
11208 var lookup
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
11210 function b64ToByteArray(b64
) {
11211 var i
, j
, l
, tmp
, placeHolders
, arr
;
11213 if (b64
.length
% 4 > 0) {
11214 throw 'Invalid string. Length must be a multiple of 4';
11217 // the number of equal signs (place holders)
11218 // if there are two placeholders, than the two characters before it
11219 // represent one byte
11220 // if there is only one, then the three characters before it represent 2 bytes
11221 // this is just a cheap hack to not do indexOf twice
11222 placeHolders
= b64
.indexOf('=');
11223 placeHolders
= placeHolders
> 0 ? b64
.length
- placeHolders
: 0;
11225 // base64 is 4/3 + up to two characters of the original data
11226 arr
= [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
11228 // if there are placeholders, only get up to the last complete 4 chars
11229 l
= placeHolders
> 0 ? b64
.length
- 4 : b64
.length
;
11231 for (i
= 0, j
= 0; i
< l
; i
+= 4, j
+= 3) {
11232 tmp
= (lookup
.indexOf(b64
[i
]) << 18) | (lookup
.indexOf(b64
[i
+ 1]) << 12) | (lookup
.indexOf(b64
[i
+ 2]) << 6) | lookup
.indexOf(b64
[i
+ 3]);
11233 arr
.push((tmp
& 0xFF0000) >> 16);
11234 arr
.push((tmp
& 0xFF00) >> 8);
11235 arr
.push(tmp
& 0xFF);
11238 if (placeHolders
=== 2) {
11239 tmp
= (lookup
.indexOf(b64
[i
]) << 2) | (lookup
.indexOf(b64
[i
+ 1]) >> 4);
11240 arr
.push(tmp
& 0xFF);
11241 } else if (placeHolders
=== 1) {
11242 tmp
= (lookup
.indexOf(b64
[i
]) << 10) | (lookup
.indexOf(b64
[i
+ 1]) << 4) | (lookup
.indexOf(b64
[i
+ 2]) >> 2);
11243 arr
.push((tmp
>> 8) & 0xFF);
11244 arr
.push(tmp
& 0xFF);
11250 function uint8ToBase64(uint8
) {
11252 extraBytes
= uint8
.length
% 3, // if we have 1 byte left, pad 2 bytes
11256 function tripletToBase64 (num
) {
11257 return lookup
[num
>> 18 & 0x3F] + lookup
[num
>> 12 & 0x3F] + lookup
[num
>> 6 & 0x3F] + lookup
[num
& 0x3F];
11260 // go through the array every three bytes, we'll deal with trailing stuff later
11261 for (i
= 0, length
= uint8
.length
- extraBytes
; i
< length
; i
+= 3) {
11262 temp
= (uint8
[i
] << 16) + (uint8
[i
+ 1] << 8) + (uint8
[i
+ 2]);
11263 output
+= tripletToBase64(temp
);
11266 // pad the end with zeros, but make sure to not forget the extra bytes
11267 switch (extraBytes
) {
11269 temp
= uint8
[uint8
.length
- 1];
11270 output
+= lookup
[temp
>> 2];
11271 output
+= lookup
[(temp
<< 4) & 0x3F];
11275 temp
= (uint8
[uint8
.length
- 2] << 8) + (uint8
[uint8
.length
- 1]);
11276 output
+= lookup
[temp
>> 10];
11277 output
+= lookup
[(temp
>> 4) & 0x3F];
11278 output
+= lookup
[(temp
<< 2) & 0x3F];
11286 module
.exports
.toByteArray
= b64ToByteArray
;
11287 module
.exports
.fromByteArray
= uint8ToBase64
;
11290 },{}]},{},["E/GbHF"])
11292 JSHINT
= require('jshint').JSHINT
;