Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

/*properties*/ and /*global*/ now respect function scope

  • Loading branch information...
commit 475768b9a33b83aa12947176c30f3f3727d00a5e 1 parent dd545ce
@douglascrockford authored
Showing with 332 additions and 243 deletions.
  1. +325 −236 fulljslint.js
  2. +7 −7 lint.html
View
561 fulljslint.js
@@ -1,5 +1,5 @@
// jslint.js
-// 2011-03-04
+// 2011-03-05
/*
Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
@@ -45,7 +45,7 @@ SOFTWARE.
If it checks out, JSLINT returns true. Otherwise, it returns false.
If false, you can inspect JSLINT.errors to find out the problems.
- JSLINT.errors is an array of objects containing these members:
+ JSLINT.errors is an array of objects containing these properties:
{
line : The line (relative to 0) at which the lint was found
@@ -152,69 +152,123 @@ SOFTWARE.
*/
+/*
+ JSLint provides three directives. They look like slashstar comments, and
+ allow for setting options, declaring global variables, and establishing a
+ set of allowed property names.
+
+ These directives respect function scope.
+*/
+
+/*
+ The jslint directive is a special comment that can set one or more options.
+ The current option set is
+
+ adsafe true, if ADsafe rules should be enforced
+ bitwise true, if bitwise operators should not be allowed
+ browser true, if the standard browser globals should be predefined
+ cap true, if upper case HTML should be allowed
+ 'continue' true, if the continuation statement should be tolerated
+ css true, if CSS workarounds should be tolerated
+ debug true, if debugger statements should be allowed
+ devel true, if logging should be allowed (console, alert, etc.)
+ es5 true, if ES5 syntax should be allowed
+ evil true, if eval should be allowed
+ forin true, if for in statements need not filter
+ fragment true, if HTML fragments should be allowed
+ indent the indentation factor
+ maxerr the maximum number of errors to allow
+ maxlen the maximum length of a source line
+ newcap true, if constructor names must be capitalized
+ nomen true, if names should be checked
+ on true, if HTML event handlers should be allowed
+ onevar true, if only one var statement per function should be allowed
+ passfail true, if the scan should stop on first error
+ plusplus true, if increment/decrement should not be allowed
+ regexp true, if the . should not be allowed in regexp literals
+ rhino true, if the Rhino environment globals should be predefined
+ undef true, if variables should be declared before used
+ safe true, if use of some browser features should be restricted
+ windows true, if MS Windows-specigic globals should be predefined
+ strict true, require the "use strict"; pragma
+ sub true, if all forms of subscript notation are tolerated
+ white true, if strict whitespace rules apply
+ widget true if the Yahoo Widgets globals should be predefined
+
+ For example:
+*/
+
+
/*jslint
evil: true, nomen: false, onevar: false, regexp: false, strict: true
*/
-/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "'",
- "(begin)", "(breakage)", "(context)", "(end)", "(error)", "(global)",
- "(identifier)", "(line)", "(loopage)", "(name)", "(onevar)",
- "(params)", "(scope)", "(statement)", "(token)", "(verb)", ")", "*",
- "+", "-", "/", ";", "<", "</", "<=", "==", "===", ">", ">=", ADSAFE,
- ActiveXObject, Array, Boolean, COM, CScript, Canvas, CustomAnimation,
- Date, Debug, E, Enumerator, Error, EvalError, FadeAnimation, Flash,
- FormField, Frame, Function, HotKey, Image, JSON, LN10, LN2, LOG10E,
- LOG2E, MAX_VALUE, MIN_VALUE, Math, MenuItem, MoveAnimation,
- NEGATIVE_INFINITY, Number, Object, Option, PI, POSITIVE_INFINITY, Point,
- RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation,
- RotateAnimation, SQRT1_2, SQRT2, ScrollBar, String, Style, SyntaxError,
- System, Text, TextArea, Timer, TypeError, URIError, URL, VBArray,
- WScript, Web, Window, XMLDOM, XMLHttpRequest, "\\", a, a_function,
- a_label, a_not_allowed, a_not_defined, a_scope, abbr, acronym,
- activeborder, activecaption, address, adsafe, adsafe_a,
- adsafe_autocomplete, adsafe_bad_id, adsafe_div, adsafe_fragment,
- adsafe_go, adsafe_html, adsafe_id, adsafe_id_go, adsafe_lib,
- adsafe_lib_second, adsafe_missing_id, adsafe_name_a, adsafe_placement,
- adsafe_prefix_a, adsafe_script, adsafe_source, adsafe_subscript_a,
- adsafe_tag, alert, aliceblue, all, already_defined, and, animator,
- antiquewhite, appleScript, applet, apply, approved, appworkspace, aqua,
- aquamarine, area, arguments, arity, article, aside, assign,
- assign_exception, assignment_function_expression, at, attribute_case_a,
- audio, autocomplete, avoid_a, azure, b, background,
- "background-attachment", "background-color", "background-image",
- "background-position", "background-repeat", bad_assignment, bad_color_a,
- bad_constructor, bad_entity, bad_html, bad_id_a, bad_in_a,
- bad_invocation, bad_name_a, bad_new, bad_number, bad_operand, bad_type,
- bad_url, bad_wrap, base, bdo, beep, beige, big, bisque, bitwise, black,
- blanchedalmond, block, blockquote, blue, blueviolet, body, border,
- "border-bottom", "border-bottom-color", "border-bottom-style",
- "border-bottom-width", "border-collapse", "border-color", "border-left",
- "border-left-color", "border-left-style", "border-left-width",
- "border-right", "border-right-color", "border-right-style",
- "border-right-width", "border-spacing", "border-style", "border-top",
- "border-top-color", "border-top-style", "border-top-width",
- "border-width", bottom, br, braille, brown, browser, burlywood, button,
- buttonface, buttonhighlight, buttonshadow, buttontext, bytesToUIString,
- c, cadetblue, call, callee, caller, canvas, cap, caption,
- "caption-side", captiontext, case, center, charAt, charCodeAt,
- character, chartreuse, chocolate, chooseColor, chooseFile, chooseFolder,
- cite, clear, clearInterval, clearTimeout, clip, closeWidget, closure,
- cm, code, col, colgroup, color, combine_var, command, comments, concat,
- conditional_assignment, confirm, confusing_a, confusing_regexp, console,
- constructor, constructor_name_a, content, continue, control_a,
- convertPathToHFS, convertPathToPlatform, coral, cornflowerblue,
- cornsilk, "counter-increment", "counter-reset", create, crimson, css,
- cursor, cyan, d, dangerous_comment, dangling_a, darkblue, darkcyan,
- darkgoldenrod, darkgray, darkgreen, darkkhaki, darkmagenta,
+/*
+ The properties directive declares an exclusive list of property names.
+ Any properties named in the program that are not in the list will
+ produce a warning.
+
+ For example:
+*/
+
+/*properties "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "'",
+ "(begin)", "(breakage)", "(context)", "(error)", "(global)",
+ "(identifier)", "(line)", "(loopage)", "(name)", "(onevar)", "(params)",
+ "(scope)", "(statement)", "(token)", "(verb)", ")", "*", "+", "-", "\/",
+ ";", "<", "<=", "==", "===", ">", ">=", ADSAFE, ActiveXObject,
+ Array, Boolean, COM, CScript, Canvas, CustomAnimation, Date, Debug, E,
+ Enumerator, Error, EvalError, FadeAnimation, Flash, FormField, Frame,
+ Function, HotKey, Image, JSON, LN10, LN2, LOG10E, LOG2E, MAX_VALUE,
+ MIN_VALUE, Math, MenuItem, MoveAnimation, NEGATIVE_INFINITY, Number,
+ Object, Option, PI, POSITIVE_INFINITY, Point, RangeError, Rectangle,
+ ReferenceError, RegExp, ResizeAnimation, RotateAnimation, SQRT1_2,
+ SQRT2, ScrollBar, String, Style, SyntaxError, System, Text, TextArea,
+ Timer, TypeError, URIError, URL, VBArray, WScript, Web, Window, XMLDOM,
+ XMLHttpRequest, "\\", a, a_function, a_label, a_not_allowed,
+ a_not_defined, a_scope, abbr, acronym, activeborder, activecaption,
+ address, adsafe, adsafe_a, adsafe_autocomplete, adsafe_bad_id,
+ adsafe_div, adsafe_fragment, adsafe_go, adsafe_html, adsafe_id,
+ adsafe_id_go, adsafe_lib, adsafe_lib_second, adsafe_missing_id,
+ adsafe_name_a, adsafe_placement, adsafe_prefix_a, adsafe_script,
+ adsafe_source, adsafe_subscript_a, adsafe_tag, alert, aliceblue, all,
+ already_defined, and, animator, antiquewhite, appleScript, applet,
+ apply, approved, appworkspace, aqua, aquamarine, area, arguments, arity,
+ article, aside, assign, assign_exception,
+ assignment_function_expression, at, attribute_case_a, audio,
+ autocomplete, avoid_a, azure, b, background, "background-attachment",
+ "background-color", "background-image", "background-position",
+ "background-repeat", bad_assignment, bad_color_a, bad_constructor,
+ bad_entity, bad_html, bad_id_a, bad_in_a, bad_invocation, bad_name_a,
+ bad_new, bad_number, bad_operand, bad_type, bad_url, bad_wrap, base,
+ bdo, beep, beige, big, bisque, bitwise, black, blanchedalmond, block,
+ blockquote, blue, blueviolet, body, border, "border-bottom",
+ "border-bottom-color", "border-bottom-style", "border-bottom-width",
+ "border-collapse", "border-color", "border-left", "border-left-color",
+ "border-left-style", "border-left-width", "border-right",
+ "border-right-color", "border-right-style", "border-right-width",
+ "border-spacing", "border-style", "border-top", "border-top-color",
+ "border-top-style", "border-top-width", "border-width", bottom, br,
+ braille, brown, browser, burlywood, button, buttonface, buttonhighlight,
+ buttonshadow, buttontext, bytesToUIString, c, cadetblue, call, callee,
+ caller, canvas, cap, caption, "caption-side", captiontext, center,
+ charAt, charCodeAt, character, chartreuse, chocolate, chooseColor,
+ chooseFile, chooseFolder, cite, clear, clearInterval, clearTimeout,
+ clip, closeWidget, closure, cm, code, col, colgroup, color, combine_var,
+ command, comments, concat, conditional_assignment, confirm, confusing_a,
+ confusing_regexp, console, constructor, constructor_name_a, content,
+ continue, control_a, convertPathToHFS, convertPathToPlatform, coral,
+ cornflowerblue, cornsilk, "counter-increment", "counter-reset", create,
+ crimson, css, cursor, cyan, d, dangerous_comment, dangling_a, darkblue,
+ darkcyan, darkgoldenrod, darkgray, darkgreen, darkkhaki, darkmagenta,
darkolivegreen, darkorange, darkorchid, darkred, darksalmon,
darkseagreen, darkslateblue, darkslategray, darkturquoise, darkviolet,
data, datalist, dd, debug, decodeURI, decodeURIComponent, deeppink,
- deepskyblue, default, defineClass, del, deleted, deserialize, details,
- devel, dfn, dialog, dimgray, dir, direction, display, disrupt, div, dl,
- do, document, dodgerblue, dt, duplicate_a, edge, edition, else, em,
- embed, embossed, empty, "empty-cells", empty_block, empty_case,
- empty_class, encodeURI, encodeURIComponent, entityify, errors, es5,
- escape, eval, event, evidence, evil, ex, exception, exec, expected_a,
+ deepskyblue, defineClass, del, deleted, deserialize, details, devel,
+ dfn, dialog, dimgray, dir, direction, display, disrupt, div, dl,
+ document, dodgerblue, dt, duplicate_a, edge, edition, else, em, embed,
+ embossed, empty, "empty-cells", empty_block, empty_case, empty_class,
+ encodeURI, encodeURIComponent, entityify, errors, es5, escape, eval,
+ event, evidence, evil, ex, exception, exec, expected_a,
expected_a_at_b_c, expected_a_b, expected_a_b_from_c_d, expected_at_a,
expected_attribute_a, expected_attribute_value_a, expected_class_a,
expected_fraction_a, expected_id_a, expected_identifier_a,
@@ -224,10 +278,10 @@ SOFTWARE.
expected_positive_a, expected_pseudo_a, expected_selector_a,
expected_small_a, expected_space_a_b, expected_string_a,
expected_style_attribute, expected_style_pattern, expected_tagname_a,
- fieldset, figure, filesystem, firebrick, first, float, floor,
+ fieldset, figure, filesystem, filter, firebrick, first, float, floor,
floralwhite, focusWidget, font, "font-family", "font-size",
"font-size-adjust", "font-stretch", "font-style", "font-variant",
- "font-weight", footer, for, for_if, forestgreen, forin, form, fragment,
+ "font-weight", footer, for_if, forestgreen, forin, form, fragment,
frame, frames, frameset, from, fromCharCode, fuchsia, fud, funct,
function, function_block, function_eval, function_loop,
function_statement, function_strict, functions, g, gainsboro, gc,
@@ -237,12 +291,12 @@ SOFTWARE.
honeydew, hotpink, hr, "hta:application", html, html_confusion_a,
html_handlers, i, iTunes, id, identifier, identifier_function, iframe,
img, immed, implied_evil, implieds, in, inactiveborder, inactivecaption,
- inactivecaptiontext, include, indent, indexOf, indianred, indigo, infix_in,
- infobackground, infotext, init, input, ins, insecure_a, isAlpha,
- isApplicationRunning, isArray, isDigit, isFinite, isNaN, ivory, join,
- jslint, json, kbd, keygen, keys, khaki, konfabulatorVersion, label,
- label_a_b, labeled, lang, lavender, lavenderblush, lawngreen, lbp,
- leading_decimal_a, led, left, legend, lemonchiffon, length,
+ inactivecaptiontext, include, indent, indexOf, indianred, indigo,
+ infix_in, infobackground, infotext, init, input, ins, insecure_a,
+ isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, ivory,
+ join, jslint, json, kbd, keygen, keys, khaki, konfabulatorVersion,
+ label, label_a_b, labeled, lang, lavender, lavenderblush, lawngreen,
+ lbp, leading_decimal_a, led, left, legend, lemonchiffon, length,
"letter-spacing", li, lib, lightblue, lightcoral, lightcyan,
lightgoldenrodyellow, lightgreen, lightpink, lightsalmon, lightseagreen,
lightskyblue, lightslategray, lightsteelblue, lightyellow, lime,
@@ -281,30 +335,35 @@ SOFTWARE.
select, serialize, setInterval, setTimeout, shift,
showWidgetPreferences, sienna, silver, skyblue, slash_equal, slateblue,
slategray, sleep, slice, small, snow, sort, source, span, spawn, speak,
- speech, split, springgreen, src, stack, statement, statement_block,
- steelblue, stopping, strange_loop, strict, strong, style, styleproperty,
- sub, subscript, substr, sup, supplant, suppressUpdates, switch, sync,
- system, table, "table-layout", tag_a_in_b, tan, tbody, td, teal,
- tellWidget, test, "text-align", "text-decoration", "text-indent",
- "text-shadow", "text-transform", textarea, tfoot, th, thead, third,
- thistle, threeddarkshadow, threedface, threedhighlight,
- threedlightshadow, threedshadow, thru, time, title, toLowerCase,
- toString, toUpperCase, toint32, token, tomato, too_long, too_many, top,
- tr, trailing_decimal_a, tree, tt, tty, turquoise, tv, type, u, ul,
- unclosed, unclosed_comment, unclosed_regexp, undef, unescape,
- unescaped_a, unexpected_a, unexpected_char_a_b, unexpected_comment,
- unexpected_member_a, unexpected_space_a_b, "unicode-bidi",
- unnecessary_initialize, unnecessary_use, unreachable_a_b,
- unrecognized_style_attribute_a, unrecognized_tag_a, unsafe, unused,
- unwatch, updateNow, url, urls, use_array, use_braces, use_object,
- used_before_a, value, valueOf, var, var_a_not, version,
- "vertical-align", video, violet, visibility, was, watch,
- weird_assignment, weird_condition, weird_new, weird_program,
- weird_relation, weird_ternary, wheat, while, white, "white-space",
- whitesmoke, widget, width, window, windowframe, windows, windowtext,
- "word-spacing", "word-wrap", wrap, wrap_immediate, wrap_regexp,
- write_is_wrong, yahooCheckLogin, yahooLogin, yahooLogout, yellow,
- yellowgreen, "z-index", "}"
+ speech, split, springgreen, src, stack, statement_block, steelblue,
+ stopping, strange_loop, strict, strong, style, styleproperty, sub,
+ subscript, substr, sup, supplant, suppressUpdates, sync, system, table,
+ "table-layout", tag_a_in_b, tan, tbody, td, teal, tellWidget, test,
+ "text-align", "text-decoration", "text-indent", "text-shadow",
+ "text-transform", textarea, tfoot, th, thead, third, thistle,
+ threeddarkshadow, threedface, threedhighlight, threedlightshadow,
+ threedshadow, thru, time, title, toLowerCase, toString, toUpperCase,
+ toint32, token, tomato, too_long, too_many, top, tr, trailing_decimal_a,
+ tree, tt, tty, turquoise, tv, type, u, ul, unclosed, unclosed_comment,
+ unclosed_regexp, undef, unescape, unescaped_a, unexpected_a,
+ unexpected_char_a_b, unexpected_comment, unexpected_member_a,
+ unexpected_space_a_b, "unicode-bidi", unnecessary_initialize,
+ unnecessary_use, unreachable_a_b, unrecognized_style_attribute_a,
+ unrecognized_tag_a, unsafe, unused, unwatch, updateNow, url, urls,
+ use_array, use_braces, use_object, used_before_a, value, valueOf, var,
+ var_a_not, version, "vertical-align", video, violet, visibility, was,
+ watch, weird_assignment, weird_condition, weird_new, weird_program,
+ weird_relation, weird_ternary, wheat, white, "white-space", whitesmoke,
+ widget, width, window, windowframe, windows, windowtext, "word-spacing",
+ "word-wrap", wrap, wrap_immediate, wrap_regexp, write_is_wrong,
+ yahooCheckLogin, yahooLogin, yahooLogout, yellow, yellowgreen,
+ "z-index"
+*/
+
+/*
+ The global directive is used to declare global variables that can
+ be accessed by the program. If a declaration is true, then the variable
+ is writeable. Otherwise, it is read-only.
*/
// We build the application inside a function so that we produce only a single
@@ -355,39 +414,6 @@ var JSLINT = (function () {
watch : true
},
-
-// These are the JSLint boolean options.
-
- bool_options = {
- adsafe : true, // if ADsafe should be enforced
- bitwise : true, // if bitwise operators should not be allowed
- browser : true, // if the standard browser globals should be predefined
- cap : true, // if upper case HTML should be allowed
- 'continue' : true, // if the continuation statement should be tolerated
- css : true, // if CSS workarounds should be tolerated
- debug : true, // if debugger statements should be allowed
- devel : true, // if logging should be allowed (console, alert, etc.)
- es5 : true, // if ES5 syntax should be allowed
- evil : true, // if eval should be allowed
- forin : true, // if for in statements need not filter
- fragment : true, // if HTML fragments should be allowed
- newcap : true, // if constructor names must be capitalized
- nomen : true, // if names should be checked
- on : true, // if HTML event handlers should be allowed
- onevar : true, // if only one var statement per function should be allowed
- passfail : true, // if the scan should stop on first error
- plusplus : true, // if increment/decrement should not be allowed
- regexp : true, // if the . should not be allowed in regexp literals
- rhino : true, // if the Rhino environment globals should be predefined
- undef : true, // if variables should be declared before used
- safe : true, // if use of some browser features should be restricted
- windows : true, // if MS Windows-specigic globals should be predefined
- strict : true, // require the "use strict"; pragma
- sub : true, // if all forms of subscript notation are tolerated
- white : true, // if strict whitespace rules apply
- widget : true // if the Yahoo Widgets globals should be predefined
- },
-
// browser contains a set of global names that are commonly provided by a
// web browser environment. self and window are intentially excluded because
// of the high likelihood for misue.
@@ -567,7 +593,7 @@ var JSLINT = (function () {
unexpected_a: "Unexpected '{a}'.",
unexpected_char_a_b: "Unexpected character '{a}' in {b}.",
unexpected_comment: "Unexpected comment.",
- unexpected_member_a: "Unexpected /*member {a}.",
+ unexpected_member_a: "Unexpected property '{a}'.",
unexpected_space_a_b: "Unexpected space between '{a}' and '{b}'.",
unnecessary_initialize: "It is not necessary to initialize '{a}' to 'undefined'.",
unnecessary_use: "Unnecessary \"use strict\".",
@@ -940,7 +966,7 @@ var JSLINT = (function () {
lines,
lookahead,
member,
- members_only,
+ properties,
nexttoken,
option,
predefined, // Global variables defined by option
@@ -1147,7 +1173,7 @@ var JSLINT = (function () {
// unsafe characters that are silently deleted by one or more browsers
cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
// token
- tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/,
+ tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jslint|properties|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/,
// html token
hx = /^\s*(['"=>\/&#]|<(?:\/|\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\-:]*|[0-9]+|--)/,
// characters in strings that need escapement
@@ -1187,6 +1213,19 @@ var JSLINT = (function () {
// Provide critical ES5 functions to ES3.
+ if (typeof Array.prototype.filter !== 'function') {
+ Array.prototype.filter = function (f) {
+ var i, length = this.length, result = [];
+ for (i = 0; i < length; i += 1) {
+ try {
+ result.push(f(this[i]));
+ } catch (ignore) {
+ }
+ }
+ return result;
+ };
+ }
+
if (typeof Array.isArray !== 'function') {
Array.isArray = function (o) {
return Object.prototype.toString.apply(o) === '[object Array]';
@@ -2196,7 +2235,10 @@ klass: do {
}
funct[t] = type;
if (funct['(global)']) {
- global[t] = funct;
+ if (global[t] === false) {
+ warn(bundle.read_only);
+ }
+ global[t] = true;
if (Object.prototype.hasOwnProperty.call(implied, t)) {
warn(bundle.used_before_a, nexttoken, t);
delete implied[t];
@@ -2355,11 +2397,9 @@ klass: do {
}
- function do_option() {
+ function directive() {
var command = this.id,
- filter,
name,
- object,
old_comments_off = comments_off,
old_option_white = option.white,
value;
@@ -2369,26 +2409,23 @@ klass: do {
warn(bundle.unexpected_a, this);
}
switch (command) {
+ case '/*properties':
case '/*members':
case '/*member':
- command = '/*members';
- if (!members_only) {
- members_only = {};
+ command = '/*properties';
+ if (!properties) {
+ properties = {};
}
- object = members_only;
break;
case '/*jslint':
if (option.safe) {
warn(bundle.adsafe_a, this);
}
- filter = bool_options;
- object = option;
break;
case '/*global':
if (option.safe) {
warn(bundle.adsafe_a, this);
}
- object = predefined;
break;
default:
fail("What?");
@@ -2406,61 +2443,102 @@ loop: for (;;) {
if (nexttoken.arity !== 'string' && !nexttoken.identifier) {
fail(bundle.unexpected_a, nexttoken);
}
- name = nexttoken;
+ name = nexttoken.value;
advance();
- if (nexttoken.id === ':') {
- advance(':');
- if (object === members_only) {
- fail(bundle.expected_a_b, name, '*/', ':');
+ switch (command) {
+ case '/*global':
+ if (nexttoken.id === ':') {
+ advance(':');
+ switch (nexttoken.id) {
+ case 'true':
+ if (typeof scope[name] === 'object' ||
+ global[name] === false) {
+ fail(bundle.unexpected_a);
+ }
+ global[name] = true;
+ advance('true');
+ break;
+ case 'false':
+ if (typeof scope[name] === 'object') {
+ fail(bundle.unexpected_a);
+ }
+ global[name] = false;
+ advance('false');
+ break;
+ default:
+ fail(bundle.unexpected_a);
+ }
+ } else {
+ if (typeof scope[name] === 'object') {
+ fail(bundle.unexpected_a);
+ }
+ global[name] = false;
+ }
+ break;
+ case '/*jslint':
+ if (nexttoken.id !== ':') {
+ fail(bundle.expected_a_b, nexttoken, ':', nexttoken.value);
}
- if (name.value === 'indent' && command === '/*jslint') {
+ advance(':');
+ switch (name) {
+ case 'indent':
value = +nexttoken.value;
- if (typeof value !== 'number' || !isFinite(value) || value < 0 ||
+ if (typeof value !== 'number' ||
+ !isFinite(value) || value < 0 ||
Math.floor(value) !== value) {
fail(bundle.expected_small_a);
}
if (value > 0) {
old_option_white = true;
}
- object.indent = value;
- } else if (name.value === 'maxerr' && command === '/*jslint') {
+ option.indent = value;
+ break;
+ case 'maxerr':
value = +nexttoken.value;
- if (typeof value !== 'number' || !isFinite(value) || value <= 0 ||
+ if (typeof value !== 'number' ||
+ !isFinite(value) ||
+ value <= 0 ||
Math.floor(value) !== value) {
fail(bundle.expected_small_a, nexttoken);
}
- object.maxerr = value;
- } else if (name.value === 'maxlen' && command === '/*jslint') {
+ option.maxerr = value;
+ break;
+ case 'maxlen':
value = +nexttoken.value;
if (typeof value !== 'number' || !isFinite(value) || value < 0 ||
Math.floor(value) !== value) {
fail(bundle.expected_small_a);
}
- object.maxlen = value;
- } else if (nexttoken.id === 'true') {
- if (name.value === 'white' && command === '/*jslint') {
- old_option_white = object.white = true;
+ option.maxlen = value;
+ break;
+ case 'white':
+ if (nexttoken.id === 'true') {
+ old_option_white = true;
+ } else if (nexttoken.id === 'false') {
+ old_option_white = false;
} else {
- object[name.value] = true;
+ fail(bundle.unexpected_a);
}
- } else if (nexttoken.id === 'false') {
- if (name.value === 'white' && command === '/*jslint') {
- old_option_white = object.white = false;
+ break;
+ default:
+ if (nexttoken.id === 'true') {
+ option[name] = true;
+ } else if (nexttoken.id === 'false') {
+ option[name] = false;
} else {
- object[name.value] = false;
+ fail(bundle.unexpected_a);
}
- } else {
- fail(bundle.unexpected_a);
}
advance();
- } else {
- if (command === '/*jslint') {
- fail(bundle.missing_option, nexttoken);
- }
- object[name.value] = false;
+ break;
+ case '/*properties':
+ properties[name] = true;
+ break;
+ default:
+ fail(bundle.unexpected_a);
}
}
- if (filter) {
+ if (command === '/*jslint') {
assume();
}
comments_off = old_comments_off;
@@ -2951,8 +3029,7 @@ loop: for (;;) {
warn(bundle.unexpected_a, that);
}
that.first = left;
- if (predefined[left.value] === false &&
- scope[left.value]['(global)'] === true) {
+ if (funct[left.value] === false) {
warn(bundle.read_only, left);
} else if (left['function']) {
warn(bundle.a_function, left);
@@ -3206,7 +3283,7 @@ loop: for (;;) {
function tally_member(name) {
- if (members_only && typeof members_only[name] !== 'boolean') {
+ if (properties && typeof properties[name] !== 'boolean') {
warn(bundle.unexpected_member_a, token, name);
}
if (typeof member[name] === 'number') {
@@ -3238,41 +3315,35 @@ loop: for (;;) {
lbp: 0,
identifier: true,
nud: function () {
- var v = this.value,
- s = scope[v],
- f;
- if (typeof s === 'function') {
-
-// Protection against accidental inheritance.
-
- s = undefined;
- } else if (typeof s === 'boolean') {
- f = funct;
- funct = functions[0];
- add_label(v, 'var');
- s = funct;
- funct = f;
+ var variable = this.value,
+ site = scope[variable];
+ if (typeof site === 'function') {
+ site = undefined;
}
// The name is in scope and defined in the current function.
- if (funct === s) {
+ if (funct === site) {
// Change 'unused' to 'var', and reject labels.
- switch (funct[v]) {
+ switch (funct[variable]) {
+ case 'error':
+ warn(bundle.unexpected_a, token);
+ funct[variable] = 'var';
+ break;
case 'unused':
- funct[v] = 'var';
+ funct[variable] = 'var';
break;
case 'unction':
- funct[v] = 'function';
+ funct[variable] = 'function';
this['function'] = true;
break;
case 'function':
this['function'] = true;
break;
case 'label':
- warn(bundle.a_label, token, v);
+ warn(bundle.a_label, token, variable);
break;
}
@@ -3280,64 +3351,71 @@ loop: for (;;) {
// then we have an undefined variable.
} else if (funct['(global)']) {
- if (option.undef && typeof predefined[v] !== 'boolean') {
- warn(bundle.a_not_defined, token, v);
+ if (typeof global[variable] === 'boolean') {
+ funct[variable] = global[variable];
+ } else {
+ if (option.undef) {
+ warn(bundle.a_not_defined, token, variable);
+ } else {
+ note_implied(token);
+ }
}
- note_implied(token);
// If the name is already defined in the current
// function, but not as outer, then there is a scope error.
} else {
- switch (funct[v]) {
+ switch (funct[variable]) {
case 'closure':
case 'function':
case 'var':
case 'unused':
- warn(bundle.a_scope, token, v);
+ warn(bundle.a_scope, token, variable);
break;
case 'label':
- warn(bundle.a_label, token, v);
+ warn(bundle.a_label, token, variable);
break;
case 'outer':
- case 'global':
+ case true:
+ case false:
break;
default:
// If the name is defined in an outer function, make an outer entry, and if
// it was unused, make it var.
- if (s === true) {
- funct[v] = true;
- } else if (s === null) {
- warn(bundle.a_not_allowed, token, v);
+ if (typeof site === 'boolean') {
+ funct[variable] = site;
+ functions[0][variable] = true;
+ } else if (site === null) {
+ warn(bundle.a_not_allowed, token, variable);
note_implied(token);
- } else if (typeof s !== 'object') {
+ } else if (typeof site !== 'object') {
if (option.undef) {
- warn(bundle.a_not_defined, token, v);
+ warn(bundle.a_not_defined, token, variable);
} else {
- funct[v] = true;
+ funct[variable] = true;
}
note_implied(token);
} else {
- switch (s[v]) {
+ switch (site[variable]) {
case 'function':
case 'unction':
this['function'] = true;
- s[v] = 'closure';
- funct[v] = s['(global)'] ? 'global' : 'outer';
+ site[variable] = 'closure';
+ funct[variable] = site['(global)'] ? false : 'outer';
break;
case 'var':
case 'unused':
- s[v] = 'closure';
- funct[v] = s['(global)'] ? 'global' : 'outer';
+ site[variable] = 'closure';
+ funct[variable] = site['(global)'] ? true : 'outer';
break;
case 'closure':
case 'parameter':
- funct[v] = s['(global)'] ? 'global' : 'outer';
+ funct[variable] = site['(global)'] ? true : 'outer';
break;
case 'label':
- warn(bundle.a_label, token, v);
+ warn(bundle.a_label, token, variable);
break;
}
}
@@ -4013,10 +4091,10 @@ loop: for (;;) {
function do_function(func, name) {
- var old_option = option,
- old_scope = scope;
- option = Object.create(option);
- scope = Object.create(scope);
+ var old_properties = properties,
+ old_option = option,
+ old_global = global,
+ old_scope = scope;
funct = {
'(name)' : name || '"' + anonname + '"',
'(line)' : nexttoken.line,
@@ -4026,6 +4104,10 @@ loop: for (;;) {
'(scope)' : scope,
'(token)' : func
};
+ properties = Object.create(old_properties);
+ option = Object.create(old_option);
+ global = Object.create(old_global);
+ scope = Object.create(old_scope);
token.funct = funct;
functions.push(funct);
if (name) {
@@ -4035,11 +4117,11 @@ loop: for (;;) {
func.first = funct['(params)'] = function_params();
one_space();
func.block = block(false);
-
- scope = old_scope;
- option = old_option;
- funct = funct['(context)'];
- return func;
+ funct = funct['(context)'];
+ properties = old_properties;
+ option = old_option;
+ global = old_global;
+ scope = old_scope;
}
@@ -4137,10 +4219,11 @@ loop: for (;;) {
return this;
});
- stmt('/*members', do_option);
- stmt('/*member', do_option);
- stmt('/*jslint', do_option);
- stmt('/*global', do_option);
+ stmt('/*properties', directive);
+ stmt('/*members', directive);
+ stmt('/*member', directive);
+ stmt('/*jslint', directive);
+ stmt('/*global', directive);
@@ -4168,7 +4251,7 @@ loop: for (;;) {
if (funct['(global)'] && predefined[id] === false) {
warn(bundle.redefinition_a, token, id);
}
- add_label(id, 'unused');
+ add_label(id, 'error');
if (nexttoken.id === '=') {
assign = nexttoken;
@@ -4188,6 +4271,7 @@ loop: for (;;) {
} else {
this.first.push(name);
}
+ funct[id] = 'unused';
if (nexttoken.id !== ',') {
break;
}
@@ -6169,7 +6253,7 @@ loop: for (;;) {
json_mode = false;
lookahead = [];
member = {};
- members_only = null;
+ properties = null;
prereg = true;
src = false;
stack = null;
@@ -6280,11 +6364,11 @@ loop: for (;;) {
i,
implieds = [],
j,
+ kind,
members = [],
name,
the_function,
- unused = [],
- variable;
+ unused = [];
if (itself.errors.length) {
data.errors = itself.errors;
}
@@ -6309,7 +6393,9 @@ loop: for (;;) {
data.urls = urls;
}
- globals = Object.keys(scope);
+ globals = Object.keys(functions[0]).filter(function (value) {
+ return value.charAt(0) !== '(' ? value : undefined;
+ });
if (globals.length > 0) {
data.globals = globals;
}
@@ -6323,13 +6409,15 @@ loop: for (;;) {
for (name in the_function) {
if (Object.prototype.hasOwnProperty.call(the_function, name)) {
if (name.charAt(0) !== '(') {
- variable = the_function[name];
- if (variable === 'unction') {
- variable = 'unused';
+ kind = the_function[name];
+ if (kind === 'unction') {
+ kind = 'unused';
+ } else if (typeof kind === 'boolean') {
+ kind = 'global';
}
- if (Array.isArray(function_data[variable])) {
- function_data[variable].push(name);
- if (variable === 'unused') {
+ if (Array.isArray(function_data[kind])) {
+ function_data[kind].push(name);
+ if (kind === 'unused') {
unused.push({
name: name,
line: the_function['(line)'],
@@ -6366,6 +6454,7 @@ loop: for (;;) {
return data;
};
+
itself.report = function (errors_only) {
var data = itself.data();
@@ -6472,8 +6561,8 @@ loop: for (;;) {
keys = Object.keys(data.member);
if (keys.length) {
keys = keys.sort();
- mem = '<br><pre id=members>/*members ';
- length = 10;
+ mem = '<br><pre id=properties>/*properties ';
+ length = 13;
for (i = 0; i < keys.length; i += 1) {
key = keys[i];
name = key.name();
@@ -6500,7 +6589,7 @@ loop: for (;;) {
};
itself.jslint = itself;
- itself.edition = '2011-03-04';
+ itself.edition = '2011-03-05';
return itself;
View
14 lint.html
@@ -102,7 +102,7 @@ <h2 id=global>Global Variables</h2>
<p>The declaration should appears near the top of the file. It must appear before the use of the variables
it declares. </p>
<p>It is necessary to use a <code>var</code> statement to declare a variable before that variable is assigned to. </p>
-<p><code>JSLint</code> also recognizes a <code>/*global */</code> comment that can indicate to <code>JSLint</code> that variables used in this file were defined in other files. The comment can contain a comma separated list of names. Each name can optionally be followed by a colon and either <code>true</code> or <code>false</code>, <code>true</code> indicated that the variable may be assigned to by this file, and <code>false</code> indicating that assignment is not allowed (which is the default).</p>
+<p><code>JSLint</code> also recognizes a <code>/*global */</code> directive that can indicate to <code>JSLint</code> that variables used in this file were defined in other files. The comment can contain a comma separated list of names. Each name can optionally be followed by a colon and either <code>true</code> or <code>false</code>, <code>true</code> indicated that the variable may be assigned to by this file, and <code>false</code> indicating that assignment is not allowed (which is the default). The directive respects function scope.</p>
<p id=browser>Some globals can be predefined for you. Select the <i>Assume
a browser</i> (<code>browser</code>) <a href="#options">option</a> to
predefine the standard global properties that are supplied by web browsers,
@@ -437,7 +437,7 @@ <h2 id=options>Options</h2>
acceptable to you. The web page version of <code>JSLint</code> at <a href="http://www.JSLint.com/">http://www.JSLint.com/</a>
does this for you. </p>
<p>Options can also be specified within a script with a <code>/*jslint */</code>
- comment:</p>
+ directive:</p>
<pre>/*jslint nomen: true, debug: true,
evil: false, onevar: true */</pre>
<p>An option specification starts with <code>/*jslint</code>. Notice that
@@ -445,7 +445,7 @@ <h2 id=options>Options</h2>
a sequence of name value pairs, where the names are <code>JSLint</code>
options, and the values are <code>true</code> or <code>false</code>. The
<code>indent</code> <a href="#options">option</a> can take a number. A <code>/*jslint */</code>
- comment takes precedence over the <code>option</code> object. </p>
+ comment takes precedence over the <code>option</code> object. The directive respects function scope.</p>
<table>
<tbody>
<tr>
@@ -628,20 +628,20 @@ <h2 id=options>Options</h2>
</tr>
</tbody>
</table>
-<h2 id=members>Members</h2>
+<h2 id=members>Properties</h2>
<p>Since JavaScript is a loosely-typed, dynamic-object language, it is not
possible to determine at compile time if property names are spelled correctly.
<code>JSLint</code> provides some assistance with this.</p>
-<p>At the bottom of its report, <code>JSLint</code> displays a <code>/*members*/</code>
+<p>At the bottom of its report, <code>JSLint</code> displays a <code>/*properties*/</code>
comment. It contains all of the names and string literals that were used
with dot notation, subscript notation, and object literals to name the
members of objects. You can look through the list for misspellings. Member
names that were only used once are shown in italics. This is to make misspellings
easier to spot.</p>
-<p>You can copy the <code>/*members*/</code> comment into your script file.
+<p>You can copy the <code>/*properties*/</code> comment into your script file.
<code>JSLint</code> will check the spelling of all property names against
the list. That way, you can have <code>JSLint</code> look for misspellings
- for you.</p>
+ for you. The directive respects function scope.</p>
<h2 id=report>Report</h2>
<p>If <code>JSLint</code> is able to complete its scan, it generates a function
Please sign in to comment.
Something went wrong with that request. Please try again.