pre-commit 0.1.17 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/pre-commit/checks/jshint_check.rb +1 -5
- data/lib/support/jshint/jshint.js +969 -433
- metadata +5 -5
|
@@ -24,11 +24,7 @@ class PreCommit
|
|
|
24
24
|
|
|
25
25
|
def run_check(file)
|
|
26
26
|
context = ExecJS.compile(File.read(linter_src))
|
|
27
|
-
|
|
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
|
-
|
|
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
|
-
"(
|
|
159
|
-
"(
|
|
160
|
-
"(
|
|
161
|
-
"
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
269
|
-
|
|
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
|
|
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
|
-
|
|
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;`
|
|
284
|
-
|
|
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
|
|
292
|
-
ArrayBufferView
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
|
377
|
-
confirm
|
|
378
|
-
console
|
|
379
|
-
Debug
|
|
380
|
-
opera
|
|
381
|
-
prompt
|
|
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
|
|
471
|
-
__dirname
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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
|
|
530
|
-
deserialize
|
|
531
|
-
gc
|
|
532
|
-
help
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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
|
-
|
|
719
|
+
directive,
|
|
601
720
|
syntax = {},
|
|
602
721
|
tab,
|
|
603
722
|
token,
|
|
604
723
|
urls,
|
|
724
|
+
useESNextSyntax,
|
|
605
725
|
warnings,
|
|
606
726
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
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*!|</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.
|
|
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.
|
|
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.
|
|
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:
|
|
768
|
-
character:
|
|
769
|
-
message:
|
|
770
|
-
|
|
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
|
-
|
|
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
|
|
859
|
-
if (option.
|
|
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 === '
|
|
886
|
-
|
|
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
|
-
|
|
892
|
-
|
|
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
|
-
|
|
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.",
|
|
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
|
-
|
|
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
|
-
|
|
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("
|
|
1200
|
-
|
|
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
|
-
|
|
1501
|
+
if (isInRange) {
|
|
1502
|
+
isInRange = false;
|
|
1503
|
+
} else {
|
|
1504
|
+
isLiteral = true;
|
|
1505
|
+
}
|
|
1299
1506
|
break;
|
|
1300
1507
|
case '-':
|
|
1301
|
-
if (
|
|
1302
|
-
|
|
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
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
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 (!
|
|
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
|
-
|
|
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
|
-
|
|
1558
|
+
|
|
1559
|
+
if (isInRange) {
|
|
1560
|
+
isInRange = false;
|
|
1561
|
+
} else {
|
|
1562
|
+
isLiteral = true;
|
|
1563
|
+
}
|
|
1331
1564
|
break;
|
|
1332
1565
|
case '<':
|
|
1333
|
-
|
|
1566
|
+
if (isInRange) {
|
|
1567
|
+
isInRange = false;
|
|
1568
|
+
} else {
|
|
1569
|
+
isLiteral = true;
|
|
1570
|
+
}
|
|
1334
1571
|
break;
|
|
1335
1572
|
default:
|
|
1336
|
-
|
|
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
|
|
1933
|
+
isArray = token.value === 'Array';
|
|
1683
1934
|
advance();
|
|
1684
|
-
if (isArray && token.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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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}'.",
|
|
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
|
|
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
|
-
|
|
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.",
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
2361
|
-
//
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
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 (
|
|
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 (
|
|
2793
|
+
if (directive['use strict'] && !option.validthis && ((funct['(statement)'] &&
|
|
2442
2794
|
funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {
|
|
2443
|
-
warning("
|
|
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
|
-
|
|
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
|
-
|
|
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.",
|
|
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 (
|
|
2655
|
-
|
|
2656
|
-
|
|
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,
|
|
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
|
-
|
|
2929
|
-
indentation();
|
|
3315
|
+
} else if (nexttoken.value === 'set' && peek().id !== ':') {
|
|
2930
3316
|
advance('set');
|
|
2931
|
-
|
|
2932
|
-
|
|
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
|
|
2940
|
-
warning("Expected
|
|
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
|
-
|
|
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
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
3232
|
-
|
|
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
|
|
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
|
-
|
|
3830
|
+
|
|
3831
|
+
if (funct['(breakage)'] === 0)
|
|
3361
3832
|
warning("Unexpected '{a}'.", nexttoken, this.value);
|
|
3362
|
-
|
|
3363
|
-
|
|
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
|
-
|
|
3855
|
+
|
|
3856
|
+
if (funct['(breakage)'] === 0)
|
|
3383
3857
|
warning("Unexpected '{a}'.", nexttoken, this.value);
|
|
3384
|
-
|
|
3385
|
-
|
|
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
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
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
|
-
|
|
3473
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
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
|
-
|
|
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 ||
|
|
3624
|
-
character : e.character ||
|
|
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.
|
|
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
|
|
3854
|
-
exports.JSHINT = JSHINT;
|
|
4389
|
+
if (typeof exports === 'object' && exports)
|
|
4390
|
+
exports.JSHINT = JSHINT;
|