screw_server 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.run.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- screw_server (0.1.9)
5
- bundler (~> 1.2.0)
4
+ screw_server (0.1.10)
5
+ bundler (~> 1.2)
6
6
  daemons (= 1.0.10)
7
7
  eventmachine (= 0.12.6)
8
8
  haml (= 3.0.13)
@@ -1,10 +1,10 @@
1
1
  (function() {
2
2
 
3
- Screw.jslint_scripts = {};
3
+ Screw.jshint_scripts = {};
4
4
 
5
5
  Screw.matching_suite = function(filename) {
6
6
  var suite;
7
- $.each(Screw.jslint_suites, function() {
7
+ $.each(Screw.jshint_suites, function() {
8
8
  var found;
9
9
  $.each(this.file_list, function() {
10
10
  if (this == filename) { found = true; }
@@ -21,33 +21,33 @@ $("script").map(function() {
21
21
 
22
22
  if (!Screw.matching_suite(normalized_source_url)) { return; }
23
23
 
24
- Screw.jslint_scripts[normalized_source_url] = null;
24
+ Screw.jshint_scripts[normalized_source_url] = null;
25
25
 
26
26
  Screw.ajax({
27
27
  url: source_url,
28
28
  dataType: "text",
29
29
  contentType: "text/plain",
30
30
  success: function(code) {
31
- Screw.jslint_scripts[normalized_source_url] = code;
31
+ Screw.jshint_scripts[normalized_source_url] = code;
32
32
  }
33
33
  });
34
34
  }
35
35
  });
36
36
 
37
- if (Screw.jslint_suites.length > 0) {
37
+ if (Screw.jshint_suites.length > 0) {
38
38
  Screw.Unit(function(){
39
- describe("JSLINT check", function() {
39
+ describe("JSHINT check", function() {
40
40
  it("should succeed", function() {
41
41
  var message = "";
42
42
  var ajax = Screw.ajax;
43
- $.each(Screw.jslint_scripts, function(name, source_code) {
43
+ $.each(Screw.jshint_scripts, function(name, source_code) {
44
44
  if (source_code === null) { throw "failed to load "+name; }
45
45
 
46
46
  var suite = Screw.matching_suite(name);
47
47
 
48
- if (!JSLINT(source_code, suite.options)) {
49
- for (var i = 0; i < JSLINT.errors.length; i += 1) {
50
- var e = JSLINT.errors[i];
48
+ if (!JSHINT(source_code, suite.options)) {
49
+ for (var i = 0; i < JSHINT.errors.length; i += 1) {
50
+ var e = JSHINT.errors[i];
51
51
  if (e) {
52
52
  var line = parseInt(e.line, 10);
53
53
  var character = parseInt(e.character, 10);
@@ -0,0 +1,4832 @@
1
+ /*!
2
+ * JSHint, by JSHint Community.
3
+ *
4
+ * Licensed under the same slightly modified MIT license that JSLint is.
5
+ * It stops evil-doers everywhere.
6
+ *
7
+ * JSHint is a derivative work of JSLint:
8
+ *
9
+ * Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
10
+ *
11
+ * Permission is hereby granted, free of charge, to any person obtaining
12
+ * a copy of this software and associated documentation files (the "Software"),
13
+ * to deal in the Software without restriction, including without limitation
14
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
+ * and/or sell copies of the Software, and to permit persons to whom
16
+ * the Software is furnished to do so, subject to the following conditions:
17
+ *
18
+ * The above copyright notice and this permission notice shall be included
19
+ * in all copies or substantial portions of the Software.
20
+ *
21
+ * The Software shall be used for Good, not Evil.
22
+ *
23
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
+ * DEALINGS IN THE SOFTWARE.
30
+ *
31
+ * JSHint was forked from the 2010-12-16 edition of JSLint.
32
+ *
33
+ */
34
+
35
+ /*
36
+ JSHINT is a global function. It takes two parameters.
37
+
38
+ var myResult = JSHINT(source, option);
39
+
40
+ The first parameter is either a string or an array of strings. If it is a
41
+ string, it will be split on '\n' or '\r'. If it is an array of strings, it
42
+ is assumed that each string represents one line. The source can be a
43
+ JavaScript text or a JSON text.
44
+
45
+ The second parameter is an optional object of options which control the
46
+ operation of JSHINT. Most of the options are booleans: They are all
47
+ optional and have a default value of false. One of the options, predef,
48
+ can be an array of names, which will be used to declare global variables,
49
+ or an object whose keys are used as global names, with a boolean value
50
+ that determines if they are assignable.
51
+
52
+ If it checks out, JSHINT returns true. Otherwise, it returns false.
53
+
54
+ If false, you can inspect JSHINT.errors to find out the problems.
55
+ JSHINT.errors is an array of objects containing these members:
56
+
57
+ {
58
+ line : The line (relative to 1) at which the lint was found
59
+ character : The character (relative to 1) at which the lint was found
60
+ reason : The problem
61
+ evidence : The text line in which the problem occurred
62
+ raw : The raw message before the details were inserted
63
+ a : The first detail
64
+ b : The second detail
65
+ c : The third detail
66
+ d : The fourth detail
67
+ }
68
+
69
+ If a fatal error was found, a null will be the last element of the
70
+ JSHINT.errors array.
71
+
72
+ You can request a data structure which contains JSHint's results.
73
+
74
+ var myData = JSHINT.data();
75
+
76
+ It returns a structure with this form:
77
+
78
+ {
79
+ errors: [
80
+ {
81
+ line: NUMBER,
82
+ character: NUMBER,
83
+ reason: STRING,
84
+ evidence: STRING
85
+ }
86
+ ],
87
+ functions: [
88
+ name: STRING,
89
+ line: NUMBER,
90
+ character: NUMBER,
91
+ last: NUMBER,
92
+ lastcharacter: NUMBER,
93
+ param: [
94
+ STRING
95
+ ],
96
+ closure: [
97
+ STRING
98
+ ],
99
+ var: [
100
+ STRING
101
+ ],
102
+ exception: [
103
+ STRING
104
+ ],
105
+ outer: [
106
+ STRING
107
+ ],
108
+ unused: [
109
+ STRING
110
+ ],
111
+ global: [
112
+ STRING
113
+ ],
114
+ label: [
115
+ STRING
116
+ ]
117
+ ],
118
+ globals: [
119
+ STRING
120
+ ],
121
+ member: {
122
+ STRING: NUMBER
123
+ },
124
+ unused: [
125
+ {
126
+ name: STRING,
127
+ line: NUMBER
128
+ }
129
+ ],
130
+ implieds: [
131
+ {
132
+ name: STRING,
133
+ line: NUMBER
134
+ }
135
+ ],
136
+ urls: [
137
+ STRING
138
+ ],
139
+ json: BOOLEAN
140
+ }
141
+
142
+ Empty arrays will not be included.
143
+
144
+ */
145
+
146
+ /*jshint
147
+ evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true,
148
+ undef: true, maxlen: 100, indent: 4, quotmark: double, unused: true
149
+ */
150
+
151
+ /*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)",
152
+ "(breakage)", "(character)", "(context)", "(error)", "(explicitNewcap)", "(global)",
153
+ "(identifier)", "(last)", "(lastcharacter)", "(line)", "(loopage)", "(metrics)",
154
+ "(name)", "(onevar)", "(params)", "(scope)", "(statement)", "(verb)", "(tokens)", "(catch)",
155
+ "*", "+", "++", "-", "--", "\/", "<", "<=", "==",
156
+ "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,
157
+ __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio,
158
+ Autocompleter, Asset, Boolean, Builder, Buffer, Browser, Blob, COM, CScript, Canvas,
159
+ CustomAnimation, Class, Control, ComplexityCount, Chain, Color, Cookie, Core, DataView, Date,
160
+ Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMEvent, DOMReady, DOMParser,
161
+ Drag, E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,
162
+ Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,
163
+ FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey,
164
+ HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement,
165
+ HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement,
166
+ HTMLDivElement, HTMLDListElement, HTMLFieldSetElement,
167
+ HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement,
168
+ HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement,
169
+ HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement,
170
+ HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement,
171
+ HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement,
172
+ HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement,
173
+ HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement,
174
+ HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement,
175
+ HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement,
176
+ HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement,
177
+ HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement,
178
+ Iframe, IframeShim, Image, importScripts, Int16Array, Int32Array, Int8Array,
179
+ Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,
180
+ MAX_VALUE, MIN_VALUE, Map, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort,
181
+ MoveAnimation, MooTools, MutationObserver, NaN, Native, NEGATIVE_INFINITY, Node, NodeFilter,
182
+ Number, Object, ObjectRange,
183
+ Option, Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype,
184
+ RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, Set,
185
+ SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,
186
+ ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,
187
+ Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables,
188
+ SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,
189
+ Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL,
190
+ VBArray, WeakMap, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer,
191
+ XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult,
192
+ "\\", a, abs, addEventListener, address, alert, apply, applicationCache, arguments, arity,
193
+ asi, atob, b, basic, basicToken, bitwise, blacklist, block, blur, boolOptions, boss,
194
+ browser, btoa, c, call, callee, caller, camelcase, cases, charAt, charCodeAt, character,
195
+ clearInterval, clearTimeout, close, closed, closure, comment, complexityCount, condition,
196
+ confirm, console, constructor, content, couch, create, css, curly, d, data, datalist, dd, debug,
197
+ decodeURI, decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,
198
+ dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent, elem,
199
+ eqeq, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,
200
+ ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, forEach,
201
+ forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,
202
+ g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,
203
+ hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,
204
+ indent, indexOf, init, ins, internals, instanceOf, isAlpha, isApplicationRunning, isArray,
205
+ isDigit, isFinite, isNaN, iterator, java, join, jshint,
206
+ JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastcharacter, lastsemic, laxbreak,
207
+ laxcomma, latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,
208
+ log, loopfunc, m, match, max, maxcomplexity, maxdepth, maxerr, maxlen, maxstatements, maxparams,
209
+ member, message, meta, module, moveBy, moveTo, mootools, multistr, name, navigator, new, newcap,
210
+ nestedBlockDepth, noarg, node, noempty, nomen, nonew, nonstandard, nud, onbeforeunload, onblur,
211
+ onerror, onevar, onecase, onfocus, onload, onresize, onunload, open, openDatabase, openURL,
212
+ opener, opera, options, outer, param, parent, parseFloat, parseInt, passfail, plusplus,
213
+ postMessage, pop, predef, print, process, prompt, proto, prototype, prototypejs, provides, push,
214
+ quit, quotmark, range, raw, reach, reason, regexp, readFile, readUrl, regexdash,
215
+ removeEventListener, replace, report, require, reserved, resizeBy, resizeTo, resolvePath,
216
+ resumeUpdates, respond, rhino, right, runCommand, scroll, scope, screen, scripturl, scrollBy,
217
+ scrollTo, scrollbar, search, seal, self, send, serialize, sessionStorage, setInterval, setTimeout,
218
+ setter, setterToken, shift, slice, smarttabs, sort, spawn, split, statement, statementCount, stack,
219
+ status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync, test, toLowerCase,
220
+ toString, toUpperCase, toint32, token, tokens, top, trailing, type, typeOf, Uint16Array,
221
+ Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis, value, valueOf, var, vars,
222
+ version, verifyMaxParametersPerFunction, verifyMaxStatementsPerFunction,
223
+ verifyMaxComplexityPerFunction, verifyMaxNestedBlockDepthPerFunction, WebSocket, withstmt, white,
224
+ window, windows, Worker, worker, wsh, yui, YUI, Y, YUI_config*/
225
+
226
+ /*global exports: false */
227
+
228
+ // We build the application inside a function so that we produce only a single
229
+ // global variable. That function will be invoked immediately, and its return
230
+ // value is the JSHINT function itself.
231
+
232
+ var JSHINT = (function () {
233
+ "use strict";
234
+
235
+ var anonname, // The guessed name for anonymous functions.
236
+
237
+ // These are operators that should not be used with the ! operator.
238
+
239
+ bang = {
240
+ "<" : true,
241
+ "<=" : true,
242
+ "==" : true,
243
+ "===": true,
244
+ "!==": true,
245
+ "!=" : true,
246
+ ">" : true,
247
+ ">=" : true,
248
+ "+" : true,
249
+ "-" : true,
250
+ "*" : true,
251
+ "/" : true,
252
+ "%" : true
253
+ },
254
+
255
+ // These are the JSHint boolean options.
256
+ boolOptions = {
257
+ asi : true, // if automatic semicolon insertion should be tolerated
258
+ bitwise : true, // if bitwise operators should not be allowed
259
+ boss : true, // if advanced usage of assignments should be allowed
260
+ browser : true, // if the standard browser globals should be predefined
261
+ camelcase : true, // if identifiers should be required in camel case
262
+ couch : true, // if CouchDB globals should be predefined
263
+ curly : true, // if curly braces around all blocks should be required
264
+ debug : true, // if debugger statements should be allowed
265
+ devel : true, // if logging globals should be predefined (console,
266
+ // alert, etc.)
267
+ dojo : true, // if Dojo Toolkit globals should be predefined
268
+ eqeqeq : true, // if === should be required
269
+ eqnull : true, // if == null comparisons should be tolerated
270
+ es5 : true, // if ES5 syntax should be allowed
271
+ esnext : true, // if es.next specific syntax should be allowed
272
+ evil : true, // if eval should be allowed
273
+ expr : true, // if ExpressionStatement should be allowed as Programs
274
+ forin : true, // if for in statements must filter
275
+ funcscope : true, // if only function scope should be used for scope tests
276
+ globalstrict: true, // if global "use strict"; should be allowed (also
277
+ // enables 'strict')
278
+ immed : true, // if immediate invocations must be wrapped in parens
279
+ iterator : true, // if the `__iterator__` property should be allowed
280
+ jquery : true, // if jQuery globals should be predefined
281
+ lastsemic : true, // if semicolons may be ommitted for the trailing
282
+ // statements inside of a one-line blocks.
283
+ latedef : true, // if the use before definition should not be tolerated
284
+ laxbreak : true, // if line breaks should not be checked
285
+ laxcomma : true, // if line breaks should not be checked around commas
286
+ loopfunc : true, // if functions should be allowed to be defined within
287
+ // loops
288
+ mootools : true, // if MooTools globals should be predefined
289
+ multistr : true, // allow multiline strings
290
+ newcap : true, // if constructor names must be capitalized
291
+ noarg : true, // if arguments.caller and arguments.callee should be
292
+ // disallowed
293
+ node : true, // if the Node.js environment globals should be
294
+ // predefined
295
+ noempty : true, // if empty blocks should be disallowed
296
+ nonew : true, // if using `new` for side-effects should be disallowed
297
+ nonstandard : true, // if non-standard (but widely adopted) globals should
298
+ // be predefined
299
+ nomen : true, // if names should be checked
300
+ onevar : true, // if only one var statement per function should be
301
+ // allowed
302
+ onecase : true, // if one case switch statements should be allowed
303
+ passfail : true, // if the scan should stop on first error
304
+ plusplus : true, // if increment/decrement should not be allowed
305
+ proto : true, // if the `__proto__` property should be allowed
306
+ prototypejs : true, // if Prototype and Scriptaculous globals should be
307
+ // predefined
308
+ regexdash : true, // if unescaped first/last dash (-) inside brackets
309
+ // should be tolerated
310
+ regexp : true, // if the . should not be allowed in regexp literals
311
+ rhino : true, // if the Rhino environment globals should be predefined
312
+ undef : true, // if variables should be declared before used
313
+ unused : true, // if variables should be always used
314
+ scripturl : true, // if script-targeted URLs should be tolerated
315
+ shadow : true, // if variable shadowing should be tolerated
316
+ smarttabs : true, // if smarttabs should be tolerated
317
+ // (http://www.emacswiki.org/emacs/SmartTabs)
318
+ strict : true, // require the "use strict"; pragma
319
+ sub : true, // if all forms of subscript notation are tolerated
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
+ withstmt : true, // if with statements should be allowed
326
+ white : true, // if strict whitespace rules apply
327
+ worker : true, // if Web Worker script symbols should be allowed
328
+ wsh : true, // if the Windows Scripting Host environment globals
329
+ // should be predefined
330
+ yui : true // YUI variables should be predefined
331
+ },
332
+
333
+ // These are the JSHint options that can take any value
334
+ // (we use this object to detect invalid options)
335
+ valOptions = {
336
+ maxlen : false,
337
+ indent : false,
338
+ maxerr : false,
339
+ predef : false,
340
+ quotmark : false, //'single'|'double'|true
341
+ scope : false,
342
+ maxstatements: false, // {int} max statements per function
343
+ maxdepth : false, // {int} max nested block depth per function
344
+ maxparams : false, // {int} max params per function
345
+ maxcomplexity: false // {int} max cyclomatic complexity per function
346
+ },
347
+
348
+ // These are JSHint boolean options which are shared with JSLint
349
+ // where the definition in JSHint is opposite JSLint
350
+ invertedOptions = {
351
+ bitwise : true,
352
+ forin : true,
353
+ newcap : true,
354
+ nomen : true,
355
+ plusplus : true,
356
+ regexp : true,
357
+ undef : true,
358
+ white : true,
359
+
360
+ // Inverted and renamed, use JSHint name here
361
+ eqeqeq : true,
362
+ onevar : true
363
+ },
364
+
365
+ // These are JSHint boolean options which are shared with JSLint
366
+ // where the name has been changed but the effect is unchanged
367
+ renamedOptions = {
368
+ eqeq : "eqeqeq",
369
+ vars : "onevar",
370
+ windows : "wsh"
371
+ },
372
+
373
+
374
+ // browser contains a set of global names which are commonly provided by a
375
+ // web browser environment.
376
+ browser = {
377
+ ArrayBuffer : false,
378
+ ArrayBufferView : false,
379
+ Audio : false,
380
+ Blob : false,
381
+ addEventListener : false,
382
+ applicationCache : false,
383
+ atob : false,
384
+ blur : false,
385
+ btoa : false,
386
+ clearInterval : false,
387
+ clearTimeout : false,
388
+ close : false,
389
+ closed : false,
390
+ DataView : false,
391
+ DOMParser : false,
392
+ defaultStatus : false,
393
+ document : false,
394
+ event : false,
395
+ FileReader : false,
396
+ Float32Array : false,
397
+ Float64Array : false,
398
+ FormData : false,
399
+ focus : false,
400
+ frames : false,
401
+ getComputedStyle : false,
402
+ HTMLElement : false,
403
+ HTMLAnchorElement : false,
404
+ HTMLBaseElement : false,
405
+ HTMLBlockquoteElement : false,
406
+ HTMLBodyElement : false,
407
+ HTMLBRElement : false,
408
+ HTMLButtonElement : false,
409
+ HTMLCanvasElement : false,
410
+ HTMLDirectoryElement : false,
411
+ HTMLDivElement : false,
412
+ HTMLDListElement : false,
413
+ HTMLFieldSetElement : false,
414
+ HTMLFontElement : false,
415
+ HTMLFormElement : false,
416
+ HTMLFrameElement : false,
417
+ HTMLFrameSetElement : false,
418
+ HTMLHeadElement : false,
419
+ HTMLHeadingElement : false,
420
+ HTMLHRElement : false,
421
+ HTMLHtmlElement : false,
422
+ HTMLIFrameElement : false,
423
+ HTMLImageElement : false,
424
+ HTMLInputElement : false,
425
+ HTMLIsIndexElement : false,
426
+ HTMLLabelElement : false,
427
+ HTMLLayerElement : false,
428
+ HTMLLegendElement : false,
429
+ HTMLLIElement : false,
430
+ HTMLLinkElement : false,
431
+ HTMLMapElement : false,
432
+ HTMLMenuElement : false,
433
+ HTMLMetaElement : false,
434
+ HTMLModElement : false,
435
+ HTMLObjectElement : false,
436
+ HTMLOListElement : false,
437
+ HTMLOptGroupElement : false,
438
+ HTMLOptionElement : false,
439
+ HTMLParagraphElement : false,
440
+ HTMLParamElement : false,
441
+ HTMLPreElement : false,
442
+ HTMLQuoteElement : false,
443
+ HTMLScriptElement : false,
444
+ HTMLSelectElement : false,
445
+ HTMLStyleElement : false,
446
+ HTMLTableCaptionElement : false,
447
+ HTMLTableCellElement : false,
448
+ HTMLTableColElement : false,
449
+ HTMLTableElement : false,
450
+ HTMLTableRowElement : false,
451
+ HTMLTableSectionElement : false,
452
+ HTMLTextAreaElement : false,
453
+ HTMLTitleElement : false,
454
+ HTMLUListElement : false,
455
+ HTMLVideoElement : false,
456
+ history : false,
457
+ Int16Array : false,
458
+ Int32Array : false,
459
+ Int8Array : false,
460
+ Image : false,
461
+ length : false,
462
+ localStorage : false,
463
+ location : false,
464
+ MessageChannel : false,
465
+ MessageEvent : false,
466
+ MessagePort : false,
467
+ moveBy : false,
468
+ moveTo : false,
469
+ MutationObserver : false,
470
+ name : false,
471
+ Node : false,
472
+ NodeFilter : false,
473
+ navigator : false,
474
+ onbeforeunload : true,
475
+ onblur : true,
476
+ onerror : true,
477
+ onfocus : true,
478
+ onload : true,
479
+ onresize : true,
480
+ onunload : true,
481
+ open : false,
482
+ openDatabase : false,
483
+ opener : false,
484
+ Option : false,
485
+ parent : false,
486
+ print : false,
487
+ removeEventListener : false,
488
+ resizeBy : false,
489
+ resizeTo : false,
490
+ screen : false,
491
+ scroll : false,
492
+ scrollBy : false,
493
+ scrollTo : false,
494
+ sessionStorage : false,
495
+ setInterval : false,
496
+ setTimeout : false,
497
+ SharedWorker : false,
498
+ status : false,
499
+ top : false,
500
+ Uint16Array : false,
501
+ Uint32Array : false,
502
+ Uint8Array : false,
503
+ WebSocket : false,
504
+ window : false,
505
+ Worker : false,
506
+ XMLHttpRequest : false,
507
+ XMLSerializer : false,
508
+ XPathEvaluator : false,
509
+ XPathException : false,
510
+ XPathExpression : false,
511
+ XPathNamespace : false,
512
+ XPathNSResolver : false,
513
+ XPathResult : false
514
+ },
515
+
516
+ couch = {
517
+ "require" : false,
518
+ respond : false,
519
+ getRow : false,
520
+ emit : false,
521
+ send : false,
522
+ start : false,
523
+ sum : false,
524
+ log : false,
525
+ exports : false,
526
+ module : false,
527
+ provides : false
528
+ },
529
+
530
+ declared, // Globals that were declared using /*global ... */ syntax.
531
+
532
+ devel = {
533
+ alert : false,
534
+ confirm : false,
535
+ console : false,
536
+ Debug : false,
537
+ opera : false,
538
+ prompt : false
539
+ },
540
+
541
+ dojo = {
542
+ dojo : false,
543
+ dijit : false,
544
+ dojox : false,
545
+ define : false,
546
+ "require" : false
547
+ },
548
+
549
+ funct, // The current function
550
+
551
+ functionicity = [
552
+ "closure", "exception", "global", "label",
553
+ "outer", "unused", "var"
554
+ ],
555
+
556
+ functions, // All of the functions
557
+
558
+ global, // The global scope
559
+ implied, // Implied globals
560
+ inblock,
561
+ indent,
562
+ jsonmode,
563
+
564
+ jquery = {
565
+ "$" : false,
566
+ jQuery : false
567
+ },
568
+
569
+ lines,
570
+ lookahead,
571
+ member,
572
+ membersOnly,
573
+
574
+ mootools = {
575
+ "$" : false,
576
+ "$$" : false,
577
+ Asset : false,
578
+ Browser : false,
579
+ Chain : false,
580
+ Class : false,
581
+ Color : false,
582
+ Cookie : false,
583
+ Core : false,
584
+ Document : false,
585
+ DomReady : false,
586
+ DOMEvent : false,
587
+ DOMReady : false,
588
+ Drag : false,
589
+ Element : false,
590
+ Elements : false,
591
+ Event : false,
592
+ Events : false,
593
+ Fx : false,
594
+ Group : false,
595
+ Hash : false,
596
+ HtmlTable : false,
597
+ Iframe : false,
598
+ IframeShim : false,
599
+ InputValidator : false,
600
+ instanceOf : false,
601
+ Keyboard : false,
602
+ Locale : false,
603
+ Mask : false,
604
+ MooTools : false,
605
+ Native : false,
606
+ Options : false,
607
+ OverText : false,
608
+ Request : false,
609
+ Scroller : false,
610
+ Slick : false,
611
+ Slider : false,
612
+ Sortables : false,
613
+ Spinner : false,
614
+ Swiff : false,
615
+ Tips : false,
616
+ Type : false,
617
+ typeOf : false,
618
+ URI : false,
619
+ Window : false
620
+ },
621
+
622
+ nexttoken,
623
+
624
+ node = {
625
+ __filename : false,
626
+ __dirname : false,
627
+ Buffer : false,
628
+ console : false,
629
+ exports : true, // In Node it is ok to exports = module.exports = foo();
630
+ GLOBAL : false,
631
+ global : false,
632
+ module : false,
633
+ process : false,
634
+ require : false,
635
+ setTimeout : false,
636
+ clearTimeout : false,
637
+ setInterval : false,
638
+ clearInterval : false
639
+ },
640
+
641
+ noreach,
642
+ option,
643
+ predefined, // Global variables defined by option
644
+ prereg,
645
+ prevtoken,
646
+
647
+ prototypejs = {
648
+ "$" : false,
649
+ "$$" : false,
650
+ "$A" : false,
651
+ "$F" : false,
652
+ "$H" : false,
653
+ "$R" : false,
654
+ "$break" : false,
655
+ "$continue" : false,
656
+ "$w" : false,
657
+ Abstract : false,
658
+ Ajax : false,
659
+ Class : false,
660
+ Enumerable : false,
661
+ Element : false,
662
+ Event : false,
663
+ Field : false,
664
+ Form : false,
665
+ Hash : false,
666
+ Insertion : false,
667
+ ObjectRange : false,
668
+ PeriodicalExecuter: false,
669
+ Position : false,
670
+ Prototype : false,
671
+ Selector : false,
672
+ Template : false,
673
+ Toggle : false,
674
+ Try : false,
675
+ Autocompleter : false,
676
+ Builder : false,
677
+ Control : false,
678
+ Draggable : false,
679
+ Draggables : false,
680
+ Droppables : false,
681
+ Effect : false,
682
+ Sortable : false,
683
+ SortableObserver : false,
684
+ Sound : false,
685
+ Scriptaculous : false
686
+ },
687
+
688
+ quotmark,
689
+
690
+ rhino = {
691
+ defineClass : false,
692
+ deserialize : false,
693
+ gc : false,
694
+ help : false,
695
+ importPackage: false,
696
+ "java" : false,
697
+ load : false,
698
+ loadClass : false,
699
+ print : false,
700
+ quit : false,
701
+ readFile : false,
702
+ readUrl : false,
703
+ runCommand : false,
704
+ seal : false,
705
+ serialize : false,
706
+ spawn : false,
707
+ sync : false,
708
+ toint32 : false,
709
+ version : false
710
+ },
711
+
712
+ scope, // The current scope
713
+ stack,
714
+
715
+ // standard contains the global names that are provided by the
716
+ // ECMAScript standard.
717
+ standard = {
718
+ Array : false,
719
+ Boolean : false,
720
+ Date : false,
721
+ decodeURI : false,
722
+ decodeURIComponent : false,
723
+ encodeURI : false,
724
+ encodeURIComponent : false,
725
+ Error : false,
726
+ "eval" : false,
727
+ EvalError : false,
728
+ Function : false,
729
+ hasOwnProperty : false,
730
+ isFinite : false,
731
+ isNaN : false,
732
+ JSON : false,
733
+ Map : false,
734
+ Math : false,
735
+ NaN : false,
736
+ Number : false,
737
+ Object : false,
738
+ parseInt : false,
739
+ parseFloat : false,
740
+ RangeError : false,
741
+ ReferenceError : false,
742
+ RegExp : false,
743
+ Set : false,
744
+ String : false,
745
+ SyntaxError : false,
746
+ TypeError : false,
747
+ URIError : false,
748
+ WeakMap : false
749
+ },
750
+
751
+ // widely adopted global names that are not part of ECMAScript standard
752
+ nonstandard = {
753
+ escape : false,
754
+ unescape : false
755
+ },
756
+
757
+ directive,
758
+ syntax = {},
759
+ tab,
760
+ token,
761
+ unuseds,
762
+ urls,
763
+ useESNextSyntax,
764
+ warnings,
765
+
766
+ worker = {
767
+ importScripts : true,
768
+ postMessage : true,
769
+ self : true
770
+ },
771
+
772
+ wsh = {
773
+ ActiveXObject : true,
774
+ Enumerator : true,
775
+ GetObject : true,
776
+ ScriptEngine : true,
777
+ ScriptEngineBuildVersion : true,
778
+ ScriptEngineMajorVersion : true,
779
+ ScriptEngineMinorVersion : true,
780
+ VBArray : true,
781
+ WSH : true,
782
+ WScript : true,
783
+ XDomainRequest : true
784
+ },
785
+
786
+ yui = {
787
+ YUI : false,
788
+ Y : false,
789
+ YUI_config : false
790
+ };
791
+ // Regular expressions. Some of these are stupidly long.
792
+ var ax, cx, tx, nx, nxg, lx, ix, jx, ft;
793
+ (function () {
794
+ /*jshint maxlen:300 */
795
+
796
+ // unsafe comment or string
797
+ ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
798
+
799
+ // unsafe characters that are silently deleted by one or more browsers
800
+ cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
801
+
802
+ // token
803
+ tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/=(?!(\S*\/[gim]?))|\/(\*(jshint|jslint|members?|global)?|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/;
804
+
805
+ // characters in strings that need escapement
806
+ nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
807
+ nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
808
+
809
+ // star slash
810
+ lx = /\*\//;
811
+
812
+ // identifier
813
+ ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
814
+
815
+ // javascript url
816
+ jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
817
+
818
+ // catches /* falls through */ comments
819
+ ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/;
820
+ }());
821
+
822
+ function F() {} // Used by Object.create
823
+
824
+ function is_own(object, name) {
825
+ // The object.hasOwnProperty method fails when the property under consideration
826
+ // is named 'hasOwnProperty'. So we have to use this more convoluted form.
827
+ return Object.prototype.hasOwnProperty.call(object, name);
828
+ }
829
+
830
+ function checkOption(name, t) {
831
+ if (valOptions[name] === undefined && boolOptions[name] === undefined) {
832
+ warning("Bad option: '" + name + "'.", t);
833
+ }
834
+ }
835
+
836
+ function isString(obj) {
837
+ return Object.prototype.toString.call(obj) === "[object String]";
838
+ }
839
+
840
+ // Provide critical ES5 functions to ES3.
841
+
842
+ if (typeof Array.isArray !== "function") {
843
+ Array.isArray = function (o) {
844
+ return Object.prototype.toString.apply(o) === "[object Array]";
845
+ };
846
+ }
847
+
848
+ if (!Array.prototype.forEach) {
849
+ Array.prototype.forEach = function (fn, scope) {
850
+ var len = this.length;
851
+
852
+ for (var i = 0; i < len; i++) {
853
+ fn.call(scope || this, this[i], i, this);
854
+ }
855
+ };
856
+ }
857
+
858
+ if (!Array.prototype.indexOf) {
859
+ Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
860
+ if (this === null || this === undefined) {
861
+ throw new TypeError();
862
+ }
863
+
864
+ var t = new Object(this);
865
+ var len = t.length >>> 0;
866
+
867
+ if (len === 0) {
868
+ return -1;
869
+ }
870
+
871
+ var n = 0;
872
+ if (arguments.length > 0) {
873
+ n = Number(arguments[1]);
874
+ if (n != n) { // shortcut for verifying if it's NaN
875
+ n = 0;
876
+ } else if (n !== 0 && n != Infinity && n != -Infinity) {
877
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
878
+ }
879
+ }
880
+
881
+ if (n >= len) {
882
+ return -1;
883
+ }
884
+
885
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
886
+ for (; k < len; k++) {
887
+ if (k in t && t[k] === searchElement) {
888
+ return k;
889
+ }
890
+ }
891
+
892
+ return -1;
893
+ };
894
+ }
895
+
896
+ if (typeof Object.create !== "function") {
897
+ Object.create = function (o) {
898
+ F.prototype = o;
899
+ return new F();
900
+ };
901
+ }
902
+
903
+ if (typeof Object.keys !== "function") {
904
+ Object.keys = function (o) {
905
+ var a = [], k;
906
+ for (k in o) {
907
+ if (is_own(o, k)) {
908
+ a.push(k);
909
+ }
910
+ }
911
+ return a;
912
+ };
913
+ }
914
+
915
+ // Non standard methods
916
+
917
+ function isAlpha(str) {
918
+ return (str >= "a" && str <= "z\uffff") ||
919
+ (str >= "A" && str <= "Z\uffff");
920
+ }
921
+
922
+ function isDigit(str) {
923
+ return (str >= "0" && str <= "9");
924
+ }
925
+
926
+ function isIdentifier(token, value) {
927
+ if (!token)
928
+ return false;
929
+
930
+ if (!token.identifier || token.value !== value)
931
+ return false;
932
+
933
+ return true;
934
+ }
935
+
936
+ function supplant(str, data) {
937
+ return str.replace(/\{([^{}]*)\}/g, function (a, b) {
938
+ var r = data[b];
939
+ return typeof r === "string" || typeof r === "number" ? r : a;
940
+ });
941
+ }
942
+
943
+ function combine(t, o) {
944
+ var n;
945
+ for (n in o) {
946
+ if (is_own(o, n) && !is_own(JSHINT.blacklist, n)) {
947
+ t[n] = o[n];
948
+ }
949
+ }
950
+ }
951
+
952
+ function updatePredefined() {
953
+ Object.keys(JSHINT.blacklist).forEach(function (key) {
954
+ delete predefined[key];
955
+ });
956
+ }
957
+
958
+ function assume() {
959
+ if (option.couch) {
960
+ combine(predefined, couch);
961
+ }
962
+
963
+ if (option.rhino) {
964
+ combine(predefined, rhino);
965
+ }
966
+
967
+ if (option.prototypejs) {
968
+ combine(predefined, prototypejs);
969
+ }
970
+
971
+ if (option.node) {
972
+ combine(predefined, node);
973
+ option.globalstrict = true;
974
+ }
975
+
976
+ if (option.devel) {
977
+ combine(predefined, devel);
978
+ }
979
+
980
+ if (option.dojo) {
981
+ combine(predefined, dojo);
982
+ }
983
+
984
+ if (option.browser) {
985
+ combine(predefined, browser);
986
+ }
987
+
988
+ if (option.nonstandard) {
989
+ combine(predefined, nonstandard);
990
+ }
991
+
992
+ if (option.jquery) {
993
+ combine(predefined, jquery);
994
+ }
995
+
996
+ if (option.mootools) {
997
+ combine(predefined, mootools);
998
+ }
999
+
1000
+ if (option.worker) {
1001
+ combine(predefined, worker);
1002
+ }
1003
+
1004
+ if (option.wsh) {
1005
+ combine(predefined, wsh);
1006
+ }
1007
+
1008
+ if (option.esnext) {
1009
+ useESNextSyntax();
1010
+ }
1011
+
1012
+ if (option.globalstrict && option.strict !== false) {
1013
+ option.strict = true;
1014
+ }
1015
+
1016
+ if (option.yui) {
1017
+ combine(predefined, yui);
1018
+ }
1019
+ }
1020
+
1021
+
1022
+ // Produce an error warning.
1023
+ function quit(message, line, chr) {
1024
+ var percentage = Math.floor((line / lines.length) * 100);
1025
+
1026
+ throw {
1027
+ name: "JSHintError",
1028
+ line: line,
1029
+ character: chr,
1030
+ message: message + " (" + percentage + "% scanned).",
1031
+ raw: message
1032
+ };
1033
+ }
1034
+
1035
+ function isundef(scope, m, t, a) {
1036
+ return JSHINT.undefs.push([scope, m, t, a]);
1037
+ }
1038
+
1039
+ function warning(m, t, a, b, c, d) {
1040
+ var ch, l, w;
1041
+ t = t || nexttoken;
1042
+ if (t.id === "(end)") { // `~
1043
+ t = token;
1044
+ }
1045
+ l = t.line || 0;
1046
+ ch = t.from || 0;
1047
+ w = {
1048
+ id: "(error)",
1049
+ raw: m,
1050
+ evidence: lines[l - 1] || "",
1051
+ line: l,
1052
+ character: ch,
1053
+ scope: JSHINT.scope,
1054
+ a: a,
1055
+ b: b,
1056
+ c: c,
1057
+ d: d
1058
+ };
1059
+ w.reason = supplant(m, w);
1060
+ JSHINT.errors.push(w);
1061
+ if (option.passfail) {
1062
+ quit("Stopping. ", l, ch);
1063
+ }
1064
+ warnings += 1;
1065
+ if (warnings >= option.maxerr) {
1066
+ quit("Too many errors.", l, ch);
1067
+ }
1068
+ return w;
1069
+ }
1070
+
1071
+ function warningAt(m, l, ch, a, b, c, d) {
1072
+ return warning(m, {
1073
+ line: l,
1074
+ from: ch
1075
+ }, a, b, c, d);
1076
+ }
1077
+
1078
+ function error(m, t, a, b, c, d) {
1079
+ warning(m, t, a, b, c, d);
1080
+ }
1081
+
1082
+ function errorAt(m, l, ch, a, b, c, d) {
1083
+ return error(m, {
1084
+ line: l,
1085
+ from: ch
1086
+ }, a, b, c, d);
1087
+ }
1088
+
1089
+ // Tracking of "internal" scripts, like eval containing a static string
1090
+ function addInternalSrc(elem, src) {
1091
+ var i;
1092
+ i = {
1093
+ id: "(internal)",
1094
+ elem: elem,
1095
+ value: src
1096
+ };
1097
+ JSHINT.internals.push(i);
1098
+ return i;
1099
+ }
1100
+
1101
+
1102
+ // lexical analysis and token construction
1103
+
1104
+ var lex = (function lex() {
1105
+ var character, from, line, s;
1106
+
1107
+ // Private lex methods
1108
+
1109
+ function nextLine() {
1110
+ var at,
1111
+ match,
1112
+ tw; // trailing whitespace check
1113
+
1114
+ if (line >= lines.length)
1115
+ return false;
1116
+
1117
+ character = 1;
1118
+ s = lines[line];
1119
+ line += 1;
1120
+
1121
+ // If smarttabs option is used check for spaces followed by tabs only.
1122
+ // Otherwise check for any occurence of mixed tabs and spaces.
1123
+ // Tabs and one space followed by block comment is allowed.
1124
+ if (option.smarttabs) {
1125
+ // negative look-behind for "//"
1126
+ match = s.match(/(\/\/)? \t/);
1127
+ at = match && !match[1] ? 0 : -1;
1128
+ } else {
1129
+ at = s.search(/ \t|\t [^\*]/);
1130
+ }
1131
+
1132
+ if (at >= 0)
1133
+ warningAt("Mixed spaces and tabs.", line, at + 1);
1134
+
1135
+ s = s.replace(/\t/g, tab);
1136
+ at = s.search(cx);
1137
+
1138
+ if (at >= 0)
1139
+ warningAt("Unsafe character.", line, at);
1140
+
1141
+ if (option.maxlen && option.maxlen < s.length)
1142
+ warningAt("Line too long.", line, s.length);
1143
+
1144
+ // Check for trailing whitespaces
1145
+ tw = option.trailing && s.match(/^(.*?)\s+$/);
1146
+ if (tw && !/^\s+$/.test(s)) {
1147
+ warningAt("Trailing whitespace.", line, tw[1].length + 1);
1148
+ }
1149
+ return true;
1150
+ }
1151
+
1152
+ // Produce a token object. The token inherits from a syntax symbol.
1153
+
1154
+ function it(type, value) {
1155
+ var i, t;
1156
+
1157
+ function checkName(name) {
1158
+ if (!option.proto && name === "__proto__") {
1159
+ warningAt("The '{a}' property is deprecated.", line, from, name);
1160
+ return;
1161
+ }
1162
+
1163
+ if (!option.iterator && name === "__iterator__") {
1164
+ warningAt("'{a}' is only available in JavaScript 1.7.", line, from, name);
1165
+ return;
1166
+ }
1167
+
1168
+ // Check for dangling underscores unless we're in Node
1169
+ // environment and this identifier represents built-in
1170
+ // Node globals with underscores.
1171
+
1172
+ var hasDangling = /^(_+.*|.*_+)$/.test(name);
1173
+
1174
+ if (option.nomen && hasDangling && name !== "_") {
1175
+ if (option.node && token.id !== "." && /^(__dirname|__filename)$/.test(name))
1176
+ return;
1177
+
1178
+ warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", name);
1179
+ return;
1180
+ }
1181
+
1182
+ // Check for non-camelcase names. Names like MY_VAR and
1183
+ // _myVar are okay though.
1184
+
1185
+ if (option.camelcase) {
1186
+ if (name.replace(/^_+/, "").indexOf("_") > -1 && !name.match(/^[A-Z0-9_]*$/)) {
1187
+ warningAt("Identifier '{a}' is not in camel case.", line, from, value);
1188
+ }
1189
+ }
1190
+ }
1191
+
1192
+ if (type === "(color)" || type === "(range)") {
1193
+ t = {type: type};
1194
+ } else if (type === "(punctuator)" ||
1195
+ (type === "(identifier)" && is_own(syntax, value))) {
1196
+ t = syntax[value] || syntax["(error)"];
1197
+ } else {
1198
+ t = syntax[type];
1199
+ }
1200
+
1201
+ t = Object.create(t);
1202
+
1203
+ if (type === "(string)" || type === "(range)") {
1204
+ if (!option.scripturl && jx.test(value)) {
1205
+ warningAt("Script URL.", line, from);
1206
+ }
1207
+ }
1208
+
1209
+ if (type === "(identifier)") {
1210
+ t.identifier = true;
1211
+ checkName(value);
1212
+ }
1213
+
1214
+ t.value = value;
1215
+ t.line = line;
1216
+ t.character = character;
1217
+ t.from = from;
1218
+ i = t.id;
1219
+ if (i !== "(endline)") {
1220
+ prereg = i &&
1221
+ (("(,=:[!&|?{};".indexOf(i.charAt(i.length - 1)) >= 0) ||
1222
+ i === "return" ||
1223
+ i === "case");
1224
+ }
1225
+ return t;
1226
+ }
1227
+
1228
+ // Public lex methods
1229
+ return {
1230
+ init: function (source) {
1231
+ if (typeof source === "string") {
1232
+ lines = source
1233
+ .replace(/\r\n/g, "\n")
1234
+ .replace(/\r/g, "\n")
1235
+ .split("\n");
1236
+ } else {
1237
+ lines = source;
1238
+ }
1239
+
1240
+ // If the first line is a shebang (#!), make it a blank and move on.
1241
+ // Shebangs are used by Node scripts.
1242
+ if (lines[0] && lines[0].substr(0, 2) === "#!")
1243
+ lines[0] = "";
1244
+
1245
+ line = 0;
1246
+ nextLine();
1247
+ from = 1;
1248
+ },
1249
+
1250
+ range: function (begin, end) {
1251
+ var c, value = "";
1252
+ from = character;
1253
+ if (s.charAt(0) !== begin) {
1254
+ errorAt("Expected '{a}' and instead saw '{b}'.",
1255
+ line, character, begin, s.charAt(0));
1256
+ }
1257
+ for (;;) {
1258
+ s = s.slice(1);
1259
+ character += 1;
1260
+ c = s.charAt(0);
1261
+ switch (c) {
1262
+ case "":
1263
+ errorAt("Missing '{a}'.", line, character, c);
1264
+ break;
1265
+ case end:
1266
+ s = s.slice(1);
1267
+ character += 1;
1268
+ return it("(range)", value);
1269
+ case "\\":
1270
+ warningAt("Unexpected '{a}'.", line, character, c);
1271
+ }
1272
+ value += c;
1273
+ }
1274
+
1275
+ },
1276
+
1277
+
1278
+ // token -- this is called by advance to get the next token
1279
+ token: function () {
1280
+ var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n;
1281
+
1282
+ function match(x) {
1283
+ var r = x.exec(s), r1;
1284
+
1285
+ if (r) {
1286
+ l = r[0].length;
1287
+ r1 = r[1];
1288
+ c = r1.charAt(0);
1289
+ s = s.substr(l);
1290
+ from = character + l - r1.length;
1291
+ character += l;
1292
+ return r1;
1293
+ }
1294
+ }
1295
+
1296
+ function string(x) {
1297
+ var c, j, r = "", allowNewLine = false;
1298
+
1299
+ if (jsonmode && x !== "\"") {
1300
+ warningAt("Strings must use doublequote.",
1301
+ line, character);
1302
+ }
1303
+
1304
+ if (option.quotmark) {
1305
+ if (option.quotmark === "single" && x !== "'") {
1306
+ warningAt("Strings must use singlequote.",
1307
+ line, character);
1308
+ } else if (option.quotmark === "double" && x !== "\"") {
1309
+ warningAt("Strings must use doublequote.",
1310
+ line, character);
1311
+ } else if (option.quotmark === true) {
1312
+ quotmark = quotmark || x;
1313
+ if (quotmark !== x) {
1314
+ warningAt("Mixed double and single quotes.",
1315
+ line, character);
1316
+ }
1317
+ }
1318
+ }
1319
+
1320
+ function esc(n) {
1321
+ var i = parseInt(s.substr(j + 1, n), 16);
1322
+ j += n;
1323
+ if (i >= 32 && i <= 126 &&
1324
+ i !== 34 && i !== 92 && i !== 39) {
1325
+ warningAt("Unnecessary escapement.", line, character);
1326
+ }
1327
+ character += n;
1328
+ c = String.fromCharCode(i);
1329
+ }
1330
+
1331
+ j = 0;
1332
+ unclosedString: for (;;) {
1333
+ while (j >= s.length) {
1334
+ j = 0;
1335
+
1336
+ var cl = line, cf = from;
1337
+ if (!nextLine()) {
1338
+ errorAt("Unclosed string.", cl, cf);
1339
+ break unclosedString;
1340
+ }
1341
+
1342
+ if (allowNewLine) {
1343
+ allowNewLine = false;
1344
+ } else {
1345
+ warningAt("Unclosed string.", cl, cf);
1346
+ }
1347
+ }
1348
+
1349
+ c = s.charAt(j);
1350
+ if (c === x) {
1351
+ character += 1;
1352
+ s = s.substr(j + 1);
1353
+ return it("(string)", r, x);
1354
+ }
1355
+
1356
+ if (c < " ") {
1357
+ if (c === "\n" || c === "\r") {
1358
+ break;
1359
+ }
1360
+ warningAt("Control character in string: {a}.",
1361
+ line, character + j, s.slice(0, j));
1362
+ } else if (c === "\\") {
1363
+ j += 1;
1364
+ character += 1;
1365
+ c = s.charAt(j);
1366
+ n = s.charAt(j + 1);
1367
+ switch (c) {
1368
+ case "\\":
1369
+ case "\"":
1370
+ case "/":
1371
+ break;
1372
+ case "\'":
1373
+ if (jsonmode) {
1374
+ warningAt("Avoid \\'.", line, character);
1375
+ }
1376
+ break;
1377
+ case "b":
1378
+ c = "\b";
1379
+ break;
1380
+ case "f":
1381
+ c = "\f";
1382
+ break;
1383
+ case "n":
1384
+ c = "\n";
1385
+ break;
1386
+ case "r":
1387
+ c = "\r";
1388
+ break;
1389
+ case "t":
1390
+ c = "\t";
1391
+ break;
1392
+ case "0":
1393
+ c = "\0";
1394
+ // Octal literals fail in strict mode
1395
+ // check if the number is between 00 and 07
1396
+ // where 'n' is the token next to 'c'
1397
+ if (n >= 0 && n <= 7 && directive["use strict"]) {
1398
+ warningAt(
1399
+ "Octal literals are not allowed in strict mode.",
1400
+ line, character);
1401
+ }
1402
+ break;
1403
+ case "u":
1404
+ esc(4);
1405
+ break;
1406
+ case "v":
1407
+ if (jsonmode) {
1408
+ warningAt("Avoid \\v.", line, character);
1409
+ }
1410
+ c = "\v";
1411
+ break;
1412
+ case "x":
1413
+ if (jsonmode) {
1414
+ warningAt("Avoid \\x-.", line, character);
1415
+ }
1416
+ esc(2);
1417
+ break;
1418
+ case "":
1419
+ // last character is escape character
1420
+ // always allow new line if escaped, but show
1421
+ // warning if option is not set
1422
+ allowNewLine = true;
1423
+ if (option.multistr) {
1424
+ if (jsonmode) {
1425
+ warningAt("Avoid EOL escapement.", line, character);
1426
+ }
1427
+ c = "";
1428
+ character -= 1;
1429
+ break;
1430
+ }
1431
+ warningAt("Bad escapement of EOL. Use option multistr if needed.",
1432
+ line, character);
1433
+ break;
1434
+ case "!":
1435
+ if (s.charAt(j - 2) === "<")
1436
+ break;
1437
+ /*falls through*/
1438
+ default:
1439
+ warningAt("Bad escapement.", line, character);
1440
+ }
1441
+ }
1442
+ r += c;
1443
+ character += 1;
1444
+ j += 1;
1445
+ }
1446
+ }
1447
+
1448
+ for (;;) {
1449
+ if (!s) {
1450
+ return it(nextLine() ? "(endline)" : "(end)", "");
1451
+ }
1452
+
1453
+ t = match(tx);
1454
+
1455
+ if (!t) {
1456
+ t = "";
1457
+ c = "";
1458
+ while (s && s < "!") {
1459
+ s = s.substr(1);
1460
+ }
1461
+ if (s) {
1462
+ errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1));
1463
+ s = "";
1464
+ }
1465
+ } else {
1466
+
1467
+ // identifier
1468
+
1469
+ if (isAlpha(c) || c === "_" || c === "$") {
1470
+ return it("(identifier)", t);
1471
+ }
1472
+
1473
+ // number
1474
+
1475
+ if (isDigit(c)) {
1476
+ if (!isFinite(Number(t))) {
1477
+ warningAt("Bad number '{a}'.",
1478
+ line, character, t);
1479
+ }
1480
+ if (isAlpha(s.substr(0, 1))) {
1481
+ warningAt("Missing space after '{a}'.",
1482
+ line, character, t);
1483
+ }
1484
+ if (c === "0") {
1485
+ d = t.substr(1, 1);
1486
+ if (isDigit(d)) {
1487
+ if (token.id !== ".") {
1488
+ warningAt("Don't use extra leading zeros '{a}'.",
1489
+ line, character, t);
1490
+ }
1491
+ } else if (jsonmode && (d === "x" || d === "X")) {
1492
+ warningAt("Avoid 0x-. '{a}'.",
1493
+ line, character, t);
1494
+ }
1495
+ }
1496
+ if (t.substr(t.length - 1) === ".") {
1497
+ warningAt(
1498
+ "A trailing decimal point can be confused with a dot '{a}'.", line, character, t);
1499
+ }
1500
+ return it("(number)", t);
1501
+ }
1502
+ switch (t) {
1503
+
1504
+ // string
1505
+
1506
+ case "\"":
1507
+ case "'":
1508
+ return string(t);
1509
+
1510
+ // // comment
1511
+
1512
+ case "//":
1513
+ s = "";
1514
+ token.comment = true;
1515
+ break;
1516
+
1517
+ // /* comment
1518
+
1519
+ case "/*":
1520
+ for (;;) {
1521
+ i = s.search(lx);
1522
+ if (i >= 0) {
1523
+ break;
1524
+ }
1525
+ if (!nextLine()) {
1526
+ errorAt("Unclosed comment.", line, character);
1527
+ }
1528
+ }
1529
+ s = s.substr(i + 2);
1530
+ token.comment = true;
1531
+ break;
1532
+
1533
+ // /*members /*jshint /*global
1534
+
1535
+ case "/*members":
1536
+ case "/*member":
1537
+ case "/*jshint":
1538
+ case "/*jslint":
1539
+ case "/*global":
1540
+ case "*/":
1541
+ return {
1542
+ value: t,
1543
+ type: "special",
1544
+ line: line,
1545
+ character: character,
1546
+ from: from
1547
+ };
1548
+
1549
+ case "":
1550
+ break;
1551
+ // /
1552
+ case "/":
1553
+ if (s.charAt(0) === "=") {
1554
+ errorAt("A regular expression literal can be confused with '/='.",
1555
+ line, from);
1556
+ }
1557
+
1558
+ if (prereg) {
1559
+ depth = 0;
1560
+ captures = 0;
1561
+ l = 0;
1562
+ for (;;) {
1563
+ b = true;
1564
+ c = s.charAt(l);
1565
+ l += 1;
1566
+ switch (c) {
1567
+ case "":
1568
+ errorAt("Unclosed regular expression.", line, from);
1569
+ return quit("Stopping.", line, from);
1570
+ case "/":
1571
+ if (depth > 0) {
1572
+ warningAt("{a} unterminated regular expression " +
1573
+ "group(s).", line, from + l, depth);
1574
+ }
1575
+ c = s.substr(0, l - 1);
1576
+ q = {
1577
+ g: true,
1578
+ i: true,
1579
+ m: true
1580
+ };
1581
+ while (q[s.charAt(l)] === true) {
1582
+ q[s.charAt(l)] = false;
1583
+ l += 1;
1584
+ }
1585
+ character += l;
1586
+ s = s.substr(l);
1587
+ q = s.charAt(0);
1588
+ if (q === "/" || q === "*") {
1589
+ errorAt("Confusing regular expression.",
1590
+ line, from);
1591
+ }
1592
+ return it("(regexp)", c);
1593
+ case "\\":
1594
+ c = s.charAt(l);
1595
+ if (c < " ") {
1596
+ warningAt(
1597
+ "Unexpected control character in regular expression.", line, from + l);
1598
+ } else if (c === "<") {
1599
+ warningAt(
1600
+ "Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
1601
+ }
1602
+ l += 1;
1603
+ break;
1604
+ case "(":
1605
+ depth += 1;
1606
+ b = false;
1607
+ if (s.charAt(l) === "?") {
1608
+ l += 1;
1609
+ switch (s.charAt(l)) {
1610
+ case ":":
1611
+ case "=":
1612
+ case "!":
1613
+ l += 1;
1614
+ break;
1615
+ default:
1616
+ warningAt(
1617
+ "Expected '{a}' and instead saw '{b}'.", line, from + l, ":", s.charAt(l));
1618
+ }
1619
+ } else {
1620
+ captures += 1;
1621
+ }
1622
+ break;
1623
+ case "|":
1624
+ b = false;
1625
+ break;
1626
+ case ")":
1627
+ if (depth === 0) {
1628
+ warningAt("Unescaped '{a}'.",
1629
+ line, from + l, ")");
1630
+ } else {
1631
+ depth -= 1;
1632
+ }
1633
+ break;
1634
+ case " ":
1635
+ q = 1;
1636
+ while (s.charAt(l) === " ") {
1637
+ l += 1;
1638
+ q += 1;
1639
+ }
1640
+ if (q > 1) {
1641
+ warningAt(
1642
+ "Spaces are hard to count. Use {{a}}.", line, from + l, q);
1643
+ }
1644
+ break;
1645
+ case "[":
1646
+ c = s.charAt(l);
1647
+ if (c === "^") {
1648
+ l += 1;
1649
+ if (s.charAt(l) === "]") {
1650
+ errorAt("Unescaped '{a}'.",
1651
+ line, from + l, "^");
1652
+ }
1653
+ }
1654
+ if (c === "]") {
1655
+ warningAt("Empty class.", line,
1656
+ from + l - 1);
1657
+ }
1658
+ isLiteral = false;
1659
+ isInRange = false;
1660
+ klass: do {
1661
+ c = s.charAt(l);
1662
+ l += 1;
1663
+ switch (c) {
1664
+ case "[":
1665
+ case "^":
1666
+ warningAt("Unescaped '{a}'.",
1667
+ line, from + l, c);
1668
+ if (isInRange) {
1669
+ isInRange = false;
1670
+ } else {
1671
+ isLiteral = true;
1672
+ }
1673
+ break;
1674
+ case "-":
1675
+ if (isLiteral && !isInRange) {
1676
+ isLiteral = false;
1677
+ isInRange = true;
1678
+ } else if (isInRange) {
1679
+ isInRange = false;
1680
+ } else if (s.charAt(l) === "]") {
1681
+ isInRange = true;
1682
+ } else {
1683
+ if (option.regexdash !== (l === 2 || (l === 3 &&
1684
+ s.charAt(1) === "^"))) {
1685
+ warningAt("Unescaped '{a}'.",
1686
+ line, from + l - 1, "-");
1687
+ }
1688
+ isLiteral = true;
1689
+ }
1690
+ break;
1691
+ case "]":
1692
+ if (isInRange && !option.regexdash) {
1693
+ warningAt("Unescaped '{a}'.",
1694
+ line, from + l - 1, "-");
1695
+ }
1696
+ break klass;
1697
+ case "\\":
1698
+ c = s.charAt(l);
1699
+ if (c < " ") {
1700
+ warningAt(
1701
+ "Unexpected control character in regular expression.", line, from + l);
1702
+ } else if (c === "<") {
1703
+ warningAt(
1704
+ "Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
1705
+ }
1706
+ l += 1;
1707
+
1708
+ // \w, \s and \d are never part of a character range
1709
+ if (/[wsd]/i.test(c)) {
1710
+ if (isInRange) {
1711
+ warningAt("Unescaped '{a}'.",
1712
+ line, from + l, "-");
1713
+ isInRange = false;
1714
+ }
1715
+ isLiteral = false;
1716
+ } else if (isInRange) {
1717
+ isInRange = false;
1718
+ } else {
1719
+ isLiteral = true;
1720
+ }
1721
+ break;
1722
+ case "/":
1723
+ warningAt("Unescaped '{a}'.",
1724
+ line, from + l - 1, "/");
1725
+
1726
+ if (isInRange) {
1727
+ isInRange = false;
1728
+ } else {
1729
+ isLiteral = true;
1730
+ }
1731
+ break;
1732
+ case "<":
1733
+ if (isInRange) {
1734
+ isInRange = false;
1735
+ } else {
1736
+ isLiteral = true;
1737
+ }
1738
+ break;
1739
+ default:
1740
+ if (isInRange) {
1741
+ isInRange = false;
1742
+ } else {
1743
+ isLiteral = true;
1744
+ }
1745
+ }
1746
+ } while (c);
1747
+ break;
1748
+ case ".":
1749
+ if (option.regexp) {
1750
+ warningAt("Insecure '{a}'.", line,
1751
+ from + l, c);
1752
+ }
1753
+ break;
1754
+ case "]":
1755
+ case "?":
1756
+ case "{":
1757
+ case "}":
1758
+ case "+":
1759
+ case "*":
1760
+ warningAt("Unescaped '{a}'.", line,
1761
+ from + l, c);
1762
+ }
1763
+ if (b) {
1764
+ switch (s.charAt(l)) {
1765
+ case "?":
1766
+ case "+":
1767
+ case "*":
1768
+ l += 1;
1769
+ if (s.charAt(l) === "?") {
1770
+ l += 1;
1771
+ }
1772
+ break;
1773
+ case "{":
1774
+ l += 1;
1775
+ c = s.charAt(l);
1776
+ if (c < "0" || c > "9") {
1777
+ warningAt(
1778
+ "Expected a number and instead saw '{a}'.", line, from + l, c);
1779
+ break; // No reason to continue checking numbers.
1780
+ }
1781
+ l += 1;
1782
+ low = +c;
1783
+ for (;;) {
1784
+ c = s.charAt(l);
1785
+ if (c < "0" || c > "9") {
1786
+ break;
1787
+ }
1788
+ l += 1;
1789
+ low = +c + (low * 10);
1790
+ }
1791
+ high = low;
1792
+ if (c === ",") {
1793
+ l += 1;
1794
+ high = Infinity;
1795
+ c = s.charAt(l);
1796
+ if (c >= "0" && c <= "9") {
1797
+ l += 1;
1798
+ high = +c;
1799
+ for (;;) {
1800
+ c = s.charAt(l);
1801
+ if (c < "0" || c > "9") {
1802
+ break;
1803
+ }
1804
+ l += 1;
1805
+ high = +c + (high * 10);
1806
+ }
1807
+ }
1808
+ }
1809
+ if (s.charAt(l) !== "}") {
1810
+ warningAt(
1811
+ "Expected '{a}' and instead saw '{b}'.", line, from + l, "}", c);
1812
+ } else {
1813
+ l += 1;
1814
+ }
1815
+ if (s.charAt(l) === "?") {
1816
+ l += 1;
1817
+ }
1818
+ if (low > high) {
1819
+ warningAt(
1820
+ "'{a}' should not be greater than '{b}'.", line, from + l, low, high);
1821
+ }
1822
+ }
1823
+ }
1824
+ }
1825
+ c = s.substr(0, l - 1);
1826
+ character += l;
1827
+ s = s.substr(l);
1828
+ return it("(regexp)", c);
1829
+ }
1830
+ return it("(punctuator)", t);
1831
+
1832
+ // punctuator
1833
+
1834
+ case "#":
1835
+ return it("(punctuator)", t);
1836
+ default:
1837
+ return it("(punctuator)", t);
1838
+ }
1839
+ }
1840
+ }
1841
+ }
1842
+ };
1843
+ }());
1844
+
1845
+
1846
+ function addlabel(t, type, token) {
1847
+ if (t === "hasOwnProperty") {
1848
+ warning("'hasOwnProperty' is a really bad name.");
1849
+ }
1850
+
1851
+ // Define t in the current function in the current scope.
1852
+ if (type === "exception") {
1853
+ if (is_own(funct["(context)"], t)) {
1854
+ if (funct[t] !== true && !option.node) {
1855
+ warning("Value of '{a}' may be overwritten in IE.", nexttoken, t);
1856
+ }
1857
+ }
1858
+ }
1859
+
1860
+ if (is_own(funct, t) && !funct["(global)"]) {
1861
+ if (funct[t] === true) {
1862
+ if (option.latedef)
1863
+ warning("'{a}' was used before it was defined.", nexttoken, t);
1864
+ } else {
1865
+ if (!option.shadow && type !== "exception") {
1866
+ warning("'{a}' is already defined.", nexttoken, t);
1867
+ }
1868
+ }
1869
+ }
1870
+
1871
+ funct[t] = type;
1872
+
1873
+ if (token) {
1874
+ funct["(tokens)"][t] = token;
1875
+ }
1876
+
1877
+ if (funct["(global)"]) {
1878
+ global[t] = funct;
1879
+ if (is_own(implied, t)) {
1880
+ if (option.latedef)
1881
+ warning("'{a}' was used before it was defined.", nexttoken, t);
1882
+ delete implied[t];
1883
+ }
1884
+ } else {
1885
+ scope[t] = funct;
1886
+ }
1887
+ }
1888
+
1889
+
1890
+ function doOption() {
1891
+ var nt = nexttoken;
1892
+ var o = nt.value;
1893
+ var quotmarkValue = option.quotmark;
1894
+ var predef = {};
1895
+ var b, obj, filter, t, tn, v, minus;
1896
+
1897
+ switch (o) {
1898
+ case "*/":
1899
+ error("Unbegun comment.");
1900
+ break;
1901
+ case "/*members":
1902
+ case "/*member":
1903
+ o = "/*members";
1904
+ if (!membersOnly) {
1905
+ membersOnly = {};
1906
+ }
1907
+ obj = membersOnly;
1908
+ option.quotmark = false;
1909
+ break;
1910
+ case "/*jshint":
1911
+ case "/*jslint":
1912
+ obj = option;
1913
+ filter = boolOptions;
1914
+ break;
1915
+ case "/*global":
1916
+ obj = predef;
1917
+ break;
1918
+ default:
1919
+ error("What?");
1920
+ }
1921
+
1922
+ t = lex.token();
1923
+ loop: for (;;) {
1924
+ minus = false;
1925
+ for (;;) {
1926
+ if (t.type === "special" && t.value === "*/") {
1927
+ break loop;
1928
+ }
1929
+ if (t.id !== "(endline)" && t.id !== ",") {
1930
+ break;
1931
+ }
1932
+ t = lex.token();
1933
+ }
1934
+
1935
+ if (o === "/*global" && t.value === "-") {
1936
+ minus = true;
1937
+ t = lex.token();
1938
+ }
1939
+
1940
+ if (t.type !== "(string)" && t.type !== "(identifier)" && o !== "/*members") {
1941
+ error("Bad option.", t);
1942
+ }
1943
+
1944
+ v = lex.token();
1945
+ if (v.id === ":") {
1946
+ v = lex.token();
1947
+
1948
+ if (obj === membersOnly) {
1949
+ error("Expected '{a}' and instead saw '{b}'.", t, "*/", ":");
1950
+ }
1951
+
1952
+ if (o === "/*jshint") {
1953
+ checkOption(t.value, t);
1954
+ }
1955
+
1956
+ var numericVals = [
1957
+ "maxstatements",
1958
+ "maxparams",
1959
+ "maxdepth",
1960
+ "maxcomplexity",
1961
+ "maxerr",
1962
+ "maxlen",
1963
+ "indent"
1964
+ ];
1965
+
1966
+ if (numericVals.indexOf(t.value) > -1 && (o === "/*jshint" || o === "/*jslint")) {
1967
+ b = +v.value;
1968
+
1969
+ if (typeof b !== "number" || !isFinite(b) || b <= 0 || Math.floor(b) !== b) {
1970
+ error("Expected a small integer and instead saw '{a}'.", v, v.value);
1971
+ }
1972
+
1973
+ if (t.value === "indent")
1974
+ obj.white = true;
1975
+
1976
+ obj[t.value] = b;
1977
+ } else if (t.value === "validthis") {
1978
+ if (funct["(global)"]) {
1979
+ error("Option 'validthis' can't be used in a global scope.");
1980
+ } else {
1981
+ if (v.value === "true" || v.value === "false")
1982
+ obj[t.value] = v.value === "true";
1983
+ else
1984
+ error("Bad option value.", v);
1985
+ }
1986
+ } else if (t.value === "quotmark" && (o === "/*jshint")) {
1987
+ switch (v.value) {
1988
+ case "true":
1989
+ obj.quotmark = true;
1990
+ break;
1991
+ case "false":
1992
+ obj.quotmark = false;
1993
+ break;
1994
+ case "double":
1995
+ case "single":
1996
+ obj.quotmark = v.value;
1997
+ break;
1998
+ default:
1999
+ error("Bad option value.", v);
2000
+ }
2001
+ } else if (v.value === "true" || v.value === "false") {
2002
+ if (o === "/*jslint") {
2003
+ tn = renamedOptions[t.value] || t.value;
2004
+ obj[tn] = v.value === "true";
2005
+ if (invertedOptions[tn] !== undefined) {
2006
+ obj[tn] = !obj[tn];
2007
+ }
2008
+ } else {
2009
+ obj[t.value] = v.value === "true";
2010
+ }
2011
+
2012
+ if (t.value === "newcap")
2013
+ obj["(explicitNewcap)"] = true;
2014
+ } else {
2015
+ error("Bad option value.", v);
2016
+ }
2017
+ t = lex.token();
2018
+ } else {
2019
+ if (o === "/*jshint" || o === "/*jslint") {
2020
+ error("Missing option value.", t);
2021
+ }
2022
+
2023
+ obj[t.value] = false;
2024
+
2025
+ if (o === "/*global" && minus === true) {
2026
+ JSHINT.blacklist[t.value] = t.value;
2027
+ updatePredefined();
2028
+ }
2029
+
2030
+ t = v;
2031
+ }
2032
+ }
2033
+
2034
+ if (o === "/*members") {
2035
+ option.quotmark = quotmarkValue;
2036
+ }
2037
+
2038
+ combine(predefined, predef);
2039
+
2040
+ for (var key in predef) {
2041
+ if (is_own(predef, key)) {
2042
+ declared[key] = nt;
2043
+ }
2044
+ }
2045
+
2046
+ if (filter) {
2047
+ assume();
2048
+ }
2049
+ }
2050
+
2051
+
2052
+ // We need a peek function. If it has an argument, it peeks that much farther
2053
+ // ahead. It is used to distinguish
2054
+ // for ( var i in ...
2055
+ // from
2056
+ // for ( var i = ...
2057
+
2058
+ function peek(p) {
2059
+ var i = p || 0, j = 0, t;
2060
+
2061
+ while (j <= i) {
2062
+ t = lookahead[j];
2063
+ if (!t) {
2064
+ t = lookahead[j] = lex.token();
2065
+ }
2066
+ j += 1;
2067
+ }
2068
+ return t;
2069
+ }
2070
+
2071
+
2072
+
2073
+ // Produce the next token. It looks for programming errors.
2074
+
2075
+ function advance(id, t) {
2076
+ switch (token.id) {
2077
+ case "(number)":
2078
+ if (nexttoken.id === ".") {
2079
+ warning("A dot following a number can be confused with a decimal point.", token);
2080
+ }
2081
+ break;
2082
+ case "-":
2083
+ if (nexttoken.id === "-" || nexttoken.id === "--") {
2084
+ warning("Confusing minusses.");
2085
+ }
2086
+ break;
2087
+ case "+":
2088
+ if (nexttoken.id === "+" || nexttoken.id === "++") {
2089
+ warning("Confusing plusses.");
2090
+ }
2091
+ break;
2092
+ }
2093
+
2094
+ if (token.type === "(string)" || token.identifier) {
2095
+ anonname = token.value;
2096
+ }
2097
+
2098
+ if (id && nexttoken.id !== id) {
2099
+ if (t) {
2100
+ if (nexttoken.id === "(end)") {
2101
+ warning("Unmatched '{a}'.", t, t.id);
2102
+ } else {
2103
+ warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
2104
+ nexttoken, id, t.id, t.line, nexttoken.value);
2105
+ }
2106
+ } else if (nexttoken.type !== "(identifier)" ||
2107
+ nexttoken.value !== id) {
2108
+ warning("Expected '{a}' and instead saw '{b}'.",
2109
+ nexttoken, id, nexttoken.value);
2110
+ }
2111
+ }
2112
+
2113
+ prevtoken = token;
2114
+ token = nexttoken;
2115
+ for (;;) {
2116
+ nexttoken = lookahead.shift() || lex.token();
2117
+ if (nexttoken.id === "(end)" || nexttoken.id === "(error)") {
2118
+ return;
2119
+ }
2120
+ if (nexttoken.type === "special") {
2121
+ doOption();
2122
+ } else {
2123
+ if (nexttoken.id !== "(endline)") {
2124
+ break;
2125
+ }
2126
+ }
2127
+ }
2128
+ }
2129
+
2130
+
2131
+ // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
2132
+ // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
2133
+ // like .nud except that it is only used on the first token of a statement.
2134
+ // Having .fud makes it much easier to define statement-oriented languages like
2135
+ // JavaScript. I retained Pratt's nomenclature.
2136
+
2137
+ // .nud Null denotation
2138
+ // .fud First null denotation
2139
+ // .led Left denotation
2140
+ // lbp Left binding power
2141
+ // rbp Right binding power
2142
+
2143
+ // They are elements of the parsing method called Top Down Operator Precedence.
2144
+
2145
+ function expression(rbp, initial) {
2146
+ var left, isArray = false, isObject = false;
2147
+
2148
+ if (nexttoken.id === "(end)")
2149
+ error("Unexpected early end of program.", token);
2150
+
2151
+ advance();
2152
+ if (initial) {
2153
+ anonname = "anonymous";
2154
+ funct["(verb)"] = token.value;
2155
+ }
2156
+ if (initial === true && token.fud) {
2157
+ left = token.fud();
2158
+ } else {
2159
+ if (token.nud) {
2160
+ left = token.nud();
2161
+ } else {
2162
+ if (nexttoken.type === "(number)" && token.id === ".") {
2163
+ warning("A leading decimal point can be confused with a dot: '.{a}'.",
2164
+ token, nexttoken.value);
2165
+ advance();
2166
+ return token;
2167
+ } else {
2168
+ error("Expected an identifier and instead saw '{a}'.",
2169
+ token, token.id);
2170
+ }
2171
+ }
2172
+ while (rbp < nexttoken.lbp) {
2173
+ isArray = token.value === "Array";
2174
+ isObject = token.value === "Object";
2175
+
2176
+ // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
2177
+ // Line breaks in IfStatement heads exist to satisfy the checkJSHint
2178
+ // "Line too long." error.
2179
+ if (left && (left.value || (left.first && left.first.value))) {
2180
+ // If the left.value is not "new", or the left.first.value is a "."
2181
+ // then safely assume that this is not "new Array()" and possibly
2182
+ // not "new Object()"...
2183
+ if (left.value !== "new" ||
2184
+ (left.first && left.first.value && left.first.value === ".")) {
2185
+ isArray = false;
2186
+ // ...In the case of Object, if the left.value and token.value
2187
+ // are not equal, then safely assume that this not "new Object()"
2188
+ if (left.value !== token.value) {
2189
+ isObject = false;
2190
+ }
2191
+ }
2192
+ }
2193
+
2194
+ advance();
2195
+ if (isArray && token.id === "(" && nexttoken.id === ")")
2196
+ warning("Use the array literal notation [].", token);
2197
+ if (isObject && token.id === "(" && nexttoken.id === ")")
2198
+ warning("Use the object literal notation {}.", token);
2199
+ if (token.led) {
2200
+ left = token.led(left);
2201
+ } else {
2202
+ error("Expected an operator and instead saw '{a}'.",
2203
+ token, token.id);
2204
+ }
2205
+ }
2206
+ }
2207
+ return left;
2208
+ }
2209
+
2210
+
2211
+ // Functions for conformance of style.
2212
+
2213
+ function adjacent(left, right) {
2214
+ left = left || token;
2215
+ right = right || nexttoken;
2216
+ if (option.white) {
2217
+ if (left.character !== right.from && left.line === right.line) {
2218
+ left.from += (left.character - left.from);
2219
+ warning("Unexpected space after '{a}'.", left, left.value);
2220
+ }
2221
+ }
2222
+ }
2223
+
2224
+ function nobreak(left, right) {
2225
+ left = left || token;
2226
+ right = right || nexttoken;
2227
+ if (option.white && (left.character !== right.from || left.line !== right.line)) {
2228
+ warning("Unexpected space before '{a}'.", right, right.value);
2229
+ }
2230
+ }
2231
+
2232
+ function nospace(left, right) {
2233
+ left = left || token;
2234
+ right = right || nexttoken;
2235
+ if (option.white && !left.comment) {
2236
+ if (left.line === right.line) {
2237
+ adjacent(left, right);
2238
+ }
2239
+ }
2240
+ }
2241
+
2242
+ function nonadjacent(left, right) {
2243
+ if (option.white) {
2244
+ left = left || token;
2245
+ right = right || nexttoken;
2246
+ if (left.value === ";" && right.value === ";") {
2247
+ return;
2248
+ }
2249
+ if (left.line === right.line && left.character === right.from) {
2250
+ left.from += (left.character - left.from);
2251
+ warning("Missing space after '{a}'.",
2252
+ left, left.value);
2253
+ }
2254
+ }
2255
+ }
2256
+
2257
+ function nobreaknonadjacent(left, right) {
2258
+ left = left || token;
2259
+ right = right || nexttoken;
2260
+ if (!option.laxbreak && left.line !== right.line) {
2261
+ warning("Bad line breaking before '{a}'.", right, right.id);
2262
+ } else if (option.white) {
2263
+ left = left || token;
2264
+ right = right || nexttoken;
2265
+ if (left.character === right.from) {
2266
+ left.from += (left.character - left.from);
2267
+ warning("Missing space after '{a}'.",
2268
+ left, left.value);
2269
+ }
2270
+ }
2271
+ }
2272
+
2273
+ function indentation(bias) {
2274
+ var i;
2275
+ if (option.white && nexttoken.id !== "(end)") {
2276
+ i = indent + (bias || 0);
2277
+ if (nexttoken.from !== i) {
2278
+ warning(
2279
+ "Expected '{a}' to have an indentation at {b} instead at {c}.",
2280
+ nexttoken, nexttoken.value, i, nexttoken.from);
2281
+ }
2282
+ }
2283
+ }
2284
+
2285
+ function nolinebreak(t) {
2286
+ t = t || token;
2287
+ if (t.line !== nexttoken.line) {
2288
+ warning("Line breaking error '{a}'.", t, t.value);
2289
+ }
2290
+ }
2291
+
2292
+
2293
+ function comma() {
2294
+ if (token.line !== nexttoken.line) {
2295
+ if (!option.laxcomma) {
2296
+ if (comma.first) {
2297
+ warning("Comma warnings can be turned off with 'laxcomma'");
2298
+ comma.first = false;
2299
+ }
2300
+ warning("Bad line breaking before '{a}'.", token, nexttoken.id);
2301
+ }
2302
+ } else if (!token.comment && token.character !== nexttoken.from && option.white) {
2303
+ token.from += (token.character - token.from);
2304
+ warning("Unexpected space after '{a}'.", token, token.value);
2305
+ }
2306
+ advance(",");
2307
+ nonadjacent(token, nexttoken);
2308
+ }
2309
+
2310
+
2311
+ // Functional constructors for making the symbols that will be inherited by
2312
+ // tokens.
2313
+
2314
+ function symbol(s, p) {
2315
+ var x = syntax[s];
2316
+ if (!x || typeof x !== "object") {
2317
+ syntax[s] = x = {
2318
+ id: s,
2319
+ lbp: p,
2320
+ value: s
2321
+ };
2322
+ }
2323
+ return x;
2324
+ }
2325
+
2326
+
2327
+ function delim(s) {
2328
+ return symbol(s, 0);
2329
+ }
2330
+
2331
+
2332
+ function stmt(s, f) {
2333
+ var x = delim(s);
2334
+ x.identifier = x.reserved = true;
2335
+ x.fud = f;
2336
+ return x;
2337
+ }
2338
+
2339
+
2340
+ function blockstmt(s, f) {
2341
+ var x = stmt(s, f);
2342
+ x.block = true;
2343
+ return x;
2344
+ }
2345
+
2346
+
2347
+ function reserveName(x) {
2348
+ var c = x.id.charAt(0);
2349
+ if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
2350
+ x.identifier = x.reserved = true;
2351
+ }
2352
+ return x;
2353
+ }
2354
+
2355
+
2356
+ function prefix(s, f) {
2357
+ var x = symbol(s, 150);
2358
+ reserveName(x);
2359
+ x.nud = (typeof f === "function") ? f : function () {
2360
+ this.right = expression(150);
2361
+ this.arity = "unary";
2362
+ if (this.id === "++" || this.id === "--") {
2363
+ if (option.plusplus) {
2364
+ warning("Unexpected use of '{a}'.", this, this.id);
2365
+ } else if ((!this.right.identifier || this.right.reserved) &&
2366
+ this.right.id !== "." && this.right.id !== "[") {
2367
+ warning("Bad operand.", this);
2368
+ }
2369
+ }
2370
+ return this;
2371
+ };
2372
+ return x;
2373
+ }
2374
+
2375
+
2376
+ function type(s, f) {
2377
+ var x = delim(s);
2378
+ x.type = s;
2379
+ x.nud = f;
2380
+ return x;
2381
+ }
2382
+
2383
+
2384
+ function reserve(s, f) {
2385
+ var x = type(s, f);
2386
+ x.identifier = x.reserved = true;
2387
+ return x;
2388
+ }
2389
+
2390
+
2391
+ function reservevar(s, v) {
2392
+ return reserve(s, function () {
2393
+ if (typeof v === "function") {
2394
+ v(this);
2395
+ }
2396
+ return this;
2397
+ });
2398
+ }
2399
+
2400
+
2401
+ function infix(s, f, p, w) {
2402
+ var x = symbol(s, p);
2403
+ reserveName(x);
2404
+ x.led = function (left) {
2405
+ if (!w) {
2406
+ nobreaknonadjacent(prevtoken, token);
2407
+ nonadjacent(token, nexttoken);
2408
+ }
2409
+ if (s === "in" && left.id === "!") {
2410
+ warning("Confusing use of '{a}'.", left, "!");
2411
+ }
2412
+ if (typeof f === "function") {
2413
+ return f(left, this);
2414
+ } else {
2415
+ this.left = left;
2416
+ this.right = expression(p);
2417
+ return this;
2418
+ }
2419
+ };
2420
+ return x;
2421
+ }
2422
+
2423
+
2424
+ function relation(s, f) {
2425
+ var x = symbol(s, 100);
2426
+ x.led = function (left) {
2427
+ nobreaknonadjacent(prevtoken, token);
2428
+ nonadjacent(token, nexttoken);
2429
+ var right = expression(100);
2430
+
2431
+ if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
2432
+ warning("Use the isNaN function to compare with NaN.", this);
2433
+ } else if (f) {
2434
+ f.apply(this, [left, right]);
2435
+ }
2436
+ if (left.id === "!") {
2437
+ warning("Confusing use of '{a}'.", left, "!");
2438
+ }
2439
+ if (right.id === "!") {
2440
+ warning("Confusing use of '{a}'.", right, "!");
2441
+ }
2442
+ this.left = left;
2443
+ this.right = right;
2444
+ return this;
2445
+ };
2446
+ return x;
2447
+ }
2448
+
2449
+
2450
+ function isPoorRelation(node) {
2451
+ return node &&
2452
+ ((node.type === "(number)" && +node.value === 0) ||
2453
+ (node.type === "(string)" && node.value === "") ||
2454
+ (node.type === "null" && !option.eqnull) ||
2455
+ node.type === "true" ||
2456
+ node.type === "false" ||
2457
+ node.type === "undefined");
2458
+ }
2459
+
2460
+
2461
+ function assignop(s) {
2462
+ symbol(s, 20).exps = true;
2463
+
2464
+ return infix(s, function (left, that) {
2465
+ that.left = left;
2466
+
2467
+ if (predefined[left.value] === false &&
2468
+ scope[left.value]["(global)"] === true) {
2469
+ warning("Read only.", left);
2470
+ } else if (left["function"]) {
2471
+ warning("'{a}' is a function.", left, left.value);
2472
+ }
2473
+
2474
+ if (left) {
2475
+ if (option.esnext && funct[left.value] === "const") {
2476
+ warning("Attempting to override '{a}' which is a constant", left, left.value);
2477
+ }
2478
+
2479
+ if (left.id === "." || left.id === "[") {
2480
+ if (!left.left || left.left.value === "arguments") {
2481
+ warning("Bad assignment.", that);
2482
+ }
2483
+ that.right = expression(19);
2484
+ return that;
2485
+ } else if (left.identifier && !left.reserved) {
2486
+ if (funct[left.value] === "exception") {
2487
+ warning("Do not assign to the exception parameter.", left);
2488
+ }
2489
+ that.right = expression(19);
2490
+ return that;
2491
+ }
2492
+
2493
+ if (left === syntax["function"]) {
2494
+ warning(
2495
+ "Expected an identifier in an assignment and instead saw a function invocation.",
2496
+ token);
2497
+ }
2498
+ }
2499
+
2500
+ error("Bad assignment.", that);
2501
+ }, 20);
2502
+ }
2503
+
2504
+
2505
+ function bitwise(s, f, p) {
2506
+ var x = symbol(s, p);
2507
+ reserveName(x);
2508
+ x.led = (typeof f === "function") ? f : function (left) {
2509
+ if (option.bitwise) {
2510
+ warning("Unexpected use of '{a}'.", this, this.id);
2511
+ }
2512
+ this.left = left;
2513
+ this.right = expression(p);
2514
+ return this;
2515
+ };
2516
+ return x;
2517
+ }
2518
+
2519
+
2520
+ function bitwiseassignop(s) {
2521
+ symbol(s, 20).exps = true;
2522
+ return infix(s, function (left, that) {
2523
+ if (option.bitwise) {
2524
+ warning("Unexpected use of '{a}'.", that, that.id);
2525
+ }
2526
+ nonadjacent(prevtoken, token);
2527
+ nonadjacent(token, nexttoken);
2528
+ if (left) {
2529
+ if (left.id === "." || left.id === "[" ||
2530
+ (left.identifier && !left.reserved)) {
2531
+ expression(19);
2532
+ return that;
2533
+ }
2534
+ if (left === syntax["function"]) {
2535
+ warning(
2536
+ "Expected an identifier in an assignment, and instead saw a function invocation.",
2537
+ token);
2538
+ }
2539
+ return that;
2540
+ }
2541
+ error("Bad assignment.", that);
2542
+ }, 20);
2543
+ }
2544
+
2545
+
2546
+ function suffix(s) {
2547
+ var x = symbol(s, 150);
2548
+ x.led = function (left) {
2549
+ if (option.plusplus) {
2550
+ warning("Unexpected use of '{a}'.", this, this.id);
2551
+ } else if ((!left.identifier || left.reserved) &&
2552
+ left.id !== "." && left.id !== "[") {
2553
+ warning("Bad operand.", this);
2554
+ }
2555
+ this.left = left;
2556
+ return this;
2557
+ };
2558
+ return x;
2559
+ }
2560
+
2561
+
2562
+ // fnparam means that this identifier is being defined as a function
2563
+ // argument (see identifier())
2564
+ function optionalidentifier(fnparam) {
2565
+ if (nexttoken.identifier) {
2566
+ advance();
2567
+ if (token.reserved && !option.es5) {
2568
+ // `undefined` as a function param is a common pattern to protect
2569
+ // against the case when somebody does `undefined = true` and
2570
+ // help with minification. More info: https://gist.github.com/315916
2571
+ if (!fnparam || token.value !== "undefined") {
2572
+ warning("Expected an identifier and instead saw '{a}' (a reserved word).",
2573
+ token, token.id);
2574
+ }
2575
+ }
2576
+ return token.value;
2577
+ }
2578
+ }
2579
+
2580
+ // fnparam means that this identifier is being defined as a function
2581
+ // argument
2582
+ function identifier(fnparam) {
2583
+ var i = optionalidentifier(fnparam);
2584
+ if (i) {
2585
+ return i;
2586
+ }
2587
+ if (token.id === "function" && nexttoken.id === "(") {
2588
+ warning("Missing name in function declaration.");
2589
+ } else {
2590
+ error("Expected an identifier and instead saw '{a}'.",
2591
+ nexttoken, nexttoken.value);
2592
+ }
2593
+ }
2594
+
2595
+
2596
+ function reachable(s) {
2597
+ var i = 0, t;
2598
+ if (nexttoken.id !== ";" || noreach) {
2599
+ return;
2600
+ }
2601
+ for (;;) {
2602
+ t = peek(i);
2603
+ if (t.reach) {
2604
+ return;
2605
+ }
2606
+ if (t.id !== "(endline)") {
2607
+ if (t.id === "function") {
2608
+ if (!option.latedef) {
2609
+ break;
2610
+ }
2611
+ warning(
2612
+ "Inner functions should be listed at the top of the outer function.", t);
2613
+ break;
2614
+ }
2615
+ warning("Unreachable '{a}' after '{b}'.", t, t.value, s);
2616
+ break;
2617
+ }
2618
+ i += 1;
2619
+ }
2620
+ }
2621
+
2622
+
2623
+ function statement(noindent) {
2624
+ var i = indent, r, s = scope, t = nexttoken;
2625
+
2626
+ if (t.id === ";") {
2627
+ advance(";");
2628
+ return;
2629
+ }
2630
+
2631
+ // Is this a labelled statement?
2632
+
2633
+ if (t.identifier && !t.reserved && peek().id === ":") {
2634
+ advance();
2635
+ advance(":");
2636
+ scope = Object.create(s);
2637
+ addlabel(t.value, "label");
2638
+
2639
+ if (!nexttoken.labelled && nexttoken.value !== "{") {
2640
+ warning("Label '{a}' on {b} statement.", nexttoken, t.value, nexttoken.value);
2641
+ }
2642
+
2643
+ if (jx.test(t.value + ":")) {
2644
+ warning("Label '{a}' looks like a javascript url.", t, t.value);
2645
+ }
2646
+
2647
+ nexttoken.label = t.value;
2648
+ t = nexttoken;
2649
+ }
2650
+
2651
+ // Is it a lonely block?
2652
+
2653
+ if (t.id === "{") {
2654
+ block(true, true);
2655
+ return;
2656
+ }
2657
+
2658
+ // Parse the statement.
2659
+
2660
+ if (!noindent) {
2661
+ indentation();
2662
+ }
2663
+ r = expression(0, true);
2664
+
2665
+ // Look for the final semicolon.
2666
+
2667
+ if (!t.block) {
2668
+ if (!option.expr && (!r || !r.exps)) {
2669
+ warning("Expected an assignment or function call and instead saw an expression.",
2670
+ token);
2671
+ } else if (option.nonew && r.id === "(" && r.left.id === "new") {
2672
+ warning("Do not use 'new' for side effects.", t);
2673
+ }
2674
+
2675
+ if (nexttoken.id === ",") {
2676
+ return comma();
2677
+ }
2678
+
2679
+ if (nexttoken.id !== ";") {
2680
+ if (!option.asi) {
2681
+ // If this is the last statement in a block that ends on
2682
+ // the same line *and* option lastsemic is on, ignore the warning.
2683
+ // Otherwise, complain about missing semicolon.
2684
+ if (!option.lastsemic || nexttoken.id !== "}" ||
2685
+ nexttoken.line !== token.line) {
2686
+ warningAt("Missing semicolon.", token.line, token.character);
2687
+ }
2688
+ }
2689
+ } else {
2690
+ adjacent(token, nexttoken);
2691
+ advance(";");
2692
+ nonadjacent(token, nexttoken);
2693
+ }
2694
+ }
2695
+
2696
+ // Restore the indentation.
2697
+
2698
+ indent = i;
2699
+ scope = s;
2700
+ return r;
2701
+ }
2702
+
2703
+
2704
+ function statements(startLine) {
2705
+ var a = [], p;
2706
+
2707
+ while (!nexttoken.reach && nexttoken.id !== "(end)") {
2708
+ if (nexttoken.id === ";") {
2709
+ p = peek();
2710
+ if (!p || p.id !== "(") {
2711
+ warning("Unnecessary semicolon.");
2712
+ }
2713
+ advance(";");
2714
+ } else {
2715
+ a.push(statement(startLine === nexttoken.line));
2716
+ }
2717
+ }
2718
+ return a;
2719
+ }
2720
+
2721
+
2722
+ /*
2723
+ * read all directives
2724
+ * recognizes a simple form of asi, but always
2725
+ * warns, if it is used
2726
+ */
2727
+ function directives() {
2728
+ var i, p, pn;
2729
+
2730
+ for (;;) {
2731
+ if (nexttoken.id === "(string)") {
2732
+ p = peek(0);
2733
+ if (p.id === "(endline)") {
2734
+ i = 1;
2735
+ do {
2736
+ pn = peek(i);
2737
+ i = i + 1;
2738
+ } while (pn.id === "(endline)");
2739
+
2740
+ if (pn.id !== ";") {
2741
+ if (pn.id !== "(string)" && pn.id !== "(number)" &&
2742
+ pn.id !== "(regexp)" && pn.identifier !== true &&
2743
+ pn.id !== "}") {
2744
+ break;
2745
+ }
2746
+ warning("Missing semicolon.", nexttoken);
2747
+ } else {
2748
+ p = pn;
2749
+ }
2750
+ } else if (p.id === "}") {
2751
+ // directive with no other statements, warn about missing semicolon
2752
+ warning("Missing semicolon.", p);
2753
+ } else if (p.id !== ";") {
2754
+ break;
2755
+ }
2756
+
2757
+ indentation();
2758
+ advance();
2759
+ if (directive[token.value]) {
2760
+ warning("Unnecessary directive \"{a}\".", token, token.value);
2761
+ }
2762
+
2763
+ if (token.value === "use strict") {
2764
+ if (!option["(explicitNewcap)"])
2765
+ option.newcap = true;
2766
+ option.undef = true;
2767
+ }
2768
+
2769
+ // there's no directive negation, so always set to true
2770
+ directive[token.value] = true;
2771
+
2772
+ if (p.id === ";") {
2773
+ advance(";");
2774
+ }
2775
+ continue;
2776
+ }
2777
+ break;
2778
+ }
2779
+ }
2780
+
2781
+
2782
+ /*
2783
+ * Parses a single block. A block is a sequence of statements wrapped in
2784
+ * braces.
2785
+ *
2786
+ * ordinary - true for everything but function bodies and try blocks.
2787
+ * stmt - true if block can be a single statement (e.g. in if/for/while).
2788
+ * isfunc - true if block is a function body
2789
+ */
2790
+ function block(ordinary, stmt, isfunc) {
2791
+ var a,
2792
+ b = inblock,
2793
+ old_indent = indent,
2794
+ m,
2795
+ s = scope,
2796
+ t,
2797
+ line,
2798
+ d;
2799
+
2800
+ inblock = ordinary;
2801
+
2802
+ if (!ordinary || !option.funcscope)
2803
+ scope = Object.create(scope);
2804
+
2805
+ nonadjacent(token, nexttoken);
2806
+ t = nexttoken;
2807
+
2808
+ var metrics = funct["(metrics)"];
2809
+ metrics.nestedBlockDepth += 1;
2810
+ metrics.verifyMaxNestedBlockDepthPerFunction();
2811
+
2812
+ if (nexttoken.id === "{") {
2813
+ advance("{");
2814
+ line = token.line;
2815
+ if (nexttoken.id !== "}") {
2816
+ indent += option.indent;
2817
+ while (!ordinary && nexttoken.from > indent) {
2818
+ indent += option.indent;
2819
+ }
2820
+
2821
+ if (isfunc) {
2822
+ m = {};
2823
+ for (d in directive) {
2824
+ if (is_own(directive, d)) {
2825
+ m[d] = directive[d];
2826
+ }
2827
+ }
2828
+ directives();
2829
+
2830
+ if (option.strict && funct["(context)"]["(global)"]) {
2831
+ if (!m["use strict"] && !directive["use strict"]) {
2832
+ warning("Missing \"use strict\" statement.");
2833
+ }
2834
+ }
2835
+ }
2836
+
2837
+ a = statements(line);
2838
+
2839
+ metrics.statementCount += a.length;
2840
+
2841
+ if (isfunc) {
2842
+ directive = m;
2843
+ }
2844
+
2845
+ indent -= option.indent;
2846
+ if (line !== nexttoken.line) {
2847
+ indentation();
2848
+ }
2849
+ } else if (line !== nexttoken.line) {
2850
+ indentation();
2851
+ }
2852
+ advance("}", t);
2853
+ indent = old_indent;
2854
+ } else if (!ordinary) {
2855
+ error("Expected '{a}' and instead saw '{b}'.",
2856
+ nexttoken, "{", nexttoken.value);
2857
+ } else {
2858
+ if (!stmt || option.curly)
2859
+ warning("Expected '{a}' and instead saw '{b}'.",
2860
+ nexttoken, "{", nexttoken.value);
2861
+
2862
+ noreach = true;
2863
+ indent += option.indent;
2864
+ // test indentation only if statement is in new line
2865
+ a = [statement(nexttoken.line === token.line)];
2866
+ indent -= option.indent;
2867
+ noreach = false;
2868
+ }
2869
+ funct["(verb)"] = null;
2870
+ if (!ordinary || !option.funcscope) scope = s;
2871
+ inblock = b;
2872
+ if (ordinary && option.noempty && (!a || a.length === 0)) {
2873
+ warning("Empty block.");
2874
+ }
2875
+ metrics.nestedBlockDepth -= 1;
2876
+ return a;
2877
+ }
2878
+
2879
+
2880
+ function countMember(m) {
2881
+ if (membersOnly && typeof membersOnly[m] !== "boolean") {
2882
+ warning("Unexpected /*member '{a}'.", token, m);
2883
+ }
2884
+ if (typeof member[m] === "number") {
2885
+ member[m] += 1;
2886
+ } else {
2887
+ member[m] = 1;
2888
+ }
2889
+ }
2890
+
2891
+
2892
+ function note_implied(token) {
2893
+ var name = token.value, line = token.line, a = implied[name];
2894
+ if (typeof a === "function") {
2895
+ a = false;
2896
+ }
2897
+
2898
+ if (!a) {
2899
+ a = [line];
2900
+ implied[name] = a;
2901
+ } else if (a[a.length - 1] !== line) {
2902
+ a.push(line);
2903
+ }
2904
+ }
2905
+
2906
+
2907
+ // Build the syntax table by declaring the syntactic elements of the language.
2908
+
2909
+ type("(number)", function () {
2910
+ return this;
2911
+ });
2912
+
2913
+ type("(string)", function () {
2914
+ return this;
2915
+ });
2916
+
2917
+ syntax["(identifier)"] = {
2918
+ type: "(identifier)",
2919
+ lbp: 0,
2920
+ identifier: true,
2921
+ nud: function () {
2922
+ var v = this.value,
2923
+ s = scope[v],
2924
+ f;
2925
+
2926
+ if (typeof s === "function") {
2927
+ // Protection against accidental inheritance.
2928
+ s = undefined;
2929
+ } else if (typeof s === "boolean") {
2930
+ f = funct;
2931
+ funct = functions[0];
2932
+ addlabel(v, "var");
2933
+ s = funct;
2934
+ funct = f;
2935
+ }
2936
+
2937
+ // The name is in scope and defined in the current function.
2938
+ if (funct === s) {
2939
+ // Change 'unused' to 'var', and reject labels.
2940
+ switch (funct[v]) {
2941
+ case "unused":
2942
+ funct[v] = "var";
2943
+ break;
2944
+ case "unction":
2945
+ funct[v] = "function";
2946
+ this["function"] = true;
2947
+ break;
2948
+ case "function":
2949
+ this["function"] = true;
2950
+ break;
2951
+ case "label":
2952
+ warning("'{a}' is a statement label.", token, v);
2953
+ break;
2954
+ }
2955
+ } else if (funct["(global)"]) {
2956
+ // The name is not defined in the function. If we are in the global
2957
+ // scope, then we have an undefined variable.
2958
+ //
2959
+ // Operators typeof and delete do not raise runtime errors even if
2960
+ // the base object of a reference is null so no need to display warning
2961
+ // if we're inside of typeof or delete.
2962
+
2963
+ if (option.undef && typeof predefined[v] !== "boolean") {
2964
+ // Attempting to subscript a null reference will throw an
2965
+ // error, even within the typeof and delete operators
2966
+ if (!(anonname === "typeof" || anonname === "delete") ||
2967
+ (nexttoken && (nexttoken.value === "." || nexttoken.value === "["))) {
2968
+
2969
+ isundef(funct, "'{a}' is not defined.", token, v);
2970
+ }
2971
+ }
2972
+
2973
+ note_implied(token);
2974
+ } else {
2975
+ // If the name is already defined in the current
2976
+ // function, but not as outer, then there is a scope error.
2977
+
2978
+ switch (funct[v]) {
2979
+ case "closure":
2980
+ case "function":
2981
+ case "var":
2982
+ case "unused":
2983
+ warning("'{a}' used out of scope.", token, v);
2984
+ break;
2985
+ case "label":
2986
+ warning("'{a}' is a statement label.", token, v);
2987
+ break;
2988
+ case "outer":
2989
+ case "global":
2990
+ break;
2991
+ default:
2992
+ // If the name is defined in an outer function, make an outer entry,
2993
+ // and if it was unused, make it var.
2994
+ if (s === true) {
2995
+ funct[v] = true;
2996
+ } else if (s === null) {
2997
+ warning("'{a}' is not allowed.", token, v);
2998
+ note_implied(token);
2999
+ } else if (typeof s !== "object") {
3000
+ // Operators typeof and delete do not raise runtime errors even
3001
+ // if the base object of a reference is null so no need to
3002
+ // display warning if we're inside of typeof or delete.
3003
+ if (option.undef) {
3004
+ // Attempting to subscript a null reference will throw an
3005
+ // error, even within the typeof and delete operators
3006
+ if (!(anonname === "typeof" || anonname === "delete") ||
3007
+ (nexttoken &&
3008
+ (nexttoken.value === "." || nexttoken.value === "["))) {
3009
+
3010
+ isundef(funct, "'{a}' is not defined.", token, v);
3011
+ }
3012
+ }
3013
+ funct[v] = true;
3014
+ note_implied(token);
3015
+ } else {
3016
+ switch (s[v]) {
3017
+ case "function":
3018
+ case "unction":
3019
+ this["function"] = true;
3020
+ s[v] = "closure";
3021
+ funct[v] = s["(global)"] ? "global" : "outer";
3022
+ break;
3023
+ case "var":
3024
+ case "unused":
3025
+ s[v] = "closure";
3026
+ funct[v] = s["(global)"] ? "global" : "outer";
3027
+ break;
3028
+ case "closure":
3029
+ funct[v] = s["(global)"] ? "global" : "outer";
3030
+ break;
3031
+ case "label":
3032
+ warning("'{a}' is a statement label.", token, v);
3033
+ }
3034
+ }
3035
+ }
3036
+ }
3037
+ return this;
3038
+ },
3039
+ led: function () {
3040
+ error("Expected an operator and instead saw '{a}'.",
3041
+ nexttoken, nexttoken.value);
3042
+ }
3043
+ };
3044
+
3045
+ type("(regexp)", function () {
3046
+ return this;
3047
+ });
3048
+
3049
+
3050
+ // ECMAScript parser
3051
+
3052
+ delim("(endline)");
3053
+ delim("(begin)");
3054
+ delim("(end)").reach = true;
3055
+ delim("</").reach = true;
3056
+ delim("<!");
3057
+ delim("<!--");
3058
+ delim("-->");
3059
+ delim("(error)").reach = true;
3060
+ delim("}").reach = true;
3061
+ delim(")");
3062
+ delim("]");
3063
+ delim("\"").reach = true;
3064
+ delim("'").reach = true;
3065
+ delim(";");
3066
+ delim(":").reach = true;
3067
+ delim(",");
3068
+ delim("#");
3069
+ delim("@");
3070
+ reserve("else");
3071
+ reserve("case").reach = true;
3072
+ reserve("catch");
3073
+ reserve("default").reach = true;
3074
+ reserve("finally");
3075
+ reservevar("arguments", function (x) {
3076
+ if (directive["use strict"] && funct["(global)"]) {
3077
+ warning("Strict violation.", x);
3078
+ }
3079
+ });
3080
+ reservevar("eval");
3081
+ reservevar("false");
3082
+ reservevar("Infinity");
3083
+ reservevar("null");
3084
+ reservevar("this", function (x) {
3085
+ if (directive["use strict"] && !option.validthis && ((funct["(statement)"] &&
3086
+ funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
3087
+ warning("Possible strict violation.", x);
3088
+ }
3089
+ });
3090
+ reservevar("true");
3091
+ reservevar("undefined");
3092
+ assignop("=", "assign", 20);
3093
+ assignop("+=", "assignadd", 20);
3094
+ assignop("-=", "assignsub", 20);
3095
+ assignop("*=", "assignmult", 20);
3096
+ assignop("/=", "assigndiv", 20).nud = function () {
3097
+ error("A regular expression literal can be confused with '/='.");
3098
+ };
3099
+ assignop("%=", "assignmod", 20);
3100
+ bitwiseassignop("&=", "assignbitand", 20);
3101
+ bitwiseassignop("|=", "assignbitor", 20);
3102
+ bitwiseassignop("^=", "assignbitxor", 20);
3103
+ bitwiseassignop("<<=", "assignshiftleft", 20);
3104
+ bitwiseassignop(">>=", "assignshiftright", 20);
3105
+ bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
3106
+ infix("?", function (left, that) {
3107
+ that.left = left;
3108
+ that.right = expression(10);
3109
+ advance(":");
3110
+ that["else"] = expression(10);
3111
+ return that;
3112
+ }, 30);
3113
+
3114
+ infix("||", "or", 40);
3115
+ infix("&&", "and", 50);
3116
+ bitwise("|", "bitor", 70);
3117
+ bitwise("^", "bitxor", 80);
3118
+ bitwise("&", "bitand", 90);
3119
+ relation("==", function (left, right) {
3120
+ var eqnull = option.eqnull && (left.value === "null" || right.value === "null");
3121
+
3122
+ if (!eqnull && option.eqeqeq)
3123
+ warning("Expected '{a}' and instead saw '{b}'.", this, "===", "==");
3124
+ else if (isPoorRelation(left))
3125
+ warning("Use '{a}' to compare with '{b}'.", this, "===", left.value);
3126
+ else if (isPoorRelation(right))
3127
+ warning("Use '{a}' to compare with '{b}'.", this, "===", right.value);
3128
+
3129
+ return this;
3130
+ });
3131
+ relation("===");
3132
+ relation("!=", function (left, right) {
3133
+ var eqnull = option.eqnull &&
3134
+ (left.value === "null" || right.value === "null");
3135
+
3136
+ if (!eqnull && option.eqeqeq) {
3137
+ warning("Expected '{a}' and instead saw '{b}'.",
3138
+ this, "!==", "!=");
3139
+ } else if (isPoorRelation(left)) {
3140
+ warning("Use '{a}' to compare with '{b}'.",
3141
+ this, "!==", left.value);
3142
+ } else if (isPoorRelation(right)) {
3143
+ warning("Use '{a}' to compare with '{b}'.",
3144
+ this, "!==", right.value);
3145
+ }
3146
+ return this;
3147
+ });
3148
+ relation("!==");
3149
+ relation("<");
3150
+ relation(">");
3151
+ relation("<=");
3152
+ relation(">=");
3153
+ bitwise("<<", "shiftleft", 120);
3154
+ bitwise(">>", "shiftright", 120);
3155
+ bitwise(">>>", "shiftrightunsigned", 120);
3156
+ infix("in", "in", 120);
3157
+ infix("instanceof", "instanceof", 120);
3158
+ infix("+", function (left, that) {
3159
+ var right = expression(130);
3160
+ if (left && right && left.id === "(string)" && right.id === "(string)") {
3161
+ left.value += right.value;
3162
+ left.character = right.character;
3163
+ if (!option.scripturl && jx.test(left.value)) {
3164
+ warning("JavaScript URL.", left);
3165
+ }
3166
+ return left;
3167
+ }
3168
+ that.left = left;
3169
+ that.right = right;
3170
+ return that;
3171
+ }, 130);
3172
+ prefix("+", "num");
3173
+ prefix("+++", function () {
3174
+ warning("Confusing pluses.");
3175
+ this.right = expression(150);
3176
+ this.arity = "unary";
3177
+ return this;
3178
+ });
3179
+ infix("+++", function (left) {
3180
+ warning("Confusing pluses.");
3181
+ this.left = left;
3182
+ this.right = expression(130);
3183
+ return this;
3184
+ }, 130);
3185
+ infix("-", "sub", 130);
3186
+ prefix("-", "neg");
3187
+ prefix("---", function () {
3188
+ warning("Confusing minuses.");
3189
+ this.right = expression(150);
3190
+ this.arity = "unary";
3191
+ return this;
3192
+ });
3193
+ infix("---", function (left) {
3194
+ warning("Confusing minuses.");
3195
+ this.left = left;
3196
+ this.right = expression(130);
3197
+ return this;
3198
+ }, 130);
3199
+ infix("*", "mult", 140);
3200
+ infix("/", "div", 140);
3201
+ infix("%", "mod", 140);
3202
+
3203
+ suffix("++", "postinc");
3204
+ prefix("++", "preinc");
3205
+ syntax["++"].exps = true;
3206
+
3207
+ suffix("--", "postdec");
3208
+ prefix("--", "predec");
3209
+ syntax["--"].exps = true;
3210
+ prefix("delete", function () {
3211
+ var p = expression(0);
3212
+ if (!p || (p.id !== "." && p.id !== "[")) {
3213
+ warning("Variables should not be deleted.");
3214
+ }
3215
+ this.first = p;
3216
+ return this;
3217
+ }).exps = true;
3218
+
3219
+ prefix("~", function () {
3220
+ if (option.bitwise) {
3221
+ warning("Unexpected '{a}'.", this, "~");
3222
+ }
3223
+ expression(150);
3224
+ return this;
3225
+ });
3226
+
3227
+ prefix("!", function () {
3228
+ this.right = expression(150);
3229
+ this.arity = "unary";
3230
+ if (bang[this.right.id] === true) {
3231
+ warning("Confusing use of '{a}'.", this, "!");
3232
+ }
3233
+ return this;
3234
+ });
3235
+ prefix("typeof", "typeof");
3236
+ prefix("new", function () {
3237
+ var c = expression(155), i;
3238
+ if (c && c.id !== "function") {
3239
+ if (c.identifier) {
3240
+ c["new"] = true;
3241
+ switch (c.value) {
3242
+ case "Number":
3243
+ case "String":
3244
+ case "Boolean":
3245
+ case "Math":
3246
+ case "JSON":
3247
+ warning("Do not use {a} as a constructor.", prevtoken, c.value);
3248
+ break;
3249
+ case "Function":
3250
+ if (!option.evil) {
3251
+ warning("The Function constructor is eval.");
3252
+ }
3253
+ break;
3254
+ case "Date":
3255
+ case "RegExp":
3256
+ break;
3257
+ default:
3258
+ if (c.id !== "function") {
3259
+ i = c.value.substr(0, 1);
3260
+ if (option.newcap && (i < "A" || i > "Z") && !is_own(global, c.value)) {
3261
+ warning("A constructor name should start with an uppercase letter.",
3262
+ token);
3263
+ }
3264
+ }
3265
+ }
3266
+ } else {
3267
+ if (c.id !== "." && c.id !== "[" && c.id !== "(") {
3268
+ warning("Bad constructor.", token);
3269
+ }
3270
+ }
3271
+ } else {
3272
+ if (!option.supernew)
3273
+ warning("Weird construction. Delete 'new'.", this);
3274
+ }
3275
+ adjacent(token, nexttoken);
3276
+ if (nexttoken.id !== "(" && !option.supernew) {
3277
+ warning("Missing '()' invoking a constructor.",
3278
+ token, token.value);
3279
+ }
3280
+ this.first = c;
3281
+ return this;
3282
+ });
3283
+ syntax["new"].exps = true;
3284
+
3285
+ prefix("void").exps = true;
3286
+
3287
+ infix(".", function (left, that) {
3288
+ adjacent(prevtoken, token);
3289
+ nobreak();
3290
+ var m = identifier();
3291
+ if (typeof m === "string") {
3292
+ countMember(m);
3293
+ }
3294
+ that.left = left;
3295
+ that.right = m;
3296
+ if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
3297
+ if (option.noarg)
3298
+ warning("Avoid arguments.{a}.", left, m);
3299
+ else if (directive["use strict"])
3300
+ error("Strict violation.");
3301
+ } else if (!option.evil && left && left.value === "document" &&
3302
+ (m === "write" || m === "writeln")) {
3303
+ warning("document.write can be a form of eval.", left);
3304
+ }
3305
+ if (!option.evil && (m === "eval" || m === "execScript")) {
3306
+ warning("eval is evil.");
3307
+ }
3308
+ return that;
3309
+ }, 160, true);
3310
+
3311
+ infix("(", function (left, that) {
3312
+ if (prevtoken.id !== "}" && prevtoken.id !== ")") {
3313
+ nobreak(prevtoken, token);
3314
+ }
3315
+ nospace();
3316
+ if (option.immed && !left.immed && left.id === "function") {
3317
+ warning("Wrap an immediate function invocation in parentheses " +
3318
+ "to assist the reader in understanding that the expression " +
3319
+ "is the result of a function, and not the function itself.");
3320
+ }
3321
+ var n = 0,
3322
+ p = [];
3323
+ if (left) {
3324
+ if (left.type === "(identifier)") {
3325
+ if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
3326
+ if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
3327
+ if (left.value === "Math") {
3328
+ warning("Math is not a function.", left);
3329
+ } else if (option.newcap) {
3330
+ warning("Missing 'new' prefix when invoking a constructor.", left);
3331
+ }
3332
+ }
3333
+ }
3334
+ }
3335
+ }
3336
+ if (nexttoken.id !== ")") {
3337
+ for (;;) {
3338
+ p[p.length] = expression(10);
3339
+ n += 1;
3340
+ if (nexttoken.id !== ",") {
3341
+ break;
3342
+ }
3343
+ comma();
3344
+ }
3345
+ }
3346
+ advance(")");
3347
+ nospace(prevtoken, token);
3348
+ if (typeof left === "object") {
3349
+ if (left.value === "parseInt" && n === 1) {
3350
+ warning("Missing radix parameter.", token);
3351
+ }
3352
+ if (!option.evil) {
3353
+ if (left.value === "eval" || left.value === "Function" ||
3354
+ left.value === "execScript") {
3355
+ warning("eval is evil.", left);
3356
+
3357
+ if (p[0] && [0].id === "(string)") {
3358
+ addInternalSrc(left, p[0].value);
3359
+ }
3360
+ } else if (p[0] && p[0].id === "(string)" &&
3361
+ (left.value === "setTimeout" ||
3362
+ left.value === "setInterval")) {
3363
+ warning(
3364
+ "Implied eval is evil. Pass a function instead of a string.", left);
3365
+ addInternalSrc(left, p[0].value);
3366
+
3367
+ // window.setTimeout/setInterval
3368
+ } else if (p[0] && p[0].id === "(string)" &&
3369
+ left.value === "." &&
3370
+ left.left.value === "window" &&
3371
+ (left.right === "setTimeout" ||
3372
+ left.right === "setInterval")) {
3373
+ warning(
3374
+ "Implied eval is evil. Pass a function instead of a string.", left);
3375
+ addInternalSrc(left, p[0].value);
3376
+ }
3377
+ }
3378
+ if (!left.identifier && left.id !== "." && left.id !== "[" &&
3379
+ left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
3380
+ left.id !== "?") {
3381
+ warning("Bad invocation.", left);
3382
+ }
3383
+ }
3384
+ that.left = left;
3385
+ return that;
3386
+ }, 155, true).exps = true;
3387
+
3388
+ prefix("(", function () {
3389
+ nospace();
3390
+ if (nexttoken.id === "function") {
3391
+ nexttoken.immed = true;
3392
+ }
3393
+ var v = expression(0);
3394
+ advance(")", this);
3395
+ nospace(prevtoken, token);
3396
+ if (option.immed && v.id === "function") {
3397
+ if (nexttoken.id !== "(" &&
3398
+ (nexttoken.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
3399
+ warning(
3400
+ "Do not wrap function literals in parens unless they are to be immediately invoked.",
3401
+ this);
3402
+ }
3403
+ }
3404
+
3405
+ return v;
3406
+ });
3407
+
3408
+ infix("[", function (left, that) {
3409
+ nobreak(prevtoken, token);
3410
+ nospace();
3411
+ var e = expression(0), s;
3412
+ if (e && e.type === "(string)") {
3413
+ if (!option.evil && (e.value === "eval" || e.value === "execScript")) {
3414
+ warning("eval is evil.", that);
3415
+ }
3416
+ countMember(e.value);
3417
+ if (!option.sub && ix.test(e.value)) {
3418
+ s = syntax[e.value];
3419
+ if (!s || !s.reserved) {
3420
+ warning("['{a}'] is better written in dot notation.",
3421
+ prevtoken, e.value);
3422
+ }
3423
+ }
3424
+ }
3425
+ advance("]", that);
3426
+ nospace(prevtoken, token);
3427
+ that.left = left;
3428
+ that.right = e;
3429
+ return that;
3430
+ }, 160, true);
3431
+
3432
+ prefix("[", function () {
3433
+ var b = token.line !== nexttoken.line;
3434
+ this.first = [];
3435
+ if (b) {
3436
+ indent += option.indent;
3437
+ if (nexttoken.from === indent + option.indent) {
3438
+ indent += option.indent;
3439
+ }
3440
+ }
3441
+ while (nexttoken.id !== "(end)") {
3442
+ while (nexttoken.id === ",") {
3443
+ if (!option.es5)
3444
+ warning("Extra comma.");
3445
+ advance(",");
3446
+ }
3447
+ if (nexttoken.id === "]") {
3448
+ break;
3449
+ }
3450
+ if (b && token.line !== nexttoken.line) {
3451
+ indentation();
3452
+ }
3453
+ this.first.push(expression(10));
3454
+ if (nexttoken.id === ",") {
3455
+ comma();
3456
+ if (nexttoken.id === "]" && !option.es5) {
3457
+ warning("Extra comma.", token);
3458
+ break;
3459
+ }
3460
+ } else {
3461
+ break;
3462
+ }
3463
+ }
3464
+ if (b) {
3465
+ indent -= option.indent;
3466
+ indentation();
3467
+ }
3468
+ advance("]", this);
3469
+ return this;
3470
+ }, 160);
3471
+
3472
+
3473
+ function property_name() {
3474
+ var id = optionalidentifier(true);
3475
+ if (!id) {
3476
+ if (nexttoken.id === "(string)") {
3477
+ id = nexttoken.value;
3478
+ advance();
3479
+ } else if (nexttoken.id === "(number)") {
3480
+ id = nexttoken.value.toString();
3481
+ advance();
3482
+ }
3483
+ }
3484
+ return id;
3485
+ }
3486
+
3487
+
3488
+ function functionparams() {
3489
+ var next = nexttoken;
3490
+ var params = [];
3491
+ var ident;
3492
+
3493
+ advance("(");
3494
+ nospace();
3495
+
3496
+ if (nexttoken.id === ")") {
3497
+ advance(")");
3498
+ return;
3499
+ }
3500
+
3501
+ for (;;) {
3502
+ ident = identifier(true);
3503
+ params.push(ident);
3504
+ addlabel(ident, "unused", token);
3505
+ if (nexttoken.id === ",") {
3506
+ comma();
3507
+ } else {
3508
+ advance(")", next);
3509
+ nospace(prevtoken, token);
3510
+ return params;
3511
+ }
3512
+ }
3513
+ }
3514
+
3515
+
3516
+ function doFunction(name, statement) {
3517
+ var f;
3518
+ var oldOption = option;
3519
+ var oldScope = scope;
3520
+
3521
+ option = Object.create(option);
3522
+ scope = Object.create(scope);
3523
+
3524
+ funct = {
3525
+ "(name)" : name || "\"" + anonname + "\"",
3526
+ "(line)" : nexttoken.line,
3527
+ "(character)": nexttoken.character,
3528
+ "(context)" : funct,
3529
+ "(breakage)" : 0,
3530
+ "(loopage)" : 0,
3531
+ "(metrics)" : createMetrics(nexttoken),
3532
+ "(scope)" : scope,
3533
+ "(statement)": statement,
3534
+ "(tokens)" : {}
3535
+ };
3536
+
3537
+ f = funct;
3538
+ token.funct = funct;
3539
+
3540
+ functions.push(funct);
3541
+
3542
+ if (name) {
3543
+ addlabel(name, "function");
3544
+ }
3545
+
3546
+ funct["(params)"] = functionparams();
3547
+ funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
3548
+
3549
+ block(false, false, true);
3550
+
3551
+ funct["(metrics)"].verifyMaxStatementsPerFunction();
3552
+ funct["(metrics)"].verifyMaxComplexityPerFunction();
3553
+
3554
+ scope = oldScope;
3555
+ option = oldOption;
3556
+ funct["(last)"] = token.line;
3557
+ funct["(lastcharacter)"] = token.character;
3558
+ funct = funct["(context)"];
3559
+
3560
+ return f;
3561
+ }
3562
+
3563
+ function createMetrics(functionStartToken) {
3564
+ return {
3565
+ statementCount: 0,
3566
+ nestedBlockDepth: -1,
3567
+ ComplexityCount: 1,
3568
+ verifyMaxStatementsPerFunction: function () {
3569
+ if (option.maxstatements &&
3570
+ this.statementCount > option.maxstatements) {
3571
+ var message = "Too many statements per function (" + this.statementCount + ").";
3572
+ warning(message, functionStartToken);
3573
+ }
3574
+ },
3575
+
3576
+ verifyMaxParametersPerFunction: function (params) {
3577
+ params = params || [];
3578
+
3579
+ if (option.maxparams && params.length > option.maxparams) {
3580
+ var message = "Too many parameters per function (" + params.length + ").";
3581
+ warning(message, functionStartToken);
3582
+ }
3583
+ },
3584
+
3585
+ verifyMaxNestedBlockDepthPerFunction: function () {
3586
+ if (option.maxdepth &&
3587
+ this.nestedBlockDepth > 0 &&
3588
+ this.nestedBlockDepth === option.maxdepth + 1) {
3589
+ var message = "Blocks are nested too deeply (" + this.nestedBlockDepth + ").";
3590
+ warning(message);
3591
+ }
3592
+ },
3593
+
3594
+ verifyMaxComplexityPerFunction: function () {
3595
+ var max = option.maxcomplexity;
3596
+ var cc = this.ComplexityCount;
3597
+ if (max && cc > max) {
3598
+ var message = "Cyclomatic complexity is too high per function (" + cc + ").";
3599
+ warning(message, functionStartToken);
3600
+ }
3601
+ }
3602
+ };
3603
+ }
3604
+
3605
+ function increaseComplexityCount() {
3606
+ funct["(metrics)"].ComplexityCount += 1;
3607
+ }
3608
+
3609
+
3610
+ (function (x) {
3611
+ x.nud = function () {
3612
+ var b, f, i, p, t;
3613
+ var props = {}; // All properties, including accessors
3614
+
3615
+ function saveProperty(name, token) {
3616
+ if (props[name] && is_own(props, name))
3617
+ warning("Duplicate member '{a}'.", nexttoken, i);
3618
+ else
3619
+ props[name] = {};
3620
+
3621
+ props[name].basic = true;
3622
+ props[name].basicToken = token;
3623
+ }
3624
+
3625
+ function saveSetter(name, token) {
3626
+ if (props[name] && is_own(props, name)) {
3627
+ if (props[name].basic || props[name].setter)
3628
+ warning("Duplicate member '{a}'.", nexttoken, i);
3629
+ } else {
3630
+ props[name] = {};
3631
+ }
3632
+
3633
+ props[name].setter = true;
3634
+ props[name].setterToken = token;
3635
+ }
3636
+
3637
+ function saveGetter(name) {
3638
+ if (props[name] && is_own(props, name)) {
3639
+ if (props[name].basic || props[name].getter)
3640
+ warning("Duplicate member '{a}'.", nexttoken, i);
3641
+ } else {
3642
+ props[name] = {};
3643
+ }
3644
+
3645
+ props[name].getter = true;
3646
+ props[name].getterToken = token;
3647
+ }
3648
+
3649
+ b = token.line !== nexttoken.line;
3650
+ if (b) {
3651
+ indent += option.indent;
3652
+ if (nexttoken.from === indent + option.indent) {
3653
+ indent += option.indent;
3654
+ }
3655
+ }
3656
+ for (;;) {
3657
+ if (nexttoken.id === "}") {
3658
+ break;
3659
+ }
3660
+ if (b) {
3661
+ indentation();
3662
+ }
3663
+ if (nexttoken.value === "get" && peek().id !== ":") {
3664
+ advance("get");
3665
+ if (!option.es5) {
3666
+ error("get/set are ES5 features.");
3667
+ }
3668
+ i = property_name();
3669
+ if (!i) {
3670
+ error("Missing property name.");
3671
+ }
3672
+ saveGetter(i);
3673
+ t = nexttoken;
3674
+ adjacent(token, nexttoken);
3675
+ f = doFunction();
3676
+ p = f["(params)"];
3677
+ if (p) {
3678
+ warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i);
3679
+ }
3680
+ adjacent(token, nexttoken);
3681
+ } else if (nexttoken.value === "set" && peek().id !== ":") {
3682
+ advance("set");
3683
+ if (!option.es5) {
3684
+ error("get/set are ES5 features.");
3685
+ }
3686
+ i = property_name();
3687
+ if (!i) {
3688
+ error("Missing property name.");
3689
+ }
3690
+ saveSetter(i, nexttoken);
3691
+ t = nexttoken;
3692
+ adjacent(token, nexttoken);
3693
+ f = doFunction();
3694
+ p = f["(params)"];
3695
+ if (!p || p.length !== 1) {
3696
+ warning("Expected a single parameter in set {a} function.", t, i);
3697
+ }
3698
+ } else {
3699
+ i = property_name();
3700
+ saveProperty(i, nexttoken);
3701
+ if (typeof i !== "string") {
3702
+ break;
3703
+ }
3704
+ advance(":");
3705
+ nonadjacent(token, nexttoken);
3706
+ expression(10);
3707
+ }
3708
+
3709
+ countMember(i);
3710
+ if (nexttoken.id === ",") {
3711
+ comma();
3712
+ if (nexttoken.id === ",") {
3713
+ warning("Extra comma.", token);
3714
+ } else if (nexttoken.id === "}" && !option.es5) {
3715
+ warning("Extra comma.", token);
3716
+ }
3717
+ } else {
3718
+ break;
3719
+ }
3720
+ }
3721
+ if (b) {
3722
+ indent -= option.indent;
3723
+ indentation();
3724
+ }
3725
+ advance("}", this);
3726
+
3727
+ // Check for lonely setters if in the ES5 mode.
3728
+ if (option.es5) {
3729
+ for (var name in props) {
3730
+ if (is_own(props, name) && props[name].setter && !props[name].getter) {
3731
+ warning("Setter is defined without getter.", props[name].setterToken);
3732
+ }
3733
+ }
3734
+ }
3735
+ return this;
3736
+ };
3737
+ x.fud = function () {
3738
+ error("Expected to see a statement and instead saw a block.", token);
3739
+ };
3740
+ }(delim("{")));
3741
+
3742
+ // This Function is called when esnext option is set to true
3743
+ // it adds the `const` statement to JSHINT
3744
+
3745
+ useESNextSyntax = function () {
3746
+ var conststatement = stmt("const", function (prefix) {
3747
+ var id, name, value;
3748
+
3749
+ this.first = [];
3750
+ for (;;) {
3751
+ nonadjacent(token, nexttoken);
3752
+ id = identifier();
3753
+ if (funct[id] === "const") {
3754
+ warning("const '" + id + "' has already been declared");
3755
+ }
3756
+ if (funct["(global)"] && predefined[id] === false) {
3757
+ warning("Redefinition of '{a}'.", token, id);
3758
+ }
3759
+ addlabel(id, "const");
3760
+ if (prefix) {
3761
+ break;
3762
+ }
3763
+ name = token;
3764
+ this.first.push(token);
3765
+
3766
+ if (nexttoken.id !== "=") {
3767
+ warning("const " +
3768
+ "'{a}' is initialized to 'undefined'.", token, id);
3769
+ }
3770
+
3771
+ if (nexttoken.id === "=") {
3772
+ nonadjacent(token, nexttoken);
3773
+ advance("=");
3774
+ nonadjacent(token, nexttoken);
3775
+ if (nexttoken.id === "undefined") {
3776
+ warning("It is not necessary to initialize " +
3777
+ "'{a}' to 'undefined'.", token, id);
3778
+ }
3779
+ if (peek(0).id === "=" && nexttoken.identifier) {
3780
+ error("Constant {a} was not declared correctly.",
3781
+ nexttoken, nexttoken.value);
3782
+ }
3783
+ value = expression(0);
3784
+ name.first = value;
3785
+ }
3786
+
3787
+ if (nexttoken.id !== ",") {
3788
+ break;
3789
+ }
3790
+ comma();
3791
+ }
3792
+ return this;
3793
+ });
3794
+ conststatement.exps = true;
3795
+ };
3796
+
3797
+ var varstatement = stmt("var", function (prefix) {
3798
+ // JavaScript does not have block scope. It only has function scope. So,
3799
+ // declaring a variable in a block can have unexpected consequences.
3800
+ var id, name, value;
3801
+
3802
+ if (funct["(onevar)"] && option.onevar) {
3803
+ warning("Too many var statements.");
3804
+ } else if (!funct["(global)"]) {
3805
+ funct["(onevar)"] = true;
3806
+ }
3807
+
3808
+ this.first = [];
3809
+
3810
+ for (;;) {
3811
+ nonadjacent(token, nexttoken);
3812
+ id = identifier();
3813
+
3814
+ if (option.esnext && funct[id] === "const") {
3815
+ warning("const '" + id + "' has already been declared");
3816
+ }
3817
+
3818
+ if (funct["(global)"] && predefined[id] === false) {
3819
+ warning("Redefinition of '{a}'.", token, id);
3820
+ }
3821
+
3822
+ addlabel(id, "unused", token);
3823
+
3824
+ if (prefix) {
3825
+ break;
3826
+ }
3827
+
3828
+ name = token;
3829
+ this.first.push(token);
3830
+
3831
+ if (nexttoken.id === "=") {
3832
+ nonadjacent(token, nexttoken);
3833
+ advance("=");
3834
+ nonadjacent(token, nexttoken);
3835
+ if (nexttoken.id === "undefined") {
3836
+ warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id);
3837
+ }
3838
+ if (peek(0).id === "=" && nexttoken.identifier) {
3839
+ error("Variable {a} was not declared correctly.",
3840
+ nexttoken, nexttoken.value);
3841
+ }
3842
+ value = expression(0);
3843
+ name.first = value;
3844
+ }
3845
+ if (nexttoken.id !== ",") {
3846
+ break;
3847
+ }
3848
+ comma();
3849
+ }
3850
+ return this;
3851
+ });
3852
+ varstatement.exps = true;
3853
+
3854
+ blockstmt("function", function () {
3855
+ if (inblock) {
3856
+ warning("Function declarations should not be placed in blocks. " +
3857
+ "Use a function expression or move the statement to the top of " +
3858
+ "the outer function.", token);
3859
+
3860
+ }
3861
+ var i = identifier();
3862
+ if (option.esnext && funct[i] === "const") {
3863
+ warning("const '" + i + "' has already been declared");
3864
+ }
3865
+ adjacent(token, nexttoken);
3866
+ addlabel(i, "unction", token);
3867
+
3868
+ doFunction(i, { statement: true });
3869
+ if (nexttoken.id === "(" && nexttoken.line === token.line) {
3870
+ error(
3871
+ "Function declarations are not invocable. Wrap the whole function invocation in parens.");
3872
+ }
3873
+ return this;
3874
+ });
3875
+
3876
+ prefix("function", function () {
3877
+ var i = optionalidentifier();
3878
+ if (i) {
3879
+ adjacent(token, nexttoken);
3880
+ } else {
3881
+ nonadjacent(token, nexttoken);
3882
+ }
3883
+ doFunction(i);
3884
+ if (!option.loopfunc && funct["(loopage)"]) {
3885
+ warning("Don't make functions within a loop.");
3886
+ }
3887
+ return this;
3888
+ });
3889
+
3890
+ blockstmt("if", function () {
3891
+ var t = nexttoken;
3892
+ increaseComplexityCount();
3893
+ advance("(");
3894
+ nonadjacent(this, t);
3895
+ nospace();
3896
+ expression(20);
3897
+ if (nexttoken.id === "=") {
3898
+ if (!option.boss)
3899
+ warning("Expected a conditional expression and instead saw an assignment.");
3900
+ advance("=");
3901
+ expression(20);
3902
+ }
3903
+ advance(")", t);
3904
+ nospace(prevtoken, token);
3905
+ block(true, true);
3906
+ if (nexttoken.id === "else") {
3907
+ nonadjacent(token, nexttoken);
3908
+ advance("else");
3909
+ if (nexttoken.id === "if" || nexttoken.id === "switch") {
3910
+ statement(true);
3911
+ } else {
3912
+ block(true, true);
3913
+ }
3914
+ }
3915
+ return this;
3916
+ });
3917
+
3918
+ blockstmt("try", function () {
3919
+ var b;
3920
+
3921
+ function doCatch() {
3922
+ var oldScope = scope;
3923
+ var e;
3924
+
3925
+ advance("catch");
3926
+ nonadjacent(token, nexttoken);
3927
+ advance("(");
3928
+
3929
+ scope = Object.create(oldScope);
3930
+
3931
+ e = nexttoken.value;
3932
+ if (nexttoken.type !== "(identifier)") {
3933
+ e = null;
3934
+ warning("Expected an identifier and instead saw '{a}'.", nexttoken, e);
3935
+ }
3936
+
3937
+ advance();
3938
+ advance(")");
3939
+
3940
+ funct = {
3941
+ "(name)" : "(catch)",
3942
+ "(line)" : nexttoken.line,
3943
+ "(character)": nexttoken.character,
3944
+ "(context)" : funct,
3945
+ "(breakage)" : funct["(breakage)"],
3946
+ "(loopage)" : funct["(loopage)"],
3947
+ "(scope)" : scope,
3948
+ "(statement)": false,
3949
+ "(metrics)" : createMetrics(nexttoken),
3950
+ "(catch)" : true,
3951
+ "(tokens)" : {}
3952
+ };
3953
+
3954
+ if (e) {
3955
+ addlabel(e, "exception");
3956
+ }
3957
+
3958
+ token.funct = funct;
3959
+ functions.push(funct);
3960
+
3961
+ block(false);
3962
+
3963
+ scope = oldScope;
3964
+
3965
+ funct["(last)"] = token.line;
3966
+ funct["(lastcharacter)"] = token.character;
3967
+ funct = funct["(context)"];
3968
+ }
3969
+
3970
+ block(false);
3971
+
3972
+ if (nexttoken.id === "catch") {
3973
+ increaseComplexityCount();
3974
+ doCatch();
3975
+ b = true;
3976
+ }
3977
+
3978
+ if (nexttoken.id === "finally") {
3979
+ advance("finally");
3980
+ block(false);
3981
+ return;
3982
+ } else if (!b) {
3983
+ error("Expected '{a}' and instead saw '{b}'.",
3984
+ nexttoken, "catch", nexttoken.value);
3985
+ }
3986
+
3987
+ return this;
3988
+ });
3989
+
3990
+ blockstmt("while", function () {
3991
+ var t = nexttoken;
3992
+ funct["(breakage)"] += 1;
3993
+ funct["(loopage)"] += 1;
3994
+ increaseComplexityCount();
3995
+ advance("(");
3996
+ nonadjacent(this, t);
3997
+ nospace();
3998
+ expression(20);
3999
+ if (nexttoken.id === "=") {
4000
+ if (!option.boss)
4001
+ warning("Expected a conditional expression and instead saw an assignment.");
4002
+ advance("=");
4003
+ expression(20);
4004
+ }
4005
+ advance(")", t);
4006
+ nospace(prevtoken, token);
4007
+ block(true, true);
4008
+ funct["(breakage)"] -= 1;
4009
+ funct["(loopage)"] -= 1;
4010
+ return this;
4011
+ }).labelled = true;
4012
+
4013
+ blockstmt("with", function () {
4014
+ var t = nexttoken;
4015
+ if (directive["use strict"]) {
4016
+ error("'with' is not allowed in strict mode.", token);
4017
+ } else if (!option.withstmt) {
4018
+ warning("Don't use 'with'.", token);
4019
+ }
4020
+
4021
+ advance("(");
4022
+ nonadjacent(this, t);
4023
+ nospace();
4024
+ expression(0);
4025
+ advance(")", t);
4026
+ nospace(prevtoken, token);
4027
+ block(true, true);
4028
+
4029
+ return this;
4030
+ });
4031
+
4032
+ blockstmt("switch", function () {
4033
+ var t = nexttoken,
4034
+ g = false;
4035
+ funct["(breakage)"] += 1;
4036
+ advance("(");
4037
+ nonadjacent(this, t);
4038
+ nospace();
4039
+ this.condition = expression(20);
4040
+ advance(")", t);
4041
+ nospace(prevtoken, token);
4042
+ nonadjacent(token, nexttoken);
4043
+ t = nexttoken;
4044
+ advance("{");
4045
+ nonadjacent(token, nexttoken);
4046
+ indent += option.indent;
4047
+ this.cases = [];
4048
+ for (;;) {
4049
+ switch (nexttoken.id) {
4050
+ case "case":
4051
+ switch (funct["(verb)"]) {
4052
+ case "break":
4053
+ case "case":
4054
+ case "continue":
4055
+ case "return":
4056
+ case "switch":
4057
+ case "throw":
4058
+ break;
4059
+ default:
4060
+ // You can tell JSHint that you don't use break intentionally by
4061
+ // adding a comment /* falls through */ on a line just before
4062
+ // the next `case`.
4063
+ if (!ft.test(lines[nexttoken.line - 2])) {
4064
+ warning(
4065
+ "Expected a 'break' statement before 'case'.",
4066
+ token);
4067
+ }
4068
+ }
4069
+ indentation(-option.indent);
4070
+ advance("case");
4071
+ this.cases.push(expression(20));
4072
+ increaseComplexityCount();
4073
+ g = true;
4074
+ advance(":");
4075
+ funct["(verb)"] = "case";
4076
+ break;
4077
+ case "default":
4078
+ switch (funct["(verb)"]) {
4079
+ case "break":
4080
+ case "continue":
4081
+ case "return":
4082
+ case "throw":
4083
+ break;
4084
+ default:
4085
+ if (!ft.test(lines[nexttoken.line - 2])) {
4086
+ warning(
4087
+ "Expected a 'break' statement before 'default'.",
4088
+ token);
4089
+ }
4090
+ }
4091
+ indentation(-option.indent);
4092
+ advance("default");
4093
+ g = true;
4094
+ advance(":");
4095
+ break;
4096
+ case "}":
4097
+ indent -= option.indent;
4098
+ indentation();
4099
+ advance("}", t);
4100
+ if (this.cases.length === 1 || this.condition.id === "true" ||
4101
+ this.condition.id === "false") {
4102
+ if (!option.onecase)
4103
+ warning("This 'switch' should be an 'if'.", this);
4104
+ }
4105
+ funct["(breakage)"] -= 1;
4106
+ funct["(verb)"] = undefined;
4107
+ return;
4108
+ case "(end)":
4109
+ error("Missing '{a}'.", nexttoken, "}");
4110
+ return;
4111
+ default:
4112
+ if (g) {
4113
+ switch (token.id) {
4114
+ case ",":
4115
+ error("Each value should have its own case label.");
4116
+ return;
4117
+ case ":":
4118
+ g = false;
4119
+ statements();
4120
+ break;
4121
+ default:
4122
+ error("Missing ':' on a case clause.", token);
4123
+ return;
4124
+ }
4125
+ } else {
4126
+ if (token.id === ":") {
4127
+ advance(":");
4128
+ error("Unexpected '{a}'.", token, ":");
4129
+ statements();
4130
+ } else {
4131
+ error("Expected '{a}' and instead saw '{b}'.",
4132
+ nexttoken, "case", nexttoken.value);
4133
+ return;
4134
+ }
4135
+ }
4136
+ }
4137
+ }
4138
+ }).labelled = true;
4139
+
4140
+ stmt("debugger", function () {
4141
+ if (!option.debug) {
4142
+ warning("All 'debugger' statements should be removed.");
4143
+ }
4144
+ return this;
4145
+ }).exps = true;
4146
+
4147
+ (function () {
4148
+ var x = stmt("do", function () {
4149
+ funct["(breakage)"] += 1;
4150
+ funct["(loopage)"] += 1;
4151
+ increaseComplexityCount();
4152
+
4153
+ this.first = block(true);
4154
+ advance("while");
4155
+ var t = nexttoken;
4156
+ nonadjacent(token, t);
4157
+ advance("(");
4158
+ nospace();
4159
+ expression(20);
4160
+ if (nexttoken.id === "=") {
4161
+ if (!option.boss)
4162
+ warning("Expected a conditional expression and instead saw an assignment.");
4163
+ advance("=");
4164
+ expression(20);
4165
+ }
4166
+ advance(")", t);
4167
+ nospace(prevtoken, token);
4168
+ funct["(breakage)"] -= 1;
4169
+ funct["(loopage)"] -= 1;
4170
+ return this;
4171
+ });
4172
+ x.labelled = true;
4173
+ x.exps = true;
4174
+ }());
4175
+
4176
+ blockstmt("for", function () {
4177
+ var s, t = nexttoken;
4178
+ funct["(breakage)"] += 1;
4179
+ funct["(loopage)"] += 1;
4180
+ increaseComplexityCount();
4181
+ advance("(");
4182
+ nonadjacent(this, t);
4183
+ nospace();
4184
+ if (peek(nexttoken.id === "var" ? 1 : 0).id === "in") {
4185
+ if (nexttoken.id === "var") {
4186
+ advance("var");
4187
+ varstatement.fud.call(varstatement, true);
4188
+ } else {
4189
+ switch (funct[nexttoken.value]) {
4190
+ case "unused":
4191
+ funct[nexttoken.value] = "var";
4192
+ break;
4193
+ case "var":
4194
+ break;
4195
+ default:
4196
+ warning("Bad for in variable '{a}'.",
4197
+ nexttoken, nexttoken.value);
4198
+ }
4199
+ advance();
4200
+ }
4201
+ advance("in");
4202
+ expression(20);
4203
+ advance(")", t);
4204
+ s = block(true, true);
4205
+ if (option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
4206
+ s[0].value !== "if")) {
4207
+ warning("The body of a for in should be wrapped in an if statement to filter " +
4208
+ "unwanted properties from the prototype.", this);
4209
+ }
4210
+ funct["(breakage)"] -= 1;
4211
+ funct["(loopage)"] -= 1;
4212
+ return this;
4213
+ } else {
4214
+ if (nexttoken.id !== ";") {
4215
+ if (nexttoken.id === "var") {
4216
+ advance("var");
4217
+ varstatement.fud.call(varstatement);
4218
+ } else {
4219
+ for (;;) {
4220
+ expression(0, "for");
4221
+ if (nexttoken.id !== ",") {
4222
+ break;
4223
+ }
4224
+ comma();
4225
+ }
4226
+ }
4227
+ }
4228
+ nolinebreak(token);
4229
+ advance(";");
4230
+ if (nexttoken.id !== ";") {
4231
+ expression(20);
4232
+ if (nexttoken.id === "=") {
4233
+ if (!option.boss)
4234
+ warning("Expected a conditional expression and instead saw an assignment.");
4235
+ advance("=");
4236
+ expression(20);
4237
+ }
4238
+ }
4239
+ nolinebreak(token);
4240
+ advance(";");
4241
+ if (nexttoken.id === ";") {
4242
+ error("Expected '{a}' and instead saw '{b}'.",
4243
+ nexttoken, ")", ";");
4244
+ }
4245
+ if (nexttoken.id !== ")") {
4246
+ for (;;) {
4247
+ expression(0, "for");
4248
+ if (nexttoken.id !== ",") {
4249
+ break;
4250
+ }
4251
+ comma();
4252
+ }
4253
+ }
4254
+ advance(")", t);
4255
+ nospace(prevtoken, token);
4256
+ block(true, true);
4257
+ funct["(breakage)"] -= 1;
4258
+ funct["(loopage)"] -= 1;
4259
+ return this;
4260
+ }
4261
+ }).labelled = true;
4262
+
4263
+
4264
+ stmt("break", function () {
4265
+ var v = nexttoken.value;
4266
+
4267
+ if (funct["(breakage)"] === 0)
4268
+ warning("Unexpected '{a}'.", nexttoken, this.value);
4269
+
4270
+ if (!option.asi)
4271
+ nolinebreak(this);
4272
+
4273
+ if (nexttoken.id !== ";") {
4274
+ if (token.line === nexttoken.line) {
4275
+ if (funct[v] !== "label") {
4276
+ warning("'{a}' is not a statement label.", nexttoken, v);
4277
+ } else if (scope[v] !== funct) {
4278
+ warning("'{a}' is out of scope.", nexttoken, v);
4279
+ }
4280
+ this.first = nexttoken;
4281
+ advance();
4282
+ }
4283
+ }
4284
+ reachable("break");
4285
+ return this;
4286
+ }).exps = true;
4287
+
4288
+
4289
+ stmt("continue", function () {
4290
+ var v = nexttoken.value;
4291
+
4292
+ if (funct["(breakage)"] === 0)
4293
+ warning("Unexpected '{a}'.", nexttoken, this.value);
4294
+
4295
+ if (!option.asi)
4296
+ nolinebreak(this);
4297
+
4298
+ if (nexttoken.id !== ";") {
4299
+ if (token.line === nexttoken.line) {
4300
+ if (funct[v] !== "label") {
4301
+ warning("'{a}' is not a statement label.", nexttoken, v);
4302
+ } else if (scope[v] !== funct) {
4303
+ warning("'{a}' is out of scope.", nexttoken, v);
4304
+ }
4305
+ this.first = nexttoken;
4306
+ advance();
4307
+ }
4308
+ } else if (!funct["(loopage)"]) {
4309
+ warning("Unexpected '{a}'.", nexttoken, this.value);
4310
+ }
4311
+ reachable("continue");
4312
+ return this;
4313
+ }).exps = true;
4314
+
4315
+
4316
+ stmt("return", function () {
4317
+ if (this.line === nexttoken.line) {
4318
+ if (nexttoken.id === "(regexp)")
4319
+ warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");
4320
+
4321
+ if (nexttoken.id !== ";" && !nexttoken.reach) {
4322
+ nonadjacent(token, nexttoken);
4323
+ if (peek().value === "=" && !option.boss) {
4324
+ warningAt("Did you mean to return a conditional instead of an assignment?",
4325
+ token.line, token.character + 1);
4326
+ }
4327
+ this.first = expression(0);
4328
+ }
4329
+ } else if (!option.asi) {
4330
+ nolinebreak(this); // always warn (Line breaking error)
4331
+ }
4332
+ reachable("return");
4333
+ return this;
4334
+ }).exps = true;
4335
+
4336
+
4337
+ stmt("throw", function () {
4338
+ nolinebreak(this);
4339
+ nonadjacent(token, nexttoken);
4340
+ this.first = expression(20);
4341
+ reachable("throw");
4342
+ return this;
4343
+ }).exps = true;
4344
+
4345
+ // Superfluous reserved words
4346
+
4347
+ reserve("class");
4348
+ reserve("const");
4349
+ reserve("enum");
4350
+ reserve("export");
4351
+ reserve("extends");
4352
+ reserve("import");
4353
+ reserve("super");
4354
+
4355
+ reserve("let");
4356
+ reserve("yield");
4357
+ reserve("implements");
4358
+ reserve("interface");
4359
+ reserve("package");
4360
+ reserve("private");
4361
+ reserve("protected");
4362
+ reserve("public");
4363
+ reserve("static");
4364
+
4365
+
4366
+ // Parse JSON
4367
+
4368
+ function jsonValue() {
4369
+
4370
+ function jsonObject() {
4371
+ var o = {}, t = nexttoken;
4372
+ advance("{");
4373
+ if (nexttoken.id !== "}") {
4374
+ for (;;) {
4375
+ if (nexttoken.id === "(end)") {
4376
+ error("Missing '}' to match '{' from line {a}.",
4377
+ nexttoken, t.line);
4378
+ } else if (nexttoken.id === "}") {
4379
+ warning("Unexpected comma.", token);
4380
+ break;
4381
+ } else if (nexttoken.id === ",") {
4382
+ error("Unexpected comma.", nexttoken);
4383
+ } else if (nexttoken.id !== "(string)") {
4384
+ warning("Expected a string and instead saw {a}.",
4385
+ nexttoken, nexttoken.value);
4386
+ }
4387
+ if (o[nexttoken.value] === true) {
4388
+ warning("Duplicate key '{a}'.",
4389
+ nexttoken, nexttoken.value);
4390
+ } else if ((nexttoken.value === "__proto__" &&
4391
+ !option.proto) || (nexttoken.value === "__iterator__" &&
4392
+ !option.iterator)) {
4393
+ warning("The '{a}' key may produce unexpected results.",
4394
+ nexttoken, nexttoken.value);
4395
+ } else {
4396
+ o[nexttoken.value] = true;
4397
+ }
4398
+ advance();
4399
+ advance(":");
4400
+ jsonValue();
4401
+ if (nexttoken.id !== ",") {
4402
+ break;
4403
+ }
4404
+ advance(",");
4405
+ }
4406
+ }
4407
+ advance("}");
4408
+ }
4409
+
4410
+ function jsonArray() {
4411
+ var t = nexttoken;
4412
+ advance("[");
4413
+ if (nexttoken.id !== "]") {
4414
+ for (;;) {
4415
+ if (nexttoken.id === "(end)") {
4416
+ error("Missing ']' to match '[' from line {a}.",
4417
+ nexttoken, t.line);
4418
+ } else if (nexttoken.id === "]") {
4419
+ warning("Unexpected comma.", token);
4420
+ break;
4421
+ } else if (nexttoken.id === ",") {
4422
+ error("Unexpected comma.", nexttoken);
4423
+ }
4424
+ jsonValue();
4425
+ if (nexttoken.id !== ",") {
4426
+ break;
4427
+ }
4428
+ advance(",");
4429
+ }
4430
+ }
4431
+ advance("]");
4432
+ }
4433
+
4434
+ switch (nexttoken.id) {
4435
+ case "{":
4436
+ jsonObject();
4437
+ break;
4438
+ case "[":
4439
+ jsonArray();
4440
+ break;
4441
+ case "true":
4442
+ case "false":
4443
+ case "null":
4444
+ case "(number)":
4445
+ case "(string)":
4446
+ advance();
4447
+ break;
4448
+ case "-":
4449
+ advance("-");
4450
+ if (token.character !== nexttoken.from) {
4451
+ warning("Unexpected space after '-'.", token);
4452
+ }
4453
+ adjacent(token, nexttoken);
4454
+ advance("(number)");
4455
+ break;
4456
+ default:
4457
+ error("Expected a JSON value.", nexttoken);
4458
+ }
4459
+ }
4460
+
4461
+
4462
+ // The actual JSHINT function itself.
4463
+ var itself = function (s, o, g) {
4464
+ var a, i, k, x;
4465
+ var optionKeys;
4466
+ var newOptionObj = {};
4467
+
4468
+ if (o && o.scope) {
4469
+ JSHINT.scope = o.scope;
4470
+ } else {
4471
+ JSHINT.errors = [];
4472
+ JSHINT.undefs = [];
4473
+ JSHINT.internals = [];
4474
+ JSHINT.blacklist = {};
4475
+ JSHINT.scope = "(main)";
4476
+ }
4477
+
4478
+ predefined = Object.create(standard);
4479
+ declared = Object.create(null);
4480
+ combine(predefined, g || {});
4481
+
4482
+ if (o) {
4483
+ a = o.predef;
4484
+ if (a) {
4485
+ if (!Array.isArray(a) && typeof a === "object") {
4486
+ a = Object.keys(a);
4487
+ }
4488
+ a.forEach(function (item) {
4489
+ var slice;
4490
+ if (item[0] === "-") {
4491
+ slice = item.slice(1);
4492
+ JSHINT.blacklist[slice] = slice;
4493
+ } else {
4494
+ predefined[item] = true;
4495
+ }
4496
+ });
4497
+ }
4498
+
4499
+ optionKeys = Object.keys(o);
4500
+ for (x = 0; x < optionKeys.length; x++) {
4501
+ newOptionObj[optionKeys[x]] = o[optionKeys[x]];
4502
+
4503
+ if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
4504
+ newOptionObj["(explicitNewcap)"] = true;
4505
+
4506
+ if (optionKeys[x] === "indent")
4507
+ newOptionObj.white = true;
4508
+ }
4509
+ }
4510
+
4511
+ option = newOptionObj;
4512
+
4513
+ option.indent = option.indent || 4;
4514
+ option.maxerr = option.maxerr || 50;
4515
+
4516
+ tab = "";
4517
+ for (i = 0; i < option.indent; i += 1) {
4518
+ tab += " ";
4519
+ }
4520
+ indent = 1;
4521
+ global = Object.create(predefined);
4522
+ scope = global;
4523
+ funct = {
4524
+ "(global)": true,
4525
+ "(name)": "(global)",
4526
+ "(scope)": scope,
4527
+ "(breakage)": 0,
4528
+ "(loopage)": 0,
4529
+ "(tokens)": {},
4530
+ "(metrics)": createMetrics(nexttoken)
4531
+ };
4532
+ functions = [funct];
4533
+ urls = [];
4534
+ stack = null;
4535
+ member = {};
4536
+ membersOnly = null;
4537
+ implied = {};
4538
+ inblock = false;
4539
+ lookahead = [];
4540
+ jsonmode = false;
4541
+ warnings = 0;
4542
+ lines = [];
4543
+ unuseds = [];
4544
+
4545
+ if (!isString(s) && !Array.isArray(s)) {
4546
+ errorAt("Input is neither a string nor an array of strings.", 0);
4547
+ return false;
4548
+ }
4549
+
4550
+ if (isString(s) && /^\s*$/g.test(s)) {
4551
+ errorAt("Input is an empty string.", 0);
4552
+ return false;
4553
+ }
4554
+
4555
+ if (s.length === 0) {
4556
+ errorAt("Input is an empty array.", 0);
4557
+ return false;
4558
+ }
4559
+
4560
+ lex.init(s);
4561
+
4562
+ prereg = true;
4563
+ directive = {};
4564
+
4565
+ prevtoken = token = nexttoken = syntax["(begin)"];
4566
+
4567
+ // Check options
4568
+ for (var name in o) {
4569
+ if (is_own(o, name)) {
4570
+ checkOption(name, token);
4571
+ }
4572
+ }
4573
+
4574
+ assume();
4575
+
4576
+ // combine the passed globals after we've assumed all our options
4577
+ combine(predefined, g || {});
4578
+
4579
+ //reset values
4580
+ comma.first = true;
4581
+ quotmark = undefined;
4582
+
4583
+ try {
4584
+ advance();
4585
+ switch (nexttoken.id) {
4586
+ case "{":
4587
+ case "[":
4588
+ option.laxbreak = true;
4589
+ jsonmode = true;
4590
+ jsonValue();
4591
+ break;
4592
+ default:
4593
+ directives();
4594
+ if (directive["use strict"] && !option.globalstrict) {
4595
+ warning("Use the function form of \"use strict\".", prevtoken);
4596
+ }
4597
+
4598
+ statements();
4599
+ }
4600
+ advance((nexttoken && nexttoken.value !== ".") ? "(end)" : undefined);
4601
+
4602
+ var markDefined = function (name, context) {
4603
+ do {
4604
+ if (typeof context[name] === "string") {
4605
+ // JSHINT marks unused variables as 'unused' and
4606
+ // unused function declaration as 'unction'. This
4607
+ // code changes such instances back 'var' and
4608
+ // 'closure' so that the code in JSHINT.data()
4609
+ // doesn't think they're unused.
4610
+
4611
+ if (context[name] === "unused")
4612
+ context[name] = "var";
4613
+ else if (context[name] === "unction")
4614
+ context[name] = "closure";
4615
+
4616
+ return true;
4617
+ }
4618
+
4619
+ context = context["(context)"];
4620
+ } while (context);
4621
+
4622
+ return false;
4623
+ };
4624
+
4625
+ var clearImplied = function (name, line) {
4626
+ if (!implied[name])
4627
+ return;
4628
+
4629
+ var newImplied = [];
4630
+ for (var i = 0; i < implied[name].length; i += 1) {
4631
+ if (implied[name][i] !== line)
4632
+ newImplied.push(implied[name][i]);
4633
+ }
4634
+
4635
+ if (newImplied.length === 0)
4636
+ delete implied[name];
4637
+ else
4638
+ implied[name] = newImplied;
4639
+ };
4640
+
4641
+ var warnUnused = function (name, token) {
4642
+ var line = token.line;
4643
+ var chr = token.character;
4644
+
4645
+ if (option.unused)
4646
+ warningAt("'{a}' is defined but never used.", line, chr, name);
4647
+
4648
+ unuseds.push({
4649
+ name: name,
4650
+ line: line,
4651
+ character: chr
4652
+ });
4653
+ };
4654
+
4655
+ var checkUnused = function (func, key) {
4656
+ var type = func[key];
4657
+ var token = func["(tokens)"][key];
4658
+
4659
+ if (key.charAt(0) === "(")
4660
+ return;
4661
+
4662
+ if (type !== "unused" && type !== "unction")
4663
+ return;
4664
+
4665
+ // Params are checked separately from other variables.
4666
+ if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
4667
+ return;
4668
+
4669
+ warnUnused(key, token);
4670
+ };
4671
+
4672
+ // Check queued 'x is not defined' instances to see if they're still undefined.
4673
+ for (i = 0; i < JSHINT.undefs.length; i += 1) {
4674
+ k = JSHINT.undefs[i].slice(0);
4675
+
4676
+ if (markDefined(k[2].value, k[0])) {
4677
+ clearImplied(k[2].value, k[2].line);
4678
+ } else {
4679
+ warning.apply(warning, k.slice(1));
4680
+ }
4681
+ }
4682
+
4683
+ functions.forEach(function (func) {
4684
+ for (var key in func) {
4685
+ if (is_own(func, key)) {
4686
+ checkUnused(func, key);
4687
+ }
4688
+ }
4689
+
4690
+ if (!func["(params)"])
4691
+ return;
4692
+
4693
+ var params = func["(params)"].slice();
4694
+ var param = params.pop();
4695
+ var type;
4696
+
4697
+ while (param) {
4698
+ type = func[param];
4699
+
4700
+ // 'undefined' is a special case for (function (window, undefined) { ... })();
4701
+ // patterns.
4702
+
4703
+ if (param === "undefined")
4704
+ return;
4705
+
4706
+ if (type !== "unused" && type !== "unction")
4707
+ return;
4708
+
4709
+ warnUnused(param, func["(tokens)"][param]);
4710
+ param = params.pop();
4711
+ }
4712
+ });
4713
+
4714
+ for (var key in declared) {
4715
+ if (is_own(declared, key) && !is_own(global, key)) {
4716
+ warnUnused(key, declared[key]);
4717
+ }
4718
+ }
4719
+ } catch (e) {
4720
+ if (e) {
4721
+ var nt = nexttoken || {};
4722
+ JSHINT.errors.push({
4723
+ raw : e.raw,
4724
+ reason : e.message,
4725
+ line : e.line || nt.line,
4726
+ character : e.character || nt.from
4727
+ }, null);
4728
+ }
4729
+ }
4730
+
4731
+ // Loop over the listed "internals", and check them as well.
4732
+
4733
+ if (JSHINT.scope === "(main)") {
4734
+ o = o || {};
4735
+
4736
+ for (i = 0; i < JSHINT.internals.length; i += 1) {
4737
+ k = JSHINT.internals[i];
4738
+ o.scope = k.elem;
4739
+ itself(k.value, o, g);
4740
+ }
4741
+ }
4742
+
4743
+ return JSHINT.errors.length === 0;
4744
+ };
4745
+
4746
+ // Data summary.
4747
+ itself.data = function () {
4748
+ var data = {
4749
+ functions: [],
4750
+ options: option
4751
+ };
4752
+ var implieds = [];
4753
+ var members = [];
4754
+ var fu, f, i, j, n, globals;
4755
+
4756
+ if (itself.errors.length) {
4757
+ data.errors = itself.errors;
4758
+ }
4759
+
4760
+ if (jsonmode) {
4761
+ data.json = true;
4762
+ }
4763
+
4764
+ for (n in implied) {
4765
+ if (is_own(implied, n)) {
4766
+ implieds.push({
4767
+ name: n,
4768
+ line: implied[n]
4769
+ });
4770
+ }
4771
+ }
4772
+
4773
+ if (implieds.length > 0) {
4774
+ data.implieds = implieds;
4775
+ }
4776
+
4777
+ if (urls.length > 0) {
4778
+ data.urls = urls;
4779
+ }
4780
+
4781
+ globals = Object.keys(scope);
4782
+ if (globals.length > 0) {
4783
+ data.globals = globals;
4784
+ }
4785
+
4786
+ for (i = 1; i < functions.length; i += 1) {
4787
+ f = functions[i];
4788
+ fu = {};
4789
+
4790
+ for (j = 0; j < functionicity.length; j += 1) {
4791
+ fu[functionicity[j]] = [];
4792
+ }
4793
+
4794
+ for (j = 0; j < functionicity.length; j += 1) {
4795
+ if (fu[functionicity[j]].length === 0) {
4796
+ delete fu[functionicity[j]];
4797
+ }
4798
+ }
4799
+
4800
+ fu.name = f["(name)"];
4801
+ fu.param = f["(params)"];
4802
+ fu.line = f["(line)"];
4803
+ fu.character = f["(character)"];
4804
+ fu.last = f["(last)"];
4805
+ fu.lastcharacter = f["(lastcharacter)"];
4806
+ data.functions.push(fu);
4807
+ }
4808
+
4809
+ if (unuseds.length > 0) {
4810
+ data.unused = unuseds;
4811
+ }
4812
+
4813
+ members = [];
4814
+ for (n in member) {
4815
+ if (typeof member[n] === "number") {
4816
+ data.member = member;
4817
+ break;
4818
+ }
4819
+ }
4820
+
4821
+ return data;
4822
+ };
4823
+
4824
+ itself.jshint = itself;
4825
+
4826
+ return itself;
4827
+ }());
4828
+
4829
+ // Make JSHINT a Node module, if possible.
4830
+ if (typeof exports === "object" && exports) {
4831
+ exports.JSHINT = JSHINT;
4832
+ }