oneis 1.0.0-java

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