UNPKG

node-webodf

Version:

WebODF - JavaScript Document Engine http://webodf.org/

1,216 lines (1,116 loc) 150 kB
/*global core*/ // jslint.js // 2014-07-08 // Copyright (c) 2002 Douglas Crockford (www.JSLint.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // The Software shall be used for Good, not Evil. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // WARNING: JSLint will hurt your feelings. // JSLINT is a global function. It takes two parameters. // var myResult = JSLINT(source, option); // The first parameter is either a string or an array of strings. If it is a // string, it will be split on '\n' or '\r'. If it is an array of strings, it // is assumed that each string represents one line. The source can be a // JavaScript text or a JSON text. // The second parameter is an optional object of options that control the // operation of JSLINT. Most of the options are booleans: They are all // optional and have a default value of false. One of the options, predef, // can be an array of names, which will be used to declare global variables, // or an object whose keys are used as global names, with a boolean value // that determines if they are assignable. // 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 properties: // { // line : The line (relative to 0) at which the lint was found // character : The character (relative to 0) at which the lint was found // reason : The problem // evidence : The text line in which the problem occurred // raw : The raw message before the details were inserted // a : The first detail // b : The second detail // c : The third detail // d : The fourth detail // } // If a stopping error was found, a null will be the last element of the // JSLINT.errors array. A stopping error means that JSLint was not confident // enough to continue. It does not necessarily mean that the error was // especially heinous. // You can request a data structure that contains JSLint's results. // var myData = JSLINT.data(); // It returns a structure with this form: // { // errors: [ // { // line: NUMBER, // character: NUMBER, // reason: STRING, // evidence: STRING // } // ], // functions: [ // { // name: STRING, // line: NUMBER, // level: NUMBER, // parameter: [ // STRING // ], // var: [ // STRING // ], // exception: [ // STRING // ], // closure: [ // STRING // ], // outer: [ // STRING // ], // global: [ // STRING // ], // label: [ // STRING // ] // } // ], // global: [ // STRING // ], // member: { // STRING: NUMBER // }, // json: BOOLEAN // } // You can request a Function Report, which shows all of the functions // and the parameters and vars that they use. This can be used to find // implied global variables and other problems. The report is in HTML and // can be inserted into an HTML <body>. It should be given the result of the // JSLINT.data function. // var myReport = JSLINT.report(data); // You can request an HTML error report. // var myErrorReport = JSLINT.error_report(data); // You can obtain an object containing all of the properties found in the // file. JSLINT.property contains an object containing a key for each // property used in the program, the value being the number of times that // property name was used in the file. // You can request a properties report, which produces a list of the program's // properties in the form of a /*properties*/ declaration. // var myPropertyReport = JSLINT.properties_report(JSLINT.property); // You can obtain the parse tree that JSLint constructed while parsing. The // latest tree is kept in JSLINT.tree. A nice stringification can be produced // with // JSON.stringify(JSLINT.tree, [ // 'string', 'arity', 'name', 'first', // 'second', 'third', 'block', 'else' // ], 4)); // You can request a context coloring table. It contains information that can be // applied to the file that was analyzed. Context coloring colors functions // based on their nesting level, and variables on the color of the functions // in which they are defined. // var myColorization = JSLINT.color(data); // It returns an array containing objects of this form: // { // from: COLUMN, // thru: COLUMN, // line: ROW, // level: 0 or higher // } // JSLint provides three inline 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. // For example: /*jslint evil: true, nomen: true, regexp: true, todo: true */ // The current option set is // ass true, if assignment expressions should be allowed // bitwise true, if bitwise operators should be allowed // browser true, if the standard browser globals should be predefined // closure true, if Google Closure idioms should be tolerated // continue true, if the continuation statement should be tolerated // debug true, if debugger statements should be allowed // defined true, if already defined variables are allowed // devel true, if logging should be allowed (console, alert, etc.) // emptyblock true, if empty blocks should be allowed // eqeq true, if == should be allowed // evil true, if eval should be allowed // forin true, if for in statements need not filter // 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 capitalization is ignored // node true, if Node.js globals should be predefined // nomen true, if names may have dangling _ // passfail true, if the scan should stop on first error // plusplus true, if increment/decrement should be allowed // properties true, if all property names must be declared with /*properties*/ // regexp true, if the . should be allowed in regexp literals // rhino true, if the Rhino environment globals should be predefined // unparam true, if unused parameters should be tolerated // sloppy true, if the 'use strict'; pragma is optional // stupid true, if really stupid practices are tolerated // sub true, if all forms of subscript notation are tolerated // todo true, if TODO comments are tolerated // unvar true, if unused variables should be tolerated // vars true, if multiple var statements per function should be allowed // white true, if sloppy whitespace is tolerated // 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 defined, emptyblock, unvar, JSLINT, JSLint, core, '\b', '\t', '\n', '\f', '\r', '!', '!=', '!==', '"', '%', '\'', '(begin)', '(error)', '*', '+', '-', '/', '<', '<=', '==', '===', '>', '>=', '\\', a, a_label, a_scope, already_defined, and, apply, arguments, arity, ass, assign, assignment_expression, assignment_function_expression, at, avoid_a, b, bad_assignment, bad_constructor, bad_in_a, bad_invocation, bad_new, bad_number, bad_operand, bad_wrap, bitwise, block, break, breakage, browser, c, call, charAt, charCodeAt, character, closure, code, color, combine_var, comments, conditional_assignment, confusing_a, confusing_regexp, constructor_name_a, continue, control_a, couch, create, d, dangling_a, data, dead, debug, deleted, devel, disrupt, duplicate_a, edge, edition, elif, else, empty_block, empty_case, empty_class, entityify, eqeq, error_report, errors, evidence, evil, exception, exec, expected_a_at_b_c, expected_a_b, expected_a_b_from_c_d, expected_id_a, expected_identifier_a, expected_identifier_a_reserved, expected_number_a, expected_operator_a, expected_positive_a, expected_small_a, expected_space_a_b, expected_string_a, f, first, flag, floor, forEach, for_if, forin, from, fromCharCode, fud, function, function_block, function_eval, function_loop, function_statement, function_strict, functions, global, hasOwnProperty, id, identifier, identifier_function, immed, implied_evil, indent, indexOf, infix_in, init, insecure_a, isAlpha, isArray, isDigit, isNaN, join, jslint, json, keys, kind, label, labeled, lbp, leading_decimal_a, led, left, length, level, line, loopage, master, match, maxerr, maxlen, message, missing_a, missing_a_after_b, missing_property, missing_space_a_b, missing_use_strict, mode, move_invocation, move_var, n, name, name_function, nested_comment, newcap, node, nomen, not, not_a_constructor, not_a_defined, not_a_function, not_a_label, not_a_scope, not_greater, nud, number, octal_a, open, outer, parameter, parameter_a_get_b, parameter_arguments_a, parameter_set_a, params, paren, passfail, plusplus, pop, postscript, predef, properties, properties_report, property, prototype, push, quote, r, radix, raw, read_only, reason, redefinition_a_b, regexp, relation, replace, report, reserved, reserved_a, rhino, right, scanned_a_b, scope, search, second, shift, slash_equal, slice, sloppy, sort, split, statement, statement_block, stop, stopping, strange_loop, strict, string, stupid, sub, subscript, substr, supplant, sync_a, t, tag_a_in_b, test, third, thru, toString, todo, todo_comment, token, tokens, too_long, too_many, trailing_decimal_a, tree, unclosed, unclosed_comment, unclosed_regexp, unescaped_a, unexpected_a, unexpected_char_a, unexpected_comment, unexpected_label_a, unexpected_property_a, unexpected_space_a_b, unexpected_typeof_a, uninitialized_a, unnecessary_else, unnecessary_initialize, unnecessary_use, unparam, unreachable_a_b, unsafe, unused_a, url, use_array, use_braces, use_nested_if, use_object, use_or, use_param, use_spaces, used, used_before_a, var, var_a_not, var_loop, vars, varstatement, warn, warning, was, weird_assignment, weird_condition, weird_new, weird_program, weird_relation, weird_ternary, white, wrap, wrap_immediate, wrap_regexp, write_is_wrong, writeable */ // 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 // global variable. That function will be invoked immediately, and its return // value is the JSLINT function itself. That function is also an object that // can contain data and other functions. var JSLINT = (function () { 'use strict'; function array_to_object(array, value) { // Make an object from an array of keys and a common value. var i, length = array.length, object = Object.create(null); for (i = 0; i < length; i += 1) { object[array[i]] = value; } return object; } var allowed_option = { ass : true, bitwise : true, browser : true, closure : true, continue : true, couch : true, debug : true, defined : true, devel : true, emptyblock: true, eqeq : true, evil : true, forin : true, indent : 10, maxerr : 1000, maxlen : 256, newcap : true, node : true, nomen : true, passfail : true, plusplus : true, properties: true, regexp : true, rhino : true, unparam : true, sloppy : true, stupid : true, sub : true, todo : true, unvar : true, vars : true, white : true }, anonname, // The guessed name for anonymous functions. // These are operators that should not be used with the ! operator. bang = { '<' : true, '<=' : true, '==' : true, '===': true, '!==': true, '!=' : true, '>' : true, '>=' : true, '+' : true, '-' : true, '*' : true, '/' : true, '%' : true }, begin, // The root token block_var, // vars defined in the current block // browser contains a set of global names that are commonly provided by a // web browser environment. browser = array_to_object([ 'clearInterval', 'clearTimeout', 'document', 'event', 'FormData', 'frames', 'history', 'Image', 'localStorage', 'location', 'name', 'navigator', 'Option', 'parent', 'screen', 'sessionStorage', 'setInterval', 'setTimeout', 'Storage', 'window', 'XMLHttpRequest' ], false), // bundle contains the text messages. bundle = { a_label: "'{a}' is a statement label.", a_scope: "'{a}' used out of scope.", already_defined: "'{a}' is already defined.", and: "The '&&' subexpression should be wrapped in parens.", assignment_expression: "Unexpected assignment expression.", assignment_function_expression: "Expected an assignment or " + "function call and instead saw an expression.", avoid_a: "Avoid '{a}'.", bad_assignment: "Bad assignment.", bad_constructor: "Bad constructor.", bad_in_a: "Bad for in variable '{a}'.", bad_invocation: "Bad invocation.", bad_new: "Do not use 'new' for side effects.", bad_number: "Bad number '{a}'.", bad_operand: "Bad operand.", bad_wrap: "Do not wrap function literals in parens unless they " + "are to be immediately invoked.", combine_var: "Combine this with the previous 'var' statement.", conditional_assignment: "Expected a conditional expression and " + "instead saw an assignment.", confusing_a: "Confusing use of '{a}'.", confusing_regexp: "Confusing regular expression.", constructor_name_a: "A constructor name '{a}' should start with " + "an uppercase letter.", control_a: "Unexpected control character '{a}'.", dangling_a: "Unexpected dangling '_' in '{a}'.", deleted: "Only properties should be deleted.", duplicate_a: "Duplicate '{a}'.", empty_block: "Empty block.", empty_case: "Empty case.", empty_class: "Empty class.", evil: "eval is evil.", expected_a_b: "Expected '{a}' and instead saw '{b}'.", expected_a_b_from_c_d: "Expected '{a}' to match '{b}' from line " + "{c} and instead saw '{d}'.", expected_a_at_b_c: "Expected '{a}' at column {b}, not column {c}.", expected_id_a: "Expected an id, and instead saw #{a}.", expected_identifier_a: "Expected an identifier and instead saw '{a}'.", expected_identifier_a_reserved: "Expected an identifier and " + "instead saw '{a}' (a reserved word).", expected_number_a: "Expected a number and instead saw '{a}'.", expected_operator_a: "Expected an operator and instead saw '{a}'.", expected_positive_a: "Expected a positive number and instead saw '{a}'", expected_small_a: "Expected a small positive integer and instead saw '{a}'", expected_space_a_b: "Expected exactly one space between '{a}' and '{b}'.", expected_string_a: "Expected a string and instead saw '{a}'.", for_if: "The body of a for in should be wrapped in an if " + "statement to filter unwanted properties from the prototype.", function_block: "Function statements should not be placed in blocks." + "Use a function expression or move the statement to the top of " + "the outer function.", function_eval: "The Function constructor is eval.", function_loop: "Don't make functions within a loop.", function_statement: "Function statements are not invocable. " + "Wrap the whole function invocation in parens.", function_strict: "Use the function form of 'use strict'.", identifier_function: "Expected an identifier in an assignment " + "and instead saw a function invocation.", implied_evil: "Implied eval is evil. Pass a function instead of a string.", infix_in: "Unexpected 'in'. Compare with undefined, or use the " + "hasOwnProperty method instead.", insecure_a: "Insecure '{a}'.", isNaN: "Use the isNaN function to compare with NaN.", leading_decimal_a: "A leading decimal point can be confused with a dot: '.{a}'.", missing_a: "Missing '{a}'.", missing_a_after_b: "Missing '{a}' after '{b}'.", missing_property: "Missing property name.", missing_space_a_b: "Missing space between '{a}' and '{b}'.", missing_use_strict: "Missing 'use strict' statement.", move_invocation: "Move the invocation into the parens that " + "contain the function.", move_var: "Move 'var' declarations to the top of the function.", name_function: "Missing name in function statement.", nested_comment: "Nested comment.", not: "Nested not.", not_a_constructor: "Do not use {a} as a constructor.", not_a_defined: "'{a}' has not been fully defined yet.", not_a_function: "'{a}' is not a function.", not_a_label: "'{a}' is not a label.", not_a_scope: "'{a}' is out of scope.", not_greater: "'{a}' should not be greater than '{b}'.", octal_a: "Don't use octal: '{a}'. Use '\\u....' instead.", parameter_arguments_a: "Do not mutate parameter '{a}' when using 'arguments'.", parameter_a_get_b: "Unexpected parameter '{a}' in get {b} function.", parameter_set_a: "Expected parameter (value) in set {a} function.", radix: "Missing radix parameter.", read_only: "Read only.", redefinition_a_b: "Redefinition of '{a}' from line {b}.", reserved_a: "Reserved name '{a}'.", scanned_a_b: "{a} ({b}% scanned).", slash_equal: "A regular expression literal can be confused with '/='.", statement_block: "Expected to see a statement and instead saw a block.", stopping: "Stopping.", strange_loop: "Strange loop.", strict: "Strict violation.", subscript: "['{a}'] is better written in dot notation.", sync_a: "Unexpected sync method: '{a}'.", tag_a_in_b: "A '<{a}>' must be within '<{b}>'.", todo_comment: "Unexpected TODO comment.", too_long: "Line too long.", too_many: "Too many errors.", trailing_decimal_a: "A trailing decimal point can be confused " + "with a dot: '.{a}'.", unclosed: "Unclosed string.", unclosed_comment: "Unclosed comment.", unclosed_regexp: "Unclosed regular expression.", unescaped_a: "Unescaped '{a}'.", unexpected_a: "Unexpected '{a}'.", unexpected_char_a: "Unexpected character '{a}'.", unexpected_comment: "Unexpected comment.", unexpected_label_a: "Unexpected label '{a}'.", unexpected_property_a: "Unexpected /*property*/ '{a}'.", unexpected_space_a_b: "Unexpected space between '{a}' and '{b}'.", unexpected_typeof_a: "Unexpected 'typeof'. " + "Use '===' to compare directly with {a}.", uninitialized_a: "Uninitialized '{a}'.", unnecessary_else: "Unnecessary 'else' after disruption.", unnecessary_initialize: "It is not necessary to initialize '{a}' " + "to 'undefined'.", unnecessary_use: "Unnecessary 'use strict'.", unreachable_a_b: "Unreachable '{a}' after '{b}'.", unsafe: "Unsafe character.", unused_a: "Unused '{a}'.", url: "JavaScript URL.", use_array: "Use the array literal notation [].", use_braces: "Spaces are hard to count. Use {{a}}.", use_nested_if: "Expected 'else { if' and instead saw 'else if'.", use_object: "Use the object literal notation {} or Object.create(null).", use_or: "Use the || operator.", use_param: "Use a named parameter.", use_spaces: "Use spaces, not tabs.", used_before_a: "'{a}' was used before it was defined.", var_a_not: "Variable {a} was not declared correctly.", var_loop: "Don't declare variables in a loop.", weird_assignment: "Weird assignment.", weird_condition: "Weird condition.", weird_new: "Weird construction. Delete 'new'.", weird_program: "Weird program.", weird_relation: "Weird relation.", weird_ternary: "Weird ternary.", wrap_immediate: "Wrap an immediate function invocation in " + "parentheses to assist the reader in understanding that the " + "expression is the result of a function, and not the " + "function itself.", wrap_regexp: "Wrap the /regexp/ literal in parens to " + "disambiguate the slash operator.", write_is_wrong: "document.write can be a form of eval." }, closure = array_to_object([ 'goog' ], false), comments, comments_off, couch = array_to_object([ 'emit', 'getRow', 'isArray', 'log', 'provides', 'registerType', 'require', 'send', 'start', 'sum', 'toJSON' ], false), descapes = { 'b': '\b', 't': '\t', 'n': '\n', 'f': '\f', 'r': '\r', '"': '"', '/': '/', '\\': '\\', '!': '!' }, devel = array_to_object([ 'alert', 'confirm', 'console', 'Debug', 'opera', 'prompt', 'WSH' ], false), directive, escapes = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\'': '\\\'', '"' : '\\"', '/' : '\\/', '\\': '\\\\' }, funct, // The current function functions, // All of the functions global_funct, // The global body global_scope, // The global scope in_block, // Where function statements are not allowed indent, itself, // JSLINT itself json_mode, lex, // the tokenizer lines, lookahead, node = array_to_object([ 'Buffer', 'clearImmediate', 'clearInterval', 'clearTimeout', 'console', 'exports', 'global', 'module', 'process', 'require', 'setImmediate', 'setInterval', 'setTimeout', '__dirname', '__filename' ], false), node_js, numbery = array_to_object(['indexOf', 'lastIndexOf', 'search'], true), next_token, option, predefined, // Global variables defined by option prereg, prev_token, property, protosymbol, regexp_flag = array_to_object(['g', 'i', 'm'], true), return_this = function return_this() { return this; }, rhino = array_to_object([ 'defineClass', 'deserialize', 'gc', 'help', 'load', 'loadClass', 'print', 'quit', 'readFile', 'readUrl', 'runCommand', 'seal', 'serialize', 'spawn', 'sync', 'toint32', 'version' ], false), scope, // An object containing an object for each variable in scope semicolon_coda = array_to_object([';', '"', '\'', ')'], true), // standard contains the global names that are provided by the // ECMAScript standard. standard = array_to_object([ 'Array', 'Boolean', 'Date', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'Error', 'eval', 'EvalError', 'Function', 'isFinite', 'isNaN', 'JSON', 'Map', 'Math', 'Number', 'Object', 'parseInt', 'parseFloat', 'Promise', 'Proxy', 'RangeError', 'ReferenceError', 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'SyntaxError', 'System', 'TypeError', 'URIError', 'WeakMap', 'WeakSet' ], false), strict_mode, syntax = Object.create(null), token, tokens, var_mode, warnings, // Regular expressions. Some of these are stupidly long. // carriage return, carriage return linefeed, or linefeed crlfx = /\r\n?|\n/, // unsafe characters that are silently deleted by one or more browsers cx = /[\u0000-\u0008\u000a-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/, // identifier ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/, // javascript url jx = /^(?:javascript|jscript|ecmascript|vbscript)\s*:/i, // star slash lx = /\*\/|\/\*/, // characters in strings that need escapement nx = /[\u0000-\u001f'\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, // sync syx = /Sync$/, // comment todo tox = /^\W*to\s*do(?:\W|$)/i, // token tx = /^\s*([(){}\[\]\?.,:;'"~#@`]|={1,3}|\/(\*(jslint|properties|property|members?|globals?)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|[\^%]=?|&[&=]?|\|[|=]?|>{1,3}=?|<(?:[\/=!]|\!(\[|--)?|<=?)?|\!(\!|==?)?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+(?:[xX][0-9a-fA-F]+|\.[0-9]*)?(?:[eE][+\-]?[0-9]+)?)/; if (typeof String.prototype.entityify !== 'function') { String.prototype.entityify = function () { return this .replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;'); }; } if (typeof String.prototype.isAlpha !== 'function') { String.prototype.isAlpha = function () { return (this >= 'a' && this <= 'z\uffff') || (this >= 'A' && this <= 'Z\uffff'); }; } if (typeof String.prototype.isDigit !== 'function') { String.prototype.isDigit = function () { return (this >= '0' && this <= '9'); }; } if (typeof String.prototype.supplant !== 'function') { String.prototype.supplant = function (o) { return this.replace(/\{([^{}]*)\}/g, function (a, b) { var replacement = o[b]; return typeof replacement === 'string' || typeof replacement === 'number' ? replacement : a; }); }; } function sanitize(a) { // Escapify a troublesome character. return escapes[a] || '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4); } function add_to_predefined(group) { Object.keys(group).forEach(function (name) { predefined[name] = group[name]; }); } function assume() { if (option.browser) { add_to_predefined(browser); option.browser = false; } if (option.closure) { add_to_predefined(closure); } if (option.couch) { add_to_predefined(couch); option.couch = false; } if (option.devel) { add_to_predefined(devel); option.devel = false; } if (option.node) { add_to_predefined(node); option.node = false; node_js = true; } if (option.rhino) { add_to_predefined(rhino); option.rhino = false; } } // Produce an error warning. function artifact(tok) { if (!tok) { tok = next_token; } return tok.id === '(number)' ? tok.number : tok.string; } function quit(message, line, character) { throw { name: 'JSLintError', line: line, character: character, message: bundle.scanned_a_b.supplant({ a: bundle[message] || message, b: Math.floor((line / lines.length) * 100) }) }; } function warn(code, line, character, a, b, c, d) { var warning = { // ~~ id: '(error)', raw: bundle[code] || code, code: code, evidence: lines[line - 1] || '', line: line, character: character, a: a || artifact(this), b: b, c: c, d: d }; warning.reason = warning.raw.supplant(warning); itself.errors.push(warning); if (option.passfail) { quit('stopping', line, character); } warnings += 1; if (warnings >= option.maxerr) { quit('too_many', line, character); } return warning; } function stop(code, line, character, a, b, c, d) { var warning = warn(code, line, character, a, b, c, d); quit('stopping', warning.line, warning.character); } function expected_at(at) { if (!option.white && next_token.from !== at) { next_token.warn('expected_a_at_b_c', '', at, next_token.from); } } // lexical analysis and token construction lex = (function lex() { var character, c, from, length, line, pos, source_row; // Private lex methods function next_line() { var at; character = 1; source_row = lines[line]; line += 1; if (source_row === undefined) { return false; } at = source_row.search(/\t/); if (at >= 0) { if (option.white) { source_row = source_row.replace(/\t/g, ' '); } else { warn('use_spaces', line, at + 1); } } at = source_row.search(cx); if (at >= 0) { warn('unsafe', line, at); } if (option.maxlen && option.maxlen < source_row.length) { warn('too_long', line, source_row.length); } return true; } // Produce a token object. The token inherits from a syntax symbol. function it(type, value) { var id, the_token; if (type === '(string)') { if (jx.test(value)) { warn('url', line, from); } } the_token = Object.create(syntax[( type === '(punctuator)' || (type === '(identifier)' && Object.prototype.hasOwnProperty.call(syntax, value)) ? value : type )] || syntax['(error)']); if (type === '(identifier)') { the_token.identifier = true; if (value === '__iterator__' || value === '__proto__') { stop('reserved_a', line, from, value); } else if (!option.nomen && (value.charAt(0) === '_' || value.charAt(value.length - 1) === '_')) { warn('dangling_a', line, from, value); } } if (type === '(number)') { the_token.number = +value; } else if (value !== undefined) { the_token.string = String(value); } the_token.line = line; the_token.from = from; the_token.thru = character; if (comments.length) { the_token.comments = comments; comments = []; } id = the_token.id; prereg = id && ( ('(,=:[!&|?{};~+-*%^<>'.indexOf(id.charAt(id.length - 1)) >= 0) || id === 'return' || id === 'case' ); return the_token; } function match(x) { var exec = x.exec(source_row), first; if (exec) { length = exec[0].length; first = exec[1]; c = first.charAt(0); source_row = source_row.slice(length); from = character + length - first.length; character += length; return first; } for (;;) { if (!source_row) { if (!option.white) { warn('unexpected_char_a', line, character - 1, '(space)'); } return; } c = source_row.charAt(0); if (c !== ' ') { break; } source_row = source_row.slice(1); character += 1; } stop('unexpected_char_a', line, character, c); } function string(x) { var ch, at = 0, r = '', result; function hex(n) { var i = parseInt(source_row.substr(at + 1, n), 16); at += n; if (i >= 32 && i <= 126 && i !== 34 && i !== 92 && i !== 39) { warn('unexpected_a', line, character, '\\'); } character += n; ch = String.fromCharCode(i); } if (json_mode && x !== '"') { warn('expected_a_b', line, character, '"', x); } for (;;) { while (at >= source_row.length) { at = 0; if (!next_line()) { stop('unclosed', line - 1, from); } } ch = source_row.charAt(at); if (ch === x) { character += 1; source_row = source_row.slice(at + 1); result = it('(string)', r); result.quote = x; return result; } if (ch < ' ') { if (ch === '\n' || ch === '\r') { break; } warn('control_a', line, character + at, source_row.slice(0, at)); } else if (ch === '\\') { at += 1; character += 1; ch = source_row.charAt(at); switch (ch) { case '': warn('unexpected_a', line, character, '\\'); next_line(); at = -1; break; case '\'': if (json_mode) { warn('unexpected_a', line, character, '\\\''); } break; case 'u': hex(4); break; case 'v': if (json_mode) { warn('unexpected_a', line, character, '\\v'); } ch = '\v'; break; case 'x': if (json_mode) { warn('unexpected_a', line, character, '\\x'); } hex(2); break; default: if (typeof descapes[ch] !== 'string') { warn(ch >= '0' && ch <= '7' ? 'octal_a' : 'unexpected_a', line, character, '\\' + ch); } else { ch = descapes[ch]; } } } r += ch; character += 1; at += 1; } } function number(snippet) { var digit; if (source_row.charAt(0).isAlpha()) { warn('expected_space_a_b', line, character, c, source_row.charAt(0)); } if (c === '0') { digit = snippet.charAt(1); if (digit.isDigit()) { if (token.id !== '.') { warn('unexpected_a', line, character, snippet); } } else if (json_mode && (digit === 'x' || digit === 'X')) { warn('unexpected_a', line, character, '0x'); } } if (snippet.slice(snippet.length - 1) === '.') { warn('trailing_decimal_a', line, character, snippet); } digit = +snippet; if (!isFinite(digit)) { warn('bad_number', line, character, snippet); } snippet = digit; return it('(number)', snippet); } function comment(snippet, type) { if (comments_off) { warn('unexpected_comment', line, character); } else if (!option.todo && tox.test(snippet)) { warn('todo_comment', line, character); } comments.push({ id: type, from: from, thru: character, line: line, string: snippet }); } function regexp() { var at = 0, b, bit, depth = 0, flag = '', high, letter, low, potential, quote, result; for (;;) { b = true; c = source_row.charAt(at); at += 1; switch (c) { case '': stop('unclosed_regexp', line, from); return; case '/': if (depth > 0) { warn('unescaped_a', line, from + at, '/'); } c = source_row.slice(0, at - 1); potential = Object.create(regexp_flag); for (;;) { letter = source_row.charAt(at); if (potential[letter] !== true) { break; } potential[letter] = false; at += 1; flag += letter; } if (source_row.charAt(at).isAlpha()) { stop('unexpected_a', line, from, source_row.charAt(at)); } character += at; source_row = source_row.slice(at); quote = source_row.charAt(0); if (quote === '/' || quote === '*') { stop('confusing_regexp', line, from); } result = it('(regexp)', c); result.flag = flag; return result; case '\\': c = source_row.charAt(at); if (c < ' ') { warn('control_a', line, from + at, String(c)); } else if (c === '<') { warn('unexpected_a', line, from + at, '\\'); } at += 1; break; case '(': depth += 1; b = false; if (source_row.charAt(at) === '?') { at += 1; switch (source_row.charAt(at)) { case ':': case '=': case '!': at += 1; break; default: warn('expected_a_b', line, from + at, ':', source_row.charAt(at)); } } break; case '|': b = false; break; case ')': if (depth === 0) { warn('unescaped_a', line, from + at, ')'); } else { depth -= 1; } break; case ' ': pos = 1; while (source_row.charAt(at) === ' ') { at += 1; pos += 1; } if (pos > 1) { warn('use_braces', line, from + at, pos); } break; case '[': c = source_row.charAt(at); if (c === '^') { at += 1; if (!option.regexp) { warn('insecure_a', line, from + at, c); } else if (source_row.charAt(at) === ']') { stop('unescaped_a', line, from + at, '^'); } } bit = false; if (c === ']') { warn('empty_class', line, from + at - 1); bit = true; } klass: do { c = source_row.charAt(at); at += 1; switch (c) { case '[': case '^': warn('unescaped_a', line, from + at, c); bit = true; break; case '-': if (bit) { bit = false; } else { warn('unescaped_a', line, from + at, '-'); bit = true; } break; case ']': if (!bit) { warn('unescaped_a', line, from + at - 1, '-'); } break klass; case '\\': c = source_row.charAt(at); if (c < ' ') { warn('control_a', line, from + at, String(c)); } else if (c === '<') { warn('unexpected_a', line, from + at, '\\'); } at += 1; bit = true; break; case '/': warn('unescaped_a', line, from + at - 1, '/'); bit = true; break; default: bit = true; } } while (c); break; case '.': if (!option.regexp) { warn('insecure_a', line, from + at, c); } break; case ']': case '?': case '{': case '}': case '+': case '*': warn('unescaped_a', line, from + at, c); break; } if (b) { switch (source_row.charAt(at)) { case '?': case '+': case '*': at += 1; if (source_row.charAt(at) === '?') { at += 1; } break; case '{': at += 1; c = source_row.charAt(at); if (c < '0' || c > '9') { warn('expected_number_a', line, from + at, c); } at += 1; low = +c; for (;;) { c = source_row.charAt(at); if (c < '0' || c > '9') { break; } at += 1; low = +c + (low * 10); } high = low; if (c === ',') { at += 1; high = Infinity; c = source_row.charAt(at); if (c >= '0' && c <= '9') { at += 1; high = +c; for (;;) { c = source_row.charAt(at); if (c < '0' || c > '9') { break; } at += 1; high = +c + (high * 10); } } } if (source_row.charAt(at) !== '}') { warn('expected_a_b', line, from + at, '}', c); } else { at += 1; } if (source_row.charAt(at) === '?') { at += 1; } if (low > high) { warn('not_greater', line, from + at, low, high);