pre-commit 0.1.17 → 0.1.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,11 +24,7 @@ class PreCommit
24
24
 
25
25
  def run_check(file)
26
26
  context = ExecJS.compile(File.read(linter_src))
27
- if !(context.call('JSHINT', File.read(file), config))
28
- context.exec('return JSHINT.errors;')
29
- else
30
- []
31
- end
27
+ context.call('JSHINT', File.read(file), config)
32
28
  end
33
29
 
34
30
  def linter_src
@@ -1,4 +1,4 @@
1
- /*
1
+ /*!
2
2
  * JSHint, by JSHint Community.
3
3
  *
4
4
  * Licensed under the same slightly modified MIT license that JSLint is.
@@ -128,7 +128,7 @@
128
128
  member: {
129
129
  STRING: NUMBER
130
130
  },
131
- unuseds: [
131
+ unused: [
132
132
  {
133
133
  name: STRING,
134
134
  line: NUMBER
@@ -151,65 +151,79 @@
151
151
  */
152
152
 
153
153
  /*jshint
154
- evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true
154
+ evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true,
155
+ undef: true, maxlen: 100, indent:4
155
156
  */
156
157
 
157
- /*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%",
158
- "(begin)", "(breakage)", "(context)", "(error)", "(global)",
159
- "(identifier)", "(last)", "(line)", "(loopage)", "(name)", "(onevar)",
160
- "(params)", "(scope)", "(statement)", "(verb)", "*", "+", "++", "-",
161
- "--", "\/", "<", "<=", "==", "===", ">", ">=", $, $$, $A, $F, $H, $R, $break,
162
- $continue, $w, Abstract, Ajax, __filename, __dirname, ActiveXObject, Array,
163
- ArrayBuffer, ArrayBufferView, Autocompleter, Assets, Boolean, Builder,
164
- Buffer, Browser, COM, CScript, Canvas, CustomAnimation, Class, Control,
165
- Chain, Color, Cookie, Core, DataView, Date, Debug, Draggable, Draggables,
166
- Droppables, Document, DomReady, DOMReady, Drag, E, Enumerator, Enumerable,
167
- Element, Elements, Error, Effect, EvalError, Event, Events, FadeAnimation,
168
- Field, Flash, Float32Array, Float64Array, Form, FormField, Frame, Function,
169
- Fx, Group, Hash, HotKey, HTMLElement, HtmlTable, Iframe, IframeShim, Image,
170
- Int16Array, Int32Array, Int8Array, Insertion, InputValidator, JSON, Keyboard,
171
- Locale, LN10, LN2, LOG10E, LOG2E, MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem,
172
- MoveAnimation, MooTools, Native, NEGATIVE_INFINITY, Number, Object,
173
- ObjectRange, Option, Options, OverText, PI, POSITIVE_INFINITY,
174
- PeriodicalExecuter, Point, Position, Prototype, RangeError, Rectangle,
175
- ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, SQRT1_2,
176
- SQRT2, ScrollBar, Scriptaculous, Scroller, Slick, Slider, Selector, String,
177
- Style, SyntaxError, Sortable, Sortables, SortableObserver, Sound, Spinner,
178
- System, Swiff, Text, TextArea, Template, Timer, Tips, Type, TypeError,
179
- Toggle, Try, URI, URIError, URL, VBArray, WScript, Web, Window, XMLDOM,
180
- XMLHttpRequest, XPathEvaluator, XPathException, XPathExpression,
181
- XPathNamespace, XPathNSResolver, XPathResult, "\\", a, addEventListener,
182
- address, alert, apply, applicationCache, arguments, arity, asi, b, bitwise,
183
- block, blur, boolOptions, boss, browser, c, call, callee, caller, cases,
184
- charAt, charCodeAt, character, clearInterval, clearTimeout, close, closed,
185
- closure, comment, condition, confirm, console, constructor, content, couch,
186
- create, css, curly, d, data, datalist, dd, debug, decodeURI,
187
- decodeURIComponent, defaultStatus, defineClass, deserialize, devel,
188
- document, edition, else, emit, encodeURI, encodeURIComponent, entityify,
189
- eqeqeq, eqnull, errors, es5, escape, eval, event, evidence, evil, ex,
190
- exception, exec, exps, expr, exports, FileReader, first, floor, focus,
191
- forin, fragment, frames, from, fromCharCode, fud, funct, function, functions,
192
- g, gc, getComputedStyle, getRow, GLOBAL, global, globals, globalstrict,
193
- hasOwnProperty, help, history, i, id, identifier, immed, implieds,
194
- include, indent, indexOf, init, ins, instanceOf, isAlpha,
195
- isApplicationRunning, isArray, isDigit, isFinite, isNaN, join, jshint,
196
- JSHINT, json, jquery, jQuery, keys, label, labelled, last, laxbreak,
197
- latedef, lbp, led, left, length, line, load, loadClass, localStorage,
198
- location, log, loopfunc, m, match, maxerr, maxlen, member,message, meta,
199
- module, moveBy, moveTo, mootools, name, navigator, new, newcap, noarg,
200
- node, noempty, nomen, nonew, nud, onbeforeunload, onblur, onerror, onevar,
201
- onfocus, onload, onresize, onunload, open, openDatabase, openURL, opener,
202
- opera, outer, param, parent, parseFloat, parseInt, passfail, plusplus,
203
- predef, print, process, prompt, prototype, prototypejs, push, quit, range,
204
- raw, reach, reason, regexp, readFile, readUrl, removeEventListener, replace,
205
- report, require, reserved, resizeBy, resizeTo, resolvePath, resumeUpdates,
206
- respond, rhino, right, runCommand, scroll, screen, scrollBy, scrollTo,
207
- scrollbar, search, seal, send, serialize, setInterval, setTimeout, shift,
208
- slice, sort,spawn, split, stack, status, start, strict, sub, substr, supernew,
209
- shadow, supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32,
210
- token, top, type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef,
211
- unused, urls, value, valueOf, var, version, WebSocket, white, window, Worker
212
- */
158
+ /*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)",
159
+ "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)",
160
+ "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)",
161
+ "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==",
162
+ "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,
163
+ __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio,
164
+ Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas,
165
+ CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date,
166
+ Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag,
167
+ E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,
168
+ Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,
169
+ FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey,
170
+ HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement,
171
+ HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement,
172
+ HTMLDivElement, HTMLDListElement, HTMLFieldSetElement,
173
+ HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement,
174
+ HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement,
175
+ HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement,
176
+ HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement,
177
+ HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement,
178
+ HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement,
179
+ HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement,
180
+ HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement,
181
+ HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement,
182
+ HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement,
183
+ HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement,
184
+ Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array,
185
+ Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,
186
+ MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native,
187
+ NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI,
188
+ POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError,
189
+ Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation,
190
+ SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,
191
+ ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,
192
+ Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables,
193
+ SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,
194
+ Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL,
195
+ VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator,
196
+ XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a,
197
+ addEventListener, address, alert, apply, applicationCache, arguments, arity,
198
+ asi, b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, c, call, callee,
199
+ caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout,
200
+ close, closed, closure, comment, condition, confirm, console, constructor,
201
+ content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI,
202
+ decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,
203
+ dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent,
204
+ entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,
205
+ ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus,
206
+ forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,
207
+ g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,
208
+ hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,
209
+ indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray,
210
+ isDigit, isFinite, isNaN, iterator, java, join, jshint,
211
+ JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, laxcomma,
212
+ latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,
213
+ log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy,
214
+ moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen,
215
+ nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus,
216
+ onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param,
217
+ parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt,
218
+ proto, prototype, prototypejs, provides, push, quit, range, raw, reach, reason, regexp,
219
+ readFile, readUrl, regexdash, removeEventListener, replace, report, require,
220
+ reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right,
221
+ runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal,
222
+ send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice,
223
+ smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow,
224
+ supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing,
225
+ type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis,
226
+ value, valueOf, var, version, WebSocket, white, window, Worker, wsh*/
213
227
 
214
228
  /*global exports: false */
215
229
 
@@ -240,123 +254,208 @@ var JSHINT = (function () {
240
254
  '%' : true
241
255
  },
242
256
 
243
- // These are the JSHint boolean options.
244
-
257
+ // These are the JSHint boolean options.
245
258
  boolOptions = {
246
259
  asi : true, // if automatic semicolon insertion should be tolerated
247
260
  bitwise : true, // if bitwise operators should not be allowed
248
261
  boss : true, // if advanced usage of assignments should be allowed
249
262
  browser : true, // if the standard browser globals should be predefined
250
263
  couch : true, // if CouchDB globals should be predefined
251
- curly : true, // if curly braces around blocks should be required (even in if/for/while)
264
+ curly : true, // if curly braces around all blocks should be required
252
265
  debug : true, // if debugger statements should be allowed
253
- devel : true, // if logging globals should be predefined (console, alert, etc.)
266
+ devel : true, // if logging globals should be predefined (console,
267
+ // alert, etc.)
268
+ dojo : true, // if Dojo Toolkit globals should be predefined
254
269
  eqeqeq : true, // if === should be required
255
270
  eqnull : true, // if == null comparisons should be tolerated
256
271
  es5 : true, // if ES5 syntax should be allowed
272
+ esnext : true, // if es.next specific syntax should be allowed
257
273
  evil : true, // if eval should be allowed
258
274
  expr : true, // if ExpressionStatement should be allowed as Programs
259
275
  forin : true, // if for in statements must filter
260
- globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
276
+ funcscope : true, // if only function scope should be used for scope tests
277
+ globalstrict: true, // if global "use strict"; should be allowed (also
278
+ // enables 'strict')
261
279
  immed : true, // if immediate invocations must be wrapped in parens
280
+ iterator : true, // if the `__iterator__` property should be allowed
262
281
  jquery : true, // if jQuery globals should be predefined
282
+ lastsemic : true, // if semicolons may be ommitted for the trailing
283
+ // statements inside of a one-line blocks.
263
284
  latedef : true, // if the use before definition should not be tolerated
264
285
  laxbreak : true, // if line breaks should not be checked
265
- loopfunc : true, // if functions should be allowed to be defined within loops
286
+ laxcomma : true, // if line breaks should not be checked around commas
287
+ loopfunc : true, // if functions should be allowed to be defined within
288
+ // loops
266
289
  mootools : true, // if MooTools globals should be predefined
290
+ multistr : true, // allow multiline strings
267
291
  newcap : true, // if constructor names must be capitalized
268
- noarg : true, // if arguments.caller and arguments.callee should be disallowed
269
- node : true, // if the Node.js environment globals should be predefined
292
+ noarg : true, // if arguments.caller and arguments.callee should be
293
+ // disallowed
294
+ node : true, // if the Node.js environment globals should be
295
+ // predefined
270
296
  noempty : true, // if empty blocks should be disallowed
271
297
  nonew : true, // if using `new` for side-effects should be disallowed
298
+ nonstandard : true, // if non-standard (but widely adopted) globals should
299
+ // be predefined
272
300
  nomen : true, // if names should be checked
273
- onevar : true, // if only one var statement per function should be allowed
301
+ onevar : true, // if only one var statement per function should be
302
+ // allowed
303
+ onecase : true, // if one case switch statements should be allowed
274
304
  passfail : true, // if the scan should stop on first error
275
305
  plusplus : true, // if increment/decrement should not be allowed
276
- prototypejs : true, // if Prototype and Scriptaculous globals shoudl be predefined
306
+ proto : true, // if the `__proto__` property should be allowed
307
+ prototypejs : true, // if Prototype and Scriptaculous globals should be
308
+ // predefined
309
+ regexdash : true, // if unescaped first/last dash (-) inside brackets
310
+ // should be tolerated
277
311
  regexp : true, // if the . should not be allowed in regexp literals
278
312
  rhino : true, // if the Rhino environment globals should be predefined
279
313
  undef : true, // if variables should be declared before used
314
+ scripturl : true, // if script-targeted URLs should be tolerated
280
315
  shadow : true, // if variable shadowing should be tolerated
316
+ smarttabs : true, // if smarttabs should be tolerated
317
+ // (http://www.emacswiki.org/emacs/SmartTabs)
281
318
  strict : true, // require the "use strict"; pragma
282
319
  sub : true, // if all forms of subscript notation are tolerated
283
- supernew : true, // if `new function () { ... };` and `new Object;` should be tolerated
284
- white : true // if strict whitespace rules apply
320
+ supernew : true, // if `new function () { ... };` and `new Object;`
321
+ // should be tolerated
322
+ trailing : true, // if trailing whitespace rules apply
323
+ validthis : true, // if 'this' inside a non-constructor function is valid.
324
+ // This is a function scoped option only.
325
+ white : true, // if strict whitespace rules apply
326
+ wsh : true // if the Windows Scripting Host environment globals
327
+ // should be predefined
285
328
  },
286
329
 
287
- // browser contains a set of global names which are commonly provided by a
288
- // web browser environment.
289
-
330
+ // browser contains a set of global names which are commonly provided by a
331
+ // web browser environment.
290
332
  browser = {
291
- ArrayBuffer : false,
292
- ArrayBufferView : false,
293
- addEventListener: false,
294
- applicationCache: false,
295
- blur : false,
296
- clearInterval : false,
297
- clearTimeout : false,
298
- close : false,
299
- closed : false,
300
- DataView : false,
301
- defaultStatus : false,
302
- document : false,
303
- event : false,
304
- FileReader : false,
305
- Float32Array : false,
306
- Float64Array : false,
307
- focus : false,
308
- frames : false,
309
- getComputedStyle: false,
310
- HTMLElement : false,
311
- history : false,
312
- Int16Array : false,
313
- Int32Array : false,
314
- Int8Array : false,
315
- Image : false,
316
- length : false,
317
- localStorage : false,
318
- location : false,
319
- moveBy : false,
320
- moveTo : false,
321
- name : false,
322
- navigator : false,
323
- onbeforeunload : true,
324
- onblur : true,
325
- onerror : true,
326
- onfocus : true,
327
- onload : true,
328
- onresize : true,
329
- onunload : true,
330
- open : false,
331
- openDatabase : false,
332
- opener : false,
333
- Option : false,
334
- parent : false,
335
- print : false,
336
- removeEventListener: false,
337
- resizeBy : false,
338
- resizeTo : false,
339
- screen : false,
340
- scroll : false,
341
- scrollBy : false,
342
- scrollTo : false,
343
- setInterval : false,
344
- setTimeout : false,
345
- status : false,
346
- top : false,
347
- Uint16Array : false,
348
- Uint32Array : false,
349
- Uint8Array : false,
350
- WebSocket : false,
351
- window : false,
352
- Worker : false,
353
- XMLHttpRequest : false,
354
- XPathEvaluator : false,
355
- XPathException : false,
356
- XPathExpression : false,
357
- XPathNamespace : false,
358
- XPathNSResolver : false,
359
- XPathResult : false
333
+ ArrayBuffer : false,
334
+ ArrayBufferView : false,
335
+ Audio : false,
336
+ addEventListener : false,
337
+ applicationCache : false,
338
+ blur : false,
339
+ clearInterval : false,
340
+ clearTimeout : false,
341
+ close : false,
342
+ closed : false,
343
+ DataView : false,
344
+ defaultStatus : false,
345
+ document : false,
346
+ event : false,
347
+ FileReader : false,
348
+ Float32Array : false,
349
+ Float64Array : false,
350
+ FormData : false,
351
+ focus : false,
352
+ frames : false,
353
+ getComputedStyle : false,
354
+ HTMLElement : false,
355
+ HTMLAnchorElement : false,
356
+ HTMLBaseElement : false,
357
+ HTMLBlockquoteElement : false,
358
+ HTMLBodyElement : false,
359
+ HTMLBRElement : false,
360
+ HTMLButtonElement : false,
361
+ HTMLCanvasElement : false,
362
+ HTMLDirectoryElement : false,
363
+ HTMLDivElement : false,
364
+ HTMLDListElement : false,
365
+ HTMLFieldSetElement : false,
366
+ HTMLFontElement : false,
367
+ HTMLFormElement : false,
368
+ HTMLFrameElement : false,
369
+ HTMLFrameSetElement : false,
370
+ HTMLHeadElement : false,
371
+ HTMLHeadingElement : false,
372
+ HTMLHRElement : false,
373
+ HTMLHtmlElement : false,
374
+ HTMLIFrameElement : false,
375
+ HTMLImageElement : false,
376
+ HTMLInputElement : false,
377
+ HTMLIsIndexElement : false,
378
+ HTMLLabelElement : false,
379
+ HTMLLayerElement : false,
380
+ HTMLLegendElement : false,
381
+ HTMLLIElement : false,
382
+ HTMLLinkElement : false,
383
+ HTMLMapElement : false,
384
+ HTMLMenuElement : false,
385
+ HTMLMetaElement : false,
386
+ HTMLModElement : false,
387
+ HTMLObjectElement : false,
388
+ HTMLOListElement : false,
389
+ HTMLOptGroupElement : false,
390
+ HTMLOptionElement : false,
391
+ HTMLParagraphElement : false,
392
+ HTMLParamElement : false,
393
+ HTMLPreElement : false,
394
+ HTMLQuoteElement : false,
395
+ HTMLScriptElement : false,
396
+ HTMLSelectElement : false,
397
+ HTMLStyleElement : false,
398
+ HTMLTableCaptionElement : false,
399
+ HTMLTableCellElement : false,
400
+ HTMLTableColElement : false,
401
+ HTMLTableElement : false,
402
+ HTMLTableRowElement : false,
403
+ HTMLTableSectionElement : false,
404
+ HTMLTextAreaElement : false,
405
+ HTMLTitleElement : false,
406
+ HTMLUListElement : false,
407
+ HTMLVideoElement : false,
408
+ history : false,
409
+ Int16Array : false,
410
+ Int32Array : false,
411
+ Int8Array : false,
412
+ Image : false,
413
+ length : false,
414
+ localStorage : false,
415
+ location : false,
416
+ moveBy : false,
417
+ moveTo : false,
418
+ name : false,
419
+ navigator : false,
420
+ onbeforeunload : true,
421
+ onblur : true,
422
+ onerror : true,
423
+ onfocus : true,
424
+ onload : true,
425
+ onresize : true,
426
+ onunload : true,
427
+ open : false,
428
+ openDatabase : false,
429
+ opener : false,
430
+ Option : false,
431
+ parent : false,
432
+ print : false,
433
+ removeEventListener : false,
434
+ resizeBy : false,
435
+ resizeTo : false,
436
+ screen : false,
437
+ scroll : false,
438
+ scrollBy : false,
439
+ scrollTo : false,
440
+ sessionStorage : false,
441
+ setInterval : false,
442
+ setTimeout : false,
443
+ SharedWorker : false,
444
+ status : false,
445
+ top : false,
446
+ Uint16Array : false,
447
+ Uint32Array : false,
448
+ Uint8Array : false,
449
+ WebSocket : false,
450
+ window : false,
451
+ Worker : false,
452
+ XMLHttpRequest : false,
453
+ XPathEvaluator : false,
454
+ XPathException : false,
455
+ XPathExpression : false,
456
+ XPathNamespace : false,
457
+ XPathNSResolver : false,
458
+ XPathResult : false
360
459
  },
361
460
 
362
461
  couch = {
@@ -369,16 +468,25 @@ var JSHINT = (function () {
369
468
  sum : false,
370
469
  log : false,
371
470
  exports : false,
372
- module : false
471
+ module : false,
472
+ provides : false
373
473
  },
374
474
 
375
475
  devel = {
376
- alert : false,
377
- confirm : false,
378
- console : false,
379
- Debug : false,
380
- opera : false,
381
- prompt : false
476
+ alert : false,
477
+ confirm : false,
478
+ console : false,
479
+ Debug : false,
480
+ opera : false,
481
+ prompt : false
482
+ },
483
+
484
+ dojo = {
485
+ dojo : false,
486
+ dijit : false,
487
+ dojox : false,
488
+ define : false,
489
+ "require" : false
382
490
  },
383
491
 
384
492
  escapes = {
@@ -467,15 +575,20 @@ var JSHINT = (function () {
467
575
  nexttoken,
468
576
 
469
577
  node = {
470
- __filename : false,
471
- __dirname : false,
472
- exports : false,
473
- Buffer : false,
474
- GLOBAL : false,
475
- global : false,
476
- module : false,
477
- process : false,
478
- require : false
578
+ __filename : false,
579
+ __dirname : false,
580
+ Buffer : false,
581
+ console : false,
582
+ exports : false,
583
+ GLOBAL : false,
584
+ global : false,
585
+ module : false,
586
+ process : false,
587
+ require : false,
588
+ setTimeout : false,
589
+ clearTimeout : false,
590
+ setInterval : false,
591
+ clearInterval : false
479
592
  },
480
593
 
481
594
  noreach,
@@ -526,32 +639,32 @@ var JSHINT = (function () {
526
639
  },
527
640
 
528
641
  rhino = {
529
- defineClass : false,
530
- deserialize : false,
531
- gc : false,
532
- help : false,
533
- load : false,
534
- loadClass : false,
535
- print : false,
536
- quit : false,
537
- readFile : false,
538
- readUrl : false,
539
- runCommand : false,
540
- seal : false,
541
- serialize : false,
542
- spawn : false,
543
- sync : false,
544
- toint32 : false,
545
- version : false
642
+ defineClass : false,
643
+ deserialize : false,
644
+ gc : false,
645
+ help : false,
646
+ importPackage: false,
647
+ "java" : false,
648
+ load : false,
649
+ loadClass : false,
650
+ print : false,
651
+ quit : false,
652
+ readFile : false,
653
+ readUrl : false,
654
+ runCommand : false,
655
+ seal : false,
656
+ serialize : false,
657
+ spawn : false,
658
+ sync : false,
659
+ toint32 : false,
660
+ version : false
546
661
  },
547
662
 
548
663
  scope, // The current scope
549
- src,
550
664
  stack,
551
665
 
552
- // standard contains the global names that are provided by the
553
- // ECMAScript standard.
554
-
666
+ // standard contains the global names that are provided by the
667
+ // ECMAScript standard.
555
668
  standard = {
556
669
  Array : false,
557
670
  Boolean : false,
@@ -582,6 +695,12 @@ var JSHINT = (function () {
582
695
  URIError : false
583
696
  },
584
697
 
698
+ // widely adopted global names that are not part of ECMAScript standard
699
+ nonstandard = {
700
+ escape : false,
701
+ unescape : false
702
+ },
703
+
585
704
  standard_member = {
586
705
  E : true,
587
706
  LN2 : true,
@@ -597,32 +716,58 @@ var JSHINT = (function () {
597
716
  SQRT2 : true
598
717
  },
599
718
 
600
- strict_mode,
719
+ directive,
601
720
  syntax = {},
602
721
  tab,
603
722
  token,
604
723
  urls,
724
+ useESNextSyntax,
605
725
  warnings,
606
726
 
607
- // Regular expressions. Some of these are stupidly long.
608
-
609
- // unsafe comment or string
610
- ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i,
611
- // unsafe characters that are silently deleted by one or more browsers
612
- cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
613
- // token
614
- tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/,
615
- // characters in strings that need escapement
616
- nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
617
- nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
618
- // star slash
619
- lx = /\*\/|\/\*/,
620
- // identifier
621
- ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,
622
- // javascript url
623
- jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i,
624
- // catches /* falls through */ comments
727
+ wsh = {
728
+ ActiveXObject : true,
729
+ Enumerator : true,
730
+ GetObject : true,
731
+ ScriptEngine : true,
732
+ ScriptEngineBuildVersion : true,
733
+ ScriptEngineMajorVersion : true,
734
+ ScriptEngineMinorVersion : true,
735
+ VBArray : true,
736
+ WSH : true,
737
+ WScript : true,
738
+ XDomainRequest : true
739
+ };
740
+
741
+ // Regular expressions. Some of these are stupidly long.
742
+ var ax, cx, tx, nx, nxg, lx, ix, jx, ft;
743
+ (function () {
744
+ /*jshint maxlen:300 */
745
+
746
+ // unsafe comment or string
747
+ ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
748
+
749
+ // unsafe characters that are silently deleted by one or more browsers
750
+ cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
751
+
752
+ // token
753
+ tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/;
754
+
755
+ // characters in strings that need escapement
756
+ nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
757
+ nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
758
+
759
+ // star slash
760
+ lx = /\*\/|\/\*/;
761
+
762
+ // identifier
763
+ ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
764
+
765
+ // javascript url
766
+ jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
767
+
768
+ // catches /* falls through */ comments
625
769
  ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/;
770
+ }());
626
771
 
627
772
  function F() {} // Used by Object.create
628
773
 
@@ -730,47 +875,77 @@ var JSHINT = (function () {
730
875
  }
731
876
 
732
877
  function assume() {
733
- if (option.couch)
878
+ if (option.couch) {
734
879
  combine(predefined, couch);
880
+ }
735
881
 
736
- if (option.rhino)
882
+ if (option.rhino) {
737
883
  combine(predefined, rhino);
884
+ }
738
885
 
739
- if (option.prototypejs)
886
+ if (option.prototypejs) {
740
887
  combine(predefined, prototypejs);
888
+ }
741
889
 
742
- if (option.node)
890
+ if (option.node) {
743
891
  combine(predefined, node);
892
+ }
744
893
 
745
- if (option.devel)
894
+ if (option.devel) {
746
895
  combine(predefined, devel);
896
+ }
747
897
 
748
- if (option.browser)
898
+ if (option.dojo) {
899
+ combine(predefined, dojo);
900
+ }
901
+
902
+ if (option.browser) {
749
903
  combine(predefined, browser);
904
+ }
750
905
 
751
- if (option.jquery)
906
+ if (option.nonstandard) {
907
+ combine(predefined, nonstandard);
908
+ }
909
+
910
+ if (option.jquery) {
752
911
  combine(predefined, jquery);
912
+ }
753
913
 
754
- if (option.mootools)
914
+ if (option.mootools) {
755
915
  combine(predefined, mootools);
916
+ }
756
917
 
757
- if (option.globalstrict)
918
+ if (option.wsh) {
919
+ combine(predefined, wsh);
920
+ }
921
+
922
+ if (option.esnext) {
923
+ useESNextSyntax();
924
+ }
925
+
926
+ if (option.globalstrict && option.strict !== false) {
758
927
  option.strict = true;
928
+ }
759
929
  }
760
930
 
761
931
 
762
- // Produce an error warning.
932
+ // Produce an error warning.
933
+ function quit(message, line, chr) {
934
+ var percentage = Math.floor((line / lines.length) * 100);
763
935
 
764
- function quit(m, l, ch) {
765
936
  throw {
766
937
  name: 'JSHintError',
767
- line: l,
768
- character: ch,
769
- message: m + " (" + Math.floor((l / lines.length) * 100) +
770
- "% scanned)."
938
+ line: line,
939
+ character: chr,
940
+ message: message + " (" + percentage + "% scanned).",
941
+ raw: message
771
942
  };
772
943
  }
773
944
 
945
+ function isundef(scope, m, t, a) {
946
+ return JSHINT.undefs.push([scope, m, t, a]);
947
+ }
948
+
774
949
  function warning(m, t, a, b, c, d) {
775
950
  var ch, l, w;
776
951
  t = t || nexttoken;
@@ -811,7 +986,6 @@ var JSHINT = (function () {
811
986
 
812
987
  function error(m, t, a, b, c, d) {
813
988
  var w = warning(m, t, a, b, c, d);
814
- quit("Stopping, unable to continue.", w.line, w.character);
815
989
  }
816
990
 
817
991
  function errorAt(m, l, ch, a, b, c, d) {
@@ -840,7 +1014,13 @@ var JSHINT = (function () {
840
1014
  character = 1;
841
1015
  s = lines[line];
842
1016
  line += 1;
843
- at = s.search(/ \t/);
1017
+
1018
+ // If smarttabs option is used check for spaces followed by tabs only.
1019
+ // Otherwise check for any occurence of mixed tabs and spaces.
1020
+ if (option.smarttabs)
1021
+ at = s.search(/ \t/);
1022
+ else
1023
+ at = s.search(/ \t|\t /);
844
1024
 
845
1025
  if (at >= 0)
846
1026
  warningAt("Mixed spaces and tabs.", line, at + 1);
@@ -855,10 +1035,10 @@ var JSHINT = (function () {
855
1035
  warningAt("Line too long.", line, s.length);
856
1036
 
857
1037
  // Check for trailing whitespaces
858
- tw = s.search(/\s+$/);
859
- if (option.white && ~tw)
1038
+ tw = /\s+$/.test(s);
1039
+ if (option.trailing && tw && !/^\s+$/.test(s)) {
860
1040
  warningAt("Trailing whitespace.", line, tw);
861
-
1041
+ }
862
1042
  return true;
863
1043
  }
864
1044
 
@@ -876,20 +1056,24 @@ var JSHINT = (function () {
876
1056
  }
877
1057
  t = Object.create(t);
878
1058
  if (type === '(string)' || type === '(range)') {
879
- if (jx.test(value)) {
1059
+ if (!option.scripturl && jx.test(value)) {
880
1060
  warningAt("Script URL.", line, from);
881
1061
  }
882
1062
  }
883
1063
  if (type === '(identifier)') {
884
1064
  t.identifier = true;
885
- if (value === '__iterator__' || value === '__proto__') {
886
- errorAt("Reserved name '{a}'.",
1065
+ if (value === '__proto__' && !option.proto) {
1066
+ warningAt("The '{a}' property is deprecated.",
1067
+ line, from, value);
1068
+ } else if (value === '__iterator__' && !option.iterator) {
1069
+ warningAt("'{a}' is only available in JavaScript 1.7.",
887
1070
  line, from, value);
888
- } else if (option.nomen &&
889
- (value.charAt(0) === '_' ||
1071
+ } else if (option.nomen && (value.charAt(0) === '_' ||
890
1072
  value.charAt(value.length - 1) === '_')) {
891
- warningAt("Unexpected {a} in '{b}'.", line, from,
892
- "dangling '_'", value);
1073
+ if (!option.node || token.id === '.' ||
1074
+ (value !== '__dirname' && value !== '__filename')) {
1075
+ warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value);
1076
+ }
893
1077
  }
894
1078
  }
895
1079
  t.value = value;
@@ -900,13 +1084,13 @@ var JSHINT = (function () {
900
1084
  if (i !== '(endline)') {
901
1085
  prereg = i &&
902
1086
  (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) ||
903
- i === 'return');
1087
+ i === 'return' ||
1088
+ i === 'case');
904
1089
  }
905
1090
  return t;
906
1091
  }
907
1092
 
908
- // Public lex methods
909
-
1093
+ // Public lex methods
910
1094
  return {
911
1095
  init: function (source) {
912
1096
  if (typeof source === 'string') {
@@ -920,7 +1104,7 @@ var JSHINT = (function () {
920
1104
 
921
1105
  // If the first line is a shebang (#!), make it a blank and move on.
922
1106
  // Shebangs are used by Node scripts.
923
- if (lines[0] && lines[0].substr(0, 2) == '#!')
1107
+ if (lines[0] && lines[0].substr(0, 2) === '#!')
924
1108
  lines[0] = '';
925
1109
 
926
1110
  line = 0;
@@ -955,10 +1139,10 @@ var JSHINT = (function () {
955
1139
 
956
1140
  },
957
1141
 
958
- // token -- this is called by advance to get the next token.
959
1142
 
1143
+ // token -- this is called by advance to get the next token
960
1144
  token: function () {
961
- var b, c, captures, d, depth, high, i, l, low, q, t;
1145
+ var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange;
962
1146
 
963
1147
  function match(x) {
964
1148
  var r = x.exec(s), r1;
@@ -974,7 +1158,7 @@ var JSHINT = (function () {
974
1158
  }
975
1159
 
976
1160
  function string(x) {
977
- var c, j, r = '';
1161
+ var c, j, r = '', allowNewLine = false;
978
1162
 
979
1163
  if (jsonmode && x !== '"') {
980
1164
  warningAt("Strings must use doublequote.",
@@ -992,11 +1176,20 @@ var JSHINT = (function () {
992
1176
  c = String.fromCharCode(i);
993
1177
  }
994
1178
  j = 0;
995
- for (;;) {
1179
+ unclosedString: for (;;) {
996
1180
  while (j >= s.length) {
997
1181
  j = 0;
1182
+
1183
+ var cl = line, cf = from;
998
1184
  if (!nextLine()) {
999
- errorAt("Unclosed string.", line, from);
1185
+ errorAt("Unclosed string.", cl, cf);
1186
+ break unclosedString;
1187
+ }
1188
+
1189
+ if (allowNewLine) {
1190
+ allowNewLine = false;
1191
+ } else {
1192
+ warningAt("Unclosed string.", cl, cf);
1000
1193
  }
1001
1194
  }
1002
1195
  c = s.charAt(j);
@@ -1055,6 +1248,22 @@ var JSHINT = (function () {
1055
1248
  }
1056
1249
  esc(2);
1057
1250
  break;
1251
+ case '':
1252
+ // last character is escape character
1253
+ // always allow new line if escaped, but show
1254
+ // warning if option is not set
1255
+ allowNewLine = true;
1256
+ if (option.multistr) {
1257
+ if (jsonmode) {
1258
+ warningAt("Avoid EOL escapement.", line, character);
1259
+ }
1260
+ c = '';
1261
+ character -= 1;
1262
+ break;
1263
+ }
1264
+ warningAt("Bad escapement of EOL. Use option multistr if needed.",
1265
+ line, character);
1266
+ break;
1058
1267
  default:
1059
1268
  warningAt("Bad escapement.", line, character);
1060
1269
  }
@@ -1078,6 +1287,7 @@ var JSHINT = (function () {
1078
1287
  }
1079
1288
  if (s) {
1080
1289
  errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1));
1290
+ s = '';
1081
1291
  }
1082
1292
  } else {
1083
1293
 
@@ -1127,9 +1337,6 @@ var JSHINT = (function () {
1127
1337
  // // comment
1128
1338
 
1129
1339
  case '//':
1130
- if (src) {
1131
- warningAt("Unexpected comment.", line, character);
1132
- }
1133
1340
  s = '';
1134
1341
  token.comment = true;
1135
1342
  break;
@@ -1137,9 +1344,6 @@ var JSHINT = (function () {
1137
1344
  // /* comment
1138
1345
 
1139
1346
  case '/*':
1140
- if (src) {
1141
- warningAt("Unexpected comment.", line, character);
1142
- }
1143
1347
  for (;;) {
1144
1348
  i = s.search(lx);
1145
1349
  if (i >= 0) {
@@ -1178,8 +1382,8 @@ var JSHINT = (function () {
1178
1382
  // /
1179
1383
  case '/':
1180
1384
  if (token.id === '/=') {
1181
- errorAt(
1182
- "A regular expression literal can be confused with '/='.", line, from);
1385
+ errorAt("A regular expression literal can be confused with '/='.",
1386
+ line, from);
1183
1387
  }
1184
1388
  if (prereg) {
1185
1389
  depth = 0;
@@ -1191,13 +1395,12 @@ var JSHINT = (function () {
1191
1395
  l += 1;
1192
1396
  switch (c) {
1193
1397
  case '':
1194
- errorAt("Unclosed regular expression.",
1195
- line, from);
1196
- return;
1398
+ errorAt("Unclosed regular expression.", line, from);
1399
+ return quit('Stopping.', line, from);
1197
1400
  case '/':
1198
1401
  if (depth > 0) {
1199
- warningAt("Unescaped '{a}'.",
1200
- line, from + l, '/');
1402
+ warningAt("{a} unterminated regular expression " +
1403
+ "group(s).", line, from + l, depth);
1201
1404
  }
1202
1405
  c = s.substr(0, l - 1);
1203
1406
  q = {
@@ -1281,12 +1484,12 @@ var JSHINT = (function () {
1281
1484
  line, from + l, '^');
1282
1485
  }
1283
1486
  }
1284
- q = false;
1285
1487
  if (c === ']') {
1286
1488
  warningAt("Empty class.", line,
1287
1489
  from + l - 1);
1288
- q = true;
1289
1490
  }
1491
+ isLiteral = false;
1492
+ isInRange = false;
1290
1493
  klass: do {
1291
1494
  c = s.charAt(l);
1292
1495
  l += 1;
@@ -1295,19 +1498,31 @@ klass: do {
1295
1498
  case '^':
1296
1499
  warningAt("Unescaped '{a}'.",
1297
1500
  line, from + l, c);
1298
- q = true;
1501
+ if (isInRange) {
1502
+ isInRange = false;
1503
+ } else {
1504
+ isLiteral = true;
1505
+ }
1299
1506
  break;
1300
1507
  case '-':
1301
- if (q) {
1302
- q = false;
1508
+ if (isLiteral && !isInRange) {
1509
+ isLiteral = false;
1510
+ isInRange = true;
1511
+ } else if (isInRange) {
1512
+ isInRange = false;
1513
+ } else if (s.charAt(l) === ']') {
1514
+ isInRange = true;
1303
1515
  } else {
1304
- warningAt("Unescaped '{a}'.",
1305
- line, from + l, '-');
1306
- q = true;
1516
+ if (option.regexdash !== (l === 2 || (l === 3 &&
1517
+ s.charAt(1) === '^'))) {
1518
+ warningAt("Unescaped '{a}'.",
1519
+ line, from + l - 1, '-');
1520
+ }
1521
+ isLiteral = true;
1307
1522
  }
1308
1523
  break;
1309
1524
  case ']':
1310
- if (!q) {
1525
+ if (isInRange && !option.regexdash) {
1311
1526
  warningAt("Unescaped '{a}'.",
1312
1527
  line, from + l - 1, '-');
1313
1528
  }
@@ -1322,18 +1537,44 @@ klass: do {
1322
1537
  "Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
1323
1538
  }
1324
1539
  l += 1;
1325
- q = true;
1540
+
1541
+ // \w, \s and \d are never part of a character range
1542
+ if (/[wsd]/i.test(c)) {
1543
+ if (isInRange) {
1544
+ warningAt("Unescaped '{a}'.",
1545
+ line, from + l, '-');
1546
+ isInRange = false;
1547
+ }
1548
+ isLiteral = false;
1549
+ } else if (isInRange) {
1550
+ isInRange = false;
1551
+ } else {
1552
+ isLiteral = true;
1553
+ }
1326
1554
  break;
1327
1555
  case '/':
1328
1556
  warningAt("Unescaped '{a}'.",
1329
1557
  line, from + l - 1, '/');
1330
- q = true;
1558
+
1559
+ if (isInRange) {
1560
+ isInRange = false;
1561
+ } else {
1562
+ isLiteral = true;
1563
+ }
1331
1564
  break;
1332
1565
  case '<':
1333
- q = true;
1566
+ if (isInRange) {
1567
+ isInRange = false;
1568
+ } else {
1569
+ isLiteral = true;
1570
+ }
1334
1571
  break;
1335
1572
  default:
1336
- q = true;
1573
+ if (isInRange) {
1574
+ isInRange = false;
1575
+ } else {
1576
+ isLiteral = true;
1577
+ }
1337
1578
  }
1338
1579
  } while (c);
1339
1580
  break;
@@ -1441,13 +1682,12 @@ klass: do {
1441
1682
  }
1442
1683
 
1443
1684
  // Define t in the current function in the current scope.
1444
-
1445
1685
  if (is_own(funct, t) && !funct['(global)']) {
1446
1686
  if (funct[t] === true) {
1447
1687
  if (option.latedef)
1448
1688
  warning("'{a}' was used before it was defined.", nexttoken, t);
1449
1689
  } else {
1450
- if (!option.shadow)
1690
+ if (!option.shadow && type !== "exception")
1451
1691
  warning("'{a}' is already defined.", nexttoken, t);
1452
1692
  }
1453
1693
  }
@@ -1538,6 +1778,15 @@ loop: for (;;) {
1538
1778
  v, v.value);
1539
1779
  }
1540
1780
  obj.maxlen = b;
1781
+ } else if (t.value === 'validthis') {
1782
+ if (funct['(global)']) {
1783
+ error("Option 'validthis' can't be used in a global scope.");
1784
+ } else {
1785
+ if (v.value === 'true' || v.value === 'false')
1786
+ obj[t.value] = v.value === 'true';
1787
+ else
1788
+ error("Bad option value.", v);
1789
+ }
1541
1790
  } else if (v.value === 'true') {
1542
1791
  obj[t.value] = true;
1543
1792
  } else if (v.value === 'false') {
@@ -1601,6 +1850,7 @@ loop: for (;;) {
1601
1850
  }
1602
1851
  break;
1603
1852
  }
1853
+
1604
1854
  if (token.type === '(string)' || token.identifier) {
1605
1855
  anonname = token.value;
1606
1856
  }
@@ -1619,6 +1869,7 @@ loop: for (;;) {
1619
1869
  nexttoken, id, nexttoken.value);
1620
1870
  }
1621
1871
  }
1872
+
1622
1873
  prevtoken = token;
1623
1874
  token = nexttoken;
1624
1875
  for (;;) {
@@ -1679,9 +1930,9 @@ loop: for (;;) {
1679
1930
  }
1680
1931
  }
1681
1932
  while (rbp < nexttoken.lbp) {
1682
- isArray = token.value == 'Array';
1933
+ isArray = token.value === 'Array';
1683
1934
  advance();
1684
- if (isArray && token.id == '(' && nexttoken.id == ')')
1935
+ if (isArray && token.id === '(' && nexttoken.id === ')')
1685
1936
  warning("Use the array literal notation [].", token);
1686
1937
  if (token.led) {
1687
1938
  left = token.led(left);
@@ -1702,7 +1953,8 @@ loop: for (;;) {
1702
1953
  right = right || nexttoken;
1703
1954
  if (option.white) {
1704
1955
  if (left.character !== right.from && left.line === right.line) {
1705
- warning("Unexpected space after '{a}'.", right, left.value);
1956
+ left.from += (left.character - left.from);
1957
+ warning("Unexpected space after '{a}'.", left, left.value);
1706
1958
  }
1707
1959
  }
1708
1960
  }
@@ -1730,8 +1982,9 @@ loop: for (;;) {
1730
1982
  left = left || token;
1731
1983
  right = right || nexttoken;
1732
1984
  if (left.line === right.line && left.character === right.from) {
1985
+ left.from += (left.character - left.from);
1733
1986
  warning("Missing space after '{a}'.",
1734
- nexttoken, left.value);
1987
+ left, left.value);
1735
1988
  }
1736
1989
  }
1737
1990
  }
@@ -1745,8 +1998,9 @@ loop: for (;;) {
1745
1998
  left = left || token;
1746
1999
  right = right || nexttoken;
1747
2000
  if (left.character === right.from) {
2001
+ left.from += (left.character - left.from);
1748
2002
  warning("Missing space after '{a}'.",
1749
- nexttoken, left.value);
2003
+ left, left.value);
1750
2004
  }
1751
2005
  }
1752
2006
  }
@@ -1773,16 +2027,23 @@ loop: for (;;) {
1773
2027
 
1774
2028
  function comma() {
1775
2029
  if (token.line !== nexttoken.line) {
1776
- if (!option.laxbreak) {
2030
+ if (!option.laxcomma) {
2031
+ if (comma.first) {
2032
+ warning("Comma warnings can be turned off with 'laxcomma'");
2033
+ comma.first = false;
2034
+ }
1777
2035
  warning("Bad line breaking before '{a}'.", token, nexttoken.id);
1778
2036
  }
1779
- } else if (token.character !== nexttoken.from && option.white) {
1780
- warning("Unexpected space after '{a}'.", nexttoken, token.value);
2037
+ } else if (!token.comment && token.character !== nexttoken.from && option.white) {
2038
+ token.from += (token.character - token.from);
2039
+ warning("Unexpected space after '{a}'.", token, token.value);
1781
2040
  }
1782
2041
  advance(',');
1783
2042
  nonadjacent(token, nexttoken);
1784
2043
  }
1785
2044
 
2045
+ comma.first = true;
2046
+
1786
2047
 
1787
2048
  // Functional constructors for making the symbols that will be inherited by
1788
2049
  // tokens.
@@ -1882,6 +2143,9 @@ loop: for (;;) {
1882
2143
  nobreaknonadjacent(prevtoken, token);
1883
2144
  nonadjacent(token, nexttoken);
1884
2145
  }
2146
+ if (s === "in" && left.id === "!") {
2147
+ warning("Confusing use of '{a}'.", left, '!');
2148
+ }
1885
2149
  if (typeof f === 'function') {
1886
2150
  return f(left, this);
1887
2151
  } else {
@@ -1909,7 +2173,7 @@ loop: for (;;) {
1909
2173
  warning("Confusing use of '{a}'.", left, '!');
1910
2174
  }
1911
2175
  if (right.id === '!') {
1912
- warning("Confusing use of '{a}'.", left, '!');
2176
+ warning("Confusing use of '{a}'.", right, '!');
1913
2177
  }
1914
2178
  this.left = left;
1915
2179
  this.right = right;
@@ -1942,6 +2206,9 @@ loop: for (;;) {
1942
2206
  warning("'{a}' is a function.", left, left.value);
1943
2207
  }
1944
2208
  if (left) {
2209
+ if (option.esnext && funct[left.value] === 'const') {
2210
+ warning("Attempting to override '{a}' which is a constant", left, left.value);
2211
+ }
1945
2212
  if (left.id === '.' || left.id === '[') {
1946
2213
  if (!left.left || left.left.value === 'arguments') {
1947
2214
  warning('Bad assignment.', that);
@@ -2032,7 +2299,7 @@ loop: for (;;) {
2032
2299
  // `undefined` as a function param is a common pattern to protect
2033
2300
  // against the case when somebody does `undefined = true` and
2034
2301
  // help with minification. More info: https://gist.github.com/315916
2035
- if (!fnparam || token.value != 'undefined') {
2302
+ if (!fnparam || token.value !== 'undefined') {
2036
2303
  warning("Expected an identifier and instead saw '{a}' (a reserved word).",
2037
2304
  token, token.id);
2038
2305
  }
@@ -2069,6 +2336,9 @@ loop: for (;;) {
2069
2336
  }
2070
2337
  if (t.id !== '(endline)') {
2071
2338
  if (t.id === 'function') {
2339
+ if (!option.latedef) {
2340
+ break;
2341
+ }
2072
2342
  warning(
2073
2343
  "Inner functions should be listed at the top of the outer function.", t);
2074
2344
  break;
@@ -2084,11 +2354,8 @@ loop: for (;;) {
2084
2354
  function statement(noindent) {
2085
2355
  var i = indent, r, s = scope, t = nexttoken;
2086
2356
 
2087
- // We don't like the empty statement.
2088
-
2089
- if (t.id === ';') {
2090
- warning("Unnecessary semicolon.", t);
2091
- advance(';');
2357
+ if (t.id === ";") {
2358
+ advance(";");
2092
2359
  return;
2093
2360
  }
2094
2361
 
@@ -2118,17 +2385,24 @@ loop: for (;;) {
2118
2385
  }
2119
2386
  r = expression(0, true);
2120
2387
 
2121
- // Look for the final semicolon.
2122
-
2388
+ // Look for the final semicolon.
2123
2389
  if (!t.block) {
2124
2390
  if (!option.expr && (!r || !r.exps)) {
2125
- warning("Expected an assignment or function call and instead saw an expression.", token);
2391
+ warning("Expected an assignment or function call and instead saw an expression.",
2392
+ token);
2126
2393
  } else if (option.nonew && r.id === '(' && r.left.id === 'new') {
2127
2394
  warning("Do not use 'new' for side effects.");
2128
2395
  }
2396
+
2129
2397
  if (nexttoken.id !== ';') {
2130
2398
  if (!option.asi) {
2131
- warningAt("Missing semicolon.", token.line, token.from + token.value.length);
2399
+ // If this is the last statement in a block that ends on
2400
+ // the same line *and* option lastsemic is on, ignore the warning.
2401
+ // Otherwise, complain about missing semicolon.
2402
+ if (!option.lastsemic || nexttoken.id !== '}' ||
2403
+ nexttoken.line !== token.line) {
2404
+ warningAt("Missing semicolon.", token.line, token.character);
2405
+ }
2132
2406
  }
2133
2407
  } else {
2134
2408
  adjacent(token, nexttoken);
@@ -2145,72 +2419,142 @@ loop: for (;;) {
2145
2419
  }
2146
2420
 
2147
2421
 
2148
- function use_strict() {
2149
- if (nexttoken.value === 'use strict') {
2150
- if (strict_mode) {
2151
- warning("Unnecessary \"use strict\".");
2152
- }
2153
- advance();
2154
- advance(';');
2155
- strict_mode = true;
2156
- option.newcap = true;
2157
- option.undef = true;
2158
- return true;
2159
- } else {
2160
- return false;
2161
- }
2162
- }
2163
-
2164
-
2165
- function statements(begin) {
2422
+ function statements(startLine) {
2166
2423
  var a = [], f, p;
2167
2424
 
2168
2425
  while (!nexttoken.reach && nexttoken.id !== '(end)') {
2169
2426
  if (nexttoken.id === ';') {
2170
- warning("Unnecessary semicolon.");
2427
+ p = peek();
2428
+ if (!p || p.id !== "(") {
2429
+ warning("Unnecessary semicolon.");
2430
+ }
2171
2431
  advance(';');
2172
2432
  } else {
2173
- a.push(statement());
2433
+ a.push(statement(startLine === nexttoken.line));
2174
2434
  }
2175
2435
  }
2176
2436
  return a;
2177
2437
  }
2178
2438
 
2179
2439
 
2440
+ /*
2441
+ * read all directives
2442
+ * recognizes a simple form of asi, but always
2443
+ * warns, if it is used
2444
+ */
2445
+ function directives() {
2446
+ var i, p, pn;
2447
+
2448
+ for (;;) {
2449
+ if (nexttoken.id === "(string)") {
2450
+ p = peek(0);
2451
+ if (p.id === "(endline)") {
2452
+ i = 1;
2453
+ do {
2454
+ pn = peek(i);
2455
+ i = i + 1;
2456
+ } while (pn.id === "(endline)");
2457
+
2458
+ if (pn.id !== ";") {
2459
+ if (pn.id !== "(string)" && pn.id !== "(number)" &&
2460
+ pn.id !== "(regexp)" && pn.identifier !== true &&
2461
+ pn.id !== "}") {
2462
+ break;
2463
+ }
2464
+ warning("Missing semicolon.", nexttoken);
2465
+ } else {
2466
+ p = pn;
2467
+ }
2468
+ } else if (p.id === "}") {
2469
+ // directive with no other statements, warn about missing semicolon
2470
+ warning("Missing semicolon.", p);
2471
+ } else if (p.id !== ";") {
2472
+ break;
2473
+ }
2474
+
2475
+ indentation();
2476
+ advance();
2477
+ if (directive[token.value]) {
2478
+ warning("Unnecessary directive \"{a}\".", token, token.value);
2479
+ }
2480
+
2481
+ if (token.value === "use strict") {
2482
+ option.newcap = true;
2483
+ option.undef = true;
2484
+ }
2485
+
2486
+ // there's no directive negation, so always set to true
2487
+ directive[token.value] = true;
2488
+
2489
+ if (p.id === ";") {
2490
+ advance(";");
2491
+ }
2492
+ continue;
2493
+ }
2494
+ break;
2495
+ }
2496
+ }
2497
+
2498
+
2180
2499
  /*
2181
2500
  * Parses a single block. A block is a sequence of statements wrapped in
2182
2501
  * braces.
2183
2502
  *
2184
2503
  * ordinary - true for everything but function bodies and try blocks.
2185
2504
  * stmt - true if block can be a single statement (e.g. in if/for/while).
2505
+ * isfunc - true if block is a function body
2186
2506
  */
2187
- function block(ordinary, stmt) {
2507
+ function block(ordinary, stmt, isfunc) {
2188
2508
  var a,
2189
2509
  b = inblock,
2190
2510
  old_indent = indent,
2191
- m = strict_mode,
2511
+ m,
2192
2512
  s = scope,
2193
- t;
2513
+ t,
2514
+ line,
2515
+ d;
2194
2516
 
2195
2517
  inblock = ordinary;
2196
- scope = Object.create(scope);
2518
+ if (!ordinary || !option.funcscope) scope = Object.create(scope);
2197
2519
  nonadjacent(token, nexttoken);
2198
2520
  t = nexttoken;
2199
2521
 
2200
2522
  if (nexttoken.id === '{') {
2201
2523
  advance('{');
2202
- if (nexttoken.id !== '}' || token.line !== nexttoken.line) {
2524
+ line = token.line;
2525
+ if (nexttoken.id !== '}') {
2203
2526
  indent += option.indent;
2204
2527
  while (!ordinary && nexttoken.from > indent) {
2205
2528
  indent += option.indent;
2206
2529
  }
2207
- if (!ordinary && !use_strict() && !m && option.strict &&
2208
- funct['(context)']['(global)']) {
2209
- warning("Missing \"use strict\" statement.");
2530
+
2531
+ if (isfunc) {
2532
+ m = {};
2533
+ for (d in directive) {
2534
+ if (is_own(directive, d)) {
2535
+ m[d] = directive[d];
2536
+ }
2537
+ }
2538
+ directives();
2539
+
2540
+ if (option.strict && funct['(context)']['(global)']) {
2541
+ if (!m["use strict"] && !directive["use strict"]) {
2542
+ warning("Missing \"use strict\" statement.");
2543
+ }
2544
+ }
2545
+ }
2546
+
2547
+ a = statements(line);
2548
+
2549
+ if (isfunc) {
2550
+ directive = m;
2210
2551
  }
2211
- a = statements();
2212
- strict_mode = m;
2552
+
2213
2553
  indent -= option.indent;
2554
+ if (line !== nexttoken.line) {
2555
+ indentation();
2556
+ }
2557
+ } else if (line !== nexttoken.line) {
2214
2558
  indentation();
2215
2559
  }
2216
2560
  advance('}', t);
@@ -2224,11 +2568,14 @@ loop: for (;;) {
2224
2568
  nexttoken, '{', nexttoken.value);
2225
2569
 
2226
2570
  noreach = true;
2227
- a = [statement()];
2571
+ indent += option.indent;
2572
+ // test indentation only if statement is in new line
2573
+ a = [statement(nexttoken.line === token.line)];
2574
+ indent -= option.indent;
2228
2575
  noreach = false;
2229
2576
  }
2230
2577
  funct['(verb)'] = null;
2231
- scope = s;
2578
+ if (!ordinary || !option.funcscope) scope = s;
2232
2579
  inblock = b;
2233
2580
  if (ordinary && option.noempty && (!a || a.length === 0)) {
2234
2581
  warning("Empty block.");
@@ -2254,6 +2601,7 @@ loop: for (;;) {
2254
2601
  if (typeof a === 'function') {
2255
2602
  a = false;
2256
2603
  }
2604
+
2257
2605
  if (!a) {
2258
2606
  a = [line];
2259
2607
  implied[name] = a;
@@ -2262,11 +2610,13 @@ loop: for (;;) {
2262
2610
  }
2263
2611
  }
2264
2612
 
2265
- // Build the syntax table by declaring the syntactic elements of the language.
2613
+
2614
+ // Build the syntax table by declaring the syntactic elements of the language.
2266
2615
 
2267
2616
  type('(number)', function () {
2268
2617
  return this;
2269
2618
  });
2619
+
2270
2620
  type('(string)', function () {
2271
2621
  return this;
2272
2622
  });
@@ -2279,10 +2629,9 @@ loop: for (;;) {
2279
2629
  var v = this.value,
2280
2630
  s = scope[v],
2281
2631
  f;
2282
- if (typeof s === 'function') {
2283
-
2284
- // Protection against accidental inheritance.
2285
2632
 
2633
+ if (typeof s === 'function') {
2634
+ // Protection against accidental inheritance.
2286
2635
  s = undefined;
2287
2636
  } else if (typeof s === 'boolean') {
2288
2637
  f = funct;
@@ -2292,12 +2641,9 @@ loop: for (;;) {
2292
2641
  funct = f;
2293
2642
  }
2294
2643
 
2295
- // The name is in scope and defined in the current function.
2296
-
2644
+ // The name is in scope and defined in the current function.
2297
2645
  if (funct === s) {
2298
-
2299
- // Change 'unused' to 'var', and reject labels.
2300
-
2646
+ // Change 'unused' to 'var', and reject labels.
2301
2647
  switch (funct[v]) {
2302
2648
  case 'unused':
2303
2649
  funct[v] = 'var';
@@ -2313,25 +2659,28 @@ loop: for (;;) {
2313
2659
  warning("'{a}' is a statement label.", token, v);
2314
2660
  break;
2315
2661
  }
2316
-
2317
- // The name is not defined in the function. If we are in the global scope,
2318
- // then we have an undefined variable.
2319
- //
2320
- // Operators typeof and delete do not raise runtime errors even if the base
2321
- // object of a reference is null so no need to display warning if we're
2322
- // inside of typeof or delete.
2323
-
2324
2662
  } else if (funct['(global)']) {
2325
- if (anonname != 'typeof' && anonname != 'delete' &&
2326
- option.undef && typeof predefined[v] !== 'boolean') {
2327
- warning("'{a}' is not defined.", token, v);
2663
+ // The name is not defined in the function. If we are in the global
2664
+ // scope, then we have an undefined variable.
2665
+ //
2666
+ // Operators typeof and delete do not raise runtime errors even if
2667
+ // the base object of a reference is null so no need to display warning
2668
+ // if we're inside of typeof or delete.
2669
+
2670
+ if (option.undef && typeof predefined[v] !== 'boolean') {
2671
+ // Attempting to subscript a null reference will throw an
2672
+ // error, even within the typeof and delete operators
2673
+ if (!(anonname === 'typeof' || anonname === 'delete') ||
2674
+ (nexttoken && (nexttoken.value === '.' || nexttoken.value === '['))) {
2675
+
2676
+ isundef(funct, "'{a}' is not defined.", token, v);
2677
+ }
2328
2678
  }
2329
2679
  note_implied(token);
2330
-
2331
- // If the name is already defined in the current
2332
- // function, but not as outer, then there is a scope error.
2333
-
2334
2680
  } else {
2681
+ // If the name is already defined in the current
2682
+ // function, but not as outer, then there is a scope error.
2683
+
2335
2684
  switch (funct[v]) {
2336
2685
  case 'closure':
2337
2686
  case 'function':
@@ -2346,25 +2695,28 @@ loop: for (;;) {
2346
2695
  case 'global':
2347
2696
  break;
2348
2697
  default:
2349
-
2350
- // If the name is defined in an outer function, make an outer entry, and if
2351
- // it was unused, make it var.
2352
-
2698
+ // If the name is defined in an outer function, make an outer entry,
2699
+ // and if it was unused, make it var.
2353
2700
  if (s === true) {
2354
2701
  funct[v] = true;
2355
2702
  } else if (s === null) {
2356
2703
  warning("'{a}' is not allowed.", token, v);
2357
2704
  note_implied(token);
2358
2705
  } else if (typeof s !== 'object') {
2359
-
2360
- // Operators typeof and delete do not raise runtime errors even if the base object of
2361
- // a reference is null so no need to display warning if we're inside of typeof or delete.
2362
-
2363
- if (anonname != 'typeof' && anonname != 'delete' && option.undef) {
2364
- warning("'{a}' is not defined.", token, v);
2365
- } else {
2366
- funct[v] = true;
2706
+ // Operators typeof and delete do not raise runtime errors even
2707
+ // if the base object of a reference is null so no need to
2708
+ // display warning if we're inside of typeof or delete.
2709
+ if (option.undef) {
2710
+ // Attempting to subscript a null reference will throw an
2711
+ // error, even within the typeof and delete operators
2712
+ if (!(anonname === 'typeof' || anonname === 'delete') ||
2713
+ (nexttoken &&
2714
+ (nexttoken.value === '.' || nexttoken.value === '['))) {
2715
+
2716
+ isundef(funct, "'{a}' is not defined.", token, v);
2717
+ }
2367
2718
  }
2719
+ funct[v] = true;
2368
2720
  note_implied(token);
2369
2721
  } else {
2370
2722
  switch (s[v]) {
@@ -2428,7 +2780,7 @@ loop: for (;;) {
2428
2780
  reserve('default').reach = true;
2429
2781
  reserve('finally');
2430
2782
  reservevar('arguments', function (x) {
2431
- if (strict_mode && funct['(global)']) {
2783
+ if (directive['use strict'] && funct['(global)']) {
2432
2784
  warning("Strict violation.", x);
2433
2785
  }
2434
2786
  });
@@ -2438,9 +2790,9 @@ loop: for (;;) {
2438
2790
  reservevar('NaN');
2439
2791
  reservevar('null');
2440
2792
  reservevar('this', function (x) {
2441
- if (strict_mode && ((funct['(statement)'] &&
2793
+ if (directive['use strict'] && !option.validthis && ((funct['(statement)'] &&
2442
2794
  funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {
2443
- warning("Strict violation.", x);
2795
+ warning("Possible strict violation.", x);
2444
2796
  }
2445
2797
  });
2446
2798
  reservevar('true');
@@ -2473,24 +2825,23 @@ loop: for (;;) {
2473
2825
  bitwise('^', 'bitxor', 80);
2474
2826
  bitwise('&', 'bitand', 90);
2475
2827
  relation('==', function (left, right) {
2476
- var eqnull = option.eqnull &&
2477
- (left.value == 'null' || right.value == 'null');
2828
+ var eqnull = option.eqnull && (left.value === 'null' || right.value === 'null');
2829
+
2830
+ if (!eqnull && option.eqeqeq)
2831
+ warning("Expected '{a}' and instead saw '{b}'.", this, '===', '==');
2832
+ else if (isPoorRelation(left))
2833
+ warning("Use '{a}' to compare with '{b}'.", this, '===', left.value);
2834
+ else if (isPoorRelation(right))
2835
+ warning("Use '{a}' to compare with '{b}'.", this, '===', right.value);
2478
2836
 
2479
- if (!eqnull && option.eqeqeq) {
2480
- warning("Expected '{a}' and instead saw '{b}'.",
2481
- this, '===', '==');
2482
- } else if (isPoorRelation(left)) {
2483
- warning("Use '{a}' to compare with '{b}'.",
2484
- this, '===', left.value);
2485
- } else if (isPoorRelation(right)) {
2486
- warning("Use '{a}' to compare with '{b}'.",
2487
- this, '===', right.value);
2488
- }
2489
2837
  return this;
2490
2838
  });
2491
2839
  relation('===');
2492
2840
  relation('!=', function (left, right) {
2493
- if (option.eqeqeq) {
2841
+ var eqnull = option.eqnull &&
2842
+ (left.value === 'null' || right.value === 'null');
2843
+
2844
+ if (!eqnull && option.eqeqeq) {
2494
2845
  warning("Expected '{a}' and instead saw '{b}'.",
2495
2846
  this, '!==', '!=');
2496
2847
  } else if (isPoorRelation(left)) {
@@ -2517,7 +2868,7 @@ loop: for (;;) {
2517
2868
  if (left && right && left.id === '(string)' && right.id === '(string)') {
2518
2869
  left.value += right.value;
2519
2870
  left.character = right.character;
2520
- if (jx.test(left.value)) {
2871
+ if (!option.scripturl && jx.test(left.value)) {
2521
2872
  warning("JavaScript URL.", left);
2522
2873
  }
2523
2874
  return left;
@@ -2618,7 +2969,8 @@ loop: for (;;) {
2618
2969
  if (c.id !== 'function') {
2619
2970
  i = c.value.substr(0, 1);
2620
2971
  if (option.newcap && (i < 'A' || i > 'Z')) {
2621
- warning("A constructor name should start with an uppercase letter.", token);
2972
+ warning("A constructor name should start with an uppercase letter.",
2973
+ token);
2622
2974
  }
2623
2975
  }
2624
2976
  }
@@ -2651,9 +3003,11 @@ loop: for (;;) {
2651
3003
  }
2652
3004
  that.left = left;
2653
3005
  that.right = m;
2654
- if (option.noarg && left && left.value === 'arguments' &&
2655
- (m === 'callee' || m === 'caller')) {
2656
- warning("Avoid arguments.{a}.", left, m);
3006
+ if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) {
3007
+ if (option.noarg)
3008
+ warning("Avoid arguments.{a}.", left, m);
3009
+ else if (directive['use strict'])
3010
+ error('Strict violation.');
2657
3011
  } else if (!option.evil && left && left.value === 'document' &&
2658
3012
  (m === 'write' || m === 'writeln')) {
2659
3013
  warning("document.write can be a form of eval.", left);
@@ -2738,7 +3092,8 @@ loop: for (;;) {
2738
3092
  advance(')', this);
2739
3093
  nospace(prevtoken, token);
2740
3094
  if (option.immed && v.id === 'function') {
2741
- if (nexttoken.id === '(') {
3095
+ if (nexttoken.id === '(' ||
3096
+ (nexttoken.id === '.' && (peek().value === 'call' || peek().value === 'apply'))) {
2742
3097
  warning(
2743
3098
  "Move the invocation into the parens that contain the function.", nexttoken);
2744
3099
  } else {
@@ -2835,7 +3190,6 @@ loop: for (;;) {
2835
3190
  nospace();
2836
3191
  if (nexttoken.id === ')') {
2837
3192
  advance(')');
2838
- nospace(prevtoken, token);
2839
3193
  return;
2840
3194
  }
2841
3195
  for (;;) {
@@ -2878,7 +3232,7 @@ loop: for (;;) {
2878
3232
  }
2879
3233
  funct['(params)'] = functionparams();
2880
3234
 
2881
- block(false);
3235
+ block(false, false, true);
2882
3236
  scope = oldScope;
2883
3237
  option = oldOption;
2884
3238
  funct['(last)'] = token.line;
@@ -2889,7 +3243,42 @@ loop: for (;;) {
2889
3243
 
2890
3244
  (function (x) {
2891
3245
  x.nud = function () {
2892
- var b, f, i, j, p, seen = {}, t;
3246
+ var b, f, i, j, p, t;
3247
+ var props = {}; // All properties, including accessors
3248
+
3249
+ function saveProperty(name, token) {
3250
+ if (props[name] && is_own(props, name))
3251
+ warning("Duplicate member '{a}'.", nexttoken, i);
3252
+ else
3253
+ props[name] = {};
3254
+
3255
+ props[name].basic = true;
3256
+ props[name].basicToken = token;
3257
+ }
3258
+
3259
+ function saveSetter(name, token) {
3260
+ if (props[name] && is_own(props, name)) {
3261
+ if (props[name].basic || props[name].setter)
3262
+ warning("Duplicate member '{a}'.", nexttoken, i);
3263
+ } else {
3264
+ props[name] = {};
3265
+ }
3266
+
3267
+ props[name].setter = true;
3268
+ props[name].setterToken = token;
3269
+ }
3270
+
3271
+ function saveGetter(name) {
3272
+ if (props[name] && is_own(props, name)) {
3273
+ if (props[name].basic || props[name].getter)
3274
+ warning("Duplicate member '{a}'.", nexttoken, i);
3275
+ } else {
3276
+ props[name] = {};
3277
+ }
3278
+
3279
+ props[name].getter = true;
3280
+ props[name].getterToken = token;
3281
+ }
2893
3282
 
2894
3283
  b = token.line !== nexttoken.line;
2895
3284
  if (b) {
@@ -2914,33 +3303,35 @@ loop: for (;;) {
2914
3303
  if (!i) {
2915
3304
  error("Missing property name.");
2916
3305
  }
3306
+ saveGetter(i);
2917
3307
  t = nexttoken;
2918
3308
  adjacent(token, nexttoken);
2919
3309
  f = doFunction();
2920
- if (!option.loopfunc && funct['(loopage)']) {
2921
- warning("Don't make functions within a loop.", t);
2922
- }
2923
3310
  p = f['(params)'];
2924
3311
  if (p) {
2925
3312
  warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i);
2926
3313
  }
2927
3314
  adjacent(token, nexttoken);
2928
- advance(',');
2929
- indentation();
3315
+ } else if (nexttoken.value === 'set' && peek().id !== ':') {
2930
3316
  advance('set');
2931
- j = property_name();
2932
- if (i !== j) {
2933
- error("Expected {a} and instead saw {b}.", token, i, j);
3317
+ if (!option.es5) {
3318
+ error("get/set are ES5 features.");
2934
3319
  }
3320
+ i = property_name();
3321
+ if (!i) {
3322
+ error("Missing property name.");
3323
+ }
3324
+ saveSetter(i, nexttoken);
2935
3325
  t = nexttoken;
2936
3326
  adjacent(token, nexttoken);
2937
3327
  f = doFunction();
2938
3328
  p = f['(params)'];
2939
- if (!p || p.length !== 1 || p[0] !== 'value') {
2940
- warning("Expected (value) in set {a} function.", t, i);
3329
+ if (!p || p.length !== 1) {
3330
+ warning("Expected a single parameter in set {a} function.", t, i);
2941
3331
  }
2942
3332
  } else {
2943
3333
  i = property_name();
3334
+ saveProperty(i, nexttoken);
2944
3335
  if (typeof i !== 'string') {
2945
3336
  break;
2946
3337
  }
@@ -2948,10 +3339,7 @@ loop: for (;;) {
2948
3339
  nonadjacent(token, nexttoken);
2949
3340
  expression(10);
2950
3341
  }
2951
- if (seen[i] === true) {
2952
- warning("Duplicate member '{a}'.", nexttoken, i);
2953
- }
2954
- seen[i] = true;
3342
+
2955
3343
  countMember(i);
2956
3344
  if (nexttoken.id === ',') {
2957
3345
  comma();
@@ -2969,6 +3357,15 @@ loop: for (;;) {
2969
3357
  indentation();
2970
3358
  }
2971
3359
  advance('}', this);
3360
+
3361
+ // Check for lonely setters if in the ES5 mode.
3362
+ if (option.es5) {
3363
+ for (var name in props) {
3364
+ if (is_own(props, name) && props[name].setter && !props[name].getter) {
3365
+ warning("Setter is defined without getter.", props[name].setterToken);
3366
+ }
3367
+ }
3368
+ }
2972
3369
  return this;
2973
3370
  };
2974
3371
  x.fud = function () {
@@ -2976,6 +3373,61 @@ loop: for (;;) {
2976
3373
  };
2977
3374
  }(delim('{')));
2978
3375
 
3376
+ // This Function is called when esnext option is set to true
3377
+ // it adds the `const` statement to JSHINT
3378
+
3379
+ useESNextSyntax = function () {
3380
+ var conststatement = stmt('const', function (prefix) {
3381
+ var id, name, value;
3382
+
3383
+ this.first = [];
3384
+ for (;;) {
3385
+ nonadjacent(token, nexttoken);
3386
+ id = identifier();
3387
+ if (funct[id] === "const") {
3388
+ warning("const '" + id + "' has already been declared");
3389
+ }
3390
+ if (funct['(global)'] && predefined[id] === false) {
3391
+ warning("Redefinition of '{a}'.", token, id);
3392
+ }
3393
+ addlabel(id, 'const');
3394
+ if (prefix) {
3395
+ break;
3396
+ }
3397
+ name = token;
3398
+ this.first.push(token);
3399
+
3400
+ if (nexttoken.id !== "=") {
3401
+ warning("const " +
3402
+ "'{a}' is initialized to 'undefined'.", token, id);
3403
+ }
3404
+
3405
+ if (nexttoken.id === '=') {
3406
+ nonadjacent(token, nexttoken);
3407
+ advance('=');
3408
+ nonadjacent(token, nexttoken);
3409
+ if (nexttoken.id === 'undefined') {
3410
+ warning("It is not necessary to initialize " +
3411
+ "'{a}' to 'undefined'.", token, id);
3412
+ }
3413
+ if (peek(0).id === '=' && nexttoken.identifier) {
3414
+ error("Constant {a} was not declared correctly.",
3415
+ nexttoken, nexttoken.value);
3416
+ }
3417
+ value = expression(0);
3418
+ name.first = value;
3419
+ }
3420
+
3421
+ if (nexttoken.id !== ',') {
3422
+ break;
3423
+ }
3424
+ comma();
3425
+ }
3426
+ return this;
3427
+ });
3428
+ conststatement.exps = true;
3429
+ };
3430
+
2979
3431
  var varstatement = stmt('var', function (prefix) {
2980
3432
  // JavaScript does not have block scope. It only has function scope. So,
2981
3433
  // declaring a variable in a block can have unexpected consequences.
@@ -2990,6 +3442,9 @@ loop: for (;;) {
2990
3442
  for (;;) {
2991
3443
  nonadjacent(token, nexttoken);
2992
3444
  id = identifier();
3445
+ if (option.esnext && funct[id] === "const") {
3446
+ warning("const '" + id + "' has already been declared");
3447
+ }
2993
3448
  if (funct['(global)'] && predefined[id] === false) {
2994
3449
  warning("Redefinition of '{a}'.", token, id);
2995
3450
  }
@@ -3024,11 +3479,15 @@ loop: for (;;) {
3024
3479
 
3025
3480
  blockstmt('function', function () {
3026
3481
  if (inblock) {
3027
- warning(
3028
- "Function declarations should not be placed in blocks. Use a function expression or move the statement to the top of the outer function.", token);
3482
+ warning("Function declarations should not be placed in blocks. " +
3483
+ "Use a function expression or move the statement to the top of " +
3484
+ "the outer function.", token);
3029
3485
 
3030
3486
  }
3031
3487
  var i = identifier();
3488
+ if (option.esnext && funct[i] === "const") {
3489
+ warning("const '" + i + "' has already been declared");
3490
+ }
3032
3491
  adjacent(token, nexttoken);
3033
3492
  addlabel(i, 'unction');
3034
3493
  doFunction(i, true);
@@ -3207,7 +3666,8 @@ loop: for (;;) {
3207
3666
  advance('}', t);
3208
3667
  if (this.cases.length === 1 || this.condition.id === 'true' ||
3209
3668
  this.condition.id === 'false') {
3210
- warning("This 'switch' should be an 'if'.", this);
3669
+ if (!option.onecase)
3670
+ warning("This 'switch' should be an 'if'.", this);
3211
3671
  }
3212
3672
  funct['(breakage)'] -= 1;
3213
3673
  funct['(verb)'] = undefined;
@@ -3222,14 +3682,23 @@ loop: for (;;) {
3222
3682
  error("Each value should have its own case label.");
3223
3683
  return;
3224
3684
  case ':':
3685
+ g = false;
3225
3686
  statements();
3226
3687
  break;
3227
3688
  default:
3228
3689
  error("Missing ':' on a case clause.", token);
3690
+ return;
3229
3691
  }
3230
3692
  } else {
3231
- error("Expected '{a}' and instead saw '{b}'.",
3232
- nexttoken, 'case', nexttoken.value);
3693
+ if (token.id === ':') {
3694
+ advance(':');
3695
+ error("Unexpected '{a}'.", token, ':');
3696
+ statements();
3697
+ } else {
3698
+ error("Expected '{a}' and instead saw '{b}'.",
3699
+ nexttoken, 'case', nexttoken.value);
3700
+ return;
3701
+ }
3233
3702
  }
3234
3703
  }
3235
3704
  }
@@ -3297,9 +3766,10 @@ loop: for (;;) {
3297
3766
  expression(20);
3298
3767
  advance(')', t);
3299
3768
  s = block(true, true);
3300
- if (option.forin && (s.length > 1 || typeof s[0] !== 'object' ||
3769
+ if (option.forin && s && (s.length > 1 || typeof s[0] !== 'object' ||
3301
3770
  s[0].value !== 'if')) {
3302
- warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.", this);
3771
+ warning("The body of a for in should be wrapped in an if statement to filter " +
3772
+ "unwanted properties from the prototype.", this);
3303
3773
  }
3304
3774
  funct['(breakage)'] -= 1;
3305
3775
  funct['(loopage)'] -= 1;
@@ -3357,10 +3827,13 @@ loop: for (;;) {
3357
3827
 
3358
3828
  stmt('break', function () {
3359
3829
  var v = nexttoken.value;
3360
- if (funct['(breakage)'] === 0) {
3830
+
3831
+ if (funct['(breakage)'] === 0)
3361
3832
  warning("Unexpected '{a}'.", nexttoken, this.value);
3362
- }
3363
- nolinebreak(this);
3833
+
3834
+ if (!option.asi)
3835
+ nolinebreak(this);
3836
+
3364
3837
  if (nexttoken.id !== ';') {
3365
3838
  if (token.line === nexttoken.line) {
3366
3839
  if (funct[v] !== 'label') {
@@ -3379,10 +3852,13 @@ loop: for (;;) {
3379
3852
 
3380
3853
  stmt('continue', function () {
3381
3854
  var v = nexttoken.value;
3382
- if (funct['(breakage)'] === 0) {
3855
+
3856
+ if (funct['(breakage)'] === 0)
3383
3857
  warning("Unexpected '{a}'.", nexttoken, this.value);
3384
- }
3385
- nolinebreak(this);
3858
+
3859
+ if (!option.asi)
3860
+ nolinebreak(this);
3861
+
3386
3862
  if (nexttoken.id !== ';') {
3387
3863
  if (token.line === nexttoken.line) {
3388
3864
  if (funct[v] !== 'label') {
@@ -3402,13 +3878,20 @@ loop: for (;;) {
3402
3878
 
3403
3879
 
3404
3880
  stmt('return', function () {
3405
- nolinebreak(this);
3406
- if (nexttoken.id === '(regexp)') {
3407
- warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");
3408
- }
3409
- if (nexttoken.id !== ';' && !nexttoken.reach) {
3410
- nonadjacent(token, nexttoken);
3411
- this.first = expression(20);
3881
+ if (this.line === nexttoken.line) {
3882
+ if (nexttoken.id === '(regexp)')
3883
+ warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");
3884
+
3885
+ if (nexttoken.id !== ';' && !nexttoken.reach) {
3886
+ nonadjacent(token, nexttoken);
3887
+ if (peek().value === "=" && !option.boss) {
3888
+ warningAt("Did you mean to return a conditional instead of an assignment?",
3889
+ token.line, token.character + 1);
3890
+ }
3891
+ this.first = expression(0);
3892
+ }
3893
+ } else if (!option.asi) {
3894
+ nolinebreak(this); // always warn (Line breaking error)
3412
3895
  }
3413
3896
  reachable('return');
3414
3897
  return this;
@@ -3468,9 +3951,11 @@ loop: for (;;) {
3468
3951
  if (o[nexttoken.value] === true) {
3469
3952
  warning("Duplicate key '{a}'.",
3470
3953
  nexttoken, nexttoken.value);
3471
- } else if (nexttoken.value === '__proto__') {
3472
- warning("Stupid key '{a}'.",
3473
- nexttoken, nexttoken.value);
3954
+ } else if ((nexttoken.value === '__proto__' &&
3955
+ !option.proto) || (nexttoken.value === '__iterator__' &&
3956
+ !option.iterator)) {
3957
+ warning("The '{a}' key may produce unexpected results.",
3958
+ nexttoken, nexttoken.value);
3474
3959
  } else {
3475
3960
  o[nexttoken.value] = true;
3476
3961
  }
@@ -3543,6 +4028,7 @@ loop: for (;;) {
3543
4028
  var itself = function (s, o, g) {
3544
4029
  var a, i, k;
3545
4030
  JSHINT.errors = [];
4031
+ JSHINT.undefs = [];
3546
4032
  predefined = Object.create(standard);
3547
4033
  combine(predefined, g || {});
3548
4034
  if (o) {
@@ -3555,7 +4041,7 @@ loop: for (;;) {
3555
4041
  } else if (typeof a === 'object') {
3556
4042
  k = Object.keys(a);
3557
4043
  for (i = 0; i < k.length; i += 1) {
3558
- predefined[k[i]] = !!a[k];
4044
+ predefined[k[i]] = !!a[k[i]];
3559
4045
  }
3560
4046
  }
3561
4047
  }
@@ -3582,7 +4068,6 @@ loop: for (;;) {
3582
4068
  };
3583
4069
  functions = [funct];
3584
4070
  urls = [];
3585
- src = false;
3586
4071
  stack = null;
3587
4072
  member = {};
3588
4073
  membersOnly = null;
@@ -3593,11 +4078,14 @@ loop: for (;;) {
3593
4078
  warnings = 0;
3594
4079
  lex.init(s);
3595
4080
  prereg = true;
3596
- strict_mode = false;
4081
+ directive = {};
3597
4082
 
3598
4083
  prevtoken = token = nexttoken = syntax['(begin)'];
3599
4084
  assume();
3600
4085
 
4086
+ // combine the passed globals after we've assumed all our options
4087
+ combine(predefined, g || {});
4088
+
3601
4089
  try {
3602
4090
  advance();
3603
4091
  switch (nexttoken.id) {
@@ -3608,32 +4096,83 @@ loop: for (;;) {
3608
4096
  jsonValue();
3609
4097
  break;
3610
4098
  default:
3611
- if (nexttoken.value === 'use strict') {
3612
- if (!option.globalstrict)
3613
- warning("Use the function form of \"use strict\".");
3614
- use_strict();
4099
+ directives();
4100
+ if (directive["use strict"] && !option.globalstrict) {
4101
+ warning("Use the function form of \"use strict\".", prevtoken);
3615
4102
  }
3616
- statements('lib');
4103
+
4104
+ statements();
3617
4105
  }
3618
4106
  advance('(end)');
4107
+
4108
+ var markDefined = function (name, context) {
4109
+ do {
4110
+ if (typeof context[name] === 'string') {
4111
+ // JSHINT marks unused variables as 'unused' and
4112
+ // unused function declaration as 'unction'. This
4113
+ // code changes such instances back 'var' and
4114
+ // 'closure' so that the code in JSHINT.data()
4115
+ // doesn't think they're unused.
4116
+
4117
+ if (context[name] === 'unused')
4118
+ context[name] = 'var';
4119
+ else if (context[name] === 'unction')
4120
+ context[name] = 'closure';
4121
+
4122
+ return true;
4123
+ }
4124
+
4125
+ context = context['(context)'];
4126
+ } while (context);
4127
+
4128
+ return false;
4129
+ };
4130
+
4131
+ var clearImplied = function (name, line) {
4132
+ if (!implied[name])
4133
+ return;
4134
+
4135
+ var newImplied = [];
4136
+ for (var i = 0; i < implied[name].length; i += 1) {
4137
+ if (implied[name][i] !== line)
4138
+ newImplied.push(implied[name][i]);
4139
+ }
4140
+
4141
+ if (newImplied.length === 0)
4142
+ delete implied[name];
4143
+ else
4144
+ implied[name] = newImplied;
4145
+ };
4146
+
4147
+ // Check queued 'x is not defined' instances to see if they're still undefined.
4148
+ for (i = 0; i < JSHINT.undefs.length; i += 1) {
4149
+ k = JSHINT.undefs[i].slice(0);
4150
+
4151
+ if (markDefined(k[2].value, k[0])) {
4152
+ clearImplied(k[2].value, k[2].line);
4153
+ } else {
4154
+ warning.apply(warning, k.slice(1));
4155
+ }
4156
+ }
3619
4157
  } catch (e) {
3620
4158
  if (e) {
4159
+ var nt = nexttoken || {};
3621
4160
  JSHINT.errors.push({
4161
+ raw : e.raw,
3622
4162
  reason : e.message,
3623
- line : e.line || nexttoken.line,
3624
- character : e.character || nexttoken.from
4163
+ line : e.line || nt.line,
4164
+ character : e.character || nt.from
3625
4165
  }, null);
3626
4166
  }
3627
4167
  }
3628
- return JSHINT.errors.length === 0;
3629
- };
3630
4168
 
4169
+ return JSHINT.errors;
4170
+ };
3631
4171
 
3632
- // Data summary.
3633
-
4172
+ // Data summary.
3634
4173
  itself.data = function () {
3635
4174
 
3636
- var data = {functions: []}, fu, globals, implieds = [], f, i, j,
4175
+ var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j,
3637
4176
  members = [], n, unused = [], v;
3638
4177
  if (itself.errors.length) {
3639
4178
  data.errors = itself.errors;
@@ -3663,7 +4202,6 @@ loop: for (;;) {
3663
4202
  if (globals.length > 0) {
3664
4203
  data.globals = globals;
3665
4204
  }
3666
-
3667
4205
  for (i = 1; i < functions.length; i += 1) {
3668
4206
  f = functions[i];
3669
4207
  fu = {};
@@ -3841,14 +4379,12 @@ loop: for (;;) {
3841
4379
  }
3842
4380
  return o.join('');
3843
4381
  };
3844
- itself.jshint = itself;
3845
4382
 
3846
- itself.edition = '2011-04-16';
4383
+ itself.jshint = itself;
3847
4384
 
3848
4385
  return itself;
3849
-
3850
4386
  }());
3851
4387
 
3852
4388
  // Make JSHINT a Node module, if possible.
3853
- if (typeof exports == 'object' && exports)
3854
- exports.JSHINT = JSHINT;
4389
+ if (typeof exports === 'object' && exports)
4390
+ exports.JSHINT = JSHINT;