vendor/assets/javascripts/eslint.js in eslint-rails-0.1.1 vs vendor/assets/javascripts/eslint.js in eslint-rails-0.2.0
- old
+ new
@@ -43,36 +43,32 @@
/**
* Create an Array Expression ASTNode out of an array of elements
* @param {ASTNode[]} elements An array of ASTNode elements
* @returns {ASTNode} An ASTNode representing the entire array expression
*/
- createArrayExpression: function (elements) {
+ createArrayExpression: function(elements) {
return {
type: astNodeTypes.ArrayExpression,
elements: elements
};
},
/**
* Create an Arrow Function Expression ASTNode
* @param {ASTNode} params The function arguments
- * @param {ASTNode} defaults Any default arguments
* @param {ASTNode} body The function body
- * @param {ASTNode} rest The rest parameter
* @param {boolean} expression True if the arrow function is created via an expression.
* Always false for declarations, but kept here to be in sync with
* FunctionExpression objects.
* @returns {ASTNode} An ASTNode representing the entire arrow function expression
*/
- createArrowFunctionExpression: function (params, defaults, body, rest, expression) {
+ createArrowFunctionExpression: function (params, body, expression) {
return {
type: astNodeTypes.ArrowFunctionExpression,
id: null,
params: params,
- defaults: defaults,
body: body,
- rest: rest,
generator: false,
expression: expression
};
},
@@ -81,27 +77,41 @@
* @param {ASTNode} operator The assignment operator
* @param {ASTNode} left The left operand
* @param {ASTNode} right The right operand
* @returns {ASTNode} An ASTNode representing the entire assignment expression
*/
- createAssignmentExpression: function (operator, left, right) {
+ createAssignmentExpression: function(operator, left, right) {
return {
type: astNodeTypes.AssignmentExpression,
operator: operator,
left: left,
right: right
};
},
/**
+ * Create an ASTNode representation of an assignment pattern (default parameters)
+ * @param {ASTNode} left The left operand
+ * @param {ASTNode} right The right operand
+ * @returns {ASTNode} An ASTNode representing the entire assignment pattern
+ */
+ createAssignmentPattern: function(left, right) {
+ return {
+ type: astNodeTypes.AssignmentPattern,
+ left: left,
+ right: right
+ };
+ },
+
+ /**
* Create an ASTNode representation of a binary expression
* @param {ASTNode} operator The assignment operator
* @param {ASTNode} left The left operand
* @param {ASTNode} right The right operand
* @returns {ASTNode} An ASTNode representing the entire binary expression
*/
- createBinaryExpression: function (operator, left, right) {
+ createBinaryExpression: function(operator, left, right) {
var type = (operator === "||" || operator === "&&") ? astNodeTypes.LogicalExpression :
astNodeTypes.BinaryExpression;
return {
type: type,
operator: operator,
@@ -113,11 +123,11 @@
/**
* Create an ASTNode representation of a block statement
* @param {ASTNode} body The block statement body
* @returns {ASTNode} An ASTNode representing the entire block statement
*/
- createBlockStatement: function (body) {
+ createBlockStatement: function(body) {
return {
type: astNodeTypes.BlockStatement,
body: body
};
},
@@ -125,11 +135,11 @@
/**
* Create an ASTNode representation of a break statement
* @param {ASTNode} label The break statement label
* @returns {ASTNode} An ASTNode representing the break statement
*/
- createBreakStatement: function (label) {
+ createBreakStatement: function(label) {
return {
type: astNodeTypes.BreakStatement,
label: label
};
},
@@ -138,11 +148,11 @@
* Create an ASTNode representation of a call expression
* @param {ASTNode} callee The function being called
* @param {ASTNode[]} args An array of ASTNodes representing the function call arguments
* @returns {ASTNode} An ASTNode representing the entire call expression
*/
- createCallExpression: function (callee, args) {
+ createCallExpression: function(callee, args) {
return {
type: astNodeTypes.CallExpression,
callee: callee,
"arguments": args
};
@@ -152,11 +162,11 @@
* Create an ASTNode representation of a catch clause/block
* @param {ASTNode} param Any catch clause exeption/conditional parameter information
* @param {ASTNode} body The catch block body
* @returns {ASTNode} An ASTNode representing the entire catch clause
*/
- createCatchClause: function (param, body) {
+ createCatchClause: function(param, body) {
return {
type: astNodeTypes.CatchClause,
param: param,
body: body
};
@@ -165,54 +175,62 @@
/**
* Creates an ASTNode representation of a class body.
* @param {ASTNode} body The node representing the body of the class.
* @returns {ASTNode} An ASTNode representing the class body.
*/
- createClassBody: function (body) {
+ createClassBody: function(body) {
return {
type: astNodeTypes.ClassBody,
body: body
};
},
- createClassExpression: function (id, superClass, body) {
+ createClassExpression: function(id, superClass, body) {
return {
type: astNodeTypes.ClassExpression,
id: id,
superClass: superClass,
body: body
};
},
- createClassDeclaration: function (id, superClass, body) {
+ createClassDeclaration: function(id, superClass, body) {
return {
type: astNodeTypes.ClassDeclaration,
id: id,
superClass: superClass,
body: body
};
},
- createMethodDefinition: function (propertyType, kind, key, value, computed) {
+ createMethodDefinition: function(propertyType, kind, key, value, computed) {
return {
type: astNodeTypes.MethodDefinition,
key: key,
value: value,
kind: kind,
"static": propertyType === "static",
computed: computed
};
},
+ createMetaProperty: function(meta, property) {
+ return {
+ type: astNodeTypes.MetaProperty,
+ meta: meta,
+ property: property
+ };
+ },
+
/**
* Create an ASTNode representation of a conditional expression
* @param {ASTNode} test The conditional to evaluate
* @param {ASTNode} consequent The code to be run if the test returns true
* @param {ASTNode} alternate The code to be run if the test returns false
* @returns {ASTNode} An ASTNode representing the entire conditional expression
*/
- createConditionalExpression: function (test, consequent, alternate) {
+ createConditionalExpression: function(test, consequent, alternate) {
return {
type: astNodeTypes.ConditionalExpression,
test: test,
consequent: consequent,
alternate: alternate
@@ -222,43 +240,43 @@
/**
* Create an ASTNode representation of a continue statement
* @param {?ASTNode} label The optional continue label (null if not set)
* @returns {ASTNode} An ASTNode representing the continue statement
*/
- createContinueStatement: function (label) {
+ createContinueStatement: function(label) {
return {
type: astNodeTypes.ContinueStatement,
label: label
};
},
/**
* Create an ASTNode representation of a debugger statement
* @returns {ASTNode} An ASTNode representing the debugger statement
*/
- createDebuggerStatement: function () {
+ createDebuggerStatement: function() {
return {
type: astNodeTypes.DebuggerStatement
};
},
/**
* Create an ASTNode representation of an empty statement
* @returns {ASTNode} An ASTNode representing an empty statement
*/
- createEmptyStatement: function () {
+ createEmptyStatement: function() {
return {
type: astNodeTypes.EmptyStatement
};
},
/**
* Create an ASTNode representation of an expression statement
* @param {ASTNode} expression The expression
* @returns {ASTNode} An ASTNode representing an expression statement
*/
- createExpressionStatement: function (expression) {
+ createExpressionStatement: function(expression) {
return {
type: astNodeTypes.ExpressionStatement,
expression: expression
};
},
@@ -267,11 +285,11 @@
* Create an ASTNode representation of a while statement
* @param {ASTNode} test The while conditional
* @param {ASTNode} body The while loop body
* @returns {ASTNode} An ASTNode representing a while statement
*/
- createWhileStatement: function (test, body) {
+ createWhileStatement: function(test, body) {
return {
type: astNodeTypes.WhileStatement,
test: test,
body: body
};
@@ -281,11 +299,11 @@
* Create an ASTNode representation of a do..while statement
* @param {ASTNode} test The do..while conditional
* @param {ASTNode} body The do..while loop body
* @returns {ASTNode} An ASTNode representing a do..while statement
*/
- createDoWhileStatement: function (test, body) {
+ createDoWhileStatement: function(test, body) {
return {
type: astNodeTypes.DoWhileStatement,
body: body,
test: test
};
@@ -297,11 +315,11 @@
* @param {ASTNode} test The conditional test expression
* @param {ASTNode} update The update expression
* @param {ASTNode} body The statement body
* @returns {ASTNode} An ASTNode representing a for statement
*/
- createForStatement: function (init, test, update, body) {
+ createForStatement: function(init, test, update, body) {
return {
type: astNodeTypes.ForStatement,
init: init,
test: test,
update: update,
@@ -314,11 +332,11 @@
* @param {ASTNode} left The left-side variable for the property name
* @param {ASTNode} right The right-side object
* @param {ASTNode} body The statement body
* @returns {ASTNode} An ASTNode representing a for..in statement
*/
- createForInStatement: function (left, right, body) {
+ createForInStatement: function(left, right, body) {
return {
type: astNodeTypes.ForInStatement,
left: left,
right: right,
body: body,
@@ -331,11 +349,11 @@
* @param {ASTNode} left The left-side variable for the property value
* @param {ASTNode} right The right-side object
* @param {ASTNode} body The statement body
* @returns {ASTNode} An ASTNode representing a for..of statement
*/
- createForOfStatement: function (left, right, body) {
+ createForOfStatement: function(left, right, body) {
return {
type: astNodeTypes.ForOfStatement,
left: left,
right: right,
body: body
@@ -344,62 +362,54 @@
/**
* Create an ASTNode representation of a function declaration
* @param {ASTNode} id The function name
* @param {ASTNode} params The function arguments
- * @param {ASTNode} defaults Any default arguments (ES6-only feature)
* @param {ASTNode} body The function body
- * @param {ASTNode} rest The node representing a rest argument.
* @param {boolean} generator True if the function is a generator, false if not.
* @param {boolean} expression True if the function is created via an expression.
* Always false for declarations, but kept here to be in sync with
* FunctionExpression objects.
* @returns {ASTNode} An ASTNode representing a function declaration
*/
- createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression) {
+ createFunctionDeclaration: function (id, params, body, generator, expression) {
return {
type: astNodeTypes.FunctionDeclaration,
id: id,
params: params || [],
- defaults: defaults || [],
body: body,
- rest: rest || null,
generator: !!generator,
expression: !!expression
};
},
/**
* Create an ASTNode representation of a function expression
* @param {ASTNode} id The function name
* @param {ASTNode} params The function arguments
- * @param {ASTNode} defaults Any default arguments (ES6-only feature)
* @param {ASTNode} body The function body
- * @param {ASTNode} rest The node representing a rest argument.
* @param {boolean} generator True if the function is a generator, false if not.
* @param {boolean} expression True if the function is created via an expression.
* @returns {ASTNode} An ASTNode representing a function declaration
*/
- createFunctionExpression: function (id, params, defaults, body, rest, generator, expression) {
+ createFunctionExpression: function (id, params, body, generator, expression) {
return {
type: astNodeTypes.FunctionExpression,
id: id,
params: params || [],
- defaults: defaults || [],
body: body,
- rest: rest || null,
generator: !!generator,
expression: !!expression
};
},
/**
* Create an ASTNode representation of an identifier
* @param {ASTNode} name The identifier name
* @returns {ASTNode} An ASTNode representing an identifier
*/
- createIdentifier: function (name) {
+ createIdentifier: function(name) {
return {
type: astNodeTypes.Identifier,
name: name
};
},
@@ -409,11 +419,11 @@
* @param {ASTNode} test The if conditional expression
* @param {ASTNode} consequent The consequent if statement to run
* @param {ASTNode} alternate the "else" alternate statement
* @returns {ASTNode} An ASTNode representing an if statement
*/
- createIfStatement: function (test, consequent, alternate) {
+ createIfStatement: function(test, consequent, alternate) {
return {
type: astNodeTypes.IfStatement,
test: test,
consequent: consequent,
alternate: alternate
@@ -424,11 +434,11 @@
* Create an ASTNode representation of a labeled statement
* @param {ASTNode} label The statement label
* @param {ASTNode} body The labeled statement body
* @returns {ASTNode} An ASTNode representing a labeled statement
*/
- createLabeledStatement: function (label, body) {
+ createLabeledStatement: function(label, body) {
return {
type: astNodeTypes.LabeledStatement,
label: label,
body: body
};
@@ -438,11 +448,11 @@
* Create an ASTNode literal from the source code
* @param {ASTNode} token The ASTNode token
* @param {string} source The source code to get the literal from
* @returns {ASTNode} An ASTNode representing the new literal
*/
- createLiteralFromSource: function (token, source) {
+ createLiteralFromSource: function(token, source) {
var node = {
type: astNodeTypes.Literal,
value: token.value,
raw: source.slice(token.range[0], token.range[1])
};
@@ -461,11 +471,11 @@
* @param {string} value.raw The raw template string
* @param {string} value.cooked The processed template string
* @param {boolean} tail True if this is the final element in a template string
* @returns {ASTNode} An ASTNode representing the template string element
*/
- createTemplateElement: function (value, tail) {
+ createTemplateElement: function(value, tail) {
return {
type: astNodeTypes.TemplateElement,
value: value,
tail: tail
};
@@ -475,11 +485,11 @@
* Create an ASTNode template literal
* @param {ASTNode[]} quasis An array of the template string elements
* @param {ASTNode[]} expressions An array of the template string expressions
* @returns {ASTNode} An ASTNode representing the template string
*/
- createTemplateLiteral: function (quasis, expressions) {
+ createTemplateLiteral: function(quasis, expressions) {
return {
type: astNodeTypes.TemplateLiteral,
quasis: quasis,
expressions: expressions
};
@@ -488,25 +498,49 @@
/**
* Create an ASTNode representation of a spread element
* @param {ASTNode} argument The array being spread
* @returns {ASTNode} An ASTNode representing a spread element
*/
- createSpreadElement: function (argument) {
+ createSpreadElement: function(argument) {
return {
type: astNodeTypes.SpreadElement,
argument: argument
};
},
/**
+ * Create an ASTNode representation of an experimental rest property
+ * @param {ASTNode} argument The identifier being rested
+ * @returns {ASTNode} An ASTNode representing a rest element
+ */
+ createExperimentalRestProperty: function(argument) {
+ return {
+ type: astNodeTypes.ExperimentalRestProperty,
+ argument: argument
+ };
+ },
+
+ /**
+ * Create an ASTNode representation of an experimental spread property
+ * @param {ASTNode} argument The identifier being spread
+ * @returns {ASTNode} An ASTNode representing a spread element
+ */
+ createExperimentalSpreadProperty: function(argument) {
+ return {
+ type: astNodeTypes.ExperimentalSpreadProperty,
+ argument: argument
+ };
+ },
+
+ /**
* Create an ASTNode tagged template expression
* @param {ASTNode} tag The tag expression
* @param {ASTNode} quasi A TemplateLiteral ASTNode representing
* the template string itself.
* @returns {ASTNode} An ASTNode representing the tagged template
*/
- createTaggedTemplateExpression: function (tag, quasi) {
+ createTaggedTemplateExpression: function(tag, quasi) {
return {
type: astNodeTypes.TaggedTemplateExpression,
tag: tag,
quasi: quasi
};
@@ -517,11 +551,11 @@
* @param {string} accessor The member access method (bracket or period)
* @param {ASTNode} object The object being referenced
* @param {ASTNode} property The object-property being referenced
* @returns {ASTNode} An ASTNode representing a member expression
*/
- createMemberExpression: function (accessor, object, property) {
+ createMemberExpression: function(accessor, object, property) {
return {
type: astNodeTypes.MemberExpression,
computed: accessor === "[",
object: object,
property: property
@@ -532,11 +566,11 @@
* Create an ASTNode representation of a new expression
* @param {ASTNode} callee The constructor for the new object type
* @param {ASTNode} args The arguments passed to the constructor
* @returns {ASTNode} An ASTNode representing a new expression
*/
- createNewExpression: function (callee, args) {
+ createNewExpression: function(callee, args) {
return {
type: astNodeTypes.NewExpression,
callee: callee,
"arguments": args
};
@@ -546,11 +580,11 @@
* Create an ASTNode representation of a new object expression
* @param {ASTNode[]} properties An array of ASTNodes that represent all object
* properties and associated values
* @returns {ASTNode} An ASTNode representing a new object expression
*/
- createObjectExpression: function (properties) {
+ createObjectExpression: function(properties) {
return {
type: astNodeTypes.ObjectExpression,
properties: properties
};
},
@@ -559,11 +593,11 @@
* Create an ASTNode representation of a postfix expression
* @param {string} operator The postfix operator ("++", "--", etc.)
* @param {ASTNode} argument The operator argument
* @returns {ASTNode} An ASTNode representing a postfix expression
*/
- createPostfixExpression: function (operator, argument) {
+ createPostfixExpression: function(operator, argument) {
return {
type: astNodeTypes.UpdateExpression,
operator: operator,
argument: argument,
prefix: false
@@ -571,16 +605,18 @@
},
/**
* Create an ASTNode representation of an entire program
* @param {ASTNode} body The program body
+ * @param {string} sourceType Either "module" or "script".
* @returns {ASTNode} An ASTNode representing an entire program
*/
- createProgram: function (body) {
+ createProgram: function(body, sourceType) {
return {
type: astNodeTypes.Program,
- body: body
+ body: body,
+ sourceType: sourceType
};
},
/**
* Create an ASTNode representation of an object property
@@ -590,11 +626,11 @@
* @param {boolean} method True if the property is also a method (value is a function)
* @param {boolean} shorthand True if the property is shorthand
* @param {boolean} computed True if the property value has been computed
* @returns {ASTNode} An ASTNode representing an object property
*/
- createProperty: function (kind, key, value, method, shorthand, computed) {
+ createProperty: function(kind, key, value, method, shorthand, computed) {
return {
type: astNodeTypes.Property,
key: key,
value: value,
kind: kind,
@@ -603,15 +639,27 @@
computed: computed
};
},
/**
+ * Create an ASTNode representation of a rest element
+ * @param {ASTNode} argument The rest argument
+ * @returns {ASTNode} An ASTNode representing a rest element
+ */
+ createRestElement: function (argument) {
+ return {
+ type: astNodeTypes.RestElement,
+ argument: argument
+ };
+ },
+
+ /**
* Create an ASTNode representation of a return statement
* @param {?ASTNode} argument The return argument, null if no argument is provided
* @returns {ASTNode} An ASTNode representing a return statement
*/
- createReturnStatement: function (argument) {
+ createReturnStatement: function(argument) {
return {
type: astNodeTypes.ReturnStatement,
argument: argument
};
},
@@ -619,24 +667,34 @@
/**
* Create an ASTNode representation of a sequence of expressions
* @param {ASTNode[]} expressions An array containing each expression, in order
* @returns {ASTNode} An ASTNode representing a sequence of expressions
*/
- createSequenceExpression: function (expressions) {
+ createSequenceExpression: function(expressions) {
return {
type: astNodeTypes.SequenceExpression,
expressions: expressions
};
},
/**
+ * Create an ASTNode representation of super
+ * @returns {ASTNode} An ASTNode representing super
+ */
+ createSuper: function() {
+ return {
+ type: astNodeTypes.Super
+ };
+ },
+
+ /**
* Create an ASTNode representation of a switch case statement
* @param {ASTNode} test The case value to test against the switch value
* @param {ASTNode} consequent The consequent case statement
* @returns {ASTNode} An ASTNode representing a switch case
*/
- createSwitchCase: function (test, consequent) {
+ createSwitchCase: function(test, consequent) {
return {
type: astNodeTypes.SwitchCase,
test: test,
consequent: consequent
};
@@ -646,11 +704,11 @@
* Create an ASTNode representation of a switch statement
* @param {ASTNode} discriminant An expression to test against each case value
* @param {ASTNode[]} cases An array of switch case statements
* @returns {ASTNode} An ASTNode representing a switch statement
*/
- createSwitchStatement: function (discriminant, cases) {
+ createSwitchStatement: function(discriminant, cases) {
return {
type: astNodeTypes.SwitchStatement,
discriminant: discriminant,
cases: cases
};
@@ -658,22 +716,22 @@
/**
* Create an ASTNode representation of a this statement
* @returns {ASTNode} An ASTNode representing a this statement
*/
- createThisExpression: function () {
+ createThisExpression: function() {
return {
type: astNodeTypes.ThisExpression
};
},
/**
* Create an ASTNode representation of a throw statement
* @param {ASTNode} argument The argument to throw
* @returns {ASTNode} An ASTNode representing a throw statement
*/
- createThrowStatement: function (argument) {
+ createThrowStatement: function(argument) {
return {
type: astNodeTypes.ThrowStatement,
argument: argument
};
},
@@ -683,16 +741,14 @@
* @param {ASTNode} block The try block
* @param {ASTNode} handler A catch handler
* @param {?ASTNode} finalizer The final code block to run after the try/catch has run
* @returns {ASTNode} An ASTNode representing a try statement
*/
- createTryStatement: function (block, handler, finalizer) {
+ createTryStatement: function(block, handler, finalizer) {
return {
type: astNodeTypes.TryStatement,
block: block,
- guardedHandlers: [],
- handlers: handler ? [ handler ] : [],
handler: handler,
finalizer: finalizer
};
},
@@ -700,11 +756,11 @@
* Create an ASTNode representation of a unary expression
* @param {string} operator The unary operator
* @param {ASTNode} argument The unary operand
* @returns {ASTNode} An ASTNode representing a unary expression
*/
- createUnaryExpression: function (operator, argument) {
+ createUnaryExpression: function(operator, argument) {
if (operator === "++" || operator === "--") {
return {
type: astNodeTypes.UpdateExpression,
operator: operator,
argument: argument,
@@ -723,11 +779,11 @@
* Create an ASTNode representation of a variable declaration
* @param {ASTNode[]} declarations An array of variable declarations
* @param {string} kind The kind of variable created ("var", "let", etc.)
* @returns {ASTNode} An ASTNode representing a variable declaration
*/
- createVariableDeclaration: function (declarations, kind) {
+ createVariableDeclaration: function(declarations, kind) {
return {
type: astNodeTypes.VariableDeclaration,
declarations: declarations,
kind: kind
};
@@ -737,11 +793,11 @@
* Create an ASTNode representation of a variable declarator
* @param {ASTNode} id The variable ID
* @param {ASTNode} init The variable's initial value
* @returns {ASTNode} An ASTNode representing a variable declarator
*/
- createVariableDeclarator: function (id, init) {
+ createVariableDeclarator: function(id, init) {
return {
type: astNodeTypes.VariableDeclarator,
id: id,
init: init
};
@@ -751,156 +807,156 @@
* Create an ASTNode representation of a with statement
* @param {ASTNode} object The with statement object expression
* @param {ASTNode} body The with statement body
* @returns {ASTNode} An ASTNode representing a with statement
*/
- createWithStatement: function (object, body) {
+ createWithStatement: function(object, body) {
return {
type: astNodeTypes.WithStatement,
object: object,
body: body
};
},
- createYieldExpression: function (argument, delegate) {
+ createYieldExpression: function(argument, delegate) {
return {
type: astNodeTypes.YieldExpression,
- argument: argument,
+ argument: argument || null,
delegate: delegate
};
},
- createJSXAttribute: function (name, value) {
+ createJSXAttribute: function(name, value) {
return {
type: astNodeTypes.JSXAttribute,
name: name,
value: value || null
};
},
- createJSXSpreadAttribute: function (argument) {
+ createJSXSpreadAttribute: function(argument) {
return {
type: astNodeTypes.JSXSpreadAttribute,
argument: argument
};
},
- createJSXIdentifier: function (name) {
+ createJSXIdentifier: function(name) {
return {
type: astNodeTypes.JSXIdentifier,
name: name
};
},
- createJSXNamespacedName: function (namespace, name) {
+ createJSXNamespacedName: function(namespace, name) {
return {
type: astNodeTypes.JSXNamespacedName,
namespace: namespace,
name: name
};
},
- createJSXMemberExpression: function (object, property) {
+ createJSXMemberExpression: function(object, property) {
return {
type: astNodeTypes.JSXMemberExpression,
object: object,
property: property
};
},
- createJSXElement: function (openingElement, closingElement, children) {
+ createJSXElement: function(openingElement, closingElement, children) {
return {
type: astNodeTypes.JSXElement,
openingElement: openingElement,
closingElement: closingElement,
children: children
};
},
- createJSXEmptyExpression: function () {
+ createJSXEmptyExpression: function() {
return {
type: astNodeTypes.JSXEmptyExpression
};
},
- createJSXExpressionContainer: function (expression) {
+ createJSXExpressionContainer: function(expression) {
return {
type: astNodeTypes.JSXExpressionContainer,
expression: expression
};
},
- createJSXOpeningElement: function (name, attributes, selfClosing) {
+ createJSXOpeningElement: function(name, attributes, selfClosing) {
return {
type: astNodeTypes.JSXOpeningElement,
name: name,
selfClosing: selfClosing,
attributes: attributes
};
},
- createJSXClosingElement: function (name) {
+ createJSXClosingElement: function(name) {
return {
type: astNodeTypes.JSXClosingElement,
name: name
};
},
- createExportSpecifier: function (local, exported) {
+ createExportSpecifier: function(local, exported) {
return {
type: astNodeTypes.ExportSpecifier,
exported: exported || local,
local: local
};
},
- createImportDefaultSpecifier: function (local) {
+ createImportDefaultSpecifier: function(local) {
return {
type: astNodeTypes.ImportDefaultSpecifier,
local: local
};
},
- createImportNamespaceSpecifier: function (local) {
+ createImportNamespaceSpecifier: function(local) {
return {
type: astNodeTypes.ImportNamespaceSpecifier,
local: local
};
},
- createExportNamedDeclaration: function (declaration, specifiers, source) {
+ createExportNamedDeclaration: function(declaration, specifiers, source) {
return {
type: astNodeTypes.ExportNamedDeclaration,
declaration: declaration,
specifiers: specifiers,
source: source
};
},
- createExportDefaultDeclaration: function (declaration) {
+ createExportDefaultDeclaration: function(declaration) {
return {
type: astNodeTypes.ExportDefaultDeclaration,
declaration: declaration
};
},
- createExportAllDeclaration: function (source) {
+ createExportAllDeclaration: function(source) {
return {
type: astNodeTypes.ExportAllDeclaration,
source: source
};
},
- createImportSpecifier: function (local, imported) {
+ createImportSpecifier: function(local, imported) {
return {
type: astNodeTypes.ImportSpecifier,
local: local || imported,
imported: imported
};
},
- createImportDeclaration: function (specifiers, source) {
+ createImportDeclaration: function(specifiers, source) {
return {
type: astNodeTypes.ImportDeclaration,
specifiers: specifiers,
source: source
};
@@ -965,10 +1021,12 @@
ConditionalExpression: "ConditionalExpression",
ContinueStatement: "ContinueStatement",
DoWhileStatement: "DoWhileStatement",
DebuggerStatement: "DebuggerStatement",
EmptyStatement: "EmptyStatement",
+ ExperimentalRestProperty: "ExperimentalRestProperty",
+ ExperimentalSpreadProperty: "ExperimentalSpreadProperty",
ExpressionStatement: "ExpressionStatement",
ForStatement: "ForStatement",
ForInStatement: "ForInStatement",
ForOfStatement: "ForOfStatement",
FunctionDeclaration: "FunctionDeclaration",
@@ -977,19 +1035,22 @@
IfStatement: "IfStatement",
Literal: "Literal",
LabeledStatement: "LabeledStatement",
LogicalExpression: "LogicalExpression",
MemberExpression: "MemberExpression",
+ MetaProperty: "MetaProperty",
MethodDefinition: "MethodDefinition",
NewExpression: "NewExpression",
ObjectExpression: "ObjectExpression",
ObjectPattern: "ObjectPattern",
Program: "Program",
Property: "Property",
+ RestElement: "RestElement",
ReturnStatement: "ReturnStatement",
SequenceExpression: "SequenceExpression",
SpreadElement: "SpreadElement",
+ Super: "Super",
SwitchCase: "SwitchCase",
SwitchStatement: "SwitchStatement",
TaggedTemplateExpression: "TaggedTemplateExpression",
TemplateElement: "TemplateElement",
TemplateLiteral: "TemplateLiteral",
@@ -1134,13 +1195,25 @@
while (extra.bottomRightStack.length > 0 && extra.bottomRightStack[extra.bottomRightStack.length - 1].range[0] >= node.range[0]) {
lastChild = extra.bottomRightStack.pop();
}
if (lastChild) {
- if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) {
- node.leadingComments = lastChild.leadingComments;
- delete lastChild.leadingComments;
+ if (lastChild.leadingComments) {
+ if (lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) {
+ node.leadingComments = lastChild.leadingComments;
+ delete lastChild.leadingComments;
+ } else {
+ // A leading comment for an anonymous class had been stolen by its first MethodDefinition,
+ // so this takes back the leading comment.
+ // See Also: https://github.com/eslint/espree/issues/158
+ for (i = lastChild.leadingComments.length - 2; i >= 0; --i) {
+ if (lastChild.leadingComments[i].range[1] <= node.range[0]) {
+ node.leadingComments = lastChild.leadingComments.splice(0, i + 1);
+ break;
+ }
+ }
+ }
}
} else if (extra.leadingComments.length > 0) {
if (extra.leadingComments[extra.leadingComments.length - 1].range[1] <= node.range[0]) {
node.leadingComments = extra.leadingComments;
@@ -1298,18 +1371,24 @@
superInFunctions: false,
// enable parsing of classes
classes: false,
+ // enable parsing of new.target
+ newTarget: false,
+
// enable parsing of modules
modules: false,
// React JSX parsing
jsx: false,
// allow return statement in global scope
- globalReturn: false
+ globalReturn: false,
+
+ // allow experimental object rest/spread
+ experimentalObjectRestSpread: false
};
},{}],5:[function(require,module,exports){
/**
* @fileoverview Error messages returned by the parser.
@@ -1379,11 +1458,12 @@
StrictModeWith: "Strict mode code may not include a with statement",
StrictCatchVariable: "Catch variable may not be eval or arguments in strict mode",
StrictVarName: "Variable name may not be eval or arguments in strict mode",
StrictParamName: "Parameter name eval or arguments is not allowed in strict mode",
StrictParamDupe: "Strict mode function may not have duplicate parameter names",
- ParameterAfterRestParameter: "Rest parameter must be final parameter of an argument list",
+ TemplateOctalLiteral: "Octal literals are not allowed in template strings.",
+ ParameterAfterRestParameter: "Rest parameter must be last formal parameter",
DefaultRestParameter: "Rest parameter can not have a default value",
ElementAfterSpreadElement: "Spread must be the final element of an element list",
ObjectPatternAsRestParameter: "Invalid rest parameter",
ObjectPatternAsSpread: "Invalid spread argument",
StrictFunctionName: "Function name may not be eval or arguments in strict mode",
@@ -1581,11 +1661,11 @@
default:
return false;
}
},
- isStrictModeReservedWord: function(id) {
+ isStrictModeReservedWord: function(id, ecmaFeatures) {
switch (id) {
case "implements":
case "interface":
case "package":
case "private":
@@ -1593,10 +1673,12 @@
case "public":
case "static":
case "yield":
case "let":
return true;
+ case "await":
+ return ecmaFeatures.modules;
default:
return false;
}
},
@@ -1606,11 +1688,11 @@
// 7.6.1.1 Keywords
isKeyword: function(id, strict, ecmaFeatures) {
- if (strict && this.isStrictModeReservedWord(id)) {
+ if (strict && this.isStrictModeReservedWord(id, ecmaFeatures)) {
return true;
}
// "const" is specialized as Keyword in V8.
// "yield" and "let" are for compatiblity with SpiderMonkey and ES.next.
@@ -2043,56 +2125,64 @@
diams: "\u2666"
};
},{}],10:[function(require,module,exports){
module.exports={
- "name": "espree",
- "description": "An actively-maintained fork of Esprima, the ECMAScript parsing infrastructure for multipurpose analysis",
+ "_args": [
+ [
+ "espree@^2.2.4",
+ "/Users/force/code/eslint"
+ ]
+ ],
+ "_from": "espree@>=2.2.4 <3.0.0",
+ "_id": "espree@2.2.5",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/espree",
+ "_npmUser": {
+ "email": "nicholas@nczconsulting.com",
+ "name": "nzakas"
+ },
+ "_npmVersion": "1.4.28",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "espree",
+ "raw": "espree@^2.2.4",
+ "rawSpec": "^2.2.4",
+ "scope": null,
+ "spec": ">=2.2.4 <3.0.0",
+ "type": "range"
+ },
+ "_requiredBy": [
+ "/",
+ "/jsdoc"
+ ],
+ "_resolved": "https://registry.npmjs.org/espree/-/espree-2.2.5.tgz",
+ "_shasum": "df691b9310889402aeb29cc066708c56690b854b",
+ "_shrinkwrap": null,
+ "_spec": "espree@^2.2.4",
+ "_where": "/Users/force/code/eslint",
"author": {
- "name": "Nicholas C. Zakas",
- "email": "nicholas+npm@nczconsulting.com"
+ "email": "nicholas+npm@nczconsulting.com",
+ "name": "Nicholas C. Zakas"
},
- "homepage": "https://github.com/eslint/espree",
- "main": "espree.js",
"bin": {
"esparse": "./bin/esparse.js",
"esvalidate": "./bin/esvalidate.js"
},
- "version": "1.11.0",
- "files": [
- "bin",
- "lib",
- "test/run.js",
- "test/runner.js",
- "test/test.js",
- "test/compat.js",
- "test/reflect.js",
- "espree.js"
- ],
- "engines": {
- "node": ">=0.10.0"
- },
- "repository": {
- "type": "git",
- "url": "http://github.com/eslint/espree.git"
- },
"bugs": {
"url": "http://github.com/eslint/espree.git"
},
- "licenses": [
- {
- "type": "BSD",
- "url": "http://github.com/nzakas/espree/raw/master/LICENSE"
- }
- ],
+ "dependencies": {},
+ "description": "An actively-maintained fork of Esprima, the ECMAScript parsing infrastructure for multipurpose analysis",
"devDependencies": {
"browserify": "^7.0.0",
"chai": "^1.10.0",
"complexity-report": "~0.6.1",
"dateformat": "^1.0.11",
"eslint": "^0.9.2",
- "esprima": "git://github.com/ariya/esprima#harmony",
+ "esprima": "git://github.com/jquery/esprima.git",
"esprima-fb": "^8001.2001.0-dev-harmony-fb",
"istanbul": "~0.2.6",
"json-diff": "~0.3.1",
"leche": "^1.0.1",
"mocha": "^2.0.1",
@@ -2102,56 +2192,75 @@
"semver": "^4.1.1",
"shelljs": "^0.3.0",
"shelljs-nodecli": "^0.1.1",
"unicode-6.3.0": "~0.1.0"
},
+ "directories": {},
+ "dist": {
+ "shasum": "df691b9310889402aeb29cc066708c56690b854b",
+ "tarball": "http://registry.npmjs.org/espree/-/espree-2.2.5.tgz"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "files": [
+ "bin",
+ "espree.js",
+ "lib",
+ "test/compat.js",
+ "test/reflect.js",
+ "test/run.js",
+ "test/runner.js",
+ "test/test.js"
+ ],
+ "gitHead": "eeeeb05b879783901ff2308efcbd0cda76753cbe",
+ "homepage": "https://github.com/eslint/espree",
"keywords": [
"ast",
"ecmascript",
"javascript",
"parser",
"syntax"
],
- "scripts": {
- "generate-regex": "node tools/generate-identifier-regex.js",
- "test": "npm run-script lint && node Makefile.js test && node test/run.js",
- "lint": "node Makefile.js lint",
- "patch": "node Makefile.js patch",
- "minor": "node Makefile.js minor",
- "major": "node Makefile.js major",
- "browserify": "node Makefile.js browserify",
- "coverage": "npm run-script analyze-coverage && npm run-script check-coverage",
- "analyze-coverage": "node node_modules/istanbul/lib/cli.js cover test/runner.js",
- "check-coverage": "node node_modules/istanbul/lib/cli.js check-coverage --statement 99 --branch 99 --function 99",
- "complexity": "npm run-script analyze-complexity && npm run-script check-complexity",
- "analyze-complexity": "node tools/list-complexity.js",
- "check-complexity": "node node_modules/complexity-report/src/cli.js --maxcc 14 --silent -l -w espree.js",
- "benchmark": "node test/benchmarks.js",
- "benchmark-quick": "node test/benchmarks.js quick"
- },
- "dependencies": {},
- "gitHead": "06fdcd69a6a6006a635910c8c80baaab931cb0cd",
- "_id": "espree@1.11.0",
- "_shasum": "862c3033fad49ea1f3c5446fbab7650d7759186b",
- "_from": "espree@>=1.11.0 <2.0.0",
- "_npmVersion": "1.4.28",
- "_npmUser": {
- "name": "nzakas",
- "email": "nicholas@nczconsulting.com"
- },
+ "licenses": [
+ {
+ "type": "BSD",
+ "url": "http://github.com/nzakas/espree/raw/master/LICENSE"
+ }
+ ],
+ "main": "espree.js",
"maintainers": [
{
"name": "nzakas",
"email": "nicholas@nczconsulting.com"
}
],
- "dist": {
- "shasum": "862c3033fad49ea1f3c5446fbab7650d7759186b",
- "tarball": "http://registry.npmjs.org/espree/-/espree-1.11.0.tgz"
+ "name": "espree",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/eslint/espree.git"
},
- "_resolved": "https://registry.npmjs.org/espree/-/espree-1.11.0.tgz",
- "readme": "ERROR: No README data found!"
+ "scripts": {
+ "analyze-complexity": "node tools/list-complexity.js",
+ "analyze-coverage": "node node_modules/istanbul/lib/cli.js cover test/runner.js",
+ "benchmark": "node test/benchmarks.js",
+ "benchmark-quick": "node test/benchmarks.js quick",
+ "browserify": "node Makefile.js browserify",
+ "check-complexity": "node node_modules/complexity-report/src/cli.js --maxcc 14 --silent -l -w espree.js",
+ "check-coverage": "node node_modules/istanbul/lib/cli.js check-coverage --statement 99 --branch 99 --function 99",
+ "complexity": "npm run-script analyze-complexity && npm run-script check-complexity",
+ "coverage": "npm run-script analyze-coverage && npm run-script check-coverage",
+ "generate-regex": "node tools/generate-identifier-regex.js",
+ "lint": "node Makefile.js lint",
+ "major": "node Makefile.js major",
+ "minor": "node Makefile.js minor",
+ "patch": "node Makefile.js patch",
+ "test": "npm run-script lint && node Makefile.js test && node test/run.js"
+ },
+ "version": "2.2.5"
}
},{}],"espree":[function(require,module,exports){
/*
Copyright (C) 2015 Fred K. Schott <fkschott@gmail.com>
@@ -2580,25 +2689,49 @@
// Check for most common single-character punctuators.
case 40: // ( open bracket
case 41: // ) close bracket
case 59: // ; semicolon
case 44: // , comma
- case 123: // { open curly brace
- case 125: // } close curly brace
case 91: // [
case 93: // ]
case 58: // :
case 63: // ?
case 126: // ~
++index;
- if (extra.tokenize) {
- if (code === 40) {
- extra.openParenToken = extra.tokens.length;
- } else if (code === 123) {
- extra.openCurlyToken = extra.tokens.length;
+
+ if (extra.tokenize && code === 40) {
+ extra.openParenToken = extra.tokens.length;
+ }
+
+ return {
+ type: Token.Punctuator,
+ value: String.fromCharCode(code),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+
+ case 123: // { open curly brace
+ case 125: // } close curly brace
+ ++index;
+
+ if (extra.tokenize && code === 123) {
+ extra.openCurlyToken = extra.tokens.length;
+ }
+
+ // lookahead2 function can cause tokens to be scanned twice and in doing so
+ // would wreck the curly stack by pushing the same token onto the stack twice.
+ // curlyLastIndex ensures each token is pushed or popped exactly once
+ if (index > state.curlyLastIndex) {
+ state.curlyLastIndex = index;
+ if (code === 123) {
+ state.curlyStack.push("{");
+ } else {
+ state.curlyStack.pop();
}
}
+
return {
type: Token.Punctuator,
value: String.fromCharCode(code),
lineNumber: lineNumber,
lineStart: lineStart,
@@ -2709,10 +2842,11 @@
}
// The ... operator (spread, restParams, JSX, etc.)
if (extra.ecmaFeatures.spread ||
extra.ecmaFeatures.restParams ||
+ extra.ecmaFeatures.experimentalObjectRestSpread ||
(extra.ecmaFeatures.jsx && state.inJSXSpreadAttribute)
) {
if (ch1 === "." && ch2 === "." && ch3 === ".") {
index += 3;
return {
@@ -3103,11 +3237,10 @@
*/
function scanTemplate() {
var cooked = "",
ch,
escapedSequence,
- octal = false,
start = index,
terminated = false,
tail = false,
head = (source[index] === "`");
@@ -3128,12 +3261,17 @@
}
cooked += ch;
} else if (ch === "\\") {
ch = source[index++];
escapedSequence = scanEscapeSequence(ch);
+
+ if (escapedSequence.octal) {
+ throwError({}, Messages.TemplateOctalLiteral);
+ }
+
cooked += escapedSequence.ch;
- octal = escapedSequence.octal || octal;
+
} else if (syntax.isLineTerminator(ch.charCodeAt(0))) {
++lineNumber;
if (ch === "\r" && source[index] === "\n") {
++index;
}
@@ -3146,56 +3284,36 @@
if (!terminated) {
throwError({}, Messages.UnexpectedToken, "ILLEGAL");
}
+ if (index > state.curlyLastIndex) {
+ state.curlyLastIndex = index;
+
+ if (!tail) {
+ state.curlyStack.push("template");
+ }
+
+ if (!head) {
+ state.curlyStack.pop();
+ }
+ }
+
return {
type: Token.Template,
value: {
cooked: cooked,
raw: source.slice(start + 1, index - ((tail) ? 1 : 2))
},
head: head,
tail: tail,
- octal: octal,
lineNumber: lineNumber,
lineStart: lineStart,
range: [start, index]
};
}
-/**
- * Scan a template string element and return a ASTNode representation
- * @param {Object} options Scan options
- * @param {Object} options.head True if this element is the first in the
- * template string, false otherwise.
- * @returns {ASTNode} The template element node
- * @private
- */
-function scanTemplateElement(options) {
- var startsWith, template;
-
- lookahead = null;
- skipComment();
-
- startsWith = (options.head) ? "`" : "}";
-
- if (source[index] !== startsWith) {
- throwError({}, Messages.UnexpectedToken, "ILLEGAL");
- }
-
- template = scanTemplate();
-
- if (!template.tail) {
- extra.curlies.push("template");
- }
-
- peek();
-
- return template;
-}
-
function testRegExp(pattern, flags) {
var tmp = pattern,
validFlags = "gmsi";
if (extra.ecmaFeatures.regexYFlag) {
@@ -3538,12 +3656,11 @@
// Template strings start with backtick (U+0096) or closing curly brace (125) and backtick.
if (allowTemplateStrings) {
// template strings start with backtick (96) or open curly (125) but only if the open
// curly closes a previously opened curly from a template.
- if (ch === 96 || (ch === 125 && extra.curlies[extra.curlies.length - 1] === "template")) {
- extra.curlies.pop();
+ if (ch === 96 || (ch === 125 && state.curlyStack[state.curlyStack.length - 1] === "template")) {
return scanTemplate();
}
}
if (syntax.isIdentifierStart(ch)) {
@@ -3626,26 +3743,10 @@
index = token.range[1];
lineNumber = token.lineNumber;
lineStart = token.lineStart;
- if (token.type === Token.Template) {
- if (token.tail) {
- extra.curlies.pop();
- } else {
- extra.curlies.push("template");
- }
- }
-
- if (token.value === "{") {
- extra.curlies.push("{");
- }
-
- if (token.value === "}") {
- extra.curlies.pop();
- }
-
return token;
}
function peek() {
var pos,
@@ -4110,11 +4211,11 @@
/**
* Applies location information to the given node by using the given marker.
* The marker indicates the point at which the node is said to have to begun
* in the source code.
- * @param {Object} marker The market to use for the node.
+ * @param {Object} marker The marker to use for the node.
* @param {ASTNode} node The AST node to apply location information to.
* @returns {ASTNode} The node that was passed in.
* @private
*/
function markerApply(marker, node) {
@@ -4231,11 +4332,11 @@
if (typeof token.lineNumber === "number") {
error = new Error("Line " + token.lineNumber + ": " + msg);
error.index = token.range[0];
error.lineNumber = token.lineNumber;
- error.column = token.range[0] - lineStart + 1;
+ error.column = token.range[0] - token.lineStart + 1;
} else {
error = new Error("Line " + lineNumber + ": " + msg);
error.index = index;
error.lineNumber = lineNumber;
error.column = index - lineStart + 1;
@@ -4279,11 +4380,11 @@
}
if (token.type === Token.Keyword) {
if (syntax.isFutureReservedWord(token.value)) {
throwError(token, Messages.UnexpectedReserved);
- } else if (strict && syntax.isStrictModeReservedWord(token.value)) {
+ } else if (strict && syntax.isStrictModeReservedWord(token.value, extra.ecmaFeatures)) {
throwErrorTolerant(token, Messages.StrictReservedWord);
return;
}
throwError(token, Messages.UnexpectedToken, token.value);
}
@@ -4398,15 +4499,11 @@
lex(); // only get here when you have [a,,] or similar
elements.push(null);
} else {
tmp = parseSpreadOrAssignmentExpression();
elements.push(tmp);
- if (tmp && tmp.type === astNodeTypes.SpreadElement) {
- if (!match("]")) {
- throwError({}, Messages.ElementAfterSpreadElement);
- }
- } else if (!(match("]"))) {
+ if (!(match("]"))) {
expect(","); // handles the common case of comma-separated values
}
}
}
@@ -4443,13 +4540,11 @@
state.yieldAllowed = previousYieldAllowed;
return markerApply(options.marker, astNodeFactory.createFunctionExpression(
null,
paramInfo.params,
- paramInfo.defaults,
body,
- paramInfo.rest,
generator,
body.type !== astNodeTypes.BlockStatement
));
}
@@ -4554,15 +4649,13 @@
expect("(");
expect(")");
value = parsePropertyFunction({
params: [],
- defaults: [],
stricted: null,
firstRestricted: null,
- message: null,
- rest: null
+ message: null
}, {
marker: methodMarker
});
return markerApply(marker, astNodeFactory.createProperty("get", key, value, false, false, computed));
@@ -4574,23 +4667,18 @@
expect("(");
options = {
params: [],
defaultCount: 0,
- defaults: [],
stricted: null,
firstRestricted: null,
- paramSet: new StringMap(),
- rest: null
+ paramSet: new StringMap()
};
if (match(")")) {
- throwErrorTolerant(lookahead, Messages.UnexpectedToken);
+ throwErrorTolerant(lookahead, Messages.UnexpectedToken, lookahead.value);
} else {
parseParam(options);
- if (options.defaultCount === 0) {
- options.defaults = [];
- }
}
expect(")");
value = parsePropertyFunction(options, { marker: methodMarker });
return markerApply(marker, astNodeFactory.createProperty("set", key, value, false, false, computed));
@@ -4604,18 +4692,46 @@
// Not a MethodDefinition.
return null;
}
+/**
+ * Parses Generator Properties
+ * @param {ASTNode} key The property key (usually an identifier).
+ * @param {Object} marker The marker to use for the node.
+ * @returns {ASTNode} The generator property node.
+ */
+function parseGeneratorProperty(key, marker) {
+
+ var computed = (lookahead.type === Token.Punctuator && lookahead.value === "[");
+
+ if (!match("(")) {
+ throwUnexpected(lex());
+ }
+
+ return markerApply(
+ marker,
+ astNodeFactory.createProperty(
+ "init",
+ key,
+ parsePropertyMethodFunction({ generator: true }),
+ true,
+ false,
+ computed
+ )
+ );
+}
+
// TODO(nzakas): Update to match Esprima
function parseObjectProperty() {
var token, key, id, computed, methodMarker, options;
var allowComputed = extra.ecmaFeatures.objectLiteralComputedProperties,
allowMethod = extra.ecmaFeatures.objectLiteralShorthandMethods,
allowShorthand = extra.ecmaFeatures.objectLiteralShorthandProperties,
allowGenerators = extra.ecmaFeatures.generators,
allowDestructuring = extra.ecmaFeatures.destructuring,
+ allowSpread = extra.ecmaFeatures.experimentalObjectRestSpread,
marker = markerCreate();
token = lookahead;
computed = (token.value === "[" && token.type === Token.Punctuator);
@@ -4625,11 +4741,12 @@
/*
* Check for getters and setters. Be careful! "get" and "set" are legal
* method names. It's only a getter or setter if followed by a space.
*/
- if (token.value === "get" && !(match(":") || match("("))) {
+ if (token.value === "get" &&
+ !(match(":") || match("(") || match(",") || match("}"))) {
computed = (lookahead.value === "[");
key = parseObjectPropertyKey();
methodMarker = markerCreate();
expect("(");
expect(")");
@@ -4649,33 +4766,29 @@
computed
)
);
}
- if (token.value === "set" && !(match(":") || match("("))) {
+ if (token.value === "set" &&
+ !(match(":") || match("(") || match(",") || match("}"))) {
computed = (lookahead.value === "[");
key = parseObjectPropertyKey();
methodMarker = markerCreate();
expect("(");
options = {
params: [],
defaultCount: 0,
- defaults: [],
stricted: null,
firstRestricted: null,
- paramSet: new StringMap(),
- rest: null
+ paramSet: new StringMap()
};
if (match(")")) {
throwErrorTolerant(lookahead, Messages.UnexpectedToken, lookahead.value);
} else {
parseParam(options);
- if (options.defaultCount === 0) {
- options.defaults = [];
- }
}
expect(")");
return markerApply(
@@ -4763,37 +4876,28 @@
false
)
);
}
- // only possibility in this branch is a generator
+ // object spread property
+ if (allowSpread && match("...")) {
+ lex();
+ return markerApply(marker, astNodeFactory.createExperimentalSpreadProperty(parseAssignmentExpression()));
+ }
+
+ // only possibility in this branch is a shorthand generator
if (token.type === Token.EOF || token.type === Token.Punctuator) {
- if (!allowGenerators || !match("*")) {
+ if (!allowGenerators || !match("*") || !allowMethod) {
throwUnexpected(token);
}
+
lex();
- computed = (lookahead.type === Token.Punctuator && lookahead.value === "[");
-
id = parseObjectPropertyKey();
- if (!match("(")) {
- throwUnexpected(lex());
- }
+ return parseGeneratorProperty(id, marker);
- return markerApply(
- marker,
- astNodeFactory.createProperty(
- "init",
- id,
- parsePropertyMethodFunction({ generator: true }),
- true,
- false,
- computed
- )
- );
-
}
/*
* If we've made it here, then that means the property name is represented
* by a string (i.e, { "foo": 2}). The only options here are normal
@@ -4851,21 +4955,22 @@
property,
name,
propertyFn,
kind,
storedKind,
+ previousInObjectLiteral = state.inObjectLiteral,
kindMap = new StringMap();
state.inObjectLiteral = true;
expect("{");
while (!match("}")) {
property = parseObjectProperty();
- if (!property.computed) {
+ if (!property.computed && property.type.indexOf("Experimental") === -1) {
name = getFieldName(property.key);
propertyFn = (property.kind === "get") ? PropertyKind.Get : PropertyKind.Set;
kind = (property.kind === "init") ? PropertyKind.Data : propertyFn;
@@ -4901,30 +5006,43 @@
}
}
expect("}");
- state.inObjectLiteral = false;
+ state.inObjectLiteral = previousInObjectLiteral;
return markerApply(marker, astNodeFactory.createObjectExpression(properties));
}
/**
* Parse a template string element and return its ASTNode representation
- * @param {Object} options Parsing & scanning options
- * @param {Object} options.head True if this element is the first in the
+ * @param {Object} option Parsing & scanning options
+ * @param {Object} option.head True if this element is the first in the
* template string, false otherwise.
* @returns {ASTNode} The template element node with marker info applied
* @private
*/
-function parseTemplateElement(options) {
- var marker = markerCreate(),
- token = scanTemplateElement(options);
- if (strict && token.octal) {
- throwError(token, Messages.StrictOctalLiteral);
+function parseTemplateElement(option) {
+ var marker, token;
+
+ if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) {
+ throwError({}, Messages.UnexpectedToken, "ILLEGAL");
}
- return markerApply(marker, astNodeFactory.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail));
+
+ marker = markerCreate();
+ token = lex();
+
+ return markerApply(
+ marker,
+ astNodeFactory.createTemplateElement(
+ {
+ raw: token.value.raw,
+ cooked: token.value.cooked
+ },
+ token.tail
+ )
+ );
}
/**
* Parse a template string literal and return its ASTNode representation
* @returns {ASTNode} The template literal node with marker info applied
@@ -4967,12 +5085,12 @@
function parsePrimaryExpression() {
var type, token, expr,
marker,
allowJSX = extra.ecmaFeatures.jsx,
- allowSuper = extra.ecmaFeatures.superInFunctions,
- allowClasses = extra.ecmaFeatures.classes;
+ allowClasses = extra.ecmaFeatures.classes,
+ allowSuper = allowClasses || extra.ecmaFeatures.superInFunctions;
if (match("(")) {
return parseGroupExpression();
}
@@ -5004,11 +5122,11 @@
}
if (allowSuper && matchKeyword("super") && state.inFunctionBody) {
marker = markerCreate();
lex();
- return markerApply(marker, astNodeFactory.createIdentifier("super"));
+ return markerApply(marker, astNodeFactory.createSuper());
}
if (matchKeyword("this")) {
marker = markerCreate();
lex();
@@ -5048,20 +5166,17 @@
function parseArguments() {
var args = [], arg;
expect("(");
-
if (!match(")")) {
while (index < length) {
arg = parseSpreadOrAssignmentExpression();
args.push(arg);
if (match(")")) {
break;
- } else if (arg.type === astNodeTypes.SpreadElement) {
- throwError({}, Messages.ElementAfterSpreadElement);
}
expect(",");
}
}
@@ -5114,10 +5229,23 @@
function parseNewExpression() {
var callee, args,
marker = markerCreate();
expectKeyword("new");
+
+ if (extra.ecmaFeatures.newTarget && match(".")) {
+ lex();
+ if (lookahead.type === Token.Identifier && lookahead.value === "target") {
+ if (state.inFunctionBody) {
+ lex();
+ return markerApply(marker, astNodeFactory.createMetaProperty("new", "target"));
+ }
+ }
+
+ throwUnexpected(lookahead);
+ }
+
callee = parseLeftHandSideExpression();
args = match("(") ? parseArguments() : [];
return markerApply(marker, astNodeFactory.createNewExpression(callee, args));
}
@@ -5138,11 +5266,11 @@
expr = markerApply(marker, astNodeFactory.createCallExpression(expr, args));
} else if (match("[")) {
expr = markerApply(marker, astNodeFactory.createMemberExpression("[", expr, parseComputedMember()));
} else if (match(".")) {
expr = markerApply(marker, astNodeFactory.createMemberExpression(".", expr, parseNonComputedMember()));
- } else if (!lookahead.tail) {
+ } else {
expr = markerApply(marker, astNodeFactory.createTaggedTemplateExpression(expr, parseTemplateLiteral()));
}
}
return expr;
@@ -5416,41 +5544,61 @@
}
return parseAssignmentExpression();
}
function reinterpretAsCoverFormalsList(expressions) {
- var i, len, param, params, defaults, defaultCount, options, rest;
+ var i, len, param, params, options,
+ allowRestParams = extra.ecmaFeatures.restParams;
params = [];
- defaults = [];
- defaultCount = 0;
- rest = null;
options = {
paramSet: new StringMap()
};
for (i = 0, len = expressions.length; i < len; i += 1) {
param = expressions[i];
if (param.type === astNodeTypes.Identifier) {
params.push(param);
- defaults.push(null);
validateParam(options, param, param.name);
} else if (param.type === astNodeTypes.ObjectExpression || param.type === astNodeTypes.ArrayExpression) {
reinterpretAsDestructuredParameter(options, param);
params.push(param);
- defaults.push(null);
} else if (param.type === astNodeTypes.SpreadElement) {
assert(i === len - 1, "It is guaranteed that SpreadElement is last element by parseExpression");
if (param.argument.type !== astNodeTypes.Identifier) {
- throwError({}, Messages.InvalidLHSInFormalsList);
+ throwError({}, Messages.UnexpectedToken, "[");
}
- reinterpretAsDestructuredParameter(options, param.argument);
- rest = param.argument;
+
+ if (!allowRestParams) {
+ // can't get correct line/column here :(
+ throwError({}, Messages.UnexpectedToken, ".");
+ }
+
+ validateParam(options, param.argument, param.argument.name);
+ param.type = astNodeTypes.RestElement;
+ params.push(param);
+ } else if (param.type === astNodeTypes.RestElement) {
+ params.push(param);
+ validateParam(options, param.argument, param.argument.name);
} else if (param.type === astNodeTypes.AssignmentExpression) {
- params.push(param.left);
- defaults.push(param.right);
- ++defaultCount;
+
+ // TODO: Find a less hacky way of doing this
+ param.type = astNodeTypes.AssignmentPattern;
+ delete param.operator;
+
+ if (param.right.type === astNodeTypes.YieldExpression) {
+ if (param.right.argument) {
+ throwUnexpected(lookahead);
+ }
+
+ param.right.type = astNodeTypes.Identifier;
+ param.right.name = "yield";
+ delete param.right.argument;
+ delete param.right.delegate;
+ }
+
+ params.push(param);
validateParam(options, param.left, param.left.name);
} else {
return null;
}
}
@@ -5460,31 +5608,29 @@
strict ? options.stricted : options.firstRestricted,
options.message
);
}
- // must be here so it's not an array of [null, null]
- if (defaultCount === 0) {
- defaults = [];
- }
-
return {
params: params,
- defaults: defaults,
- rest: rest,
stricted: options.stricted,
firstRestricted: options.firstRestricted,
message: options.message
};
}
function parseArrowFunctionExpression(options, marker) {
var previousStrict, body;
+ var arrowStart = lineNumber;
expect("=>");
previousStrict = strict;
+ if (lineNumber > arrowStart) {
+ throwError({}, Messages.UnexpectedToken, "=>");
+ }
+
body = parseConciseBody();
if (strict && options.firstRestricted) {
throwError(options.firstRestricted, options.message);
}
@@ -5493,33 +5639,44 @@
}
strict = previousStrict;
return markerApply(marker, astNodeFactory.createArrowFunctionExpression(
options.params,
- options.defaults,
body,
- options.rest,
body.type !== astNodeTypes.BlockStatement
));
}
// 11.13 Assignment Operators
// 12.14.5 AssignmentPattern
function reinterpretAsAssignmentBindingPattern(expr) {
var i, len, property, element,
- allowDestructuring = extra.ecmaFeatures.destructuring;
+ allowDestructuring = extra.ecmaFeatures.destructuring,
+ allowRest = extra.ecmaFeatures.experimentalObjectRestSpread;
if (!allowDestructuring) {
throwUnexpected(lex());
}
if (expr.type === astNodeTypes.ObjectExpression) {
expr.type = astNodeTypes.ObjectPattern;
for (i = 0, len = expr.properties.length; i < len; i += 1) {
property = expr.properties[i];
+
+ if (allowRest && property.type === astNodeTypes.ExperimentalSpreadProperty) {
+
+ // only allow identifiers
+ if (property.argument.type !== astNodeTypes.Identifier) {
+ throwErrorTolerant({}, "Invalid object rest.");
+ }
+
+ property.type = astNodeTypes.ExperimentalRestProperty;
+ return;
+ }
+
if (property.kind !== "init") {
throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
}
reinterpretAsAssignmentBindingPattern(property.value);
}
@@ -5630,11 +5787,10 @@
node = left = parseConditionalExpression();
if (match("=>") &&
(state.parenthesisCount === oldParenthesisCount ||
state.parenthesisCount === (oldParenthesisCount + 1))) {
-
if (node.type === astNodeTypes.Identifier) {
params = reinterpretAsCoverFormalsList([ node ]);
} else if (node.type === astNodeTypes.AssignmentExpression ||
node.type === astNodeTypes.ArrayExpression ||
node.type === astNodeTypes.ObjectExpression) {
@@ -5645,10 +5801,11 @@
} else if (node.type === astNodeTypes.SequenceExpression) {
params = reinterpretAsCoverFormalsList(node.expressions);
}
if (params) {
+ state.parenthesisCount--;
return parseArrowFunctionExpression(params, marker);
}
}
if (matchAssign()) {
@@ -5665,10 +5822,11 @@
throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
}
token = lex();
right = parseAssignmentExpression();
+
node = markerApply(marker, astNodeFactory.createAssignmentExpression(token.value, left, right));
}
return node;
}
@@ -5749,11 +5907,11 @@
marker = markerCreate();
token = lex();
if (token.type !== Token.Identifier) {
- if (strict && token.type === Token.Keyword && syntax.isStrictModeReservedWord(token.value)) {
+ if (strict && token.type === Token.Keyword && syntax.isStrictModeReservedWord(token.value, extra.ecmaFeatures)) {
throwErrorTolerant(token, Messages.StrictReservedWord);
} else {
throwUnexpected(token);
}
}
@@ -5836,10 +5994,34 @@
consumeSemicolon();
return markerApply(marker, astNodeFactory.createVariableDeclaration(declarations, kind));
}
+
+function parseRestElement() {
+ var param,
+ marker = markerCreate();
+
+ lex();
+
+ if (match("{")) {
+ throwError(lookahead, Messages.ObjectPatternAsRestParameter);
+ }
+
+ param = parseVariableIdentifier();
+
+ if (match("=")) {
+ throwError(lookahead, Messages.DefaultRestParameter);
+ }
+
+ if (!match(")")) {
+ throwError(lookahead, Messages.ParameterAfterRestParameter);
+ }
+
+ return markerApply(marker, astNodeFactory.createRestElement(param));
+}
+
// 12.3 Empty Statement
function parseEmptyStatement() {
expect(";");
return astNodeFactory.createEmptyStatement();
@@ -5977,10 +6159,15 @@
} else {
state.allowIn = false;
init = parseExpression();
state.allowIn = true;
+ if (init.type === astNodeTypes.ArrayExpression) {
+ init.type = astNodeTypes.ArrayPattern;
+ }
+
+
if (allowForOf && matchContextualKeyword("of")) {
operator = lex();
left = init;
right = parseExpression();
init = null;
@@ -6199,10 +6386,13 @@
while (index < length) {
if (match("}") || matchKeyword("default") || matchKeyword("case")) {
break;
}
statement = parseSourceElement();
+ if (typeof statement === "undefined") {
+ break;
+ }
consequent.push(statement);
}
return markerApply(marker, astNodeFactory.createSwitchCase(test, consequent));
}
@@ -6272,22 +6462,42 @@
// 12.14 The try statement
function parseCatchClause() {
var param, body,
- marker = markerCreate();
+ marker = markerCreate(),
+ allowDestructuring = extra.ecmaFeatures.destructuring,
+ options = {
+ paramSet: new StringMap()
+ };
expectKeyword("catch");
expect("(");
if (match(")")) {
throwUnexpected(lookahead);
}
- param = parseVariableIdentifier();
+ if (match("[")) {
+ if (!allowDestructuring) {
+ throwUnexpected(lookahead);
+ }
+ param = parseArrayInitialiser();
+ reinterpretAsDestructuredParameter(options, param);
+ } else if (match("{")) {
+
+ if (!allowDestructuring) {
+ throwUnexpected(lookahead);
+ }
+ param = parseObjectInitialiser();
+ reinterpretAsDestructuredParameter(options, param);
+ } else {
+ param = parseVariableIdentifier();
+ }
+
// 12.14.1
- if (strict && syntax.isRestrictedWord(param.name)) {
+ if (strict && param.name && syntax.isRestrictedWord(param.name)) {
throwErrorTolerant({}, Messages.StrictCatchVariable);
}
expect(")");
body = parseBlock();
@@ -6461,11 +6671,11 @@
oldLabelSet = state.labelSet;
oldInIteration = state.inIteration;
oldInSwitch = state.inSwitch;
oldInFunctionBody = state.inFunctionBody;
- oldParenthesisCount = state.parenthesizedCount;
+ oldParenthesisCount = state.parenthesisCount;
state.labelSet = new StringMap();
state.inIteration = false;
state.inSwitch = false;
state.inFunctionBody = true;
@@ -6489,11 +6699,11 @@
state.labelSet = oldLabelSet;
state.inIteration = oldInIteration;
state.inSwitch = oldInSwitch;
state.inFunctionBody = oldInFunctionBody;
- state.parenthesizedCount = oldParenthesisCount;
+ state.parenthesisCount = oldParenthesisCount;
return markerApply(marker, astNodeFactory.createBlockStatement(sourceElements));
}
function validateParam(options, param, name) {
@@ -6510,11 +6720,11 @@
}
} else if (!options.firstRestricted) {
if (syntax.isRestrictedWord(name)) {
options.firstRestricted = param;
options.message = Messages.StrictParamName;
- } else if (syntax.isStrictModeReservedWord(name)) {
+ } else if (syntax.isStrictModeReservedWord(name, extra.ecmaFeatures)) {
options.firstRestricted = param;
options.message = Messages.StrictReservedWord;
} else if (options.paramSet.has(name)) {
options.firstRestricted = param;
options.message = Messages.StrictParamDupe;
@@ -6522,35 +6732,34 @@
}
options.paramSet.set(name, true);
}
function parseParam(options) {
- var token, rest, param, def,
+ var token, param, def,
allowRestParams = extra.ecmaFeatures.restParams,
allowDestructuring = extra.ecmaFeatures.destructuring,
- allowDefaultParams = extra.ecmaFeatures.defaultParams;
+ allowDefaultParams = extra.ecmaFeatures.defaultParams,
+ marker = markerCreate();
-
token = lookahead;
if (token.value === "...") {
if (!allowRestParams) {
throwUnexpected(lookahead);
}
- token = lex();
- rest = true;
+ param = parseRestElement();
+ validateParam(options, param.argument, param.argument.name);
+ options.params.push(param);
+ return false;
}
if (match("[")) {
if (!allowDestructuring) {
throwUnexpected(lookahead);
}
param = parseArrayInitialiser();
reinterpretAsDestructuredParameter(options, param);
} else if (match("{")) {
- if (rest) {
- throwError({}, Messages.ObjectPatternAsRestParameter);
- }
if (!allowDestructuring) {
throwUnexpected(lookahead);
}
param = parseObjectInitialiser();
reinterpretAsDestructuredParameter(options, param);
@@ -6558,45 +6767,41 @@
param = parseVariableIdentifier();
validateParam(options, token, token.value);
}
if (match("=")) {
- if (rest) {
- throwErrorTolerant(lookahead, Messages.DefaultRestParameter);
- }
if (allowDefaultParams || allowDestructuring) {
lex();
def = parseAssignmentExpression();
++options.defaultCount;
} else {
throwUnexpected(lookahead);
}
}
- if (rest) {
- if (!match(")")) {
- throwError({}, Messages.ParameterAfterRestParameter);
- }
- options.rest = param;
- return false;
+ if (def) {
+ options.params.push(markerApply(
+ marker,
+ astNodeFactory.createAssignmentPattern(
+ param,
+ def
+ )
+ ));
+ } else {
+ options.params.push(param);
}
- options.params.push(param);
- options.defaults.push(def ? def : null); // TODO: determine if null or undefined (see: #55)
-
return !match(")");
}
function parseParams(firstRestricted) {
var options;
options = {
params: [],
defaultCount: 0,
- defaults: [],
- rest: null,
firstRestricted: firstRestricted
};
expect("(");
@@ -6610,18 +6815,12 @@
}
}
expect(")");
- if (options.defaultCount === 0) {
- options.defaults = [];
- }
-
return {
params: options.params,
- defaults: options.defaults,
- rest: options.rest,
stricted: options.stricted,
firstRestricted: options.firstRestricted,
message: options.message
};
}
@@ -6651,11 +6850,11 @@
}
} else {
if (syntax.isRestrictedWord(token.value)) {
firstRestricted = token;
message = Messages.StrictFunctionName;
- } else if (syntax.isStrictModeReservedWord(token.value)) {
+ } else if (syntax.isStrictModeReservedWord(token.value, extra.ecmaFeatures)) {
firstRestricted = token;
message = Messages.StrictReservedWord;
}
}
}
@@ -6684,13 +6883,11 @@
return markerApply(
marker,
astNodeFactory.createFunctionDeclaration(
id,
tmp.params,
- tmp.defaults,
body,
- tmp.rest,
generator,
false
)
);
}
@@ -6718,11 +6915,11 @@
}
} else {
if (syntax.isRestrictedWord(token.value)) {
firstRestricted = token;
message = Messages.StrictFunctionName;
- } else if (syntax.isStrictModeReservedWord(token.value)) {
+ } else if (syntax.isStrictModeReservedWord(token.value, extra.ecmaFeatures)) {
firstRestricted = token;
message = Messages.StrictReservedWord;
}
}
}
@@ -6751,13 +6948,11 @@
return markerApply(
marker,
astNodeFactory.createFunctionExpression(
id,
tmp.params,
- tmp.defaults,
body,
- tmp.rest,
generator,
false
)
);
}
@@ -6776,12 +6971,20 @@
if (match("*")) {
lex();
delegateFlag = true;
}
- expr = parseAssignmentExpression();
+ if (peekLineTerminator()) {
+ return markerApply(marker, astNodeFactory.createYieldExpression(null, delegateFlag));
+ }
+ if (!match(";") && !match(")")) {
+ if (!match("}") && lookahead.type !== Token.EOF) {
+ expr = parseAssignmentExpression();
+ }
+ }
+
return markerApply(marker, astNodeFactory.createYieldExpression(expr, delegateFlag));
}
// Modules grammar from:
// people.mozilla.org/~jorendorff/es6-draft.html
@@ -6841,11 +7044,11 @@
expect("{");
if (!match("}")) {
do {
isExportFromIdentifier = isExportFromIdentifier || matchKeyword("default");
specifiers.push(parseExportSpecifier());
- } while (match(",") && lex());
+ } while (match(",") && lex() && !match("}"));
}
expect("}");
if (matchContextualKeyword("from")) {
// covering:
@@ -6971,11 +7174,11 @@
// {foo, bar as bas}
expect("{");
if (!match("}")) {
do {
specifiers.push(parseImportSpecifier());
- } while (match(",") && lex());
+ } while (match(",") && lex() && !match("}"));
}
expect("}");
return specifiers;
}
@@ -7061,11 +7264,13 @@
// 14.3.7
// 14.5 Class Definitions
function parseClassBody() {
- var token, isStatic, hasConstructor = false, body = [], method, computed, key;
+ var hasConstructor = false, generator = false,
+ allowGenerators = extra.ecmaFeatures.generators,
+ token, isStatic, body = [], method, computed, key;
var existingProps = {},
topMarker = markerCreate(),
marker;
@@ -7082,31 +7287,54 @@
continue;
}
token = lookahead;
isStatic = false;
+ generator = match("*");
computed = match("[");
marker = markerCreate();
+
+ if (generator) {
+ if (!allowGenerators) {
+ throwUnexpected(lookahead);
+ }
+ lex();
+ }
+
key = parseObjectPropertyKey();
+ // static generator methods
+ if (key.name === "static" && match("*")) {
+ if (!allowGenerators) {
+ throwUnexpected(lookahead);
+ }
+ generator = true;
+ lex();
+ }
+
if (key.name === "static" && lookaheadPropertyName()) {
token = lookahead;
isStatic = true;
computed = match("[");
key = parseObjectPropertyKey();
}
- method = tryParseMethodDefinition(token, key, computed, marker);
+ if (generator) {
+ method = parseGeneratorProperty(key, marker);
+ } else {
+ method = tryParseMethodDefinition(token, key, computed, marker, generator);
+ }
if (method) {
method.static = isStatic;
if (method.kind === "init") {
method.kind = "method";
}
if (!isStatic) {
- if (!method.computed && (method.key.name || method.key.value.toString()) === "constructor") {
+
+ if (!method.computed && (method.key.name || (method.key.value && method.key.value.toString())) === "constructor") {
if (method.kind !== "method" || !method.method || method.value.generator) {
throwUnexpected(token, Messages.ConstructorSpecialMethod);
}
if (hasConstructor) {
throwUnexpected(token, Messages.DuplicateConstructor);
@@ -7263,19 +7491,20 @@
return sourceElements;
}
function parseProgram() {
var body,
- marker;
+ marker,
+ isModule = !!extra.ecmaFeatures.modules;
skipComment();
peek();
marker = markerCreate();
- strict = extra.ecmaFeatures.modules;
+ strict = isModule;
body = parseSourceElements();
- return markerApply(marker, astNodeFactory.createProgram(body));
+ return markerApply(marker, astNodeFactory.createProgram(body, isModule ? "module" : "script"));
}
function filterTokenLocation() {
var i, entry, token, tokens = [];
@@ -7329,10 +7558,12 @@
inFunctionBody: false,
inIteration: false,
inSwitch: false,
lastCommentStart: -1,
yieldAllowed: false,
+ curlyStack: [],
+ curlyLastIndex: 0,
inJSXSpreadAttribute: false,
inJSXChild: false,
inJSXTag: false
};
@@ -7350,13 +7581,10 @@
// The following two fields are necessary to compute the Regex tokens.
extra.openParenToken = -1;
extra.openCurlyToken = -1;
- // Needed when using template string tokenization
- extra.curlies = [];
-
extra.range = (typeof options.range === "boolean") && options.range;
extra.loc = (typeof options.loc === "boolean") && options.loc;
if (typeof options.comment === "boolean" && options.comment) {
extra.comments = [];
@@ -7434,21 +7662,23 @@
inFunctionBody: false,
inIteration: false,
inSwitch: false,
lastCommentStart: -1,
yieldAllowed: false,
+ curlyStack: [],
+ curlyLastIndex: 0,
inJSXSpreadAttribute: false,
inJSXChild: false,
inJSXTag: false
};
extra = {
ecmaFeatures: Object.create(defaultFeatures)
};
// for template strings
- extra.curlies = [];
+ state.curlyStack = [];
if (typeof options !== "undefined") {
extra.range = (typeof options.range === "boolean") && options.range;
extra.loc = (typeof options.loc === "boolean") && options.loc;
extra.attachComment = (typeof options.attachComment === "boolean") && options.attachComment;
@@ -7491,11 +7721,12 @@
objectLiteralShorthandProperties: true,
objectLiteralDuplicateProperties: true,
generators: true,
destructuring: true,
classes: true,
- modules: true
+ modules: true,
+ newTarget: true
};
}
// apply parsing flags after sourceType to allow overriding
if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") {
@@ -7565,65 +7796,122 @@
return types;
}());
},{"./lib/ast-node-factory":1,"./lib/ast-node-types":2,"./lib/comment-attachment":3,"./lib/features":4,"./lib/messages":5,"./lib/string-map":6,"./lib/syntax":7,"./lib/token-info":8,"./lib/xhtml-entities":9,"./package.json":10}]},{},[]);
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.eslint=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.eslint = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+module.exports={
+ "type": "Program",
+ "body": [],
+ "sourceType": "script",
+ "range": [
+ 0,
+ 0
+ ],
+ "loc": {
+ "start": {
+ "line": 0,
+ "column": 0
+ },
+ "end": {
+ "line": 0,
+ "column": 0
+ }
+ },
+ "comments": [],
+ "tokens": []
+}
+
+},{}],2:[function(require,module,exports){
/**
* @fileoverview Defines environment settings and globals.
* @author Elan Shanker
* @copyright 2014 Elan Shanker. All rights reserved.
*/
"use strict";
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
var globals = require("globals");
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
module.exports = {
builtin: globals.builtin,
browser: {
globals: globals.browser
},
node: {
globals: globals.node,
ecmaFeatures: {
globalReturn: true
- },
- rules: {
- "no-catch-shadow": 0,
- "no-console": 0,
- "no-mixed-requires": 2,
- "no-new-require": 2,
- "no-path-concat": 2,
- "no-process-exit": 2,
- "global-strict": [0, "always"],
- "handle-callback-err": [2, "err"]
}
},
+ commonjs: {
+ globals: globals.commonjs,
+ ecmaFeatures: {
+ globalReturn: true
+ }
+ },
+ worker: {
+ globals: globals.worker
+ },
amd: {
globals: globals.amd
},
mocha: {
globals: globals.mocha
},
jasmine: {
globals: globals.jasmine
},
+ jest: {
+ globals: globals.jest
+ },
phantomjs: {
- globals: globals.phantom
+ globals: globals.phantomjs
},
jquery: {
globals: globals.jquery
},
+ qunit: {
+ globals: globals.qunit
+ },
prototypejs: {
globals: globals.prototypejs
},
shelljs: {
globals: globals.shelljs
},
meteor: {
globals: globals.meteor
},
+ mongo: {
+ globals: globals.mongo
+ },
+ protractor: {
+ globals: globals.protractor
+ },
+ applescript: {
+ globals: globals.applescript
+ },
+ nashorn: {
+ globals: globals.nashorn
+ },
+ serviceworker: {
+ globals: globals.serviceworker
+ },
+ embertest: {
+ globals: globals.embertest
+ },
+ webextensions: {
+ globals: globals.webextensions
+ },
es6: {
ecmaFeatures: {
arrowFunctions: true,
blockBindings: true,
regexUFlag: true,
@@ -7640,182 +7928,235 @@
objectLiteralShorthandMethods: true,
objectLiteralShorthandProperties: true,
objectLiteralDuplicateProperties: true,
generators: true,
destructuring: true,
- classes: true
+ classes: true,
+ spread: true,
+ newTarget: true
}
}
};
-},{"globals":130}],2:[function(require,module,exports){
+},{"globals":100}],3:[function(require,module,exports){
module.exports={
- "ecmaFeatures": {},
"parser": "espree",
- "env": {
- "browser": false,
- "node": false,
- "amd": false,
- "mocha": false,
- "jasmine": false
- },
-
+ "ecmaFeatures": {},
"rules": {
- "no-alert": 2,
- "no-array-constructor": 2,
+ "no-alert": 0,
+ "no-array-constructor": 0,
+ "no-arrow-condition": 0,
"no-bitwise": 0,
- "no-caller": 2,
- "no-catch-shadow": 2,
- "no-comma-dangle": 0,
+ "no-caller": 0,
+ "no-case-declarations": 0,
+ "no-catch-shadow": 0,
+ "no-class-assign": 0,
"no-cond-assign": 2,
"no-console": 2,
+ "no-const-assign": 0,
"no-constant-condition": 2,
+ "no-continue": 0,
"no-control-regex": 2,
"no-debugger": 2,
"no-delete-var": 2,
"no-div-regex": 0,
+ "no-dupe-class-members": 0,
"no-dupe-keys": 2,
"no-dupe-args": 2,
+ "no-duplicate-case": 2,
"no-else-return": 0,
"no-empty": 2,
- "no-empty-class": 2,
- "no-empty-label": 2,
+ "no-empty-character-class": 2,
+ "no-empty-label": 0,
+ "no-empty-pattern": 0,
"no-eq-null": 0,
- "no-eval": 2,
+ "no-eval": 0,
"no-ex-assign": 2,
- "no-extend-native": 2,
- "no-extra-bind": 2,
+ "no-extend-native": 0,
+ "no-extra-bind": 0,
"no-extra-boolean-cast": 2,
"no-extra-parens": 0,
"no-extra-semi": 2,
- "no-extra-strict": 2,
"no-fallthrough": 2,
"no-floating-decimal": 0,
"no-func-assign": 2,
- "no-implied-eval": 2,
+ "no-implicit-coercion": 0,
+ "no-implied-eval": 0,
"no-inline-comments": 0,
"no-inner-declarations": [2, "functions"],
"no-invalid-regexp": 2,
+ "no-invalid-this": 0,
"no-irregular-whitespace": 2,
- "no-iterator": 2,
- "no-label-var": 2,
- "no-labels": 2,
- "no-lone-blocks": 2,
+ "no-iterator": 0,
+ "no-label-var": 0,
+ "no-labels": 0,
+ "no-lone-blocks": 0,
"no-lonely-if": 0,
- "no-loop-func": 2,
+ "no-loop-func": 0,
"no-mixed-requires": [0, false],
"no-mixed-spaces-and-tabs": [2, false],
- "no-multi-spaces": 2,
- "no-multi-str": 2,
+ "linebreak-style": [0, "unix"],
+ "no-multi-spaces": 0,
+ "no-multi-str": 0,
"no-multiple-empty-lines": [0, {"max": 2}],
- "no-native-reassign": 2,
+ "no-native-reassign": 0,
+ "no-negated-condition": 0,
"no-negated-in-lhs": 2,
"no-nested-ternary": 0,
- "no-new": 2,
- "no-new-func": 2,
- "no-new-object": 2,
+ "no-new": 0,
+ "no-new-func": 0,
+ "no-new-object": 0,
"no-new-require": 0,
- "no-new-wrappers": 2,
+ "no-new-wrappers": 0,
"no-obj-calls": 2,
"no-octal": 2,
- "no-octal-escape": 2,
+ "no-octal-escape": 0,
+ "no-param-reassign": 0,
"no-path-concat": 0,
"no-plusplus": 0,
"no-process-env": 0,
- "no-process-exit": 2,
- "no-proto": 2,
+ "no-process-exit": 0,
+ "no-proto": 0,
"no-redeclare": 2,
"no-regex-spaces": 2,
- "no-reserved-keys": 0,
"no-restricted-modules": 0,
- "no-return-assign": 2,
- "no-script-url": 2,
+ "no-restricted-syntax": 0,
+ "no-return-assign": 0,
+ "no-script-url": 0,
"no-self-compare": 0,
- "no-sequences": 2,
- "no-shadow": 2,
- "no-shadow-restricted-names": 2,
- "no-space-before-semi": 0,
- "no-spaced-func": 2,
+ "no-sequences": 0,
+ "no-shadow": 0,
+ "no-shadow-restricted-names": 0,
+ "no-spaced-func": 0,
"no-sparse-arrays": 2,
"no-sync": 0,
"no-ternary": 0,
- "no-trailing-spaces": 2,
+ "no-trailing-spaces": 0,
+ "no-this-before-super": 0,
"no-throw-literal": 0,
"no-undef": 2,
- "no-undef-init": 2,
+ "no-undef-init": 0,
"no-undefined": 0,
- "no-underscore-dangle": 2,
+ "no-unexpected-multiline": 0,
+ "no-underscore-dangle": 0,
+ "no-unneeded-ternary": 0,
"no-unreachable": 2,
- "no-unused-expressions": 2,
+ "no-unused-expressions": 0,
"no-unused-vars": [2, {"vars": "all", "args": "after-used"}],
- "no-use-before-define": 2,
+ "no-use-before-define": 0,
+ "no-useless-call": 0,
+ "no-useless-concat": 0,
"no-void": 0,
"no-var": 0,
"no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
- "no-with": 2,
- "no-wrap-func": 2,
+ "no-with": 0,
+ "no-magic-numbers": 0,
+ "array-bracket-spacing": [0, "never"],
+ "arrow-body-style": [0, "as-needed"],
+ "arrow-parens": 0,
+ "arrow-spacing": 0,
+ "accessor-pairs": 0,
"block-scoped-var": 0,
+ "block-spacing": 0,
"brace-style": [0, "1tbs"],
- "camelcase": 2,
+ "callback-return": 0,
+ "camelcase": 0,
"comma-dangle": [2, "never"],
- "comma-spacing": 2,
+ "comma-spacing": 0,
"comma-style": 0,
"complexity": [0, 11],
- "consistent-return": 2,
+ "computed-property-spacing": [0, "never"],
+ "consistent-return": 0,
"consistent-this": [0, "that"],
- "curly": [2, "all"],
+ "constructor-super": 0,
+ "curly": [0, "all"],
"default-case": 0,
- "dot-notation": [2, { "allowKeywords": true }],
- "eol-last": 2,
- "eqeqeq": 2,
+ "dot-location": 0,
+ "dot-notation": [0, { "allowKeywords": true }],
+ "eol-last": 0,
+ "eqeqeq": 0,
"func-names": 0,
"func-style": [0, "declaration"],
- "generator-star": 0,
- "global-strict": [2, "never"],
+ "generator-star-spacing": 0,
+ "global-require": 0,
"guard-for-in": 0,
"handle-callback-err": 0,
+ "id-length": 0,
"indent": 0,
- "key-spacing": [2, { "beforeColon": false, "afterColon": true }],
+ "init-declarations": 0,
+ "jsx-quotes": [0, "prefer-double"],
+ "key-spacing": [0, { "beforeColon": false, "afterColon": true }],
+ "lines-around-comment": 0,
"max-depth": [0, 4],
"max-len": [0, 80, 4],
"max-nested-callbacks": [0, 2],
"max-params": [0, 3],
"max-statements": [0, 10],
- "new-cap": 2,
- "new-parens": 2,
- "one-var": 0,
+ "new-cap": 0,
+ "new-parens": 0,
+ "newline-after-var": 0,
+ "object-curly-spacing": [0, "never"],
+ "object-shorthand": 0,
+ "one-var": [0, "always"],
"operator-assignment": [0, "always"],
+ "operator-linebreak": 0,
"padded-blocks": 0,
+ "prefer-arrow-callback": 0,
+ "prefer-const": 0,
+ "prefer-spread": 0,
+ "prefer-reflect": 0,
+ "prefer-template": 0,
"quote-props": 0,
- "quotes": [2, "double"],
+ "quotes": [0, "double"],
"radix": 0,
- "semi": 2,
- "semi-spacing": [2, {"before": false, "after": true}],
+ "id-match": 0,
+ "require-jsdoc": 0,
+ "require-yield": 0,
+ "semi": 0,
+ "semi-spacing": [0, {"before": false, "after": true}],
"sort-vars": 0,
- "space-after-function-name": [0, "never"],
"space-after-keywords": [0, "always"],
+ "space-before-keywords": [0, "always"],
"space-before-blocks": [0, "always"],
- "space-before-function-parentheses": [0, "always"],
- "space-in-brackets": [0, "never"],
+ "space-before-function-paren": [0, "always"],
"space-in-parens": [0, "never"],
- "space-infix-ops": 2,
- "space-return-throw-case": 2,
- "space-unary-ops": [2, { "words": true, "nonwords": false }],
- "spaced-line-comment": [0, "always"],
- "strict": 2,
+ "space-infix-ops": 0,
+ "space-return-throw-case": 0,
+ "space-unary-ops": [0, { "words": true, "nonwords": false }],
+ "spaced-comment": 0,
+ "strict": 0,
"use-isnan": 2,
"valid-jsdoc": 0,
"valid-typeof": 2,
"vars-on-top": 0,
"wrap-iife": 0,
"wrap-regex": 0,
- "yoda": [2, "never"]
+ "yoda": [0, "never"]
}
}
-},{}],3:[function(require,module,exports){
+},{}],4:[function(require,module,exports){
+module.exports={
+ "rules": {
+ "generator-star": ["generator-star-spacing"],
+ "global-strict": ["strict"],
+ "no-comma-dangle": ["comma-dangle"],
+ "no-empty-class": ["no-empty-character-class"],
+ "no-extra-strict": ["strict"],
+ "no-reserved-keys": ["quote-props"],
+ "no-space-before-semi": ["semi-spacing"],
+ "no-wrap-func": ["no-extra-parens"],
+ "space-after-function-name": ["space-before-function-paren"],
+ "space-before-function-parentheses": ["space-before-function-paren"],
+ "space-in-brackets": ["object-curly-spacing", "array-bracket-spacing", "computed-property-spacing"],
+ "space-unary-word-ops": ["space-unary-ops"],
+ "spaced-line-comment": ["spaced-comment"]
+ }
+}
+
+},{}],5:[function(require,module,exports){
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
@@ -8172,996 +8513,478 @@
if (hasOwn.call(obj, key)) keys.push(key);
}
return keys;
};
-},{"util/":8}],4:[function(require,module,exports){
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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 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.
+},{"util/":111}],6:[function(require,module,exports){
+'use strict';
-function EventEmitter() {
- this._events = this._events || {};
- this._maxListeners = this._maxListeners || undefined;
-}
-module.exports = EventEmitter;
+var copy = require('es5-ext/object/copy')
+ , map = require('es5-ext/object/map')
+ , callable = require('es5-ext/object/valid-callable')
+ , validValue = require('es5-ext/object/valid-value')
-// Backwards-compat with node 0.10.x
-EventEmitter.EventEmitter = EventEmitter;
+ , bind = Function.prototype.bind, defineProperty = Object.defineProperty
+ , hasOwnProperty = Object.prototype.hasOwnProperty
+ , define;
-EventEmitter.prototype._events = undefined;
-EventEmitter.prototype._maxListeners = undefined;
-
-// By default EventEmitters will print a warning if more than 10 listeners are
-// added to it. This is a useful default which helps finding memory leaks.
-EventEmitter.defaultMaxListeners = 10;
-
-// Obviously not all Emitters should be limited to 10. This function allows
-// that to be increased. Set to zero for unlimited.
-EventEmitter.prototype.setMaxListeners = function(n) {
- if (!isNumber(n) || n < 0 || isNaN(n))
- throw TypeError('n must be a positive number');
- this._maxListeners = n;
- return this;
+define = function (name, desc, bindTo) {
+ var value = validValue(desc) && callable(desc.value), dgs;
+ dgs = copy(desc);
+ delete dgs.writable;
+ delete dgs.value;
+ dgs.get = function () {
+ if (hasOwnProperty.call(this, name)) return value;
+ desc.value = bind.call(value, (bindTo == null) ? this : this[bindTo]);
+ defineProperty(this, name, desc);
+ return this[name];
+ };
+ return dgs;
};
-EventEmitter.prototype.emit = function(type) {
- var er, handler, len, args, i, listeners;
-
- if (!this._events)
- this._events = {};
-
- // If there is no 'error' event listener then throw.
- if (type === 'error') {
- if (!this._events.error ||
- (isObject(this._events.error) && !this._events.error.length)) {
- er = arguments[1];
- if (er instanceof Error) {
- throw er; // Unhandled 'error' event
- }
- throw TypeError('Uncaught, unspecified "error" event.');
- }
- }
-
- handler = this._events[type];
-
- if (isUndefined(handler))
- return false;
-
- if (isFunction(handler)) {
- switch (arguments.length) {
- // fast cases
- case 1:
- handler.call(this);
- break;
- case 2:
- handler.call(this, arguments[1]);
- break;
- case 3:
- handler.call(this, arguments[1], arguments[2]);
- break;
- // slower
- default:
- len = arguments.length;
- args = new Array(len - 1);
- for (i = 1; i < len; i++)
- args[i - 1] = arguments[i];
- handler.apply(this, args);
- }
- } else if (isObject(handler)) {
- len = arguments.length;
- args = new Array(len - 1);
- for (i = 1; i < len; i++)
- args[i - 1] = arguments[i];
-
- listeners = handler.slice();
- len = listeners.length;
- for (i = 0; i < len; i++)
- listeners[i].apply(this, args);
- }
-
- return true;
+module.exports = function (props/*, bindTo*/) {
+ var bindTo = arguments[1];
+ return map(props, function (desc, name) {
+ return define(name, desc, bindTo);
+ });
};
-EventEmitter.prototype.addListener = function(type, listener) {
- var m;
+},{"es5-ext/object/copy":30,"es5-ext/object/map":38,"es5-ext/object/valid-callable":44,"es5-ext/object/valid-value":46}],7:[function(require,module,exports){
+'use strict';
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
+var assign = require('es5-ext/object/assign')
+ , normalizeOpts = require('es5-ext/object/normalize-options')
+ , isCallable = require('es5-ext/object/is-callable')
+ , contains = require('es5-ext/string/#/contains')
- if (!this._events)
- this._events = {};
+ , d;
- // To avoid recursion in the case that type === "newListener"! Before
- // adding it to the listeners, first emit "newListener".
- if (this._events.newListener)
- this.emit('newListener', type,
- isFunction(listener.listener) ?
- listener.listener : listener);
+d = module.exports = function (dscr, value/*, options*/) {
+ var c, e, w, options, desc;
+ if ((arguments.length < 2) || (typeof dscr !== 'string')) {
+ options = value;
+ value = dscr;
+ dscr = null;
+ } else {
+ options = arguments[2];
+ }
+ if (dscr == null) {
+ c = w = true;
+ e = false;
+ } else {
+ c = contains.call(dscr, 'c');
+ e = contains.call(dscr, 'e');
+ w = contains.call(dscr, 'w');
+ }
- if (!this._events[type])
- // Optimize the case of one listener. Don't need the extra array object.
- this._events[type] = listener;
- else if (isObject(this._events[type]))
- // If we've already got an array, just append.
- this._events[type].push(listener);
- else
- // Adding the second element, need to change to array.
- this._events[type] = [this._events[type], listener];
-
- // Check for listener leak
- if (isObject(this._events[type]) && !this._events[type].warned) {
- var m;
- if (!isUndefined(this._maxListeners)) {
- m = this._maxListeners;
- } else {
- m = EventEmitter.defaultMaxListeners;
- }
-
- if (m && m > 0 && this._events[type].length > m) {
- this._events[type].warned = true;
- console.error('(node) warning: possible EventEmitter memory ' +
- 'leak detected. %d listeners added. ' +
- 'Use emitter.setMaxListeners() to increase limit.',
- this._events[type].length);
- if (typeof console.trace === 'function') {
- // not supported in IE 10
- console.trace();
- }
- }
- }
-
- return this;
+ desc = { value: value, configurable: c, enumerable: e, writable: w };
+ return !options ? desc : assign(normalizeOpts(options), desc);
};
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+d.gs = function (dscr, get, set/*, options*/) {
+ var c, e, options, desc;
+ if (typeof dscr !== 'string') {
+ options = set;
+ set = get;
+ get = dscr;
+ dscr = null;
+ } else {
+ options = arguments[3];
+ }
+ if (get == null) {
+ get = undefined;
+ } else if (!isCallable(get)) {
+ options = get;
+ get = set = undefined;
+ } else if (set == null) {
+ set = undefined;
+ } else if (!isCallable(set)) {
+ options = set;
+ set = undefined;
+ }
+ if (dscr == null) {
+ c = true;
+ e = false;
+ } else {
+ c = contains.call(dscr, 'c');
+ e = contains.call(dscr, 'e');
+ }
-EventEmitter.prototype.once = function(type, listener) {
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
-
- var fired = false;
-
- function g() {
- this.removeListener(type, g);
-
- if (!fired) {
- fired = true;
- listener.apply(this, arguments);
- }
- }
-
- g.listener = listener;
- this.on(type, g);
-
- return this;
+ desc = { get: get, set: set, configurable: c, enumerable: e };
+ return !options ? desc : assign(normalizeOpts(options), desc);
};
-// emits a 'removeListener' event iff the listener was removed
-EventEmitter.prototype.removeListener = function(type, listener) {
- var list, position, length, i;
+},{"es5-ext/object/assign":27,"es5-ext/object/is-callable":33,"es5-ext/object/normalize-options":39,"es5-ext/string/#/contains":47}],8:[function(require,module,exports){
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
- if (!this._events || !this._events[type])
- return this;
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+ && 'undefined' != typeof chrome.storage
+ ? chrome.storage.local
+ : localstorage();
- list = this._events[type];
- length = list.length;
- position = -1;
+/**
+ * Colors.
+ */
- if (list === listener ||
- (isFunction(list.listener) && list.listener === listener)) {
- delete this._events[type];
- if (this._events.removeListener)
- this.emit('removeListener', type, listener);
+exports.colors = [
+ 'lightseagreen',
+ 'forestgreen',
+ 'goldenrod',
+ 'dodgerblue',
+ 'darkorchid',
+ 'crimson'
+];
- } else if (isObject(list)) {
- for (i = length; i-- > 0;) {
- if (list[i] === listener ||
- (list[i].listener && list[i].listener === listener)) {
- position = i;
- break;
- }
- }
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
- if (position < 0)
- return this;
+function useColors() {
+ // is webkit? http://stackoverflow.com/a/16459606/376773
+ return ('WebkitAppearance' in document.documentElement.style) ||
+ // is firebug? http://stackoverflow.com/a/398120/376773
+ (window.console && (console.firebug || (console.exception && console.table))) ||
+ // is firefox >= v31?
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+ (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
+}
- if (list.length === 1) {
- list.length = 0;
- delete this._events[type];
- } else {
- list.splice(position, 1);
- }
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
- if (this._events.removeListener)
- this.emit('removeListener', type, listener);
- }
-
- return this;
+exports.formatters.j = function(v) {
+ return JSON.stringify(v);
};
-EventEmitter.prototype.removeAllListeners = function(type) {
- var key, listeners;
- if (!this._events)
- return this;
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
- // not listening for removeListener, no need to emit
- if (!this._events.removeListener) {
- if (arguments.length === 0)
- this._events = {};
- else if (this._events[type])
- delete this._events[type];
- return this;
- }
+function formatArgs() {
+ var args = arguments;
+ var useColors = this.useColors;
- // emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- for (key in this._events) {
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = {};
- return this;
- }
+ args[0] = (useColors ? '%c' : '')
+ + this.namespace
+ + (useColors ? ' %c' : ' ')
+ + args[0]
+ + (useColors ? '%c ' : ' ')
+ + '+' + exports.humanize(this.diff);
- listeners = this._events[type];
+ if (!useColors) return args;
- if (isFunction(listeners)) {
- this.removeListener(type, listeners);
- } else {
- // LIFO order
- while (listeners.length)
- this.removeListener(type, listeners[listeners.length - 1]);
- }
- delete this._events[type];
+ var c = 'color: ' + this.color;
+ args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
- return this;
-};
+ // the final "%c" is somewhat tricky, because there could be other
+ // arguments passed either before or after the %c, so we need to
+ // figure out the correct index to insert the CSS into
+ var index = 0;
+ var lastC = 0;
+ args[0].replace(/%[a-z%]/g, function(match) {
+ if ('%%' === match) return;
+ index++;
+ if ('%c' === match) {
+ // we only are interested in the *last* %c
+ // (the user may have provided their own)
+ lastC = index;
+ }
+ });
-EventEmitter.prototype.listeners = function(type) {
- var ret;
- if (!this._events || !this._events[type])
- ret = [];
- else if (isFunction(this._events[type]))
- ret = [this._events[type]];
- else
- ret = this._events[type].slice();
- return ret;
-};
-
-EventEmitter.listenerCount = function(emitter, type) {
- var ret;
- if (!emitter._events || !emitter._events[type])
- ret = 0;
- else if (isFunction(emitter._events[type]))
- ret = 1;
- else
- ret = emitter._events[type].length;
- return ret;
-};
-
-function isFunction(arg) {
- return typeof arg === 'function';
+ args.splice(lastC, 0, c);
+ return args;
}
-function isNumber(arg) {
- return typeof arg === 'number';
-}
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
-function isObject(arg) {
- return typeof arg === 'object' && arg !== null;
+function log() {
+ // this hackery is required for IE8/9, where
+ // the `console.log` function doesn't have 'apply'
+ return 'object' === typeof console
+ && console.log
+ && Function.prototype.apply.call(console.log, console, arguments);
}
-function isUndefined(arg) {
- return arg === void 0;
-}
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
-},{}],5:[function(require,module,exports){
-if (typeof Object.create === 'function') {
- // implementation from standard node.js 'util' module
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- ctor.prototype = Object.create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- };
-} else {
- // old school shim for old browsers
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- var TempCtor = function () {}
- TempCtor.prototype = superCtor.prototype
- ctor.prototype = new TempCtor()
- ctor.prototype.constructor = ctor
- }
+function save(namespaces) {
+ try {
+ if (null == namespaces) {
+ exports.storage.removeItem('debug');
+ } else {
+ exports.storage.debug = namespaces;
+ }
+ } catch(e) {}
}
-},{}],6:[function(require,module,exports){
-// shim for using process in browser
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
-var process = module.exports = {};
-var queue = [];
-var draining = false;
-
-function drainQueue() {
- if (draining) {
- return;
- }
- draining = true;
- var currentQueue;
- var len = queue.length;
- while(len) {
- currentQueue = queue;
- queue = [];
- var i = -1;
- while (++i < len) {
- currentQueue[i]();
- }
- len = queue.length;
- }
- draining = false;
+function load() {
+ var r;
+ try {
+ r = exports.storage.debug;
+ } catch(e) {}
+ return r;
}
-process.nextTick = function (fun) {
- queue.push(fun);
- if (!draining) {
- setTimeout(drainQueue, 0);
- }
-};
-process.title = 'browser';
-process.browser = true;
-process.env = {};
-process.argv = [];
-process.version = ''; // empty string to avoid regexp issues
-process.versions = {};
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
-function noop() {}
+exports.enable(load());
-process.on = noop;
-process.addListener = noop;
-process.once = noop;
-process.off = noop;
-process.removeListener = noop;
-process.removeAllListeners = noop;
-process.emit = noop;
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
-process.binding = function (name) {
- throw new Error('process.binding is not supported');
-};
-
-// TODO(shtylman)
-process.cwd = function () { return '/' };
-process.chdir = function (dir) {
- throw new Error('process.chdir is not supported');
-};
-process.umask = function() { return 0; };
-
-},{}],7:[function(require,module,exports){
-module.exports = function isBuffer(arg) {
- return arg && typeof arg === 'object'
- && typeof arg.copy === 'function'
- && typeof arg.fill === 'function'
- && typeof arg.readUInt8 === 'function';
+function localstorage(){
+ try {
+ return window.localStorage;
+ } catch (e) {}
}
-},{}],8:[function(require,module,exports){
-(function (process,global){
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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 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.
-var formatRegExp = /%[sdj%]/g;
-exports.format = function(f) {
- if (!isString(f)) {
- var objects = [];
- for (var i = 0; i < arguments.length; i++) {
- objects.push(inspect(arguments[i]));
- }
- return objects.join(' ');
- }
+},{"./debug":9}],9:[function(require,module,exports){
- var i = 1;
- var args = arguments;
- var len = args.length;
- var str = String(f).replace(formatRegExp, function(x) {
- if (x === '%%') return '%';
- if (i >= len) return x;
- switch (x) {
- case '%s': return String(args[i++]);
- case '%d': return Number(args[i++]);
- case '%j':
- try {
- return JSON.stringify(args[i++]);
- } catch (_) {
- return '[Circular]';
- }
- default:
- return x;
- }
- });
- for (var x = args[i]; i < len; x = args[++i]) {
- if (isNull(x) || !isObject(x)) {
- str += ' ' + x;
- } else {
- str += ' ' + inspect(x);
- }
- }
- return str;
-};
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+exports = module.exports = debug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
-// Mark that a method should not be used.
-// Returns a modified function which warns once by default.
-// If --no-deprecation is set, then it is a no-op.
-exports.deprecate = function(fn, msg) {
- // Allow for deprecating things in the process of starting up.
- if (isUndefined(global.process)) {
- return function() {
- return exports.deprecate(fn, msg).apply(this, arguments);
- };
- }
+/**
+ * The currently active debug mode names, and names to skip.
+ */
- if (process.noDeprecation === true) {
- return fn;
- }
+exports.names = [];
+exports.skips = [];
- var warned = false;
- function deprecated() {
- if (!warned) {
- if (process.throwDeprecation) {
- throw new Error(msg);
- } else if (process.traceDeprecation) {
- console.trace(msg);
- } else {
- console.error(msg);
- }
- warned = true;
- }
- return fn.apply(this, arguments);
- }
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lowercased letter, i.e. "n".
+ */
- return deprecated;
-};
+exports.formatters = {};
+/**
+ * Previously assigned color.
+ */
-var debugs = {};
-var debugEnviron;
-exports.debuglog = function(set) {
- if (isUndefined(debugEnviron))
- debugEnviron = process.env.NODE_DEBUG || '';
- set = set.toUpperCase();
- if (!debugs[set]) {
- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
- var pid = process.pid;
- debugs[set] = function() {
- var msg = exports.format.apply(exports, arguments);
- console.error('%s %d: %s', set, pid, msg);
- };
- } else {
- debugs[set] = function() {};
- }
- }
- return debugs[set];
-};
+var prevColor = 0;
+/**
+ * Previous log timestamp.
+ */
+var prevTime;
+
/**
- * Echos the value of a value. Trys to print the value out
- * in the best way possible given the different types.
+ * Select a color.
*
- * @param {Object} obj The object to print out.
- * @param {Object} opts Optional options object that alters the output.
+ * @return {Number}
+ * @api private
*/
-/* legacy: obj, showHidden, depth, colors*/
-function inspect(obj, opts) {
- // default options
- var ctx = {
- seen: [],
- stylize: stylizeNoColor
- };
- // legacy...
- if (arguments.length >= 3) ctx.depth = arguments[2];
- if (arguments.length >= 4) ctx.colors = arguments[3];
- if (isBoolean(opts)) {
- // legacy...
- ctx.showHidden = opts;
- } else if (opts) {
- // got an "options" object
- exports._extend(ctx, opts);
- }
- // set default options
- if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
- if (isUndefined(ctx.depth)) ctx.depth = 2;
- if (isUndefined(ctx.colors)) ctx.colors = false;
- if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
- if (ctx.colors) ctx.stylize = stylizeWithColor;
- return formatValue(ctx, obj, ctx.depth);
+
+function selectColor() {
+ return exports.colors[prevColor++ % exports.colors.length];
}
-exports.inspect = inspect;
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
-// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
-inspect.colors = {
- 'bold' : [1, 22],
- 'italic' : [3, 23],
- 'underline' : [4, 24],
- 'inverse' : [7, 27],
- 'white' : [37, 39],
- 'grey' : [90, 39],
- 'black' : [30, 39],
- 'blue' : [34, 39],
- 'cyan' : [36, 39],
- 'green' : [32, 39],
- 'magenta' : [35, 39],
- 'red' : [31, 39],
- 'yellow' : [33, 39]
-};
+function debug(namespace) {
-// Don't use 'blue' not visible on cmd.exe
-inspect.styles = {
- 'special': 'cyan',
- 'number': 'yellow',
- 'boolean': 'yellow',
- 'undefined': 'grey',
- 'null': 'bold',
- 'string': 'green',
- 'date': 'magenta',
- // "name": intentionally not styling
- 'regexp': 'red'
-};
-
-
-function stylizeWithColor(str, styleType) {
- var style = inspect.styles[styleType];
-
- if (style) {
- return '\u001b[' + inspect.colors[style][0] + 'm' + str +
- '\u001b[' + inspect.colors[style][1] + 'm';
- } else {
- return str;
+ // define the `disabled` version
+ function disabled() {
}
-}
+ disabled.enabled = false;
+ // define the `enabled` version
+ function enabled() {
-function stylizeNoColor(str, styleType) {
- return str;
-}
+ var self = enabled;
+ // set `diff` timestamp
+ var curr = +new Date();
+ var ms = curr - (prevTime || curr);
+ self.diff = ms;
+ self.prev = prevTime;
+ self.curr = curr;
+ prevTime = curr;
-function arrayToHash(array) {
- var hash = {};
+ // add the `color` if not set
+ if (null == self.useColors) self.useColors = exports.useColors();
+ if (null == self.color && self.useColors) self.color = selectColor();
- array.forEach(function(val, idx) {
- hash[val] = true;
- });
+ var args = Array.prototype.slice.call(arguments);
- return hash;
-}
+ args[0] = exports.coerce(args[0]);
-
-function formatValue(ctx, value, recurseTimes) {
- // Provide a hook for user-specified inspect functions.
- // Check that value is an object with an inspect function on it
- if (ctx.customInspect &&
- value &&
- isFunction(value.inspect) &&
- // Filter out the util module, it's inspect function is special
- value.inspect !== exports.inspect &&
- // Also filter out any prototype objects using the circular check.
- !(value.constructor && value.constructor.prototype === value)) {
- var ret = value.inspect(recurseTimes, ctx);
- if (!isString(ret)) {
- ret = formatValue(ctx, ret, recurseTimes);
+ if ('string' !== typeof args[0]) {
+ // anything else let's inspect with %o
+ args = ['%o'].concat(args);
}
- return ret;
- }
- // Primitive types cannot have properties
- var primitive = formatPrimitive(ctx, value);
- if (primitive) {
- return primitive;
- }
+ // apply any `formatters` transformations
+ var index = 0;
+ args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
+ // if we encounter an escaped % then don't increase the array index
+ if (match === '%%') return match;
+ index++;
+ var formatter = exports.formatters[format];
+ if ('function' === typeof formatter) {
+ var val = args[index];
+ match = formatter.call(self, val);
- // Look up the keys of the object.
- var keys = Object.keys(value);
- var visibleKeys = arrayToHash(keys);
+ // now we need to remove `args[index]` since it's inlined in the `format`
+ args.splice(index, 1);
+ index--;
+ }
+ return match;
+ });
- if (ctx.showHidden) {
- keys = Object.getOwnPropertyNames(value);
- }
-
- // IE doesn't make error fields non-enumerable
- // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
- if (isError(value)
- && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
- return formatError(value);
- }
-
- // Some type of object without properties can be shortcutted.
- if (keys.length === 0) {
- if (isFunction(value)) {
- var name = value.name ? ': ' + value.name : '';
- return ctx.stylize('[Function' + name + ']', 'special');
+ if ('function' === typeof exports.formatArgs) {
+ args = exports.formatArgs.apply(self, args);
}
- if (isRegExp(value)) {
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
- }
- if (isDate(value)) {
- return ctx.stylize(Date.prototype.toString.call(value), 'date');
- }
- if (isError(value)) {
- return formatError(value);
- }
+ var logFn = enabled.log || exports.log || console.log.bind(console);
+ logFn.apply(self, args);
}
+ enabled.enabled = true;
- var base = '', array = false, braces = ['{', '}'];
+ var fn = exports.enabled(namespace) ? enabled : disabled;
- // Make Array say that they are Array
- if (isArray(value)) {
- array = true;
- braces = ['[', ']'];
- }
+ fn.namespace = namespace;
- // Make functions say that they are functions
- if (isFunction(value)) {
- var n = value.name ? ': ' + value.name : '';
- base = ' [Function' + n + ']';
- }
+ return fn;
+}
- // Make RegExps say that they are RegExps
- if (isRegExp(value)) {
- base = ' ' + RegExp.prototype.toString.call(value);
- }
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
- // Make dates with properties first say the date
- if (isDate(value)) {
- base = ' ' + Date.prototype.toUTCString.call(value);
- }
+function enable(namespaces) {
+ exports.save(namespaces);
- // Make error with message first say the error
- if (isError(value)) {
- base = ' ' + formatError(value);
- }
+ var split = (namespaces || '').split(/[\s,]+/);
+ var len = split.length;
- if (keys.length === 0 && (!array || value.length == 0)) {
- return braces[0] + base + braces[1];
- }
-
- if (recurseTimes < 0) {
- if (isRegExp(value)) {
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+ for (var i = 0; i < len; i++) {
+ if (!split[i]) continue; // ignore empty strings
+ namespaces = split[i].replace(/\*/g, '.*?');
+ if (namespaces[0] === '-') {
+ exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
} else {
- return ctx.stylize('[Object]', 'special');
+ exports.names.push(new RegExp('^' + namespaces + '$'));
}
}
-
- ctx.seen.push(value);
-
- var output;
- if (array) {
- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
- } else {
- output = keys.map(function(key) {
- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
- });
- }
-
- ctx.seen.pop();
-
- return reduceToSingleString(output, base, braces);
}
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
-function formatPrimitive(ctx, value) {
- if (isUndefined(value))
- return ctx.stylize('undefined', 'undefined');
- if (isString(value)) {
- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
- .replace(/'/g, "\\'")
- .replace(/\\"/g, '"') + '\'';
- return ctx.stylize(simple, 'string');
- }
- if (isNumber(value))
- return ctx.stylize('' + value, 'number');
- if (isBoolean(value))
- return ctx.stylize('' + value, 'boolean');
- // For some reason typeof null is "object", so special case here.
- if (isNull(value))
- return ctx.stylize('null', 'null');
+function disable() {
+ exports.enable('');
}
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
-function formatError(value) {
- return '[' + Error.prototype.toString.call(value) + ']';
-}
-
-
-function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
- var output = [];
- for (var i = 0, l = value.length; i < l; ++i) {
- if (hasOwnProperty(value, String(i))) {
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
- String(i), true));
- } else {
- output.push('');
+function enabled(name) {
+ var i, len;
+ for (i = 0, len = exports.skips.length; i < len; i++) {
+ if (exports.skips[i].test(name)) {
+ return false;
}
}
- keys.forEach(function(key) {
- if (!key.match(/^\d+$/)) {
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
- key, true));
+ for (i = 0, len = exports.names.length; i < len; i++) {
+ if (exports.names[i].test(name)) {
+ return true;
}
- });
- return output;
-}
-
-
-function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
- var name, str, desc;
- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
- if (desc.get) {
- if (desc.set) {
- str = ctx.stylize('[Getter/Setter]', 'special');
- } else {
- str = ctx.stylize('[Getter]', 'special');
- }
- } else {
- if (desc.set) {
- str = ctx.stylize('[Setter]', 'special');
- }
}
- if (!hasOwnProperty(visibleKeys, key)) {
- name = '[' + key + ']';
- }
- if (!str) {
- if (ctx.seen.indexOf(desc.value) < 0) {
- if (isNull(recurseTimes)) {
- str = formatValue(ctx, desc.value, null);
- } else {
- str = formatValue(ctx, desc.value, recurseTimes - 1);
- }
- if (str.indexOf('\n') > -1) {
- if (array) {
- str = str.split('\n').map(function(line) {
- return ' ' + line;
- }).join('\n').substr(2);
- } else {
- str = '\n' + str.split('\n').map(function(line) {
- return ' ' + line;
- }).join('\n');
- }
- }
- } else {
- str = ctx.stylize('[Circular]', 'special');
- }
- }
- if (isUndefined(name)) {
- if (array && key.match(/^\d+$/)) {
- return str;
- }
- name = JSON.stringify('' + key);
- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
- name = name.substr(1, name.length - 2);
- name = ctx.stylize(name, 'name');
- } else {
- name = name.replace(/'/g, "\\'")
- .replace(/\\"/g, '"')
- .replace(/(^"|"$)/g, "'");
- name = ctx.stylize(name, 'string');
- }
- }
-
- return name + ': ' + str;
+ return false;
}
-
-function reduceToSingleString(output, base, braces) {
- var numLinesEst = 0;
- var length = output.reduce(function(prev, cur) {
- numLinesEst++;
- if (cur.indexOf('\n') >= 0) numLinesEst++;
- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
- }, 0);
-
- if (length > 60) {
- return braces[0] +
- (base === '' ? '' : base + '\n ') +
- ' ' +
- output.join(',\n ') +
- ' ' +
- braces[1];
- }
-
- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
-}
-
-
-// NOTE: These type checking functions intentionally don't use `instanceof`
-// because it is fragile and can be easily faked with `Object.create()`.
-function isArray(ar) {
- return Array.isArray(ar);
-}
-exports.isArray = isArray;
-
-function isBoolean(arg) {
- return typeof arg === 'boolean';
-}
-exports.isBoolean = isBoolean;
-
-function isNull(arg) {
- return arg === null;
-}
-exports.isNull = isNull;
-
-function isNullOrUndefined(arg) {
- return arg == null;
-}
-exports.isNullOrUndefined = isNullOrUndefined;
-
-function isNumber(arg) {
- return typeof arg === 'number';
-}
-exports.isNumber = isNumber;
-
-function isString(arg) {
- return typeof arg === 'string';
-}
-exports.isString = isString;
-
-function isSymbol(arg) {
- return typeof arg === 'symbol';
-}
-exports.isSymbol = isSymbol;
-
-function isUndefined(arg) {
- return arg === void 0;
-}
-exports.isUndefined = isUndefined;
-
-function isRegExp(re) {
- return isObject(re) && objectToString(re) === '[object RegExp]';
-}
-exports.isRegExp = isRegExp;
-
-function isObject(arg) {
- return typeof arg === 'object' && arg !== null;
-}
-exports.isObject = isObject;
-
-function isDate(d) {
- return isObject(d) && objectToString(d) === '[object Date]';
-}
-exports.isDate = isDate;
-
-function isError(e) {
- return isObject(e) &&
- (objectToString(e) === '[object Error]' || e instanceof Error);
-}
-exports.isError = isError;
-
-function isFunction(arg) {
- return typeof arg === 'function';
-}
-exports.isFunction = isFunction;
-
-function isPrimitive(arg) {
- return arg === null ||
- typeof arg === 'boolean' ||
- typeof arg === 'number' ||
- typeof arg === 'string' ||
- typeof arg === 'symbol' || // ES6 symbol
- typeof arg === 'undefined';
-}
-exports.isPrimitive = isPrimitive;
-
-exports.isBuffer = require('./support/isBuffer');
-
-function objectToString(o) {
- return Object.prototype.toString.call(o);
-}
-
-
-function pad(n) {
- return n < 10 ? '0' + n.toString(10) : n.toString(10);
-}
-
-
-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
- 'Oct', 'Nov', 'Dec'];
-
-// 26 Feb 16:19:34
-function timestamp() {
- var d = new Date();
- var time = [pad(d.getHours()),
- pad(d.getMinutes()),
- pad(d.getSeconds())].join(':');
- return [d.getDate(), months[d.getMonth()], time].join(' ');
-}
-
-
-// log is just a thin wrapper to console.log that prepends a timestamp
-exports.log = function() {
- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
-};
-
-
/**
- * Inherit the prototype methods from one constructor into another.
+ * Coerce `val`.
*
- * The Function.prototype.inherits from lang.js rewritten as a standalone
- * function (not on Function.prototype). NOTE: If this file is to be loaded
- * during bootstrapping this function needs to be rewritten using some native
- * functions as prototype setup using normal JavaScript does not work as
- * expected during bootstrapping (see mirror.js in r114903).
- *
- * @param {function} ctor Constructor function which needs to inherit the
- * prototype.
- * @param {function} superCtor Constructor function to inherit prototype from.
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
*/
-exports.inherits = require('inherits');
-exports._extend = function(origin, add) {
- // Don't do anything if add isn't an object
- if (!add || !isObject(add)) return origin;
-
- var keys = Object.keys(add);
- var i = keys.length;
- while (i--) {
- origin[keys[i]] = add[keys[i]];
- }
- return origin;
-};
-
-function hasOwnProperty(obj, prop) {
- return Object.prototype.hasOwnProperty.call(obj, prop);
+function coerce(val) {
+ if (val instanceof Error) return val.stack || val.message;
+ return val;
}
-}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./support/isBuffer":7,"_process":6,"inherits":5}],9:[function(require,module,exports){
+},{"ms":107}],10:[function(require,module,exports){
/*
Copyright (C) 2012-2014 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2014 Dan Tao <daniel.tao@gmail.com>
Copyright (C) 2013 Andrew Eisenberg <andrew@eisenberg.as>
@@ -9230,10 +9053,14 @@
function isParamTitle(title) {
return title === 'param' || title === 'argument' || title === 'arg';
}
+ function isReturnTitle(title) {
+ return title === 'return' || title === 'returns';
+ }
+
function isProperty(title) {
return title === 'property' || title === 'prop';
}
function isNameParameterRequired(title) {
@@ -9248,14 +9075,14 @@
function isAllowedNested(title) {
return isProperty(title) || isParamTitle(title);
}
function isTypeParameterRequired(title) {
- return isParamTitle(title) || title === 'define' || title === 'enum' ||
- title === 'implements' || title === 'return' ||
- title === 'this' || title === 'type' || title === 'typedef' ||
- title === 'returns' || isProperty(title);
+ return isParamTitle(title) || isReturnTitle(title) ||
+ title === 'define' || title === 'enum' ||
+ title === 'implements' || title === 'this' ||
+ title === 'type' || title === 'typedef' || isProperty(title);
}
// Consider deprecation instead using 'isTypeParameterRequired' and 'Rules' declaration to pick when a type is optional/required
// This would require changes to 'parseType'
function isAllowedType(title) {
@@ -9319,11 +9146,11 @@
break;
}
index += 1;
}
- return result;
+ return result.replace(/\s+$/, '');
}
// JSDoc Tag Parser
(function (exports) {
@@ -9484,26 +9311,38 @@
name === 'event')) {
name += advance();
name += scanIdentifier(last);
}
+ if(source.charCodeAt(index) === 0x5B /* '[' */ && source.charCodeAt(index + 1) === 0x5D /* ']' */){
+ name += advance();
+ name += advance();
+ }
while (source.charCodeAt(index) === 0x2E /* '.' */ ||
source.charCodeAt(index) === 0x23 /* '#' */ ||
source.charCodeAt(index) === 0x7E /* '~' */) {
name += advance();
name += scanIdentifier(last);
}
}
if (useBrackets) {
+
+
// do we have a default value for this?
if (source.charCodeAt(index) === 0x3D /* '=' */) {
-
// consume the '='' symbol
name += advance();
+ var bracketDepth = 1;
// scan in the default value
- while (index < last && source.charCodeAt(index) !== 0x5D /* ']' */) {
+ while (index < last) {
+ if (source.charCodeAt(index) === 0x5B /* '[' */) {
+ bracketDepth++;
+ } else if (source.charCodeAt(index) === 0x5D /* ']' */ &&
+ --bracketDepth === 0) {
+ break;
+ }
name += advance();
}
}
if (index >= last || source.charCodeAt(index) !== 0x5D /* ']' */) {
@@ -9569,11 +9408,11 @@
// type required titles
if (isTypeParameterRequired(this._title)) {
try {
this._tag.type = parseType(this._title, this._last);
if (!this._tag.type) {
- if (!isParamTitle(this._title)) {
+ if (!isParamTitle(this._title) && !isReturnTitle(this._title)) {
if (!this.addError('Missing or invalid tag type')) {
return false;
}
}
}
@@ -9741,11 +9580,13 @@
description = this._tag.description;
// un-fix potentially sloppy declaration
if (isParamTitle(this._title) && !this._tag.type && description && description.charAt(0) === '[') {
this._tag.type = this._extra.name;
- this._tag.name = undefined;
+ if (!this._tag.name) {
+ this._tag.name = undefined;
+ }
if (!sloppy) {
if (!this.addError('Missing or invalid tag name')) {
return false;
}
@@ -9816,10 +9657,12 @@
'summary': ['parseDescription'],
// http://usejsdoc.org/tags-this.html
'this': ['parseNamePath', 'ensureEnd'],
// http://usejsdoc.org/tags-todo.html
'todo': ['parseDescription'],
+ // http://usejsdoc.org/tags-typedef.html
+ 'typedef': ['parseType', 'parseNamePathOptional'],
// http://usejsdoc.org/tags-variation.html
'variation': ['parseVariation'],
// http://usejsdoc.org/tags-version.html
'version': ['parseDescription']
};
@@ -9874,11 +9717,11 @@
//
// Parse JSDoc
//
- function scanJSDocDescription() {
+ function scanJSDocDescription(preserveWhitespace) {
var description = '', ch, atAllowed;
atAllowed = true;
while (index < length) {
ch = source.charCodeAt(index);
@@ -9893,11 +9736,12 @@
atAllowed = false;
}
description += advance();
}
- return trim(description);
+
+ return preserveWhitespace ? description : trim(description);
}
function parse(comment, options) {
var tags = [], tag, description, interestingTags, i, iz;
@@ -9932,11 +9776,11 @@
lineNumber = 0;
recoverable = options.recoverable;
sloppy = options.sloppy;
strict = options.strict;
- description = scanJSDocDescription();
+ description = scanJSDocDescription(options.preserveWhitespace);
while (true) {
tag = parseTag(options);
if (!tag) {
break;
@@ -9968,11 +9812,11 @@
stringify: typed.stringify
};
}());
/* vim: set sw=4 ts=4 et tw=80 : */
-},{"./typed":10,"./utility":11,"esutils":15,"isarray":16}],10:[function(require,module,exports){
+},{"./typed":11,"./utility":12,"esutils":16,"isarray":105}],11:[function(require,module,exports){
/*
Copyright (C) 2012-2014 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2014 Dan Tao <daniel.tao@gmail.com>
Copyright (C) 2013 Andrew Eisenberg <andrew@eisenberg.as>
@@ -11231,11 +11075,11 @@
exports.stringify = stringify;
exports.Syntax = Syntax;
}());
/* vim: set sw=4 ts=4 et tw=80 : */
-},{"./utility":11,"esutils":15}],11:[function(require,module,exports){
+},{"./utility":12,"esutils":16}],12:[function(require,module,exports){
/*
Copyright (C) 2014 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -11287,11 +11131,11 @@
exports.assert = require('assert');
}());
/* vim: set sw=4 ts=4 et tw=80 : */
-},{"../package.json":17,"assert":3}],12:[function(require,module,exports){
+},{"../package.json":17,"assert":5}],13:[function(require,module,exports){
/*
Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -11433,11 +11277,11 @@
trailingStatement: trailingStatement
};
}());
/* vim: set sw=4 ts=4 et tw=80 : */
-},{}],13:[function(require,module,exports){
+},{}],14:[function(require,module,exports){
/*
Copyright (C) 2013-2014 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2014 Ivan Nikulin <ifaaan@gmail.com>
Redistribution and use in source and binary forms, with or without
@@ -11536,11 +11380,11 @@
isIdentifierPart: isIdentifierPart
};
}());
/* vim: set sw=4 ts=4 et tw=80 : */
-},{}],14:[function(require,module,exports){
+},{}],15:[function(require,module,exports){
/*
Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -11675,11 +11519,11 @@
isIdentifierES6: isIdentifierES6
};
}());
/* vim: set sw=4 ts=4 et tw=80 : */
-},{"./code":13}],15:[function(require,module,exports){
+},{"./code":14}],16:[function(require,module,exports){
/*
Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -11710,1746 +11554,127 @@
exports.code = require('./code');
exports.keyword = require('./keyword');
}());
/* vim: set sw=4 ts=4 et tw=80 : */
-},{"./ast":12,"./code":13,"./keyword":14}],16:[function(require,module,exports){
-module.exports = Array.isArray || function (arr) {
- return Object.prototype.toString.call(arr) == '[object Array]';
-};
-
-},{}],17:[function(require,module,exports){
+},{"./ast":13,"./code":14,"./keyword":15}],17:[function(require,module,exports){
module.exports={
- "name": "doctrine",
- "description": "JSDoc parser",
- "homepage": "http://github.com/Constellation/doctrine.html",
- "main": "lib/doctrine.js",
- "version": "0.6.4",
- "engines": {
- "node": ">=0.10.0"
+ "_args": [
+ [
+ "doctrine@^0.7.0",
+ "/Users/force/code/eslint"
+ ]
+ ],
+ "_from": "doctrine@>=0.7.0 <0.8.0",
+ "_id": "doctrine@0.7.1",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/doctrine",
+ "_npmUser": {
+ "email": "nicholas@nczconsulting.com",
+ "name": "nzakas"
},
- "directories": {
- "lib": "./lib"
+ "_npmVersion": "1.4.28",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "doctrine",
+ "raw": "doctrine@^0.7.0",
+ "rawSpec": "^0.7.0",
+ "scope": null,
+ "spec": ">=0.7.0 <0.8.0",
+ "type": "range"
},
- "maintainers": [
- {
- "name": "constellation",
- "email": "utatane.tea@gmail.com"
- }
+ "_requiredBy": [
+ "/"
],
- "repository": {
- "type": "git",
- "url": "http://github.com/Constellation/doctrine.git"
+ "_resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.1.tgz",
+ "_shasum": "7ecff8b8981693c0a1ce9cc5438a7ec55e29f702",
+ "_shrinkwrap": null,
+ "_spec": "doctrine@^0.7.0",
+ "_where": "/Users/force/code/eslint",
+ "bugs": {
+ "url": "https://github.com/eslint/doctrine/issues"
},
+ "dependencies": {
+ "esutils": "^1.1.6",
+ "isarray": "0.0.1"
+ },
+ "description": "JSDoc parser",
"devDependencies": {
"coveralls": "^2.11.2",
+ "dateformat": "^1.0.11",
+ "eslint": "^1.9.0",
"gulp": "^3.8.10",
"gulp-bump": "^0.1.13",
"gulp-eslint": "^0.5.0",
"gulp-filter": "^2.0.2",
"gulp-git": "^1.0.0",
"gulp-istanbul": "^0.6.0",
"gulp-jshint": "^1.9.0",
"gulp-mocha": "^2.0.0",
"gulp-tag-version": "^1.2.1",
"jshint-stylish": "^1.0.0",
+ "mocha": "^2.3.3",
+ "npm-license": "^0.3.1",
+ "semver": "^5.0.3",
+ "shelljs": "^0.5.3",
+ "shelljs-nodecli": "^0.1.1",
"should": "^5.0.1"
},
+ "directories": {
+ "lib": "./lib"
+ },
+ "dist": {
+ "shasum": "7ecff8b8981693c0a1ce9cc5438a7ec55e29f702",
+ "tarball": "http://registry.npmjs.org/doctrine/-/doctrine-0.7.1.tgz"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "files": [
+ "LICENSE.BSD",
+ "LICENSE.closure-compiler",
+ "LICENSE.esprima",
+ "README.md",
+ "lib"
+ ],
+ "gitHead": "400aea03020456769eb4048c349892c7a7dcfb6e",
+ "homepage": "https://github.com/eslint/doctrine",
"licenses": [
{
"type": "BSD",
- "url": "http://github.com/Constellation/doctrine/raw/master/LICENSE.BSD"
+ "url": "http://github.com/eslint/doctrine/raw/master/LICENSE.BSD"
}
],
+ "main": "lib/doctrine.js",
+ "maintainers": [
+ {
+ "name": "constellation",
+ "email": "utatane.tea@gmail.com"
+ },
+ {
+ "name": "nzakas",
+ "email": "nicholas@nczconsulting.com"
+ }
+ ],
+ "name": "doctrine",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/eslint/doctrine.git"
+ },
"scripts": {
- "test": "gulp",
- "unit-test": "gulp test",
+ "coveralls": "cat ./coverage/lcov.info | coveralls && rm -rf ./coverage",
"lint": "gulp lint",
- "coveralls": "cat ./coverage/lcov.info | coveralls && rm -rf ./coverage"
+ "test": "gulp",
+ "unit-test": "gulp test"
},
- "dependencies": {
- "esutils": "^1.1.6",
- "isarray": "0.0.1"
- },
- "gitHead": "0835299b485ecdfa908d20628d6c8900144590ff",
- "bugs": {
- "url": "https://github.com/Constellation/doctrine/issues"
- },
- "_id": "doctrine@0.6.4",
- "_shasum": "81428491a942ef18b0492056eda3800eee57d61d",
- "_from": "doctrine@>=0.6.2 <0.7.0",
- "_npmVersion": "1.4.28",
- "_npmUser": {
- "name": "constellation",
- "email": "utatane.tea@gmail.com"
- },
- "dist": {
- "shasum": "81428491a942ef18b0492056eda3800eee57d61d",
- "tarball": "http://registry.npmjs.org/doctrine/-/doctrine-0.6.4.tgz"
- },
- "_resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.6.4.tgz",
- "readme": "ERROR: No README data found!"
+ "version": "0.7.1"
}
},{}],18:[function(require,module,exports){
-'use strict';
-
-var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
-
-module.exports = function (str) {
- if (typeof str !== 'string') {
- throw new TypeError('Expected a string');
- }
-
- return str.replace(matchOperatorsRe, '\\$&');
-};
-
-},{}],19:[function(require,module,exports){
-/*
- Copyright (C) 2012-2014 Yusuke Suzuki <utatane.tea@gmail.com>
- Copyright (C) 2013 Alex Seville <hi@alexanderseville.com>
- Copyright (C) 2014 Thiago de Arruda <tpadilha84@gmail.com>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- * Escope (<a href="http://github.com/Constellation/escope">escope</a>) is an <a
- * href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript</a>
- * scope analyzer extracted from the <a
- * href="http://github.com/Constellation/esmangle">esmangle project</a/>.
- * <p>
- * <em>escope</em> finds lexical scopes in a source program, i.e. areas of that
- * program where different occurrences of the same identifier refer to the same
- * variable. With each scope the contained variables are collected, and each
- * identifier reference in code is linked to its corresponding variable (if
- * possible).
- * <p>
- * <em>escope</em> works on a syntax tree of the parsed source code which has
- * to adhere to the <a
- * href="https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API">
- * Mozilla Parser API</a>. E.g. <a href="http://esprima.org">esprima</a> is a parser
- * that produces such syntax trees.
- * <p>
- * The main interface is the {@link analyze} function.
- * @module
- */
-
-/*jslint bitwise:true */
-(function () {
- 'use strict';
-
- var Syntax,
- util,
- extend,
- estraverse,
- esrecurse,
- Map,
- WeakMap;
-
- util = require('util');
- extend = require('util-extend');
- estraverse = require('estraverse');
- esrecurse = require('esrecurse');
-
- Map = require('es6-map');
- WeakMap = require('es6-weak-map');
-
- Syntax = estraverse.Syntax;
-
- function assert(cond, text) {
- if (!cond) {
- throw new Error(text);
- }
- }
-
- function defaultOptions() {
- return {
- optimistic: false,
- directive: false,
- nodejsScope: false,
- sourceType: 'script', // one of ['script', 'module']
- ecmaVersion: 5
- };
- }
-
- function updateDeeply(target, override) {
- var key, val;
-
- function isHashObject(target) {
- return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
- }
-
- for (key in override) {
- if (override.hasOwnProperty(key)) {
- val = override[key];
- if (isHashObject(val)) {
- if (isHashObject(target[key])) {
- updateDeeply(target[key], val);
- } else {
- target[key] = updateDeeply({}, val);
- }
- } else {
- target[key] = val;
- }
- }
- }
- return target;
- }
-
- /**
- * A Reference represents a single occurrence of an identifier in code.
- * @class Reference
- */
- function Reference(ident, scope, flag, writeExpr, maybeImplicitGlobal, partial) {
- /**
- * Identifier syntax node.
- * @member {esprima#Identifier} Reference#identifier
- */
- this.identifier = ident;
- /**
- * Reference to the enclosing Scope.
- * @member {Scope} Reference#from
- */
- this.from = scope;
- /**
- * Whether the reference comes from a dynamic scope (such as 'eval',
- * 'with', etc.), and may be trapped by dynamic scopes.
- * @member {boolean} Reference#tainted
- */
- this.tainted = false;
- /**
- * The variable this reference is resolved with.
- * @member {Variable} Reference#resolved
- */
- this.resolved = null;
- /**
- * The read-write mode of the reference. (Value is one of {@link
- * Reference.READ}, {@link Reference.RW}, {@link Reference.WRITE}).
- * @member {number} Reference#flag
- * @private
- */
- this.flag = flag;
- if (this.isWrite()) {
- /**
- * If reference is writeable, this is the tree being written to it.
- * @member {esprima#Node} Reference#writeExpr
- */
- this.writeExpr = writeExpr;
- /**
- * Whether the Reference might refer to a partial value of writeExpr.
- * @member {boolean} Reference#partial
- */
- this.partial = partial;
- }
- this.__maybeImplicitGlobal = maybeImplicitGlobal;
- }
-
- /**
- * @constant Reference.READ
- * @private
- */
- Reference.READ = 0x1;
- /**
- * @constant Reference.WRITE
- * @private
- */
- Reference.WRITE = 0x2;
- /**
- * @constant Reference.RW
- * @private
- */
- Reference.RW = Reference.READ | Reference.WRITE;
-
- /**
- * Whether the reference is static.
- * @method Reference#isStatic
- * @return {boolean}
- */
- Reference.prototype.isStatic = function isStatic() {
- return !this.tainted && this.resolved && this.resolved.scope.isStatic();
- };
-
- /**
- * Whether the reference is writeable.
- * @method Reference#isWrite
- * @return {boolean}
- */
- Reference.prototype.isWrite = function isWrite() {
- return !!(this.flag & Reference.WRITE);
- };
-
- /**
- * Whether the reference is readable.
- * @method Reference#isRead
- * @return {boolean}
- */
- Reference.prototype.isRead = function isRead() {
- return !!(this.flag & Reference.READ);
- };
-
- /**
- * Whether the reference is read-only.
- * @method Reference#isReadOnly
- * @return {boolean}
- */
- Reference.prototype.isReadOnly = function isReadOnly() {
- return this.flag === Reference.READ;
- };
-
- /**
- * Whether the reference is write-only.
- * @method Reference#isWriteOnly
- * @return {boolean}
- */
- Reference.prototype.isWriteOnly = function isWriteOnly() {
- return this.flag === Reference.WRITE;
- };
-
- /**
- * Whether the reference is read-write.
- * @method Reference#isReadWrite
- * @return {boolean}
- */
- Reference.prototype.isReadWrite = function isReadWrite() {
- return this.flag === Reference.RW;
- };
-
- /**
- * A Variable represents a locally scoped identifier. These include arguments to
- * functions.
- * @class Variable
- */
- function Variable(name, scope) {
- /**
- * The variable name, as given in the source code.
- * @member {String} Variable#name
- */
- this.name = name;
- /**
- * List of defining occurrences of this variable (like in 'var ...'
- * statements or as parameter), as AST nodes.
- * @member {esprima.Identifier[]} Variable#identifiers
- */
- this.identifiers = [];
- /**
- * List of {@link Reference|references} of this variable (excluding parameter entries)
- * in its defining scope and all nested scopes. For defining
- * occurrences only see {@link Variable#defs}.
- * @member {Reference[]} Variable#references
- */
- this.references = [];
-
- /**
- * List of defining occurrences of this variable (like in 'var ...'
- * statements or as parameter), as custom objects.
- * @typedef {Object} DefEntry
- * @property {String} DefEntry.type - the type of the occurrence (e.g.
- * "Parameter", "Variable", ...)
- * @property {esprima.Identifier} DefEntry.name - the identifier AST node of the occurrence
- * @property {esprima.Node} DefEntry.node - the enclosing node of the
- * identifier
- * @property {esprima.Node} [DefEntry.parent] - the enclosing statement
- * node of the identifier
- * @member {DefEntry[]} Variable#defs
- */
- this.defs = [];
-
- this.tainted = false;
- /**
- * Whether this is a stack variable.
- * @member {boolean} Variable#stack
- */
- this.stack = true;
- /**
- * Reference to the enclosing Scope.
- * @member {Scope} Variable#scope
- */
- this.scope = scope;
- }
-
- Variable.CatchClause = 'CatchClause';
- Variable.Parameter = 'Parameter';
- Variable.FunctionName = 'FunctionName';
- Variable.ClassName = 'ClassName';
- Variable.Variable = 'Variable';
- Variable.ImportBinding = 'ImportBinding';
- Variable.TDZ = 'TDZ';
- Variable.ImplicitGlobalVariable = 'ImplicitGlobalVariable';
-
- function isStrictScope(scope, block, isMethodDefinition, useDirective) {
- var body, i, iz, stmt, expr;
-
- // When upper scope is exists and strict, inner scope is also strict.
- if (scope.upper && scope.upper.isStrict) {
- return true;
- }
-
- // ArrowFunctionExpression's scope is always strict scope.
- if (block.type === Syntax.ArrowFunctionExpression) {
- return true;
- }
-
- if (isMethodDefinition) {
- return true;
- }
-
- if (scope.type === 'class' || scope.type === 'module') {
- return true;
- }
-
- if (scope.type === 'block' || scope.type === 'switch') {
- return false;
- }
-
- if (scope.type === 'function') {
- if (block.type === 'Program') {
- body = block;
- } else {
- body = block.body;
- }
- } else if (scope.type === 'global') {
- body = block;
- } else {
- return false;
- }
-
- // Search 'use strict' directive.
- if (useDirective) {
- for (i = 0, iz = body.body.length; i < iz; ++i) {
- stmt = body.body[i];
- if (stmt.type !== 'DirectiveStatement') {
- break;
- }
- if (stmt.raw === '"use strict"' || stmt.raw === '\'use strict\'') {
- return true;
- }
- }
- } else {
- for (i = 0, iz = body.body.length; i < iz; ++i) {
- stmt = body.body[i];
- if (stmt.type !== Syntax.ExpressionStatement) {
- break;
- }
- expr = stmt.expression;
- if (expr.type !== Syntax.Literal || typeof expr.value !== 'string') {
- break;
- }
- if (expr.raw != null) {
- if (expr.raw === '"use strict"' || expr.raw === '\'use strict\'') {
- return true;
- }
- } else {
- if (expr.value === 'use strict') {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- function registerScope(scopeManager, scope) {
- var scopes;
-
- scopeManager.scopes.push(scope);
-
- scopes = scopeManager.__nodeToScope.get(scope.block);
- if (scopes) {
- scopes.push(scope);
- } else {
- scopeManager.__nodeToScope.set(scope.block, [ scope ]);
- }
- }
-
- /* Special Scope types. */
- var SCOPE_NORMAL = 0,
- SCOPE_MODULE = 1,
- SCOPE_FUNCTION_EXPRESSION_NAME = 2,
- SCOPE_TDZ = 3,
- SCOPE_FUNCTION = 4;
-
- /**
- * @class Scope
- */
- function Scope(scopeManager, block, isMethodDefinition, scopeType) {
- /**
- * One of 'catch', 'with', 'function', 'global' or 'block'.
- * @member {String} Scope#type
- */
- this.type =
- (scopeType === SCOPE_TDZ) ? 'TDZ' :
- (scopeType === SCOPE_MODULE) ? 'module' :
- (block.type === Syntax.BlockStatement) ? 'block' :
- (block.type === Syntax.SwitchStatement) ? 'switch' :
- (scopeType === SCOPE_FUNCTION || block.type === Syntax.FunctionExpression || block.type === Syntax.FunctionDeclaration || block.type === Syntax.ArrowFunctionExpression) ? 'function' :
- (block.type === Syntax.CatchClause) ? 'catch' :
- (block.type === Syntax.ForInStatement || block.type === Syntax.ForOfStatement || block.type === Syntax.ForStatement) ? 'for' :
- (block.type === Syntax.WithStatement) ? 'with' :
- (block.type === Syntax.ClassExpression || block.type === Syntax.ClassDeclaration) ? 'class' : 'global';
- /**
- * The scoped {@link Variable}s of this scope, as <code>{ Variable.name
- * : Variable }</code>.
- * @member {Map} Scope#set
- */
- this.set = new Map();
- /**
- * The tainted variables of this scope, as <code>{ Variable.name :
- * boolean }</code>.
- * @member {Map} Scope#taints */
- this.taints = new Map();
- /**
- * Generally, through the lexical scoping of JS you can always know
- * which variable an identifier in the source code refers to. There are
- * a few exceptions to this rule. With 'global' and 'with' scopes you
- * can only decide at runtime which variable a reference refers to.
- * Moreover, if 'eval()' is used in a scope, it might introduce new
- * bindings in this or its prarent scopes.
- * All those scopes are considered 'dynamic'.
- * @member {boolean} Scope#dynamic
- */
- this.dynamic = this.type === 'global' || this.type === 'with';
- /**
- * A reference to the scope-defining syntax node.
- * @member {esprima.Node} Scope#block
- */
- this.block = block;
- /**
- * The {@link Reference|references} that are not resolved with this scope.
- * @member {Reference[]} Scope#through
- */
- this.through = [];
- /**
- * The scoped {@link Variable}s of this scope. In the case of a
- * 'function' scope this includes the automatic argument <em>arguments</em> as
- * its first element, as well as all further formal arguments.
- * @member {Variable[]} Scope#variables
- */
- this.variables = [];
- /**
- * Any variable {@link Reference|reference} found in this scope. This
- * includes occurrences of local variables as well as variables from
- * parent scopes (including the global scope). For local variables
- * this also includes defining occurrences (like in a 'var' statement).
- * In a 'function' scope this does not include the occurrences of the
- * formal parameter in the parameter list.
- * @member {Reference[]} Scope#references
- */
- this.references = [];
-
- /**
- * For 'global' and 'function' scopes, this is a self-reference. For
- * other scope types this is the <em>variableScope</em> value of the
- * parent scope.
- * @member {Scope} Scope#variableScope
- */
- this.variableScope =
- (this.type === 'global' || this.type === 'function' || this.type === 'module') ? this : scopeManager.__currentScope.variableScope;
- /**
- * Whether this scope is created by a FunctionExpression.
- * @member {boolean} Scope#functionExpressionScope
- */
- this.functionExpressionScope = false;
- /**
- * Whether this is a scope that contains an 'eval()' invocation.
- * @member {boolean} Scope#directCallToEvalScope
- */
- this.directCallToEvalScope = false;
- /**
- * @member {boolean} Scope#thisFound
- */
- this.thisFound = false;
-
- this.__left = [];
-
- if (scopeType === SCOPE_FUNCTION_EXPRESSION_NAME) {
- this.__define(block.id, {
- type: Variable.FunctionName,
- name: block.id,
- node: block
- });
- this.functionExpressionScope = true;
- } else {
- // section 9.2.13, FunctionDeclarationInstantiation.
- // NOTE Arrow functions never have an arguments objects.
- if (this.type === 'function' && this.block.type !== Syntax.ArrowFunctionExpression) {
- this.__defineArguments();
- }
-
- if (block.type === Syntax.FunctionExpression && block.id) {
- scopeManager.__nestFunctionExpressionNameScope(block, isMethodDefinition);
- }
- }
-
- /**
- * Reference to the parent {@link Scope|scope}.
- * @member {Scope} Scope#upper
- */
- this.upper = scopeManager.__currentScope;
- /**
- * Whether 'use strict' is in effect in this scope.
- * @member {boolean} Scope#isStrict
- */
- this.isStrict = isStrictScope(this, block, isMethodDefinition, scopeManager.__useDirective());
-
- /**
- * List of nested {@link Scope}s.
- * @member {Scope[]} Scope#childScopes
- */
- this.childScopes = [];
- if (scopeManager.__currentScope) {
- scopeManager.__currentScope.childScopes.push(this);
- }
-
-
- // RAII
- scopeManager.__currentScope = this;
- if (this.type === 'global') {
- scopeManager.globalScope = this;
- scopeManager.globalScope.implicit = {
- set: new Map(),
- variables: [],
- /**
- * List of {@link Reference}s that are left to be resolved (i.e. which
- * need to be linked to the variable they refer to).
- * @member {Reference[]} Scope#implicit#left
- */
- left: []
- };
- }
-
- registerScope(scopeManager, this);
- }
-
- Scope.prototype.__close = function __close(scopeManager) {
- var i, iz, ref, current, implicit, info;
-
- // Because if this is global environment, upper is null
- if (!this.dynamic || scopeManager.__isOptimistic()) {
- // static resolve
- for (i = 0, iz = this.__left.length; i < iz; ++i) {
- ref = this.__left[i];
- if (!this.__resolve(ref)) {
- this.__delegateToUpperScope(ref);
- }
- }
- } else {
- // this is "global" / "with" / "function with eval" environment
- if (this.type === 'with') {
- for (i = 0, iz = this.__left.length; i < iz; ++i) {
- ref = this.__left[i];
- ref.tainted = true;
- this.__delegateToUpperScope(ref);
- }
- } else {
- for (i = 0, iz = this.__left.length; i < iz; ++i) {
- // notify all names are through to global
- ref = this.__left[i];
- current = this;
- do {
- current.through.push(ref);
- current = current.upper;
- } while (current);
- }
- }
- }
-
- if (this.type === 'global') {
- implicit = [];
- for (i = 0, iz = this.__left.length; i < iz; ++i) {
- ref = this.__left[i];
- if (ref.__maybeImplicitGlobal && !this.set.has(ref.identifier.name)) {
- implicit.push(ref.__maybeImplicitGlobal);
- }
- }
-
- // create an implicit global variable from assignment expression
- for (i = 0, iz = implicit.length; i < iz; ++i) {
- info = implicit[i];
- this.__defineImplicit(info.pattern, {
- type: Variable.ImplicitGlobalVariable,
- name: info.pattern,
- node: info.node
- });
- }
-
- this.implicit.left = this.__left;
- }
-
- this.__left = null;
- scopeManager.__currentScope = this.upper;
- };
-
- Scope.prototype.__resolve = function __resolve(ref) {
- var variable, name;
- name = ref.identifier.name;
- if (this.set.has(name)) {
- variable = this.set.get(name);
- variable.references.push(ref);
- variable.stack = variable.stack && ref.from.variableScope === this.variableScope;
- if (ref.tainted) {
- variable.tainted = true;
- this.taints.set(variable.name, true);
- }
- ref.resolved = variable;
- return true;
- }
- return false;
- };
-
- Scope.prototype.__delegateToUpperScope = function __delegateToUpperScope(ref) {
- if (this.upper) {
- this.upper.__left.push(ref);
- }
- this.through.push(ref);
- };
-
- Scope.prototype.__defineGeneric = function (name, set, variables, node, info) {
- var variable;
-
- variable = set.get(name);
- if (!variable) {
- variable = new Variable(name, this);
- set.set(name, variable);
- variables.push(variable);
- }
-
- if (info) {
- variable.defs.push(info);
- }
- if (node) {
- variable.identifiers.push(node);
- }
- };
-
- Scope.prototype.__defineArguments = function () {
- this.__defineGeneric('arguments', this.set, this.variables);
- this.taints.set('arguments', true);
- };
-
- Scope.prototype.__defineImplicit = function (node, info) {
- if (node && node.type === Syntax.Identifier) {
- this.__defineGeneric(node.name, this.implicit.set, this.implicit.variables, node, info);
- }
- };
-
- Scope.prototype.__define = function (node, info) {
- if (node && node.type === Syntax.Identifier) {
- this.__defineGeneric(node.name, this.set, this.variables, node, info);
- }
- };
-
- Scope.prototype.__referencing = function __referencing(node, assign, writeExpr, maybeImplicitGlobal, partial) {
- var ref;
- // because Array element may be null
- if (node && node.type === Syntax.Identifier) {
- ref = new Reference(node, this, assign || Reference.READ, writeExpr, maybeImplicitGlobal, !!partial);
- this.references.push(ref);
- this.__left.push(ref);
- }
- };
-
- Scope.prototype.__detectEval = function __detectEval() {
- var current;
- current = this;
- this.directCallToEvalScope = true;
- do {
- current.dynamic = true;
- current = current.upper;
- } while (current);
- };
-
- Scope.prototype.__detectThis = function __detectThis() {
- this.thisFound = true;
- };
-
- Scope.prototype.__isClosed = function isClosed() {
- return this.__left === null;
- };
-
- // API Scope#resolve(name)
- // returns resolved reference
- Scope.prototype.resolve = function resolve(ident) {
- var ref, i, iz;
- assert(this.__isClosed(), 'scope should be closed');
- assert(ident.type === Syntax.Identifier, 'target should be identifier');
- for (i = 0, iz = this.references.length; i < iz; ++i) {
- ref = this.references[i];
- if (ref.identifier === ident) {
- return ref;
- }
- }
- return null;
- };
-
- // API Scope#isStatic
- // returns this scope is static
- Scope.prototype.isStatic = function isStatic() {
- return !this.dynamic;
- };
-
- // API Scope#isArgumentsMaterialized
- // return this scope has materialized arguments
- Scope.prototype.isArgumentsMaterialized = function isArgumentsMaterialized() {
- // TODO(Constellation)
- // We can more aggressive on this condition like this.
- //
- // function t() {
- // // arguments of t is always hidden.
- // function arguments() {
- // }
- // }
- var variable;
-
- // This is not function scope
- if (this.type !== 'function') {
- return true;
- }
-
- if (!this.isStatic()) {
- return true;
- }
-
- variable = this.set.get('arguments');
- assert(variable, 'always have arguments variable');
- return variable.tainted || variable.references.length !== 0;
- };
-
- // API Scope#isThisMaterialized
- // return this scope has materialized `this` reference
- Scope.prototype.isThisMaterialized = function isThisMaterialized() {
- // This is not function scope
- if (this.type !== 'function') {
- return true;
- }
- if (!this.isStatic()) {
- return true;
- }
- return this.thisFound;
- };
-
- Scope.prototype.isUsedName = function (name) {
- if (this.set.has(name)) {
- return true;
- }
- for (var i = 0, iz = this.through.length; i < iz; ++i) {
- if (this.through[i].identifier.name === name) {
- return true;
- }
- }
- return false;
- };
-
- /**
- * @class ScopeManager
- */
- function ScopeManager(options) {
- this.scopes = [];
- this.globalScope = null;
- this.__nodeToScope = new WeakMap();
- this.__currentScope = null;
- this.__options = options;
- }
-
- ScopeManager.prototype.__useDirective = function () {
- return this.__options.directive;
- };
-
- ScopeManager.prototype.__isOptimistic = function () {
- return this.__options.optimistic;
- };
-
- ScopeManager.prototype.__ignoreEval = function () {
- return this.__options.ignoreEval;
- };
-
- ScopeManager.prototype.__isNodejsScope = function () {
- return this.__options.nodejsScope;
- };
-
- ScopeManager.prototype.isModule = function () {
- return this.__options.sourceType === 'module';
- };
-
- // Returns appropliate scope for this node.
- ScopeManager.prototype.__get = function __get(node) {
- return this.__nodeToScope.get(node);
- };
-
- ScopeManager.prototype.acquire = function acquire(node, inner) {
- var scopes, scope, i, iz;
-
- function predicate(scope) {
- if (scope.type === 'function' && scope.functionExpressionScope) {
- return false;
- }
- if (scope.type === 'TDZ') {
- return false;
- }
- return true;
- }
-
- scopes = this.__get(node);
- if (!scopes || scopes.length === 0) {
- return null;
- }
-
- // Heuristic selection from all scopes.
- // If you would like to get all scopes, please use ScopeManager#acquireAll.
- if (scopes.length === 1) {
- return scopes[0];
- }
-
- if (inner) {
- for (i = scopes.length - 1; i >= 0; --i) {
- scope = scopes[i];
- if (predicate(scope)) {
- return scope;
- }
- }
- } else {
- for (i = 0, iz = scopes.length; i < iz; ++i) {
- scope = scopes[i];
- if (predicate(scope)) {
- return scope;
- }
- }
- }
-
- return null;
- };
-
- ScopeManager.prototype.acquireAll = function acquire(node) {
- return this.__get(node);
- };
-
- ScopeManager.prototype.release = function release(node, inner) {
- var scopes, scope;
- scopes = this.__get(node);
- if (scopes && scopes.length) {
- scope = scopes[0].upper;
- if (!scope) {
- return null;
- }
- return this.acquire(scope.block, inner);
- }
- return null;
- };
-
- ScopeManager.prototype.attach = function attach() { };
-
- ScopeManager.prototype.detach = function detach() { };
-
- ScopeManager.prototype.__nestScope = function (node, isMethodDefinition) {
- return new Scope(this, node, isMethodDefinition, SCOPE_NORMAL);
- };
-
- ScopeManager.prototype.__nestForceFunctionScope = function (node) {
- return new Scope(this, node, false, SCOPE_FUNCTION);
- };
-
- ScopeManager.prototype.__nestModuleScope = function (node) {
- return new Scope(this, node, false, SCOPE_MODULE);
- };
-
- ScopeManager.prototype.__nestTDZScope = function (node) {
- return new Scope(this, node, false, SCOPE_TDZ);
- };
-
- ScopeManager.prototype.__nestFunctionExpressionNameScope = function (node, isMethodDefinition) {
- return new Scope(this, node, isMethodDefinition, SCOPE_FUNCTION_EXPRESSION_NAME);
- };
-
- ScopeManager.prototype.__isES6 = function () {
- return this.__options.ecmaVersion >= 6;
- };
-
- function traverseIdentifierInPattern(rootPattern, callback) {
- estraverse.traverse(rootPattern, {
- enter: function (pattern, parent) {
- var i, iz, element, property;
-
- switch (pattern.type) {
- case Syntax.Identifier:
- // Toplevel identifier.
- if (parent === null) {
- callback(pattern, true);
- }
- break;
-
- case Syntax.SpreadElement:
- if (pattern.argument.type === Syntax.Identifier) {
- callback(pattern.argument, false);
- }
- break;
-
- case Syntax.ObjectPattern:
- for (i = 0, iz = pattern.properties.length; i < iz; ++i) {
- property = pattern.properties[i];
- if (property.shorthand) {
- callback(property.key, false);
- continue;
- }
- if (property.value.type === Syntax.Identifier) {
- callback(property.value, false);
- continue;
- }
- }
- break;
-
- case Syntax.ArrayPattern:
- for (i = 0, iz = pattern.elements.length; i < iz; ++i) {
- element = pattern.elements[i];
- if (element && element.type === Syntax.Identifier) {
- callback(element, false);
- }
- }
- break;
- }
- }
- });
- }
-
- function isPattern(node) {
- var nodeType = node.type;
- return nodeType === Syntax.Identifier || nodeType === Syntax.ObjectPattern || nodeType === Syntax.ArrayPattern || nodeType === Syntax.SpreadElement;
- }
-
- // Importing ImportDeclaration.
- // http://people.mozilla.org/~jorendorff/es6-draft.html#sec-moduledeclarationinstantiation
- // FIXME: Now, we don't create module environment, because the context is
- // implementation dependent.
-
- function Importer(declaration, referencer) {
- esrecurse.Visitor.call(this, this);
- this.declaration = declaration;
- this.referencer = referencer;
- }
- util.inherits(Importer, esrecurse.Visitor);
-
- Importer.prototype.visitImport = function (id, specifier) {
- var that = this;
- that.referencer.visitPattern(id, function (pattern) {
- that.referencer.currentScope().__define(pattern, {
- type: Variable.ImportBinding,
- name: pattern,
- node: specifier,
- parent: that.declaration
- });
- });
- };
-
- Importer.prototype.ImportNamespaceSpecifier = function (node) {
- if (node.id) {
- this.visitImport(node.id, node);
- }
- };
-
- Importer.prototype.ImportDefaultSpecifier = function (node) {
- this.visitImport(node.id, node);
- };
-
- Importer.prototype.ImportSpecifier = function (node) {
- if (node.name) {
- this.visitImport(node.name, node);
- } else {
- this.visitImport(node.id, node);
- }
- };
-
- // Referencing variables and creating bindings.
-
- function Referencer(scopeManager) {
- esrecurse.Visitor.call(this, this);
- this.scopeManager = scopeManager;
- this.parent = null;
- this.isInnerMethodDefinition = false;
- }
-
- util.inherits(Referencer, esrecurse.Visitor);
-
- extend(Referencer.prototype, {
- currentScope: function () {
- return this.scopeManager.__currentScope;
- },
-
- close: function (node) {
- while (this.currentScope() && node === this.currentScope().block) {
- this.currentScope().__close(this.scopeManager);
- }
- },
-
- pushInnerMethodDefinition: function (isInnerMethodDefinition) {
- var previous = this.isInnerMethodDefinition;
- this.isInnerMethodDefinition = isInnerMethodDefinition;
- return previous;
- },
-
- popInnerMethodDefinition: function (isInnerMethodDefinition) {
- this.isInnerMethodDefinition = isInnerMethodDefinition;
- },
-
- materializeTDZScope: function (node, iterationNode) {
- // http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-forin-div-ofexpressionevaluation-abstract-operation
- // TDZ scope hides the declaration's names.
- this.scopeManager.__nestTDZScope(node, iterationNode);
- this.visitVariableDeclaration(this.currentScope(), Variable.TDZ, iterationNode.left, 0);
- },
-
- materializeIterationScope: function (node) {
- // Generate iteration scope for upper ForIn/ForOf Statements.
- // parent node for __nestScope is only necessary to
- // distinguish MethodDefinition.
- var letOrConstDecl, that = this;
- this.scopeManager.__nestScope(node, false);
- letOrConstDecl = node.left;
- this.visitVariableDeclaration(this.currentScope(), Variable.Variable, letOrConstDecl, 0);
- this.visitPattern(letOrConstDecl.declarations[0].id, function (pattern) {
- that.currentScope().__referencing(pattern, Reference.WRITE, node.right, null, true);
- });
- },
-
- visitPattern: function (node, callback) {
- traverseIdentifierInPattern(node, callback);
- },
-
- visitFunction: function (node) {
- var i, iz, that = this;
- // FunctionDeclaration name is defined in upper scope
- // NOTE: Not referring variableScope. It is intended.
- // Since
- // in ES5, FunctionDeclaration should be in FunctionBody.
- // in ES6, FunctionDeclaration should be block scoped.
- if (node.type === Syntax.FunctionDeclaration) {
- // id is defined in upper scope
- this.currentScope().__define(node.id, {
- type: Variable.FunctionName,
- name: node.id,
- node: node
- });
- }
-
- // Consider this function is in the MethodDefinition.
- this.scopeManager.__nestScope(node, this.isInnerMethodDefinition);
-
- for (i = 0, iz = node.params.length; i < iz; ++i) {
- this.visitPattern(node.params[i], function (pattern) {
- that.currentScope().__define(pattern, {
- type: Variable.Parameter,
- name: pattern,
- node: node,
- index: i,
- rest: false
- });
- });
- }
-
-
- // if there's a rest argument, add that
- if (node.rest) {
- this.visitPattern(node.rest, function (pattern) {
- that.currentScope().__define(pattern, {
- type: Variable.Parameter,
- name: pattern,
- node: node,
- index: node.params.length,
- rest: true
- });
- });
- }
-
- // Skip BlockStatement to prevent creating BlockStatement scope.
- if (node.body.type === Syntax.BlockStatement) {
- this.visitChildren(node.body);
- } else {
- this.visit(node.body);
- }
-
- this.close(node);
- },
-
- visitClass: function (node) {
- if (node.type === Syntax.ClassDeclaration) {
- this.currentScope().__define(node.id, {
- type: Variable.ClassName,
- name: node.id,
- node: node
- });
- }
-
- // FIXME: Maybe consider TDZ.
- this.visit(node.superClass);
-
- this.scopeManager.__nestScope(node);
-
- if (node.id) {
- this.currentScope().__define(node.id, {
- type: Variable.ClassName,
- name: node.id,
- node: node
- });
- }
- this.visit(node.body);
-
- this.close(node);
- },
-
- visitProperty: function (node) {
- var previous, isMethodDefinition;
- if (node.computed) {
- this.visit(node.key);
- }
-
- isMethodDefinition = node.type === Syntax.MethodDefinition || node.method;
- if (isMethodDefinition) {
- previous = this.pushInnerMethodDefinition(true);
- }
- this.visit(node.value);
- if (isMethodDefinition) {
- this.popInnerMethodDefinition(previous);
- }
- },
-
- visitForIn: function (node) {
- var that = this;
- if (node.left.type === Syntax.VariableDeclaration && node.left.kind !== 'var') {
- this.materializeTDZScope(node.right, node);
- this.visit(node.right);
- this.close(node.right);
-
- this.materializeIterationScope(node);
- this.visit(node.body);
- this.close(node);
- } else {
- if (node.left.type === Syntax.VariableDeclaration) {
- this.visit(node.left);
- this.visitPattern(node.left.declarations[0].id, function (pattern) {
- that.currentScope().__referencing(pattern, Reference.WRITE, node.right, null, true);
- });
- } else {
- if (!isPattern(node.left)) {
- this.visit(node.left);
- }
- this.visitPattern(node.left, function (pattern) {
- var maybeImplicitGlobal = null;
- if (!that.currentScope().isStrict) {
- maybeImplicitGlobal = {
- pattern: pattern,
- node: node
- };
- }
- that.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, true);
- });
- }
- this.visit(node.right);
- this.visit(node.body);
- }
- },
-
- visitVariableDeclaration: function (variableTargetScope, type, node, index) {
- var decl, init, that = this;
-
- decl = node.declarations[index];
- init = decl.init;
- // FIXME: Don't consider initializer with complex patterns.
- // Such as,
- // var [a, b, c = 20] = array;
- this.visitPattern(decl.id, function (pattern, toplevel) {
- variableTargetScope.__define(pattern, {
- type: type,
- name: pattern,
- node: decl,
- index: index,
- kind: node.kind,
- parent: node
- });
-
- if (init) {
- that.currentScope().__referencing(pattern, Reference.WRITE, init, null, !toplevel);
- }
- });
- },
-
- AssignmentExpression: function (node) {
- var that = this;
- if (isPattern(node.left)) {
- if (node.operator === '=') {
- this.visitPattern(node.left, function (pattern, toplevel) {
- var maybeImplicitGlobal = null;
- if (!that.currentScope().isStrict) {
- maybeImplicitGlobal = {
- pattern: pattern,
- node: node
- };
- }
- that.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, !toplevel);
- });
- } else {
- that.currentScope().__referencing(node.left, Reference.RW, node.right);
- }
- } else {
- this.visit(node.left);
- }
- this.visit(node.right);
- },
-
- CatchClause: function (node) {
- var that = this;
- this.scopeManager.__nestScope(node);
-
- this.visitPattern(node.param, function (pattern) {
- that.currentScope().__define(pattern, {
- type: Variable.CatchClause,
- name: node.param,
- node: node
- });
- });
- this.visit(node.body);
-
- this.close(node);
- },
-
- Program: function (node) {
- this.scopeManager.__nestScope(node);
-
- if (this.scopeManager.__isNodejsScope()) {
- // Force strictness of GlobalScope to false when using node.js scope.
- this.currentScope().isStrict = false;
- this.scopeManager.__nestForceFunctionScope(node);
- }
-
- if (this.scopeManager.__isES6() && this.scopeManager.isModule()) {
- this.scopeManager.__nestModuleScope(node);
- }
-
- this.visitChildren(node);
- this.close(node);
- },
-
- Identifier: function (node) {
- this.currentScope().__referencing(node);
- },
-
- UpdateExpression: function (node) {
- if (isPattern(node.argument)) {
- this.currentScope().__referencing(node.argument, Reference.RW, null);
- } else {
- this.visitChildren(node);
- }
- },
-
- MemberExpression: function (node) {
- this.visit(node.object);
- if (node.computed) {
- this.visit(node.property);
- }
- },
-
- Property: function (node) {
- this.visitProperty(node);
- },
-
- MethodDefinition: function (node) {
- this.visitProperty(node);
- },
-
- BreakStatement: function () {},
-
- ContinueStatement: function () {},
-
- LabeledStatement: function (node) {
- this.visit(node.body);
- },
-
- ForStatement: function (node) {
- // Create ForStatement declaration.
- // NOTE: In ES6, ForStatement dynamically generates
- // per iteration environment. However, escope is
- // a static analyzer, we only generate one scope for ForStatement.
- if (node.init && node.init.type === Syntax.VariableDeclaration && node.init.kind !== 'var') {
- this.scopeManager.__nestScope(node);
- }
-
- this.visitChildren(node);
-
- this.close(node);
- },
-
- ClassExpression: function (node) {
- this.visitClass(node);
- },
-
- ClassDeclaration: function (node) {
- this.visitClass(node);
- },
-
- CallExpression: function (node) {
- // Check this is direct call to eval
- if (!this.scopeManager.__ignoreEval() && node.callee.type === Syntax.Identifier && node.callee.name === 'eval') {
- // NOTE: This should be `variableScope`. Since direct eval call always creates Lexical environment and
- // let / const should be enclosed into it. Only VariableDeclaration affects on the caller's environment.
- this.currentScope().variableScope.__detectEval();
- }
- this.visitChildren(node);
- },
-
- BlockStatement: function (node) {
- if (this.scopeManager.__isES6()) {
- this.scopeManager.__nestScope(node);
- }
-
- this.visitChildren(node);
-
- this.close(node);
- },
-
- ThisExpression: function () {
- this.currentScope().variableScope.__detectThis();
- },
-
- WithStatement: function (node) {
- this.visit(node.object);
- // Then nest scope for WithStatement.
- this.scopeManager.__nestScope(node);
-
- this.visit(node.body);
-
- this.close(node);
- },
-
- VariableDeclaration: function (node) {
- var variableTargetScope, i, iz, decl;
- variableTargetScope = (node.kind === 'var') ? this.currentScope().variableScope : this.currentScope();
- for (i = 0, iz = node.declarations.length; i < iz; ++i) {
- decl = node.declarations[i];
- this.visitVariableDeclaration(variableTargetScope, Variable.Variable, node, i);
- if (decl.init) {
- this.visit(decl.init);
- }
- }
- },
-
- // sec 13.11.8
- SwitchStatement: function (node) {
- var i, iz;
-
- this.visit(node.discriminant);
-
- if (this.scopeManager.__isES6()) {
- this.scopeManager.__nestScope(node);
- }
-
- for (i = 0, iz = node.cases.length; i < iz; ++i) {
- this.visit(node.cases[i]);
- }
-
- this.close(node);
- },
-
- FunctionDeclaration: function (node) {
- this.visitFunction(node);
- },
-
- FunctionExpression: function (node) {
- this.visitFunction(node);
- },
-
- ForOfStatement: function (node) {
- this.visitForIn(node);
- },
-
- ForInStatement: function (node) {
- this.visitForIn(node);
- },
-
- ArrowFunctionExpression: function (node) {
- this.visitFunction(node);
- },
-
- ImportDeclaration: function (node) {
- var importer;
-
- assert(this.scopeManager.__isES6() && this.scopeManager.isModule());
-
- importer = new Importer(node, this);
- importer.visit(node);
- },
-
- ExportDeclaration: function (node) {
- if (node.source) {
- return;
- }
- if (node.declaration) {
- this.visit(node.declaration);
- return;
- }
-
- this.visitChildren(node);
- },
-
- ExportSpecifier: function (node) {
- this.visit(node.id);
- }
- });
-
- /**
- * Main interface function. Takes an Esprima syntax tree and returns the
- * analyzed scopes.
- * @function analyze
- * @param {esprima.Tree} tree
- * @param {Object} providedOptions - Options that tailor the scope analysis
- * @param {boolean} [providedOptions.optimistic=false] - the optimistic flag
- * @param {boolean} [providedOptions.directive=false]- the directive flag
- * @param {boolean} [providedOptions.nodejsScope=false]- whether the whole
- * script is executed under node.js environment. When enabled, escope adds
- * a function scope immediately following the global scope.
- * @param {boolean} [providedOptions.ignoreEval=false]- whether to check 'eval()' calls
- * @param {string} [providedOptions.sourceType='script']- the source type of the script. one of 'script' and 'module'
- * @param {number} [providedOptions.ecmaVersion=5]- which ECMAScript version is considered
- * @return {ScopeManager}
- */
- function analyze(tree, providedOptions) {
- var scopeManager, referencer, options;
-
- options = updateDeeply(defaultOptions(), providedOptions);
-
- scopeManager = new ScopeManager(options);
-
- referencer = new Referencer(scopeManager);
- referencer.visit(tree);
-
- assert(scopeManager.__currentScope === null);
-
- return scopeManager;
- }
-
- /** @name module:escope.version */
- exports.version = require('./package.json').version;
- /** @name module:escope.Reference */
- exports.Reference = Reference;
- /** @name module:escope.Variable */
- exports.Variable = Variable;
- /** @name module:escope.Scope */
- exports.Scope = Scope;
- /** @name module:escope.ScopeManager */
- exports.ScopeManager = ScopeManager;
- /** @name module:escope.analyze */
- exports.analyze = analyze;
-}());
-/* vim: set sw=4 ts=4 et tw=80 : */
-
-},{"./package.json":124,"es6-map":20,"es6-weak-map":75,"esrecurse":121,"estraverse":127,"util":8,"util-extend":123}],20:[function(require,module,exports){
-'use strict';
-
-module.exports = require('./is-implemented')() ? Map : require('./polyfill');
-
-},{"./is-implemented":21,"./polyfill":74}],21:[function(require,module,exports){
-'use strict';
-
-module.exports = function () {
- var map, iterator, result;
- if (typeof Map !== 'function') return false;
- try {
- // WebKit doesn't support arguments and crashes
- map = new Map([['raz', 'one'], ['dwa', 'two'], ['trzy', 'three']]);
- } catch (e) {
- return false;
- }
- if (map.size !== 3) return false;
- if (typeof map.clear !== 'function') return false;
- if (typeof map.delete !== 'function') return false;
- if (typeof map.entries !== 'function') return false;
- if (typeof map.forEach !== 'function') return false;
- if (typeof map.get !== 'function') return false;
- if (typeof map.has !== 'function') return false;
- if (typeof map.keys !== 'function') return false;
- if (typeof map.set !== 'function') return false;
- if (typeof map.values !== 'function') return false;
-
- iterator = map.entries();
- result = iterator.next();
- if (result.done !== false) return false;
- if (!result.value) return false;
- if (result.value[0] !== 'raz') return false;
- if (result.value[1] !== 'one') return false;
- return true;
-};
-
-},{}],22:[function(require,module,exports){
-// Exports true if environment provides native `Map` implementation,
-// whatever that is.
-
-'use strict';
-
-module.exports = (function () {
- if (typeof Map === 'undefined') return false;
- return (Object.prototype.toString.call(Map.prototype) === '[object Map]');
-}());
-
-},{}],23:[function(require,module,exports){
-'use strict';
-
-module.exports = require('es5-ext/object/primitive-set')('key',
- 'value', 'key+value');
-
-},{"es5-ext/object/primitive-set":48}],24:[function(require,module,exports){
-'use strict';
-
-var setPrototypeOf = require('es5-ext/object/set-prototype-of')
- , d = require('d')
- , Iterator = require('es6-iterator')
- , toStringTagSymbol = require('es6-symbol').toStringTag
- , kinds = require('./iterator-kinds')
-
- , defineProperties = Object.defineProperties
- , unBind = Iterator.prototype._unBind
- , MapIterator;
-
-MapIterator = module.exports = function (map, kind) {
- if (!(this instanceof MapIterator)) return new MapIterator(map, kind);
- Iterator.call(this, map.__mapKeysData__, map);
- if (!kind || !kinds[kind]) kind = 'key+value';
- defineProperties(this, {
- __kind__: d('', kind),
- __values__: d('w', map.__mapValuesData__)
- });
-};
-if (setPrototypeOf) setPrototypeOf(MapIterator, Iterator);
-
-MapIterator.prototype = Object.create(Iterator.prototype, {
- constructor: d(MapIterator),
- _resolve: d(function (i) {
- if (this.__kind__ === 'value') return this.__values__[i];
- if (this.__kind__ === 'key') return this.__list__[i];
- return [this.__list__[i], this.__values__[i]];
- }),
- _unBind: d(function () {
- this.__values__ = null;
- unBind.call(this);
- }),
- toString: d(function () { return '[object Map Iterator]'; })
-});
-Object.defineProperty(MapIterator.prototype, toStringTagSymbol,
- d('c', 'Map Iterator'));
-
-},{"./iterator-kinds":23,"d":26,"es5-ext/object/set-prototype-of":49,"es6-iterator":61,"es6-symbol":70}],25:[function(require,module,exports){
-'use strict';
-
-var copy = require('es5-ext/object/copy')
- , map = require('es5-ext/object/map')
- , callable = require('es5-ext/object/valid-callable')
- , validValue = require('es5-ext/object/valid-value')
-
- , bind = Function.prototype.bind, defineProperty = Object.defineProperty
- , hasOwnProperty = Object.prototype.hasOwnProperty
- , define;
-
-define = function (name, desc, bindTo) {
- var value = validValue(desc) && callable(desc.value), dgs;
- dgs = copy(desc);
- delete dgs.writable;
- delete dgs.value;
- dgs.get = function () {
- if (hasOwnProperty.call(this, name)) return value;
- desc.value = bind.call(value, (bindTo == null) ? this : this[bindTo]);
- defineProperty(this, name, desc);
- return this[name];
- };
- return dgs;
-};
-
-module.exports = function (props/*, bindTo*/) {
- var bindTo = arguments[1];
- return map(props, function (desc, name) {
- return define(name, desc, bindTo);
- });
-};
-
-},{"es5-ext/object/copy":38,"es5-ext/object/map":46,"es5-ext/object/valid-callable":52,"es5-ext/object/valid-value":53}],26:[function(require,module,exports){
-'use strict';
-
-var assign = require('es5-ext/object/assign')
- , normalizeOpts = require('es5-ext/object/normalize-options')
- , isCallable = require('es5-ext/object/is-callable')
- , contains = require('es5-ext/string/#/contains')
-
- , d;
-
-d = module.exports = function (dscr, value/*, options*/) {
- var c, e, w, options, desc;
- if ((arguments.length < 2) || (typeof dscr !== 'string')) {
- options = value;
- value = dscr;
- dscr = null;
- } else {
- options = arguments[2];
- }
- if (dscr == null) {
- c = w = true;
- e = false;
- } else {
- c = contains.call(dscr, 'c');
- e = contains.call(dscr, 'e');
- w = contains.call(dscr, 'w');
- }
-
- desc = { value: value, configurable: c, enumerable: e, writable: w };
- return !options ? desc : assign(normalizeOpts(options), desc);
-};
-
-d.gs = function (dscr, get, set/*, options*/) {
- var c, e, options, desc;
- if (typeof dscr !== 'string') {
- options = set;
- set = get;
- get = dscr;
- dscr = null;
- } else {
- options = arguments[3];
- }
- if (get == null) {
- get = undefined;
- } else if (!isCallable(get)) {
- options = get;
- get = set = undefined;
- } else if (set == null) {
- set = undefined;
- } else if (!isCallable(set)) {
- options = set;
- set = undefined;
- }
- if (dscr == null) {
- c = true;
- e = false;
- } else {
- c = contains.call(dscr, 'c');
- e = contains.call(dscr, 'e');
- }
-
- desc = { get: get, set: set, configurable: c, enumerable: e };
- return !options ? desc : assign(normalizeOpts(options), desc);
-};
-
-},{"es5-ext/object/assign":35,"es5-ext/object/is-callable":41,"es5-ext/object/normalize-options":47,"es5-ext/string/#/contains":54}],27:[function(require,module,exports){
// Inspired by Google Closure:
// http://closure-library.googlecode.com/svn/docs/
// closure_goog_array_array.js.html#goog.array.clear
'use strict';
@@ -13459,11 +11684,11 @@
module.exports = function () {
value(this).length = 0;
return this;
};
-},{"../../object/valid-value":53}],28:[function(require,module,exports){
+},{"../../object/valid-value":46}],19:[function(require,module,exports){
'use strict';
var toPosInt = require('../../number/to-pos-integer')
, value = require('../../object/valid-value')
@@ -13490,36 +11715,45 @@
}
}
return -1;
};
-},{"../../number/to-pos-integer":33,"../../object/valid-value":53}],29:[function(require,module,exports){
+},{"../../number/to-pos-integer":25,"../../object/valid-value":46}],20:[function(require,module,exports){
'use strict';
+var toString = Object.prototype.toString
+
+ , id = toString.call((function () { return arguments; }()));
+
+module.exports = function (x) { return (toString.call(x) === id); };
+
+},{}],21:[function(require,module,exports){
+'use strict';
+
module.exports = require('./is-implemented')()
? Math.sign
: require('./shim');
-},{"./is-implemented":30,"./shim":31}],30:[function(require,module,exports){
+},{"./is-implemented":22,"./shim":23}],22:[function(require,module,exports){
'use strict';
module.exports = function () {
var sign = Math.sign;
if (typeof sign !== 'function') return false;
return ((sign(10) === 1) && (sign(-20) === -1));
};
-},{}],31:[function(require,module,exports){
+},{}],23:[function(require,module,exports){
'use strict';
module.exports = function (value) {
value = Number(value);
if (isNaN(value) || (value === 0)) return value;
return (value > 0) ? 1 : -1;
};
-},{}],32:[function(require,module,exports){
+},{}],24:[function(require,module,exports){
'use strict';
var sign = require('../math/sign')
, abs = Math.abs, floor = Math.floor;
@@ -13529,69 +11763,69 @@
value = Number(value);
if ((value === 0) || !isFinite(value)) return value;
return sign(value) * floor(abs(value));
};
-},{"../math/sign":29}],33:[function(require,module,exports){
+},{"../math/sign":21}],25:[function(require,module,exports){
'use strict';
var toInteger = require('./to-integer')
, max = Math.max;
module.exports = function (value) { return max(0, toInteger(value)); };
-},{"./to-integer":32}],34:[function(require,module,exports){
+},{"./to-integer":24}],26:[function(require,module,exports){
// Internal method, used by iteration functions.
// Calls a function for each key-value pair found in object
// Optionally takes compareFn to iterate object in specific order
'use strict';
-var isCallable = require('./is-callable')
- , callable = require('./valid-callable')
- , value = require('./valid-value')
+var callable = require('./valid-callable')
+ , value = require('./valid-value')
- , call = Function.prototype.call, keys = Object.keys
+ , bind = Function.prototype.bind, call = Function.prototype.call, keys = Object.keys
, propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
module.exports = function (method, defVal) {
return function (obj, cb/*, thisArg, compareFn*/) {
var list, thisArg = arguments[2], compareFn = arguments[3];
obj = Object(value(obj));
callable(cb);
list = keys(obj);
if (compareFn) {
- list.sort(isCallable(compareFn) ? compareFn.bind(obj) : undefined);
+ list.sort((typeof compareFn === 'function') ? bind.call(compareFn, obj) : undefined);
}
- return list[method](function (key, index) {
+ if (typeof method !== 'function') method = list[method];
+ return call.call(method, list, function (key, index) {
if (!propertyIsEnumerable.call(obj, key)) return defVal;
return call.call(cb, thisArg, obj[key], key, obj, index);
});
};
};
-},{"./is-callable":41,"./valid-callable":52,"./valid-value":53}],35:[function(require,module,exports){
+},{"./valid-callable":44,"./valid-value":46}],27:[function(require,module,exports){
'use strict';
module.exports = require('./is-implemented')()
? Object.assign
: require('./shim');
-},{"./is-implemented":36,"./shim":37}],36:[function(require,module,exports){
+},{"./is-implemented":28,"./shim":29}],28:[function(require,module,exports){
'use strict';
module.exports = function () {
var assign = Object.assign, obj;
if (typeof assign !== 'function') return false;
obj = { foo: 'raz' };
assign(obj, { bar: 'dwa' }, { trzy: 'trzy' });
return (obj.foo + obj.bar + obj.trzy) === 'razdwatrzy';
};
-},{}],37:[function(require,module,exports){
+},{}],29:[function(require,module,exports){
'use strict';
var keys = require('../keys')
, value = require('../valid-value')
@@ -13611,11 +11845,11 @@
}
if (error !== undefined) throw error;
return dest;
};
-},{"../keys":43,"../valid-value":53}],38:[function(require,module,exports){
+},{"../keys":35,"../valid-value":46}],30:[function(require,module,exports){
'use strict';
var assign = require('./assign')
, value = require('./valid-value');
@@ -13623,11 +11857,11 @@
var copy = Object(value(obj));
if (copy !== obj) return copy;
return assign({}, obj);
};
-},{"./assign":35,"./valid-value":53}],39:[function(require,module,exports){
+},{"./assign":27,"./valid-value":46}],31:[function(require,module,exports){
// Workaround for http://code.google.com/p/v8/issues/detail?id=2804
'use strict';
var create = Object.create, shim;
@@ -13661,58 +11895,58 @@
return function (prototype, props) {
return create((prototype === null) ? nullObject : prototype, props);
};
}());
-},{"./set-prototype-of/is-implemented":50,"./set-prototype-of/shim":51}],40:[function(require,module,exports){
+},{"./set-prototype-of/is-implemented":42,"./set-prototype-of/shim":43}],32:[function(require,module,exports){
'use strict';
module.exports = require('./_iterate')('forEach');
-},{"./_iterate":34}],41:[function(require,module,exports){
+},{"./_iterate":26}],33:[function(require,module,exports){
// Deprecated
'use strict';
module.exports = function (obj) { return typeof obj === 'function'; };
-},{}],42:[function(require,module,exports){
+},{}],34:[function(require,module,exports){
'use strict';
var map = { function: true, object: true };
module.exports = function (x) {
return ((x != null) && map[typeof x]) || false;
};
-},{}],43:[function(require,module,exports){
+},{}],35:[function(require,module,exports){
'use strict';
module.exports = require('./is-implemented')()
? Object.keys
: require('./shim');
-},{"./is-implemented":44,"./shim":45}],44:[function(require,module,exports){
+},{"./is-implemented":36,"./shim":37}],36:[function(require,module,exports){
'use strict';
module.exports = function () {
try {
Object.keys('primitive');
return true;
} catch (e) { return false; }
};
-},{}],45:[function(require,module,exports){
+},{}],37:[function(require,module,exports){
'use strict';
var keys = Object.keys;
module.exports = function (object) {
return keys(object == null ? object : Object(object));
};
-},{}],46:[function(require,module,exports){
+},{}],38:[function(require,module,exports){
'use strict';
var callable = require('./valid-callable')
, forEach = require('./for-each')
@@ -13725,11 +11959,11 @@
o[key] = call.call(cb, thisArg, value, key, obj, index);
});
return o;
};
-},{"./for-each":40,"./valid-callable":52}],47:[function(require,module,exports){
+},{"./for-each":32,"./valid-callable":44}],39:[function(require,module,exports){
'use strict';
var forEach = Array.prototype.forEach, create = Object.create;
var process = function (src, obj) {
@@ -13744,29 +11978,29 @@
process(Object(options), result);
});
return result;
};
-},{}],48:[function(require,module,exports){
+},{}],40:[function(require,module,exports){
'use strict';
var forEach = Array.prototype.forEach, create = Object.create;
module.exports = function (arg/*, …args*/) {
var set = create(null);
forEach.call(arguments, function (name) { set[name] = true; });
return set;
};
-},{}],49:[function(require,module,exports){
+},{}],41:[function(require,module,exports){
'use strict';
module.exports = require('./is-implemented')()
? Object.setPrototypeOf
: require('./shim');
-},{"./is-implemented":50,"./shim":51}],50:[function(require,module,exports){
+},{"./is-implemented":42,"./shim":43}],42:[function(require,module,exports){
'use strict';
var create = Object.create, getPrototypeOf = Object.getPrototypeOf
, x = {};
@@ -13775,11 +12009,11 @@
, customCreate = arguments[0] || create;
if (typeof setPrototypeOf !== 'function') return false;
return getPrototypeOf(setPrototypeOf(customCreate(null), x)) === x;
};
-},{}],51:[function(require,module,exports){
+},{}],43:[function(require,module,exports){
// Big thanks to @WebReflection for sorting this out
// https://gist.github.com/WebReflection/5593554
'use strict';
@@ -13850,53 +12084,63 @@
return false;
}())));
require('../create');
-},{"../create":39,"../is-object":42,"../valid-value":53}],52:[function(require,module,exports){
+},{"../create":31,"../is-object":34,"../valid-value":46}],44:[function(require,module,exports){
'use strict';
module.exports = function (fn) {
if (typeof fn !== 'function') throw new TypeError(fn + " is not a function");
return fn;
};
-},{}],53:[function(require,module,exports){
+},{}],45:[function(require,module,exports){
'use strict';
+var isObject = require('./is-object');
+
module.exports = function (value) {
+ if (!isObject(value)) throw new TypeError(value + " is not an Object");
+ return value;
+};
+
+},{"./is-object":34}],46:[function(require,module,exports){
+'use strict';
+
+module.exports = function (value) {
if (value == null) throw new TypeError("Cannot use null or undefined");
return value;
};
-},{}],54:[function(require,module,exports){
+},{}],47:[function(require,module,exports){
'use strict';
module.exports = require('./is-implemented')()
? String.prototype.contains
: require('./shim');
-},{"./is-implemented":55,"./shim":56}],55:[function(require,module,exports){
+},{"./is-implemented":48,"./shim":49}],48:[function(require,module,exports){
'use strict';
var str = 'razdwatrzy';
module.exports = function () {
if (typeof str.contains !== 'function') return false;
return ((str.contains('dwa') === true) && (str.contains('foo') === false));
};
-},{}],56:[function(require,module,exports){
+},{}],49:[function(require,module,exports){
'use strict';
var indexOf = String.prototype.indexOf;
module.exports = function (searchString/*, position*/) {
return indexOf.call(this, searchString, arguments[1]) > -1;
};
-},{}],57:[function(require,module,exports){
+},{}],50:[function(require,module,exports){
'use strict';
var toString = Object.prototype.toString
, id = toString.call('');
@@ -13904,13 +12148,26 @@
module.exports = function (x) {
return (typeof x === 'string') || (x && (typeof x === 'object') &&
((x instanceof String) || (toString.call(x) === id))) || false;
};
-},{}],58:[function(require,module,exports){
+},{}],51:[function(require,module,exports){
'use strict';
+var generated = Object.create(null)
+
+ , random = Math.random;
+
+module.exports = function () {
+ var str;
+ do { str = random().toString(36).slice(2); } while (generated[str]);
+ return str;
+};
+
+},{}],52:[function(require,module,exports){
+'use strict';
+
var setPrototypeOf = require('es5-ext/object/set-prototype-of')
, contains = require('es5-ext/string/#/contains')
, d = require('d')
, Iterator = require('./')
@@ -13936,29 +12193,31 @@
return i;
}),
toString: d(function () { return '[object Array Iterator]'; })
});
-},{"./":61,"d":26,"es5-ext/object/set-prototype-of":49,"es5-ext/string/#/contains":54}],59:[function(require,module,exports){
+},{"./":55,"d":7,"es5-ext/object/set-prototype-of":41,"es5-ext/string/#/contains":47}],53:[function(require,module,exports){
'use strict';
-var callable = require('es5-ext/object/valid-callable')
- , isString = require('es5-ext/string/is-string')
- , get = require('./get')
+var isArguments = require('es5-ext/function/is-arguments')
+ , callable = require('es5-ext/object/valid-callable')
+ , isString = require('es5-ext/string/is-string')
+ , get = require('./get')
- , isArray = Array.isArray, call = Function.prototype.call;
+ , isArray = Array.isArray, call = Function.prototype.call
+ , some = Array.prototype.some;
module.exports = function (iterable, cb/*, thisArg*/) {
var mode, thisArg = arguments[2], result, doBreak, broken, i, l, char, code;
- if (isArray(iterable)) mode = 'array';
+ if (isArray(iterable) || isArguments(iterable)) mode = 'array';
else if (isString(iterable)) mode = 'string';
else iterable = get(iterable);
callable(cb);
doBreak = function () { broken = true; };
if (mode === 'array') {
- iterable.some(function (value) {
+ some.call(iterable, function (value) {
call.call(cb, thisArg, value, doBreak);
if (broken) return true;
});
return;
}
@@ -13982,26 +12241,28 @@
if (broken) return;
result = iterable.next();
}
};
-},{"./get":60,"es5-ext/object/valid-callable":52,"es5-ext/string/is-string":57}],60:[function(require,module,exports){
+},{"./get":54,"es5-ext/function/is-arguments":20,"es5-ext/object/valid-callable":44,"es5-ext/string/is-string":50}],54:[function(require,module,exports){
'use strict';
-var isString = require('es5-ext/string/is-string')
+var isArguments = require('es5-ext/function/is-arguments')
+ , isString = require('es5-ext/string/is-string')
, ArrayIterator = require('./array')
, StringIterator = require('./string')
, iterable = require('./valid-iterable')
, iteratorSymbol = require('es6-symbol').iterator;
module.exports = function (obj) {
if (typeof iterable(obj)[iteratorSymbol] === 'function') return obj[iteratorSymbol]();
+ if (isArguments(obj)) return new ArrayIterator(obj);
if (isString(obj)) return new StringIterator(obj);
return new ArrayIterator(obj);
};
-},{"./array":58,"./string":68,"./valid-iterable":69,"es5-ext/string/is-string":57,"es6-symbol":63}],61:[function(require,module,exports){
+},{"./array":52,"./string":57,"./valid-iterable":58,"es5-ext/function/is-arguments":20,"es5-ext/string/is-string":50,"es6-symbol":65}],55:[function(require,module,exports){
'use strict';
var clear = require('es5-ext/array/#/clear')
, assign = require('es5-ext/object/assign')
, callable = require('es5-ext/object/valid-callable')
@@ -14089,147 +12350,28 @@
defineProperty(Iterator.prototype, Symbol.iterator, d(function () {
return this;
}));
defineProperty(Iterator.prototype, Symbol.toStringTag, d('', 'Iterator'));
-},{"d":26,"d/auto-bind":25,"es5-ext/array/#/clear":27,"es5-ext/object/assign":35,"es5-ext/object/valid-callable":52,"es5-ext/object/valid-value":53,"es6-symbol":63}],62:[function(require,module,exports){
+},{"d":7,"d/auto-bind":6,"es5-ext/array/#/clear":18,"es5-ext/object/assign":27,"es5-ext/object/valid-callable":44,"es5-ext/object/valid-value":46,"es6-symbol":65}],56:[function(require,module,exports){
'use strict';
-var isString = require('es5-ext/string/is-string')
+var isArguments = require('es5-ext/function/is-arguments')
+ , isString = require('es5-ext/string/is-string')
, iteratorSymbol = require('es6-symbol').iterator
, isArray = Array.isArray;
module.exports = function (value) {
if (value == null) return false;
if (isArray(value)) return true;
if (isString(value)) return true;
+ if (isArguments(value)) return true;
return (typeof value[iteratorSymbol] === 'function');
};
-},{"es5-ext/string/is-string":57,"es6-symbol":63}],63:[function(require,module,exports){
-'use strict';
-
-module.exports = require('./is-implemented')() ? Symbol : require('./polyfill');
-
-},{"./is-implemented":64,"./polyfill":66}],64:[function(require,module,exports){
-'use strict';
-
-module.exports = function () {
- var symbol;
- if (typeof Symbol !== 'function') return false;
- symbol = Symbol('test symbol');
- try { String(symbol); } catch (e) { return false; }
- if (typeof Symbol.iterator === 'symbol') return true;
-
- // Return 'true' for polyfills
- if (typeof Symbol.isConcatSpreadable !== 'object') return false;
- if (typeof Symbol.iterator !== 'object') return false;
- if (typeof Symbol.toPrimitive !== 'object') return false;
- if (typeof Symbol.toStringTag !== 'object') return false;
- if (typeof Symbol.unscopables !== 'object') return false;
-
- return true;
-};
-
-},{}],65:[function(require,module,exports){
-'use strict';
-
-module.exports = function (x) {
- return (x && ((typeof x === 'symbol') || (x['@@toStringTag'] === 'Symbol'))) || false;
-};
-
-},{}],66:[function(require,module,exports){
-'use strict';
-
-var d = require('d')
- , validateSymbol = require('./validate-symbol')
-
- , create = Object.create, defineProperties = Object.defineProperties
- , defineProperty = Object.defineProperty, objPrototype = Object.prototype
- , Symbol, HiddenSymbol, globalSymbols = create(null);
-
-var generateName = (function () {
- var created = create(null);
- return function (desc) {
- var postfix = 0, name;
- while (created[desc + (postfix || '')]) ++postfix;
- desc += (postfix || '');
- created[desc] = true;
- name = '@@' + desc;
- defineProperty(objPrototype, name, d.gs(null, function (value) {
- defineProperty(this, name, d(value));
- }));
- return name;
- };
-}());
-
-HiddenSymbol = function Symbol(description) {
- if (this instanceof HiddenSymbol) throw new TypeError('TypeError: Symbol is not a constructor');
- return Symbol(description);
-};
-module.exports = Symbol = function Symbol(description) {
- var symbol;
- if (this instanceof Symbol) throw new TypeError('TypeError: Symbol is not a constructor');
- symbol = create(HiddenSymbol.prototype);
- description = (description === undefined ? '' : String(description));
- return defineProperties(symbol, {
- __description__: d('', description),
- __name__: d('', generateName(description))
- });
-};
-defineProperties(Symbol, {
- for: d(function (key) {
- if (globalSymbols[key]) return globalSymbols[key];
- return (globalSymbols[key] = Symbol(String(key)));
- }),
- keyFor: d(function (s) {
- var key;
- validateSymbol(s);
- for (key in globalSymbols) if (globalSymbols[key] === s) return key;
- }),
- hasInstance: d('', Symbol('hasInstance')),
- isConcatSpreadable: d('', Symbol('isConcatSpreadable')),
- iterator: d('', Symbol('iterator')),
- match: d('', Symbol('match')),
- replace: d('', Symbol('replace')),
- search: d('', Symbol('search')),
- species: d('', Symbol('species')),
- split: d('', Symbol('split')),
- toPrimitive: d('', Symbol('toPrimitive')),
- toStringTag: d('', Symbol('toStringTag')),
- unscopables: d('', Symbol('unscopables'))
-});
-defineProperties(HiddenSymbol.prototype, {
- constructor: d(Symbol),
- toString: d('', function () { return this.__name__; })
-});
-
-defineProperties(Symbol.prototype, {
- toString: d(function () { return 'Symbol (' + validateSymbol(this).__description__ + ')'; }),
- valueOf: d(function () { return validateSymbol(this); })
-});
-defineProperty(Symbol.prototype, Symbol.toPrimitive, d('',
- function () { return validateSymbol(this); }));
-defineProperty(Symbol.prototype, Symbol.toStringTag, d('c', 'Symbol'));
-
-defineProperty(HiddenSymbol.prototype, Symbol.toPrimitive,
- d('c', Symbol.prototype[Symbol.toPrimitive]));
-defineProperty(HiddenSymbol.prototype, Symbol.toStringTag,
- d('c', Symbol.prototype[Symbol.toStringTag]));
-
-},{"./validate-symbol":67,"d":26}],67:[function(require,module,exports){
-'use strict';
-
-var isSymbol = require('./is-symbol');
-
-module.exports = function (value) {
- if (!isSymbol(value)) throw new TypeError(value + " is not a symbol");
- return value;
-};
-
-},{"./is-symbol":65}],68:[function(require,module,exports){
+},{"es5-ext/function/is-arguments":20,"es5-ext/string/is-string":50,"es6-symbol":65}],57:[function(require,module,exports){
// Thanks @mathiasbynens
// http://mathiasbynens.be/notes/javascript-unicode#iterating-over-symbols
'use strict';
@@ -14264,233 +12406,117 @@
return char;
}),
toString: d(function () { return '[object String Iterator]'; })
});
-},{"./":61,"d":26,"es5-ext/object/set-prototype-of":49}],69:[function(require,module,exports){
+},{"./":55,"d":7,"es5-ext/object/set-prototype-of":41}],58:[function(require,module,exports){
'use strict';
var isIterable = require('./is-iterable');
module.exports = function (value) {
if (!isIterable(value)) throw new TypeError(value + " is not iterable");
return value;
};
-},{"./is-iterable":62}],70:[function(require,module,exports){
-arguments[4][63][0].apply(exports,arguments)
-},{"./is-implemented":71,"./polyfill":72,"dup":63}],71:[function(require,module,exports){
+},{"./is-iterable":56}],59:[function(require,module,exports){
'use strict';
+module.exports = require('./is-implemented')() ? Map : require('./polyfill');
+
+},{"./is-implemented":60,"./polyfill":64}],60:[function(require,module,exports){
+'use strict';
+
module.exports = function () {
- var symbol;
- if (typeof Symbol !== 'function') return false;
- symbol = Symbol('test symbol');
- try { String(symbol); } catch (e) { return false; }
- if (typeof Symbol.iterator === 'symbol') return true;
+ var map, iterator, result;
+ if (typeof Map !== 'function') return false;
+ try {
+ // WebKit doesn't support arguments and crashes
+ map = new Map([['raz', 'one'], ['dwa', 'two'], ['trzy', 'three']]);
+ } catch (e) {
+ return false;
+ }
+ if (String(map) !== '[object Map]') return false;
+ if (map.size !== 3) return false;
+ if (typeof map.clear !== 'function') return false;
+ if (typeof map.delete !== 'function') return false;
+ if (typeof map.entries !== 'function') return false;
+ if (typeof map.forEach !== 'function') return false;
+ if (typeof map.get !== 'function') return false;
+ if (typeof map.has !== 'function') return false;
+ if (typeof map.keys !== 'function') return false;
+ if (typeof map.set !== 'function') return false;
+ if (typeof map.values !== 'function') return false;
- // Return 'true' for polyfills
- if (typeof Symbol.isConcatSpreadable !== 'object') return false;
- if (typeof Symbol.isRegExp !== 'object') return false;
- if (typeof Symbol.iterator !== 'object') return false;
- if (typeof Symbol.toPrimitive !== 'object') return false;
- if (typeof Symbol.toStringTag !== 'object') return false;
- if (typeof Symbol.unscopables !== 'object') return false;
+ iterator = map.entries();
+ result = iterator.next();
+ if (result.done !== false) return false;
+ if (!result.value) return false;
+ if (result.value[0] !== 'raz') return false;
+ if (result.value[1] !== 'one') return false;
return true;
};
-},{}],72:[function(require,module,exports){
+},{}],61:[function(require,module,exports){
+// Exports true if environment provides native `Map` implementation,
+// whatever that is.
+
'use strict';
-var d = require('d')
-
- , create = Object.create, defineProperties = Object.defineProperties
- , generateName, Symbol;
-
-generateName = (function () {
- var created = create(null);
- return function (desc) {
- var postfix = 0;
- while (created[desc + (postfix || '')]) ++postfix;
- desc += (postfix || '');
- created[desc] = true;
- return '@@' + desc;
- };
+module.exports = (function () {
+ if (typeof Map === 'undefined') return false;
+ return (Object.prototype.toString.call(new Map()) === '[object Map]');
}());
-module.exports = Symbol = function (description) {
- var symbol;
- if (this instanceof Symbol) {
- throw new TypeError('TypeError: Symbol is not a constructor');
- }
- symbol = create(Symbol.prototype);
- description = (description === undefined ? '' : String(description));
- return defineProperties(symbol, {
- __description__: d('', description),
- __name__: d('', generateName(description))
- });
-};
+},{}],62:[function(require,module,exports){
+'use strict';
-Object.defineProperties(Symbol, {
- create: d('', Symbol('create')),
- hasInstance: d('', Symbol('hasInstance')),
- isConcatSpreadable: d('', Symbol('isConcatSpreadable')),
- isRegExp: d('', Symbol('isRegExp')),
- iterator: d('', Symbol('iterator')),
- toPrimitive: d('', Symbol('toPrimitive')),
- toStringTag: d('', Symbol('toStringTag')),
- unscopables: d('', Symbol('unscopables'))
-});
+module.exports = require('es5-ext/object/primitive-set')('key',
+ 'value', 'key+value');
-defineProperties(Symbol.prototype, {
- properToString: d(function () {
- return 'Symbol (' + this.__description__ + ')';
- }),
- toString: d('', function () { return this.__name__; })
-});
-Object.defineProperty(Symbol.prototype, Symbol.toPrimitive, d('',
- function (hint) {
- throw new TypeError("Conversion of symbol objects is not allowed");
- }));
-Object.defineProperty(Symbol.prototype, Symbol.toStringTag, d('c', 'Symbol'));
-
-},{"d":26}],73:[function(require,module,exports){
+},{"es5-ext/object/primitive-set":40}],63:[function(require,module,exports){
'use strict';
-var d = require('d')
- , callable = require('es5-ext/object/valid-callable')
+var setPrototypeOf = require('es5-ext/object/set-prototype-of')
+ , d = require('d')
+ , Iterator = require('es6-iterator')
+ , toStringTagSymbol = require('es6-symbol').toStringTag
+ , kinds = require('./iterator-kinds')
- , apply = Function.prototype.apply, call = Function.prototype.call
- , create = Object.create, defineProperty = Object.defineProperty
, defineProperties = Object.defineProperties
- , hasOwnProperty = Object.prototype.hasOwnProperty
- , descriptor = { configurable: true, enumerable: false, writable: true }
+ , unBind = Iterator.prototype._unBind
+ , MapIterator;
- , on, once, off, emit, methods, descriptors, base;
-
-on = function (type, listener) {
- var data;
-
- callable(listener);
-
- if (!hasOwnProperty.call(this, '__ee__')) {
- data = descriptor.value = create(null);
- defineProperty(this, '__ee__', descriptor);
- descriptor.value = null;
- } else {
- data = this.__ee__;
- }
- if (!data[type]) data[type] = listener;
- else if (typeof data[type] === 'object') data[type].push(listener);
- else data[type] = [data[type], listener];
-
- return this;
-};
-
-once = function (type, listener) {
- var once, self;
-
- callable(listener);
- self = this;
- on.call(this, type, once = function () {
- off.call(self, type, once);
- apply.call(listener, this, arguments);
+MapIterator = module.exports = function (map, kind) {
+ if (!(this instanceof MapIterator)) return new MapIterator(map, kind);
+ Iterator.call(this, map.__mapKeysData__, map);
+ if (!kind || !kinds[kind]) kind = 'key+value';
+ defineProperties(this, {
+ __kind__: d('', kind),
+ __values__: d('w', map.__mapValuesData__)
});
-
- once.__eeOnceListener__ = listener;
- return this;
};
+if (setPrototypeOf) setPrototypeOf(MapIterator, Iterator);
-off = function (type, listener) {
- var data, listeners, candidate, i;
+MapIterator.prototype = Object.create(Iterator.prototype, {
+ constructor: d(MapIterator),
+ _resolve: d(function (i) {
+ if (this.__kind__ === 'value') return this.__values__[i];
+ if (this.__kind__ === 'key') return this.__list__[i];
+ return [this.__list__[i], this.__values__[i]];
+ }),
+ _unBind: d(function () {
+ this.__values__ = null;
+ unBind.call(this);
+ }),
+ toString: d(function () { return '[object Map Iterator]'; })
+});
+Object.defineProperty(MapIterator.prototype, toStringTagSymbol,
+ d('c', 'Map Iterator'));
- callable(listener);
-
- if (!hasOwnProperty.call(this, '__ee__')) return this;
- data = this.__ee__;
- if (!data[type]) return this;
- listeners = data[type];
-
- if (typeof listeners === 'object') {
- for (i = 0; (candidate = listeners[i]); ++i) {
- if ((candidate === listener) ||
- (candidate.__eeOnceListener__ === listener)) {
- if (listeners.length === 2) data[type] = listeners[i ? 0 : 1];
- else listeners.splice(i, 1);
- }
- }
- } else {
- if ((listeners === listener) ||
- (listeners.__eeOnceListener__ === listener)) {
- delete data[type];
- }
- }
-
- return this;
-};
-
-emit = function (type) {
- var i, l, listener, listeners, args;
-
- if (!hasOwnProperty.call(this, '__ee__')) return;
- listeners = this.__ee__[type];
- if (!listeners) return;
-
- if (typeof listeners === 'object') {
- l = arguments.length;
- args = new Array(l - 1);
- for (i = 1; i < l; ++i) args[i - 1] = arguments[i];
-
- listeners = listeners.slice();
- for (i = 0; (listener = listeners[i]); ++i) {
- apply.call(listener, this, args);
- }
- } else {
- switch (arguments.length) {
- case 1:
- call.call(listeners, this);
- break;
- case 2:
- call.call(listeners, this, arguments[1]);
- break;
- case 3:
- call.call(listeners, this, arguments[1], arguments[2]);
- break;
- default:
- l = arguments.length;
- args = new Array(l - 1);
- for (i = 1; i < l; ++i) {
- args[i - 1] = arguments[i];
- }
- apply.call(listeners, this, args);
- }
- }
-};
-
-methods = {
- on: on,
- once: once,
- off: off,
- emit: emit
-};
-
-descriptors = {
- on: d(on),
- once: d(once),
- off: d(off),
- emit: d(emit)
-};
-
-base = defineProperties({}, descriptors);
-
-module.exports = exports = function (o) {
- return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
-};
-exports.methods = methods;
-
-},{"d":26,"es5-ext/object/valid-callable":52}],74:[function(require,module,exports){
+},{"./iterator-kinds":62,"d":7,"es5-ext/object/set-prototype-of":41,"es6-iterator":55,"es6-symbol":65}],64:[function(require,module,exports){
'use strict';
var clear = require('es5-ext/array/#/clear')
, eIndexOf = require('es5-ext/array/#/e-index-of')
, setPrototypeOf = require('es5-ext/object/set-prototype-of')
@@ -14502,32 +12528,36 @@
, iterator = require('es6-iterator/valid-iterable')
, forOf = require('es6-iterator/for-of')
, Iterator = require('./lib/iterator')
, isNative = require('./is-native-implemented')
- , call = Function.prototype.call, defineProperties = Object.defineProperties
+ , call = Function.prototype.call
+ , defineProperties = Object.defineProperties, getPrototypeOf = Object.getPrototypeOf
, MapPoly;
module.exports = MapPoly = function (/*iterable*/) {
- var iterable = arguments[0], keys, values;
- if (!(this instanceof MapPoly)) return new MapPoly(iterable);
- if (this.__mapKeysData__ !== undefined) {
- throw new TypeError(this + " cannot be reinitialized");
+ var iterable = arguments[0], keys, values, self;
+ if (!(this instanceof MapPoly)) throw new TypeError('Constructor requires \'new\'');
+ if (isNative && setPrototypeOf && (Map !== MapPoly)) {
+ self = setPrototypeOf(new Map(), getPrototypeOf(this));
+ } else {
+ self = this;
}
if (iterable != null) iterator(iterable);
- defineProperties(this, {
+ defineProperties(self, {
__mapKeysData__: d('c', keys = []),
__mapValuesData__: d('c', values = [])
});
- if (!iterable) return;
+ if (!iterable) return self;
forOf(iterable, function (value) {
var key = validValue(value)[0];
value = value[1];
if (eIndexOf.call(keys, key) !== -1) return;
keys.push(key);
values.push(value);
- }, this);
+ }, self);
+ return self;
};
if (isNative) {
if (setPrototypeOf) setPrototypeOf(MapPoly, Map);
MapPoly.prototype = Object.create(Map.prototype, {
@@ -14588,190 +12618,223 @@
Object.defineProperty(MapPoly.prototype, Symbol.iterator, d(function () {
return this.entries();
}));
Object.defineProperty(MapPoly.prototype, Symbol.toStringTag, d('c', 'Map'));
-},{"./is-native-implemented":22,"./lib/iterator":24,"d":26,"es5-ext/array/#/clear":27,"es5-ext/array/#/e-index-of":28,"es5-ext/object/set-prototype-of":49,"es5-ext/object/valid-callable":52,"es5-ext/object/valid-value":53,"es6-iterator/for-of":59,"es6-iterator/valid-iterable":69,"es6-symbol":70,"event-emitter":73}],75:[function(require,module,exports){
+},{"./is-native-implemented":61,"./lib/iterator":63,"d":7,"es5-ext/array/#/clear":18,"es5-ext/array/#/e-index-of":19,"es5-ext/object/set-prototype-of":41,"es5-ext/object/valid-callable":44,"es5-ext/object/valid-value":46,"es6-iterator/for-of":53,"es6-iterator/valid-iterable":58,"es6-symbol":65,"event-emitter":95}],65:[function(require,module,exports){
'use strict';
-module.exports = require('./is-implemented')() ?
- WeakMap : require('./polyfill');
+module.exports = require('./is-implemented')() ? Symbol : require('./polyfill');
-},{"./is-implemented":76,"./polyfill":120}],76:[function(require,module,exports){
+},{"./is-implemented":66,"./polyfill":68}],66:[function(require,module,exports){
'use strict';
module.exports = function () {
- var map;
- if (typeof WeakMap !== 'function') return false;
- map = new WeakMap();
- if (typeof map.set !== 'function') return false;
- if (map.set({}, 1) !== map) return false;
- if (typeof map.clear !== 'function') return false;
- if (typeof map.delete !== 'function') return false;
- if (typeof map.has !== 'function') return false;
+ var symbol;
+ if (typeof Symbol !== 'function') return false;
+ symbol = Symbol('test symbol');
+ try { String(symbol); } catch (e) { return false; }
+ if (typeof Symbol.iterator === 'symbol') return true;
+ // Return 'true' for polyfills
+ if (typeof Symbol.isConcatSpreadable !== 'object') return false;
+ if (typeof Symbol.iterator !== 'object') return false;
+ if (typeof Symbol.toPrimitive !== 'object') return false;
+ if (typeof Symbol.toStringTag !== 'object') return false;
+ if (typeof Symbol.unscopables !== 'object') return false;
+
return true;
};
-},{}],77:[function(require,module,exports){
-// Exports true if environment provides native `WeakMap` implementation,
-// whatever that is.
+},{}],67:[function(require,module,exports){
+'use strict';
+module.exports = function (x) {
+ return (x && ((typeof x === 'symbol') || (x['@@toStringTag'] === 'Symbol'))) || false;
+};
+
+},{}],68:[function(require,module,exports){
'use strict';
-module.exports = (function () {
- if (typeof WeakMap === 'undefined') return false;
- return (Object.prototype.toString.call(WeakMap.prototype) ===
- '[object WeakMap]');
+var d = require('d')
+ , validateSymbol = require('./validate-symbol')
+
+ , create = Object.create, defineProperties = Object.defineProperties
+ , defineProperty = Object.defineProperty, objPrototype = Object.prototype
+ , NativeSymbol, SymbolPolyfill, HiddenSymbol, globalSymbols = create(null);
+
+if (typeof Symbol === 'function') NativeSymbol = Symbol;
+
+var generateName = (function () {
+ var created = create(null);
+ return function (desc) {
+ var postfix = 0, name, ie11BugWorkaround;
+ while (created[desc + (postfix || '')]) ++postfix;
+ desc += (postfix || '');
+ created[desc] = true;
+ name = '@@' + desc;
+ defineProperty(objPrototype, name, d.gs(null, function (value) {
+ // For IE11 issue see:
+ // https://connect.microsoft.com/IE/feedbackdetail/view/1928508/
+ // ie11-broken-getters-on-dom-objects
+ // https://github.com/medikoo/es6-symbol/issues/12
+ if (ie11BugWorkaround) return;
+ ie11BugWorkaround = true;
+ defineProperty(this, name, d(value));
+ ie11BugWorkaround = false;
+ }));
+ return name;
+ };
}());
-},{}],78:[function(require,module,exports){
-arguments[4][25][0].apply(exports,arguments)
-},{"dup":25,"es5-ext/object/copy":85,"es5-ext/object/map":93,"es5-ext/object/valid-callable":98,"es5-ext/object/valid-value":100}],79:[function(require,module,exports){
-arguments[4][26][0].apply(exports,arguments)
-},{"dup":26,"es5-ext/object/assign":82,"es5-ext/object/is-callable":88,"es5-ext/object/normalize-options":94,"es5-ext/string/#/contains":101}],80:[function(require,module,exports){
-arguments[4][27][0].apply(exports,arguments)
-},{"../../object/valid-value":100,"dup":27}],81:[function(require,module,exports){
-arguments[4][34][0].apply(exports,arguments)
-},{"./is-callable":88,"./valid-callable":98,"./valid-value":100,"dup":34}],82:[function(require,module,exports){
-arguments[4][35][0].apply(exports,arguments)
-},{"./is-implemented":83,"./shim":84,"dup":35}],83:[function(require,module,exports){
-arguments[4][36][0].apply(exports,arguments)
-},{"dup":36}],84:[function(require,module,exports){
-arguments[4][37][0].apply(exports,arguments)
-},{"../keys":90,"../valid-value":100,"dup":37}],85:[function(require,module,exports){
-arguments[4][38][0].apply(exports,arguments)
-},{"./assign":82,"./valid-value":100,"dup":38}],86:[function(require,module,exports){
-arguments[4][39][0].apply(exports,arguments)
-},{"./set-prototype-of/is-implemented":96,"./set-prototype-of/shim":97,"dup":39}],87:[function(require,module,exports){
-arguments[4][40][0].apply(exports,arguments)
-},{"./_iterate":81,"dup":40}],88:[function(require,module,exports){
-arguments[4][41][0].apply(exports,arguments)
-},{"dup":41}],89:[function(require,module,exports){
-arguments[4][42][0].apply(exports,arguments)
-},{"dup":42}],90:[function(require,module,exports){
-arguments[4][43][0].apply(exports,arguments)
-},{"./is-implemented":91,"./shim":92,"dup":43}],91:[function(require,module,exports){
-arguments[4][44][0].apply(exports,arguments)
-},{"dup":44}],92:[function(require,module,exports){
-arguments[4][45][0].apply(exports,arguments)
-},{"dup":45}],93:[function(require,module,exports){
-arguments[4][46][0].apply(exports,arguments)
-},{"./for-each":87,"./valid-callable":98,"dup":46}],94:[function(require,module,exports){
-arguments[4][47][0].apply(exports,arguments)
-},{"dup":47}],95:[function(require,module,exports){
-arguments[4][49][0].apply(exports,arguments)
-},{"./is-implemented":96,"./shim":97,"dup":49}],96:[function(require,module,exports){
-arguments[4][50][0].apply(exports,arguments)
-},{"dup":50}],97:[function(require,module,exports){
-arguments[4][51][0].apply(exports,arguments)
-},{"../create":86,"../is-object":89,"../valid-value":100,"dup":51}],98:[function(require,module,exports){
-arguments[4][52][0].apply(exports,arguments)
-},{"dup":52}],99:[function(require,module,exports){
+HiddenSymbol = function Symbol(description) {
+ if (this instanceof HiddenSymbol) throw new TypeError('TypeError: Symbol is not a constructor');
+ return SymbolPolyfill(description);
+};
+module.exports = SymbolPolyfill = function Symbol(description) {
+ var symbol;
+ if (this instanceof Symbol) throw new TypeError('TypeError: Symbol is not a constructor');
+ symbol = create(HiddenSymbol.prototype);
+ description = (description === undefined ? '' : String(description));
+ return defineProperties(symbol, {
+ __description__: d('', description),
+ __name__: d('', generateName(description))
+ });
+};
+defineProperties(SymbolPolyfill, {
+ for: d(function (key) {
+ if (globalSymbols[key]) return globalSymbols[key];
+ return (globalSymbols[key] = SymbolPolyfill(String(key)));
+ }),
+ keyFor: d(function (s) {
+ var key;
+ validateSymbol(s);
+ for (key in globalSymbols) if (globalSymbols[key] === s) return key;
+ }),
+ hasInstance: d('', (NativeSymbol && NativeSymbol.hasInstance) || SymbolPolyfill('hasInstance')),
+ isConcatSpreadable: d('', (NativeSymbol && NativeSymbol.isConcatSpreadable) ||
+ SymbolPolyfill('isConcatSpreadable')),
+ iterator: d('', (NativeSymbol && NativeSymbol.iterator) || SymbolPolyfill('iterator')),
+ match: d('', (NativeSymbol && NativeSymbol.match) || SymbolPolyfill('match')),
+ replace: d('', (NativeSymbol && NativeSymbol.replace) || SymbolPolyfill('replace')),
+ search: d('', (NativeSymbol && NativeSymbol.search) || SymbolPolyfill('search')),
+ species: d('', (NativeSymbol && NativeSymbol.species) || SymbolPolyfill('species')),
+ split: d('', (NativeSymbol && NativeSymbol.split) || SymbolPolyfill('split')),
+ toPrimitive: d('', (NativeSymbol && NativeSymbol.toPrimitive) || SymbolPolyfill('toPrimitive')),
+ toStringTag: d('', (NativeSymbol && NativeSymbol.toStringTag) || SymbolPolyfill('toStringTag')),
+ unscopables: d('', (NativeSymbol && NativeSymbol.unscopables) || SymbolPolyfill('unscopables'))
+});
+defineProperties(HiddenSymbol.prototype, {
+ constructor: d(SymbolPolyfill),
+ toString: d('', function () { return this.__name__; })
+});
+
+defineProperties(SymbolPolyfill.prototype, {
+ toString: d(function () { return 'Symbol (' + validateSymbol(this).__description__ + ')'; }),
+ valueOf: d(function () { return validateSymbol(this); })
+});
+defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toPrimitive, d('',
+ function () { return validateSymbol(this); }));
+defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, d('c', 'Symbol'));
+
+defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toPrimitive,
+ d('c', SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive]));
+defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toStringTag,
+ d('c', SymbolPolyfill.prototype[SymbolPolyfill.toStringTag]));
+
+},{"./validate-symbol":69,"d":7}],69:[function(require,module,exports){
'use strict';
-var isObject = require('./is-object');
+var isSymbol = require('./is-symbol');
module.exports = function (value) {
- if (!isObject(value)) throw new TypeError(value + " is not an Object");
+ if (!isSymbol(value)) throw new TypeError(value + " is not a symbol");
return value;
};
-},{"./is-object":89}],100:[function(require,module,exports){
-arguments[4][53][0].apply(exports,arguments)
-},{"dup":53}],101:[function(require,module,exports){
-arguments[4][54][0].apply(exports,arguments)
-},{"./is-implemented":102,"./shim":103,"dup":54}],102:[function(require,module,exports){
-arguments[4][55][0].apply(exports,arguments)
-},{"dup":55}],103:[function(require,module,exports){
-arguments[4][56][0].apply(exports,arguments)
-},{"dup":56}],104:[function(require,module,exports){
-arguments[4][57][0].apply(exports,arguments)
-},{"dup":57}],105:[function(require,module,exports){
-arguments[4][58][0].apply(exports,arguments)
-},{"./":108,"d":79,"dup":58,"es5-ext/object/set-prototype-of":95,"es5-ext/string/#/contains":101}],106:[function(require,module,exports){
-arguments[4][59][0].apply(exports,arguments)
-},{"./get":107,"dup":59,"es5-ext/object/valid-callable":98,"es5-ext/string/is-string":104}],107:[function(require,module,exports){
-arguments[4][60][0].apply(exports,arguments)
-},{"./array":105,"./string":115,"./valid-iterable":116,"dup":60,"es5-ext/string/is-string":104,"es6-symbol":110}],108:[function(require,module,exports){
-arguments[4][61][0].apply(exports,arguments)
-},{"d":79,"d/auto-bind":78,"dup":61,"es5-ext/array/#/clear":80,"es5-ext/object/assign":82,"es5-ext/object/valid-callable":98,"es5-ext/object/valid-value":100,"es6-symbol":110}],109:[function(require,module,exports){
-arguments[4][62][0].apply(exports,arguments)
-},{"dup":62,"es5-ext/string/is-string":104,"es6-symbol":110}],110:[function(require,module,exports){
-arguments[4][63][0].apply(exports,arguments)
-},{"./is-implemented":111,"./polyfill":113,"dup":63}],111:[function(require,module,exports){
-arguments[4][64][0].apply(exports,arguments)
-},{"dup":64}],112:[function(require,module,exports){
-arguments[4][65][0].apply(exports,arguments)
-},{"dup":65}],113:[function(require,module,exports){
-arguments[4][66][0].apply(exports,arguments)
-},{"./validate-symbol":114,"d":79,"dup":66}],114:[function(require,module,exports){
-arguments[4][67][0].apply(exports,arguments)
-},{"./is-symbol":112,"dup":67}],115:[function(require,module,exports){
-arguments[4][68][0].apply(exports,arguments)
-},{"./":108,"d":79,"dup":68,"es5-ext/object/set-prototype-of":95}],116:[function(require,module,exports){
-arguments[4][69][0].apply(exports,arguments)
-},{"./is-iterable":109,"dup":69}],117:[function(require,module,exports){
-arguments[4][63][0].apply(exports,arguments)
-},{"./is-implemented":118,"./polyfill":119,"dup":63}],118:[function(require,module,exports){
-arguments[4][71][0].apply(exports,arguments)
-},{"dup":71}],119:[function(require,module,exports){
-arguments[4][72][0].apply(exports,arguments)
-},{"d":79,"dup":72}],120:[function(require,module,exports){
+},{"./is-symbol":67}],70:[function(require,module,exports){
'use strict';
+module.exports = require('./is-implemented')() ? WeakMap : require('./polyfill');
+
+},{"./is-implemented":71,"./polyfill":73}],71:[function(require,module,exports){
+'use strict';
+
+module.exports = function () {
+ var weakMap, x;
+ if (typeof WeakMap !== 'function') return false;
+ try {
+ // WebKit doesn't support arguments and crashes
+ weakMap = new WeakMap([[x = {}, 'one'], [{}, 'two'], [{}, 'three']]);
+ } catch (e) {
+ return false;
+ }
+ if (String(weakMap) !== '[object WeakMap]') return false;
+ if (typeof weakMap.set !== 'function') return false;
+ if (weakMap.set({}, 1) !== weakMap) return false;
+ if (typeof weakMap.delete !== 'function') return false;
+ if (typeof weakMap.has !== 'function') return false;
+ if (weakMap.get(x) !== 'one') return false;
+
+ return true;
+};
+
+},{}],72:[function(require,module,exports){
+// Exports true if environment provides native `WeakMap` implementation, whatever that is.
+
+'use strict';
+
+module.exports = (function () {
+ if (typeof WeakMap !== 'function') return false;
+ return (Object.prototype.toString.call(new WeakMap()) === '[object WeakMap]');
+}());
+
+},{}],73:[function(require,module,exports){
+'use strict';
+
var setPrototypeOf = require('es5-ext/object/set-prototype-of')
, object = require('es5-ext/object/valid-object')
, value = require('es5-ext/object/valid-value')
+ , randomUniq = require('es5-ext/string/random-uniq')
, d = require('d')
, getIterator = require('es6-iterator/get')
, forOf = require('es6-iterator/for-of')
, toStringTagSymbol = require('es6-symbol').toStringTag
, isNative = require('./is-native-implemented')
- , isArray = Array.isArray, defineProperty = Object.defineProperty, random = Math.random
- , hasOwnProperty = Object.prototype.hasOwnProperty
- , genId, WeakMapPoly;
+ , isArray = Array.isArray, defineProperty = Object.defineProperty
+ , hasOwnProperty = Object.prototype.hasOwnProperty, getPrototypeOf = Object.getPrototypeOf
+ , WeakMapPoly;
-genId = (function () {
- var generated = Object.create(null);
- return function () {
- var id;
- do { id = random().toString(36).slice(2); } while (generated[id]);
- generated[id] = true;
- return id;
- };
-}());
-
module.exports = WeakMapPoly = function (/*iterable*/) {
- var iterable = arguments[0];
- if (!(this instanceof WeakMapPoly)) return new WeakMapPoly(iterable);
- if (this.__weakMapData__ !== undefined) {
- throw new TypeError(this + " cannot be reinitialized");
+ var iterable = arguments[0], self;
+ if (!(this instanceof WeakMapPoly)) throw new TypeError('Constructor requires \'new\'');
+ if (isNative && setPrototypeOf && (WeakMap !== WeakMapPoly)) {
+ self = setPrototypeOf(new WeakMap(), getPrototypeOf(this));
+ } else {
+ self = this;
}
if (iterable != null) {
if (!isArray(iterable)) iterable = getIterator(iterable);
}
- defineProperty(this, '__weakMapData__', d('c', '$weakMap$' + genId()));
- if (!iterable) return;
+ defineProperty(self, '__weakMapData__', d('c', '$weakMap$' + randomUniq()));
+ if (!iterable) return self;
forOf(iterable, function (val) {
value(val);
- this.set(val[0], val[1]);
- }, this);
+ self.set(val[0], val[1]);
+ });
+ return self;
};
if (isNative) {
if (setPrototypeOf) setPrototypeOf(WeakMapPoly, WeakMap);
WeakMapPoly.prototype = Object.create(WeakMap.prototype, {
constructor: d(WeakMapPoly)
});
}
Object.defineProperties(WeakMapPoly.prototype, {
- clear: d(function () {
- defineProperty(this, '__weakMapData__', d('c', '$weakMap$' + genId()));
- }),
delete: d(function (key) {
if (hasOwnProperty.call(object(key), this.__weakMapData__)) {
delete key[this.__weakMapData__];
return true;
}
@@ -14791,12 +12854,2513 @@
}),
toString: d(function () { return '[object WeakMap]'; })
});
defineProperty(WeakMapPoly.prototype, toStringTagSymbol, d('c', 'WeakMap'));
-},{"./is-native-implemented":77,"d":79,"es5-ext/object/set-prototype-of":95,"es5-ext/object/valid-object":99,"es5-ext/object/valid-value":100,"es6-iterator/for-of":106,"es6-iterator/get":107,"es6-symbol":117}],121:[function(require,module,exports){
+},{"./is-native-implemented":72,"d":7,"es5-ext/object/set-prototype-of":41,"es5-ext/object/valid-object":45,"es5-ext/object/valid-value":46,"es5-ext/string/random-uniq":51,"es6-iterator/for-of":53,"es6-iterator/get":54,"es6-symbol":65}],74:[function(require,module,exports){
+'use strict';
+
+var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
+
+module.exports = function (str) {
+ if (typeof str !== 'string') {
+ throw new TypeError('Expected a string');
+ }
+
+ return str.replace(matchOperatorsRe, '\\$&');
+};
+
+},{}],75:[function(require,module,exports){
+"use strict";
+
+var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
+
+var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
+
+var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
/*
+ Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+var Variable = _interopRequire(require("./variable"));
+
+/**
+ * @class Definition
+ */
+
+var Definition = function Definition(type, name, node, parent, index, kind) {
+ _classCallCheck(this, Definition);
+
+ /**
+ * @member {String} Definition#type - type of the occurrence (e.g. "Parameter", "Variable", ...).
+ */
+ this.type = type;
+ /**
+ * @member {esprima.Identifier} Definition#name - the identifier AST node of the occurrence.
+ */
+ this.name = name;
+ /**
+ * @member {esprima.Node} Definition#node - the enclosing node of the identifier.
+ */
+ this.node = node;
+ /**
+ * @member {esprima.Node?} Definition#parent - the enclosing statement node of the identifier.
+ */
+ this.parent = parent;
+ /**
+ * @member {Number?} Definition#index - the index in the declaration statement.
+ */
+ this.index = index;
+ /**
+ * @member {String?} Definition#kind - the kind of the declaration statement.
+ */
+ this.kind = kind;
+};
+
+exports["default"] = Definition;
+
+/**
+ * @class ParameterDefinition
+ */
+
+var ParameterDefinition = (function (_Definition) {
+ function ParameterDefinition(name, node, index, rest) {
+ _classCallCheck(this, ParameterDefinition);
+
+ _get(Object.getPrototypeOf(ParameterDefinition.prototype), "constructor", this).call(this, Variable.Parameter, name, node, null, index, null);
+ /**
+ * Whether the parameter definition is a part of a rest parameter.
+ * @member {boolean} ParameterDefinition#rest
+ */
+ this.rest = rest;
+ }
+
+ _inherits(ParameterDefinition, _Definition);
+
+ return ParameterDefinition;
+})(Definition);
+
+exports.ParameterDefinition = ParameterDefinition;
+
+/* vim: set sw=4 ts=4 et tw=80 : */
+exports.Definition = Definition;
+
+
+},{"./variable":82}],76:[function(require,module,exports){
+"use strict";
+
+var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
+
+/**
+ * Main interface function. Takes an Esprima syntax tree and returns the
+ * analyzed scopes.
+ * @function analyze
+ * @param {esprima.Tree} tree
+ * @param {Object} providedOptions - Options that tailor the scope analysis
+ * @param {boolean} [providedOptions.optimistic=false] - the optimistic flag
+ * @param {boolean} [providedOptions.directive=false]- the directive flag
+ * @param {boolean} [providedOptions.ignoreEval=false]- whether to check 'eval()' calls
+ * @param {boolean} [providedOptions.nodejsScope=false]- whether the whole
+ * script is executed under node.js environment. When enabled, escope adds
+ * a function scope immediately following the global scope.
+ * @param {string} [providedOptions.sourceType='script']- the source type of the script. one of 'script' and 'module'
+ * @param {number} [providedOptions.ecmaVersion=5]- which ECMAScript version is considered
+ * @return {ScopeManager}
+ */
+exports.analyze = analyze;
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+/*
+ Copyright (C) 2012-2014 Yusuke Suzuki <utatane.tea@gmail.com>
+ Copyright (C) 2013 Alex Seville <hi@alexanderseville.com>
+ Copyright (C) 2014 Thiago de Arruda <tpadilha84@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * Escope (<a href="http://github.com/estools/escope">escope</a>) is an <a
+ * href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript</a>
+ * scope analyzer extracted from the <a
+ * href="http://github.com/estools/esmangle">esmangle project</a/>.
+ * <p>
+ * <em>escope</em> finds lexical scopes in a source program, i.e. areas of that
+ * program where different occurrences of the same identifier refer to the same
+ * variable. With each scope the contained variables are collected, and each
+ * identifier reference in code is linked to its corresponding variable (if
+ * possible).
+ * <p>
+ * <em>escope</em> works on a syntax tree of the parsed source code which has
+ * to adhere to the <a
+ * href="https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API">
+ * Mozilla Parser API</a>. E.g. <a href="http://esprima.org">esprima</a> is a parser
+ * that produces such syntax trees.
+ * <p>
+ * The main interface is the {@link analyze} function.
+ * @module escope
+ */
+
+/*jslint bitwise:true */
+
+var assert = _interopRequire(require("assert"));
+
+var ScopeManager = _interopRequire(require("./scope-manager"));
+
+var Referencer = _interopRequire(require("./referencer"));
+
+var Reference = _interopRequire(require("./reference"));
+
+var Variable = _interopRequire(require("./variable"));
+
+var Scope = _interopRequire(require("./scope"));
+
+var version = require("../package.json").version;
+
+function defaultOptions() {
+ return {
+ optimistic: false,
+ directive: false,
+ nodejsScope: false,
+ sourceType: "script", // one of ['script', 'module']
+ ecmaVersion: 5
+ };
+}
+
+function updateDeeply(target, override) {
+ var key, val;
+
+ function isHashObject(target) {
+ return typeof target === "object" && target instanceof Object && !(target instanceof RegExp);
+ }
+
+ for (key in override) {
+ if (override.hasOwnProperty(key)) {
+ val = override[key];
+ if (isHashObject(val)) {
+ if (isHashObject(target[key])) {
+ updateDeeply(target[key], val);
+ } else {
+ target[key] = updateDeeply({}, val);
+ }
+ } else {
+ target[key] = val;
+ }
+ }
+ }
+ return target;
+}
+function analyze(tree, providedOptions) {
+ var scopeManager, referencer, options;
+
+ options = updateDeeply(defaultOptions(), providedOptions);
+
+ scopeManager = new ScopeManager(options);
+
+ referencer = new Referencer(scopeManager);
+ referencer.visit(tree);
+
+ assert(scopeManager.__currentScope === null, "currentScope should be null.");
+
+ return scopeManager;
+}
+
+exports.version = version;
+
+/* vim: set sw=4 ts=4 et tw=80 : */
+exports.Reference = Reference;
+exports.Variable = Variable;
+exports.Scope = Scope;
+exports.ScopeManager = ScopeManager;
+
+/** @name module:escope.version */
+
+/** @name module:escope.Reference */
+
+/** @name module:escope.Variable */
+
+/** @name module:escope.Scope */
+
+/** @name module:escope.ScopeManager */
+
+
+},{"../package.json":83,"./reference":78,"./referencer":79,"./scope":81,"./scope-manager":80,"./variable":82,"assert":5}],77:[function(require,module,exports){
+"use strict";
+
+var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
+
+var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
+
+var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+/*
+ Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+var Syntax = require("estraverse").Syntax;
+
+var esrecurse = _interopRequire(require("esrecurse"));
+
+function getLast(xs) {
+ return xs[xs.length - 1] || null;
+}
+
+var PatternVisitor = (function (_esrecurse$Visitor) {
+ function PatternVisitor(rootPattern, callback) {
+ _classCallCheck(this, PatternVisitor);
+
+ _get(Object.getPrototypeOf(PatternVisitor.prototype), "constructor", this).call(this);
+ this.rootPattern = rootPattern;
+ this.callback = callback;
+ this.assignments = [];
+ this.rightHandNodes = [];
+ this.restElements = [];
+ }
+
+ _inherits(PatternVisitor, _esrecurse$Visitor);
+
+ _createClass(PatternVisitor, {
+ Identifier: {
+ value: function Identifier(pattern) {
+ var lastRestElement = getLast(this.restElements);
+ this.callback(pattern, {
+ topLevel: pattern === this.rootPattern,
+ rest: lastRestElement != null && lastRestElement.argument === pattern,
+ assignments: this.assignments
+ });
+ }
+ },
+ Property: {
+ value: function Property(property) {
+ // Computed property's key is a right hand node.
+ if (property.computed) {
+ this.rightHandNodes.push(property.key);
+ }
+
+ // If it's shorthand, its key is same as its value.
+ // If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern).
+ // If it's not shorthand, the name of new variable is its value's.
+ this.visit(property.value);
+ }
+ },
+ ArrayPattern: {
+ value: function ArrayPattern(pattern) {
+ var i, iz, element;
+ for (i = 0, iz = pattern.elements.length; i < iz; ++i) {
+ element = pattern.elements[i];
+ this.visit(element);
+ }
+ }
+ },
+ AssignmentPattern: {
+ value: function AssignmentPattern(pattern) {
+ this.assignments.push(pattern);
+ this.visit(pattern.left);
+ this.rightHandNodes.push(pattern.right);
+ this.assignments.pop();
+ }
+ },
+ RestElement: {
+ value: function RestElement(pattern) {
+ this.restElements.push(pattern);
+ this.visit(pattern.argument);
+ this.restElements.pop();
+ }
+ },
+ MemberExpression: {
+ value: function MemberExpression(node) {
+ // Computed property's key is a right hand node.
+ if (node.computed) {
+ this.rightHandNodes.push(node.property);
+ }
+ // the object is only read, write to its property.
+ this.rightHandNodes.push(node.object);
+ }
+ },
+ SpreadElement: {
+
+ //
+ // ForInStatement.left and AssignmentExpression.left are LeftHandSideExpression.
+ // By spec, LeftHandSideExpression is Pattern or MemberExpression.
+ // (see also: https://github.com/estree/estree/pull/20#issuecomment-74584758)
+ // But espree 2.0 and esprima 2.0 parse to ArrayExpression, ObjectExpression, etc...
+ //
+
+ value: function SpreadElement(node) {
+ this.visit(node.argument);
+ }
+ },
+ ArrayExpression: {
+ value: function ArrayExpression(node) {
+ node.elements.forEach(this.visit, this);
+ }
+ },
+ AssignmentExpression: {
+ value: function AssignmentExpression(node) {
+ this.assignments.push(node);
+ this.visit(node.left);
+ this.rightHandNodes.push(node.right);
+ this.assignments.pop();
+ }
+ },
+ CallExpression: {
+ value: function CallExpression(node) {
+ var _this = this;
+
+ // arguments are right hand nodes.
+ node.arguments.forEach(function (a) {
+ _this.rightHandNodes.push(a);
+ });
+ this.visit(node.callee);
+ }
+ }
+ }, {
+ isPattern: {
+ value: function isPattern(node) {
+ var nodeType = node.type;
+ return nodeType === Syntax.Identifier || nodeType === Syntax.ObjectPattern || nodeType === Syntax.ArrayPattern || nodeType === Syntax.SpreadElement || nodeType === Syntax.RestElement || nodeType === Syntax.AssignmentPattern;
+ }
+ }
+ });
+
+ return PatternVisitor;
+})(esrecurse.Visitor);
+
+module.exports = PatternVisitor;
+
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+
+},{"esrecurse":84,"estraverse":89}],78:[function(require,module,exports){
+"use strict";
+
+var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+/*
+ Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+var READ = 1;
+var WRITE = 2;
+var RW = READ | WRITE;
+
+/**
+ * A Reference represents a single occurrence of an identifier in code.
+ * @class Reference
+ */
+
+var Reference = (function () {
+ function Reference(ident, scope, flag, writeExpr, maybeImplicitGlobal, partial, init) {
+ _classCallCheck(this, Reference);
+
+ /**
+ * Identifier syntax node.
+ * @member {esprima#Identifier} Reference#identifier
+ */
+ this.identifier = ident;
+ /**
+ * Reference to the enclosing Scope.
+ * @member {Scope} Reference#from
+ */
+ this.from = scope;
+ /**
+ * Whether the reference comes from a dynamic scope (such as 'eval',
+ * 'with', etc.), and may be trapped by dynamic scopes.
+ * @member {boolean} Reference#tainted
+ */
+ this.tainted = false;
+ /**
+ * The variable this reference is resolved with.
+ * @member {Variable} Reference#resolved
+ */
+ this.resolved = null;
+ /**
+ * The read-write mode of the reference. (Value is one of {@link
+ * Reference.READ}, {@link Reference.RW}, {@link Reference.WRITE}).
+ * @member {number} Reference#flag
+ * @private
+ */
+ this.flag = flag;
+ if (this.isWrite()) {
+ /**
+ * If reference is writeable, this is the tree being written to it.
+ * @member {esprima#Node} Reference#writeExpr
+ */
+ this.writeExpr = writeExpr;
+ /**
+ * Whether the Reference might refer to a partial value of writeExpr.
+ * @member {boolean} Reference#partial
+ */
+ this.partial = partial;
+ /**
+ * Whether the Reference is to write of initialization.
+ * @member {boolean} Reference#init
+ */
+ this.init = init;
+ }
+ this.__maybeImplicitGlobal = maybeImplicitGlobal;
+ }
+
+ _createClass(Reference, {
+ isStatic: {
+
+ /**
+ * Whether the reference is static.
+ * @method Reference#isStatic
+ * @return {boolean}
+ */
+
+ value: function isStatic() {
+ return !this.tainted && this.resolved && this.resolved.scope.isStatic();
+ }
+ },
+ isWrite: {
+
+ /**
+ * Whether the reference is writeable.
+ * @method Reference#isWrite
+ * @return {boolean}
+ */
+
+ value: function isWrite() {
+ return !!(this.flag & Reference.WRITE);
+ }
+ },
+ isRead: {
+
+ /**
+ * Whether the reference is readable.
+ * @method Reference#isRead
+ * @return {boolean}
+ */
+
+ value: function isRead() {
+ return !!(this.flag & Reference.READ);
+ }
+ },
+ isReadOnly: {
+
+ /**
+ * Whether the reference is read-only.
+ * @method Reference#isReadOnly
+ * @return {boolean}
+ */
+
+ value: function isReadOnly() {
+ return this.flag === Reference.READ;
+ }
+ },
+ isWriteOnly: {
+
+ /**
+ * Whether the reference is write-only.
+ * @method Reference#isWriteOnly
+ * @return {boolean}
+ */
+
+ value: function isWriteOnly() {
+ return this.flag === Reference.WRITE;
+ }
+ },
+ isReadWrite: {
+
+ /**
+ * Whether the reference is read-write.
+ * @method Reference#isReadWrite
+ * @return {boolean}
+ */
+
+ value: function isReadWrite() {
+ return this.flag === Reference.RW;
+ }
+ }
+ });
+
+ return Reference;
+})();
+
+module.exports = Reference;
+
+/**
+ * @constant Reference.READ
+ * @private
+ */
+Reference.READ = READ;
+/**
+ * @constant Reference.WRITE
+ * @private
+ */
+Reference.WRITE = WRITE;
+/**
+ * @constant Reference.RW
+ * @private
+ */
+Reference.RW = RW;
+
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+
+},{}],79:[function(require,module,exports){
+"use strict";
+
+var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
+
+var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
+
+var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+/*
+ Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+var Syntax = require("estraverse").Syntax;
+
+var esrecurse = _interopRequire(require("esrecurse"));
+
+var Reference = _interopRequire(require("./reference"));
+
+var Variable = _interopRequire(require("./variable"));
+
+var PatternVisitor = _interopRequire(require("./pattern-visitor"));
+
+var _definition = require("./definition");
+
+var ParameterDefinition = _definition.ParameterDefinition;
+var Definition = _definition.Definition;
+
+var assert = _interopRequire(require("assert"));
+
+function traverseIdentifierInPattern(rootPattern, referencer, callback) {
+ // Call the callback at left hand identifier nodes, and Collect right hand nodes.
+ var visitor = new PatternVisitor(rootPattern, callback);
+ visitor.visit(rootPattern);
+
+ // Process the right hand nodes recursively.
+ if (referencer != null) {
+ visitor.rightHandNodes.forEach(referencer.visit, referencer);
+ }
+}
+
+// Importing ImportDeclaration.
+// http://people.mozilla.org/~jorendorff/es6-draft.html#sec-moduledeclarationinstantiation
+// https://github.com/estree/estree/blob/master/es6.md#importdeclaration
+// FIXME: Now, we don't create module environment, because the context is
+// implementation dependent.
+
+var Importer = (function (_esrecurse$Visitor) {
+ function Importer(declaration, referencer) {
+ _classCallCheck(this, Importer);
+
+ _get(Object.getPrototypeOf(Importer.prototype), "constructor", this).call(this);
+ this.declaration = declaration;
+ this.referencer = referencer;
+ }
+
+ _inherits(Importer, _esrecurse$Visitor);
+
+ _createClass(Importer, {
+ visitImport: {
+ value: function visitImport(id, specifier) {
+ var _this = this;
+
+ this.referencer.visitPattern(id, function (pattern) {
+ _this.referencer.currentScope().__define(pattern, new Definition(Variable.ImportBinding, pattern, specifier, _this.declaration, null, null));
+ });
+ }
+ },
+ ImportNamespaceSpecifier: {
+ value: function ImportNamespaceSpecifier(node) {
+ var local = node.local || node.id;
+ if (local) {
+ this.visitImport(local, node);
+ }
+ }
+ },
+ ImportDefaultSpecifier: {
+ value: function ImportDefaultSpecifier(node) {
+ var local = node.local || node.id;
+ this.visitImport(local, node);
+ }
+ },
+ ImportSpecifier: {
+ value: function ImportSpecifier(node) {
+ var local = node.local || node.id;
+ if (node.name) {
+ this.visitImport(node.name, node);
+ } else {
+ this.visitImport(local, node);
+ }
+ }
+ }
+ });
+
+ return Importer;
+})(esrecurse.Visitor);
+
+// Referencing variables and creating bindings.
+
+var Referencer = (function (_esrecurse$Visitor2) {
+ function Referencer(scopeManager) {
+ _classCallCheck(this, Referencer);
+
+ _get(Object.getPrototypeOf(Referencer.prototype), "constructor", this).call(this);
+ this.scopeManager = scopeManager;
+ this.parent = null;
+ this.isInnerMethodDefinition = false;
+ }
+
+ _inherits(Referencer, _esrecurse$Visitor2);
+
+ _createClass(Referencer, {
+ currentScope: {
+ value: function currentScope() {
+ return this.scopeManager.__currentScope;
+ }
+ },
+ close: {
+ value: function close(node) {
+ while (this.currentScope() && node === this.currentScope().block) {
+ this.scopeManager.__currentScope = this.currentScope().__close(this.scopeManager);
+ }
+ }
+ },
+ pushInnerMethodDefinition: {
+ value: function pushInnerMethodDefinition(isInnerMethodDefinition) {
+ var previous = this.isInnerMethodDefinition;
+ this.isInnerMethodDefinition = isInnerMethodDefinition;
+ return previous;
+ }
+ },
+ popInnerMethodDefinition: {
+ value: function popInnerMethodDefinition(isInnerMethodDefinition) {
+ this.isInnerMethodDefinition = isInnerMethodDefinition;
+ }
+ },
+ materializeTDZScope: {
+ value: function materializeTDZScope(node, iterationNode) {
+ // http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-forin-div-ofexpressionevaluation-abstract-operation
+ // TDZ scope hides the declaration's names.
+ this.scopeManager.__nestTDZScope(node, iterationNode);
+ this.visitVariableDeclaration(this.currentScope(), Variable.TDZ, iterationNode.left, 0, true);
+ }
+ },
+ materializeIterationScope: {
+ value: function materializeIterationScope(node) {
+ var _this = this;
+
+ // Generate iteration scope for upper ForIn/ForOf Statements.
+ var letOrConstDecl;
+ this.scopeManager.__nestForScope(node);
+ letOrConstDecl = node.left;
+ this.visitVariableDeclaration(this.currentScope(), Variable.Variable, letOrConstDecl, 0);
+ this.visitPattern(letOrConstDecl.declarations[0].id, function (pattern) {
+ _this.currentScope().__referencing(pattern, Reference.WRITE, node.right, null, true, true);
+ });
+ }
+ },
+ referencingDefaultValue: {
+ value: function referencingDefaultValue(pattern, assignments, maybeImplicitGlobal, init) {
+ var scope = this.currentScope();
+ assignments.forEach(function (assignment) {
+ scope.__referencing(pattern, Reference.WRITE, assignment.right, maybeImplicitGlobal, pattern !== assignment.left, init);
+ });
+ }
+ },
+ visitPattern: {
+ value: function visitPattern(node, options, callback) {
+ if (typeof options === "function") {
+ callback = options;
+ options = { processRightHandNodes: false };
+ }
+ traverseIdentifierInPattern(node, options.processRightHandNodes ? this : null, callback);
+ }
+ },
+ visitFunction: {
+ value: function visitFunction(node) {
+ var _this = this;
+
+ var i, iz;
+ // FunctionDeclaration name is defined in upper scope
+ // NOTE: Not referring variableScope. It is intended.
+ // Since
+ // in ES5, FunctionDeclaration should be in FunctionBody.
+ // in ES6, FunctionDeclaration should be block scoped.
+ if (node.type === Syntax.FunctionDeclaration) {
+ // id is defined in upper scope
+ this.currentScope().__define(node.id, new Definition(Variable.FunctionName, node.id, node, null, null, null));
+ }
+
+ // FunctionExpression with name creates its special scope;
+ // FunctionExpressionNameScope.
+ if (node.type === Syntax.FunctionExpression && node.id) {
+ this.scopeManager.__nestFunctionExpressionNameScope(node);
+ }
+
+ // Consider this function is in the MethodDefinition.
+ this.scopeManager.__nestFunctionScope(node, this.isInnerMethodDefinition);
+
+ // Process parameter declarations.
+ for (i = 0, iz = node.params.length; i < iz; ++i) {
+ this.visitPattern(node.params[i], { processRightHandNodes: true }, function (pattern, info) {
+ _this.currentScope().__define(pattern, new ParameterDefinition(pattern, node, i, info.rest));
+
+ _this.referencingDefaultValue(pattern, info.assignments, null, true);
+ });
+ }
+
+ // if there's a rest argument, add that
+ if (node.rest) {
+ this.visitPattern({
+ type: "RestElement",
+ argument: node.rest
+ }, function (pattern) {
+ _this.currentScope().__define(pattern, new ParameterDefinition(pattern, node, node.params.length, true));
+ });
+ }
+
+ // Skip BlockStatement to prevent creating BlockStatement scope.
+ if (node.body.type === Syntax.BlockStatement) {
+ this.visitChildren(node.body);
+ } else {
+ this.visit(node.body);
+ }
+
+ this.close(node);
+ }
+ },
+ visitClass: {
+ value: function visitClass(node) {
+ if (node.type === Syntax.ClassDeclaration) {
+ this.currentScope().__define(node.id, new Definition(Variable.ClassName, node.id, node, null, null, null));
+ }
+
+ // FIXME: Maybe consider TDZ.
+ this.visit(node.superClass);
+
+ this.scopeManager.__nestClassScope(node);
+
+ if (node.id) {
+ this.currentScope().__define(node.id, new Definition(Variable.ClassName, node.id, node));
+ }
+ this.visit(node.body);
+
+ this.close(node);
+ }
+ },
+ visitProperty: {
+ value: function visitProperty(node) {
+ var previous, isMethodDefinition;
+ if (node.computed) {
+ this.visit(node.key);
+ }
+
+ isMethodDefinition = node.type === Syntax.MethodDefinition;
+ if (isMethodDefinition) {
+ previous = this.pushInnerMethodDefinition(true);
+ }
+ this.visit(node.value);
+ if (isMethodDefinition) {
+ this.popInnerMethodDefinition(previous);
+ }
+ }
+ },
+ visitForIn: {
+ value: function visitForIn(node) {
+ var _this = this;
+
+ if (node.left.type === Syntax.VariableDeclaration && node.left.kind !== "var") {
+ this.materializeTDZScope(node.right, node);
+ this.visit(node.right);
+ this.close(node.right);
+
+ this.materializeIterationScope(node);
+ this.visit(node.body);
+ this.close(node);
+ } else {
+ if (node.left.type === Syntax.VariableDeclaration) {
+ this.visit(node.left);
+ this.visitPattern(node.left.declarations[0].id, function (pattern) {
+ _this.currentScope().__referencing(pattern, Reference.WRITE, node.right, null, true, true);
+ });
+ } else {
+ this.visitPattern(node.left, { processRightHandNodes: true }, function (pattern, info) {
+ var maybeImplicitGlobal = null;
+ if (!_this.currentScope().isStrict) {
+ maybeImplicitGlobal = {
+ pattern: pattern,
+ node: node
+ };
+ }
+ _this.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
+ _this.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, true, false);
+ });
+ }
+ this.visit(node.right);
+ this.visit(node.body);
+ }
+ }
+ },
+ visitVariableDeclaration: {
+ value: function visitVariableDeclaration(variableTargetScope, type, node, index, fromTDZ) {
+ var _this = this;
+
+ // If this was called to initialize a TDZ scope, this needs to make definitions, but doesn't make references.
+ var decl, init;
+
+ decl = node.declarations[index];
+ init = decl.init;
+ this.visitPattern(decl.id, { processRightHandNodes: !fromTDZ }, function (pattern, info) {
+ variableTargetScope.__define(pattern, new Definition(type, pattern, decl, node, index, node.kind));
+
+ if (!fromTDZ) {
+ _this.referencingDefaultValue(pattern, info.assignments, null, true);
+ }
+ if (init) {
+ _this.currentScope().__referencing(pattern, Reference.WRITE, init, null, !info.topLevel, true);
+ }
+ });
+ }
+ },
+ AssignmentExpression: {
+ value: function AssignmentExpression(node) {
+ var _this = this;
+
+ if (PatternVisitor.isPattern(node.left)) {
+ if (node.operator === "=") {
+ this.visitPattern(node.left, { processRightHandNodes: true }, function (pattern, info) {
+ var maybeImplicitGlobal = null;
+ if (!_this.currentScope().isStrict) {
+ maybeImplicitGlobal = {
+ pattern: pattern,
+ node: node
+ };
+ }
+ _this.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
+ _this.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, !info.topLevel, false);
+ });
+ } else {
+ this.currentScope().__referencing(node.left, Reference.RW, node.right);
+ }
+ } else {
+ this.visit(node.left);
+ }
+ this.visit(node.right);
+ }
+ },
+ CatchClause: {
+ value: function CatchClause(node) {
+ var _this = this;
+
+ this.scopeManager.__nestCatchScope(node);
+
+ this.visitPattern(node.param, { processRightHandNodes: true }, function (pattern, info) {
+ _this.currentScope().__define(pattern, new Definition(Variable.CatchClause, node.param, node, null, null, null));
+ _this.referencingDefaultValue(pattern, info.assignments, null, true);
+ });
+ this.visit(node.body);
+
+ this.close(node);
+ }
+ },
+ Program: {
+ value: function Program(node) {
+ this.scopeManager.__nestGlobalScope(node);
+
+ if (this.scopeManager.__isNodejsScope()) {
+ // Force strictness of GlobalScope to false when using node.js scope.
+ this.currentScope().isStrict = false;
+ this.scopeManager.__nestFunctionScope(node, false);
+ }
+
+ if (this.scopeManager.__isES6() && this.scopeManager.isModule()) {
+ this.scopeManager.__nestModuleScope(node);
+ }
+
+ this.visitChildren(node);
+ this.close(node);
+ }
+ },
+ Identifier: {
+ value: function Identifier(node) {
+ this.currentScope().__referencing(node);
+ }
+ },
+ UpdateExpression: {
+ value: function UpdateExpression(node) {
+ if (PatternVisitor.isPattern(node.argument)) {
+ this.currentScope().__referencing(node.argument, Reference.RW, null);
+ } else {
+ this.visitChildren(node);
+ }
+ }
+ },
+ MemberExpression: {
+ value: function MemberExpression(node) {
+ this.visit(node.object);
+ if (node.computed) {
+ this.visit(node.property);
+ }
+ }
+ },
+ Property: {
+ value: function Property(node) {
+ this.visitProperty(node);
+ }
+ },
+ MethodDefinition: {
+ value: function MethodDefinition(node) {
+ this.visitProperty(node);
+ }
+ },
+ BreakStatement: {
+ value: function BreakStatement() {}
+ },
+ ContinueStatement: {
+ value: function ContinueStatement() {}
+ },
+ LabeledStatement: {
+ value: function LabeledStatement(node) {
+ this.visit(node.body);
+ }
+ },
+ ForStatement: {
+ value: function ForStatement(node) {
+ // Create ForStatement declaration.
+ // NOTE: In ES6, ForStatement dynamically generates
+ // per iteration environment. However, escope is
+ // a static analyzer, we only generate one scope for ForStatement.
+ if (node.init && node.init.type === Syntax.VariableDeclaration && node.init.kind !== "var") {
+ this.scopeManager.__nestForScope(node);
+ }
+
+ this.visitChildren(node);
+
+ this.close(node);
+ }
+ },
+ ClassExpression: {
+ value: function ClassExpression(node) {
+ this.visitClass(node);
+ }
+ },
+ ClassDeclaration: {
+ value: function ClassDeclaration(node) {
+ this.visitClass(node);
+ }
+ },
+ CallExpression: {
+ value: function CallExpression(node) {
+ // Check this is direct call to eval
+ if (!this.scopeManager.__ignoreEval() && node.callee.type === Syntax.Identifier && node.callee.name === "eval") {
+ // NOTE: This should be `variableScope`. Since direct eval call always creates Lexical environment and
+ // let / const should be enclosed into it. Only VariableDeclaration affects on the caller's environment.
+ this.currentScope().variableScope.__detectEval();
+ }
+ this.visitChildren(node);
+ }
+ },
+ BlockStatement: {
+ value: function BlockStatement(node) {
+ if (this.scopeManager.__isES6()) {
+ this.scopeManager.__nestBlockScope(node);
+ }
+
+ this.visitChildren(node);
+
+ this.close(node);
+ }
+ },
+ ThisExpression: {
+ value: function ThisExpression() {
+ this.currentScope().variableScope.__detectThis();
+ }
+ },
+ WithStatement: {
+ value: function WithStatement(node) {
+ this.visit(node.object);
+ // Then nest scope for WithStatement.
+ this.scopeManager.__nestWithScope(node);
+
+ this.visit(node.body);
+
+ this.close(node);
+ }
+ },
+ VariableDeclaration: {
+ value: function VariableDeclaration(node) {
+ var variableTargetScope, i, iz, decl;
+ variableTargetScope = node.kind === "var" ? this.currentScope().variableScope : this.currentScope();
+ for (i = 0, iz = node.declarations.length; i < iz; ++i) {
+ decl = node.declarations[i];
+ this.visitVariableDeclaration(variableTargetScope, Variable.Variable, node, i);
+ if (decl.init) {
+ this.visit(decl.init);
+ }
+ }
+ }
+ },
+ SwitchStatement: {
+
+ // sec 13.11.8
+
+ value: function SwitchStatement(node) {
+ var i, iz;
+
+ this.visit(node.discriminant);
+
+ if (this.scopeManager.__isES6()) {
+ this.scopeManager.__nestSwitchScope(node);
+ }
+
+ for (i = 0, iz = node.cases.length; i < iz; ++i) {
+ this.visit(node.cases[i]);
+ }
+
+ this.close(node);
+ }
+ },
+ FunctionDeclaration: {
+ value: function FunctionDeclaration(node) {
+ this.visitFunction(node);
+ }
+ },
+ FunctionExpression: {
+ value: function FunctionExpression(node) {
+ this.visitFunction(node);
+ }
+ },
+ ForOfStatement: {
+ value: function ForOfStatement(node) {
+ this.visitForIn(node);
+ }
+ },
+ ForInStatement: {
+ value: function ForInStatement(node) {
+ this.visitForIn(node);
+ }
+ },
+ ArrowFunctionExpression: {
+ value: function ArrowFunctionExpression(node) {
+ this.visitFunction(node);
+ }
+ },
+ ImportDeclaration: {
+ value: function ImportDeclaration(node) {
+ var importer;
+
+ assert(this.scopeManager.__isES6() && this.scopeManager.isModule(), "ImportDeclaration should appear when the mode is ES6 and in the module context.");
+
+ importer = new Importer(node, this);
+ importer.visit(node);
+ }
+ },
+ visitExportDeclaration: {
+ value: function visitExportDeclaration(node) {
+ if (node.source) {
+ return;
+ }
+ if (node.declaration) {
+ this.visit(node.declaration);
+ return;
+ }
+
+ this.visitChildren(node);
+ }
+ },
+ ExportDeclaration: {
+ value: function ExportDeclaration(node) {
+ this.visitExportDeclaration(node);
+ }
+ },
+ ExportNamedDeclaration: {
+ value: function ExportNamedDeclaration(node) {
+ this.visitExportDeclaration(node);
+ }
+ },
+ ExportSpecifier: {
+ value: function ExportSpecifier(node) {
+ var local = node.id || node.local;
+ this.visit(local);
+ }
+ }
+ });
+
+ return Referencer;
+})(esrecurse.Visitor);
+
+module.exports = Referencer;
+
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+
+},{"./definition":75,"./pattern-visitor":77,"./reference":78,"./variable":82,"assert":5,"esrecurse":84,"estraverse":89}],80:[function(require,module,exports){
+"use strict";
+
+var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
+
+var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+/*
+ Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+var WeakMap = _interopRequire(require("es6-weak-map"));
+
+var _scope = require("./scope");
+
+var Scope = _interopRequire(_scope);
+
+var assert = _interopRequire(require("assert"));
+
+var GlobalScope = _scope.GlobalScope;
+var CatchScope = _scope.CatchScope;
+var WithScope = _scope.WithScope;
+var ModuleScope = _scope.ModuleScope;
+var ClassScope = _scope.ClassScope;
+var SwitchScope = _scope.SwitchScope;
+var FunctionScope = _scope.FunctionScope;
+var ForScope = _scope.ForScope;
+var TDZScope = _scope.TDZScope;
+var FunctionExpressionNameScope = _scope.FunctionExpressionNameScope;
+var BlockScope = _scope.BlockScope;
+
+/**
+ * @class ScopeManager
+ */
+
+var ScopeManager = (function () {
+ function ScopeManager(options) {
+ _classCallCheck(this, ScopeManager);
+
+ this.scopes = [];
+ this.globalScope = null;
+ this.__nodeToScope = new WeakMap();
+ this.__currentScope = null;
+ this.__options = options;
+ this.__declaredVariables = new WeakMap();
+ }
+
+ _createClass(ScopeManager, {
+ __useDirective: {
+ value: function __useDirective() {
+ return this.__options.directive;
+ }
+ },
+ __isOptimistic: {
+ value: function __isOptimistic() {
+ return this.__options.optimistic;
+ }
+ },
+ __ignoreEval: {
+ value: function __ignoreEval() {
+ return this.__options.ignoreEval;
+ }
+ },
+ __isNodejsScope: {
+ value: function __isNodejsScope() {
+ return this.__options.nodejsScope;
+ }
+ },
+ isModule: {
+ value: function isModule() {
+ return this.__options.sourceType === "module";
+ }
+ },
+ __get: {
+
+ // Returns appropriate scope for this node.
+
+ value: function __get(node) {
+ return this.__nodeToScope.get(node);
+ }
+ },
+ getDeclaredVariables: {
+
+ /**
+ * Get variables that are declared by the node.
+ *
+ * "are declared by the node" means the node is same as `Variable.defs[].node` or `Variable.defs[].parent`.
+ * If the node declares nothing, this method returns an empty array.
+ * CAUTION: This API is experimental. See https://github.com/estools/escope/pull/69 for more details.
+ *
+ * @param {Esprima.Node} node - a node to get.
+ * @returns {Variable[]} variables that declared by the node.
+ */
+
+ value: function getDeclaredVariables(node) {
+ return this.__declaredVariables.get(node) || [];
+ }
+ },
+ acquire: {
+
+ /**
+ * acquire scope from node.
+ * @method ScopeManager#acquire
+ * @param {Esprima.Node} node - node for the acquired scope.
+ * @param {boolean=} inner - look up the most inner scope, default value is false.
+ * @return {Scope?}
+ */
+
+ value: function acquire(node, inner) {
+ var scopes, scope, i, iz;
+
+ function predicate(scope) {
+ if (scope.type === "function" && scope.functionExpressionScope) {
+ return false;
+ }
+ if (scope.type === "TDZ") {
+ return false;
+ }
+ return true;
+ }
+
+ scopes = this.__get(node);
+ if (!scopes || scopes.length === 0) {
+ return null;
+ }
+
+ // Heuristic selection from all scopes.
+ // If you would like to get all scopes, please use ScopeManager#acquireAll.
+ if (scopes.length === 1) {
+ return scopes[0];
+ }
+
+ if (inner) {
+ for (i = scopes.length - 1; i >= 0; --i) {
+ scope = scopes[i];
+ if (predicate(scope)) {
+ return scope;
+ }
+ }
+ } else {
+ for (i = 0, iz = scopes.length; i < iz; ++i) {
+ scope = scopes[i];
+ if (predicate(scope)) {
+ return scope;
+ }
+ }
+ }
+
+ return null;
+ }
+ },
+ acquireAll: {
+
+ /**
+ * acquire all scopes from node.
+ * @method ScopeManager#acquireAll
+ * @param {Esprima.Node} node - node for the acquired scope.
+ * @return {Scope[]?}
+ */
+
+ value: function acquireAll(node) {
+ return this.__get(node);
+ }
+ },
+ release: {
+
+ /**
+ * release the node.
+ * @method ScopeManager#release
+ * @param {Esprima.Node} node - releasing node.
+ * @param {boolean=} inner - look up the most inner scope, default value is false.
+ * @return {Scope?} upper scope for the node.
+ */
+
+ value: function release(node, inner) {
+ var scopes, scope;
+ scopes = this.__get(node);
+ if (scopes && scopes.length) {
+ scope = scopes[0].upper;
+ if (!scope) {
+ return null;
+ }
+ return this.acquire(scope.block, inner);
+ }
+ return null;
+ }
+ },
+ attach: {
+ value: function attach() {}
+ },
+ detach: {
+ value: function detach() {}
+ },
+ __nestScope: {
+ value: function __nestScope(scope) {
+ if (scope instanceof GlobalScope) {
+ assert(this.__currentScope === null);
+ this.globalScope = scope;
+ }
+ this.__currentScope = scope;
+ return scope;
+ }
+ },
+ __nestGlobalScope: {
+ value: function __nestGlobalScope(node) {
+ return this.__nestScope(new GlobalScope(this, node));
+ }
+ },
+ __nestBlockScope: {
+ value: function __nestBlockScope(node, isMethodDefinition) {
+ return this.__nestScope(new BlockScope(this, this.__currentScope, node));
+ }
+ },
+ __nestFunctionScope: {
+ value: function __nestFunctionScope(node, isMethodDefinition) {
+ return this.__nestScope(new FunctionScope(this, this.__currentScope, node, isMethodDefinition));
+ }
+ },
+ __nestForScope: {
+ value: function __nestForScope(node) {
+ return this.__nestScope(new ForScope(this, this.__currentScope, node));
+ }
+ },
+ __nestCatchScope: {
+ value: function __nestCatchScope(node) {
+ return this.__nestScope(new CatchScope(this, this.__currentScope, node));
+ }
+ },
+ __nestWithScope: {
+ value: function __nestWithScope(node) {
+ return this.__nestScope(new WithScope(this, this.__currentScope, node));
+ }
+ },
+ __nestClassScope: {
+ value: function __nestClassScope(node) {
+ return this.__nestScope(new ClassScope(this, this.__currentScope, node));
+ }
+ },
+ __nestSwitchScope: {
+ value: function __nestSwitchScope(node) {
+ return this.__nestScope(new SwitchScope(this, this.__currentScope, node));
+ }
+ },
+ __nestModuleScope: {
+ value: function __nestModuleScope(node) {
+ return this.__nestScope(new ModuleScope(this, this.__currentScope, node));
+ }
+ },
+ __nestTDZScope: {
+ value: function __nestTDZScope(node) {
+ return this.__nestScope(new TDZScope(this, this.__currentScope, node));
+ }
+ },
+ __nestFunctionExpressionNameScope: {
+ value: function __nestFunctionExpressionNameScope(node) {
+ return this.__nestScope(new FunctionExpressionNameScope(this, this.__currentScope, node));
+ }
+ },
+ __isES6: {
+ value: function __isES6() {
+ return this.__options.ecmaVersion >= 6;
+ }
+ }
+ });
+
+ return ScopeManager;
+})();
+
+module.exports = ScopeManager;
+
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+
+},{"./scope":81,"assert":5,"es6-weak-map":70}],81:[function(require,module,exports){
+"use strict";
+
+var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
+
+var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
+
+var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
+
+var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+/*
+ Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+var Syntax = require("estraverse").Syntax;
+
+var Map = _interopRequire(require("es6-map"));
+
+var Reference = _interopRequire(require("./reference"));
+
+var Variable = _interopRequire(require("./variable"));
+
+var Definition = _interopRequire(require("./definition"));
+
+var assert = _interopRequire(require("assert"));
+
+function isStrictScope(scope, block, isMethodDefinition, useDirective) {
+ var body, i, iz, stmt, expr;
+
+ // When upper scope is exists and strict, inner scope is also strict.
+ if (scope.upper && scope.upper.isStrict) {
+ return true;
+ }
+
+ // ArrowFunctionExpression's scope is always strict scope.
+ if (block.type === Syntax.ArrowFunctionExpression) {
+ return true;
+ }
+
+ if (isMethodDefinition) {
+ return true;
+ }
+
+ if (scope.type === "class" || scope.type === "module") {
+ return true;
+ }
+
+ if (scope.type === "block" || scope.type === "switch") {
+ return false;
+ }
+
+ if (scope.type === "function") {
+ if (block.type === Syntax.Program) {
+ body = block;
+ } else {
+ body = block.body;
+ }
+ } else if (scope.type === "global") {
+ body = block;
+ } else {
+ return false;
+ }
+
+ // Search 'use strict' directive.
+ if (useDirective) {
+ for (i = 0, iz = body.body.length; i < iz; ++i) {
+ stmt = body.body[i];
+ if (stmt.type !== Syntax.DirectiveStatement) {
+ break;
+ }
+ if (stmt.raw === "\"use strict\"" || stmt.raw === "'use strict'") {
+ return true;
+ }
+ }
+ } else {
+ for (i = 0, iz = body.body.length; i < iz; ++i) {
+ stmt = body.body[i];
+ if (stmt.type !== Syntax.ExpressionStatement) {
+ break;
+ }
+ expr = stmt.expression;
+ if (expr.type !== Syntax.Literal || typeof expr.value !== "string") {
+ break;
+ }
+ if (expr.raw != null) {
+ if (expr.raw === "\"use strict\"" || expr.raw === "'use strict'") {
+ return true;
+ }
+ } else {
+ if (expr.value === "use strict") {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+function registerScope(scopeManager, scope) {
+ var scopes;
+
+ scopeManager.scopes.push(scope);
+
+ scopes = scopeManager.__nodeToScope.get(scope.block);
+ if (scopes) {
+ scopes.push(scope);
+ } else {
+ scopeManager.__nodeToScope.set(scope.block, [scope]);
+ }
+}
+
+function shouldBeStatically(def) {
+ return def.type === Variable.ClassName || def.type === Variable.Variable && def.parent.kind !== "var";
+}
+
+/**
+ * @class Scope
+ */
+
+var Scope = (function () {
+ function Scope(scopeManager, type, upperScope, block, isMethodDefinition) {
+ _classCallCheck(this, Scope);
+
+ /**
+ * One of 'TDZ', 'module', 'block', 'switch', 'function', 'catch', 'with', 'function', 'class', 'global'.
+ * @member {String} Scope#type
+ */
+ this.type = type;
+ /**
+ * The scoped {@link Variable}s of this scope, as <code>{ Variable.name
+ * : Variable }</code>.
+ * @member {Map} Scope#set
+ */
+ this.set = new Map();
+ /**
+ * The tainted variables of this scope, as <code>{ Variable.name :
+ * boolean }</code>.
+ * @member {Map} Scope#taints */
+ this.taints = new Map();
+ /**
+ * Generally, through the lexical scoping of JS you can always know
+ * which variable an identifier in the source code refers to. There are
+ * a few exceptions to this rule. With 'global' and 'with' scopes you
+ * can only decide at runtime which variable a reference refers to.
+ * Moreover, if 'eval()' is used in a scope, it might introduce new
+ * bindings in this or its parent scopes.
+ * All those scopes are considered 'dynamic'.
+ * @member {boolean} Scope#dynamic
+ */
+ this.dynamic = this.type === "global" || this.type === "with";
+ /**
+ * A reference to the scope-defining syntax node.
+ * @member {esprima.Node} Scope#block
+ */
+ this.block = block;
+ /**
+ * The {@link Reference|references} that are not resolved with this scope.
+ * @member {Reference[]} Scope#through
+ */
+ this.through = [];
+ /**
+ * The scoped {@link Variable}s of this scope. In the case of a
+ * 'function' scope this includes the automatic argument <em>arguments</em> as
+ * its first element, as well as all further formal arguments.
+ * @member {Variable[]} Scope#variables
+ */
+ this.variables = [];
+ /**
+ * Any variable {@link Reference|reference} found in this scope. This
+ * includes occurrences of local variables as well as variables from
+ * parent scopes (including the global scope). For local variables
+ * this also includes defining occurrences (like in a 'var' statement).
+ * In a 'function' scope this does not include the occurrences of the
+ * formal parameter in the parameter list.
+ * @member {Reference[]} Scope#references
+ */
+ this.references = [];
+
+ /**
+ * For 'global' and 'function' scopes, this is a self-reference. For
+ * other scope types this is the <em>variableScope</em> value of the
+ * parent scope.
+ * @member {Scope} Scope#variableScope
+ */
+ this.variableScope = this.type === "global" || this.type === "function" || this.type === "module" ? this : upperScope.variableScope;
+ /**
+ * Whether this scope is created by a FunctionExpression.
+ * @member {boolean} Scope#functionExpressionScope
+ */
+ this.functionExpressionScope = false;
+ /**
+ * Whether this is a scope that contains an 'eval()' invocation.
+ * @member {boolean} Scope#directCallToEvalScope
+ */
+ this.directCallToEvalScope = false;
+ /**
+ * @member {boolean} Scope#thisFound
+ */
+ this.thisFound = false;
+
+ this.__left = [];
+
+ /**
+ * Reference to the parent {@link Scope|scope}.
+ * @member {Scope} Scope#upper
+ */
+ this.upper = upperScope;
+ /**
+ * Whether 'use strict' is in effect in this scope.
+ * @member {boolean} Scope#isStrict
+ */
+ this.isStrict = isStrictScope(this, block, isMethodDefinition, scopeManager.__useDirective());
+
+ /**
+ * List of nested {@link Scope}s.
+ * @member {Scope[]} Scope#childScopes
+ */
+ this.childScopes = [];
+ if (this.upper) {
+ this.upper.childScopes.push(this);
+ }
+
+ this.__declaredVariables = scopeManager.__declaredVariables;
+
+ registerScope(scopeManager, this);
+ }
+
+ _createClass(Scope, {
+ __shouldStaticallyClose: {
+ value: function __shouldStaticallyClose(scopeManager) {
+ return !this.dynamic || scopeManager.__isOptimistic();
+ }
+ },
+ __shouldStaticallyCloseForGlobal: {
+ value: function __shouldStaticallyCloseForGlobal(ref) {
+ // On global scope, let/const/class declarations should be resolved statically.
+ var name = ref.identifier.name;
+ if (!this.set.has(name)) {
+ return false;
+ }
+
+ var variable = this.set.get(name);
+ var defs = variable.defs;
+ return defs.length > 0 && defs.every(shouldBeStatically);
+ }
+ },
+ __staticCloseRef: {
+ value: function __staticCloseRef(ref) {
+ if (!this.__resolve(ref)) {
+ this.__delegateToUpperScope(ref);
+ }
+ }
+ },
+ __dynamicCloseRef: {
+ value: function __dynamicCloseRef(ref) {
+ // notify all names are through to global
+ var current = this;
+ do {
+ current.through.push(ref);
+ current = current.upper;
+ } while (current);
+ }
+ },
+ __globalCloseRef: {
+ value: function __globalCloseRef(ref) {
+ // let/const/class declarations should be resolved statically.
+ // others should be resolved dynamically.
+ if (this.__shouldStaticallyCloseForGlobal(ref)) {
+ this.__staticCloseRef(ref);
+ } else {
+ this.__dynamicCloseRef(ref);
+ }
+ }
+ },
+ __close: {
+ value: function __close(scopeManager) {
+ var closeRef;
+ if (this.__shouldStaticallyClose(scopeManager)) {
+ closeRef = this.__staticCloseRef;
+ } else if (this.type !== "global") {
+ closeRef = this.__dynamicCloseRef;
+ } else {
+ closeRef = this.__globalCloseRef;
+ }
+
+ // Try Resolving all references in this scope.
+ for (var i = 0, iz = this.__left.length; i < iz; ++i) {
+ var ref = this.__left[i];
+ closeRef.call(this, ref);
+ }
+ this.__left = null;
+
+ return this.upper;
+ }
+ },
+ __resolve: {
+ value: function __resolve(ref) {
+ var variable, name;
+ name = ref.identifier.name;
+ if (this.set.has(name)) {
+ variable = this.set.get(name);
+ variable.references.push(ref);
+ variable.stack = variable.stack && ref.from.variableScope === this.variableScope;
+ if (ref.tainted) {
+ variable.tainted = true;
+ this.taints.set(variable.name, true);
+ }
+ ref.resolved = variable;
+ return true;
+ }
+ return false;
+ }
+ },
+ __delegateToUpperScope: {
+ value: function __delegateToUpperScope(ref) {
+ if (this.upper) {
+ this.upper.__left.push(ref);
+ }
+ this.through.push(ref);
+ }
+ },
+ __addDeclaredVariablesOfNode: {
+ value: function __addDeclaredVariablesOfNode(variable, node) {
+ if (node == null) {
+ return;
+ }
+
+ var variables = this.__declaredVariables.get(node);
+ if (variables == null) {
+ variables = [];
+ this.__declaredVariables.set(node, variables);
+ }
+ if (variables.indexOf(variable) === -1) {
+ variables.push(variable);
+ }
+ }
+ },
+ __defineGeneric: {
+ value: function __defineGeneric(name, set, variables, node, def) {
+ var variable;
+
+ variable = set.get(name);
+ if (!variable) {
+ variable = new Variable(name, this);
+ set.set(name, variable);
+ variables.push(variable);
+ }
+
+ if (def) {
+ variable.defs.push(def);
+ if (def.type !== Variable.TDZ) {
+ this.__addDeclaredVariablesOfNode(variable, def.node);
+ this.__addDeclaredVariablesOfNode(variable, def.parent);
+ }
+ }
+ if (node) {
+ variable.identifiers.push(node);
+ }
+ }
+ },
+ __define: {
+ value: function __define(node, def) {
+ if (node && node.type === Syntax.Identifier) {
+ this.__defineGeneric(node.name, this.set, this.variables, node, def);
+ }
+ }
+ },
+ __referencing: {
+ value: function __referencing(node, assign, writeExpr, maybeImplicitGlobal, partial, init) {
+ // because Array element may be null
+ if (!node || node.type !== Syntax.Identifier) {
+ return;
+ }
+
+ // Specially handle like `this`.
+ if (node.name === "super") {
+ return;
+ }
+
+ var ref = new Reference(node, this, assign || Reference.READ, writeExpr, maybeImplicitGlobal, !!partial, !!init);
+ this.references.push(ref);
+ this.__left.push(ref);
+ }
+ },
+ __detectEval: {
+ value: function __detectEval() {
+ var current;
+ current = this;
+ this.directCallToEvalScope = true;
+ do {
+ current.dynamic = true;
+ current = current.upper;
+ } while (current);
+ }
+ },
+ __detectThis: {
+ value: function __detectThis() {
+ this.thisFound = true;
+ }
+ },
+ __isClosed: {
+ value: function __isClosed() {
+ return this.__left === null;
+ }
+ },
+ resolve: {
+
+ /**
+ * returns resolved {Reference}
+ * @method Scope#resolve
+ * @param {Esprima.Identifier} ident - identifier to be resolved.
+ * @return {Reference}
+ */
+
+ value: function resolve(ident) {
+ var ref, i, iz;
+ assert(this.__isClosed(), "Scope should be closed.");
+ assert(ident.type === Syntax.Identifier, "Target should be identifier.");
+ for (i = 0, iz = this.references.length; i < iz; ++i) {
+ ref = this.references[i];
+ if (ref.identifier === ident) {
+ return ref;
+ }
+ }
+ return null;
+ }
+ },
+ isStatic: {
+
+ /**
+ * returns this scope is static
+ * @method Scope#isStatic
+ * @return {boolean}
+ */
+
+ value: function isStatic() {
+ return !this.dynamic;
+ }
+ },
+ isArgumentsMaterialized: {
+
+ /**
+ * returns this scope has materialized arguments
+ * @method Scope#isArgumentsMaterialized
+ * @return {boolean}
+ */
+
+ value: function isArgumentsMaterialized() {
+ return true;
+ }
+ },
+ isThisMaterialized: {
+
+ /**
+ * returns this scope has materialized `this` reference
+ * @method Scope#isThisMaterialized
+ * @return {boolean}
+ */
+
+ value: function isThisMaterialized() {
+ return true;
+ }
+ },
+ isUsedName: {
+ value: function isUsedName(name) {
+ if (this.set.has(name)) {
+ return true;
+ }
+ for (var i = 0, iz = this.through.length; i < iz; ++i) {
+ if (this.through[i].identifier.name === name) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ });
+
+ return Scope;
+})();
+
+exports["default"] = Scope;
+
+var GlobalScope = exports.GlobalScope = (function (_Scope) {
+ function GlobalScope(scopeManager, block) {
+ _classCallCheck(this, GlobalScope);
+
+ _get(Object.getPrototypeOf(GlobalScope.prototype), "constructor", this).call(this, scopeManager, "global", null, block, false);
+ this.implicit = {
+ set: new Map(),
+ variables: [],
+ /**
+ * List of {@link Reference}s that are left to be resolved (i.e. which
+ * need to be linked to the variable they refer to).
+ * @member {Reference[]} Scope#implicit#left
+ */
+ left: []
+ };
+ }
+
+ _inherits(GlobalScope, _Scope);
+
+ _createClass(GlobalScope, {
+ __close: {
+ value: function __close(scopeManager) {
+ var implicit = [];
+ for (var i = 0, iz = this.__left.length; i < iz; ++i) {
+ var ref = this.__left[i];
+ if (ref.__maybeImplicitGlobal && !this.set.has(ref.identifier.name)) {
+ implicit.push(ref.__maybeImplicitGlobal);
+ }
+ }
+
+ // create an implicit global variable from assignment expression
+ for (var i = 0, iz = implicit.length; i < iz; ++i) {
+ var info = implicit[i];
+ this.__defineImplicit(info.pattern, new Definition(Variable.ImplicitGlobalVariable, info.pattern, info.node, null, null, null));
+ }
+
+ this.implicit.left = this.__left;
+
+ return _get(Object.getPrototypeOf(GlobalScope.prototype), "__close", this).call(this, scopeManager);
+ }
+ },
+ __defineImplicit: {
+ value: function __defineImplicit(node, def) {
+ if (node && node.type === Syntax.Identifier) {
+ this.__defineGeneric(node.name, this.implicit.set, this.implicit.variables, node, def);
+ }
+ }
+ }
+ });
+
+ return GlobalScope;
+})(Scope);
+
+var ModuleScope = exports.ModuleScope = (function (_Scope2) {
+ function ModuleScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, ModuleScope);
+
+ _get(Object.getPrototypeOf(ModuleScope.prototype), "constructor", this).call(this, scopeManager, "module", upperScope, block, false);
+ }
+
+ _inherits(ModuleScope, _Scope2);
+
+ return ModuleScope;
+})(Scope);
+
+var FunctionExpressionNameScope = exports.FunctionExpressionNameScope = (function (_Scope3) {
+ function FunctionExpressionNameScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, FunctionExpressionNameScope);
+
+ _get(Object.getPrototypeOf(FunctionExpressionNameScope.prototype), "constructor", this).call(this, scopeManager, "function-expression-name", upperScope, block, false);
+ this.__define(block.id, new Definition(Variable.FunctionName, block.id, block, null, null, null));
+ this.functionExpressionScope = true;
+ }
+
+ _inherits(FunctionExpressionNameScope, _Scope3);
+
+ return FunctionExpressionNameScope;
+})(Scope);
+
+var CatchScope = exports.CatchScope = (function (_Scope4) {
+ function CatchScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, CatchScope);
+
+ _get(Object.getPrototypeOf(CatchScope.prototype), "constructor", this).call(this, scopeManager, "catch", upperScope, block, false);
+ }
+
+ _inherits(CatchScope, _Scope4);
+
+ return CatchScope;
+})(Scope);
+
+var WithScope = exports.WithScope = (function (_Scope5) {
+ function WithScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, WithScope);
+
+ _get(Object.getPrototypeOf(WithScope.prototype), "constructor", this).call(this, scopeManager, "with", upperScope, block, false);
+ }
+
+ _inherits(WithScope, _Scope5);
+
+ _createClass(WithScope, {
+ __close: {
+ value: function __close(scopeManager) {
+ if (this.__shouldStaticallyClose(scopeManager)) {
+ return _get(Object.getPrototypeOf(WithScope.prototype), "__close", this).call(this, scopeManager);
+ }
+
+ for (var i = 0, iz = this.__left.length; i < iz; ++i) {
+ var ref = this.__left[i];
+ ref.tainted = true;
+ this.__delegateToUpperScope(ref);
+ }
+ this.__left = null;
+
+ return this.upper;
+ }
+ }
+ });
+
+ return WithScope;
+})(Scope);
+
+var TDZScope = exports.TDZScope = (function (_Scope6) {
+ function TDZScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, TDZScope);
+
+ _get(Object.getPrototypeOf(TDZScope.prototype), "constructor", this).call(this, scopeManager, "TDZ", upperScope, block, false);
+ }
+
+ _inherits(TDZScope, _Scope6);
+
+ return TDZScope;
+})(Scope);
+
+var BlockScope = exports.BlockScope = (function (_Scope7) {
+ function BlockScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, BlockScope);
+
+ _get(Object.getPrototypeOf(BlockScope.prototype), "constructor", this).call(this, scopeManager, "block", upperScope, block, false);
+ }
+
+ _inherits(BlockScope, _Scope7);
+
+ return BlockScope;
+})(Scope);
+
+var SwitchScope = exports.SwitchScope = (function (_Scope8) {
+ function SwitchScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, SwitchScope);
+
+ _get(Object.getPrototypeOf(SwitchScope.prototype), "constructor", this).call(this, scopeManager, "switch", upperScope, block, false);
+ }
+
+ _inherits(SwitchScope, _Scope8);
+
+ return SwitchScope;
+})(Scope);
+
+var FunctionScope = exports.FunctionScope = (function (_Scope9) {
+ function FunctionScope(scopeManager, upperScope, block, isMethodDefinition) {
+ _classCallCheck(this, FunctionScope);
+
+ _get(Object.getPrototypeOf(FunctionScope.prototype), "constructor", this).call(this, scopeManager, "function", upperScope, block, isMethodDefinition);
+
+ // section 9.2.13, FunctionDeclarationInstantiation.
+ // NOTE Arrow functions never have an arguments objects.
+ if (this.block.type !== Syntax.ArrowFunctionExpression) {
+ this.__defineArguments();
+ }
+ }
+
+ _inherits(FunctionScope, _Scope9);
+
+ _createClass(FunctionScope, {
+ isArgumentsMaterialized: {
+ value: function isArgumentsMaterialized() {
+ // TODO(Constellation)
+ // We can more aggressive on this condition like this.
+ //
+ // function t() {
+ // // arguments of t is always hidden.
+ // function arguments() {
+ // }
+ // }
+ if (this.block.type === Syntax.ArrowFunctionExpression) {
+ return false;
+ }
+
+ if (!this.isStatic()) {
+ return true;
+ }
+
+ var variable = this.set.get("arguments");
+ assert(variable, "Always have arguments variable.");
+ return variable.tainted || variable.references.length !== 0;
+ }
+ },
+ isThisMaterialized: {
+ value: function isThisMaterialized() {
+ if (!this.isStatic()) {
+ return true;
+ }
+ return this.thisFound;
+ }
+ },
+ __defineArguments: {
+ value: function __defineArguments() {
+ this.__defineGeneric("arguments", this.set, this.variables, null, null);
+ this.taints.set("arguments", true);
+ }
+ }
+ });
+
+ return FunctionScope;
+})(Scope);
+
+var ForScope = exports.ForScope = (function (_Scope10) {
+ function ForScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, ForScope);
+
+ _get(Object.getPrototypeOf(ForScope.prototype), "constructor", this).call(this, scopeManager, "for", upperScope, block, false);
+ }
+
+ _inherits(ForScope, _Scope10);
+
+ return ForScope;
+})(Scope);
+
+var ClassScope = exports.ClassScope = (function (_Scope11) {
+ function ClassScope(scopeManager, upperScope, block) {
+ _classCallCheck(this, ClassScope);
+
+ _get(Object.getPrototypeOf(ClassScope.prototype), "constructor", this).call(this, scopeManager, "class", upperScope, block, false);
+ }
+
+ _inherits(ClassScope, _Scope11);
+
+ return ClassScope;
+})(Scope);
+
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+
+},{"./definition":75,"./reference":78,"./variable":82,"assert":5,"es6-map":59,"estraverse":89}],82:[function(require,module,exports){
+"use strict";
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+/*
+ Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * A Variable represents a locally scoped identifier. These include arguments to
+ * functions.
+ * @class Variable
+ */
+
+var Variable = function Variable(name, scope) {
+ _classCallCheck(this, Variable);
+
+ /**
+ * The variable name, as given in the source code.
+ * @member {String} Variable#name
+ */
+ this.name = name;
+ /**
+ * List of defining occurrences of this variable (like in 'var ...'
+ * statements or as parameter), as AST nodes.
+ * @member {esprima.Identifier[]} Variable#identifiers
+ */
+ this.identifiers = [];
+ /**
+ * List of {@link Reference|references} of this variable (excluding parameter entries)
+ * in its defining scope and all nested scopes. For defining
+ * occurrences only see {@link Variable#defs}.
+ * @member {Reference[]} Variable#references
+ */
+ this.references = [];
+
+ /**
+ * List of defining occurrences of this variable (like in 'var ...'
+ * statements or as parameter), as custom objects.
+ * @member {Definition[]} Variable#defs
+ */
+ this.defs = [];
+
+ this.tainted = false;
+ /**
+ * Whether this is a stack variable.
+ * @member {boolean} Variable#stack
+ */
+ this.stack = true;
+ /**
+ * Reference to the enclosing Scope.
+ * @member {Scope} Variable#scope
+ */
+ this.scope = scope;
+};
+
+module.exports = Variable;
+
+Variable.CatchClause = "CatchClause";
+Variable.Parameter = "Parameter";
+Variable.FunctionName = "FunctionName";
+Variable.ClassName = "ClassName";
+Variable.Variable = "Variable";
+Variable.ImportBinding = "ImportBinding";
+Variable.TDZ = "TDZ";
+Variable.ImplicitGlobalVariable = "ImplicitGlobalVariable";
+
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+
+},{}],83:[function(require,module,exports){
+module.exports={
+ "_args": [
+ [
+ "escope@^3.2.1",
+ "/Users/force/code/eslint"
+ ]
+ ],
+ "_from": "escope@>=3.2.1 <4.0.0",
+ "_id": "escope@3.3.0",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/escope",
+ "_nodeVersion": "4.1.1",
+ "_npmUser": {
+ "email": "utatane.tea@gmail.com",
+ "name": "constellation"
+ },
+ "_npmVersion": "2.14.4",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "escope",
+ "raw": "escope@^3.2.1",
+ "rawSpec": "^3.2.1",
+ "scope": null,
+ "spec": ">=3.2.1 <4.0.0",
+ "type": "range"
+ },
+ "_requiredBy": [
+ "/"
+ ],
+ "_resolved": "https://registry.npmjs.org/escope/-/escope-3.3.0.tgz",
+ "_shasum": "6201c97285c2c13643afe4453b58de64481aa1a4",
+ "_shrinkwrap": null,
+ "_spec": "escope@^3.2.1",
+ "_where": "/Users/force/code/eslint",
+ "bugs": {
+ "url": "https://github.com/estools/escope/issues"
+ },
+ "dependencies": {
+ "es6-map": "^0.1.2",
+ "es6-weak-map": "^2.0.1",
+ "esrecurse": "^3.1.1",
+ "estraverse": "^4.1.1"
+ },
+ "description": "ECMAScript scope analyzer",
+ "devDependencies": {
+ "acorn": "^2.5.2",
+ "babel": "^4.7.12",
+ "browserify": "^12.0.1",
+ "chai": "^3.4.0",
+ "coffee-script": "^1.10.0",
+ "espree": "^2.2.5",
+ "esprima": "^2.7.0",
+ "gulp": "^3.9.0",
+ "gulp-babel": "^4.0.0",
+ "gulp-bump": "^1.0.0",
+ "gulp-coffee": "^2.3.1",
+ "gulp-eslint": "^1.0.0",
+ "gulp-espower": "^1.0.1",
+ "gulp-filter": "^3.0.1",
+ "gulp-git": "^1.6.0",
+ "gulp-mocha": "^2.1.3",
+ "gulp-plumber": "^1.0.1",
+ "gulp-sourcemaps": "^1.6.0",
+ "gulp-tag-version": "^1.3.0",
+ "jsdoc": "^3.3.3",
+ "lazypipe": "^1.0.1",
+ "minimist": "^1.2.0",
+ "vinyl-source-stream": "^1.1.0"
+ },
+ "directories": {},
+ "dist": {
+ "shasum": "6201c97285c2c13643afe4453b58de64481aa1a4",
+ "tarball": "http://registry.npmjs.org/escope/-/escope-3.3.0.tgz"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ },
+ "gitHead": "a3402c3e5c04f4e3dc15c88fd2d7ce8608d26ba7",
+ "homepage": "http://github.com/estools/escope",
+ "license": "BSD-2-Clause",
+ "main": "lib/index.js",
+ "maintainers": [
+ {
+ "name": "constellation",
+ "email": "utatane.tea@gmail.com"
+ },
+ {
+ "name": "michaelficarra",
+ "email": "npm@michael.ficarra.me"
+ },
+ {
+ "name": "nzakas",
+ "email": "nicholas@nczconsulting.com"
+ }
+ ],
+ "name": "escope",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/estools/escope.git"
+ },
+ "scripts": {
+ "jsdoc": "jsdoc src/*.js README.md",
+ "lint": "gulp lint",
+ "test": "gulp travis",
+ "unit-test": "gulp test"
+ },
+ "version": "3.3.0"
+}
+
+},{}],84:[function(require,module,exports){
+/*
Copyright (C) 2014 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -14851,11 +15415,11 @@
function isProperty(nodeType, key) {
return (nodeType === estraverse.Syntax.ObjectExpression || nodeType === estraverse.Syntax.ObjectPattern) && key === 'properties';
}
function Visitor(visitor) {
- this.__visitor = visitor;
+ this.__visitor = visitor || this;
}
/* Default method for visiting children.
* When you need to call default visiting operation inside custom visiting
* operation, you can use it with `this.visitChildren(node)`.
@@ -14915,195 +15479,1046 @@
v.visit(node);
};
}());
/* vim: set sw=4 ts=4 et tw=80 : */
-},{"./package.json":122,"estraverse":127}],122:[function(require,module,exports){
+},{"./package.json":87,"estraverse":85}],85:[function(require,module,exports){
+/*
+ Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>
+ Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*jslint vars:false, bitwise:true*/
+/*jshint indent:4*/
+/*global exports:true*/
+(function clone(exports) {
+ 'use strict';
+
+ var Syntax,
+ isArray,
+ VisitorOption,
+ VisitorKeys,
+ objectCreate,
+ objectKeys,
+ BREAK,
+ SKIP,
+ REMOVE;
+
+ function ignoreJSHintError() { }
+
+ isArray = Array.isArray;
+ if (!isArray) {
+ isArray = function isArray(array) {
+ return Object.prototype.toString.call(array) === '[object Array]';
+ };
+ }
+
+ function deepCopy(obj) {
+ var ret = {}, key, val;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ val = obj[key];
+ if (typeof val === 'object' && val !== null) {
+ ret[key] = deepCopy(val);
+ } else {
+ ret[key] = val;
+ }
+ }
+ }
+ return ret;
+ }
+
+ function shallowCopy(obj) {
+ var ret = {}, key;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ ret[key] = obj[key];
+ }
+ }
+ return ret;
+ }
+ ignoreJSHintError(shallowCopy);
+
+ // based on LLVM libc++ upper_bound / lower_bound
+ // MIT License
+
+ function upperBound(array, func) {
+ var diff, len, i, current;
+
+ len = array.length;
+ i = 0;
+
+ while (len) {
+ diff = len >>> 1;
+ current = i + diff;
+ if (func(array[current])) {
+ len = diff;
+ } else {
+ i = current + 1;
+ len -= diff + 1;
+ }
+ }
+ return i;
+ }
+
+ function lowerBound(array, func) {
+ var diff, len, i, current;
+
+ len = array.length;
+ i = 0;
+
+ while (len) {
+ diff = len >>> 1;
+ current = i + diff;
+ if (func(array[current])) {
+ i = current + 1;
+ len -= diff + 1;
+ } else {
+ len = diff;
+ }
+ }
+ return i;
+ }
+ ignoreJSHintError(lowerBound);
+
+ objectCreate = Object.create || (function () {
+ function F() { }
+
+ return function (o) {
+ F.prototype = o;
+ return new F();
+ };
+ })();
+
+ objectKeys = Object.keys || function (o) {
+ var keys = [], key;
+ for (key in o) {
+ keys.push(key);
+ }
+ return keys;
+ };
+
+ function extend(to, from) {
+ var keys = objectKeys(from), key, i, len;
+ for (i = 0, len = keys.length; i < len; i += 1) {
+ key = keys[i];
+ to[key] = from[key];
+ }
+ return to;
+ }
+
+ Syntax = {
+ AssignmentExpression: 'AssignmentExpression',
+ AssignmentPattern: 'AssignmentPattern',
+ ArrayExpression: 'ArrayExpression',
+ ArrayPattern: 'ArrayPattern',
+ ArrowFunctionExpression: 'ArrowFunctionExpression',
+ AwaitExpression: 'AwaitExpression', // CAUTION: It's deferred to ES7.
+ BlockStatement: 'BlockStatement',
+ BinaryExpression: 'BinaryExpression',
+ BreakStatement: 'BreakStatement',
+ CallExpression: 'CallExpression',
+ CatchClause: 'CatchClause',
+ ClassBody: 'ClassBody',
+ ClassDeclaration: 'ClassDeclaration',
+ ClassExpression: 'ClassExpression',
+ ComprehensionBlock: 'ComprehensionBlock', // CAUTION: It's deferred to ES7.
+ ComprehensionExpression: 'ComprehensionExpression', // CAUTION: It's deferred to ES7.
+ ConditionalExpression: 'ConditionalExpression',
+ ContinueStatement: 'ContinueStatement',
+ DebuggerStatement: 'DebuggerStatement',
+ DirectiveStatement: 'DirectiveStatement',
+ DoWhileStatement: 'DoWhileStatement',
+ EmptyStatement: 'EmptyStatement',
+ ExportAllDeclaration: 'ExportAllDeclaration',
+ ExportDefaultDeclaration: 'ExportDefaultDeclaration',
+ ExportNamedDeclaration: 'ExportNamedDeclaration',
+ ExportSpecifier: 'ExportSpecifier',
+ ExpressionStatement: 'ExpressionStatement',
+ ForStatement: 'ForStatement',
+ ForInStatement: 'ForInStatement',
+ ForOfStatement: 'ForOfStatement',
+ FunctionDeclaration: 'FunctionDeclaration',
+ FunctionExpression: 'FunctionExpression',
+ GeneratorExpression: 'GeneratorExpression', // CAUTION: It's deferred to ES7.
+ Identifier: 'Identifier',
+ IfStatement: 'IfStatement',
+ ImportDeclaration: 'ImportDeclaration',
+ ImportDefaultSpecifier: 'ImportDefaultSpecifier',
+ ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
+ ImportSpecifier: 'ImportSpecifier',
+ Literal: 'Literal',
+ LabeledStatement: 'LabeledStatement',
+ LogicalExpression: 'LogicalExpression',
+ MemberExpression: 'MemberExpression',
+ MethodDefinition: 'MethodDefinition',
+ ModuleSpecifier: 'ModuleSpecifier',
+ NewExpression: 'NewExpression',
+ ObjectExpression: 'ObjectExpression',
+ ObjectPattern: 'ObjectPattern',
+ Program: 'Program',
+ Property: 'Property',
+ RestElement: 'RestElement',
+ ReturnStatement: 'ReturnStatement',
+ SequenceExpression: 'SequenceExpression',
+ SpreadElement: 'SpreadElement',
+ SuperExpression: 'SuperExpression',
+ SwitchStatement: 'SwitchStatement',
+ SwitchCase: 'SwitchCase',
+ TaggedTemplateExpression: 'TaggedTemplateExpression',
+ TemplateElement: 'TemplateElement',
+ TemplateLiteral: 'TemplateLiteral',
+ ThisExpression: 'ThisExpression',
+ ThrowStatement: 'ThrowStatement',
+ TryStatement: 'TryStatement',
+ UnaryExpression: 'UnaryExpression',
+ UpdateExpression: 'UpdateExpression',
+ VariableDeclaration: 'VariableDeclaration',
+ VariableDeclarator: 'VariableDeclarator',
+ WhileStatement: 'WhileStatement',
+ WithStatement: 'WithStatement',
+ YieldExpression: 'YieldExpression'
+ };
+
+ VisitorKeys = {
+ AssignmentExpression: ['left', 'right'],
+ AssignmentPattern: ['left', 'right'],
+ ArrayExpression: ['elements'],
+ ArrayPattern: ['elements'],
+ ArrowFunctionExpression: ['params', 'body'],
+ AwaitExpression: ['argument'], // CAUTION: It's deferred to ES7.
+ BlockStatement: ['body'],
+ BinaryExpression: ['left', 'right'],
+ BreakStatement: ['label'],
+ CallExpression: ['callee', 'arguments'],
+ CatchClause: ['param', 'body'],
+ ClassBody: ['body'],
+ ClassDeclaration: ['id', 'superClass', 'body'],
+ ClassExpression: ['id', 'superClass', 'body'],
+ ComprehensionBlock: ['left', 'right'], // CAUTION: It's deferred to ES7.
+ ComprehensionExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7.
+ ConditionalExpression: ['test', 'consequent', 'alternate'],
+ ContinueStatement: ['label'],
+ DebuggerStatement: [],
+ DirectiveStatement: [],
+ DoWhileStatement: ['body', 'test'],
+ EmptyStatement: [],
+ ExportAllDeclaration: ['source'],
+ ExportDefaultDeclaration: ['declaration'],
+ ExportNamedDeclaration: ['declaration', 'specifiers', 'source'],
+ ExportSpecifier: ['exported', 'local'],
+ ExpressionStatement: ['expression'],
+ ForStatement: ['init', 'test', 'update', 'body'],
+ ForInStatement: ['left', 'right', 'body'],
+ ForOfStatement: ['left', 'right', 'body'],
+ FunctionDeclaration: ['id', 'params', 'body'],
+ FunctionExpression: ['id', 'params', 'body'],
+ GeneratorExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7.
+ Identifier: [],
+ IfStatement: ['test', 'consequent', 'alternate'],
+ ImportDeclaration: ['specifiers', 'source'],
+ ImportDefaultSpecifier: ['local'],
+ ImportNamespaceSpecifier: ['local'],
+ ImportSpecifier: ['imported', 'local'],
+ Literal: [],
+ LabeledStatement: ['label', 'body'],
+ LogicalExpression: ['left', 'right'],
+ MemberExpression: ['object', 'property'],
+ MethodDefinition: ['key', 'value'],
+ ModuleSpecifier: [],
+ NewExpression: ['callee', 'arguments'],
+ ObjectExpression: ['properties'],
+ ObjectPattern: ['properties'],
+ Program: ['body'],
+ Property: ['key', 'value'],
+ RestElement: [ 'argument' ],
+ ReturnStatement: ['argument'],
+ SequenceExpression: ['expressions'],
+ SpreadElement: ['argument'],
+ SuperExpression: ['super'],
+ SwitchStatement: ['discriminant', 'cases'],
+ SwitchCase: ['test', 'consequent'],
+ TaggedTemplateExpression: ['tag', 'quasi'],
+ TemplateElement: [],
+ TemplateLiteral: ['quasis', 'expressions'],
+ ThisExpression: [],
+ ThrowStatement: ['argument'],
+ TryStatement: ['block', 'handler', 'finalizer'],
+ UnaryExpression: ['argument'],
+ UpdateExpression: ['argument'],
+ VariableDeclaration: ['declarations'],
+ VariableDeclarator: ['id', 'init'],
+ WhileStatement: ['test', 'body'],
+ WithStatement: ['object', 'body'],
+ YieldExpression: ['argument']
+ };
+
+ // unique id
+ BREAK = {};
+ SKIP = {};
+ REMOVE = {};
+
+ VisitorOption = {
+ Break: BREAK,
+ Skip: SKIP,
+ Remove: REMOVE
+ };
+
+ function Reference(parent, key) {
+ this.parent = parent;
+ this.key = key;
+ }
+
+ Reference.prototype.replace = function replace(node) {
+ this.parent[this.key] = node;
+ };
+
+ Reference.prototype.remove = function remove() {
+ if (isArray(this.parent)) {
+ this.parent.splice(this.key, 1);
+ return true;
+ } else {
+ this.replace(null);
+ return false;
+ }
+ };
+
+ function Element(node, path, wrap, ref) {
+ this.node = node;
+ this.path = path;
+ this.wrap = wrap;
+ this.ref = ref;
+ }
+
+ function Controller() { }
+
+ // API:
+ // return property path array from root to current node
+ Controller.prototype.path = function path() {
+ var i, iz, j, jz, result, element;
+
+ function addToPath(result, path) {
+ if (isArray(path)) {
+ for (j = 0, jz = path.length; j < jz; ++j) {
+ result.push(path[j]);
+ }
+ } else {
+ result.push(path);
+ }
+ }
+
+ // root node
+ if (!this.__current.path) {
+ return null;
+ }
+
+ // first node is sentinel, second node is root element
+ result = [];
+ for (i = 2, iz = this.__leavelist.length; i < iz; ++i) {
+ element = this.__leavelist[i];
+ addToPath(result, element.path);
+ }
+ addToPath(result, this.__current.path);
+ return result;
+ };
+
+ // API:
+ // return type of current node
+ Controller.prototype.type = function () {
+ var node = this.current();
+ return node.type || this.__current.wrap;
+ };
+
+ // API:
+ // return array of parent elements
+ Controller.prototype.parents = function parents() {
+ var i, iz, result;
+
+ // first node is sentinel
+ result = [];
+ for (i = 1, iz = this.__leavelist.length; i < iz; ++i) {
+ result.push(this.__leavelist[i].node);
+ }
+
+ return result;
+ };
+
+ // API:
+ // return current node
+ Controller.prototype.current = function current() {
+ return this.__current.node;
+ };
+
+ Controller.prototype.__execute = function __execute(callback, element) {
+ var previous, result;
+
+ result = undefined;
+
+ previous = this.__current;
+ this.__current = element;
+ this.__state = null;
+ if (callback) {
+ result = callback.call(this, element.node, this.__leavelist[this.__leavelist.length - 1].node);
+ }
+ this.__current = previous;
+
+ return result;
+ };
+
+ // API:
+ // notify control skip / break
+ Controller.prototype.notify = function notify(flag) {
+ this.__state = flag;
+ };
+
+ // API:
+ // skip child nodes of current node
+ Controller.prototype.skip = function () {
+ this.notify(SKIP);
+ };
+
+ // API:
+ // break traversals
+ Controller.prototype['break'] = function () {
+ this.notify(BREAK);
+ };
+
+ // API:
+ // remove node
+ Controller.prototype.remove = function () {
+ this.notify(REMOVE);
+ };
+
+ Controller.prototype.__initialize = function(root, visitor) {
+ this.visitor = visitor;
+ this.root = root;
+ this.__worklist = [];
+ this.__leavelist = [];
+ this.__current = null;
+ this.__state = null;
+ this.__fallback = visitor.fallback === 'iteration';
+ this.__keys = VisitorKeys;
+ if (visitor.keys) {
+ this.__keys = extend(objectCreate(this.__keys), visitor.keys);
+ }
+ };
+
+ function isNode(node) {
+ if (node == null) {
+ return false;
+ }
+ return typeof node === 'object' && typeof node.type === 'string';
+ }
+
+ function isProperty(nodeType, key) {
+ return (nodeType === Syntax.ObjectExpression || nodeType === Syntax.ObjectPattern) && 'properties' === key;
+ }
+
+ Controller.prototype.traverse = function traverse(root, visitor) {
+ var worklist,
+ leavelist,
+ element,
+ node,
+ nodeType,
+ ret,
+ key,
+ current,
+ current2,
+ candidates,
+ candidate,
+ sentinel;
+
+ this.__initialize(root, visitor);
+
+ sentinel = {};
+
+ // reference
+ worklist = this.__worklist;
+ leavelist = this.__leavelist;
+
+ // initialize
+ worklist.push(new Element(root, null, null, null));
+ leavelist.push(new Element(null, null, null, null));
+
+ while (worklist.length) {
+ element = worklist.pop();
+
+ if (element === sentinel) {
+ element = leavelist.pop();
+
+ ret = this.__execute(visitor.leave, element);
+
+ if (this.__state === BREAK || ret === BREAK) {
+ return;
+ }
+ continue;
+ }
+
+ if (element.node) {
+
+ ret = this.__execute(visitor.enter, element);
+
+ if (this.__state === BREAK || ret === BREAK) {
+ return;
+ }
+
+ worklist.push(sentinel);
+ leavelist.push(element);
+
+ if (this.__state === SKIP || ret === SKIP) {
+ continue;
+ }
+
+ node = element.node;
+ nodeType = element.wrap || node.type;
+ candidates = this.__keys[nodeType];
+ if (!candidates) {
+ if (this.__fallback) {
+ candidates = objectKeys(node);
+ } else {
+ throw new Error('Unknown node type ' + nodeType + '.');
+ }
+ }
+
+ current = candidates.length;
+ while ((current -= 1) >= 0) {
+ key = candidates[current];
+ candidate = node[key];
+ if (!candidate) {
+ continue;
+ }
+
+ if (isArray(candidate)) {
+ current2 = candidate.length;
+ while ((current2 -= 1) >= 0) {
+ if (!candidate[current2]) {
+ continue;
+ }
+ if (isProperty(nodeType, candidates[current])) {
+ element = new Element(candidate[current2], [key, current2], 'Property', null);
+ } else if (isNode(candidate[current2])) {
+ element = new Element(candidate[current2], [key, current2], null, null);
+ } else {
+ continue;
+ }
+ worklist.push(element);
+ }
+ } else if (isNode(candidate)) {
+ worklist.push(new Element(candidate, key, null, null));
+ }
+ }
+ }
+ }
+ };
+
+ Controller.prototype.replace = function replace(root, visitor) {
+ function removeElem(element) {
+ var i,
+ key,
+ nextElem,
+ parent;
+
+ if (element.ref.remove()) {
+ // When the reference is an element of an array.
+ key = element.ref.key;
+ parent = element.ref.parent;
+
+ // If removed from array, then decrease following items' keys.
+ i = worklist.length;
+ while (i--) {
+ nextElem = worklist[i];
+ if (nextElem.ref && nextElem.ref.parent === parent) {
+ if (nextElem.ref.key < key) {
+ break;
+ }
+ --nextElem.ref.key;
+ }
+ }
+ }
+ }
+
+ var worklist,
+ leavelist,
+ node,
+ nodeType,
+ target,
+ element,
+ current,
+ current2,
+ candidates,
+ candidate,
+ sentinel,
+ outer,
+ key;
+
+ this.__initialize(root, visitor);
+
+ sentinel = {};
+
+ // reference
+ worklist = this.__worklist;
+ leavelist = this.__leavelist;
+
+ // initialize
+ outer = {
+ root: root
+ };
+ element = new Element(root, null, null, new Reference(outer, 'root'));
+ worklist.push(element);
+ leavelist.push(element);
+
+ while (worklist.length) {
+ element = worklist.pop();
+
+ if (element === sentinel) {
+ element = leavelist.pop();
+
+ target = this.__execute(visitor.leave, element);
+
+ // node may be replaced with null,
+ // so distinguish between undefined and null in this place
+ if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
+ // replace
+ element.ref.replace(target);
+ }
+
+ if (this.__state === REMOVE || target === REMOVE) {
+ removeElem(element);
+ }
+
+ if (this.__state === BREAK || target === BREAK) {
+ return outer.root;
+ }
+ continue;
+ }
+
+ target = this.__execute(visitor.enter, element);
+
+ // node may be replaced with null,
+ // so distinguish between undefined and null in this place
+ if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
+ // replace
+ element.ref.replace(target);
+ element.node = target;
+ }
+
+ if (this.__state === REMOVE || target === REMOVE) {
+ removeElem(element);
+ element.node = null;
+ }
+
+ if (this.__state === BREAK || target === BREAK) {
+ return outer.root;
+ }
+
+ // node may be null
+ node = element.node;
+ if (!node) {
+ continue;
+ }
+
+ worklist.push(sentinel);
+ leavelist.push(element);
+
+ if (this.__state === SKIP || target === SKIP) {
+ continue;
+ }
+
+ nodeType = element.wrap || node.type;
+ candidates = this.__keys[nodeType];
+ if (!candidates) {
+ if (this.__fallback) {
+ candidates = objectKeys(node);
+ } else {
+ throw new Error('Unknown node type ' + nodeType + '.');
+ }
+ }
+
+ current = candidates.length;
+ while ((current -= 1) >= 0) {
+ key = candidates[current];
+ candidate = node[key];
+ if (!candidate) {
+ continue;
+ }
+
+ if (isArray(candidate)) {
+ current2 = candidate.length;
+ while ((current2 -= 1) >= 0) {
+ if (!candidate[current2]) {
+ continue;
+ }
+ if (isProperty(nodeType, candidates[current])) {
+ element = new Element(candidate[current2], [key, current2], 'Property', new Reference(candidate, current2));
+ } else if (isNode(candidate[current2])) {
+ element = new Element(candidate[current2], [key, current2], null, new Reference(candidate, current2));
+ } else {
+ continue;
+ }
+ worklist.push(element);
+ }
+ } else if (isNode(candidate)) {
+ worklist.push(new Element(candidate, key, null, new Reference(node, key)));
+ }
+ }
+ }
+
+ return outer.root;
+ };
+
+ function traverse(root, visitor) {
+ var controller = new Controller();
+ return controller.traverse(root, visitor);
+ }
+
+ function replace(root, visitor) {
+ var controller = new Controller();
+ return controller.replace(root, visitor);
+ }
+
+ function extendCommentRange(comment, tokens) {
+ var target;
+
+ target = upperBound(tokens, function search(token) {
+ return token.range[0] > comment.range[0];
+ });
+
+ comment.extendedRange = [comment.range[0], comment.range[1]];
+
+ if (target !== tokens.length) {
+ comment.extendedRange[1] = tokens[target].range[0];
+ }
+
+ target -= 1;
+ if (target >= 0) {
+ comment.extendedRange[0] = tokens[target].range[1];
+ }
+
+ return comment;
+ }
+
+ function attachComments(tree, providedComments, tokens) {
+ // At first, we should calculate extended comment ranges.
+ var comments = [], comment, len, i, cursor;
+
+ if (!tree.range) {
+ throw new Error('attachComments needs range information');
+ }
+
+ // tokens array is empty, we attach comments to tree as 'leadingComments'
+ if (!tokens.length) {
+ if (providedComments.length) {
+ for (i = 0, len = providedComments.length; i < len; i += 1) {
+ comment = deepCopy(providedComments[i]);
+ comment.extendedRange = [0, tree.range[0]];
+ comments.push(comment);
+ }
+ tree.leadingComments = comments;
+ }
+ return tree;
+ }
+
+ for (i = 0, len = providedComments.length; i < len; i += 1) {
+ comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
+ }
+
+ // This is based on John Freeman's implementation.
+ cursor = 0;
+ traverse(tree, {
+ enter: function (node) {
+ var comment;
+
+ while (cursor < comments.length) {
+ comment = comments[cursor];
+ if (comment.extendedRange[1] > node.range[0]) {
+ break;
+ }
+
+ if (comment.extendedRange[1] === node.range[0]) {
+ if (!node.leadingComments) {
+ node.leadingComments = [];
+ }
+ node.leadingComments.push(comment);
+ comments.splice(cursor, 1);
+ } else {
+ cursor += 1;
+ }
+ }
+
+ // already out of owned node
+ if (cursor === comments.length) {
+ return VisitorOption.Break;
+ }
+
+ if (comments[cursor].extendedRange[0] > node.range[1]) {
+ return VisitorOption.Skip;
+ }
+ }
+ });
+
+ cursor = 0;
+ traverse(tree, {
+ leave: function (node) {
+ var comment;
+
+ while (cursor < comments.length) {
+ comment = comments[cursor];
+ if (node.range[1] < comment.extendedRange[0]) {
+ break;
+ }
+
+ if (node.range[1] === comment.extendedRange[0]) {
+ if (!node.trailingComments) {
+ node.trailingComments = [];
+ }
+ node.trailingComments.push(comment);
+ comments.splice(cursor, 1);
+ } else {
+ cursor += 1;
+ }
+ }
+
+ // already out of owned node
+ if (cursor === comments.length) {
+ return VisitorOption.Break;
+ }
+
+ if (comments[cursor].extendedRange[0] > node.range[1]) {
+ return VisitorOption.Skip;
+ }
+ }
+ });
+
+ return tree;
+ }
+
+ exports.version = require('./package.json').version;
+ exports.Syntax = Syntax;
+ exports.traverse = traverse;
+ exports.replace = replace;
+ exports.attachComments = attachComments;
+ exports.VisitorKeys = VisitorKeys;
+ exports.VisitorOption = VisitorOption;
+ exports.Controller = Controller;
+ exports.cloneEnvironment = function () { return clone({}); };
+
+ return exports;
+}(exports));
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+},{"./package.json":86}],86:[function(require,module,exports){
module.exports={
- "name": "esrecurse",
- "description": "ECMAScript scope analyzer",
- "homepage": "http://github.com/estools/esrecurse",
- "main": "esrecurse.js",
- "version": "1.2.0",
+ "_args": [
+ [
+ "estraverse@~3.1.0",
+ "/Users/force/code/eslint/node_modules/esrecurse"
+ ]
+ ],
+ "_from": "estraverse@>=3.1.0 <3.2.0",
+ "_id": "estraverse@3.1.0",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/esrecurse/estraverse",
+ "_npmUser": {
+ "email": "utatane.tea@gmail.com",
+ "name": "constellation"
+ },
+ "_npmVersion": "2.0.0-alpha-5",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "estraverse",
+ "raw": "estraverse@~3.1.0",
+ "rawSpec": "~3.1.0",
+ "scope": null,
+ "spec": ">=3.1.0 <3.2.0",
+ "type": "range"
+ },
+ "_requiredBy": [
+ "/esrecurse"
+ ],
+ "_resolved": "https://registry.npmjs.org/estraverse/-/estraverse-3.1.0.tgz",
+ "_shasum": "15e28a446b8b82bc700ccc8b96c78af4da0d6cba",
+ "_shrinkwrap": null,
+ "_spec": "estraverse@~3.1.0",
+ "_where": "/Users/force/code/eslint/node_modules/esrecurse",
+ "bugs": {
+ "url": "https://github.com/estools/estraverse/issues"
+ },
+ "dependencies": {},
+ "description": "ECMAScript JS AST traversal functions",
+ "devDependencies": {
+ "chai": "^2.1.1",
+ "coffee-script": "^1.8.0",
+ "espree": "^1.11.0",
+ "gulp": "^3.8.10",
+ "gulp-bump": "^0.2.2",
+ "gulp-filter": "^2.0.0",
+ "gulp-git": "^1.0.1",
+ "gulp-tag-version": "^1.2.1",
+ "jshint": "^2.5.6",
+ "mocha": "^2.1.0"
+ },
+ "directories": {},
+ "dist": {
+ "shasum": "15e28a446b8b82bc700ccc8b96c78af4da0d6cba",
+ "tarball": "http://registry.npmjs.org/estraverse/-/estraverse-3.1.0.tgz"
+ },
"engines": {
"node": ">=0.10.0"
},
+ "gitHead": "166ebbe0a8d45ceb2391b6f5ef5d1bab6bfb267a",
+ "homepage": "https://github.com/estools/estraverse",
+ "licenses": [
+ {
+ "type": "BSD",
+ "url": "http://github.com/estools/estraverse/raw/master/LICENSE.BSD"
+ }
+ ],
+ "main": "estraverse.js",
"maintainers": [
{
"name": "constellation",
"email": "utatane.tea@gmail.com"
+ },
+ {
+ "name": "michaelficarra",
+ "email": "npm@michael.ficarra.me"
}
],
+ "name": "estraverse",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
"repository": {
"type": "git",
- "url": "http://github.com/estools/esrecurse.git"
+ "url": "git+ssh://git@github.com/estools/estraverse.git"
},
+ "scripts": {
+ "lint": "jshint estraverse.js",
+ "test": "npm run-script lint && npm run-script unit-test",
+ "unit-test": "mocha --compilers coffee:coffee-script/register"
+ },
+ "version": "3.1.0"
+}
+
+},{}],87:[function(require,module,exports){
+module.exports={
+ "_args": [
+ [
+ "esrecurse@^3.1.1",
+ "/Users/force/code/eslint/node_modules/escope"
+ ]
+ ],
+ "_from": "esrecurse@>=3.1.1 <4.0.0",
+ "_id": "esrecurse@3.1.1",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/esrecurse",
+ "_npmUser": {
+ "email": "utatane.tea@gmail.com",
+ "name": "constellation"
+ },
+ "_npmVersion": "2.0.0-alpha-5",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "esrecurse",
+ "raw": "esrecurse@^3.1.1",
+ "rawSpec": "^3.1.1",
+ "scope": null,
+ "spec": ">=3.1.1 <4.0.0",
+ "type": "range"
+ },
+ "_requiredBy": [
+ "/escope"
+ ],
+ "_resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-3.1.1.tgz",
+ "_shasum": "8feb963699d4d1b2d65a576cd4b1296672a0f0e9",
+ "_shrinkwrap": null,
+ "_spec": "esrecurse@^3.1.1",
+ "_where": "/Users/force/code/eslint/node_modules/escope",
+ "bugs": {
+ "url": "https://github.com/estools/esrecurse/issues"
+ },
"dependencies": {
- "estraverse": ">=1.9.0"
+ "estraverse": "~3.1.0"
},
+ "description": "ECMAScript scope analyzer",
"devDependencies": {
- "chai": "~1.10.0",
- "coffee-script": "~1.8.0",
- "esprima": "~1.2.2",
+ "chai": "^2.1.1",
+ "coffee-script": "^1.9.1",
+ "esprima": "^2.1.0",
"gulp": "~3.8.10",
- "gulp-eslint": "^0.2.0",
+ "gulp-bump": "^0.2.2",
+ "gulp-eslint": "^0.6.0",
+ "gulp-filter": "^2.0.2",
+ "gulp-git": "^1.1.0",
"gulp-mocha": "~2.0.0",
+ "gulp-tag-version": "^1.2.1",
"jsdoc": "~3.3.0-alpha10",
"minimist": "^1.1.0"
},
+ "directories": {},
+ "dist": {
+ "shasum": "8feb963699d4d1b2d65a576cd4b1296672a0f0e9",
+ "tarball": "http://registry.npmjs.org/esrecurse/-/esrecurse-3.1.1.tgz"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "gitHead": "600a8aac5e7b313875a873134fd110b47a76fc77",
+ "homepage": "http://github.com/estools/esrecurse",
"licenses": [
{
"type": "BSD",
"url": "http://github.com/estools/esrecurse/raw/master/LICENSE.BSD"
}
],
- "scripts": {
- "test": "gulp travis",
- "unit-test": "gulp test",
- "lint": "gulp lint"
- },
- "gitHead": "9b363cee6d6b6b29b5236f4b98066ba0735fe9e4",
- "bugs": {
- "url": "https://github.com/estools/esrecurse/issues"
- },
- "_id": "esrecurse@1.2.0",
- "_shasum": "25e3b3ab76ad8a1da2d38e9393fd76b8456a706f",
- "_from": "esrecurse@>=1.2.0 <2.0.0",
- "_npmVersion": "2.0.0-alpha-5",
- "_npmUser": {
- "name": "constellation",
- "email": "utatane.tea@gmail.com"
- },
- "dist": {
- "shasum": "25e3b3ab76ad8a1da2d38e9393fd76b8456a706f",
- "tarball": "http://registry.npmjs.org/esrecurse/-/esrecurse-1.2.0.tgz"
- },
- "_resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-1.2.0.tgz",
- "readme": "ERROR: No README data found!"
-}
-
-},{}],123:[function(require,module,exports){
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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 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.
-
-module.exports = extend;
-function extend(origin, add) {
- // Don't do anything if add isn't an object
- if (!add || typeof add !== 'object') return origin;
-
- var keys = Object.keys(add);
- var i = keys.length;
- while (i--) {
- origin[keys[i]] = add[keys[i]];
- }
- return origin;
-}
-
-},{}],124:[function(require,module,exports){
-module.exports={
- "name": "escope",
- "description": "ECMAScript scope analyzer",
- "homepage": "http://github.com/estools/escope.html",
- "main": "escope.js",
- "version": "2.0.6",
- "engines": {
- "node": ">=0.4.0"
- },
+ "main": "esrecurse.js",
"maintainers": [
{
"name": "constellation",
"email": "utatane.tea@gmail.com"
+ },
+ {
+ "name": "michaelficarra",
+ "email": "npm@michael.ficarra.me"
}
],
+ "name": "esrecurse",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
"repository": {
"type": "git",
- "url": "http://github.com/estools/escope.git"
+ "url": "git+ssh://git@github.com/estools/esrecurse.git"
},
- "dependencies": {
- "es6-map": "^0.1.1",
- "es6-weak-map": "^0.1.2",
- "esrecurse": "^1.2.0",
- "estraverse": ">=1.9.0",
- "util-extend": "^1.0.1"
- },
- "devDependencies": {
- "browserify": "^7.0.0",
- "chai": "~1.10.0",
- "coffee-script": "~1.8.0",
- "esprima": "~1.2.2",
- "gulp": "~3.8.10",
- "gulp-eslint": "^0.2.0",
- "gulp-mocha": "~2.0.0",
- "jsdoc": "~3.3.0-alpha10",
- "minimist": "^1.1.0",
- "vinyl-source-stream": "^1.0.0"
- },
- "licenses": [
- {
- "type": "BSD",
- "url": "http://github.com/estools/escope/raw/master/LICENSE.BSD"
- }
- ],
"scripts": {
- "test": "gulp travis",
- "unit-test": "gulp test",
"lint": "gulp lint",
- "jsdoc": "jsdoc escope.js README.md"
+ "test": "gulp travis",
+ "unit-test": "gulp test"
},
- "gitHead": "dc4b85631e98011268fc426dd824c74e353d5b48",
- "bugs": {
- "url": "https://github.com/estools/escope/issues"
- },
- "_id": "escope@2.0.6",
- "_shasum": "c1bac24870605bb384ba073dce0417c9305eddeb",
- "_from": "escope@2.0.6",
- "_npmVersion": "1.4.28",
- "_npmUser": {
- "name": "constellation",
- "email": "utatane.tea@gmail.com"
- },
- "dist": {
- "shasum": "c1bac24870605bb384ba073dce0417c9305eddeb",
- "tarball": "http://registry.npmjs.org/escope/-/escope-2.0.6.tgz"
- },
- "_resolved": "https://registry.npmjs.org/escope/-/escope-2.0.6.tgz",
- "readme": "ERROR: No README data found!"
+ "version": "3.1.1"
}
-},{}],125:[function(require,module,exports){
-var estraverse = module.exports = require('estraverse');
-
-var VisitorKeys = require('./keys');
-
-for (var nodeType in VisitorKeys) {
- estraverse.Syntax[nodeType] = nodeType;
-
- var keys = VisitorKeys[nodeType];
-
- if (keys) {
- estraverse.VisitorKeys[nodeType] = keys;
- }
-}
-},{"./keys":126,"estraverse":127}],126:[function(require,module,exports){
+},{}],88:[function(require,module,exports){
var unprefixedKeys = {
Identifier: [],
NamespacedName: ['namespace', 'name'],
MemberExpression: ['object', 'property'],
EmptyExpression: [],
@@ -15157,11 +16572,11 @@
}
for (var key in flowKeys) {
exports[key] = flowKeys[key];
}
-},{}],127:[function(require,module,exports){
+},{}],89:[function(require,module,exports){
/*
Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
Redistribution and use in source and binary forms, with or without
@@ -15345,10 +16760,11 @@
ImportSpecifier: 'ImportSpecifier',
Literal: 'Literal',
LabeledStatement: 'LabeledStatement',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
+ MetaProperty: 'MetaProperty',
MethodDefinition: 'MethodDefinition',
ModuleSpecifier: 'ModuleSpecifier',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
ObjectPattern: 'ObjectPattern',
@@ -15356,10 +16772,11 @@
Property: 'Property',
RestElement: 'RestElement',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SpreadElement: 'SpreadElement',
+ Super: 'Super',
SwitchStatement: 'SwitchStatement',
SwitchCase: 'SwitchCase',
TaggedTemplateExpression: 'TaggedTemplateExpression',
TemplateElement: 'TemplateElement',
TemplateLiteral: 'TemplateLiteral',
@@ -15378,11 +16795,11 @@
VisitorKeys = {
AssignmentExpression: ['left', 'right'],
AssignmentPattern: ['left', 'right'],
ArrayExpression: ['elements'],
ArrayPattern: ['elements'],
- ArrowFunctionExpression: ['params', 'defaults', 'rest', 'body'],
+ ArrowFunctionExpression: ['params', 'body'],
AwaitExpression: ['argument'], // CAUTION: It's deferred to ES7.
BlockStatement: ['body'],
BinaryExpression: ['left', 'right'],
BreakStatement: ['label'],
CallExpression: ['callee', 'arguments'],
@@ -15404,12 +16821,12 @@
ExportSpecifier: ['exported', 'local'],
ExpressionStatement: ['expression'],
ForStatement: ['init', 'test', 'update', 'body'],
ForInStatement: ['left', 'right', 'body'],
ForOfStatement: ['left', 'right', 'body'],
- FunctionDeclaration: ['id', 'params', 'defaults', 'rest', 'body'],
- FunctionExpression: ['id', 'params', 'defaults', 'rest', 'body'],
+ FunctionDeclaration: ['id', 'params', 'body'],
+ FunctionExpression: ['id', 'params', 'body'],
GeneratorExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7.
Identifier: [],
IfStatement: ['test', 'consequent', 'alternate'],
ImportDeclaration: ['specifiers', 'source'],
ImportDefaultSpecifier: ['local'],
@@ -15417,10 +16834,11 @@
ImportSpecifier: ['imported', 'local'],
Literal: [],
LabeledStatement: ['label', 'body'],
LogicalExpression: ['left', 'right'],
MemberExpression: ['object', 'property'],
+ MetaProperty: ['meta', 'property'],
MethodDefinition: ['key', 'value'],
ModuleSpecifier: [],
NewExpression: ['callee', 'arguments'],
ObjectExpression: ['properties'],
ObjectPattern: ['properties'],
@@ -15428,18 +16846,19 @@
Property: ['key', 'value'],
RestElement: [ 'argument' ],
ReturnStatement: ['argument'],
SequenceExpression: ['expressions'],
SpreadElement: ['argument'],
+ Super: [],
SwitchStatement: ['discriminant', 'cases'],
SwitchCase: ['test', 'consequent'],
TaggedTemplateExpression: ['tag', 'quasi'],
TemplateElement: [],
TemplateLiteral: ['quasis', 'expressions'],
ThisExpression: [],
ThrowStatement: ['argument'],
- TryStatement: ['block', 'handlers', 'handler', 'guardedHandlers', 'finalizer'],
+ TryStatement: ['block', 'handler', 'finalizer'],
UnaryExpression: ['argument'],
UpdateExpression: ['argument'],
VariableDeclaration: ['declarations'],
VariableDeclarator: ['id', 'init'],
WhileStatement: ['test', 'body'],
@@ -15662,11 +17081,11 @@
if (this.__state === SKIP || ret === SKIP) {
continue;
}
node = element.node;
- nodeType = element.wrap || node.type;
+ nodeType = node.type || element.wrap;
candidates = this.__keys[nodeType];
if (!candidates) {
if (this.__fallback) {
candidates = objectKeys(node);
} else {
@@ -15816,11 +17235,11 @@
if (this.__state === SKIP || target === SKIP) {
continue;
}
- nodeType = element.wrap || node.type;
+ nodeType = node.type || element.wrap;
candidates = this.__keys[nodeType];
if (!candidates) {
if (this.__fallback) {
candidates = objectKeys(node);
} else {
@@ -15998,30 +17417,52 @@
return exports;
}(exports));
/* vim: set sw=4 ts=4 et tw=80 : */
-},{"./package.json":128}],128:[function(require,module,exports){
+},{"./package.json":90}],90:[function(require,module,exports){
module.exports={
- "name": "estraverse",
- "description": "ECMAScript JS AST traversal functions",
- "homepage": "https://github.com/estools/estraverse",
- "main": "estraverse.js",
- "version": "2.0.0",
- "engines": {
- "node": ">=0.10.0"
+ "_args": [
+ [
+ "estraverse@^4.1.1",
+ "/Users/force/code/eslint"
+ ]
+ ],
+ "_from": "estraverse@>=4.1.1 <5.0.0",
+ "_id": "estraverse@4.1.1",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/estraverse",
+ "_nodeVersion": "4.1.1",
+ "_npmUser": {
+ "email": "utatane.tea@gmail.com",
+ "name": "constellation"
},
- "maintainers": [
- {
- "name": "constellation",
- "email": "utatane.tea@gmail.com"
- }
+ "_npmVersion": "2.14.4",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "estraverse",
+ "raw": "estraverse@^4.1.1",
+ "rawSpec": "^4.1.1",
+ "scope": null,
+ "spec": ">=4.1.1 <5.0.0",
+ "type": "range"
+ },
+ "_requiredBy": [
+ "/",
+ "/escope"
],
- "repository": {
- "type": "git",
- "url": "http://github.com/estools/estraverse.git"
+ "_resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz",
+ "_shasum": "f6caca728933a850ef90661d0e17982ba47111a2",
+ "_shrinkwrap": null,
+ "_spec": "estraverse@^4.1.1",
+ "_where": "/Users/force/code/eslint",
+ "bugs": {
+ "url": "https://github.com/estools/estraverse/issues"
},
+ "dependencies": {},
+ "description": "ECMAScript JS AST traversal functions",
"devDependencies": {
"chai": "^2.1.1",
"coffee-script": "^1.8.0",
"espree": "^1.11.0",
"gulp": "^3.8.10",
@@ -16030,54 +17471,885 @@
"gulp-git": "^1.0.1",
"gulp-tag-version": "^1.2.1",
"jshint": "^2.5.6",
"mocha": "^2.1.0"
},
- "licenses": [
+ "directories": {},
+ "dist": {
+ "shasum": "f6caca728933a850ef90661d0e17982ba47111a2",
+ "tarball": "http://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "gitHead": "bbcccbfe98296585e4311c8755e1d00dcd581e3c",
+ "homepage": "https://github.com/estools/estraverse",
+ "license": "BSD-2-Clause",
+ "main": "estraverse.js",
+ "maintainers": [
{
- "type": "BSD",
- "url": "http://github.com/estools/estraverse/raw/master/LICENSE.BSD"
+ "name": "constellation",
+ "email": "utatane.tea@gmail.com"
+ },
+ {
+ "name": "michaelficarra",
+ "email": "npm@michael.ficarra.me"
+ },
+ {
+ "name": "nzakas",
+ "email": "nicholas@nczconsulting.com"
}
],
+ "name": "estraverse",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/estools/estraverse.git"
+ },
"scripts": {
- "test": "npm run-script lint && npm run-script unit-test",
"lint": "jshint estraverse.js",
+ "test": "npm run-script lint && npm run-script unit-test",
"unit-test": "mocha --compilers coffee:coffee-script/register"
},
- "gitHead": "d8bc726f126817cc03c7a4e751528edb19db0ffb",
- "bugs": {
- "url": "https://github.com/estools/estraverse/issues"
- },
- "_id": "estraverse@2.0.0",
- "_shasum": "5ae46963243600206674ccb24a09e16674fcdca1",
- "_from": "estraverse@>=2.0.0 <3.0.0",
- "_npmVersion": "2.0.0-alpha-5",
- "_npmUser": {
- "name": "constellation",
- "email": "utatane.tea@gmail.com"
- },
- "dist": {
- "shasum": "5ae46963243600206674ccb24a09e16674fcdca1",
- "tarball": "http://registry.npmjs.org/estraverse/-/estraverse-2.0.0.tgz"
- },
- "_resolved": "https://registry.npmjs.org/estraverse/-/estraverse-2.0.0.tgz",
- "readme": "ERROR: No README data found!"
+ "version": "4.1.1"
}
-},{}],129:[function(require,module,exports){
+},{}],91:[function(require,module,exports){
+arguments[4][13][0].apply(exports,arguments)
+},{"dup":13}],92:[function(require,module,exports){
+/*
+ Copyright (C) 2013-2014 Yusuke Suzuki <utatane.tea@gmail.com>
+ Copyright (C) 2014 Ivan Nikulin <ifaaan@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+(function () {
+ 'use strict';
+
+ var ES6Regex, ES5Regex, NON_ASCII_WHITESPACES, IDENTIFIER_START, IDENTIFIER_PART, ch;
+
+ // See `tools/generate-identifier-regex.js`.
+ ES5Regex = {
+ // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierStart:
+ NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/,
+ // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierPart:
+ NonAsciiIdentifierPart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/
+ };
+
+ ES6Regex = {
+ // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart:
+ NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/,
+ // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart:
+ NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
+ };
+
+ function isDecimalDigit(ch) {
+ return 0x30 <= ch && ch <= 0x39; // 0..9
+ }
+
+ function isHexDigit(ch) {
+ return 0x30 <= ch && ch <= 0x39 || // 0..9
+ 0x61 <= ch && ch <= 0x66 || // a..f
+ 0x41 <= ch && ch <= 0x46; // A..F
+ }
+
+ function isOctalDigit(ch) {
+ return ch >= 0x30 && ch <= 0x37; // 0..7
+ }
+
+ // 7.2 White Space
+
+ NON_ASCII_WHITESPACES = [
+ 0x1680, 0x180E,
+ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A,
+ 0x202F, 0x205F,
+ 0x3000,
+ 0xFEFF
+ ];
+
+ function isWhiteSpace(ch) {
+ return ch === 0x20 || ch === 0x09 || ch === 0x0B || ch === 0x0C || ch === 0xA0 ||
+ ch >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(ch) >= 0;
+ }
+
+ // 7.3 Line Terminators
+
+ function isLineTerminator(ch) {
+ return ch === 0x0A || ch === 0x0D || ch === 0x2028 || ch === 0x2029;
+ }
+
+ // 7.6 Identifier Names and Identifiers
+
+ function fromCodePoint(cp) {
+ if (cp <= 0xFFFF) { return String.fromCharCode(cp); }
+ var cu1 = String.fromCharCode(Math.floor((cp - 0x10000) / 0x400) + 0xD800);
+ var cu2 = String.fromCharCode(((cp - 0x10000) % 0x400) + 0xDC00);
+ return cu1 + cu2;
+ }
+
+ IDENTIFIER_START = new Array(0x80);
+ for(ch = 0; ch < 0x80; ++ch) {
+ IDENTIFIER_START[ch] =
+ ch >= 0x61 && ch <= 0x7A || // a..z
+ ch >= 0x41 && ch <= 0x5A || // A..Z
+ ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore)
+ }
+
+ IDENTIFIER_PART = new Array(0x80);
+ for(ch = 0; ch < 0x80; ++ch) {
+ IDENTIFIER_PART[ch] =
+ ch >= 0x61 && ch <= 0x7A || // a..z
+ ch >= 0x41 && ch <= 0x5A || // A..Z
+ ch >= 0x30 && ch <= 0x39 || // 0..9
+ ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore)
+ }
+
+ function isIdentifierStartES5(ch) {
+ return ch < 0x80 ? IDENTIFIER_START[ch] : ES5Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch));
+ }
+
+ function isIdentifierPartES5(ch) {
+ return ch < 0x80 ? IDENTIFIER_PART[ch] : ES5Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch));
+ }
+
+ function isIdentifierStartES6(ch) {
+ return ch < 0x80 ? IDENTIFIER_START[ch] : ES6Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch));
+ }
+
+ function isIdentifierPartES6(ch) {
+ return ch < 0x80 ? IDENTIFIER_PART[ch] : ES6Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch));
+ }
+
+ module.exports = {
+ isDecimalDigit: isDecimalDigit,
+ isHexDigit: isHexDigit,
+ isOctalDigit: isOctalDigit,
+ isWhiteSpace: isWhiteSpace,
+ isLineTerminator: isLineTerminator,
+ isIdentifierStartES5: isIdentifierStartES5,
+ isIdentifierPartES5: isIdentifierPartES5,
+ isIdentifierStartES6: isIdentifierStartES6,
+ isIdentifierPartES6: isIdentifierPartES6
+ };
+}());
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+},{}],93:[function(require,module,exports){
+/*
+ Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+(function () {
+ 'use strict';
+
+ var code = require('./code');
+
+ function isStrictModeReservedWordES6(id) {
+ switch (id) {
+ case 'implements':
+ case 'interface':
+ case 'package':
+ case 'private':
+ case 'protected':
+ case 'public':
+ case 'static':
+ case 'let':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function isKeywordES5(id, strict) {
+ // yield should not be treated as keyword under non-strict mode.
+ if (!strict && id === 'yield') {
+ return false;
+ }
+ return isKeywordES6(id, strict);
+ }
+
+ function isKeywordES6(id, strict) {
+ if (strict && isStrictModeReservedWordES6(id)) {
+ return true;
+ }
+
+ switch (id.length) {
+ case 2:
+ return (id === 'if') || (id === 'in') || (id === 'do');
+ case 3:
+ return (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
+ case 4:
+ return (id === 'this') || (id === 'else') || (id === 'case') ||
+ (id === 'void') || (id === 'with') || (id === 'enum');
+ case 5:
+ return (id === 'while') || (id === 'break') || (id === 'catch') ||
+ (id === 'throw') || (id === 'const') || (id === 'yield') ||
+ (id === 'class') || (id === 'super');
+ case 6:
+ return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
+ (id === 'switch') || (id === 'export') || (id === 'import');
+ case 7:
+ return (id === 'default') || (id === 'finally') || (id === 'extends');
+ case 8:
+ return (id === 'function') || (id === 'continue') || (id === 'debugger');
+ case 10:
+ return (id === 'instanceof');
+ default:
+ return false;
+ }
+ }
+
+ function isReservedWordES5(id, strict) {
+ return id === 'null' || id === 'true' || id === 'false' || isKeywordES5(id, strict);
+ }
+
+ function isReservedWordES6(id, strict) {
+ return id === 'null' || id === 'true' || id === 'false' || isKeywordES6(id, strict);
+ }
+
+ function isRestrictedWord(id) {
+ return id === 'eval' || id === 'arguments';
+ }
+
+ function isIdentifierNameES5(id) {
+ var i, iz, ch;
+
+ if (id.length === 0) { return false; }
+
+ ch = id.charCodeAt(0);
+ if (!code.isIdentifierStartES5(ch)) {
+ return false;
+ }
+
+ for (i = 1, iz = id.length; i < iz; ++i) {
+ ch = id.charCodeAt(i);
+ if (!code.isIdentifierPartES5(ch)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function decodeUtf16(lead, trail) {
+ return (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
+ }
+
+ function isIdentifierNameES6(id) {
+ var i, iz, ch, lowCh, check;
+
+ if (id.length === 0) { return false; }
+
+ check = code.isIdentifierStartES6;
+ for (i = 0, iz = id.length; i < iz; ++i) {
+ ch = id.charCodeAt(i);
+ if (0xD800 <= ch && ch <= 0xDBFF) {
+ ++i;
+ if (i >= iz) { return false; }
+ lowCh = id.charCodeAt(i);
+ if (!(0xDC00 <= lowCh && lowCh <= 0xDFFF)) {
+ return false;
+ }
+ ch = decodeUtf16(ch, lowCh);
+ }
+ if (!check(ch)) {
+ return false;
+ }
+ check = code.isIdentifierPartES6;
+ }
+ return true;
+ }
+
+ function isIdentifierES5(id, strict) {
+ return isIdentifierNameES5(id) && !isReservedWordES5(id, strict);
+ }
+
+ function isIdentifierES6(id, strict) {
+ return isIdentifierNameES6(id) && !isReservedWordES6(id, strict);
+ }
+
+ module.exports = {
+ isKeywordES5: isKeywordES5,
+ isKeywordES6: isKeywordES6,
+ isReservedWordES5: isReservedWordES5,
+ isReservedWordES6: isReservedWordES6,
+ isRestrictedWord: isRestrictedWord,
+ isIdentifierNameES5: isIdentifierNameES5,
+ isIdentifierNameES6: isIdentifierNameES6,
+ isIdentifierES5: isIdentifierES5,
+ isIdentifierES6: isIdentifierES6
+ };
+}());
+/* vim: set sw=4 ts=4 et tw=80 : */
+
+},{"./code":92}],94:[function(require,module,exports){
+arguments[4][16][0].apply(exports,arguments)
+},{"./ast":91,"./code":92,"./keyword":93,"dup":16}],95:[function(require,module,exports){
+'use strict';
+
+var d = require('d')
+ , callable = require('es5-ext/object/valid-callable')
+
+ , apply = Function.prototype.apply, call = Function.prototype.call
+ , create = Object.create, defineProperty = Object.defineProperty
+ , defineProperties = Object.defineProperties
+ , hasOwnProperty = Object.prototype.hasOwnProperty
+ , descriptor = { configurable: true, enumerable: false, writable: true }
+
+ , on, once, off, emit, methods, descriptors, base;
+
+on = function (type, listener) {
+ var data;
+
+ callable(listener);
+
+ if (!hasOwnProperty.call(this, '__ee__')) {
+ data = descriptor.value = create(null);
+ defineProperty(this, '__ee__', descriptor);
+ descriptor.value = null;
+ } else {
+ data = this.__ee__;
+ }
+ if (!data[type]) data[type] = listener;
+ else if (typeof data[type] === 'object') data[type].push(listener);
+ else data[type] = [data[type], listener];
+
+ return this;
+};
+
+once = function (type, listener) {
+ var once, self;
+
+ callable(listener);
+ self = this;
+ on.call(this, type, once = function () {
+ off.call(self, type, once);
+ apply.call(listener, this, arguments);
+ });
+
+ once.__eeOnceListener__ = listener;
+ return this;
+};
+
+off = function (type, listener) {
+ var data, listeners, candidate, i;
+
+ callable(listener);
+
+ if (!hasOwnProperty.call(this, '__ee__')) return this;
+ data = this.__ee__;
+ if (!data[type]) return this;
+ listeners = data[type];
+
+ if (typeof listeners === 'object') {
+ for (i = 0; (candidate = listeners[i]); ++i) {
+ if ((candidate === listener) ||
+ (candidate.__eeOnceListener__ === listener)) {
+ if (listeners.length === 2) data[type] = listeners[i ? 0 : 1];
+ else listeners.splice(i, 1);
+ }
+ }
+ } else {
+ if ((listeners === listener) ||
+ (listeners.__eeOnceListener__ === listener)) {
+ delete data[type];
+ }
+ }
+
+ return this;
+};
+
+emit = function (type) {
+ var i, l, listener, listeners, args;
+
+ if (!hasOwnProperty.call(this, '__ee__')) return;
+ listeners = this.__ee__[type];
+ if (!listeners) return;
+
+ if (typeof listeners === 'object') {
+ l = arguments.length;
+ args = new Array(l - 1);
+ for (i = 1; i < l; ++i) args[i - 1] = arguments[i];
+
+ listeners = listeners.slice();
+ for (i = 0; (listener = listeners[i]); ++i) {
+ apply.call(listener, this, args);
+ }
+ } else {
+ switch (arguments.length) {
+ case 1:
+ call.call(listeners, this);
+ break;
+ case 2:
+ call.call(listeners, this, arguments[1]);
+ break;
+ case 3:
+ call.call(listeners, this, arguments[1], arguments[2]);
+ break;
+ default:
+ l = arguments.length;
+ args = new Array(l - 1);
+ for (i = 1; i < l; ++i) {
+ args[i - 1] = arguments[i];
+ }
+ apply.call(listeners, this, args);
+ }
+ }
+};
+
+methods = {
+ on: on,
+ once: once,
+ off: off,
+ emit: emit
+};
+
+descriptors = {
+ on: d(on),
+ once: d(once),
+ off: d(off),
+ emit: d(emit)
+};
+
+base = defineProperties({}, descriptors);
+
+module.exports = exports = function (o) {
+ return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
+};
+exports.methods = methods;
+
+},{"d":7,"es5-ext/object/valid-callable":44}],96:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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 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.
+
+function EventEmitter() {
+ this._events = this._events || {};
+ this._maxListeners = this._maxListeners || undefined;
+}
+module.exports = EventEmitter;
+
+// Backwards-compat with node 0.10.x
+EventEmitter.EventEmitter = EventEmitter;
+
+EventEmitter.prototype._events = undefined;
+EventEmitter.prototype._maxListeners = undefined;
+
+// By default EventEmitters will print a warning if more than 10 listeners are
+// added to it. This is a useful default which helps finding memory leaks.
+EventEmitter.defaultMaxListeners = 10;
+
+// Obviously not all Emitters should be limited to 10. This function allows
+// that to be increased. Set to zero for unlimited.
+EventEmitter.prototype.setMaxListeners = function(n) {
+ if (!isNumber(n) || n < 0 || isNaN(n))
+ throw TypeError('n must be a positive number');
+ this._maxListeners = n;
+ return this;
+};
+
+EventEmitter.prototype.emit = function(type) {
+ var er, handler, len, args, i, listeners;
+
+ if (!this._events)
+ this._events = {};
+
+ // If there is no 'error' event listener then throw.
+ if (type === 'error') {
+ if (!this._events.error ||
+ (isObject(this._events.error) && !this._events.error.length)) {
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ }
+ throw TypeError('Uncaught, unspecified "error" event.');
+ }
+ }
+
+ handler = this._events[type];
+
+ if (isUndefined(handler))
+ return false;
+
+ if (isFunction(handler)) {
+ switch (arguments.length) {
+ // fast cases
+ case 1:
+ handler.call(this);
+ break;
+ case 2:
+ handler.call(this, arguments[1]);
+ break;
+ case 3:
+ handler.call(this, arguments[1], arguments[2]);
+ break;
+ // slower
+ default:
+ args = Array.prototype.slice.call(arguments, 1);
+ handler.apply(this, args);
+ }
+ } else if (isObject(handler)) {
+ args = Array.prototype.slice.call(arguments, 1);
+ listeners = handler.slice();
+ len = listeners.length;
+ for (i = 0; i < len; i++)
+ listeners[i].apply(this, args);
+ }
+
+ return true;
+};
+
+EventEmitter.prototype.addListener = function(type, listener) {
+ var m;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events)
+ this._events = {};
+
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (this._events.newListener)
+ this.emit('newListener', type,
+ isFunction(listener.listener) ?
+ listener.listener : listener);
+
+ if (!this._events[type])
+ // Optimize the case of one listener. Don't need the extra array object.
+ this._events[type] = listener;
+ else if (isObject(this._events[type]))
+ // If we've already got an array, just append.
+ this._events[type].push(listener);
+ else
+ // Adding the second element, need to change to array.
+ this._events[type] = [this._events[type], listener];
+
+ // Check for listener leak
+ if (isObject(this._events[type]) && !this._events[type].warned) {
+ if (!isUndefined(this._maxListeners)) {
+ m = this._maxListeners;
+ } else {
+ m = EventEmitter.defaultMaxListeners;
+ }
+
+ if (m && m > 0 && this._events[type].length > m) {
+ this._events[type].warned = true;
+ console.error('(node) warning: possible EventEmitter memory ' +
+ 'leak detected. %d listeners added. ' +
+ 'Use emitter.setMaxListeners() to increase limit.',
+ this._events[type].length);
+ if (typeof console.trace === 'function') {
+ // not supported in IE 10
+ console.trace();
+ }
+ }
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.once = function(type, listener) {
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ var fired = false;
+
+ function g() {
+ this.removeListener(type, g);
+
+ if (!fired) {
+ fired = true;
+ listener.apply(this, arguments);
+ }
+ }
+
+ g.listener = listener;
+ this.on(type, g);
+
+ return this;
+};
+
+// emits a 'removeListener' event iff the listener was removed
+EventEmitter.prototype.removeListener = function(type, listener) {
+ var list, position, length, i;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events || !this._events[type])
+ return this;
+
+ list = this._events[type];
+ length = list.length;
+ position = -1;
+
+ if (list === listener ||
+ (isFunction(list.listener) && list.listener === listener)) {
+ delete this._events[type];
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+
+ } else if (isObject(list)) {
+ for (i = length; i-- > 0;) {
+ if (list[i] === listener ||
+ (list[i].listener && list[i].listener === listener)) {
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (list.length === 1) {
+ list.length = 0;
+ delete this._events[type];
+ } else {
+ list.splice(position, 1);
+ }
+
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.removeAllListeners = function(type) {
+ var key, listeners;
+
+ if (!this._events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!this._events.removeListener) {
+ if (arguments.length === 0)
+ this._events = {};
+ else if (this._events[type])
+ delete this._events[type];
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ for (key in this._events) {
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = {};
+ return this;
+ }
+
+ listeners = this._events[type];
+
+ if (isFunction(listeners)) {
+ this.removeListener(type, listeners);
+ } else if (listeners) {
+ // LIFO order
+ while (listeners.length)
+ this.removeListener(type, listeners[listeners.length - 1]);
+ }
+ delete this._events[type];
+
+ return this;
+};
+
+EventEmitter.prototype.listeners = function(type) {
+ var ret;
+ if (!this._events || !this._events[type])
+ ret = [];
+ else if (isFunction(this._events[type]))
+ ret = [this._events[type]];
+ else
+ ret = this._events[type].slice();
+ return ret;
+};
+
+EventEmitter.prototype.listenerCount = function(type) {
+ if (this._events) {
+ var evlistener = this._events[type];
+
+ if (isFunction(evlistener))
+ return 1;
+ else if (evlistener)
+ return evlistener.length;
+ }
+ return 0;
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ return emitter.listenerCount(type);
+};
+
+function isFunction(arg) {
+ return typeof arg === 'function';
+}
+
+function isNumber(arg) {
+ return typeof arg === 'number';
+}
+
+function isObject(arg) {
+ return typeof arg === 'object' && arg !== null;
+}
+
+function isUndefined(arg) {
+ return arg === void 0;
+}
+
+},{}],97:[function(require,module,exports){
+var util = require('util')
+
+var INDENT_START = /[\{\[]/
+var INDENT_END = /[\}\]]/
+
+module.exports = function() {
+ var lines = []
+ var indent = 0
+
+ var push = function(str) {
+ var spaces = ''
+ while (spaces.length < indent*2) spaces += ' '
+ lines.push(spaces+str)
+ }
+
+ var line = function(fmt) {
+ if (!fmt) return line
+
+ if (INDENT_END.test(fmt.trim()[0]) && INDENT_START.test(fmt[fmt.length-1])) {
+ indent--
+ push(util.format.apply(util, arguments))
+ indent++
+ return line
+ }
+ if (INDENT_START.test(fmt[fmt.length-1])) {
+ push(util.format.apply(util, arguments))
+ indent++
+ return line
+ }
+ if (INDENT_END.test(fmt.trim()[0])) {
+ indent--
+ push(util.format.apply(util, arguments))
+ return line
+ }
+
+ push(util.format.apply(util, arguments))
+ return line
+ }
+
+ line.toString = function() {
+ return lines.join('\n')
+ }
+
+ line.toFunction = function(scope) {
+ var src = 'return ('+line.toString()+')'
+
+ var keys = Object.keys(scope || {}).map(function(key) {
+ return key
+ })
+
+ var vals = keys.map(function(key) {
+ return scope[key]
+ })
+
+ return Function.apply(null, keys.concat(src)).apply(null, vals)
+ }
+
+ if (arguments.length) line.apply(null, arguments)
+
+ return line
+}
+
+},{"util":111}],98:[function(require,module,exports){
+var isProperty = require('is-property')
+
+var gen = function(obj, prop) {
+ return isProperty(prop) ? obj+'.'+prop : obj+'['+JSON.stringify(prop)+']'
+}
+
+gen.valid = isProperty
+gen.property = function (prop) {
+ return isProperty(prop) ? prop : JSON.stringify(prop)
+}
+
+module.exports = gen
+
+},{"is-property":104}],99:[function(require,module,exports){
module.exports={
"builtin": {
"Array": false,
"ArrayBuffer": false,
"Boolean": false,
"constructor": false,
+ "DataView": false,
"Date": false,
"decodeURI": false,
"decodeURIComponent": false,
"encodeURI": false,
"encodeURIComponent": false,
"Error": false,
+ "escape": false,
"eval": false,
"EvalError": false,
"Float32Array": false,
"Float64Array": false,
"Function": false,
@@ -16115,86 +18387,167 @@
"Uint16Array": false,
"Uint32Array": false,
"Uint8Array": false,
"Uint8ClampedArray": false,
"undefined": false,
+ "unescape": false,
"URIError": false,
"valueOf": false,
"WeakMap": false,
"WeakSet": false
},
- "nonstandard": {
- "escape": false,
- "unescape": false
- },
"browser": {
"addEventListener": false,
"alert": false,
+ "AnalyserNode": false,
+ "AnimationEvent": false,
"applicationCache": false,
+ "ApplicationCache": false,
+ "ApplicationCacheErrorEvent": false,
"atob": false,
+ "Attr": false,
"Audio": false,
+ "AudioBuffer": false,
+ "AudioBufferSourceNode": false,
+ "AudioContext": false,
+ "AudioDestinationNode": false,
+ "AudioListener": false,
+ "AudioNode": false,
+ "AudioParam": false,
"AudioProcessingEvent": false,
+ "AutocompleteErrorEvent": false,
+ "BarProp": false,
+ "BatteryManager": false,
"BeforeUnloadEvent": false,
+ "BiquadFilterNode": false,
"Blob": false,
"blur": false,
"btoa": false,
+ "Cache": false,
+ "caches": false,
+ "CacheStorage": false,
"cancelAnimationFrame": false,
"CanvasGradient": false,
"CanvasPattern": false,
"CanvasRenderingContext2D": false,
+ "CDATASection": false,
+ "ChannelMergerNode": false,
+ "ChannelSplitterNode": false,
+ "CharacterData": false,
"clearInterval": false,
"clearTimeout": false,
+ "clientInformation": false,
+ "ClientRect": false,
+ "ClientRectList": false,
+ "ClipboardEvent": false,
"close": false,
"closed": false,
"CloseEvent": false,
"Comment": false,
"CompositionEvent": false,
"confirm": false,
"console": false,
+ "ConvolverNode": false,
"crypto": false,
+ "Crypto": false,
+ "CryptoKey": false,
"CSS": false,
+ "CSSFontFaceRule": false,
+ "CSSImportRule": false,
+ "CSSKeyframeRule": false,
+ "CSSKeyframesRule": false,
+ "CSSMediaRule": false,
+ "CSSPageRule": false,
+ "CSSRule": false,
+ "CSSRuleList": false,
+ "CSSStyleDeclaration": false,
+ "CSSStyleRule": false,
+ "CSSStyleSheet": false,
+ "CSSSupportsRule": false,
+ "CSSUnknownRule": false,
+ "CSSViewportRule": false,
"CustomEvent": false,
- "DataView": false,
+ "DataTransfer": false,
+ "DataTransferItem": false,
+ "DataTransferItemList": false,
"Debug": false,
"defaultStatus": false,
+ "defaultstatus": false,
+ "DelayNode": false,
+ "DeviceMotionEvent": false,
+ "DeviceOrientationEvent": false,
"devicePixelRatio": false,
"dispatchEvent": false,
"document": false,
"Document": false,
"DocumentFragment": false,
+ "DocumentType": false,
+ "DOMError": false,
+ "DOMException": false,
+ "DOMImplementation": false,
"DOMParser": false,
+ "DOMSettableTokenList": false,
+ "DOMStringList": false,
+ "DOMStringMap": false,
+ "DOMTokenList": false,
"DragEvent": false,
+ "DynamicsCompressorNode": false,
"Element": false,
"ElementTimeControl": false,
"ErrorEvent": false,
"event": false,
"Event": false,
+ "EventSource": false,
+ "EventTarget": false,
+ "external": false,
+ "fetch": false,
+ "File": false,
+ "FileError": false,
+ "FileList": false,
"FileReader": false,
"find": false,
"focus": false,
"FocusEvent": false,
+ "FontFace": false,
"FormData": false,
"frameElement": false,
"frames": false,
+ "GainNode": false,
+ "Gamepad": false,
+ "GamepadButton": false,
"GamepadEvent": false,
"getComputedStyle": false,
"getSelection": false,
"HashChangeEvent": false,
+ "Headers": false,
"history": false,
+ "History": false,
+ "HTMLAllCollection": false,
"HTMLAnchorElement": false,
+ "HTMLAppletElement": false,
+ "HTMLAreaElement": false,
+ "HTMLAudioElement": false,
"HTMLBaseElement": false,
"HTMLBlockquoteElement": false,
"HTMLBodyElement": false,
"HTMLBRElement": false,
"HTMLButtonElement": false,
"HTMLCanvasElement": false,
+ "HTMLCollection": false,
+ "HTMLContentElement": false,
+ "HTMLDataListElement": false,
+ "HTMLDetailsElement": false,
+ "HTMLDialogElement": false,
"HTMLDirectoryElement": false,
"HTMLDivElement": false,
"HTMLDListElement": false,
+ "HTMLDocument": false,
"HTMLElement": false,
+ "HTMLEmbedElement": false,
"HTMLFieldSetElement": false,
"HTMLFontElement": false,
+ "HTMLFormControlsCollection": false,
"HTMLFormElement": false,
"HTMLFrameElement": false,
"HTMLFrameSetElement": false,
"HTMLHeadElement": false,
"HTMLHeadingElement": false,
@@ -16202,39 +18555,53 @@
"HTMLHtmlElement": false,
"HTMLIFrameElement": false,
"HTMLImageElement": false,
"HTMLInputElement": false,
"HTMLIsIndexElement": false,
+ "HTMLKeygenElement": false,
"HTMLLabelElement": false,
"HTMLLayerElement": false,
"HTMLLegendElement": false,
"HTMLLIElement": false,
"HTMLLinkElement": false,
"HTMLMapElement": false,
+ "HTMLMarqueeElement": false,
+ "HTMLMediaElement": false,
"HTMLMenuElement": false,
"HTMLMetaElement": false,
+ "HTMLMeterElement": false,
"HTMLModElement": false,
"HTMLObjectElement": false,
"HTMLOListElement": false,
"HTMLOptGroupElement": false,
"HTMLOptionElement": false,
+ "HTMLOptionsCollection": false,
+ "HTMLOutputElement": false,
"HTMLParagraphElement": false,
"HTMLParamElement": false,
+ "HTMLPictureElement": false,
"HTMLPreElement": false,
+ "HTMLProgressElement": false,
"HTMLQuoteElement": false,
"HTMLScriptElement": false,
"HTMLSelectElement": false,
+ "HTMLShadowElement": false,
+ "HTMLSourceElement": false,
+ "HTMLSpanElement": false,
"HTMLStyleElement": false,
"HTMLTableCaptionElement": false,
"HTMLTableCellElement": false,
"HTMLTableColElement": false,
"HTMLTableElement": false,
"HTMLTableRowElement": false,
"HTMLTableSectionElement": false,
+ "HTMLTemplateElement": false,
"HTMLTextAreaElement": false,
"HTMLTitleElement": false,
+ "HTMLTrackElement": false,
"HTMLUListElement": false,
+ "HTMLUnknownElement": false,
"HTMLVideoElement": false,
"IDBCursor": false,
"IDBCursorWithValue": false,
"IDBDatabase": false,
"IDBEnvironment": false,
@@ -16245,34 +18612,75 @@
"IDBOpenDBRequest": false,
"IDBRequest": false,
"IDBTransaction": false,
"IDBVersionChangeEvent": false,
"Image": false,
+ "ImageBitmap": false,
+ "ImageData": false,
"indexedDB": false,
"innerHeight": false,
"innerWidth": false,
"InputEvent": false,
+ "InputMethodContext": false,
"Intl": false,
"KeyboardEvent": false,
"length": false,
"localStorage": false,
"location": false,
+ "Location": false,
+ "locationbar": false,
"matchMedia": false,
+ "MediaElementAudioSourceNode": false,
+ "MediaEncryptedEvent": false,
+ "MediaError": false,
+ "MediaKeyError": false,
+ "MediaKeyEvent": false,
+ "MediaKeyMessageEvent": false,
+ "MediaKeys": false,
+ "MediaKeySession": false,
+ "MediaKeyStatusMap": false,
+ "MediaKeySystemAccess": false,
+ "MediaList": false,
+ "MediaQueryList": false,
+ "MediaQueryListEvent": false,
+ "MediaSource": false,
+ "MediaStreamAudioDestinationNode": false,
+ "MediaStreamAudioSourceNode": false,
+ "MediaStreamEvent": false,
+ "MediaStreamTrack": false,
+ "menubar": false,
"MessageChannel": false,
"MessageEvent": false,
"MessagePort": false,
+ "MIDIAccess": false,
+ "MIDIConnectionEvent": false,
+ "MIDIInput": false,
+ "MIDIInputMap": false,
+ "MIDIMessageEvent": false,
+ "MIDIOutput": false,
+ "MIDIOutputMap": false,
+ "MIDIPort": false,
+ "MimeType": false,
+ "MimeTypeArray": false,
"MouseEvent": false,
"moveBy": false,
"moveTo": false,
+ "MutationEvent": false,
"MutationObserver": false,
+ "MutationRecord": false,
"name": false,
+ "NamedNodeMap": false,
"navigator": false,
+ "Navigator": false,
"Node": false,
"NodeFilter": false,
+ "NodeIterator": false,
"NodeList": false,
"Notification": false,
"OfflineAudioCompletionEvent": false,
+ "OfflineAudioContext": false,
+ "offscreenBuffering": false,
"onbeforeunload": true,
"onblur": true,
"onerror": true,
"onfocus": true,
"onload": true,
@@ -16281,44 +18689,90 @@
"open": false,
"openDatabase": false,
"opener": false,
"opera": false,
"Option": false,
+ "OscillatorNode": false,
"outerHeight": false,
"outerWidth": false,
"PageTransitionEvent": false,
"pageXOffset": false,
"pageYOffset": false,
"parent": false,
+ "Path2D": false,
+ "performance": false,
+ "Performance": false,
+ "PerformanceEntry": false,
+ "PerformanceMark": false,
+ "PerformanceMeasure": false,
+ "PerformanceNavigation": false,
+ "PerformanceResourceTiming": false,
+ "PerformanceTiming": false,
+ "PeriodicWave": false,
+ "Permissions": false,
+ "PermissionStatus": false,
+ "personalbar": false,
+ "Plugin": false,
+ "PluginArray": false,
"PopStateEvent": false,
"postMessage": false,
"print": false,
+ "ProcessingInstruction": false,
"ProgressEvent": false,
"prompt": false,
+ "PushManager": false,
+ "PushSubscription": false,
+ "RadioNodeList": false,
"Range": false,
+ "ReadableByteStream": false,
+ "ReadableStream": false,
"removeEventListener": false,
+ "Request": false,
"requestAnimationFrame": false,
"resizeBy": false,
"resizeTo": false,
+ "Response": false,
+ "RTCIceCandidate": false,
+ "RTCSessionDescription": false,
"screen": false,
+ "Screen": false,
+ "screenLeft": false,
+ "ScreenOrientation": false,
+ "screenTop": false,
"screenX": false,
"screenY": false,
+ "ScriptProcessorNode": false,
"scroll": false,
"scrollbars": false,
"scrollBy": false,
"scrollTo": false,
"scrollX": false,
"scrollY": false,
+ "SecurityPolicyViolationEvent": false,
+ "Selection": false,
"self": false,
+ "ServiceWorker": false,
+ "ServiceWorkerContainer": false,
+ "ServiceWorkerRegistration": false,
"sessionStorage": false,
"setInterval": false,
"setTimeout": false,
+ "ShadowRoot": false,
"SharedWorker": false,
"showModalDialog": false,
+ "speechSynthesis": false,
+ "SpeechSynthesisEvent": false,
+ "SpeechSynthesisUtterance": false,
"status": false,
+ "statusbar": false,
"stop": false,
+ "Storage": false,
"StorageEvent": false,
+ "styleMedia": false,
+ "StyleSheet": false,
+ "StyleSheetList": false,
+ "SubtleCrypto": false,
"SVGAElement": false,
"SVGAltGlyphDefElement": false,
"SVGAltGlyphElement": false,
"SVGAltGlyphItemElement": false,
"SVGAngle": false,
@@ -16349,10 +18803,11 @@
"SVGComponentTransferFunctionElement": false,
"SVGCSSRule": false,
"SVGCursorElement": false,
"SVGDefsElement": false,
"SVGDescElement": false,
+ "SVGDiscardElement": false,
"SVGDocument": false,
"SVGElement": false,
"SVGElementInstance": false,
"SVGElementInstanceList": false,
"SVGEllipseElement": false,
@@ -16364,10 +18819,11 @@
"SVGFECompositeElement": false,
"SVGFEConvolveMatrixElement": false,
"SVGFEDiffuseLightingElement": false,
"SVGFEDisplacementMapElement": false,
"SVGFEDistantLightElement": false,
+ "SVGFEDropShadowElement": false,
"SVGFEFloodElement": false,
"SVGFEFuncAElement": false,
"SVGFEFuncBElement": false,
"SVGFEFuncGElement": false,
"SVGFEFuncRElement": false,
@@ -16391,13 +18847,15 @@
"SVGFontFaceNameElement": false,
"SVGFontFaceSrcElement": false,
"SVGFontFaceUriElement": false,
"SVGForeignObjectElement": false,
"SVGGElement": false,
+ "SVGGeometryElement": false,
"SVGGlyphElement": false,
"SVGGlyphRefElement": false,
"SVGGradientElement": false,
+ "SVGGraphicsElement": false,
"SVGHKernElement": false,
"SVGICCColor": false,
"SVGImageElement": false,
"SVGLangSpace": false,
"SVGLength": false,
@@ -16471,18 +18929,35 @@
"SVGUseElement": false,
"SVGViewElement": false,
"SVGViewSpec": false,
"SVGVKernElement": false,
"SVGZoomAndPan": false,
+ "SVGZoomEvent": false,
"Text": false,
"TextDecoder": false,
"TextEncoder": false,
+ "TextEvent": false,
+ "TextMetrics": false,
+ "TextTrack": false,
+ "TextTrackCue": false,
+ "TextTrackCueList": false,
+ "TextTrackList": false,
"TimeEvent": false,
+ "TimeRanges": false,
+ "toolbar": false,
"top": false,
+ "Touch": false,
"TouchEvent": false,
+ "TouchList": false,
+ "TrackEvent": false,
+ "TransitionEvent": false,
+ "TreeWalker": false,
"UIEvent": false,
"URL": false,
+ "ValidityState": false,
+ "VTTCue": false,
+ "WaveShaperNode": false,
"WebGLActiveInfo": false,
"WebGLBuffer": false,
"WebGLContextEvent": false,
"WebGLFramebuffer": false,
"WebGLProgram": false,
@@ -16496,44 +18971,116 @@
"WheelEvent": false,
"window": false,
"Window": false,
"Worker": false,
"XDomainRequest": false,
+ "XMLDocument": false,
"XMLHttpRequest": false,
+ "XMLHttpRequestEventTarget": false,
+ "XMLHttpRequestProgressEvent": false,
+ "XMLHttpRequestUpload": false,
"XMLSerializer": false,
"XPathEvaluator": false,
"XPathException": false,
"XPathExpression": false,
"XPathNamespace": false,
"XPathNSResolver": false,
- "XPathResult": false
+ "XPathResult": false,
+ "XSLTProcessor": false
},
"worker": {
+ "applicationCache": false,
+ "atob": false,
+ "BroadcastChannel": false,
+ "btoa": false,
+ "Cache": false,
+ "caches": false,
+ "clearInterval": false,
+ "clearTimeout": false,
+ "close": true,
+ "console": false,
+ "fetch": false,
+ "FileReaderSync": false,
+ "FormData": false,
+ "Headers": false,
+ "IDBCursor": false,
+ "IDBCursorWithValue": false,
+ "IDBDatabase": false,
+ "IDBFactory": false,
+ "IDBIndex": false,
+ "IDBKeyRange": false,
+ "IDBObjectStore": false,
+ "IDBOpenDBRequest": false,
+ "IDBRequest": false,
+ "IDBTransaction": false,
+ "IDBVersionChangeEvent": false,
+ "ImageData": false,
"importScripts": true,
+ "indexedDB": false,
+ "location": false,
+ "MessageChannel": false,
+ "MessagePort": false,
+ "name": false,
+ "navigator": false,
+ "Notification": false,
+ "onclose": true,
+ "onconnect": true,
+ "onerror": true,
+ "onlanguagechange": true,
+ "onmessage": true,
+ "onoffline": true,
+ "ononline": true,
+ "onrejectionhandled": true,
+ "onunhandledrejection": true,
+ "performance": false,
+ "Performance": false,
+ "PerformanceEntry": false,
+ "PerformanceMark": false,
+ "PerformanceMeasure": false,
+ "PerformanceNavigation": false,
+ "PerformanceResourceTiming": false,
+ "PerformanceTiming": false,
"postMessage": true,
- "self": true
+ "Promise": false,
+ "Request": false,
+ "Response": false,
+ "self": true,
+ "ServiceWorkerRegistration": false,
+ "setInterval": false,
+ "setTimeout": false,
+ "TextDecoder": false,
+ "TextEncoder": false,
+ "URL": false,
+ "WebSocket": false,
+ "Worker": false,
+ "XMLHttpRequest": false
},
"node": {
"__dirname": false,
"__filename": false,
"arguments": false,
"Buffer": false,
"clearImmediate": false,
"clearInterval": false,
"clearTimeout": false,
"console": false,
- "DataView": false,
"exports": true,
"GLOBAL": false,
"global": false,
"module": false,
"process": false,
"require": false,
+ "root": false,
"setImmediate": false,
"setInterval": false,
"setTimeout": false
},
+ "commonjs": {
+ "exports": true,
+ "module": false,
+ "require": false
+ },
"amd": {
"define": false,
"require": false
},
"mocha": {
@@ -16542,10 +19089,11 @@
"before": false,
"beforeEach": false,
"context": false,
"describe": false,
"it": false,
+ "mocha": false,
"setup": false,
"specify": false,
"suite": false,
"suiteSetup": false,
"suiteTeardown": false,
@@ -16574,18 +19122,31 @@
"waits": false,
"waitsFor": false,
"xdescribe": false,
"xit": false
},
+ "jest": {
+ "afterEach": false,
+ "beforeEach": false,
+ "describe": false,
+ "expect": false,
+ "it": false,
+ "jest": false,
+ "pit": false,
+ "require": false,
+ "xdescribe": false,
+ "xit": false
+ },
"qunit": {
"asyncTest": false,
"deepEqual": false,
"equal": false,
"expect": false,
"module": false,
"notDeepEqual": false,
"notEqual": false,
+ "notOk": false,
"notPropEqual": false,
"notStrictEqual": false,
"ok": false,
"propEqual": false,
"QUnit": false,
@@ -16637,10 +19198,30 @@
"spawn": false,
"sync": false,
"toint32": false,
"version": false
},
+ "nashorn": {
+ "__DIR__": false,
+ "__FILE__": false,
+ "__LINE__": false,
+ "com": false,
+ "edu": false,
+ "exit": false,
+ "Java": false,
+ "java": false,
+ "javafx": false,
+ "JavaImporter": false,
+ "javax": false,
+ "JSAdapter": false,
+ "load": false,
+ "loadWithNewGlobal": false,
+ "org": false,
+ "Packages": false,
+ "print": false,
+ "quit": false
+ },
"wsh": {
"ActiveXObject": true,
"Enumerator": true,
"GetObject": true,
"ScriptEngine": true,
@@ -16792,91 +19373,2223 @@
"rs": false,
"sh": false,
"UUID": false,
"version": false,
"WriteResult": false
+ },
+ "applescript": {
+ "$": false,
+ "Application": false,
+ "Automation": false,
+ "console": false,
+ "delay": false,
+ "Library": false,
+ "ObjC": false,
+ "ObjectSpecifier": false,
+ "Path": false,
+ "Progress": false,
+ "Ref": false
+ },
+ "serviceworker": {
+ "caches": false,
+ "Cache": false,
+ "CacheStorage": false,
+ "Client": false,
+ "clients": false,
+ "Clients": false,
+ "ExtendableEvent": false,
+ "ExtendableMessageEvent": false,
+ "FetchEvent": false,
+ "importScripts": false,
+ "registration": false,
+ "self": false,
+ "ServiceWorker": false,
+ "ServiceWorkerContainer": false,
+ "ServiceWorkerGlobalScope": false,
+ "ServiceWorkerMessageEvent": false,
+ "ServiceWorkerRegistration": false,
+ "skipWaiting": false,
+ "WindowClient": false
+ },
+ "embertest": {
+ "andThen": false,
+ "click": false,
+ "currentPath": false,
+ "currentRouteName": false,
+ "currentURL": false,
+ "fillIn": false,
+ "find": false,
+ "keyEvent": false,
+ "triggerEvent": false,
+ "visit": false
+ },
+ "protractor": {
+ "$": false,
+ "$$": false,
+ "browser": false,
+ "By": false,
+ "by": false,
+ "DartObject": false,
+ "element": false,
+ "protractor": false
+ },
+ "shared-node-browser": {
+ "clearInterval": false,
+ "clearTimeout": false,
+ "console": false,
+ "setInterval": false,
+ "setTimeout": false
+ },
+ "webextensions": {
+ "browser": false,
+ "chrome": false,
+ "opr": false
}
}
-},{}],130:[function(require,module,exports){
+},{}],100:[function(require,module,exports){
module.exports = require('./globals.json');
-},{"./globals.json":129}],131:[function(require,module,exports){
+},{"./globals.json":99}],101:[function(require,module,exports){
+if (typeof Object.create === 'function') {
+ // implementation from standard node.js 'util' module
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ };
+} else {
+ // old school shim for old browsers
+ module.exports = function inherits(ctor, superCtor) {
+ ctor.super_ = superCtor
+ var TempCtor = function () {}
+ TempCtor.prototype = superCtor.prototype
+ ctor.prototype = new TempCtor()
+ ctor.prototype.constructor = ctor
+ }
+}
+
+},{}],102:[function(require,module,exports){
+exports['date-time'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}[tT ]\d{2}:\d{2}:\d{2}(\.\d+)?([zZ]|[+-]\d{2}:\d{2})$/
+exports['date'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/
+exports['time'] = /^\d{2}:\d{2}:\d{2}$/
+exports['email'] = /^\S+@\S+$/
+exports['ip-address'] = exports['ipv4'] = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
+exports['ipv6'] = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
+exports['uri'] = /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/
+exports['color'] = /(#?([0-9A-Fa-f]{3,6})\b)|(aqua)|(black)|(blue)|(fuchsia)|(gray)|(green)|(lime)|(maroon)|(navy)|(olive)|(orange)|(purple)|(red)|(silver)|(teal)|(white)|(yellow)|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\))/
+exports['hostname'] = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$/
+exports['alpha'] = /^[a-zA-Z]+$/
+exports['alphanumeric'] = /^[a-zA-Z0-9]+$/
+exports['style'] = /\s*(.+?):\s*([^;]+);?/g
+exports['phone'] = /^\+(?:[0-9] ?){6,14}[0-9]$/
+exports['utc-millisec'] = /^[0-9]+(\.?[0-9]+)?$/
+
+},{}],103:[function(require,module,exports){
+var genobj = require('generate-object-property')
+var genfun = require('generate-function')
+var jsonpointer = require('jsonpointer')
+var xtend = require('xtend')
+var formats = require('./formats')
+
+var get = function(obj, additionalSchemas, ptr) {
+ if (/^https?:\/\//.test(ptr)) return null
+
+ var visit = function(sub) {
+ if (sub && sub.id === ptr) return sub
+ if (typeof sub !== 'object' || !sub) return null
+ return Object.keys(sub).reduce(function(res, k) {
+ return res || visit(sub[k])
+ }, null)
+ }
+
+ var res = visit(obj)
+ if (res) return res
+
+ ptr = ptr.replace(/^#/, '')
+ ptr = ptr.replace(/\/$/, '')
+
+ try {
+ return jsonpointer.get(obj, decodeURI(ptr))
+ } catch (err) {
+ var end = ptr.indexOf('#')
+ var other
+ // external reference
+ if (end !== 0) {
+ // fragment doesn't exist.
+ if (end === -1) {
+ other = additionalSchemas[ptr]
+ } else {
+ var ext = ptr.slice(0, end)
+ other = additionalSchemas[ext]
+ var fragment = ptr.slice(end).replace(/^#/, '')
+ try {
+ return jsonpointer.get(other, fragment)
+ } catch (err) {}
+ }
+ } else {
+ other = additionalSchemas[ptr]
+ }
+ return other || null
+ }
+}
+
+var formatName = function(field) {
+ field = JSON.stringify(field)
+ var pattern = /\[([^\[\]"]+)\]/
+ while (pattern.test(field)) field = field.replace(pattern, '."+$1+"')
+ return field
+}
+
+var types = {}
+
+types.any = function() {
+ return 'true'
+}
+
+types.null = function(name) {
+ return name+' === null'
+}
+
+types.boolean = function(name) {
+ return 'typeof '+name+' === "boolean"'
+}
+
+types.array = function(name) {
+ return 'Array.isArray('+name+')'
+}
+
+types.object = function(name) {
+ return 'typeof '+name+' === "object" && '+name+' && !Array.isArray('+name+')'
+}
+
+types.number = function(name) {
+ return 'typeof '+name+' === "number"'
+}
+
+types.integer = function(name) {
+ return 'typeof '+name+' === "number" && (Math.floor('+name+') === '+name+' || '+name+' > 9007199254740992 || '+name+' < -9007199254740992)'
+}
+
+types.string = function(name) {
+ return 'typeof '+name+' === "string"'
+}
+
+var unique = function(array) {
+ var list = []
+ for (var i = 0; i < array.length; i++) {
+ list.push(typeof array[i] === 'object' ? JSON.stringify(array[i]) : array[i])
+ }
+ for (var i = 1; i < list.length; i++) {
+ if (list.indexOf(list[i]) !== i) return false
+ }
+ return true
+}
+
+var toType = function(node) {
+ return node.type
+}
+
+var compile = function(schema, cache, root, reporter, opts) {
+ var fmts = opts ? xtend(formats, opts.formats) : formats
+ var scope = {unique:unique, formats:fmts}
+ var verbose = opts ? !!opts.verbose : false;
+ var greedy = opts && opts.greedy !== undefined ?
+ opts.greedy : false;
+
+ var syms = {}
+ var gensym = function(name) {
+ return name+(syms[name] = (syms[name] || 0)+1)
+ }
+
+ var reversePatterns = {}
+ var patterns = function(p) {
+ if (reversePatterns[p]) return reversePatterns[p]
+ var n = gensym('pattern')
+ scope[n] = new RegExp(p)
+ reversePatterns[p] = n
+ return n
+ }
+
+ var vars = ['i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','z']
+ var genloop = function() {
+ var v = vars.shift()
+ vars.push(v+v[0])
+ return v
+ }
+
+ var visit = function(name, node, reporter, filter) {
+ var properties = node.properties
+ var type = node.type
+ var tuple = false
+
+ if (Array.isArray(node.items)) { // tuple type
+ properties = {}
+ node.items.forEach(function(item, i) {
+ properties[i] = item
+ })
+ type = 'array'
+ tuple = true
+ }
+
+ var indent = 0
+ var error = function(msg, prop, value) {
+ validate('errors++')
+ if (reporter === true) {
+ validate('if (validate.errors === null) validate.errors = []')
+ if (verbose) {
+ validate('validate.errors.push({field:%s,message:%s,value:%s})', formatName(prop || name), JSON.stringify(msg), value || name)
+ } else {
+ validate('validate.errors.push({field:%s,message:%s})', formatName(prop || name), JSON.stringify(msg))
+ }
+ }
+ }
+
+ if (node.required === true) {
+ indent++
+ validate('if (%s === undefined) {', name)
+ error('is required')
+ validate('} else {')
+ } else {
+ indent++
+ validate('if (%s !== undefined) {', name)
+ }
+
+ var valid = [].concat(type)
+ .map(function(t) {
+ return types[t || 'any'](name)
+ })
+ .join(' || ') || 'true'
+
+ if (valid !== 'true') {
+ indent++
+ validate('if (!(%s)) {', valid)
+ error('is the wrong type')
+ validate('} else {')
+ }
+
+ if (tuple) {
+ if (node.additionalItems === false) {
+ validate('if (%s.length > %d) {', name, node.items.length)
+ error('has additional items')
+ validate('}')
+ } else if (node.additionalItems) {
+ var i = genloop()
+ validate('for (var %s = %d; %s < %s.length; %s++) {', i, node.items.length, i, name, i)
+ visit(name+'['+i+']', node.additionalItems, reporter, filter)
+ validate('}')
+ }
+ }
+
+ if (node.format && fmts[node.format]) {
+ if (type !== 'string' && formats[node.format]) validate('if (%s) {', types.string(name))
+ var n = gensym('format')
+ scope[n] = fmts[node.format]
+
+ if (typeof scope[n] === 'function') validate('if (!%s(%s)) {', n, name)
+ else validate('if (!%s.test(%s)) {', n, name)
+ error('must be '+node.format+' format')
+ validate('}')
+ if (type !== 'string' && formats[node.format]) validate('}')
+ }
+
+ if (Array.isArray(node.required)) {
+ var isUndefined = function(req) {
+ return genobj(name, req) + ' === undefined'
+ }
+
+ var checkRequired = function (req) {
+ var prop = genobj(name, req);
+ validate('if (%s === undefined) {', prop)
+ error('is required', prop)
+ validate('missing++')
+ validate('}')
+ }
+ validate('if ((%s)) {', type !== 'object' ? types.object(name) : 'true')
+ validate('var missing = 0')
+ node.required.map(checkRequired)
+ validate('}');
+ if (!greedy) {
+ validate('if (missing === 0) {')
+ indent++
+ }
+ }
+
+ if (node.uniqueItems) {
+ if (type !== 'array') validate('if (%s) {', types.array(name))
+ validate('if (!(unique(%s))) {', name)
+ error('must be unique')
+ validate('}')
+ if (type !== 'array') validate('}')
+ }
+
+ if (node.enum) {
+ var complex = node.enum.some(function(e) {
+ return typeof e === 'object'
+ })
+
+ var compare = complex ?
+ function(e) {
+ return 'JSON.stringify('+name+')'+' !== JSON.stringify('+JSON.stringify(e)+')'
+ } :
+ function(e) {
+ return name+' !== '+JSON.stringify(e)
+ }
+
+ validate('if (%s) {', node.enum.map(compare).join(' && ') || 'false')
+ error('must be an enum value')
+ validate('}')
+ }
+
+ if (node.dependencies) {
+ if (type !== 'object') validate('if (%s) {', types.object(name))
+
+ Object.keys(node.dependencies).forEach(function(key) {
+ var deps = node.dependencies[key]
+ if (typeof deps === 'string') deps = [deps]
+
+ var exists = function(k) {
+ return genobj(name, k) + ' !== undefined'
+ }
+
+ if (Array.isArray(deps)) {
+ validate('if (%s !== undefined && !(%s)) {', genobj(name, key), deps.map(exists).join(' && ') || 'true')
+ error('dependencies not set')
+ validate('}')
+ }
+ if (typeof deps === 'object') {
+ validate('if (%s !== undefined) {', genobj(name, key))
+ visit(name, deps, reporter, filter)
+ validate('}')
+ }
+ })
+
+ if (type !== 'object') validate('}')
+ }
+
+ if (node.additionalProperties || node.additionalProperties === false) {
+ if (type !== 'object') validate('if (%s) {', types.object(name))
+
+ var i = genloop()
+ var keys = gensym('keys')
+
+ var toCompare = function(p) {
+ return keys+'['+i+'] !== '+JSON.stringify(p)
+ }
+
+ var toTest = function(p) {
+ return '!'+patterns(p)+'.test('+keys+'['+i+'])'
+ }
+
+ var additionalProp = Object.keys(properties || {}).map(toCompare)
+ .concat(Object.keys(node.patternProperties || {}).map(toTest))
+ .join(' && ') || 'true'
+
+ validate('var %s = Object.keys(%s)', keys, name)
+ ('for (var %s = 0; %s < %s.length; %s++) {', i, i, keys, i)
+ ('if (%s) {', additionalProp)
+
+ if (node.additionalProperties === false) {
+ if (filter) validate('delete %s', name+'['+keys+'['+i+']]')
+ error('has additional properties', null, JSON.stringify(name+'.') + ' + ' + keys + '['+i+']')
+ } else {
+ visit(name+'['+keys+'['+i+']]', node.additionalProperties, reporter, filter)
+ }
+
+ validate
+ ('}')
+ ('}')
+
+ if (type !== 'object') validate('}')
+ }
+
+ if (node.$ref) {
+ var sub = get(root, opts && opts.schemas || {}, node.$ref)
+ if (sub) {
+ var fn = cache[node.$ref]
+ if (!fn) {
+ cache[node.$ref] = function proxy(data) {
+ return fn(data)
+ }
+ fn = compile(sub, cache, root, false, opts)
+ }
+ var n = gensym('ref')
+ scope[n] = fn
+ validate('if (!(%s(%s))) {', n, name)
+ error('referenced schema does not match')
+ validate('}')
+ }
+ }
+
+ if (node.not) {
+ var prev = gensym('prev')
+ validate('var %s = errors', prev)
+ visit(name, node.not, false, filter)
+ validate('if (%s === errors) {', prev)
+ error('negative schema matches')
+ validate('} else {')
+ ('errors = %s', prev)
+ ('}')
+ }
+
+ if (node.items && !tuple) {
+ if (type !== 'array') validate('if (%s) {', types.array(name))
+
+ var i = genloop()
+ validate('for (var %s = 0; %s < %s.length; %s++) {', i, i, name, i)
+ visit(name+'['+i+']', node.items, reporter, filter)
+ validate('}')
+
+ if (type !== 'array') validate('}')
+ }
+
+ if (node.patternProperties) {
+ if (type !== 'object') validate('if (%s) {', types.object(name))
+ var keys = gensym('keys')
+ var i = genloop()
+ validate
+ ('var %s = Object.keys(%s)', keys, name)
+ ('for (var %s = 0; %s < %s.length; %s++) {', i, i, keys, i)
+
+ Object.keys(node.patternProperties).forEach(function(key) {
+ var p = patterns(key)
+ validate('if (%s.test(%s)) {', p, keys+'['+i+']')
+ visit(name+'['+keys+'['+i+']]', node.patternProperties[key], reporter, filter)
+ validate('}')
+ })
+
+ validate('}')
+ if (type !== 'object') validate('}')
+ }
+
+ if (node.pattern) {
+ var p = patterns(node.pattern)
+ if (type !== 'string') validate('if (%s) {', types.string(name))
+ validate('if (!(%s.test(%s))) {', p, name)
+ error('pattern mismatch')
+ validate('}')
+ if (type !== 'string') validate('}')
+ }
+
+ if (node.allOf) {
+ node.allOf.forEach(function(sch) {
+ visit(name, sch, reporter, filter)
+ })
+ }
+
+ if (node.anyOf && node.anyOf.length) {
+ var prev = gensym('prev')
+
+ node.anyOf.forEach(function(sch, i) {
+ if (i === 0) {
+ validate('var %s = errors', prev)
+ } else {
+ validate('if (errors !== %s) {', prev)
+ ('errors = %s', prev)
+ }
+ visit(name, sch, false, false)
+ })
+ node.anyOf.forEach(function(sch, i) {
+ if (i) validate('}')
+ })
+ validate('if (%s !== errors) {', prev)
+ error('no schemas match')
+ validate('}')
+ }
+
+ if (node.oneOf && node.oneOf.length) {
+ var prev = gensym('prev')
+ var passes = gensym('passes')
+
+ validate
+ ('var %s = errors', prev)
+ ('var %s = 0', passes)
+
+ node.oneOf.forEach(function(sch, i) {
+ visit(name, sch, false, false)
+ validate('if (%s === errors) {', prev)
+ ('%s++', passes)
+ ('} else {')
+ ('errors = %s', prev)
+ ('}')
+ })
+
+ validate('if (%s !== 1) {', passes)
+ error('no (or more than one) schemas match')
+ validate('}')
+ }
+
+ if (node.multipleOf !== undefined) {
+ if (type !== 'number' && type !== 'integer') validate('if (%s) {', types.number(name))
+
+ var factor = ((node.multipleOf | 0) !== node.multipleOf) ? Math.pow(10, node.multipleOf.toString().split('.').pop().length) : 1
+ if (factor > 1) validate('if ((%d*%s) % %d) {', factor, name, factor*node.multipleOf)
+ else validate('if (%s % %d) {', name, node.multipleOf)
+
+ error('has a remainder')
+ validate('}')
+
+ if (type !== 'number' && type !== 'integer') validate('}')
+ }
+
+ if (node.maxProperties !== undefined) {
+ if (type !== 'object') validate('if (%s) {', types.object(name))
+
+ validate('if (Object.keys(%s).length > %d) {', name, node.maxProperties)
+ error('has more properties than allowed')
+ validate('}')
+
+ if (type !== 'object') validate('}')
+ }
+
+ if (node.minProperties !== undefined) {
+ if (type !== 'object') validate('if (%s) {', types.object(name))
+
+ validate('if (Object.keys(%s).length < %d) {', name, node.minProperties)
+ error('has less properties than allowed')
+ validate('}')
+
+ if (type !== 'object') validate('}')
+ }
+
+ if (node.maxItems !== undefined) {
+ if (type !== 'array') validate('if (%s) {', types.array(name))
+
+ validate('if (%s.length > %d) {', name, node.maxItems)
+ error('has more items than allowed')
+ validate('}')
+
+ if (type !== 'array') validate('}')
+ }
+
+ if (node.minItems !== undefined) {
+ if (type !== 'array') validate('if (%s) {', types.array(name))
+
+ validate('if (%s.length < %d) {', name, node.minItems)
+ error('has less items than allowed')
+ validate('}')
+
+ if (type !== 'array') validate('}')
+ }
+
+ if (node.maxLength !== undefined) {
+ if (type !== 'string') validate('if (%s) {', types.string(name))
+
+ validate('if (%s.length > %d) {', name, node.maxLength)
+ error('has longer length than allowed')
+ validate('}')
+
+ if (type !== 'string') validate('}')
+ }
+
+ if (node.minLength !== undefined) {
+ if (type !== 'string') validate('if (%s) {', types.string(name))
+
+ validate('if (%s.length < %d) {', name, node.minLength)
+ error('has less length than allowed')
+ validate('}')
+
+ if (type !== 'string') validate('}')
+ }
+
+ if (node.minimum !== undefined) {
+ validate('if (%s %s %d) {', name, node.exclusiveMinimum ? '<=' : '<', node.minimum)
+ error('is less than minimum')
+ validate('}')
+ }
+
+ if (node.maximum !== undefined) {
+ validate('if (%s %s %d) {', name, node.exclusiveMaximum ? '>=' : '>', node.maximum)
+ error('is more than maximum')
+ validate('}')
+ }
+
+ if (properties) {
+ Object.keys(properties).forEach(function(p) {
+ if (Array.isArray(type) && type.indexOf('null') !== -1) validate('if (%s !== null) {', name)
+
+ visit(genobj(name, p), properties[p], reporter, filter)
+
+ if (Array.isArray(type) && type.indexOf('null') !== -1) validate('}')
+ })
+ }
+
+ while (indent--) validate('}')
+ }
+
+ var validate = genfun
+ ('function validate(data) {')
+ ('validate.errors = null')
+ ('var errors = 0')
+
+ visit('data', schema, reporter, opts && opts.filter)
+
+ validate
+ ('return errors === 0')
+ ('}')
+
+ validate = validate.toFunction(scope)
+ validate.errors = null
+
+ if (Object.defineProperty) {
+ Object.defineProperty(validate, 'error', {
+ get: function() {
+ if (!validate.errors) return ''
+ return validate.errors.map(function(err) {
+ return err.field + ' ' + err.message;
+ }).join('\n')
+ }
+ })
+ }
+
+ validate.toJSON = function() {
+ return schema
+ }
+
+ return validate
+}
+
+module.exports = function(schema, opts) {
+ if (typeof schema === 'string') schema = JSON.parse(schema)
+ return compile(schema, {}, schema, true, opts)
+}
+
+module.exports.filter = function(schema, opts) {
+ var validate = module.exports(schema, xtend(opts, {filter: true}))
+ return function(sch) {
+ validate(sch)
+ return sch
+ }
+}
+
+},{"./formats":102,"generate-function":97,"generate-object-property":98,"jsonpointer":106,"xtend":112}],104:[function(require,module,exports){
+"use strict"
+function isProperty(str) {
+ return /^[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc0-9\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19d9\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f]*$/.test(str)
+}
+module.exports = isProperty
+},{}],105:[function(require,module,exports){
+module.exports = Array.isArray || function (arr) {
+ return Object.prototype.toString.call(arr) == '[object Array]';
+};
+
+},{}],106:[function(require,module,exports){
+var untilde = function(str) {
+ return str.replace(/~./g, function(m) {
+ switch (m) {
+ case "~0":
+ return "~";
+ case "~1":
+ return "/";
+ }
+ throw new Error("Invalid tilde escape: " + m);
+ });
+}
+
+var traverse = function(obj, pointer, value) {
+ // assert(isArray(pointer))
+ var part = untilde(pointer.shift());
+ if(!obj.hasOwnProperty(part)) {
+ return null;
+ }
+ if(pointer.length !== 0) { // keep traversin!
+ return traverse(obj[part], pointer, value);
+ }
+ // we're done
+ if(typeof value === "undefined") {
+ // just reading
+ return obj[part];
+ }
+ // set new value, return old value
+ var old_value = obj[part];
+ if(value === null) {
+ delete obj[part];
+ } else {
+ obj[part] = value;
+ }
+ return old_value;
+}
+
+var validate_input = function(obj, pointer) {
+ if(typeof obj !== "object") {
+ throw new Error("Invalid input object.");
+ }
+
+ if(pointer === "") {
+ return [];
+ }
+
+ if(!pointer) {
+ throw new Error("Invalid JSON pointer.");
+ }
+
+ pointer = pointer.split("/");
+ var first = pointer.shift();
+ if (first !== "") {
+ throw new Error("Invalid JSON pointer.");
+ }
+
+ return pointer;
+}
+
+var get = function(obj, pointer) {
+ pointer = validate_input(obj, pointer);
+ if (pointer.length === 0) {
+ return obj;
+ }
+ return traverse(obj, pointer);
+}
+
+var set = function(obj, pointer, value) {
+ pointer = validate_input(obj, pointer);
+ if (pointer.length === 0) {
+ throw new Error("Invalid JSON pointer for set.")
+ }
+ return traverse(obj, pointer, value);
+}
+
+exports.get = get
+exports.set = set
+
+},{}],107:[function(require,module,exports){
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ * - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} options
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options){
+ options = options || {};
+ if ('string' == typeof val) return parse(val);
+ return options.long
+ ? long(val)
+ : short(val);
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ str = '' + str;
+ if (str.length > 10000) return;
+ var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
+ if (!match) return;
+ var n = parseFloat(match[1]);
+ var type = (match[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'yrs':
+ case 'yr':
+ case 'y':
+ return n * y;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+ case 'hours':
+ case 'hour':
+ case 'hrs':
+ case 'hr':
+ case 'h':
+ return n * h;
+ case 'minutes':
+ case 'minute':
+ case 'mins':
+ case 'min':
+ case 'm':
+ return n * m;
+ case 'seconds':
+ case 'second':
+ case 'secs':
+ case 'sec':
+ case 's':
+ return n * s;
+ case 'milliseconds':
+ case 'millisecond':
+ case 'msecs':
+ case 'msec':
+ case 'ms':
+ return n;
+ }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function short(ms) {
+ if (ms >= d) return Math.round(ms / d) + 'd';
+ if (ms >= h) return Math.round(ms / h) + 'h';
+ if (ms >= m) return Math.round(ms / m) + 'm';
+ if (ms >= s) return Math.round(ms / s) + 's';
+ return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function long(ms) {
+ return plural(ms, d, 'day')
+ || plural(ms, h, 'hour')
+ || plural(ms, m, 'minute')
+ || plural(ms, s, 'second')
+ || ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+ if (ms < n) return;
+ if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
+ return Math.ceil(ms / n) + ' ' + name + 's';
+}
+
+},{}],108:[function(require,module,exports){
+/* eslint-disable no-unused-vars */
'use strict';
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var propIsEnumerable = Object.prototype.propertyIsEnumerable;
-function ToObject(val) {
- if (val == null) {
+function toObject(val) {
+ if (val === null || val === undefined) {
throw new TypeError('Object.assign cannot be called with null or undefined');
}
return Object(val);
}
module.exports = Object.assign || function (target, source) {
var from;
- var keys;
- var to = ToObject(target);
+ var to = toObject(target);
+ var symbols;
for (var s = 1; s < arguments.length; s++) {
- from = arguments[s];
- keys = Object.keys(Object(from));
+ from = Object(arguments[s]);
- for (var i = 0; i < keys.length; i++) {
- to[keys[i]] = from[keys[i]];
+ for (var key in from) {
+ if (hasOwnProperty.call(from, key)) {
+ to[key] = from[key];
+ }
}
+
+ if (Object.getOwnPropertySymbols) {
+ symbols = Object.getOwnPropertySymbols(from);
+ for (var i = 0; i < symbols.length; i++) {
+ if (propIsEnumerable.call(from, symbols[i])) {
+ to[symbols[i]] = from[symbols[i]];
+ }
+ }
+ }
}
return to;
};
-},{}],132:[function(require,module,exports){
+},{}],109:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = setTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ clearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ setTimeout(drainQueue, 0);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],110:[function(require,module,exports){
+module.exports = function isBuffer(arg) {
+ return arg && typeof arg === 'object'
+ && typeof arg.copy === 'function'
+ && typeof arg.fill === 'function'
+ && typeof arg.readUInt8 === 'function';
+}
+},{}],111:[function(require,module,exports){
+(function (process,global){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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 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.
+
+var formatRegExp = /%[sdj%]/g;
+exports.format = function(f) {
+ if (!isString(f)) {
+ var objects = [];
+ for (var i = 0; i < arguments.length; i++) {
+ objects.push(inspect(arguments[i]));
+ }
+ return objects.join(' ');
+ }
+
+ var i = 1;
+ var args = arguments;
+ var len = args.length;
+ var str = String(f).replace(formatRegExp, function(x) {
+ if (x === '%%') return '%';
+ if (i >= len) return x;
+ switch (x) {
+ case '%s': return String(args[i++]);
+ case '%d': return Number(args[i++]);
+ case '%j':
+ try {
+ return JSON.stringify(args[i++]);
+ } catch (_) {
+ return '[Circular]';
+ }
+ default:
+ return x;
+ }
+ });
+ for (var x = args[i]; i < len; x = args[++i]) {
+ if (isNull(x) || !isObject(x)) {
+ str += ' ' + x;
+ } else {
+ str += ' ' + inspect(x);
+ }
+ }
+ return str;
+};
+
+
+// Mark that a method should not be used.
+// Returns a modified function which warns once by default.
+// If --no-deprecation is set, then it is a no-op.
+exports.deprecate = function(fn, msg) {
+ // Allow for deprecating things in the process of starting up.
+ if (isUndefined(global.process)) {
+ return function() {
+ return exports.deprecate(fn, msg).apply(this, arguments);
+ };
+ }
+
+ if (process.noDeprecation === true) {
+ return fn;
+ }
+
+ var warned = false;
+ function deprecated() {
+ if (!warned) {
+ if (process.throwDeprecation) {
+ throw new Error(msg);
+ } else if (process.traceDeprecation) {
+ console.trace(msg);
+ } else {
+ console.error(msg);
+ }
+ warned = true;
+ }
+ return fn.apply(this, arguments);
+ }
+
+ return deprecated;
+};
+
+
+var debugs = {};
+var debugEnviron;
+exports.debuglog = function(set) {
+ if (isUndefined(debugEnviron))
+ debugEnviron = process.env.NODE_DEBUG || '';
+ set = set.toUpperCase();
+ if (!debugs[set]) {
+ if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+ var pid = process.pid;
+ debugs[set] = function() {
+ var msg = exports.format.apply(exports, arguments);
+ console.error('%s %d: %s', set, pid, msg);
+ };
+ } else {
+ debugs[set] = function() {};
+ }
+ }
+ return debugs[set];
+};
+
+
/**
+ * Echos the value of a value. Trys to print the value out
+ * in the best way possible given the different types.
+ *
+ * @param {Object} obj The object to print out.
+ * @param {Object} opts Optional options object that alters the output.
+ */
+/* legacy: obj, showHidden, depth, colors*/
+function inspect(obj, opts) {
+ // default options
+ var ctx = {
+ seen: [],
+ stylize: stylizeNoColor
+ };
+ // legacy...
+ if (arguments.length >= 3) ctx.depth = arguments[2];
+ if (arguments.length >= 4) ctx.colors = arguments[3];
+ if (isBoolean(opts)) {
+ // legacy...
+ ctx.showHidden = opts;
+ } else if (opts) {
+ // got an "options" object
+ exports._extend(ctx, opts);
+ }
+ // set default options
+ if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+ if (isUndefined(ctx.depth)) ctx.depth = 2;
+ if (isUndefined(ctx.colors)) ctx.colors = false;
+ if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+ if (ctx.colors) ctx.stylize = stylizeWithColor;
+ return formatValue(ctx, obj, ctx.depth);
+}
+exports.inspect = inspect;
+
+
+// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+inspect.colors = {
+ 'bold' : [1, 22],
+ 'italic' : [3, 23],
+ 'underline' : [4, 24],
+ 'inverse' : [7, 27],
+ 'white' : [37, 39],
+ 'grey' : [90, 39],
+ 'black' : [30, 39],
+ 'blue' : [34, 39],
+ 'cyan' : [36, 39],
+ 'green' : [32, 39],
+ 'magenta' : [35, 39],
+ 'red' : [31, 39],
+ 'yellow' : [33, 39]
+};
+
+// Don't use 'blue' not visible on cmd.exe
+inspect.styles = {
+ 'special': 'cyan',
+ 'number': 'yellow',
+ 'boolean': 'yellow',
+ 'undefined': 'grey',
+ 'null': 'bold',
+ 'string': 'green',
+ 'date': 'magenta',
+ // "name": intentionally not styling
+ 'regexp': 'red'
+};
+
+
+function stylizeWithColor(str, styleType) {
+ var style = inspect.styles[styleType];
+
+ if (style) {
+ return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+ '\u001b[' + inspect.colors[style][1] + 'm';
+ } else {
+ return str;
+ }
+}
+
+
+function stylizeNoColor(str, styleType) {
+ return str;
+}
+
+
+function arrayToHash(array) {
+ var hash = {};
+
+ array.forEach(function(val, idx) {
+ hash[val] = true;
+ });
+
+ return hash;
+}
+
+
+function formatValue(ctx, value, recurseTimes) {
+ // Provide a hook for user-specified inspect functions.
+ // Check that value is an object with an inspect function on it
+ if (ctx.customInspect &&
+ value &&
+ isFunction(value.inspect) &&
+ // Filter out the util module, it's inspect function is special
+ value.inspect !== exports.inspect &&
+ // Also filter out any prototype objects using the circular check.
+ !(value.constructor && value.constructor.prototype === value)) {
+ var ret = value.inspect(recurseTimes, ctx);
+ if (!isString(ret)) {
+ ret = formatValue(ctx, ret, recurseTimes);
+ }
+ return ret;
+ }
+
+ // Primitive types cannot have properties
+ var primitive = formatPrimitive(ctx, value);
+ if (primitive) {
+ return primitive;
+ }
+
+ // Look up the keys of the object.
+ var keys = Object.keys(value);
+ var visibleKeys = arrayToHash(keys);
+
+ if (ctx.showHidden) {
+ keys = Object.getOwnPropertyNames(value);
+ }
+
+ // IE doesn't make error fields non-enumerable
+ // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+ if (isError(value)
+ && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+ return formatError(value);
+ }
+
+ // Some type of object without properties can be shortcutted.
+ if (keys.length === 0) {
+ if (isFunction(value)) {
+ var name = value.name ? ': ' + value.name : '';
+ return ctx.stylize('[Function' + name + ']', 'special');
+ }
+ if (isRegExp(value)) {
+ return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+ }
+ if (isDate(value)) {
+ return ctx.stylize(Date.prototype.toString.call(value), 'date');
+ }
+ if (isError(value)) {
+ return formatError(value);
+ }
+ }
+
+ var base = '', array = false, braces = ['{', '}'];
+
+ // Make Array say that they are Array
+ if (isArray(value)) {
+ array = true;
+ braces = ['[', ']'];
+ }
+
+ // Make functions say that they are functions
+ if (isFunction(value)) {
+ var n = value.name ? ': ' + value.name : '';
+ base = ' [Function' + n + ']';
+ }
+
+ // Make RegExps say that they are RegExps
+ if (isRegExp(value)) {
+ base = ' ' + RegExp.prototype.toString.call(value);
+ }
+
+ // Make dates with properties first say the date
+ if (isDate(value)) {
+ base = ' ' + Date.prototype.toUTCString.call(value);
+ }
+
+ // Make error with message first say the error
+ if (isError(value)) {
+ base = ' ' + formatError(value);
+ }
+
+ if (keys.length === 0 && (!array || value.length == 0)) {
+ return braces[0] + base + braces[1];
+ }
+
+ if (recurseTimes < 0) {
+ if (isRegExp(value)) {
+ return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+ } else {
+ return ctx.stylize('[Object]', 'special');
+ }
+ }
+
+ ctx.seen.push(value);
+
+ var output;
+ if (array) {
+ output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
+ } else {
+ output = keys.map(function(key) {
+ return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
+ });
+ }
+
+ ctx.seen.pop();
+
+ return reduceToSingleString(output, base, braces);
+}
+
+
+function formatPrimitive(ctx, value) {
+ if (isUndefined(value))
+ return ctx.stylize('undefined', 'undefined');
+ if (isString(value)) {
+ var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+ .replace(/'/g, "\\'")
+ .replace(/\\"/g, '"') + '\'';
+ return ctx.stylize(simple, 'string');
+ }
+ if (isNumber(value))
+ return ctx.stylize('' + value, 'number');
+ if (isBoolean(value))
+ return ctx.stylize('' + value, 'boolean');
+ // For some reason typeof null is "object", so special case here.
+ if (isNull(value))
+ return ctx.stylize('null', 'null');
+}
+
+
+function formatError(value) {
+ return '[' + Error.prototype.toString.call(value) + ']';
+}
+
+
+function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
+ var output = [];
+ for (var i = 0, l = value.length; i < l; ++i) {
+ if (hasOwnProperty(value, String(i))) {
+ output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+ String(i), true));
+ } else {
+ output.push('');
+ }
+ }
+ keys.forEach(function(key) {
+ if (!key.match(/^\d+$/)) {
+ output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+ key, true));
+ }
+ });
+ return output;
+}
+
+
+function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
+ var name, str, desc;
+ desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
+ if (desc.get) {
+ if (desc.set) {
+ str = ctx.stylize('[Getter/Setter]', 'special');
+ } else {
+ str = ctx.stylize('[Getter]', 'special');
+ }
+ } else {
+ if (desc.set) {
+ str = ctx.stylize('[Setter]', 'special');
+ }
+ }
+ if (!hasOwnProperty(visibleKeys, key)) {
+ name = '[' + key + ']';
+ }
+ if (!str) {
+ if (ctx.seen.indexOf(desc.value) < 0) {
+ if (isNull(recurseTimes)) {
+ str = formatValue(ctx, desc.value, null);
+ } else {
+ str = formatValue(ctx, desc.value, recurseTimes - 1);
+ }
+ if (str.indexOf('\n') > -1) {
+ if (array) {
+ str = str.split('\n').map(function(line) {
+ return ' ' + line;
+ }).join('\n').substr(2);
+ } else {
+ str = '\n' + str.split('\n').map(function(line) {
+ return ' ' + line;
+ }).join('\n');
+ }
+ }
+ } else {
+ str = ctx.stylize('[Circular]', 'special');
+ }
+ }
+ if (isUndefined(name)) {
+ if (array && key.match(/^\d+$/)) {
+ return str;
+ }
+ name = JSON.stringify('' + key);
+ if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+ name = name.substr(1, name.length - 2);
+ name = ctx.stylize(name, 'name');
+ } else {
+ name = name.replace(/'/g, "\\'")
+ .replace(/\\"/g, '"')
+ .replace(/(^"|"$)/g, "'");
+ name = ctx.stylize(name, 'string');
+ }
+ }
+
+ return name + ': ' + str;
+}
+
+
+function reduceToSingleString(output, base, braces) {
+ var numLinesEst = 0;
+ var length = output.reduce(function(prev, cur) {
+ numLinesEst++;
+ if (cur.indexOf('\n') >= 0) numLinesEst++;
+ return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
+ }, 0);
+
+ if (length > 60) {
+ return braces[0] +
+ (base === '' ? '' : base + '\n ') +
+ ' ' +
+ output.join(',\n ') +
+ ' ' +
+ braces[1];
+ }
+
+ return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+}
+
+
+// NOTE: These type checking functions intentionally don't use `instanceof`
+// because it is fragile and can be easily faked with `Object.create()`.
+function isArray(ar) {
+ return Array.isArray(ar);
+}
+exports.isArray = isArray;
+
+function isBoolean(arg) {
+ return typeof arg === 'boolean';
+}
+exports.isBoolean = isBoolean;
+
+function isNull(arg) {
+ return arg === null;
+}
+exports.isNull = isNull;
+
+function isNullOrUndefined(arg) {
+ return arg == null;
+}
+exports.isNullOrUndefined = isNullOrUndefined;
+
+function isNumber(arg) {
+ return typeof arg === 'number';
+}
+exports.isNumber = isNumber;
+
+function isString(arg) {
+ return typeof arg === 'string';
+}
+exports.isString = isString;
+
+function isSymbol(arg) {
+ return typeof arg === 'symbol';
+}
+exports.isSymbol = isSymbol;
+
+function isUndefined(arg) {
+ return arg === void 0;
+}
+exports.isUndefined = isUndefined;
+
+function isRegExp(re) {
+ return isObject(re) && objectToString(re) === '[object RegExp]';
+}
+exports.isRegExp = isRegExp;
+
+function isObject(arg) {
+ return typeof arg === 'object' && arg !== null;
+}
+exports.isObject = isObject;
+
+function isDate(d) {
+ return isObject(d) && objectToString(d) === '[object Date]';
+}
+exports.isDate = isDate;
+
+function isError(e) {
+ return isObject(e) &&
+ (objectToString(e) === '[object Error]' || e instanceof Error);
+}
+exports.isError = isError;
+
+function isFunction(arg) {
+ return typeof arg === 'function';
+}
+exports.isFunction = isFunction;
+
+function isPrimitive(arg) {
+ return arg === null ||
+ typeof arg === 'boolean' ||
+ typeof arg === 'number' ||
+ typeof arg === 'string' ||
+ typeof arg === 'symbol' || // ES6 symbol
+ typeof arg === 'undefined';
+}
+exports.isPrimitive = isPrimitive;
+
+exports.isBuffer = require('./support/isBuffer');
+
+function objectToString(o) {
+ return Object.prototype.toString.call(o);
+}
+
+
+function pad(n) {
+ return n < 10 ? '0' + n.toString(10) : n.toString(10);
+}
+
+
+var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+ 'Oct', 'Nov', 'Dec'];
+
+// 26 Feb 16:19:34
+function timestamp() {
+ var d = new Date();
+ var time = [pad(d.getHours()),
+ pad(d.getMinutes()),
+ pad(d.getSeconds())].join(':');
+ return [d.getDate(), months[d.getMonth()], time].join(' ');
+}
+
+
+// log is just a thin wrapper to console.log that prepends a timestamp
+exports.log = function() {
+ console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+};
+
+
+/**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * The Function.prototype.inherits from lang.js rewritten as a standalone
+ * function (not on Function.prototype). NOTE: If this file is to be loaded
+ * during bootstrapping this function needs to be rewritten using some native
+ * functions as prototype setup using normal JavaScript does not work as
+ * expected during bootstrapping (see mirror.js in r114903).
+ *
+ * @param {function} ctor Constructor function which needs to inherit the
+ * prototype.
+ * @param {function} superCtor Constructor function to inherit prototype from.
+ */
+exports.inherits = require('inherits');
+
+exports._extend = function(origin, add) {
+ // Don't do anything if add isn't an object
+ if (!add || !isObject(add)) return origin;
+
+ var keys = Object.keys(add);
+ var i = keys.length;
+ while (i--) {
+ origin[keys[i]] = add[keys[i]];
+ }
+ return origin;
+};
+
+function hasOwnProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
+}
+
+}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"./support/isBuffer":110,"_process":109,"inherits":101}],112:[function(require,module,exports){
+module.exports = extend
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function extend() {
+ var target = {}
+
+ for (var i = 0; i < arguments.length; i++) {
+ var source = arguments[i]
+
+ for (var key in source) {
+ if (hasOwnProperty.call(source, key)) {
+ target[key] = source[key]
+ }
+ }
+ }
+
+ return target
+}
+
+},{}],113:[function(require,module,exports){
+/**
+ * @fileoverview Common utils for AST.
+ * @author Gyandeep Singh
+ * @copyright 2015 Gyandeep Singh. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var esutils = require("esutils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks reference if is non initializer and writable.
+ * @param {Reference} reference - A reference to check.
+ * @param {int} index - The index of the reference in the references.
+ * @param {Reference[]} references - The array that the reference belongs to.
+ * @returns {boolean} Success/Failure
+ * @private
+ */
+function isModifyingReference(reference, index, references) {
+ var identifier = reference.identifier;
+
+ return (identifier &&
+ reference.init === false &&
+ reference.isWrite() &&
+ // Destructuring assignments can have multiple default value,
+ // so possibly there are multiple writeable references for the same identifier.
+ (index === 0 || references[index - 1].identifier !== identifier)
+ );
+}
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+module.exports = {
+
+ /**
+ * Determines whether two adjacent tokens are on the same line.
+ * @param {Object} left - The left token object.
+ * @param {Object} right - The right token object.
+ * @returns {boolean} Whether or not the tokens are on the same line.
+ * @public
+ */
+ isTokenOnSameLine: function(left, right) {
+ return left.loc.end.line === right.loc.start.line;
+ },
+
+ /**
+ * Checks whether or not a node is `null` or `undefined`.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node is a `null` or `undefined`.
+ * @public
+ */
+ isNullOrUndefined: function(node) {
+ return (
+ (node.type === "Literal" && node.value === null) ||
+ (node.type === "Identifier" && node.name === "undefined") ||
+ (node.type === "UnaryExpression" && node.operator === "void")
+ );
+ },
+
+ /**
+ * Checks whether or not a given node is a string literal.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} `true` if the node is a string literal.
+ */
+ isStringLiteral: function(node) {
+ return (
+ (node.type === "Literal" && typeof node.value === "string") ||
+ node.type === "TemplateLiteral"
+ );
+ },
+
+ /**
+ * Gets references which are non initializer and writable.
+ * @param {Reference[]} references - An array of references.
+ * @returns {Reference[]} An array of only references which are non initializer and writable.
+ * @public
+ */
+ getModifyingReferences: function(references) {
+ return references.filter(isModifyingReference);
+ },
+
+ /**
+ * Validate that a string passed in is surrounded by the specified character
+ * @param {string} val The text to check.
+ * @param {string} character The character to see if it's surrounded by.
+ * @returns {boolean} True if the text is surrounded by the character, false if not.
+ * @private
+ */
+ isSurroundedBy: function(val, character) {
+ return val[0] === character && val[val.length - 1] === character;
+ },
+
+ /**
+ * Returns whether the provided node is an ESLint directive comment or not
+ * @param {LineComment|BlockComment} node The node to be checked
+ * @returns {boolean} `true` if the node is an ESLint directive comment
+ */
+ isDirectiveComment: function(node) {
+ var comment = node.value.trim();
+ return (
+ node.type === "Line" && comment.indexOf("eslint-") === 0 ||
+ node.type === "Block" && (
+ comment.indexOf("global ") === 0 ||
+ comment.indexOf("eslint ") === 0 ||
+ comment.indexOf("eslint-") === 0
+ )
+ );
+ },
+
+ /**
+ * Gets the trailing statement of a given node.
+ *
+ * if (code)
+ * consequent;
+ *
+ * When taking this `IfStatement`, returns `consequent;` statement.
+ *
+ * @param {ASTNode} A node to get.
+ * @returns {ASTNode|null} The trailing statement's node.
+ */
+ getTrailingStatement: esutils.ast.trailingStatement,
+
+ /**
+ * Finds the variable by a given name in a given scope and its upper scopes.
+ *
+ * @param {escope.Scope} initScope - A scope to start find.
+ * @param {string} name - A variable name to find.
+ * @returns {escope.Variable|null} A found variable or `null`.
+ */
+ getVariableByName: function(initScope, name) {
+ var scope = initScope;
+ while (scope) {
+ var variable = scope.set.get(name);
+ if (variable) {
+ return variable;
+ }
+
+ scope = scope.upper;
+ }
+
+ return null;
+ }
+};
+
+},{"esutils":94}],114:[function(require,module,exports){
+/**
+ * @fileoverview Config file operations. This file must be usable in the browser,
+ * so no Node-specific code can be here.
+ * @author Nicholas C. Zakas
+ * @copyright 2015 Nicholas C. Zakas. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var debug = require("debug"),
+ environments = require("../../conf/environments"),
+ assign = require("object-assign");
+
+//------------------------------------------------------------------------------
+// Private
+//------------------------------------------------------------------------------
+
+debug = debug("eslint:config-ops");
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+module.exports = {
+
+ /**
+ * Creates an empty configuration object suitable for merging as a base.
+ * @returns {Object} A configuration object.
+ */
+ createEmptyConfig: function() {
+ return {
+ globals: {},
+ env: {},
+ rules: {},
+ ecmaFeatures: {}
+ };
+ },
+
+ /**
+ * Creates an environment config based on the specified environments.
+ * @param {Object<string,boolean>} env The environment settings.
+ * @returns {Object} A configuration object with the appropriate rules and globals
+ * set.
+ */
+ createEnvironmentConfig: function(env) {
+
+ var envConfig = this.createEmptyConfig();
+
+ if (env) {
+
+ envConfig.env = env;
+
+ Object.keys(env).filter(function(name) {
+ return env[name];
+ }).forEach(function(name) {
+ var environment = environments[name];
+
+ if (environment) {
+ debug("Creating config for environment " + name);
+ if (environment.globals) {
+ assign(envConfig.globals, environment.globals);
+ }
+
+ if (environment.ecmaFeatures) {
+ assign(envConfig.ecmaFeatures, environment.ecmaFeatures);
+ }
+ }
+ });
+ }
+
+ return envConfig;
+ },
+
+ /**
+ * Given a config with environment settings, applies the globals and
+ * ecmaFeatures to the configuration and returns the result.
+ * @param {Object} config The configuration information.
+ * @returns {Object} The updated configuration information.
+ */
+ applyEnvironments: function(config) {
+ if (config.env && typeof config.env === "object") {
+ debug("Apply environment settings to config");
+ return this.merge(this.createEnvironmentConfig(config.env), config);
+ }
+
+ return config;
+ },
+
+ /**
+ * Merges two config objects. This will not only add missing keys, but will also modify values to match.
+ * @param {Object} target config object
+ * @param {Object} src config object. Overrides in this config object will take priority over base.
+ * @param {boolean} [combine] Whether to combine arrays or not
+ * @param {boolean} [isRule] Whether its a rule
+ * @returns {Object} merged config object.
+ */
+ merge: function deepmerge(target, src, combine, isRule) {
+ /*
+ The MIT License (MIT)
+
+ Copyright (c) 2012 Nicholas Fisher
+
+ 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 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.
+ */
+ // This code is taken from deepmerge repo (https://github.com/KyleAMathews/deepmerge) and modified to meet our needs.
+ var array = Array.isArray(src) || Array.isArray(target);
+ var dst = array && [] || {};
+
+ combine = !!combine;
+ isRule = !!isRule;
+ if (array) {
+ target = target || [];
+ if (isRule && src.length > 1) {
+ dst = dst.concat(src);
+ } else {
+ dst = dst.concat(target);
+ }
+ if (typeof src !== "object" && !Array.isArray(src)) {
+ src = [src];
+ }
+ Object.keys(src).forEach(function(e, i) {
+ e = src[i];
+ if (typeof dst[i] === "undefined") {
+ dst[i] = e;
+ } else if (typeof e === "object") {
+ if (isRule) {
+ dst[i] = e;
+ } else {
+ dst[i] = deepmerge(target[i], e, combine, isRule);
+ }
+ } else {
+ if (!combine) {
+ dst[i] = e;
+ } else {
+ if (dst.indexOf(e) === -1) {
+ dst.push(e);
+ }
+ }
+ }
+ });
+ } else {
+ if (target && typeof target === "object") {
+ Object.keys(target).forEach(function(key) {
+ dst[key] = target[key];
+ });
+ }
+ Object.keys(src).forEach(function(key) {
+ if (Array.isArray(src[key]) || Array.isArray(target[key])) {
+ dst[key] = deepmerge(target[key], src[key], key === "plugins", isRule);
+ } else if (typeof src[key] !== "object" || !src[key]) {
+ dst[key] = src[key];
+ } else {
+ if (!target[key]) {
+ dst[key] = src[key];
+ } else {
+ dst[key] = deepmerge(target[key], src[key], combine, key === "rules");
+ }
+ }
+ });
+ }
+
+ return dst;
+ }
+
+
+};
+
+},{"../../conf/environments":2,"debug":8,"object-assign":108}],115:[function(require,module,exports){
+/**
+ * @fileoverview Validates configs.
+ * @author Brandon Mills
+ * @copyright 2015 Brandon Mills
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var rules = require("../rules"),
+ environments = require("../../conf/environments"),
+ schemaValidator = require("is-my-json-valid");
+
+var validators = {
+ rules: Object.create(null)
+};
+
+//------------------------------------------------------------------------------
+// Private
+//------------------------------------------------------------------------------
+
+/**
+ * Gets a complete options schema for a rule.
+ * @param {string} id The rule's unique name.
+ * @returns {object} JSON Schema for the rule's options.
+ */
+function getRuleOptionsSchema(id) {
+ var rule = rules.get(id),
+ schema = rule && rule.schema;
+
+ if (!schema) {
+ return {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ }
+ ],
+ "minItems": 1
+ };
+ }
+
+ // Given a tuple of schemas, insert warning level at the beginning
+ if (Array.isArray(schema)) {
+ return {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ }
+ ].concat(schema),
+ "minItems": 1,
+ "maxItems": schema.length + 1
+ };
+ }
+
+ // Given a full schema, leave it alone
+ return schema;
+}
+
+/**
+ * Validates a rule's options against its schema.
+ * @param {string} id The rule's unique name.
+ * @param {array|number} options The given options for the rule.
+ * @param {string} source The name of the configuration source.
+ * @returns {void}
+ */
+function validateRuleOptions(id, options, source) {
+ var validateRule = validators.rules[id],
+ message;
+
+ if (!validateRule) {
+ validateRule = schemaValidator(getRuleOptionsSchema(id), { verbose: true });
+ validators.rules[id] = validateRule;
+ }
+
+ if (typeof options === "number") {
+ options = [options];
+ }
+
+ validateRule(options);
+
+ if (validateRule.errors) {
+ message = [
+ source, ":\n",
+ "\tConfiguration for rule \"", id, "\" is invalid:\n"
+ ];
+ validateRule.errors.forEach(function(error) {
+ if (error.field === "data[\"0\"]") { // better error for severity
+ message.push(
+ "\tSeverity should be one of the following: 0 = off, 1 = warning, 2 = error (you passed \"", error.value, "\").\n");
+ } else {
+ message.push(
+ "\tValue \"", error.value, "\" ", error.message, ".\n"
+ );
+ }
+ });
+
+ throw new Error(message.join(""));
+ }
+}
+
+/**
+ * Validates an environment object
+ * @param {object} environment The environment config object to validate.
+ * @param {string} source The location to report with any errors.
+ * @returns {void}
+ */
+function validateEnvironment(environment, source) {
+
+ // not having an environment is ok
+ if (!environment) {
+ return;
+ }
+
+ if (Array.isArray(environment)) {
+ throw new Error("Environment must not be an array");
+ }
+
+ if (typeof environment === "object") {
+ Object.keys(environment).forEach(function(env) {
+ if (!environments[env]) {
+ var message = [
+ source, ":\n",
+ "\tEnvironment key \"", env, "\" is unknown\n"
+ ];
+ throw new Error(message.join(""));
+ }
+ });
+ } else {
+ throw new Error("Environment must be an object");
+ }
+}
+
+/**
+ * Validates an entire config object.
+ * @param {object} config The config object to validate.
+ * @param {string} source The location to report with any errors.
+ * @returns {void}
+ */
+function validate(config, source) {
+
+ if (typeof config.rules === "object") {
+ Object.keys(config.rules).forEach(function(id) {
+ validateRuleOptions(id, config.rules[id], source);
+ });
+ }
+
+ validateEnvironment(config.env, source);
+}
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+module.exports = {
+ getRuleOptionsSchema: getRuleOptionsSchema,
+ validate: validate,
+ validateRuleOptions: validateRuleOptions
+};
+
+},{"../../conf/environments":2,"../rules":119,"is-my-json-valid":103}],116:[function(require,module,exports){
+/**
* @fileoverview Main ESLint object.
* @author Nicholas C. Zakas
+ * @copyright 2013 Nicholas C. Zakas. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
-var estraverse = require("estraverse-fb"),
+var estraverse = require("./util/estraverse"),
escope = require("escope"),
environments = require("../conf/environments"),
+ blankScriptAST = require("../conf/blank-script.json"),
assign = require("object-assign"),
rules = require("./rules"),
- util = require("./util"),
RuleContext = require("./rule-context"),
timing = require("./timing"),
- createTokenStore = require("./token-store.js"),
+ SourceCode = require("./util/source-code"),
+ NodeEventGenerator = require("./util/node-event-generator"),
+ CommentEventGenerator = require("./util/comment-event-generator"),
EventEmitter = require("events").EventEmitter,
- escapeRegExp = require("escape-string-regexp");
+ ConfigOps = require("./config/config-ops"),
+ validator = require("./config/config-validator"),
+ replacements = require("../conf/replacements.json"),
+ assert = require("assert");
+var DEFAULT_PARSER = require("../conf/eslint.json").parser;
+
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
-// Have to modify estraverse until TryStatement.handlers is removed
-estraverse.VisitorKeys.TryStatement = ["block", "handlers", "finalizer"];
-
-// TODO: Remove when estraverse is updated
-estraverse.Syntax.ExportNamedDeclaration = "ExportNamedDeclaration";
-estraverse.Syntax.ExportDefaultDeclaration = "ExportDefaultDeclaration";
-estraverse.Syntax.ExportAllDeclaration = "ExportAllDeclaration";
-estraverse.Syntax.ExportSpecifier = "ExportSpecifier";
-estraverse.VisitorKeys.ExportNamedDeclaration = ["declaration", "specifies", "source"];
-estraverse.VisitorKeys.ExportAllDeclaration = ["source"];
-estraverse.VisitorKeys.ExportDefaultDeclaration = ["declaration"];
-estraverse.VisitorKeys.ExportNamedDeclaration = ["declaration", "specifiers", "source"];
-estraverse.VisitorKeys.ExportSpecifier = ["exported", "local"];
/**
* Parses a list of "name:boolean_value" or/and "name" options divided by comma or
* whitespace.
* @param {string} string The string to parse.
+ * @param {Comment} comment The comment node which has the string.
* @returns {Object} Result map object of names and boolean values
*/
-function parseBooleanConfig(string) {
+function parseBooleanConfig(string, comment) {
var items = {};
// Collapse whitespace around : to make parsing easier
string = string.replace(/\s*:\s*/g, ":");
// Collapse whitespace around ,
string = string.replace(/\s*,\s*/g, ",");
@@ -16889,11 +21602,14 @@
if (pos !== -1) {
value = name.substring(pos + 1, name.length);
name = name.substring(0, pos);
}
- items[name] = (value === "true");
+ items[name] = {
+ value: (value === "true"),
+ comment: comment
+ };
});
return items;
}
@@ -16907,18 +21623,18 @@
function parseJsonConfig(string, location, messages) {
var items = {};
string = string.replace(/([a-zA-Z0-9\-\/]+):/g, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/, "$1,");
try {
items = JSON.parse("{" + string + "}");
- } catch(ex) {
+ } catch (ex) {
messages.push({
fatal: true,
severity: 2,
message: "Failed to parse JSON from '" + string + "': " + ex.message,
line: location.start.line,
- column: location.start.column
+ column: location.start.column + 1
});
}
return items;
@@ -16942,75 +21658,69 @@
});
return items;
}
/**
- * @param {Scope} scope The scope object to check.
- * @param {string} name The name of the variable to look up.
- * @returns {Variable} The variable object if found or null if not.
- */
-function getVariable(scope, name) {
- var variable = null;
- scope.variables.some(function(v) {
- if (v.name === name) {
- variable = v;
- return true;
- } else {
- return false;
- }
-
- });
- return variable;
-}
-
-/**
* Ensures that variables representing built-in properties of the Global Object,
* and any globals declared by special block comments, are present in the global
* scope.
* @param {ASTNode} program The top node of the AST.
* @param {Scope} globalScope The global scope.
* @param {Object} config The existing configuration data.
* @returns {void}
*/
function addDeclaredGlobals(program, globalScope, config) {
var declaredGlobals = {},
+ exportedGlobals = {},
explicitGlobals = {},
builtin = environments.builtin;
assign(declaredGlobals, builtin);
- Object.keys(config.env).forEach(function (name) {
+ Object.keys(config.env).forEach(function(name) {
if (config.env[name]) {
var environmentGlobals = environments[name] && environments[name].globals;
if (environmentGlobals) {
assign(declaredGlobals, environmentGlobals);
}
}
});
+ assign(exportedGlobals, config.exported);
assign(declaredGlobals, config.globals);
assign(explicitGlobals, config.astGlobals);
Object.keys(declaredGlobals).forEach(function(name) {
- var variable = getVariable(globalScope, name);
+ var variable = globalScope.set.get(name);
if (!variable) {
variable = new escope.Variable(name, globalScope);
variable.eslintExplicitGlobal = false;
globalScope.variables.push(variable);
+ globalScope.set.set(name, variable);
}
variable.writeable = declaredGlobals[name];
});
Object.keys(explicitGlobals).forEach(function(name) {
- var variable = getVariable(globalScope, name);
+ var variable = globalScope.set.get(name);
if (!variable) {
variable = new escope.Variable(name, globalScope);
variable.eslintExplicitGlobal = true;
+ variable.eslintExplicitGlobalComment = explicitGlobals[name].comment;
globalScope.variables.push(variable);
+ globalScope.set.set(name, variable);
}
- variable.writeable = explicitGlobals[name];
+ variable.writeable = explicitGlobals[name].value;
});
+
+ // mark all exported variables as such
+ Object.keys(exportedGlobals).forEach(function(name) {
+ var variable = globalScope.set.get(name);
+ if (variable) {
+ variable.eslintUsed = true;
+ }
+ });
}
/**
* Add data to reporting configuration to disable reporting for list of rules
* starting from start location
@@ -17076,42 +21786,48 @@
/**
* Parses comments in file to extract file-specific config of rules, globals
* and environments and merges them with global config; also code blocks
* where reporting is disabled or enabled and merges them with reporting config.
+ * @param {string} filename The file being checked.
* @param {ASTNode} ast The top node of the AST.
* @param {Object} config The existing configuration data.
* @param {Object[]} reportingConfig The existing reporting configuration data.
* @param {Object[]} messages The messages queue.
- * @returns {void}
+ * @returns {object} Modified config object
*/
-function modifyConfigsFromComments(ast, config, reportingConfig, messages) {
+function modifyConfigsFromComments(filename, ast, config, reportingConfig, messages) {
var commentConfig = {
+ exported: {},
astGlobals: {},
rules: {},
env: {}
};
var commentRules = {};
ast.comments.forEach(function(comment) {
var value = comment.value.trim();
- var match = /^(eslint-\w+|eslint-\w+-\w+|eslint|globals?)(\s|$)/.exec(value);
+ var match = /^(eslint-\w+|eslint-\w+-\w+|eslint|exported|globals?)(\s|$)/.exec(value);
if (match) {
value = value.substring(match.index + match[1].length);
if (comment.type === "Block") {
switch (match[1]) {
+ case "exported":
+ assign(commentConfig.exported, parseBooleanConfig(value, comment));
+ break;
+
case "globals":
case "global":
- util.mixin(commentConfig.astGlobals, parseBooleanConfig(value));
+ assign(commentConfig.astGlobals, parseBooleanConfig(value, comment));
break;
case "eslint-env":
- util.mixin(commentConfig.env, parseListConfig(value));
+ assign(commentConfig.env, parseListConfig(value));
break;
case "eslint-disable":
disableReporting(reportingConfig, comment.loc.start, Object.keys(parseListConfig(value)));
break;
@@ -17122,13 +21838,12 @@
case "eslint":
var items = parseJsonConfig(value, comment.loc, messages);
Object.keys(items).forEach(function(name) {
var ruleValue = items[name];
- if (typeof ruleValue === "number" || (Array.isArray(ruleValue) && typeof ruleValue[0] === "number")) {
- commentRules[name] = ruleValue;
- }
+ validator.validateRuleOptions(name, ruleValue, filename + " line " + comment.loc.start.line);
+ commentRules[name] = ruleValue;
});
break;
// no default
}
@@ -17140,20 +21855,19 @@
}
}
}
});
- // apply environment rules before user rules
- Object.keys(commentConfig.env).forEach(function (name) {
- var environmentRules = environments[name] && environments[name].rules;
- if (commentConfig.env[name] && environmentRules) {
- util.mixin(commentConfig.rules, environmentRules);
+ // apply environment configs
+ Object.keys(commentConfig.env).forEach(function(name) {
+ if (environments[name]) {
+ commentConfig = ConfigOps.merge(commentConfig, environments[name]);
}
});
- util.mixin(commentConfig.rules, commentRules);
+ assign(commentConfig.rules, commentRules);
- util.mergeConfigs(config, commentConfig);
+ return ConfigOps.merge(config, commentConfig);
}
/**
* Check if message of rule with ruleId should be ignored in location
* @param {Object[]} reportingConfig Collection of ignore records
@@ -17205,33 +21919,90 @@
}
// merge in environment ecmaFeatures
if (typeof config.env === "object") {
Object.keys(config.env).forEach(function(env) {
- if (config.env[env] && environments[env].ecmaFeatures) {
+ if (config.env[env] && environments[env] && environments[env].ecmaFeatures) {
assign(ecmaFeatures, environments[env].ecmaFeatures);
}
});
}
preparedConfig = {
rules: copiedRules,
- parser: config.parser || "espree",
- globals: util.mergeConfigs({}, config.globals),
- env: util.mergeConfigs({}, config.env || {}),
- settings: util.mergeConfigs({}, config.settings || {}),
- ecmaFeatures: util.mergeConfigs(ecmaFeatures, config.ecmaFeatures || {})
+ parser: config.parser || DEFAULT_PARSER,
+ globals: ConfigOps.merge({}, config.globals),
+ env: ConfigOps.merge({}, config.env || {}),
+ settings: ConfigOps.merge({}, config.settings || {}),
+ ecmaFeatures: ConfigOps.merge(ecmaFeatures, config.ecmaFeatures || {})
};
// can't have global return inside of modules
if (preparedConfig.ecmaFeatures.modules) {
preparedConfig.ecmaFeatures.globalReturn = false;
}
return preparedConfig;
}
+/**
+ * Provide a stub rule with a given message
+ * @param {string} message The message to be displayed for the rule
+ * @returns {Function} Stub rule function
+ */
+function createStubRule(message) {
+
+ /**
+ * Creates a fake rule object
+ * @param {object} context context object for each rule
+ * @returns {object} collection of node to listen on
+ */
+ function createRuleModule(context) {
+ return {
+ Program: function(node) {
+ context.report(node, message);
+ }
+ };
+ }
+
+ if (message) {
+ return createRuleModule;
+ } else {
+ throw new Error("No message passed to stub rule");
+ }
+}
+
+/**
+ * Provide a rule replacement message
+ * @param {string} ruleId Name of the rule
+ * @returns {string} Message detailing rule replacement
+ */
+function getRuleReplacementMessage(ruleId) {
+ if (ruleId in replacements.rules) {
+ var newRules = replacements.rules[ruleId];
+ return "Rule \'" + ruleId + "\' was removed and replaced by: " + newRules.join(", ");
+ }
+}
+
+var eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g;
+
+/**
+ * Checks whether or not there is a comment which has "eslint-env *" in a given text.
+ * @param {string} text - A source code text to check.
+ * @returns {object|null} A result of parseListConfig() with "eslint-env *" comment.
+ */
+function findEslintEnv(text) {
+ var match, retv;
+
+ eslintEnvPattern.lastIndex = 0;
+ while ((match = eslintEnvPattern.exec(text))) {
+ retv = assign(retv || {}, parseListConfig(match[1]));
+ }
+
+ return retv;
+}
+
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
/**
@@ -17240,23 +22011,18 @@
*/
module.exports = (function() {
var api = Object.create(new EventEmitter()),
messages = [],
- currentText = null,
- currentTextLines = [],
currentConfig = null,
- currentTokens = null,
currentScopes = null,
scopeMap = null,
scopeManager = null,
currentFilename = null,
controller = null,
reportingConfig = [],
- commentLocsEnter = [],
- commentLocsExit = [],
- currentAST = null;
+ sourceCode = null;
/**
* Parses text into an AST. Moved out here because the try-catch prevents
* optimization of functions, so it's best to keep the try-catch as isolated
* as possible
@@ -17299,66 +22065,28 @@
attachComment: true,
ecmaFeatures: config.ecmaFeatures
});
} catch (ex) {
+ // If the message includes a leading line number, strip it:
+ var message = ex.message.replace(/^line \d+:/i, "").trim();
+
messages.push({
fatal: true,
severity: 2,
- // messages come as "Line X: Unexpected token foo", so strip off leading part
- message: ex.message.substring(ex.message.indexOf(":") + 1).trim(),
+ message: "Parsing error: " + message,
line: ex.lineNumber,
- column: ex.column
+ column: ex.column + 1
});
return null;
}
}
/**
- * Check collection of comments to prevent double event for comment as
- * leading and trailing, then emit event if passing
- * @param {ASTNode[]} comments Collection of comment nodes
- * @param {Object[]} locs List of locations of previous comment nodes
- * @param {string} eventName Event name postfix
- * @returns {void}
- */
- function emitComments(comments, locs, eventName) {
-
- if (comments.length) {
- comments.forEach(function(node) {
- if (locs.indexOf(node.loc) >= 0) {
- locs.splice(locs.indexOf(node.loc), 1);
- } else {
- locs.push(node.loc);
- api.emit(node.type + eventName, node);
- }
- });
- }
- }
-
- /**
- * Shortcut to check and emit enter of comment nodes
- * @param {ASTNode[]} comments Collection of comment nodes
- * @returns {void}
- */
- function emitCommentsEnter(comments) {
- emitComments(comments, commentLocsEnter, "Comment");
- }
-
- /**
- * Shortcut to check and emit exit of comment nodes
- * @param {ASTNode[]} comments Collection of comment nodes
- * @returns {void}
- */
- function emitCommentsExit(comments) {
- emitComments(comments, commentLocsExit, "Comment:exit");
- }
-
- /**
* Get the severity level of a rule (0 - none, 1 - warning, 2 - error)
* Returns 0 if the rule config is not valid (an Array or a number)
* @param {Array|number} ruleConfig rule configuration
* @returns {number} 0, 1, or 2, indicating rule severity
*/
@@ -17393,107 +22121,143 @@
* @returns {void}
*/
api.reset = function() {
this.removeAllListeners();
messages = [];
- currentAST = null;
currentConfig = null;
- currentText = null;
- currentTextLines = [];
- currentTokens = null;
currentScopes = null;
scopeMap = null;
scopeManager = null;
controller = null;
reportingConfig = [];
- commentLocsEnter = [];
- commentLocsExit = [];
+ sourceCode = null;
};
/**
* Verifies the text against the rules specified by the second argument.
- * @param {string} text The JavaScript text to verify.
+ * @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
* @param {Object} config An object whose keys specify the rules to use.
- * @param {string=} filename The optional filename of the file being checked.
- * If this is not set, the filename will default to '<input>' in the rule context.
- * @param {boolean=} saveState Indicates if the state from the last run should be saved.
+ * @param {(string|Object)} [filenameOrOptions] The optional filename of the file being checked.
+ * If this is not set, the filename will default to '<input>' in the rule context. If
+ * an object, then it has "filename", "saveState", and "allowInlineConfig" properties.
+ * @param {boolean} [saveState] Indicates if the state from the last run should be saved.
* Mostly useful for testing purposes.
+ * @param {boolean} [filenameOrOptions.allowInlineConfig] Allow/disallow inline comments' ability to change config once it is set. Defaults to true if not supplied.
+ * Useful if you want to validate JS without comments overriding rules.
* @returns {Object[]} The results as an array of messages or null if no messages.
*/
- api.verify = function(text, config, filename, saveState) {
+ api.verify = function(textOrSourceCode, config, filenameOrOptions, saveState) {
var ast,
shebang,
ecmaFeatures,
- ecmaVersion;
+ ecmaVersion,
+ allowInlineConfig,
+ text = (typeof textOrSourceCode === "string") ? textOrSourceCode : null;
- // set the current parsed filename
- currentFilename = filename;
+ // evaluate arguments
+ if (typeof filenameOrOptions === "object") {
+ currentFilename = filenameOrOptions.filename;
+ allowInlineConfig = filenameOrOptions.allowInlineConfig;
+ saveState = filenameOrOptions.saveState;
+ } else {
+ currentFilename = filenameOrOptions;
+ }
if (!saveState) {
this.reset();
}
- // there's no input, just exit here
- if (text.trim().length === 0) {
- currentText = text;
- return messages;
+ // search and apply "eslint-env *".
+ var envInFile = findEslintEnv(text || textOrSourceCode.text);
+ if (envInFile) {
+ if (!config || !config.env) {
+ config = assign({}, config || {}, {env: envInFile});
+ } else {
+ config = assign({}, config);
+ config.env = assign({}, config.env, envInFile);
+ }
}
// process initial config to make it safe to extend
config = prepareConfig(config || {});
- ast = parse(text.replace(/^#!([^\r\n]+)/, function(match, captured) {
- shebang = captured;
- return "//" + captured;
- }), config);
+ // only do this for text
+ if (text !== null) {
+ // there's no input, just exit here
+ if (text.trim().length === 0) {
+ sourceCode = new SourceCode(text, blankScriptAST);
+ return messages;
+ }
+
+ ast = parse(text.replace(/^#!([^\r\n]+)/, function(match, captured) {
+ shebang = captured;
+ return "//" + captured;
+ }), config);
+
+ if (ast) {
+ sourceCode = new SourceCode(text, ast);
+ }
+
+ } else {
+ sourceCode = textOrSourceCode;
+ ast = sourceCode.ast;
+ }
+
// if espree failed to parse the file, there's no sense in setting up rules
if (ast) {
- currentAST = ast;
-
// parse global comments and modify config
- modifyConfigsFromComments(ast, config, reportingConfig, messages);
+ if (allowInlineConfig !== false) {
+ config = modifyConfigsFromComments(currentFilename, ast, config, reportingConfig, messages);
+ }
// enable appropriate rules
Object.keys(config.rules).filter(function(key) {
return getRuleSeverity(config.rules[key]) > 0;
}).forEach(function(key) {
-
- var ruleCreator = rules.get(key),
- severity = getRuleSeverity(config.rules[key]),
- options = getRuleOptions(config.rules[key]),
+ var ruleCreator,
+ severity,
+ options,
rule;
- if (ruleCreator) {
- try {
- rule = ruleCreator(new RuleContext(
- key, api, severity, options,
- config.settings, config.ecmaFeatures
- ));
-
- // add all the node types as listeners
- Object.keys(rule).forEach(function(nodeType) {
- api.on(nodeType, timing.enabled
- ? timing.time(key, rule[nodeType])
- : rule[nodeType]
- );
- });
- } catch(ex) {
- ex.message = "Error while loading rule '" + key + "': " + ex.message;
- throw ex;
+ ruleCreator = rules.get(key);
+ if (!ruleCreator) {
+ var replacementMsg = getRuleReplacementMessage(key);
+ if (replacementMsg) {
+ ruleCreator = createStubRule(replacementMsg);
+ } else {
+ ruleCreator = createStubRule("Definition for rule '" + key + "' was not found");
}
+ rules.define(key, ruleCreator);
+ }
- } else {
- throw new Error("Definition for rule '" + key + "' was not found.");
+ severity = getRuleSeverity(config.rules[key]);
+ options = getRuleOptions(config.rules[key]);
+
+ try {
+ rule = ruleCreator(new RuleContext(
+ key, api, severity, options,
+ config.settings, config.ecmaFeatures
+ ));
+
+ // add all the node types as listeners
+ Object.keys(rule).forEach(function(nodeType) {
+ api.on(nodeType, timing.enabled
+ ? timing.time(key, rule[nodeType])
+ : rule[nodeType]
+ );
+ });
+ } catch (ex) {
+ ex.message = "Error while loading rule '" + key + "': " + ex.message;
+ throw ex;
}
});
// save config so rules can access as necessary
currentConfig = config;
- currentText = text;
controller = new estraverse.Controller();
ecmaFeatures = currentConfig.ecmaFeatures;
ecmaVersion = (ecmaFeatures.blockBindings || ecmaFeatures.classes ||
ecmaFeatures.modules || ecmaFeatures.defaultParams ||
@@ -17512,35 +22276,20 @@
/*
* Index the scopes by the start range of their block for efficient
* lookup in getScope.
*/
scopeMap = [];
- currentScopes.forEach(function (scope, index) {
+ currentScopes.forEach(function(scope, index) {
var range = scope.block.range[0];
// Sometimes two scopes are returned for a given node. This is
// handled later in a known way, so just don't overwrite here.
if (!scopeMap[range]) {
scopeMap[range] = index;
}
});
- /*
- * Split text here into array of lines so
- * it's not being done repeatedly
- * by individual rules.
- */
- currentTextLines = currentText.split(/\r?\n|\u2028|\u2029/g);
-
- // Freezing so array isn't accidentally changed by a rule.
- Object.freeze(currentTextLines);
-
- currentTokens = createTokenStore(ast.tokens);
- Object.keys(currentTokens).forEach(function(method) {
- api[method] = currentTokens[method];
- });
-
// augment global scope with declared global variables
addDeclaredGlobals(ast, currentScopes[0], currentConfig);
// remove shebang comments
if (shebang && ast.comments.length && ast.comments[0].value === shebang) {
@@ -17549,32 +22298,25 @@
if (ast.body.length && ast.body[0].leadingComments && ast.body[0].leadingComments[0].value === shebang) {
ast.body[0].leadingComments.splice(0, 1);
}
}
+ var eventGenerator = new NodeEventGenerator(api);
+ eventGenerator = new CommentEventGenerator(eventGenerator, sourceCode);
+
/*
* Each node has a type property. Whenever a particular type of node is found,
* an event is fired. This allows any listeners to automatically be informed
* that this type of node has been found and react accordingly.
*/
controller.traverse(ast, {
enter: function(node, parent) {
-
- var comments = api.getComments(node);
-
- emitCommentsEnter(comments.leading);
node.parent = parent;
- api.emit(node.type, node);
- emitCommentsEnter(comments.trailing);
+ eventGenerator.enterNode(node);
},
leave: function(node) {
-
- var comments = api.getComments(node);
-
- emitCommentsExit(comments.trailing);
- api.emit(node.type + ":exit", node);
- emitCommentsExit(comments.leading);
+ eventGenerator.leaveNode(node);
}
});
}
@@ -17601,225 +22343,186 @@
* numbers. If location is not provided the node's start location will
* be used.
* @param {string} message The actual message.
* @param {Object} opts Optional template data which produces a formatted message
* with symbols being replaced by this object's values.
+ * @param {Object} fix A fix command description.
* @returns {void}
*/
- api.report = function(ruleId, severity, node, location, message, opts) {
+ api.report = function(ruleId, severity, node, location, message, opts, fix) {
+ if (node) {
+ assert.strictEqual(typeof node, "object", "Node must be an object");
+ }
if (typeof location === "string") {
+ assert.ok(node, "Node must be provided when reporting error if location is not provided");
+
+ fix = opts;
opts = message;
message = location;
location = node.loc.start;
}
+ // else, assume location was provided, so node may be omitted
- Object.keys(opts || {}).forEach(function (key) {
- var rx = new RegExp("{{" + escapeRegExp(key) + "}}", "g");
- message = message.replace(rx, opts[key]);
- });
-
if (isDisabledByReportingConfig(reportingConfig, ruleId, location)) {
return;
}
- messages.push({
+ if (opts) {
+ message = message.replace(/\{\{\s*(.+?)\s*\}\}/g, function(fullMatch, term) {
+ if (term in opts) {
+ return opts[term];
+ }
+
+ // Preserve old behavior: If parameter name not provided, don't replace it.
+ return fullMatch;
+ });
+ }
+
+ var problem = {
ruleId: ruleId,
severity: severity,
message: message,
line: location.line,
- column: location.column,
- nodeType: node.type,
- source: currentTextLines[location.line - 1] || ""
- });
- };
+ column: location.column + 1, // switch to 1-base instead of 0-base
+ nodeType: node && node.type,
+ source: sourceCode.lines[location.line - 1] || ""
+ };
- /**
- * Gets the source code for the given node.
- * @param {ASTNode=} node The AST node to get the text for.
- * @param {int=} beforeCount The number of characters before the node to retrieve.
- * @param {int=} afterCount The number of characters after the node to retrieve.
- * @returns {string} The text representing the AST node.
- */
- api.getSource = function(node, beforeCount, afterCount) {
- if (node) {
- return (currentText !== null) ? currentText.slice(Math.max(node.range[0] - (beforeCount || 0), 0),
- node.range[1] + (afterCount || 0)) : null;
- } else {
- return currentText;
+ // ensure there's range and text properties, otherwise it's not a valid fix
+ if (fix && Array.isArray(fix.range) && (typeof fix.text === "string")) {
+ problem.fix = fix;
}
+ messages.push(problem);
};
/**
- * Gets the entire source text split into an array of lines.
- * @returns {Array} The source text as an array of lines.
+ * Gets the SourceCode object representing the parsed source.
+ * @returns {SourceCode} The SourceCode object.
*/
- api.getSourceLines = function() {
- return currentTextLines;
+ api.getSourceCode = function() {
+ return sourceCode;
};
- /**
- * Retrieves an array containing all comments in the source code.
- * @returns {ASTNode[]} An array of comment nodes.
- */
- api.getAllComments = function() {
- return currentAST.comments;
+ // methods that exist on SourceCode object
+ var externalMethods = {
+ getSource: "getText",
+ getSourceLines: "getLines",
+ getAllComments: "getAllComments",
+ getNodeByRangeIndex: "getNodeByRangeIndex",
+ getComments: "getComments",
+ getJSDocComment: "getJSDocComment",
+ getFirstToken: "getFirstToken",
+ getFirstTokens: "getFirstTokens",
+ getLastToken: "getLastToken",
+ getLastTokens: "getLastTokens",
+ getTokenAfter: "getTokenAfter",
+ getTokenBefore: "getTokenBefore",
+ getTokenByRangeStart: "getTokenByRangeStart",
+ getTokens: "getTokens",
+ getTokensAfter: "getTokensAfter",
+ getTokensBefore: "getTokensBefore",
+ getTokensBetween: "getTokensBetween"
};
- /**
- * Gets all comments for the given node.
- * @param {ASTNode} node The AST node to get the comments for.
- * @returns {Object} The list of comments indexed by their position.
- */
- api.getComments = function(node) {
+ // copy over methods
+ Object.keys(externalMethods).forEach(function(methodName) {
+ var exMethodName = externalMethods[methodName];
- var leadingComments = node.leadingComments || [],
- trailingComments = node.trailingComments || [];
-
- /*
- * espree adds a "comments" array on Program nodes rather than
- * leadingComments/trailingComments. Comments are only left in the
- * Program node comments array if there is no executable code.
- */
- if (node.type === "Program") {
- if (node.body.length === 0) {
- leadingComments = node.comments;
+ // All functions expected to have less arguments than 5.
+ api[methodName] = function(a, b, c, d, e) {
+ if (sourceCode) {
+ return sourceCode[exMethodName](a, b, c, d, e);
}
- }
-
- return {
- leading: leadingComments,
- trailing: trailingComments
+ return null;
};
- };
+ });
/**
- * Retrieves the JSDoc comment for a given node.
- * @param {ASTNode} node The AST node to get the comment for.
- * @returns {ASTNode} The BlockComment node containing the JSDoc for the
- * given node or null if not found.
- */
- api.getJSDocComment = function(node) {
-
- var parent = node.parent,
- line = node.loc.start.line;
-
- /**
- * Finds a JSDoc comment node in an array of comment nodes.
- * @param {ASTNode[]} comments The array of comment nodes to search.
- * @returns {ASTNode} The node if found, null if not.
- * @private
- */
- function findJSDocComment(comments) {
-
- if (comments) {
- for (var i = comments.length - 1; i >= 0; i--) {
- if (comments[i].type === "Block" && comments[i].value.charAt(0) === "*") {
-
- if (line - comments[i].loc.end.line <= 1) {
- return comments[i];
- } else {
- break;
- }
- }
- }
- }
-
- return null;
- }
-
- switch (node.type) {
- case "FunctionDeclaration":
- return findJSDocComment(node.leadingComments);
-
- case "ArrowFunctionExpression":
- case "FunctionExpression":
-
- if (parent.type !== "CallExpression" || parent.callee !== node) {
- while (parent && !parent.leadingComments && !/Function/.test(parent.type)) {
- parent = parent.parent;
- }
-
- return parent && (parent.type !== "FunctionDeclaration") ? findJSDocComment(parent.leadingComments) : null;
- }
-
- // falls through
-
- default:
- return null;
- }
- };
-
- /**
* Gets nodes that are ancestors of current node.
* @returns {ASTNode[]} Array of objects representing ancestors.
*/
api.getAncestors = function() {
return controller.parents();
};
/**
- * Gets the deepest node containing a range index.
- * @param {int} index Range index of the desired node.
- * @returns {ASTNode} [description]
- */
- api.getNodeByRangeIndex = function(index) {
- var result = null;
-
- estraverse.traverse(controller.root, {
- enter: function (node) {
- if (node.range[0] <= index && index < node.range[1]) {
- result = node;
- } else {
- this.skip();
- }
- },
- leave: function (node) {
- if (node === result) {
- this.break();
- }
- }
- });
-
- return result;
- };
-
- /**
* Gets the scope for the current node.
* @returns {Object} An object representing the current node's scope.
*/
api.getScope = function() {
var parents = controller.parents(),
scope = currentScopes[0];
// Don't do this for Program nodes - they have no parents
if (parents.length) {
- // if current node is function declaration, add it to the list
+ // if current node introduces a scope, add it to the list
var current = controller.current();
- if (["FunctionDeclaration", "FunctionExpression",
- "ArrowFunctionExpression"].indexOf(current.type) >= 0) {
- parents.push(current);
+ if (currentConfig.ecmaFeatures.blockBindings) {
+ if (["BlockStatement", "SwitchStatement", "CatchClause", "FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].indexOf(current.type) >= 0) {
+ parents.push(current);
+ }
+ } else {
+ if (["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].indexOf(current.type) >= 0) {
+ parents.push(current);
+ }
}
// Ascend the current node's parents
for (var i = parents.length - 1; i >= 0; --i) {
- scope = scopeManager.acquire(parents[i]);
+ // Get the innermost scope
+ scope = scopeManager.acquire(parents[i], true);
if (scope) {
- return scope;
+ if (scope.type === "function-expression-name") {
+ return scope.childScopes[0];
+ } else {
+ return scope;
+ }
}
}
}
return currentScopes[0];
};
/**
+ * Record that a particular variable has been used in code
+ * @param {string} name The name of the variable to mark as used
+ * @returns {boolean} True if the variable was found and marked as used,
+ * false if not.
+ */
+ api.markVariableAsUsed = function(name) {
+ var scope = this.getScope(),
+ specialScope = currentConfig.ecmaFeatures.globalReturn || currentConfig.ecmaFeatures.modules,
+ variables,
+ i,
+ len;
+
+ // Special Node.js scope means we need to start one level deeper
+ if (scope.type === "global" && specialScope) {
+ scope = scope.childScopes[0];
+ }
+
+ do {
+ variables = scope.variables;
+ for (i = 0, len = variables.length; i < len; i++) {
+ if (variables[i].name === name) {
+ variables[i].eslintUsed = true;
+ return true;
+ }
+ }
+ } while ( (scope = scope.upper) );
+
+ return false;
+ };
+
+ /**
* Gets the filename for the currently parsed source.
* @returns {string} The filename associated with the source being parsed.
* Defaults to "<input>" if no filename info is present.
*/
api.getFilename = function() {
@@ -17857,158 +22560,221 @@
*/
api.defaults = function() {
return require("../conf/eslint.json");
};
+ /**
+ * Gets variables that are declared by a specified node.
+ *
+ * The variables are its `defs[].node` or `defs[].parent` is same as the specified node.
+ * Specifically, below:
+ *
+ * - `VariableDeclaration` - variables of its all declarators.
+ * - `VariableDeclarator` - variables.
+ * - `FunctionDeclaration`/`FunctionExpression` - its function name and parameters.
+ * - `ArrowFunctionExpression` - its parameters.
+ * - `ClassDeclaration`/`ClassExpression` - its class name.
+ * - `CatchClause` - variables of its exception.
+ * - `ImportDeclaration` - variables of its all specifiers.
+ * - `ImportSpecifier`/`ImportDefaultSpecifier`/`ImportNamespaceSpecifier` - a variable.
+ * - others - always an empty array.
+ *
+ * @param {ASTNode} node A node to get.
+ * @returns {escope.Variable[]} Variables that are declared by the node.
+ */
+ api.getDeclaredVariables = function(node) {
+ return (scopeManager && scopeManager.getDeclaredVariables(node)) || [];
+ };
+
return api;
}());
-},{"../conf/environments":1,"../conf/eslint.json":2,"./rule-context":134,"./rules":135,"./timing":285,"./token-store.js":286,"./util":287,"escape-string-regexp":18,"escope":19,"estraverse-fb":125,"events":4,"object-assign":131}],133:[function(require,module,exports){
+},{"../conf/blank-script.json":1,"../conf/environments":2,"../conf/eslint.json":3,"../conf/replacements.json":4,"./config/config-ops":114,"./config/config-validator":115,"./rule-context":118,"./rules":119,"./timing":309,"./util/comment-event-generator":311,"./util/estraverse":312,"./util/node-event-generator":314,"./util/source-code":316,"assert":5,"escope":76,"events":96,"object-assign":108}],117:[function(require,module,exports){
module.exports = function() {
var rules = Object.create(null);
+ rules["accessor-pairs"] = require("./rules/accessor-pairs");
+ rules["array-bracket-spacing"] = require("./rules/array-bracket-spacing");
+ rules["arrow-body-style"] = require("./rules/arrow-body-style");
+ rules["arrow-parens"] = require("./rules/arrow-parens");
+ rules["arrow-spacing"] = require("./rules/arrow-spacing");
rules["block-scoped-var"] = require("./rules/block-scoped-var");
+ rules["block-spacing"] = require("./rules/block-spacing");
rules["brace-style"] = require("./rules/brace-style");
+ rules["callback-return"] = require("./rules/callback-return");
rules["camelcase"] = require("./rules/camelcase");
rules["comma-dangle"] = require("./rules/comma-dangle");
rules["comma-spacing"] = require("./rules/comma-spacing");
rules["comma-style"] = require("./rules/comma-style");
rules["complexity"] = require("./rules/complexity");
+ rules["computed-property-spacing"] = require("./rules/computed-property-spacing");
rules["consistent-return"] = require("./rules/consistent-return");
rules["consistent-this"] = require("./rules/consistent-this");
+ rules["constructor-super"] = require("./rules/constructor-super");
rules["curly"] = require("./rules/curly");
rules["default-case"] = require("./rules/default-case");
+ rules["dot-location"] = require("./rules/dot-location");
rules["dot-notation"] = require("./rules/dot-notation");
rules["eol-last"] = require("./rules/eol-last");
rules["eqeqeq"] = require("./rules/eqeqeq");
rules["func-names"] = require("./rules/func-names");
rules["func-style"] = require("./rules/func-style");
- rules["generator-star"] = require("./rules/generator-star");
- rules["global-strict"] = require("./rules/global-strict");
+ rules["generator-star-spacing"] = require("./rules/generator-star-spacing");
+ rules["global-require"] = require("./rules/global-require");
rules["guard-for-in"] = require("./rules/guard-for-in");
rules["handle-callback-err"] = require("./rules/handle-callback-err");
+ rules["id-length"] = require("./rules/id-length");
+ rules["id-match"] = require("./rules/id-match");
rules["indent"] = require("./rules/indent");
+ rules["init-declarations"] = require("./rules/init-declarations");
+ rules["jsx-quotes"] = require("./rules/jsx-quotes");
rules["key-spacing"] = require("./rules/key-spacing");
+ rules["linebreak-style"] = require("./rules/linebreak-style");
+ rules["lines-around-comment"] = require("./rules/lines-around-comment");
rules["max-depth"] = require("./rules/max-depth");
rules["max-len"] = require("./rules/max-len");
rules["max-nested-callbacks"] = require("./rules/max-nested-callbacks");
rules["max-params"] = require("./rules/max-params");
rules["max-statements"] = require("./rules/max-statements");
rules["new-cap"] = require("./rules/new-cap");
rules["new-parens"] = require("./rules/new-parens");
+ rules["newline-after-var"] = require("./rules/newline-after-var");
rules["no-alert"] = require("./rules/no-alert");
rules["no-array-constructor"] = require("./rules/no-array-constructor");
+ rules["no-arrow-condition"] = require("./rules/no-arrow-condition");
rules["no-bitwise"] = require("./rules/no-bitwise");
rules["no-caller"] = require("./rules/no-caller");
+ rules["no-case-declarations"] = require("./rules/no-case-declarations");
rules["no-catch-shadow"] = require("./rules/no-catch-shadow");
- rules["no-comma-dangle"] = require("./rules/no-comma-dangle");
+ rules["no-class-assign"] = require("./rules/no-class-assign");
rules["no-cond-assign"] = require("./rules/no-cond-assign");
rules["no-console"] = require("./rules/no-console");
+ rules["no-const-assign"] = require("./rules/no-const-assign");
rules["no-constant-condition"] = require("./rules/no-constant-condition");
+ rules["no-continue"] = require("./rules/no-continue");
rules["no-control-regex"] = require("./rules/no-control-regex");
rules["no-debugger"] = require("./rules/no-debugger");
rules["no-delete-var"] = require("./rules/no-delete-var");
rules["no-div-regex"] = require("./rules/no-div-regex");
rules["no-dupe-args"] = require("./rules/no-dupe-args");
+ rules["no-dupe-class-members"] = require("./rules/no-dupe-class-members");
rules["no-dupe-keys"] = require("./rules/no-dupe-keys");
+ rules["no-duplicate-case"] = require("./rules/no-duplicate-case");
rules["no-else-return"] = require("./rules/no-else-return");
- rules["no-empty-class"] = require("./rules/no-empty-class");
+ rules["no-empty-character-class"] = require("./rules/no-empty-character-class");
rules["no-empty-label"] = require("./rules/no-empty-label");
+ rules["no-empty-pattern"] = require("./rules/no-empty-pattern");
rules["no-empty"] = require("./rules/no-empty");
rules["no-eq-null"] = require("./rules/no-eq-null");
rules["no-eval"] = require("./rules/no-eval");
rules["no-ex-assign"] = require("./rules/no-ex-assign");
rules["no-extend-native"] = require("./rules/no-extend-native");
rules["no-extra-bind"] = require("./rules/no-extra-bind");
rules["no-extra-boolean-cast"] = require("./rules/no-extra-boolean-cast");
rules["no-extra-parens"] = require("./rules/no-extra-parens");
rules["no-extra-semi"] = require("./rules/no-extra-semi");
- rules["no-extra-strict"] = require("./rules/no-extra-strict");
rules["no-fallthrough"] = require("./rules/no-fallthrough");
rules["no-floating-decimal"] = require("./rules/no-floating-decimal");
rules["no-func-assign"] = require("./rules/no-func-assign");
+ rules["no-implicit-coercion"] = require("./rules/no-implicit-coercion");
rules["no-implied-eval"] = require("./rules/no-implied-eval");
rules["no-inline-comments"] = require("./rules/no-inline-comments");
rules["no-inner-declarations"] = require("./rules/no-inner-declarations");
rules["no-invalid-regexp"] = require("./rules/no-invalid-regexp");
+ rules["no-invalid-this"] = require("./rules/no-invalid-this");
rules["no-irregular-whitespace"] = require("./rules/no-irregular-whitespace");
rules["no-iterator"] = require("./rules/no-iterator");
rules["no-label-var"] = require("./rules/no-label-var");
rules["no-labels"] = require("./rules/no-labels");
rules["no-lone-blocks"] = require("./rules/no-lone-blocks");
rules["no-lonely-if"] = require("./rules/no-lonely-if");
rules["no-loop-func"] = require("./rules/no-loop-func");
+ rules["no-magic-numbers"] = require("./rules/no-magic-numbers");
rules["no-mixed-requires"] = require("./rules/no-mixed-requires");
rules["no-mixed-spaces-and-tabs"] = require("./rules/no-mixed-spaces-and-tabs");
rules["no-multi-spaces"] = require("./rules/no-multi-spaces");
rules["no-multi-str"] = require("./rules/no-multi-str");
rules["no-multiple-empty-lines"] = require("./rules/no-multiple-empty-lines");
rules["no-native-reassign"] = require("./rules/no-native-reassign");
+ rules["no-negated-condition"] = require("./rules/no-negated-condition");
rules["no-negated-in-lhs"] = require("./rules/no-negated-in-lhs");
rules["no-nested-ternary"] = require("./rules/no-nested-ternary");
rules["no-new-func"] = require("./rules/no-new-func");
rules["no-new-object"] = require("./rules/no-new-object");
rules["no-new-require"] = require("./rules/no-new-require");
rules["no-new-wrappers"] = require("./rules/no-new-wrappers");
rules["no-new"] = require("./rules/no-new");
rules["no-obj-calls"] = require("./rules/no-obj-calls");
rules["no-octal-escape"] = require("./rules/no-octal-escape");
rules["no-octal"] = require("./rules/no-octal");
+ rules["no-param-reassign"] = require("./rules/no-param-reassign");
rules["no-path-concat"] = require("./rules/no-path-concat");
rules["no-plusplus"] = require("./rules/no-plusplus");
rules["no-process-env"] = require("./rules/no-process-env");
rules["no-process-exit"] = require("./rules/no-process-exit");
rules["no-proto"] = require("./rules/no-proto");
rules["no-redeclare"] = require("./rules/no-redeclare");
rules["no-regex-spaces"] = require("./rules/no-regex-spaces");
- rules["no-reserved-keys"] = require("./rules/no-reserved-keys");
rules["no-restricted-modules"] = require("./rules/no-restricted-modules");
+ rules["no-restricted-syntax"] = require("./rules/no-restricted-syntax");
rules["no-return-assign"] = require("./rules/no-return-assign");
rules["no-script-url"] = require("./rules/no-script-url");
rules["no-self-compare"] = require("./rules/no-self-compare");
rules["no-sequences"] = require("./rules/no-sequences");
rules["no-shadow-restricted-names"] = require("./rules/no-shadow-restricted-names");
rules["no-shadow"] = require("./rules/no-shadow");
- rules["no-space-before-semi"] = require("./rules/no-space-before-semi");
rules["no-spaced-func"] = require("./rules/no-spaced-func");
rules["no-sparse-arrays"] = require("./rules/no-sparse-arrays");
rules["no-sync"] = require("./rules/no-sync");
rules["no-ternary"] = require("./rules/no-ternary");
+ rules["no-this-before-super"] = require("./rules/no-this-before-super");
rules["no-throw-literal"] = require("./rules/no-throw-literal");
rules["no-trailing-spaces"] = require("./rules/no-trailing-spaces");
rules["no-undef-init"] = require("./rules/no-undef-init");
rules["no-undef"] = require("./rules/no-undef");
rules["no-undefined"] = require("./rules/no-undefined");
rules["no-underscore-dangle"] = require("./rules/no-underscore-dangle");
+ rules["no-unexpected-multiline"] = require("./rules/no-unexpected-multiline");
+ rules["no-unneeded-ternary"] = require("./rules/no-unneeded-ternary");
rules["no-unreachable"] = require("./rules/no-unreachable");
rules["no-unused-expressions"] = require("./rules/no-unused-expressions");
rules["no-unused-vars"] = require("./rules/no-unused-vars");
rules["no-use-before-define"] = require("./rules/no-use-before-define");
+ rules["no-useless-call"] = require("./rules/no-useless-call");
+ rules["no-useless-concat"] = require("./rules/no-useless-concat");
rules["no-var"] = require("./rules/no-var");
rules["no-void"] = require("./rules/no-void");
rules["no-warning-comments"] = require("./rules/no-warning-comments");
rules["no-with"] = require("./rules/no-with");
- rules["no-wrap-func"] = require("./rules/no-wrap-func");
+ rules["object-curly-spacing"] = require("./rules/object-curly-spacing");
+ rules["object-shorthand"] = require("./rules/object-shorthand");
rules["one-var"] = require("./rules/one-var");
rules["operator-assignment"] = require("./rules/operator-assignment");
+ rules["operator-linebreak"] = require("./rules/operator-linebreak");
rules["padded-blocks"] = require("./rules/padded-blocks");
+ rules["prefer-arrow-callback"] = require("./rules/prefer-arrow-callback");
+ rules["prefer-const"] = require("./rules/prefer-const");
+ rules["prefer-reflect"] = require("./rules/prefer-reflect");
+ rules["prefer-spread"] = require("./rules/prefer-spread");
+ rules["prefer-template"] = require("./rules/prefer-template");
rules["quote-props"] = require("./rules/quote-props");
rules["quotes"] = require("./rules/quotes");
rules["radix"] = require("./rules/radix");
+ rules["require-jsdoc"] = require("./rules/require-jsdoc");
+ rules["require-yield"] = require("./rules/require-yield");
rules["semi-spacing"] = require("./rules/semi-spacing");
rules["semi"] = require("./rules/semi");
rules["sort-vars"] = require("./rules/sort-vars");
- rules["space-after-function-name"] = require("./rules/space-after-function-name");
rules["space-after-keywords"] = require("./rules/space-after-keywords");
rules["space-before-blocks"] = require("./rules/space-before-blocks");
- rules["space-before-function-parentheses"] = require("./rules/space-before-function-parentheses");
- rules["space-in-brackets"] = require("./rules/space-in-brackets");
+ rules["space-before-function-paren"] = require("./rules/space-before-function-paren");
+ rules["space-before-keywords"] = require("./rules/space-before-keywords");
rules["space-in-parens"] = require("./rules/space-in-parens");
rules["space-infix-ops"] = require("./rules/space-infix-ops");
rules["space-return-throw-case"] = require("./rules/space-return-throw-case");
rules["space-unary-ops"] = require("./rules/space-unary-ops");
- rules["spaced-line-comment"] = require("./rules/spaced-line-comment");
+ rules["spaced-comment"] = require("./rules/spaced-comment");
rules["strict"] = require("./rules/strict");
rules["use-isnan"] = require("./rules/use-isnan");
rules["valid-jsdoc"] = require("./rules/valid-jsdoc");
rules["valid-typeof"] = require("./rules/valid-typeof");
rules["vars-on-top"] = require("./rules/vars-on-top");
@@ -18016,45 +22782,71 @@
rules["wrap-regex"] = require("./rules/wrap-regex");
rules["yoda"] = require("./rules/yoda");
return rules;
};
-},{"./rules/block-scoped-var":136,"./rules/brace-style":137,"./rules/camelcase":138,"./rules/comma-dangle":139,"./rules/comma-spacing":140,"./rules/comma-style":141,"./rules/complexity":142,"./rules/consistent-return":143,"./rules/consistent-this":144,"./rules/curly":145,"./rules/default-case":146,"./rules/dot-notation":147,"./rules/eol-last":148,"./rules/eqeqeq":149,"./rules/func-names":150,"./rules/func-style":151,"./rules/generator-star":152,"./rules/global-strict":153,"./rules/guard-for-in":154,"./rules/handle-callback-err":155,"./rules/indent":156,"./rules/key-spacing":157,"./rules/max-depth":158,"./rules/max-len":159,"./rules/max-nested-callbacks":160,"./rules/max-params":161,"./rules/max-statements":162,"./rules/new-cap":163,"./rules/new-parens":164,"./rules/no-alert":165,"./rules/no-array-constructor":166,"./rules/no-bitwise":167,"./rules/no-caller":168,"./rules/no-catch-shadow":169,"./rules/no-comma-dangle":170,"./rules/no-cond-assign":171,"./rules/no-console":172,"./rules/no-constant-condition":173,"./rules/no-control-regex":174,"./rules/no-debugger":175,"./rules/no-delete-var":176,"./rules/no-div-regex":177,"./rules/no-dupe-args":178,"./rules/no-dupe-keys":179,"./rules/no-else-return":180,"./rules/no-empty":183,"./rules/no-empty-class":181,"./rules/no-empty-label":182,"./rules/no-eq-null":184,"./rules/no-eval":185,"./rules/no-ex-assign":186,"./rules/no-extend-native":187,"./rules/no-extra-bind":188,"./rules/no-extra-boolean-cast":189,"./rules/no-extra-parens":190,"./rules/no-extra-semi":191,"./rules/no-extra-strict":192,"./rules/no-fallthrough":193,"./rules/no-floating-decimal":194,"./rules/no-func-assign":195,"./rules/no-implied-eval":196,"./rules/no-inline-comments":197,"./rules/no-inner-declarations":198,"./rules/no-invalid-regexp":199,"./rules/no-irregular-whitespace":200,"./rules/no-iterator":201,"./rules/no-label-var":202,"./rules/no-labels":203,"./rules/no-lone-blocks":204,"./rules/no-lonely-if":205,"./rules/no-loop-func":206,"./rules/no-mixed-requires":207,"./rules/no-mixed-spaces-and-tabs":208,"./rules/no-multi-spaces":209,"./rules/no-multi-str":210,"./rules/no-multiple-empty-lines":211,"./rules/no-native-reassign":212,"./rules/no-negated-in-lhs":213,"./rules/no-nested-ternary":214,"./rules/no-new":219,"./rules/no-new-func":215,"./rules/no-new-object":216,"./rules/no-new-require":217,"./rules/no-new-wrappers":218,"./rules/no-obj-calls":220,"./rules/no-octal":222,"./rules/no-octal-escape":221,"./rules/no-path-concat":223,"./rules/no-plusplus":224,"./rules/no-process-env":225,"./rules/no-process-exit":226,"./rules/no-proto":227,"./rules/no-redeclare":228,"./rules/no-regex-spaces":229,"./rules/no-reserved-keys":230,"./rules/no-restricted-modules":231,"./rules/no-return-assign":232,"./rules/no-script-url":233,"./rules/no-self-compare":234,"./rules/no-sequences":235,"./rules/no-shadow":237,"./rules/no-shadow-restricted-names":236,"./rules/no-space-before-semi":238,"./rules/no-spaced-func":239,"./rules/no-sparse-arrays":240,"./rules/no-sync":241,"./rules/no-ternary":242,"./rules/no-throw-literal":243,"./rules/no-trailing-spaces":244,"./rules/no-undef":246,"./rules/no-undef-init":245,"./rules/no-undefined":247,"./rules/no-underscore-dangle":248,"./rules/no-unreachable":249,"./rules/no-unused-expressions":250,"./rules/no-unused-vars":251,"./rules/no-use-before-define":252,"./rules/no-var":253,"./rules/no-void":254,"./rules/no-warning-comments":255,"./rules/no-with":256,"./rules/no-wrap-func":257,"./rules/one-var":258,"./rules/operator-assignment":259,"./rules/padded-blocks":260,"./rules/quote-props":261,"./rules/quotes":262,"./rules/radix":263,"./rules/semi":265,"./rules/semi-spacing":264,"./rules/sort-vars":266,"./rules/space-after-function-name":267,"./rules/space-after-keywords":268,"./rules/space-before-blocks":269,"./rules/space-before-function-parentheses":270,"./rules/space-in-brackets":271,"./rules/space-in-parens":272,"./rules/space-infix-ops":273,"./rules/space-return-throw-case":274,"./rules/space-unary-ops":275,"./rules/spaced-line-comment":276,"./rules/strict":277,"./rules/use-isnan":278,"./rules/valid-jsdoc":279,"./rules/valid-typeof":280,"./rules/vars-on-top":281,"./rules/wrap-iife":282,"./rules/wrap-regex":283,"./rules/yoda":284}],134:[function(require,module,exports){
+},{"./rules/accessor-pairs":120,"./rules/array-bracket-spacing":121,"./rules/arrow-body-style":122,"./rules/arrow-parens":123,"./rules/arrow-spacing":124,"./rules/block-scoped-var":125,"./rules/block-spacing":126,"./rules/brace-style":127,"./rules/callback-return":128,"./rules/camelcase":129,"./rules/comma-dangle":130,"./rules/comma-spacing":131,"./rules/comma-style":132,"./rules/complexity":133,"./rules/computed-property-spacing":134,"./rules/consistent-return":135,"./rules/consistent-this":136,"./rules/constructor-super":137,"./rules/curly":138,"./rules/default-case":139,"./rules/dot-location":140,"./rules/dot-notation":141,"./rules/eol-last":142,"./rules/eqeqeq":143,"./rules/func-names":144,"./rules/func-style":145,"./rules/generator-star-spacing":146,"./rules/global-require":147,"./rules/guard-for-in":148,"./rules/handle-callback-err":149,"./rules/id-length":150,"./rules/id-match":151,"./rules/indent":152,"./rules/init-declarations":153,"./rules/jsx-quotes":154,"./rules/key-spacing":155,"./rules/linebreak-style":156,"./rules/lines-around-comment":157,"./rules/max-depth":158,"./rules/max-len":159,"./rules/max-nested-callbacks":160,"./rules/max-params":161,"./rules/max-statements":162,"./rules/new-cap":163,"./rules/new-parens":164,"./rules/newline-after-var":165,"./rules/no-alert":166,"./rules/no-array-constructor":167,"./rules/no-arrow-condition":168,"./rules/no-bitwise":169,"./rules/no-caller":170,"./rules/no-case-declarations":171,"./rules/no-catch-shadow":172,"./rules/no-class-assign":173,"./rules/no-cond-assign":174,"./rules/no-console":175,"./rules/no-const-assign":176,"./rules/no-constant-condition":177,"./rules/no-continue":178,"./rules/no-control-regex":179,"./rules/no-debugger":180,"./rules/no-delete-var":181,"./rules/no-div-regex":182,"./rules/no-dupe-args":183,"./rules/no-dupe-class-members":184,"./rules/no-dupe-keys":185,"./rules/no-duplicate-case":186,"./rules/no-else-return":187,"./rules/no-empty":191,"./rules/no-empty-character-class":188,"./rules/no-empty-label":189,"./rules/no-empty-pattern":190,"./rules/no-eq-null":192,"./rules/no-eval":193,"./rules/no-ex-assign":194,"./rules/no-extend-native":195,"./rules/no-extra-bind":196,"./rules/no-extra-boolean-cast":197,"./rules/no-extra-parens":198,"./rules/no-extra-semi":199,"./rules/no-fallthrough":200,"./rules/no-floating-decimal":201,"./rules/no-func-assign":202,"./rules/no-implicit-coercion":203,"./rules/no-implied-eval":204,"./rules/no-inline-comments":205,"./rules/no-inner-declarations":206,"./rules/no-invalid-regexp":207,"./rules/no-invalid-this":208,"./rules/no-irregular-whitespace":209,"./rules/no-iterator":210,"./rules/no-label-var":211,"./rules/no-labels":212,"./rules/no-lone-blocks":213,"./rules/no-lonely-if":214,"./rules/no-loop-func":215,"./rules/no-magic-numbers":216,"./rules/no-mixed-requires":217,"./rules/no-mixed-spaces-and-tabs":218,"./rules/no-multi-spaces":219,"./rules/no-multi-str":220,"./rules/no-multiple-empty-lines":221,"./rules/no-native-reassign":222,"./rules/no-negated-condition":223,"./rules/no-negated-in-lhs":224,"./rules/no-nested-ternary":225,"./rules/no-new":230,"./rules/no-new-func":226,"./rules/no-new-object":227,"./rules/no-new-require":228,"./rules/no-new-wrappers":229,"./rules/no-obj-calls":231,"./rules/no-octal":233,"./rules/no-octal-escape":232,"./rules/no-param-reassign":234,"./rules/no-path-concat":235,"./rules/no-plusplus":236,"./rules/no-process-env":237,"./rules/no-process-exit":238,"./rules/no-proto":239,"./rules/no-redeclare":240,"./rules/no-regex-spaces":241,"./rules/no-restricted-modules":242,"./rules/no-restricted-syntax":243,"./rules/no-return-assign":244,"./rules/no-script-url":245,"./rules/no-self-compare":246,"./rules/no-sequences":247,"./rules/no-shadow":249,"./rules/no-shadow-restricted-names":248,"./rules/no-spaced-func":250,"./rules/no-sparse-arrays":251,"./rules/no-sync":252,"./rules/no-ternary":253,"./rules/no-this-before-super":254,"./rules/no-throw-literal":255,"./rules/no-trailing-spaces":256,"./rules/no-undef":258,"./rules/no-undef-init":257,"./rules/no-undefined":259,"./rules/no-underscore-dangle":260,"./rules/no-unexpected-multiline":261,"./rules/no-unneeded-ternary":262,"./rules/no-unreachable":263,"./rules/no-unused-expressions":264,"./rules/no-unused-vars":265,"./rules/no-use-before-define":266,"./rules/no-useless-call":267,"./rules/no-useless-concat":268,"./rules/no-var":269,"./rules/no-void":270,"./rules/no-warning-comments":271,"./rules/no-with":272,"./rules/object-curly-spacing":273,"./rules/object-shorthand":274,"./rules/one-var":275,"./rules/operator-assignment":276,"./rules/operator-linebreak":277,"./rules/padded-blocks":278,"./rules/prefer-arrow-callback":279,"./rules/prefer-const":280,"./rules/prefer-reflect":281,"./rules/prefer-spread":282,"./rules/prefer-template":283,"./rules/quote-props":284,"./rules/quotes":285,"./rules/radix":286,"./rules/require-jsdoc":287,"./rules/require-yield":288,"./rules/semi":290,"./rules/semi-spacing":289,"./rules/sort-vars":291,"./rules/space-after-keywords":292,"./rules/space-before-blocks":293,"./rules/space-before-function-paren":294,"./rules/space-before-keywords":295,"./rules/space-in-parens":296,"./rules/space-infix-ops":297,"./rules/space-return-throw-case":298,"./rules/space-unary-ops":299,"./rules/spaced-comment":300,"./rules/strict":301,"./rules/use-isnan":302,"./rules/valid-jsdoc":303,"./rules/valid-typeof":304,"./rules/vars-on-top":305,"./rules/wrap-iife":306,"./rules/wrap-regex":307,"./rules/yoda":308}],118:[function(require,module,exports){
/**
* @fileoverview RuleContext utility for rules
* @author Nicholas C. Zakas
+ * @copyright 2013 Nicholas C. Zakas. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var RuleFixer = require("./util/rule-fixer");
+
+//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
var PASSTHROUGHS = [
- "getAllComments",
- "getAncestors",
- "getComments",
- "getFilename",
- "getFirstToken",
- "getFirstTokens",
- "getJSDocComment",
- "getLastToken",
- "getLastTokens",
- "getNodeByRangeIndex",
- "getScope",
- "getSource",
- "getSourceLines",
- "getTokenAfter",
- "getTokenBefore",
- "getTokenByRangeStart",
- "getTokens",
- "getTokensAfter",
- "getTokensBefore",
- "getTokensBetween"
- ];
+ "getAllComments",
+ "getAncestors",
+ "getComments",
+ "getDeclaredVariables",
+ "getFilename",
+ "getFirstToken",
+ "getFirstTokens",
+ "getJSDocComment",
+ "getLastToken",
+ "getLastTokens",
+ "getNodeByRangeIndex",
+ "getScope",
+ "getSource",
+ "getSourceLines",
+ "getTokenAfter",
+ "getTokenBefore",
+ "getTokenByRangeStart",
+ "getTokens",
+ "getTokensAfter",
+ "getTokensBefore",
+ "getTokensBetween",
+ "markVariableAsUsed",
+ "isMarkedAsUsed"
+];
//------------------------------------------------------------------------------
+// Typedefs
+//------------------------------------------------------------------------------
+
+/**
+ * An error message description
+ * @typedef {Object} MessageDescriptor
+ * @property {string} nodeType The type of node.
+ * @property {Location} loc The location of the problem.
+ * @property {string} message The problem message.
+ * @property {Object} [data] Optional data to use to fill in placeholders in the
+ * message.
+ * @property {Function} fix The function to call that creates a fix command.
+ */
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/**
* Acts as an abstraction layer between rules and the main eslint object.
@@ -18104,30 +22896,62 @@
};
}, this);
/**
* Passthrough to eslint.report() that automatically assigns the rule ID and severity.
- * @param {ASTNode} node The AST node related to the message.
+ * @param {ASTNode|MessageDescriptor} nodeOrDescriptor The AST node related to the message or a message
+ * descriptor.
* @param {Object=} location The location of the error.
* @param {string} message The message to display to the user.
* @param {Object} opts Optional template data which produces a formatted message
* with symbols being replaced by this object's values.
* @returns {void}
*/
- this.report = function(node, location, message, opts) {
- eslint.report(ruleId, severity, node, location, message, opts);
+ this.report = function(nodeOrDescriptor, location, message, opts) {
+
+ var descriptor,
+ fix = null;
+
+ // check to see if it's a new style call
+ if (arguments.length === 1) {
+ descriptor = nodeOrDescriptor;
+
+ // if there's a fix specified, get it
+ if (typeof descriptor.fix === "function") {
+ fix = descriptor.fix(new RuleFixer());
+ }
+
+ eslint.report(
+ ruleId, severity, descriptor.node,
+ descriptor.loc || descriptor.node.loc.start,
+ descriptor.message, descriptor.data, fix
+ );
+
+ return;
+ }
+
+ // old style call
+ eslint.report(ruleId, severity, nodeOrDescriptor, location, message, opts);
};
+ /**
+ * Passthrough to eslint.getSourceCode().
+ * @returns {SourceCode} The SourceCode object for the code.
+ */
+ this.getSourceCode = function() {
+ return eslint.getSourceCode();
+ };
+
}
RuleContext.prototype = {
constructor: RuleContext
};
module.exports = RuleContext;
-},{}],135:[function(require,module,exports){
+},{"./util/rule-fixer":315}],119:[function(require,module,exports){
/**
* @fileoverview Defines a storage for rules.
* @author Nicholas C. Zakas
*/
@@ -18157,12 +22981,10 @@
*/
function define(ruleId, ruleModule) {
rules[ruleId] = ruleModule;
}
-exports.define = define;
-
/**
* Loads and registers all rules from passed rules directory.
* @param {String} [rulesDir] Path to rules directory, may be relative. Defaults to `lib/rules`.
* @returns {void}
*/
@@ -18171,262 +22993,939 @@
Object.keys(newRules).forEach(function(ruleId) {
define(ruleId, newRules[ruleId]);
});
}
-exports.load = load;
-
/**
* Registers all given rules of a plugin.
* @param {Object} pluginRules A key/value map of rule definitions.
* @param {String} pluginName The name of the plugin without prefix (`eslint-plugin-`).
* @returns {void}
*/
-exports.import = function (pluginRules, pluginName) {
- Object.keys(pluginRules).forEach(function (ruleId) {
+function importPlugin(pluginRules, pluginName) {
+ Object.keys(pluginRules).forEach(function(ruleId) {
var qualifiedRuleId = pluginName + "/" + ruleId,
rule = pluginRules[ruleId];
define(qualifiedRuleId, rule);
});
-};
+}
/**
* Access rule handler by id (file name).
* @param {String} ruleId Rule id (file name).
* @returns {Function} Rule handler.
*/
-exports.get = function(ruleId) {
- return rules[ruleId];
-};
+function get(ruleId) {
+ if (typeof rules[ruleId] === "string") {
+ return require(rules[ruleId]);
+ } else {
+ return rules[ruleId];
+ }
+}
/**
* Reset rules storage.
* Should be used only in tests.
* @returns {void}
*/
-exports.testClear = function() {
+function testClear() {
rules = Object.create(null);
+}
+
+module.exports = {
+ define: define,
+ load: load,
+ import: importPlugin,
+ get: get,
+ testClear: testClear
};
//------------------------------------------------------------------------------
// Initialization
//------------------------------------------------------------------------------
// loads built-in rules
load();
-},{"./load-rules":133}],136:[function(require,module,exports){
+},{"./load-rules":117}],120:[function(require,module,exports){
/**
- * @fileoverview Rule to check for "block scoped" variables by binding context
- * @author Matt DuVall <http://www.mattduvall.com>
+ * @fileoverview Rule to flag wrapping non-iife in parens
+ * @author Gyandeep Singh
+ * @copyright 2015 Gyandeep Singh. All rights reserved.
*/
+
"use strict";
//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether or not a given node is an `Identifier` node which was named a given name.
+ * @param {ASTNode} node - A node to check.
+ * @param {string} name - An expected name of the node.
+ * @returns {boolean} `true` if the node is an `Identifier` node which was named as expected.
+ */
+function isIdentifier(node, name) {
+ return node.type === "Identifier" && node.name === name;
+}
+
+/**
+ * Checks whether or not a given node is an argument of a specified method call.
+ * @param {ASTNode} node - A node to check.
+ * @param {number} index - An expected index of the node in arguments.
+ * @param {string} object - An expected name of the object of the method.
+ * @param {string} property - An expected name of the method.
+ * @returns {boolean} `true` if the node is an argument of the specified method call.
+ */
+function isArgumentOfMethodCall(node, index, object, property) {
+ var parent = node.parent;
+ return (
+ parent.type === "CallExpression" &&
+ parent.callee.type === "MemberExpression" &&
+ parent.callee.computed === false &&
+ isIdentifier(parent.callee.object, object) &&
+ isIdentifier(parent.callee.property, property) &&
+ parent.arguments[index] === node
+ );
+}
+
+/**
+ * Checks whether or not a given node is a property descriptor.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} `true` if the node is a property descriptor.
+ */
+function isPropertyDescriptor(node) {
+ // Object.defineProperty(obj, "foo", {set: ...})
+ if (isArgumentOfMethodCall(node, 2, "Object", "defineProperty") ||
+ isArgumentOfMethodCall(node, 2, "Reflect", "defineProperty")
+ ) {
+ return true;
+ }
+
+ // Object.defineProperties(obj, {foo: {set: ...}})
+ // Object.create(proto, {foo: {set: ...}})
+ node = node.parent.parent;
+ return node.type === "ObjectExpression" && (
+ isArgumentOfMethodCall(node, 1, "Object", "create") ||
+ isArgumentOfMethodCall(node, 1, "Object", "defineProperties")
+ );
+}
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var config = context.options[0] || {};
+ var checkGetWithoutSet = config.getWithoutSet === true;
+ var checkSetWithoutGet = config.setWithoutGet !== false;
- var scopeStack = [];
+ /**
+ * Checks a object expression to see if it has setter and getter both present or none.
+ * @param {ASTNode} node The node to check.
+ * @returns {void}
+ * @private
+ */
+ function checkLonelySetGet(node) {
+ var isSetPresent = false;
+ var isGetPresent = false;
+ var isDescriptor = isPropertyDescriptor(node);
+ for (var i = 0, end = node.properties.length; i < end; i++) {
+ var property = node.properties[i];
+
+ var propToCheck = "";
+ if (property.kind === "init") {
+ if (isDescriptor && !property.computed) {
+ propToCheck = property.key.name;
+ }
+ } else {
+ propToCheck = property.kind;
+ }
+
+ switch (propToCheck) {
+ case "set":
+ isSetPresent = true;
+ break;
+
+ case "get":
+ isGetPresent = true;
+ break;
+
+ default:
+ // Do nothing
+ }
+
+ if (isSetPresent && isGetPresent) {
+ break;
+ }
+ }
+
+ if (checkSetWithoutGet && isSetPresent && !isGetPresent) {
+ context.report(node, "Getter is not present");
+ } else if (checkGetWithoutSet && isGetPresent && !isSetPresent) {
+ context.report(node, "Setter is not present");
+ }
+ }
+
+ return {
+ "ObjectExpression": function(node) {
+ if (checkSetWithoutGet || checkGetWithoutSet) {
+ checkLonelySetGet(node);
+ }
+ }
+ };
+
+};
+
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "getWithoutSet": {
+ "type": "boolean"
+ },
+ "setWithoutGet": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],121:[function(require,module,exports){
+/**
+ * @fileoverview Disallows or enforces spaces inside of array brackets.
+ * @author Jamund Ferguson
+ * @copyright 2015 Jamund Ferguson. All rights reserved.
+ * @copyright 2014 Brandyn Bennett. All rights reserved.
+ * @copyright 2014 Michael Ficarra. No rights reserved.
+ * @copyright 2014 Vignesh Anand. All rights reserved.
+ */
+"use strict";
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var spaced = context.options[0] === "always",
+ sourceCode = context.getSourceCode();
+
+ /**
+ * Determines whether an option is set, relative to the spacing option.
+ * If spaced is "always", then check whether option is set to false.
+ * If spaced is "never", then check whether option is set to true.
+ * @param {Object} option - The option to exclude.
+ * @returns {boolean} Whether or not the property is excluded.
+ */
+ function isOptionSet(option) {
+ return context.options[1] ? context.options[1][option] === !spaced : false;
+ }
+
+ var options = {
+ spaced: spaced,
+ singleElementException: isOptionSet("singleValue"),
+ objectsInArraysException: isOptionSet("objectsInArrays"),
+ arraysInArraysException: isOptionSet("arraysInArrays")
+ };
+
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
- * Determines whether an identifier is in declaration position or is a non-declaration reference.
- * @param {ASTNode} id The identifier.
- * @param {ASTNode} parent The identifier's parent AST node.
- * @returns {Boolean} true when the identifier is in declaration position.
+ * Reports that there shouldn't be a space after the first token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportNoBeginningSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "There should be no space after '" + token.value + "'",
+ fix: function(fixer) {
+ var nextToken = context.getSourceCode().getTokenAfter(token);
+ return fixer.removeRange([token.range[1], nextToken.range[0]]);
+ }
+ });
+ }
+
+ /**
+ * Reports that there shouldn't be a space before the last token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportNoEndingSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "There should be no space before '" + token.value + "'",
+ fix: function(fixer) {
+ var previousToken = context.getSourceCode().getTokenBefore(token);
+ return fixer.removeRange([previousToken.range[1], token.range[0]]);
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a space after the first token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredBeginningSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "A space is required after '" + token.value + "'",
+ fix: function(fixer) {
+ return fixer.insertTextAfter(token, " ");
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a space before the last token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredEndingSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "A space is required before '" + token.value + "'",
+ fix: function(fixer) {
+ return fixer.insertTextBefore(token, " ");
+ }
+ });
+ }
+
+ /**
+ * Determines if a node is an object type
+ * @param {ASTNode} node - The node to check.
+ * @returns {boolean} Whether or not the node is an object type.
+ */
+ function isObjectType(node) {
+ return node && (node.type === "ObjectExpression" || node.type === "ObjectPattern");
+ }
+
+ /**
+ * Determines if a node is an array type
+ * @param {ASTNode} node - The node to check.
+ * @returns {boolean} Whether or not the node is an array type.
+ */
+ function isArrayType(node) {
+ return node && (node.type === "ArrayExpression" || node.type === "ArrayPattern");
+ }
+
+ /**
+ * Validates the spacing around array brackets
+ * @param {ASTNode} node - The node we're checking for spacing
+ * @returns {void}
*/
- function isDeclaration(id, parent) {
- switch (parent.type) {
- case "FunctionDeclaration":
- case "FunctionExpression":
- return parent.params.indexOf(id) > -1 || id === parent.id;
+ function validateArraySpacing(node) {
+ if (options.spaced && node.elements.length === 0) {
+ return;
+ }
- case "VariableDeclarator":
- return id === parent.id;
+ var first = context.getFirstToken(node),
+ second = context.getFirstToken(node, 1),
+ penultimate = context.getLastToken(node, 1),
+ last = context.getLastToken(node),
+ firstElement = node.elements[0],
+ lastElement = node.elements[node.elements.length - 1];
- case "CatchClause":
- return id === parent.param;
+ var openingBracketMustBeSpaced =
+ options.objectsInArraysException && isObjectType(firstElement) ||
+ options.arraysInArraysException && isArrayType(firstElement) ||
+ options.singleElementException && node.elements.length === 1
+ ? !options.spaced : options.spaced;
- default:
- return false;
+ var closingBracketMustBeSpaced =
+ options.objectsInArraysException && isObjectType(lastElement) ||
+ options.arraysInArraysException && isArrayType(lastElement) ||
+ options.singleElementException && node.elements.length === 1
+ ? !options.spaced : options.spaced;
+
+ if (astUtils.isTokenOnSameLine(first, second)) {
+ if (openingBracketMustBeSpaced && !sourceCode.isSpaceBetweenTokens(first, second)) {
+ reportRequiredBeginningSpace(node, first);
+ }
+ if (!openingBracketMustBeSpaced && sourceCode.isSpaceBetweenTokens(first, second)) {
+ reportNoBeginningSpace(node, first);
+ }
}
+
+ if (first !== penultimate && astUtils.isTokenOnSameLine(penultimate, last)) {
+ if (closingBracketMustBeSpaced && !sourceCode.isSpaceBetweenTokens(penultimate, last)) {
+ reportRequiredEndingSpace(node, last);
+ }
+ if (!closingBracketMustBeSpaced && sourceCode.isSpaceBetweenTokens(penultimate, last)) {
+ reportNoEndingSpace(node, last);
+ }
+ }
}
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ ArrayPattern: validateArraySpacing,
+ ArrayExpression: validateArraySpacing
+ };
+
+};
+
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "singleValue": {
+ "type": "boolean"
+ },
+ "objectsInArrays": {
+ "type": "boolean"
+ },
+ "arraysInArrays": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],122:[function(require,module,exports){
+/**
+ * @fileoverview Rule to require braces in arrow function body.
+ * @author Alberto RodrÃguez
+ * @copyright 2015 Alberto RodrÃguez. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var always = context.options[0] === "always";
+ var asNeeded = !context.options[0] || context.options[0] === "as-needed";
+
/**
- * Determines whether an identifier is in property position.
- * @param {ASTNode} id The identifier.
- * @param {ASTNode} parent The identifier's parent AST node.
- * @returns {Boolean} true when the identifier is in property position.
+ * Determines whether a arrow function body needs braces
+ * @param {ASTNode} node The arrow function node.
+ * @returns {void}
*/
- function isProperty(id, parent) {
- switch (parent.type) {
- case "MemberExpression":
- return id === parent.property && !parent.computed;
+ function validate(node) {
+ var arrowBody = node.body;
+ if (arrowBody.type === "BlockStatement") {
+ var blockBody = arrowBody.body;
- case "Property":
- return id === parent.key;
+ if (blockBody.length > 1) {
+ return;
+ }
- default:
- return false;
+ if (blockBody.length === 0) {
+ var hasComments = context.getComments(arrowBody).trailing.length > 0;
+ if (hasComments) {
+ return;
+ }
+
+ context.report({
+ node: node,
+ loc: arrowBody.loc.start,
+ message: "Unexpected empty block in arrow body."
+ });
+ } else {
+ if (asNeeded && blockBody[0].type === "ReturnStatement") {
+ context.report({
+ node: node,
+ loc: arrowBody.loc.start,
+ message: "Unexpected block statement surrounding arrow body."
+ });
+ }
+ }
+ } else {
+ if (always) {
+ context.report({
+ node: node,
+ loc: arrowBody.loc.start,
+ message: "Expected block statement surrounding arrow body."
+ });
+ }
}
}
+ return {
+ "ArrowFunctionExpression": validate
+ };
+};
+
+module.exports.schema = [
+ {
+ "enum": ["always", "as-needed"]
+ }
+];
+
+},{}],123:[function(require,module,exports){
+/**
+ * @fileoverview Rule to require parens in arrow function arguments.
+ * @author Jxck
+ * @copyright 2015 Jxck. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var message = "Expected parentheses around arrow function argument.";
+ var asNeededMessage = "Unexpected parentheses around single function argument";
+ var asNeeded = context.options[0] === "as-needed";
+
/**
- * Pushes a new scope object on the scope stack.
+ * Determines whether a arrow function argument end with `)`
+ * @param {ASTNode} node The arrow function node.
* @returns {void}
*/
- function pushScope() {
- scopeStack.push([]);
+ function parens(node) {
+ var token = context.getFirstToken(node);
+
+ // as-needed: x => x
+ if (asNeeded && node.params.length === 1 && node.params[0].type === "Identifier") {
+ if (token.type === "Punctuator" && token.value === "(") {
+ context.report(node, asNeededMessage);
+ }
+ return;
+ }
+
+ if (token.type === "Identifier") {
+ var after = context.getTokenAfter(token);
+
+ // (x) => x
+ if (after.value !== ")") {
+ context.report(node, message);
+ }
+ }
}
+ return {
+ "ArrowFunctionExpression": parens
+ };
+};
+
+module.exports.schema = [
+ {
+ "enum": ["always", "as-needed"]
+ }
+];
+
+},{}],124:[function(require,module,exports){
+/**
+ * @fileoverview Rule to require parens in arrow function arguments.
+ * @author Jxck
+ * @copyright 2015 Jxck. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ // merge rules with default
+ var rule = { before: true, after: true };
+ var option = context.options[0] || {};
+ rule.before = option.before !== false;
+ rule.after = option.after !== false;
+
/**
- * Removes the topmost scope object from the scope stack.
- * @returns {void}
+ * Get tokens of arrow(`=>`) and before/after arrow.
+ * @param {ASTNode} node The arrow function node.
+ * @returns {Object} Tokens of arrow and before/after arrow.
*/
- function popScope() {
- scopeStack.pop();
+ function getTokens(node) {
+ var t = context.getFirstToken(node);
+ var before;
+ while (t.type !== "Punctuator" || t.value !== "=>") {
+ before = t;
+ t = context.getTokenAfter(t);
+ }
+ var after = context.getTokenAfter(t);
+ return { before: before, arrow: t, after: after };
}
/**
- * Declares the given names in the topmost scope object.
- * @param {[String]} names A list of names to declare.
+ * Count spaces before/after arrow(`=>`) token.
+ * @param {Object} tokens Tokens before/after arrow.
+ * @returns {Object} count of space before/after arrow.
+ */
+ function countSpaces(tokens) {
+ var before = tokens.arrow.range[0] - tokens.before.range[1];
+ var after = tokens.after.range[0] - tokens.arrow.range[1];
+ return { before: before, after: after };
+ }
+
+ /**
+ * Determines whether space(s) before after arrow(`=>`) is satisfy rule.
+ * if before/after value is `true`, there should be space(s).
+ * if before/after value is `false`, there should be no space.
+ * @param {ASTNode} node The arrow function node.
* @returns {void}
*/
- function declare(names) {
- [].push.apply(scopeStack[scopeStack.length - 1], names);
+ function spaces(node) {
+ var tokens = getTokens(node);
+ var countSpace = countSpaces(tokens);
+
+ if (rule.before) {
+ // should be space(s) before arrow
+ if (countSpace.before === 0) {
+ context.report({
+ node: tokens.before,
+ message: "Missing space before =>",
+ fix: function(fixer) {
+ return fixer.insertTextBefore(tokens.arrow, " ");
+ }
+ });
+ }
+ } else {
+ // should be no space before arrow
+ if (countSpace.before > 0) {
+ context.report({
+ node: tokens.before,
+ message: "Unexpected space before =>",
+ fix: function(fixer) {
+ return fixer.removeRange([tokens.before.range[1], tokens.arrow.range[0]]);
+ }
+ });
+ }
+ }
+
+ if (rule.after) {
+ // should be space(s) after arrow
+ if (countSpace.after === 0) {
+ context.report({
+ node: tokens.after,
+ message: "Missing space after =>",
+ fix: function(fixer) {
+ return fixer.insertTextAfter(tokens.arrow, " ");
+ }
+ });
+ }
+ } else {
+ // should be no space after arrow
+ if (countSpace.after > 0) {
+ context.report({
+ node: tokens.after,
+ message: "Unexpected space after =>",
+ fix: function(fixer) {
+ return fixer.removeRange([tokens.arrow.range[1], tokens.after.range[0]]);
+ }
+ });
+ }
+ }
}
- //--------------------------------------------------------------------------
- // Public API
- //--------------------------------------------------------------------------
+ return {
+ "ArrowFunctionExpression": spaces
+ };
+};
- function functionHandler(node) {
- pushScope();
- declare(node.params.map(function(id) {
- return id.name;
- }));
- declare(node.id ? [node.id.name] : []);
- declare(node.rest ? [node.rest.name] : []);
- declare(["arguments"]);
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "before": {
+ "type": "boolean"
+ },
+ "after": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
}
+];
- function variableDeclarationHandler(node) {
- node.declarations.forEach(function(declaration) {
+},{}],125:[function(require,module,exports){
+/**
+ * @fileoverview Rule to check for "block scoped" variables by binding context
+ * @author Matt DuVall <http://www.mattduvall.com>
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ * @copyright 2015 Mathieu M-Gosselin. All rights reserved.
+ */
+"use strict";
- switch (declaration.id.type) {
- case "Identifier":
- declare([declaration.id.name]);
- break;
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
- case "ObjectPattern":
- declare(declaration.id.properties.map(function(property) {
- return property.key.name;
- }));
- break;
+/**
+ * Collects unresolved references from the global scope, then creates a map to references from its name.
+ * @param {RuleContext} context - The current context.
+ * @returns {object} A map object. Its key is the variable names. Its value is the references of each variable.
+ */
+function collectUnresolvedReferences(context) {
+ var unresolved = Object.create(null);
+ var references = context.getScope().through;
- case "ArrayPattern":
- declare(declaration.id.elements.map(function(element) {
- return element.name;
- }));
- break;
+ for (var i = 0; i < references.length; ++i) {
+ var reference = references[i];
+ var name = reference.identifier.name;
- // no default
- }
+ if (name in unresolved === false) {
+ unresolved[name] = [];
+ }
+ unresolved[name].push(reference);
+ }
- });
+ return unresolved;
+}
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var unresolvedReferences = Object.create(null);
+ var stack = [];
+
+ /**
+ * Makes a block scope.
+ * @param {ASTNode} node - A node of a scope.
+ * @returns {void}
+ */
+ function enterScope(node) {
+ stack.push(node.range);
}
- return {
- "Program": function() {
- var scope = context.getScope();
- scopeStack = [scope.variables.map(function(v) {
- return v.name;
- })];
+ /**
+ * Pops the last block scope.
+ * @returns {void}
+ */
+ function exitScope() {
+ stack.pop();
+ }
- // global return creates another scope
- if (context.ecmaFeatures.globalReturn) {
- scope = scope.childScopes[0];
- scopeStack.push(scope.variables.map(function(v) {
- return v.name;
- }));
+ /**
+ * Reports a given reference.
+ * @param {escope.Reference} reference - A reference to report.
+ * @returns {void}
+ */
+ function report(reference) {
+ var identifier = reference.identifier;
+ context.report(
+ identifier,
+ "\"{{name}}\" used outside of binding context.",
+ {name: identifier.name});
+ }
+
+ /**
+ * Finds and reports references which are outside of valid scopes.
+ * @param {ASTNode} node - A node to get variables.
+ * @returns {void}
+ */
+ function checkForVariables(node) {
+ if (node.kind !== "var") {
+ return;
+ }
+
+ var isGlobal = context.getScope().type === "global";
+
+ // Defines a predicate to check whether or not a given reference is outside of valid scope.
+ var scopeRange = stack[stack.length - 1];
+
+ /**
+ * Check if a reference is out of scope
+ * @param {ASTNode} reference node to examine
+ * @returns {boolean} True is its outside the scope
+ * @private
+ */
+ function isOutsideOfScope(reference) {
+ var idRange = reference.identifier.range;
+ return idRange[0] < scopeRange[0] || idRange[1] > scopeRange[1];
+ }
+
+ // Gets declared variables, and checks its references.
+ var variables = context.getDeclaredVariables(node);
+ for (var i = 0; i < variables.length; ++i) {
+ var variable = variables[i];
+ var references = variable.references;
+
+ // Global variables are not resolved.
+ // In this case, use unresolved references.
+ if (isGlobal && variable.name in unresolvedReferences) {
+ references = unresolvedReferences[variable.name];
}
- },
- "BlockStatement": function(node) {
- var statements = node.body;
- pushScope();
- statements.forEach(function(stmt) {
- if (stmt.type === "VariableDeclaration") {
- variableDeclarationHandler(stmt);
- } else if (stmt.type === "FunctionDeclaration") {
- declare([stmt.id.name]);
- }
- });
- },
+ // Reports.
+ references.filter(isOutsideOfScope).forEach(report);
+ }
+ }
- "VariableDeclaration": function (node) {
- variableDeclarationHandler(node);
+ return {
+ "Program": function(node) {
+ unresolvedReferences = collectUnresolvedReferences(context);
+ stack = [node.range];
},
- "BlockStatement:exit": popScope,
+ // Manages scopes.
+ "BlockStatement": enterScope,
+ "BlockStatement:exit": exitScope,
+ "ForStatement": enterScope,
+ "ForStatement:exit": exitScope,
+ "ForInStatement": enterScope,
+ "ForInStatement:exit": exitScope,
+ "ForOfStatement": enterScope,
+ "ForOfStatement:exit": exitScope,
+ "SwitchStatement": enterScope,
+ "SwitchStatement:exit": exitScope,
+ "CatchClause": enterScope,
+ "CatchClause:exit": exitScope,
- "CatchClause": function(node) {
- pushScope();
- declare([node.param.name]);
- },
- "CatchClause:exit": popScope,
+ // Finds and reports references which are outside of valid scope.
+ "VariableDeclaration": checkForVariables
+ };
- "FunctionDeclaration": functionHandler,
- "FunctionDeclaration:exit": popScope,
+};
- "FunctionExpression": functionHandler,
- "FunctionExpression:exit": popScope,
+module.exports.schema = [];
- "ArrowFunctionExpression": functionHandler,
- "ArrowFunctionExpression:exit": popScope,
+},{}],126:[function(require,module,exports){
+/**
+ * @fileoverview A rule to disallow or enforce spaces inside of single line blocks.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
- "ForStatement": function() {
- pushScope();
- },
- "ForStatement:exit": popScope,
+"use strict";
- "ForInStatement": function() {
- pushScope();
- },
- "ForInStatement:exit": popScope,
+var util = require("../ast-utils");
- "ForOfStatement": function() {
- pushScope();
- },
- "ForOfStatement:exit": popScope,
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
- "Identifier": function(node) {
- var ancestor = context.getAncestors().pop();
- if (isDeclaration(node, ancestor) || isProperty(node, ancestor) || ancestor.type === "LabeledStatement") {
- return;
+module.exports = function(context) {
+ var always = (context.options[0] !== "never"),
+ message = always ? "Requires a space" : "Unexpected space(s)",
+ sourceCode = context.getSourceCode();
+
+ /**
+ * Gets the open brace token from a given node.
+ * @param {ASTNode} node - A BlockStatement/SwitchStatement node to get.
+ * @returns {Token} The token of the open brace.
+ */
+ function getOpenBrace(node) {
+ if (node.type === "SwitchStatement") {
+ if (node.cases.length > 0) {
+ return context.getTokenBefore(node.cases[0]);
}
+ return context.getLastToken(node, 1);
+ }
+ return context.getFirstToken(node);
+ }
- for (var i = 0, l = scopeStack.length; i < l; i++) {
- if (scopeStack[i].indexOf(node.name) > -1) {
- return;
+ /**
+ * Checks whether or not:
+ * - given tokens are on same line.
+ * - there is/isn't a space between given tokens.
+ * @param {Token} left - A token to check.
+ * @param {Token} right - The token which is next to `left`.
+ * @returns {boolean}
+ * When the option is `"always"`, `true` if there are one or more spaces between given tokens.
+ * When the option is `"never"`, `true` if there are not any spaces between given tokens.
+ * If given tokens are not on same line, it's always `true`.
+ */
+ function isValid(left, right) {
+ return (
+ !util.isTokenOnSameLine(left, right) ||
+ sourceCode.isSpaceBetweenTokens(left, right) === always
+ );
+ }
+
+ /**
+ * Reports invalid spacing style inside braces.
+ * @param {ASTNode} node - A BlockStatement/SwitchStatement node to get.
+ * @returns {void}
+ */
+ function checkSpacingInsideBraces(node) {
+ // Gets braces and the first/last token of content.
+ var openBrace = getOpenBrace(node);
+ var closeBrace = context.getLastToken(node);
+ var firstToken = sourceCode.getTokenOrCommentAfter(openBrace);
+ var lastToken = sourceCode.getTokenOrCommentBefore(closeBrace);
+
+ // Skip if the node is invalid or empty.
+ if (openBrace.type !== "Punctuator" ||
+ openBrace.value !== "{" ||
+ closeBrace.type !== "Punctuator" ||
+ closeBrace.value !== "}" ||
+ firstToken === closeBrace
+ ) {
+ return;
+ }
+
+ // Skip line comments for option never
+ if (!always && firstToken.type === "Line") {
+ return;
+ }
+
+ // Check.
+ if (!isValid(openBrace, firstToken)) {
+ context.report({
+ node: node,
+ loc: openBrace.loc.start,
+ message: message + " after \"{\".",
+ fix: function(fixer) {
+ if (always) {
+ return fixer.insertTextBefore(firstToken, " ");
+ }
+
+ return fixer.removeRange([openBrace.range[1], firstToken.range[0]]);
}
- }
+ });
+ }
+ if (!isValid(lastToken, closeBrace)) {
+ context.report({
+ node: node,
+ loc: closeBrace.loc.start,
+ message: message + " before \"}\".",
+ fix: function(fixer) {
+ if (always) {
+ return fixer.insertTextAfter(lastToken, " ");
+ }
- context.report(node, "\"" + node.name + "\" used outside of binding context.");
+ return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]);
+ }
+ });
}
- };
+ }
+ return {
+ BlockStatement: checkSpacingInsideBraces,
+ SwitchStatement: checkSpacingInsideBraces
+ };
};
-},{}],137:[function(require,module,exports){
+module.exports.schema = [
+ {enum: ["always", "never"]}
+];
+
+},{"../ast-utils":113}],127:[function(require,module,exports){
/**
* @fileoverview Rule to flag block statements that do not use the one true brace style
* @author Ian Christian Myers
*/
@@ -18439,14 +23938,15 @@
module.exports = function(context) {
var style = context.options[0] || "1tbs";
var params = context.options[1] || {};
var OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.",
+ OPEN_MESSAGE_ALLMAN = "Opening curly brace appears on the same line as controlling statement.",
BODY_MESSAGE = "Statement inside of curly braces should be on next line.",
CLOSE_MESSAGE = "Closing curly brace does not appear on the same line as the subsequent block.",
CLOSE_MESSAGE_SINGLE = "Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.",
- CLOSE_MESSAGE_STROUSTRUP = "Closing curly brace appears on the same line as the subsequent block.";
+ CLOSE_MESSAGE_STROUSTRUP_ALLMAN = "Closing curly brace appears on the same line as the subsequent block.";
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
@@ -18458,10 +23958,19 @@
*/
function isBlock(node) {
return node && node.type === "BlockStatement";
}
+ /**
+ * Check if the token is an punctuator with a value of curly brace
+ * @param {object} token - Token to check
+ * @returns {boolean} true if its a curly punctuator
+ * @private
+ */
+ function isCurlyPunctuator(token) {
+ return token.value === "{" || token.value === "}";
+ }
/**
* Binds a list of properties to a function that verifies that the opening
* curly brace is on the same line as its controlling statement of a given
* node.
@@ -18473,32 +23982,34 @@
var blockProperties = arguments;
return function(node) {
[].forEach.call(blockProperties, function(blockProp) {
var block = node[blockProp], previousToken, curlyToken, curlyTokenEnd, curlyTokensOnSameLine;
- block = node[blockProp];
- if (isBlock(block)) {
+ if (!isBlock(block)) {
+ return;
+ }
- previousToken = context.getTokenBefore(block);
- curlyToken = context.getFirstToken(block);
- curlyTokenEnd = context.getLastToken(block);
- curlyTokensOnSameLine = curlyToken.loc.start.line === curlyTokenEnd.loc.start.line;
+ previousToken = context.getTokenBefore(block);
+ curlyToken = context.getFirstToken(block);
+ curlyTokenEnd = context.getLastToken(block);
+ curlyTokensOnSameLine = curlyToken.loc.start.line === curlyTokenEnd.loc.start.line;
- if (previousToken.loc.start.line !== curlyToken.loc.start.line) {
- context.report(node, OPEN_MESSAGE);
- } else if (block.body.length && params.allowSingleLine) {
+ if (style !== "allman" && previousToken.loc.start.line !== curlyToken.loc.start.line) {
+ context.report(node, OPEN_MESSAGE);
+ } else if (style === "allman" && previousToken.loc.start.line === curlyToken.loc.start.line && !params.allowSingleLine) {
+ context.report(node, OPEN_MESSAGE_ALLMAN);
+ }
- if (curlyToken.loc.start.line === block.body[0].loc.start.line && !curlyTokensOnSameLine) {
- context.report(block.body[0], BODY_MESSAGE);
- } else if (curlyTokenEnd.loc.start.line === block.body[block.body.length - 1].loc.start.line && !curlyTokensOnSameLine) {
- context.report(block.body[block.body.length - 1], CLOSE_MESSAGE_SINGLE);
- }
+ if (!block.body.length || curlyTokensOnSameLine && params.allowSingleLine) {
+ return;
+ }
- } else if (block.body.length && curlyToken.loc.start.line === block.body[0].loc.start.line) {
- context.report(block.body[0], BODY_MESSAGE);
- }
+ if (curlyToken.loc.start.line === block.body[0].loc.start.line) {
+ context.report(block.body[0], BODY_MESSAGE);
+ } else if (curlyTokenEnd.loc.start.line === block.body[block.body.length - 1].loc.start.line) {
+ context.report(block.body[block.body.length - 1], CLOSE_MESSAGE_SINGLE);
}
});
};
}
@@ -18522,17 +24033,15 @@
if (alternateIsBlock || alternateIsIfBlock) {
tokens = context.getTokensBefore(node.alternate, 2);
if (style === "1tbs") {
- if (tokens[0].loc.start.line !== tokens[1].loc.start.line) {
+ if (tokens[0].loc.start.line !== tokens[1].loc.start.line && isCurlyPunctuator(tokens[0]) ) {
context.report(node.alternate, CLOSE_MESSAGE);
}
- } else if (style === "stroustrup") {
- if (tokens[0].loc.start.line === tokens[1].loc.start.line) {
- context.report(node.alternate, CLOSE_MESSAGE_STROUSTRUP);
- }
+ } else if (tokens[0].loc.start.line === tokens[1].loc.start.line) {
+ context.report(node.alternate, CLOSE_MESSAGE_STROUSTRUP_ALLMAN);
}
}
}
}
@@ -18552,14 +24061,12 @@
tokens = context.getTokensBefore(node.finalizer, 2);
if (style === "1tbs") {
if (tokens[0].loc.start.line !== tokens[1].loc.start.line) {
context.report(node.finalizer, CLOSE_MESSAGE);
}
- } else if (style === "stroustrup") {
- if (tokens[0].loc.start.line === tokens[1].loc.start.line) {
- context.report(node.finalizer, CLOSE_MESSAGE_STROUSTRUP);
- }
+ } else if (tokens[0].loc.start.line === tokens[1].loc.start.line) {
+ context.report(node.finalizer, CLOSE_MESSAGE_STROUSTRUP_ALLMAN);
}
}
}
/**
@@ -18577,13 +24084,13 @@
if (isBlock(node.body)) {
if (style === "1tbs") {
if (previousToken.loc.start.line !== firstToken.loc.start.line) {
context.report(node, CLOSE_MESSAGE);
}
- } else if (style === "stroustrup") {
+ } else {
if (previousToken.loc.start.line === firstToken.loc.start.line) {
- context.report(node, CLOSE_MESSAGE_STROUSTRUP);
+ context.report(node, CLOSE_MESSAGE_STROUSTRUP_ALLMAN);
}
}
}
}
@@ -18595,19 +24102,19 @@
*/
function checkSwitchStatement(node) {
var tokens;
if (node.cases && node.cases.length) {
tokens = context.getTokensBefore(node.cases[0], 2);
- if (tokens[0].loc.start.line !== tokens[1].loc.start.line) {
- context.report(node, OPEN_MESSAGE);
- }
} else {
tokens = context.getLastTokens(node, 3);
- if (tokens[0].loc.start.line !== tokens[1].loc.start.line) {
- context.report(node, OPEN_MESSAGE);
- }
}
+
+ if (style !== "allman" && tokens[0].loc.start.line !== tokens[1].loc.start.line) {
+ context.report(node, OPEN_MESSAGE);
+ } else if (style === "allman" && tokens[0].loc.start.line === tokens[1].loc.start.line) {
+ context.report(node, OPEN_MESSAGE_ALLMAN);
+ }
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
@@ -18628,14 +24135,174 @@
"SwitchStatement": checkSwitchStatement
};
};
-},{}],138:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["1tbs", "stroustrup", "allman"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "allowSingleLine": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],128:[function(require,module,exports){
/**
+ * @fileoverview Enforce return after a callback.
+ * @author Jamund Ferguson
+ * @copyright 2015 Jamund Ferguson. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var callbacks = context.options[0] || ["callback", "cb", "next"];
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Find the closest parent matching a list of types.
+ * @param {ASTNode} node The node whose parents we are searching
+ * @param {Array} types The node types to match
+ * @returns {ASTNode} The matched node or undefined.
+ */
+ function findClosestParentOfType(node, types) {
+ if (!node.parent) {
+ return null;
+ }
+ if (types.indexOf(node.parent.type) === -1) {
+ return findClosestParentOfType(node.parent, types);
+ }
+ return node.parent;
+ }
+
+ /**
+ * Check to see if a CallExpression is in our callback list.
+ * @param {ASTNode} node The node to check against our callback names list.
+ * @returns {Boolean} Whether or not this function matches our callback name.
+ */
+ function isCallback(node) {
+ return node.callee.type === "Identifier" && callbacks.indexOf(node.callee.name) > -1;
+ }
+
+ /**
+ * Determines whether or not the callback is part of a callback expression.
+ * @param {ASTNode} node The callback node
+ * @param {ASTNode} parentNode The expression node
+ * @returns {boolean} Whether or not this is part of a callback expression
+ */
+ function isCallbackExpression(node, parentNode) {
+
+ // ensure the parent node exists and is an expression
+ if (!parentNode || parentNode.type !== "ExpressionStatement") {
+ return false;
+ }
+
+ // cb()
+ if (parentNode.expression === node) {
+ return true;
+ }
+
+ // special case for cb && cb() and similar
+ if (parentNode.expression.type === "BinaryExpression" || parentNode.expression.type === "LogicalExpression") {
+ if (parentNode.expression.right === node) {
+ return true;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ "CallExpression": function(node) {
+
+ // if we"re not a callback we can return
+ if (!isCallback(node)) {
+ return;
+ }
+
+ // find the closest block, return or loop
+ var closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {},
+ lastItem, parentType;
+
+ // if our parent is a return we know we're ok
+ if (closestBlock.type === "ReturnStatement" ) {
+ return;
+ }
+
+ // arrow functions don't always have blocks and implicitly return
+ if (closestBlock.type === "ArrowFunctionExpression") {
+ return;
+ }
+
+ // block statements are part of functions and most if statements
+ if (closestBlock.type === "BlockStatement") {
+
+ // find the last item in the block
+ lastItem = closestBlock.body[closestBlock.body.length - 1];
+
+ // if the callback is the last thing in a block that might be ok
+ if (isCallbackExpression(node, lastItem)) {
+
+ parentType = closestBlock.parent.type;
+
+ // but only if the block is part of a function
+ if (parentType === "FunctionExpression" ||
+ parentType === "FunctionDeclaration" ||
+ parentType === "ArrowFunctionExpression"
+ ) {
+ return;
+ }
+
+ }
+
+ // ending a block with a return is also ok
+ if (lastItem.type === "ReturnStatement") {
+
+ // but only if the callback is immediately before
+ if (isCallbackExpression(node, closestBlock.body[closestBlock.body.length - 2])) {
+ return;
+ }
+ }
+
+ }
+
+ // as long as you're the child of a function at this point you should be asked to return
+ if (findClosestParentOfType(node, ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"])) {
+ context.report(node, "Expected return with your callback function.");
+ }
+
+ }
+
+ };
+};
+
+module.exports.schema = [{
+ type: "array",
+ items: { type: "string" }
+}];
+
+},{}],129:[function(require,module,exports){
+/**
* @fileoverview Rule to flag non-camelcased identifiers
* @author Nicholas C. Zakas
+ * @copyright 2015 Dieter Oberkofler. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
@@ -18668,10 +24335,17 @@
*/
function report(node) {
context.report(node, "Identifier '{{name}}' is not in camel case.", { name: node.name });
}
+ var options = context.options[0] || {},
+ properties = options.properties || "";
+
+ if (properties !== "always" && properties !== "never") {
+ properties = "always";
+ }
+
return {
"Identifier": function(node) {
// Leading and trailing underscores are commonly used to flag private/protected identifiers, strip them
@@ -18679,10 +24353,15 @@
effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
// MemberExpressions get special rules
if (node.parent.type === "MemberExpression") {
+ // "never" check properties
+ if (properties === "never") {
+ return;
+ }
+
// Always report underscored object names
if (node.parent.object.type === "Identifier" &&
node.parent.object.name === node.name &&
isUnderscored(name)) {
report(node);
@@ -18694,120 +24373,286 @@
effectiveParent.left.type === "MemberExpression" &&
effectiveParent.left.property.name === node.name)) {
report(node);
}
+ // Properties have their own rules
+ } else if (node.parent.type === "Property") {
+
+ // "never" check properties
+ if (properties === "never") {
+ return;
+ }
+
+ if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {
+ report(node);
+ }
+
// Report anything that is underscored that isn't a CallExpression
} else if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {
report(node);
}
}
+
};
};
-},{}],139:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "properties": {
+ "enum": ["always", "never"]
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],130:[function(require,module,exports){
/**
* @fileoverview Rule to forbid or enforce dangling commas.
* @author Ian Christian Myers
+ * @copyright 2015 Toru Nagashima
* @copyright 2015 Mathias Schreck
* @copyright 2013 Ian Christian Myers
+ * See LICENSE file in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Gets the last element of a given array.
+ *
+ * @param {*[]} xs - An array to get.
+ * @returns {*} The last element, or undefined.
+ */
+function getLast(xs) {
+ if (xs.length === 0) {
+ return null;
+ }
+ return xs[xs.length - 1];
+}
+
+/**
+ * Checks whether or not a trailing comma is allowed in a given node.
+ * `ArrayPattern` which has `RestElement` disallows it.
+ *
+ * @param {ASTNode} node - A node to check.
+ * @param {ASTNode} lastItem - The node of the last element in the given node.
+ * @returns {boolean} `true` if a trailing comma is allowed.
+ */
+function isTrailingCommaAllowed(node, lastItem) {
+ switch (node.type) {
+ case "ArrayPattern":
+ // TODO(t-nagashima): Remove SpreadElement after https://github.com/eslint/espree/issues/194 was fixed.
+ return (
+ lastItem.type !== "RestElement" &&
+ lastItem.type !== "SpreadElement"
+ );
+
+ // TODO(t-nagashima): Remove this case after https://github.com/eslint/espree/issues/195 was fixed.
+ case "ArrayExpression":
+ return (
+ node.parent.type !== "ForOfStatement" ||
+ node.parent.left !== node ||
+ lastItem.type !== "SpreadElement"
+ );
+
+ default:
+ return true;
+ }
+}
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
- var forbidDanglingComma = context.options[0] !== "always";
+module.exports = function(context) {
+ var mode = context.options[0];
+ var UNEXPECTED_MESSAGE = "Unexpected trailing comma.";
+ var MISSING_MESSAGE = "Missing trailing comma.";
/**
- * Checks the given node for trailing comma and reports violations.
- * @param {ASTNode} node The node of an ObjectExpression or ArrayExpression
+ * Checks whether or not a given node is multiline.
+ * This rule handles a given node as multiline when the closing parenthesis
+ * and the last element are not on the same line.
+ *
+ * @param {ASTNode} node - A ndoe to check.
+ * @returns {boolean} `true` if the node is multiline.
+ */
+ function isMultiline(node) {
+ var lastItem = getLast(node.properties || node.elements || node.specifiers);
+ if (!lastItem) {
+ return false;
+ }
+
+ var sourceCode = context.getSourceCode(),
+ penultimateToken = sourceCode.getLastToken(lastItem),
+ lastToken = sourceCode.getLastToken(node);
+
+ if (lastToken.value === ",") {
+ penultimateToken = lastToken;
+ lastToken = sourceCode.getTokenAfter(lastToken);
+ }
+
+ return lastToken.loc.end.line !== penultimateToken.loc.end.line;
+ }
+
+ /**
+ * Reports a trailing comma if it exists.
+ *
+ * @param {ASTNode} node - A node to check. Its type is one of
+ * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern,
+ * ImportDeclaration, and ExportNamedDeclaration.
* @returns {void}
*/
- function checkForTrailingComma(node) {
- var items = node.properties || node.elements,
- length = items.length,
- lastItem,
- penultimateToken;
+ function forbidTrailingComma(node) {
+ var lastItem = getLast(node.properties || node.elements || node.specifiers);
+ if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) {
+ return;
+ }
- if (length) {
- lastItem = items[length - 1];
- if (lastItem) {
- penultimateToken = context.getLastToken(node, 1);
+ var sourceCode = context.getSourceCode(),
+ trailingToken;
- if (forbidDanglingComma) {
- if (penultimateToken.value === ",") {
- context.report(lastItem, penultimateToken.loc.start, "Unexpected trailing comma.");
- }
- } else {
- if (penultimateToken.value !== ",") {
- context.report(lastItem, lastItem.loc.end, "Missing trailing comma.");
- }
- }
- }
+ // last item can be surrounded by parentheses for object and array literals
+ if (node.type === "ObjectExpression" || node.type === "ArrayExpression") {
+ trailingToken = sourceCode.getTokenBefore(sourceCode.getLastToken(node));
+ } else {
+ trailingToken = sourceCode.getTokenAfter(lastItem);
}
+
+ if (trailingToken.value === ",") {
+ context.report(
+ lastItem,
+ trailingToken.loc.start,
+ UNEXPECTED_MESSAGE);
+ }
}
+ /**
+ * Reports the last element of a given node if it does not have a trailing
+ * comma.
+ *
+ * If a given node is `ArrayPattern` which has `RestElement`, the trailing
+ * comma is disallowed, so report if it exists.
+ *
+ * @param {ASTNode} node - A node to check. Its type is one of
+ * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern,
+ * ImportDeclaration, and ExportNamedDeclaration.
+ * @returns {void}
+ */
+ function forceTrailingComma(node) {
+ var lastItem = getLast(node.properties || node.elements || node.specifiers);
+ if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) {
+ return;
+ }
+ if (!isTrailingCommaAllowed(node, lastItem)) {
+ forbidTrailingComma(node);
+ return;
+ }
+
+ var sourceCode = context.getSourceCode(),
+ trailingToken;
+
+ // last item can be surrounded by parentheses for object and array literals
+ if (node.type === "ObjectExpression" || node.type === "ArrayExpression") {
+ trailingToken = sourceCode.getTokenBefore(sourceCode.getLastToken(node));
+ } else {
+ trailingToken = sourceCode.getTokenAfter(lastItem);
+ }
+
+ if (trailingToken.value !== ",") {
+ context.report(
+ lastItem,
+ lastItem.loc.end,
+ MISSING_MESSAGE);
+ }
+ }
+
+ /**
+ * If a given node is multiline, reports the last element of a given node
+ * when it does not have a trailing comma.
+ * Otherwise, reports a trailing comma if it exists.
+ *
+ * @param {ASTNode} node - A node to check. Its type is one of
+ * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern,
+ * ImportDeclaration, and ExportNamedDeclaration.
+ * @returns {void}
+ */
+ function forceTrailingCommaIfMultiline(node) {
+ if (isMultiline(node)) {
+ forceTrailingComma(node);
+ } else {
+ forbidTrailingComma(node);
+ }
+ }
+
+ // Chooses a checking function.
+ var checkForTrailingComma;
+ if (mode === "always") {
+ checkForTrailingComma = forceTrailingComma;
+ } else if (mode === "always-multiline") {
+ checkForTrailingComma = forceTrailingCommaIfMultiline;
+ } else {
+ checkForTrailingComma = forbidTrailingComma;
+ }
+
return {
"ObjectExpression": checkForTrailingComma,
- "ArrayExpression": checkForTrailingComma
+ "ObjectPattern": checkForTrailingComma,
+ "ArrayExpression": checkForTrailingComma,
+ "ArrayPattern": checkForTrailingComma,
+ "ImportDeclaration": checkForTrailingComma,
+ "ExportNamedDeclaration": checkForTrailingComma
};
};
-},{}],140:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "always-multiline", "never"]
+ }
+];
+
+},{}],131:[function(require,module,exports){
/**
* @fileoverview Comma spacing - validates spacing before and after comma
* @author Vignesh Anand aka vegetableman.
* @copyright 2014 Vignesh Anand. All rights reserved.
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var sourceCode = context.getSourceCode();
+ var tokensAndComments = sourceCode.tokensAndComments;
+
var options = {
before: context.options[0] ? !!context.options[0].before : false,
after: context.options[0] ? !!context.options[0].after : true
};
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
- // the index of the last comment that was checked
- var lastCommentIndex = 0;
+ // list of comma tokens to ignore for the check of leading whitespace
+ var commaTokensToIgnore = [];
/**
- * Determines whether two adjacent tokens have whitespace between them.
- * @param {Object} left - The left token object.
- * @param {Object} right - The right token object.
- * @returns {boolean} Whether or not there is space between the tokens.
- */
- function isSpaced(left, right) {
- var punctuationLength = context.getTokensBetween(left, right).length; // the length of any parenthesis
- return (left.range[1] + punctuationLength) < right.range[0];
- }
-
- /**
- * Checks whether two tokens are on the same line.
- * @param {ASTNode} left The leftmost token.
- * @param {ASTNode} right The rightmost token.
- * @returns {boolean} True if the tokens are on the same line, false if not.
- * @private
- */
- function isSameLine(left, right) {
- return left.loc.end.line === right.loc.start.line;
- }
-
- /**
* Determines if a given token is a comma operator.
* @param {ASTNode} token The token to check.
* @returns {boolean} True if the token is a comma, false if not.
* @private
*/
@@ -18817,17 +24662,43 @@
/**
* Reports a spacing error with an appropriate message.
* @param {ASTNode} node The binary expression node to report.
* @param {string} dir Is the error "before" or "after" the comma?
+ * @param {ASTNode} otherNode The node at the left or right of `node`
* @returns {void}
* @private
*/
- function report(node, dir) {
- context.report(node, options[dir] ?
- "A space is required " + dir + " ','." :
- "There should be no space " + dir + " ','.");
+ function report(node, dir, otherNode) {
+ context.report({
+ node: node,
+ fix: function(fixer) {
+ if (options[dir]) {
+ if (dir === "before") {
+ return fixer.insertTextBefore(node, " ");
+ } else {
+ return fixer.insertTextAfter(node, " ");
+ }
+ } else {
+ var start, end;
+ var newText = "";
+
+ if (dir === "before") {
+ start = otherNode.range[1];
+ end = node.range[0];
+ } else {
+ start = node.range[1];
+ end = otherNode.range[0];
+ }
+
+ return fixer.replaceTextRange([start, end], newText);
+ }
+ },
+ message: options[dir] ?
+ "A space is required " + dir + " ','." :
+ "There should be no space " + dir + " ','."
+ });
}
/**
* Validates the spacing around a comma token.
* @param {Object} tokens - The tokens to be validated.
@@ -18837,122 +24708,134 @@
* @param {Token|ASTNode} reportItem The item to use when reporting an error.
* @returns {void}
* @private
*/
function validateCommaItemSpacing(tokens, reportItem) {
- if (tokens.left && isSameLine(tokens.left, tokens.comma) &&
- (options.before !== isSpaced(tokens.left, tokens.comma))
+ if (tokens.left && astUtils.isTokenOnSameLine(tokens.left, tokens.comma) &&
+ (options.before !== sourceCode.isSpaceBetweenTokens(tokens.left, tokens.comma))
) {
- report(reportItem, "before");
+ report(reportItem, "before", tokens.left);
}
- if (tokens.right && isSameLine(tokens.comma, tokens.right) &&
- (options.after !== isSpaced(tokens.comma, tokens.right))
+
+ if (tokens.right && !options.after && tokens.right.type === "Line") {
+ return false;
+ }
+
+ if (tokens.right && astUtils.isTokenOnSameLine(tokens.comma, tokens.right) &&
+ (options.after !== sourceCode.isSpaceBetweenTokens(tokens.comma, tokens.right))
) {
- report(reportItem, "after");
+ report(reportItem, "after", tokens.right);
}
}
/**
- * Determines if a given source index is in a comment or not by checking
- * the index against the comment range. Since the check goes straight
- * through the file, once an index is passed a certain comment, we can
- * go to the next comment to check that.
- * @param {int} index The source index to check.
- * @param {ASTNode[]} comments An array of comment nodes.
- * @returns {boolean} True if the index is within a comment, false if not.
- * @private
+ * Adds null elements of the given ArrayExpression or ArrayPattern node to the ignore list.
+ * @param {ASTNode} node An ArrayExpression or ArrayPattern node.
+ * @returns {void}
*/
- function isIndexInComment(index, comments) {
+ function addNullElementsToIgnoreList(node) {
+ var previousToken = context.getFirstToken(node);
- var comment;
+ node.elements.forEach(function(element) {
+ var token;
- while (lastCommentIndex < comments.length) {
+ if (element === null) {
+ token = context.getTokenAfter(previousToken);
- comment = comments[lastCommentIndex];
-
- if (comment.range[0] <= index && index < comment.range[1]) {
- return true;
- } else if (index > comment.range[1]) {
- lastCommentIndex++;
+ if (isComma(token)) {
+ commaTokensToIgnore.push(token);
+ }
} else {
- break;
+ token = context.getTokenAfter(element);
}
- }
-
- return false;
+ previousToken = token;
+ });
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
- "Program": function() {
+ "Program:exit": function() {
- var source = context.getSource(),
- allComments = context.getAllComments(),
- pattern = /,/g,
- commaToken,
- previousToken,
+ var previousToken,
nextToken;
- while (pattern.test(source)) {
+ tokensAndComments.forEach(function(token, i) {
- // do not flag anything inside of comments
- if (!isIndexInComment(pattern.lastIndex, allComments)) {
- commaToken = context.getTokenByRangeStart(pattern.lastIndex - 1);
+ if (!isComma(token)) {
+ return;
+ }
- if (commaToken && commaToken.type !== "JSXText") {
- previousToken = context.getTokenBefore(commaToken);
- nextToken = context.getTokenAfter(commaToken);
- validateCommaItemSpacing({
- comma: commaToken,
- left: isComma(previousToken) ? null : previousToken,
- right: isComma(nextToken) ? null : nextToken
- }, commaToken);
- }
+ if (token && token.type === "JSXText") {
+ return;
}
- }
- }
+
+ previousToken = tokensAndComments[i - 1];
+ nextToken = tokensAndComments[i + 1];
+
+ validateCommaItemSpacing({
+ comma: token,
+ left: isComma(previousToken) || commaTokensToIgnore.indexOf(token) > -1 ? null : previousToken,
+ right: isComma(nextToken) ? null : nextToken
+ }, token);
+ });
+ },
+ "ArrayExpression": addNullElementsToIgnoreList,
+ "ArrayPattern": addNullElementsToIgnoreList
+
};
};
-},{}],141:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "before": {
+ "type": "boolean"
+ },
+ "after": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],132:[function(require,module,exports){
/**
* @fileoverview Comma style - enforces comma styles of two types: last and first
* @author Vignesh Anand aka vegetableman
* @copyright 2014 Vignesh Anand. All rights reserved.
+ * @copyright 2015 Evan Simmons. All rights reserved.
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var style = context.options[0] || "last";
+ var style = context.options[0] || "last",
+ exceptions = {};
+ if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) {
+ exceptions = context.options[1].exceptions;
+ }
+
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
- * Checks whether two tokens are on the same line.
- * @param {ASTNode} left The leftmost token.
- * @param {ASTNode} right The rightmost token.
- * @returns {boolean} True if the tokens are on the same line, false if not.
- * @private
- */
- function isSameLine(left, right) {
- return left.loc.end.line === right.loc.start.line;
- }
-
- /**
* Determines if a given token is a comma operator.
* @param {ASTNode} token The token to check.
* @returns {boolean} True if the token is a comma, false if not.
* @private
*/
@@ -18970,29 +24853,29 @@
* @private
*/
function validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem) {
// if single line
- if (isSameLine(commaToken, currentItemToken) &&
- isSameLine(previousItemToken, commaToken)) {
+ if (astUtils.isTokenOnSameLine(commaToken, currentItemToken) &&
+ astUtils.isTokenOnSameLine(previousItemToken, commaToken)) {
return;
- } else if (!isSameLine(commaToken, currentItemToken) &&
- !isSameLine(previousItemToken, commaToken)) {
+ } else if (!astUtils.isTokenOnSameLine(commaToken, currentItemToken) &&
+ !astUtils.isTokenOnSameLine(previousItemToken, commaToken)) {
// lone comma
context.report(reportItem, {
line: commaToken.loc.end.line,
column: commaToken.loc.start.column
}, "Bad line breaking before and after ','.");
- } else if (style === "first" && !isSameLine(commaToken, currentItemToken)) {
+ } else if (style === "first" && !astUtils.isTokenOnSameLine(commaToken, currentItemToken)) {
context.report(reportItem, "',' should be placed first.");
- } else if (style === "last" && isSameLine(commaToken, currentItemToken)) {
+ } else if (style === "last" && astUtils.isTokenOnSameLine(commaToken, currentItemToken)) {
context.report(reportItem, {
line: commaToken.loc.end.line,
column: commaToken.loc.end.column
}, "',' should be placed last.");
@@ -19068,25 +24951,50 @@
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
- return {
- "VariableDeclaration": function(node) {
+ var nodes = {};
+
+ if (!exceptions.VariableDeclaration) {
+ nodes.VariableDeclaration = function(node) {
validateComma(node, "declarations");
- },
- "ObjectExpression": function(node) {
+ };
+ }
+ if (!exceptions.ObjectExpression) {
+ nodes.ObjectExpression = function(node) {
validateComma(node, "properties");
- },
- "ArrayExpression": function(node) {
+ };
+ }
+ if (!exceptions.ArrayExpression) {
+ nodes.ArrayExpression = function(node) {
validateComma(node, "elements");
- }
- };
+ };
+ }
+ return nodes;
};
-},{}],142:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["first", "last"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "boolean"
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],133:[function(require,module,exports){
/**
* @fileoverview Counts the cyclomatic complexity of each function of the script. See http://en.wikipedia.org/wiki/Cyclomatic_complexity.
* Counts the number of if, conditional, for, whilte, try, switch/case,
* @author Patrick Brosset
*/
@@ -19106,39 +25014,70 @@
//--------------------------------------------------------------------------
// Using a stack to store complexity (handling nested functions)
var fns = [];
- // When parsing a new function, store it in our function stack
+ /**
+ * When parsing a new function, store it in our function stack
+ * @returns {void}
+ * @private
+ */
function startFunction() {
fns.push(1);
}
+ /**
+ * Evaluate the node at the end of function
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function endFunction(node) {
- var complexity = fns.pop(), name = "anonymous";
+ var complexity = fns.pop(),
+ name = "anonymous";
if (node.id) {
name = node.id.name;
+ } else if (node.parent.type === "MethodDefinition" || node.parent.type === "Property") {
+ name = node.parent.key.name;
}
+
if (complexity > THRESHOLD) {
context.report(node, "Function '{{name}}' has a complexity of {{complexity}}.", { name: name, complexity: complexity });
}
}
+ /**
+ * Increase the complexity of the function in context
+ * @returns {void}
+ * @private
+ */
function increaseComplexity() {
if (fns.length) {
fns[fns.length - 1] ++;
}
}
+ /**
+ * Increase the switch complexity in context
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function increaseSwitchComplexity(node) {
// Avoiding `default`
if (node.test) {
increaseComplexity(node);
}
}
+ /**
+ * Increase the logical path complexity in context
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function increaseLogicalComplexity(node) {
// Avoiding &&
if (node.operator === "||") {
increaseComplexity(node);
}
@@ -19168,12 +25107,173 @@
"DoWhileStatement": increaseComplexity
};
};
-},{}],143:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "integer"
+ }
+];
+
+},{}],134:[function(require,module,exports){
/**
+ * @fileoverview Disallows or enforces spaces inside computed properties.
+ * @author Jamund Ferguson
+ * @copyright 2015 Jamund Ferguson. All rights reserved.
+ */
+"use strict";
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var sourceCode = context.getSourceCode();
+ var propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never"
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Reports that there shouldn't be a space after the first token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @param {Token} tokenAfter - The token after `token`.
+ * @returns {void}
+ */
+ function reportNoBeginningSpace(node, token, tokenAfter) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "There should be no space after '" + token.value + "'",
+ fix: function(fixer) {
+ return fixer.removeRange([token.range[1], tokenAfter.range[0]]);
+ }
+ });
+ }
+
+ /**
+ * Reports that there shouldn't be a space before the last token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @param {Token} tokenBefore - The token before `token`.
+ * @returns {void}
+ */
+ function reportNoEndingSpace(node, token, tokenBefore) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "There should be no space before '" + token.value + "'",
+ fix: function(fixer) {
+ return fixer.removeRange([tokenBefore.range[1], token.range[0]]);
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a space after the first token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredBeginningSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "A space is required after '" + token.value + "'",
+ fix: function(fixer) {
+ return fixer.insertTextAfter(token, " ");
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a space before the last token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredEndingSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "A space is required before '" + token.value + "'",
+ fix: function(fixer) {
+ return fixer.insertTextBefore(token, " ");
+ }
+ });
+ }
+
+ /**
+ * Returns a function that checks the spacing of a node on the property name
+ * that was passed in.
+ * @param {String} propertyName The property on the node to check for spacing
+ * @returns {Function} A function that will check spacing on a node
+ */
+ function checkSpacing(propertyName) {
+ return function(node) {
+ if (!node.computed) {
+ return;
+ }
+
+ var property = node[propertyName];
+
+ var before = context.getTokenBefore(property),
+ first = context.getFirstToken(property),
+ last = context.getLastToken(property),
+ after = context.getTokenAfter(property);
+
+ if (astUtils.isTokenOnSameLine(before, first)) {
+ if (propertyNameMustBeSpaced) {
+ if (!sourceCode.isSpaceBetweenTokens(before, first) && astUtils.isTokenOnSameLine(before, first)) {
+ reportRequiredBeginningSpace(node, before);
+ }
+ } else {
+ if (sourceCode.isSpaceBetweenTokens(before, first)) {
+ reportNoBeginningSpace(node, before, first);
+ }
+ }
+ }
+
+ if (astUtils.isTokenOnSameLine(last, after)) {
+ if (propertyNameMustBeSpaced) {
+ if (!sourceCode.isSpaceBetweenTokens(last, after) && astUtils.isTokenOnSameLine(last, after)) {
+ reportRequiredEndingSpace(node, after);
+ }
+ } else {
+ if (sourceCode.isSpaceBetweenTokens(last, after)) {
+ reportNoEndingSpace(node, after, last);
+ }
+ }
+ }
+ };
+ }
+
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ Property: checkSpacing("key"),
+ MemberExpression: checkSpacing("property")
+ };
+
+};
+
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ }
+];
+
+},{"../ast-utils":113}],135:[function(require,module,exports){
+/**
* @fileoverview Rule to flag consistent return values
* @author Nicholas C. Zakas
*/
"use strict";
@@ -19243,15 +25343,18 @@
}
};
};
-},{}],144:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],136:[function(require,module,exports){
/**
* @fileoverview Rule to enforce consistent naming of "this" context variables
* @author Raphael Pigulla
* @copyright 2015 Timothy Jones. All rights reserved.
+ * @copyright 2015 David Aurelio. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
@@ -19298,80 +25401,205 @@
* is assigned to the correct value.
* @returns {void}
*/
function ensureWasAssigned() {
var scope = context.getScope();
+ var variable = scope.set.get(alias);
+ if (!variable) {
+ return;
+ }
- scope.variables.some(function (variable) {
- var lookup;
+ if (variable.defs.some(function(def) {
+ return def.node.type === "VariableDeclarator" &&
+ def.node.init !== null;
+ })) {
+ return;
+ }
- if (variable.name === alias) {
- if (variable.defs.some(function (def) {
- return def.node.type === "VariableDeclarator" &&
- def.node.init !== null;
- })) {
- return true;
- }
+ var lookup = (variable.references.length === 0 && scope.type === "global") ? scope : variable;
- lookup = scope.type === "global" ? scope : variable;
+ // The alias has been declared and not assigned: check it was
+ // assigned later in the same scope.
+ if (!lookup.references.some(function(reference) {
+ var write = reference.writeExpr;
- // The alias has been declared and not assigned: check it was
- // assigned later in the same scope.
- if (!lookup.references.some(function (reference) {
- var write = reference.writeExpr;
-
- if (reference.from === scope &&
- write && write.type === "ThisExpression" &&
- write.parent.operator === "=") {
- return true;
- }
- })) {
- variable.defs.map(function (def) {
- return def.node;
- }).forEach(reportBadAssignment);
- }
-
+ if (reference.from === scope &&
+ write && write.type === "ThisExpression" &&
+ write.parent.operator === "=") {
return true;
}
- });
+ })) {
+ variable.defs.map(function(def) {
+ return def.node;
+ }).forEach(reportBadAssignment);
+ }
}
return {
"Program:exit": ensureWasAssigned,
"FunctionExpression:exit": ensureWasAssigned,
"FunctionDeclaration:exit": ensureWasAssigned,
- "VariableDeclarator": function (node) {
- if (node.init !== null) {
- checkAssignment(node, node.id.name, node.init);
+ "VariableDeclarator": function(node) {
+ var id = node.id;
+ var isDestructuring =
+ id.type === "ArrayPattern" || id.type === "ObjectPattern";
+
+ if (node.init !== null && !isDestructuring) {
+ checkAssignment(node, id.name, node.init);
}
},
- "AssignmentExpression": function (node) {
+ "AssignmentExpression": function(node) {
if (node.left.type === "Identifier") {
checkAssignment(node, node.left.name, node.right);
}
}
};
};
-},{}],145:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "string"
+ }
+];
+
+},{}],137:[function(require,module,exports){
/**
+ * @fileoverview A rule to verify `super()` callings in constructor.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ /**
+ * Searches a class node from ancestors of a node.
+ * @param {Node} node - A node to get.
+ * @returns {ClassDeclaration|ClassExpression|null} the found class node or `null`.
+ */
+ function getClassInAncestor(node) {
+ while (node) {
+ if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
+ return node;
+ }
+ node = node.parent;
+ }
+ /* istanbul ignore next */
+ return null;
+ }
+
+ /**
+ * Checks whether or not a node is the null literal.
+ * @param {Node} node - A node to check.
+ * @returns {boolean} whether or not a node is the null literal.
+ */
+ function isNullLiteral(node) {
+ return node && node.type === "Literal" && node.value === null;
+ }
+
+ /**
+ * Checks whether or not the current traversal context is on constructors.
+ * @param {{scope: Scope}} item - A checking context to check.
+ * @returns {boolean} whether or not the current traversal context is on constructors.
+ */
+ function isOnConstructor(item) {
+ return item && item.scope === context.getScope().variableScope.upper.variableScope;
+ }
+
+ // A stack for checking context.
+ var stack = [];
+
+ return {
+ /**
+ * Start checking.
+ * @param {MethodDefinition} node - A target node.
+ * @returns {void}
+ */
+ "MethodDefinition": function(node) {
+ if (node.kind !== "constructor") {
+ return;
+ }
+ stack.push({
+ superCallings: [],
+ scope: context.getScope().variableScope
+ });
+ },
+
+ /**
+ * Checks the result, then reports invalid/missing `super()`.
+ * @param {MethodDefinition} node - A target node.
+ * @returns {void}
+ */
+ "MethodDefinition:exit": function(node) {
+ if (node.kind !== "constructor") {
+ return;
+ }
+ var result = stack.pop();
+
+ var classNode = getClassInAncestor(node);
+ /* istanbul ignore if */
+ if (!classNode) {
+ return;
+ }
+
+ if (classNode.superClass === null || isNullLiteral(classNode.superClass)) {
+ result.superCallings.forEach(function(superCalling) {
+ context.report(superCalling, "unexpected `super()`.");
+ });
+ } else if (result.superCallings.length === 0) {
+ context.report(node.key, "this constructor requires `super()`.");
+ }
+ },
+
+ /**
+ * Checks the result of checking, then reports invalid/missing `super()`.
+ * @param {MethodDefinition} node - A target node.
+ * @returns {void}
+ */
+ "CallExpression": function(node) {
+ var item = stack[stack.length - 1];
+ if (isOnConstructor(item) && node.callee.type === "Super") {
+ item.superCallings.push(node);
+ }
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{}],138:[function(require,module,exports){
+/**
* @fileoverview Rule to flag statements without curly braces
* @author Nicholas C. Zakas
+ * @copyright 2015 Ivan Nikulin. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
var multiOnly = (context.options[0] === "multi");
var multiLine = (context.options[0] === "multi-line");
+ var multiOrNest = (context.options[0] === "multi-or-nest");
+ var consistent = (context.options[1] === "consistent");
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
@@ -19386,83 +25614,258 @@
last = context.getLastToken(node);
return before.loc.start.line === last.loc.end.line;
}
/**
- * Checks the body of a node to see if it's a block statement. Depending on
- * the rule options, reports the appropriate problems.
+ * Determines if a given node is a one-liner.
+ * @param {ASTNode} node The node to check.
+ * @returns {boolean} True if the node is a one-liner.
+ * @private
+ */
+ function isOneLiner(node) {
+ var first = context.getFirstToken(node),
+ last = context.getLastToken(node);
+
+ return first.loc.start.line === last.loc.end.line;
+ }
+
+ /**
+ * Gets the `else` keyword token of a given `IfStatement` node.
+ * @param {ASTNode} node - A `IfStatement` node to get.
+ * @returns {Token} The `else` keyword token.
+ */
+ function getElseKeyword(node) {
+ var sourceCode = context.getSourceCode();
+ var token = sourceCode.getTokenAfter(node.consequent);
+
+ while (token.type !== "Keyword" || token.value !== "else") {
+ token = sourceCode.getTokenAfter(token);
+ }
+
+ return token;
+ }
+
+ /**
+ * Checks a given IfStatement node requires braces of the consequent chunk.
+ * This returns `true` when below:
+ *
+ * 1. The given node has the `alternate` node.
+ * 2. There is a `IfStatement` which doesn't have `alternate` node in the
+ * trailing statement chain of the `consequent` node.
+ *
+ * @param {ASTNode} node - A IfStatement node to check.
+ * @returns {boolean} `true` if the node requires braces of the consequent chunk.
+ */
+ function requiresBraceOfConsequent(node) {
+ if (node.alternate && node.consequent.type === "BlockStatement") {
+ if (node.consequent.body.length >= 2) {
+ return true;
+ }
+
+ node = node.consequent.body[0];
+ while (node) {
+ if (node.type === "IfStatement" && !node.alternate) {
+ return true;
+ }
+ node = astUtils.getTrailingStatement(node);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Reports "Expected { after ..." error
+ * @param {ASTNode} node The node to report.
+ * @param {string} name The name to report.
+ * @param {string} suffix Additional string to add to the end of a report.
+ * @returns {void}
+ * @private
+ */
+ function reportExpectedBraceError(node, name, suffix) {
+ context.report({
+ node: node,
+ loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
+ message: "Expected { after '{{name}}'{{suffix}}.",
+ data: {
+ name: name,
+ suffix: (suffix ? " " + suffix : "")
+ }
+ });
+ }
+
+ /**
+ * Reports "Unnecessary { after ..." error
+ * @param {ASTNode} node The node to report.
+ * @param {string} name The name to report.
+ * @param {string} suffix Additional string to add to the end of a report.
+ * @returns {void}
+ * @private
+ */
+ function reportUnnecessaryBraceError(node, name, suffix) {
+ context.report({
+ node: node,
+ loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
+ message: "Unnecessary { after '{{name}}'{{suffix}}.",
+ data: {
+ name: name,
+ suffix: (suffix ? " " + suffix : "")
+ }
+ });
+ }
+
+ /**
+ * Prepares to check the body of a node to see if it's a block statement.
* @param {ASTNode} node The node to report if there's a problem.
* @param {ASTNode} body The body node to check for blocks.
* @param {string} name The name to report if there's a problem.
* @param {string} suffix Additional string to add to the end of a report.
- * @returns {void}
+ * @returns {object} a prepared check object, with "actual", "expected", "check" properties.
+ * "actual" will be `true` or `false` whether the body is already a block statement.
+ * "expected" will be `true` or `false` if the body should be a block statement or not, or
+ * `null` if it doesn't matter, depending on the rule options. It can be modified to change
+ * the final behavior of "check".
+ * "check" will be a function reporting appropriate problems depending on the other
+ * properties.
*/
- function checkBody(node, body, name, suffix) {
+ function prepareCheck(node, body, name, suffix) {
var hasBlock = (body.type === "BlockStatement");
+ var expected = null;
- if (multiOnly) {
+ if (node.type === "IfStatement" && node.consequent === body && requiresBraceOfConsequent(node)) {
+ expected = true;
+ } else if (multiOnly) {
if (hasBlock && body.body.length === 1) {
- context.report(node, "Unnecessary { after '{{name}}'{{suffix}}.",
- {
- name: name,
- suffix: (suffix ? " " + suffix : "")
- }
- );
+ expected = false;
}
} else if (multiLine) {
- if (!hasBlock && !isCollapsedOneLiner(body)) {
- context.report(node, "Expected { after '{{name}}'{{suffix}}.",
- {
- name: name,
- suffix: (suffix ? " " + suffix : "")
- }
- );
+ if (!isCollapsedOneLiner(body)) {
+ expected = true;
}
+ } else if (multiOrNest) {
+ if (hasBlock && body.body.length === 1 && isOneLiner(body.body[0])) {
+ expected = false;
+ } else if (!isOneLiner(body)) {
+ expected = true;
+ }
} else {
- if (!hasBlock) {
- context.report(node, "Expected { after '{{name}}'{{suffix}}.",
- {
- name: name,
- suffix: (suffix ? " " + suffix : "")
+ expected = true;
+ }
+
+ return {
+ actual: hasBlock,
+ expected: expected,
+ check: function() {
+ if (this.expected !== null && this.expected !== this.actual) {
+ if (this.expected) {
+ reportExpectedBraceError(node, name, suffix);
+ } else {
+ reportUnnecessaryBraceError(node, name, suffix);
}
- );
+ }
}
+ };
+ }
+
+ /**
+ * Prepares to check the bodies of a "if", "else if" and "else" chain.
+ * @param {ASTNode} node The first IfStatement node of the chain.
+ * @returns {object[]} prepared checks for each body of the chain. See `prepareCheck` for more
+ * information.
+ */
+ function prepareIfChecks(node) {
+ var preparedChecks = [];
+ do {
+ preparedChecks.push(prepareCheck(node, node.consequent, "if", "condition"));
+ if (node.alternate && node.alternate.type !== "IfStatement") {
+ preparedChecks.push(prepareCheck(node, node.alternate, "else"));
+ break;
+ }
+ node = node.alternate;
+ } while (node);
+
+ if (consistent) {
+ // If any node should have or already have braces, make sure they all have braces.
+ // If all nodes shouldn't have braces, make sure they don't.
+ var expected = preparedChecks.some(function(preparedCheck) {
+ if (preparedCheck.expected !== null) {
+ return preparedCheck.expected;
+ }
+ return preparedCheck.actual;
+ });
+
+ preparedChecks.forEach(function(preparedCheck) {
+ preparedCheck.expected = expected;
+ });
}
+
+ return preparedChecks;
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
-
"IfStatement": function(node) {
-
- checkBody(node, node.consequent, "if", "condition");
-
- if (node.alternate && node.alternate.type !== "IfStatement") {
- checkBody(node, node.alternate, "else");
+ if (node.parent.type !== "IfStatement") {
+ prepareIfChecks(node).forEach(function(preparedCheck) {
+ preparedCheck.check();
+ });
}
-
},
"WhileStatement": function(node) {
- checkBody(node, node.body, "while", "condition");
+ prepareCheck(node, node.body, "while", "condition").check();
},
- "DoWhileStatement": function (node) {
- checkBody(node, node.body, "do");
+ "DoWhileStatement": function(node) {
+ prepareCheck(node, node.body, "do").check();
},
"ForStatement": function(node) {
- checkBody(node, node.body, "for", "condition");
+ prepareCheck(node, node.body, "for", "condition").check();
}
};
};
-},{}],146:[function(require,module,exports){
+module.exports.schema = {
+ "anyOf": [
+ {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ },
+ {
+ "enum": ["all"]
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 2
+ },
+ {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ },
+ {
+ "enum": ["multi", "multi-line", "multi-or-nest"]
+ },
+ {
+ "enum": ["consistent"]
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 3
+ }
+ ]
+};
+
+},{"../ast-utils":113}],139:[function(require,module,exports){
/**
* @fileoverview require default case in switch statements
* @author Aliaksei Shytkin
*/
"use strict";
@@ -19524,87 +25927,87 @@
}
}
};
};
-},{}],147:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],140:[function(require,module,exports){
/**
+ * @fileoverview Validates newlines before and after dots
+ * @author Greg Cochard
+ * @copyright 2015 Greg Cochard
+ */
+
+"use strict";
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var config = context.options[0],
+ // default to onObject if no preference is passed
+ onObject = config === "object" || !config;
+
+ /**
+ * Reports if the dot between object and property is on the correct loccation.
+ * @param {ASTNode} obj The object owning the property.
+ * @param {ASTNode} prop The property of the object.
+ * @param {ASTNode} node The corresponding node of the token.
+ * @returns {void}
+ */
+ function checkDotLocation(obj, prop, node) {
+ var dot = context.getTokenBefore(prop);
+
+ if (dot.type === "Punctuator" && dot.value === ".") {
+ if (onObject) {
+ if (!astUtils.isTokenOnSameLine(obj, dot)) {
+ context.report(node, dot.loc.start, "Expected dot to be on same line as object.");
+ }
+ } else if (!astUtils.isTokenOnSameLine(dot, prop)) {
+ context.report(node, dot.loc.start, "Expected dot to be on same line as property.");
+ }
+ }
+ }
+
+ /**
+ * Checks the spacing of the dot within a member expression.
+ * @param {ASTNode} node The node to check.
+ * @returns {void}
+ */
+ function checkNode(node) {
+ checkDotLocation(node.object, node.property, node);
+ }
+
+ return {
+ "MemberExpression": checkNode
+ };
+};
+
+module.exports.schema = [
+ {
+ "enum": ["object", "property"]
+ }
+];
+
+},{"../ast-utils":113}],141:[function(require,module,exports){
+/**
* @fileoverview Rule to warn about using dot notation instead of square bracket notation when possible.
* @author Josh Perez
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
var validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
-var keywords = [
- "this",
- "function",
- "if",
- "return",
- "var",
- "else",
- "for",
- "new",
- "arguments",
- "in",
- "typeof",
- "while",
- "case",
- "break",
- "try",
- "catch",
- "delete",
- "throw",
- "switch",
- "continue",
- "default",
- "instanceof",
- "do",
- "void",
- "finally",
- "with",
- "debugger",
- "eval",
- "implements",
- "interface",
- "package",
- "private",
- "protected",
- "public",
- "static",
- "yield",
- "let",
- "class",
- "enum",
- "export",
- "extends",
- "import",
- "super",
- "true",
- "false",
- "null",
- "abstract",
- "boolean",
- "byte",
- "char",
- "const",
- "double",
- "final",
- "float",
- "goto",
- "int",
- "long",
- "native",
- "short",
- "synchronized",
- "throws",
- "transient",
- "volatile"
-];
+var keywords = require("../util/keywords");
module.exports = function(context) {
var options = context.options[0] || {};
var allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords;
@@ -19634,11 +26037,26 @@
}
}
};
};
-},{}],148:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "allowKeywords": {
+ "type": "boolean"
+ },
+ "allowPattern": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../util/keywords":313}],142:[function(require,module,exports){
/**
* @fileoverview Require file to end with single newline.
* @author Nodeca Team <https://github.com/nodeca>
*/
"use strict";
@@ -19655,41 +26073,64 @@
return {
"Program": function checkBadEOF(node) {
// Get the whole source code, not for node only.
- var src = context.getSource(), location = {column: 1};
-
+ var src = context.getSource(),
+ location = {column: 1},
+ linebreakStyle = context.options[0] || "unix",
+ linebreak = linebreakStyle === "unix" ? "\n" : "\r\n";
if (src.length === 0) {
return;
}
if (src[src.length - 1] !== "\n") {
// file is not newline-terminated
location.line = src.split(/\n/g).length;
- context.report(node, location, "Newline required at end of file but not found.");
+ context.report({
+ node: node,
+ loc: location,
+ message: "Newline required at end of file but not found.",
+ fix: function(fixer) {
+ return fixer.insertTextAfterRange([0, src.length], linebreak);
+ }
+ });
}
}
};
};
-},{}],149:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["unix", "windows"]
+ }
+];
+
+},{}],143:[function(require,module,exports){
/**
* @fileoverview Rule to flag statements that use != and == instead of !== and ===
* @author Nicholas C. Zakas
+ * @copyright 2013 Nicholas C. Zakas. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var sourceCode = context.getSourceCode(),
+ replacements = {
+ "==": "===",
+ "!=": "!=="
+ };
+
/**
* Checks if an expression is a typeof expression
* @param {ASTNode} node The node to check
* @returns {boolean} if the node is a typeof expression
*/
@@ -19746,29 +26187,40 @@
if (node.operator !== "==" && node.operator !== "!=") {
return;
}
if (context.options[0] === "smart" && (isTypeOfBinary(node) ||
- areLiteralsAndSameType(node)) || isNullCheck(node)) {
+ areLiteralsAndSameType(node) || isNullCheck(node))) {
return;
}
if (context.options[0] === "allow-null" && isNullCheck(node)) {
return;
}
- context.report(
- node, getOperatorLocation(node),
- "Expected '{{op}}=' and instead saw '{{op}}'.",
- {op: node.operator}
- );
+ context.report({
+ node: node,
+ loc: getOperatorLocation(node),
+ message: "Expected '{{op}}=' and instead saw '{{op}}'.",
+ data: { op: node.operator },
+ fix: function(fixer) {
+ return fixer.replaceText(sourceCode.getTokenAfter(node.left), replacements[node.operator]);
+ }
+ });
+
}
};
};
-},{}],150:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["smart", "allow-null"]
+ }
+];
+
+},{}],144:[function(require,module,exports){
/**
* @fileoverview Rule to warn when a function expression does not have a name.
* @author Kyle T. Nunery
* @copyright 2015 Brandon Mills. All rights reserved.
* @copyright 2014 Kyle T. Nunery. All rights reserved.
@@ -19782,35 +26234,40 @@
module.exports = function(context) {
/**
* Determines whether the current FunctionExpression node is a get, set, or
- * shorthand method in an object literal.
+ * shorthand method in an object literal or a class.
* @returns {boolean} True if the node is a get, set, or shorthand method.
*/
- function isObjectMethod() {
+ function isObjectOrClassMethod() {
var parent = context.getAncestors().pop();
- return (parent.type === "Property" && (
- parent.method ||
- parent.kind === "get" ||
- parent.kind === "set"
+
+ return (parent.type === "MethodDefinition" || (
+ parent.type === "Property" && (
+ parent.method ||
+ parent.kind === "get" ||
+ parent.kind === "set"
+ )
));
}
return {
"FunctionExpression": function(node) {
var name = node.id && node.id.name;
- if (!name && !isObjectMethod()) {
+ if (!name && !isObjectOrClassMethod()) {
context.report(node, "Missing function expression name.");
}
}
};
};
-},{}],151:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],145:[function(require,module,exports){
/**
* @fileoverview Rule to enforce a particular function style
* @author Nicholas C. Zakas
* @copyright 2013 Nicholas C. Zakas. All rights reserved.
*/
@@ -19821,44 +26278,86 @@
//------------------------------------------------------------------------------
module.exports = function(context) {
var style = context.options[0],
- enforceDeclarations = (style === "declaration");
+ allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions === true,
+ enforceDeclarations = (style === "declaration"),
+ stack = [];
- return {
+ var nodesToCheck = {
+ "Program": function() {
+ stack = [];
+ },
"FunctionDeclaration": function(node) {
+ stack.push(false);
+
if (!enforceDeclarations) {
context.report(node, "Expected a function expression.");
}
},
+ "FunctionDeclaration:exit": function() {
+ stack.pop();
+ },
- "FunctionExpression": function() {
- var parent = context.getAncestors().pop();
+ "FunctionExpression": function(node) {
+ stack.push(false);
- if (enforceDeclarations && parent.type === "VariableDeclarator") {
- context.report(parent, "Expected a function declaration.");
+ if (enforceDeclarations && node.parent.type === "VariableDeclarator") {
+ context.report(node.parent, "Expected a function declaration.");
}
},
+ "FunctionExpression:exit": function() {
+ stack.pop();
+ },
- "ArrowFunctionExpression": function() {
- var parent = context.getAncestors().pop();
-
- if (enforceDeclarations && parent.type === "VariableDeclarator") {
- context.report(parent, "Expected a function declaration.");
+ "ThisExpression": function() {
+ if (stack.length > 0) {
+ stack[stack.length - 1] = true;
}
}
-
};
+ if (!allowArrowFunctions) {
+ nodesToCheck.ArrowFunctionExpression = function() {
+ stack.push(false);
+ };
+
+ nodesToCheck["ArrowFunctionExpression:exit"] = function(node) {
+ var hasThisExpr = stack.pop();
+
+ if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") {
+ context.report(node.parent, "Expected a function declaration.");
+ }
+ };
+ }
+
+ return nodesToCheck;
+
};
-},{}],152:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["declaration", "expression"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "allowArrowFunctions": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],146:[function(require,module,exports){
/**
- * @fileoverview Rule to check for the position of the * in your generator functions
+ * @fileoverview Rule to check the spacing around the * in generator functions.
* @author Jamund Ferguson
+ * @copyright 2015 Brandon Mills. All rights reserved.
* @copyright 2014 Jamund Ferguson. All rights reserved.
*/
"use strict";
@@ -19866,113 +26365,148 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var position = context.options[0] || "end";
+ var mode = (function(option) {
+ if (!option || typeof option === "string") {
+ return {
+ before: { before: true, after: false },
+ after: { before: false, after: true },
+ both: { before: true, after: true },
+ neither: { before: false, after: false }
+ }[option || "before"];
+ }
+ return option;
+ }(context.options[0]));
/**
- * Check the position of the star compared to the expected position.
- * @param {ASTNode} node - the entire function node
+ * Checks the spacing between two tokens before or after the star token.
+ * @param {string} side Either "before" or "after".
+ * @param {Token} leftToken `function` keyword token if side is "before", or
+ * star token if side is "after".
+ * @param {Token} rightToken Star token if side is "before", or identifier
+ * token if side is "after".
* @returns {void}
*/
- function checkStarPosition(node) {
- var starToken;
+ function checkSpacing(side, leftToken, rightToken) {
+ if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) {
+ var after = leftToken.value === "*";
+ var spaceRequired = mode[side];
+ var node = after ? leftToken : rightToken;
+ var type = spaceRequired ? "Missing" : "Unexpected";
+ var message = type + " space " + side + " *.";
+ context.report({
+ node: node,
+ message: message,
+ fix: function(fixer) {
+ if (spaceRequired) {
+ if (after) {
+ return fixer.insertTextAfter(node, " ");
+ }
+ return fixer.insertTextBefore(node, " ");
+ }
+ return fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
+ }
+ });
+ }
+ }
+ /**
+ * Enforces the spacing around the star if node is a generator function.
+ * @param {ASTNode} node A function expression or declaration node.
+ * @returns {void}
+ */
+ function checkFunction(node) {
+ var prevToken, starToken, nextToken;
+
if (!node.generator) {
return;
}
- // Blocked, pending decision to fix or work around in eslint/espree#36
- if (context.getAncestors().pop().method) {
- return;
+ if (node.parent.method || node.parent.type === "MethodDefinition") {
+ starToken = context.getTokenBefore(node, 1);
+ } else {
+ starToken = context.getFirstToken(node, 1);
}
- starToken = context.getFirstToken(node, 1);
-
- // check for function *name() {}
- if (position === "end") {
-
- // * starts where the next identifier begins
- if (starToken.range[1] !== context.getTokenAfter(starToken).range[0]) {
- context.report(node, "Expected a space before *.");
- }
+ // Only check before when preceded by `function` keyword
+ prevToken = context.getTokenBefore(starToken);
+ if (prevToken.value === "function" || prevToken.value === "static") {
+ checkSpacing("before", prevToken, starToken);
}
- // check for function* name() {}
- if (position === "start") {
-
- // * begins where the previous identifier ends
- if (starToken.range[0] !== context.getTokenBefore(starToken).range[1]) {
- context.report(node, "Expected no space before *.");
- }
+ // Only check after when followed by an identifier
+ nextToken = context.getTokenAfter(starToken);
+ if (nextToken.type === "Identifier") {
+ checkSpacing("after", starToken, nextToken);
}
-
- // check for function * name() {}
- if (position === "middle") {
-
- // must be a space before and afer the *
- if (starToken.range[0] <= context.getTokenBefore(starToken).range[1] ||
- starToken.range[1] >= context.getTokenAfter(starToken).range[0]) {
- context.report(node, "Expected spaces around *.");
- }
- }
}
return {
- "FunctionDeclaration": checkStarPosition,
- "FunctionExpression": checkStarPosition
+ "FunctionDeclaration": checkFunction,
+ "FunctionExpression": checkFunction
};
};
-},{}],153:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "oneOf": [
+ {
+ "enum": ["before", "after", "both", "neither"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "before": {"type": "boolean"},
+ "after": {"type": "boolean"}
+ },
+ "additionalProperties": false
+ }
+ ]
+ }
+];
+
+},{}],147:[function(require,module,exports){
/**
- * @fileoverview Rule to flag or require global strict mode.
- * @author Nicholas C. Zakas
+ * @fileoverview Rule for disallowing require() outside of the top-level module context
+ * @author Jamund Ferguson
+ * @copyright 2015 Jamund Ferguson. All rights reserved.
*/
+
"use strict";
-//------------------------------------------------------------------------------
-// Rule Definition
-//------------------------------------------------------------------------------
+var ACCEPTABLE_PARENTS = [
+ "AssignmentExpression",
+ "VariableDeclarator",
+ "MemberExpression",
+ "ExpressionStatement",
+ "CallExpression",
+ "ConditionalExpression",
+ "Program",
+ "VariableDeclaration"
+];
module.exports = function(context) {
-
- var mode = context.options[0];
-
- if (mode === "always") {
-
- return {
- "Program": function(node) {
- if (node.body.length > 0) {
- var statement = node.body[0];
-
- if (!(statement.type === "ExpressionStatement" && statement.expression.value === "use strict")) {
- context.report(node, "Use the global form of \"use strict\".");
- }
+ return {
+ "CallExpression": function(node) {
+ if (node.callee.name === "require") {
+ var isGoodRequire = context.getAncestors().every(function(parent) {
+ return ACCEPTABLE_PARENTS.indexOf(parent.type) > -1;
+ });
+ if (!isGoodRequire) {
+ context.report(node, "Unexpected require().");
}
}
- };
-
- } else { // mode = "never"
-
- return {
- "ExpressionStatement": function(node) {
- var parent = context.getAncestors().pop();
-
- if (node.expression.value === "use strict" && parent.type === "Program") {
- context.report(node, "Use the function form of \"use strict\".");
- }
- }
- };
-
- }
-
+ }
+ };
};
-},{}],154:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],148:[function(require,module,exports){
/**
* @fileoverview Rule to flag for-in loops without if statements inside
* @author Nicholas C. Zakas
*/
@@ -20000,14 +26534,17 @@
}
};
};
-},{}],155:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],149:[function(require,module,exports){
/**
* @fileoverview Ensure handling of errors when we know they exist.
* @author Jamund Ferguson
+ * @copyright 2015 Mathias Schreck.
* @copyright 2014 Jamund Ferguson. All rights reserved.
*/
"use strict";
@@ -20016,12 +26553,10 @@
//------------------------------------------------------------------------------
module.exports = function(context) {
var errorArgument = context.options[0] || "err";
- var callbacks = [];
- var scopes = 0;
/**
* Checks if the given argument should be interpreted as a regexp pattern.
* @param {string} stringToCheck The string which should be checked.
* @returns {boolean} Whether or not the string should be interpreted as a pattern.
@@ -20043,555 +26578,1195 @@
}
return name === errorArgument;
}
/**
- * Check the arguments to see if we need to start tracking the error object.
- * @param {ASTNode} node The AST node to check.
- * @returns {void}
+ * Get the parameters of a given function scope.
+ * @param {object} scope The function scope.
+ * @returns {array} All parameters of the given scope.
*/
- function startFunction(node) {
-
- // keep track of nested scopes
- scopes++;
-
- // check if the first argument matches our argument name
- var firstArg = node.params && node.params[0];
- if (firstArg && matchesConfiguredErrorName(firstArg.name)) {
- callbacks.push({handled: false, depth: scopes, errorVariableName: firstArg.name});
- }
+ function getParameters(scope) {
+ return scope.variables.filter(function(variable) {
+ return variable.defs[0] && variable.defs[0].type === "Parameter";
+ });
}
/**
- * At the end of a function check to see if the error was handled.
+ * Check to see if we're handling the error object properly.
* @param {ASTNode} node The AST node to check.
* @returns {void}
*/
- function endFunction(node) {
+ function checkForError(node) {
+ var scope = context.getScope(),
+ parameters = getParameters(scope),
+ firstParameter = parameters[0];
- var callback = callbacks[callbacks.length - 1] || {};
+ if (firstParameter && matchesConfiguredErrorName(firstParameter.name)) {
+ if (firstParameter.references.length === 0) {
+ context.report(node, "Expected error to be handled.");
+ }
+ }
+ }
- // check if a callback is ending, if so pop it off the stack
- if (callback.depth === scopes) {
- callbacks.pop();
+ return {
+ "FunctionDeclaration": checkForError,
+ "FunctionExpression": checkForError,
+ "ArrowFunctionExpression": checkForError
+ };
- // check if there were no handled errors since the last callback
- if (!callback.handled) {
- context.report(node, "Expected error to be handled.");
+};
+
+module.exports.schema = [
+ {
+ "type": "string"
+ }
+];
+
+},{}],150:[function(require,module,exports){
+/**
+ * @fileoverview Rule that warns when identifier names are shorter or longer
+ * than the values provided in configuration.
+ * @author Burak Yigit Kaya aka BYK
+ * @copyright 2015 Burak Yigit Kaya. All rights reserved.
+ * @copyright 2015 Mathieu M-Gosselin. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var options = context.options[0] || {};
+ var minLength = typeof options.min !== "undefined" ? options.min : 2;
+ var maxLength = typeof options.max !== "undefined" ? options.max : Infinity;
+ var properties = options.properties !== "never";
+ var exceptions = (options.exceptions ? options.exceptions : [])
+ .reduce(function(obj, item) {
+ obj[item] = true;
+
+ return obj;
+ }, {});
+
+ var SUPPORTED_EXPRESSIONS = {
+ "MemberExpression": properties && function(parent) {
+ return !parent.computed && (
+ // regular property assignment
+ parent.parent.left === parent || (
+ // or the last identifier in an ObjectPattern destructuring
+ parent.parent.type === "Property" && parent.parent.value === parent &&
+ parent.parent.parent.type === "ObjectPattern" && parent.parent.parent.parent.left === parent.parent.parent
+ )
+ );
+ },
+ "AssignmentPattern": function(parent, node) {
+ return parent.left === node;
+ },
+ "VariableDeclarator": function(parent, node) {
+ return parent.id === node;
+ },
+ "Property": properties && function(parent, node) {
+ return parent.key === node;
+ },
+ "ImportDefaultSpecifier": true,
+ "RestElement": true,
+ "FunctionExpression": true,
+ "ArrowFunctionExpression": true,
+ "ClassDeclaration": true,
+ "FunctionDeclaration": true,
+ "MethodDefinition": true,
+ "CatchClause": true
+ };
+
+ return {
+ Identifier: function(node) {
+ var name = node.name;
+ var parent = node.parent;
+
+ var isShort = name.length < minLength;
+ var isLong = name.length > maxLength;
+ if (!(isShort || isLong) || exceptions[name]) {
+ return; // Nothing to report
}
+
+ var isValidExpression = SUPPORTED_EXPRESSIONS[parent.type];
+
+ if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) {
+ context.report(
+ node,
+ isShort ?
+ "Identifier name '{{name}}' is too short. (< {{min}})" :
+ "Identifier name '{{name}}' is too long. (> {{max}})",
+ { name: name, min: minLength, max: maxLength }
+ );
+ }
}
+ };
+};
- // less nested functions
- scopes--;
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "min": {
+ "type": "number"
+ },
+ "max": {
+ "type": "number"
+ },
+ "exceptions": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "properties": {
+ "enum": ["always", "never"]
+ }
+ },
+ "additionalProperties": false
+ }
+];
+},{}],151:[function(require,module,exports){
+/**
+ * @fileoverview Rule to flag non-matching identifiers
+ * @author Matthieu Larcher
+ * @copyright 2015 Matthieu Larcher. All rights reserved.
+ * See LICENSE in root directory for full license.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ var pattern = context.options[0] || "^.+$",
+ regexp = new RegExp(pattern);
+
+ var options = context.options[1] || {},
+ properties = options.properties;
+
+ // cast to boolean and default to false
+ properties = !!properties;
+
+
+ /**
+ * Checks if a string matches the provided pattern
+ * @param {String} name The string to check.
+ * @returns {boolean} if the string is a match
+ * @private
+ */
+ function isInvalid(name) {
+ return !regexp.test(name);
}
/**
- * Check to see if we're handling the error object properly.
- * @param {ASTNode} node The AST node to check.
+ * Verifies if we should report an error or not based on the effective
+ * parent node and the identifier name.
+ * @param {ASTNode} effectiveParent The effective parent node of the node to be reported
+ * @param {String} name The identifier name of the identifier node
+ * @returns {boolean} whether an error should be reported or not
+ */
+ function shouldReport(effectiveParent, name) {
+ return effectiveParent.type !== "CallExpression"
+ && effectiveParent.type !== "NewExpression" &&
+ isInvalid(name);
+ }
+
+ /**
+ * Reports an AST node as a rule violation.
+ * @param {ASTNode} node The node to report.
* @returns {void}
+ * @private
*/
- function checkForError(node) {
- if (callbacks.length > 0) {
- var callback = callbacks[callbacks.length - 1] || {};
+ function report(node) {
+ context.report(node, "Identifier '{{name}}' does not match the pattern '{{pattern}}'.", {
+ name: node.name,
+ pattern: pattern
+ });
+ }
- // make sure the node's name matches our error argument name
- var isAboutError = node.name === callback.errorVariableName;
+ return {
- // we don't consider these use cases as "handling" the error
- var doNotCount = ["FunctionDeclaration", "ArrowFunctionExpression", "FunctionExpression", "CatchClause"];
+ "Identifier": function(node) {
+ var name = node.name,
+ effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
- // make sure this identifier isn't used as part of one of them
- var isHandled = doNotCount.indexOf(node.parent.type) === -1;
+ // MemberExpressions get special rules
+ if (node.parent.type === "MemberExpression") {
+ // return early if properties is false
+ if (!properties) {
+ return;
+ }
- if (isAboutError && isHandled) {
- // record that this callback handled its error
- callback.handled = true;
+ // Always check object names
+ if (node.parent.object.type === "Identifier" &&
+ node.parent.object.name === node.name) {
+ if (isInvalid(name)) {
+ report(node);
+ }
+
+ // Report AssignmentExpressions only if they are the left side of the assignment
+ } else if (effectiveParent.type === "AssignmentExpression" &&
+ (effectiveParent.right.type !== "MemberExpression" ||
+ effectiveParent.left.type === "MemberExpression" &&
+ effectiveParent.left.property.name === node.name)) {
+ if (isInvalid(name)) {
+ report(node);
+ }
+ }
+
+ // Properties have their own rules
+ } else if (node.parent.type === "Property") {
+ // return early if properties is false
+ if (!properties) {
+ return;
+ }
+
+ if (shouldReport(effectiveParent, name)) {
+ report(node);
+ }
+
+ // Report anything that is a match and not a CallExpression
+ } else if (shouldReport(effectiveParent, name)) {
+ report(node);
}
}
- }
- return {
- "FunctionDeclaration": startFunction,
- "FunctionExpression": startFunction,
- "ArrowFunctionExpression": startFunction,
- "Identifier": checkForError,
- "FunctionDeclaration:exit": endFunction,
- "FunctionExpression:exit": endFunction,
- "ArrowFunctionExpression:exit": endFunction
};
};
-},{}],156:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "properties": {
+ "type": "boolean"
+ }
+ }
+ }
+];
+
+},{}],152:[function(require,module,exports){
/**
* @fileoverview This option sets a specific tab width for your code
- * This rule has been ported and modified from JSCS.
- * @author Dmitriy Shekhovtsov
- * @copyright 2015 Dmitriy Shekhovtsov. All rights reserved.
- * @copyright 2013 Dulin Marat and other contributors.
- *
- * 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 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.
- */
-/*eslint no-use-before-define:[2, "nofunc"]*/
+
+ * This rule has been ported and modified from nodeca.
+ * @author Vitaly Puzrin
+ * @author Gyandeep Singh
+ * @copyright 2015 Vitaly Puzrin. All rights reserved.
+ * @copyright 2015 Gyandeep Singh. All rights reserved.
+ Copyright (C) 2014 by Vitaly Puzrin
+
+ 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 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.
+*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
+var util = require("util");
+var assign = require("object-assign");
-module.exports = function (context) {
- // indentation defaults: 4 spaces
- var indentChar = " ";
- var indentSize = 4;
- var options = {indentSwitchCase: false};
+module.exports = function(context) {
- var lines = null;
- var indentStack = [0];
- var linesToCheck = null;
- var breakIndents = null;
+ var MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}.";
+ var DEFAULT_VARIABLE_INDENT = 1;
+ var indentType = "space";
+ var indentSize = 4;
+ var options = {
+ SwitchCase: 0,
+ VariableDeclarator: {
+ var: DEFAULT_VARIABLE_INDENT,
+ let: DEFAULT_VARIABLE_INDENT,
+ const: DEFAULT_VARIABLE_INDENT
+ }
+ };
+
if (context.options.length) {
if (context.options[0] === "tab") {
- indentChar = "\t";
indentSize = 1;
- } else if (typeof context.options[0] === "number") {
+ indentType = "tab";
+ } else /* istanbul ignore else : this will be caught by options validation */ if (typeof context.options[0] === "number") {
indentSize = context.options[0];
+ indentType = "space";
}
if (context.options[1]) {
var opts = context.options[1];
- options.indentSwitchCase = opts.indentSwitchCase === true;
+ options.SwitchCase = opts.SwitchCase || 0;
+ var variableDeclaratorRules = opts.VariableDeclarator;
+ if (typeof variableDeclaratorRules === "number") {
+ options.VariableDeclarator = {
+ var: variableDeclaratorRules,
+ let: variableDeclaratorRules,
+ const: variableDeclaratorRules
+ };
+ } else if (typeof variableDeclaratorRules === "object") {
+ assign(options.VariableDeclarator, variableDeclaratorRules);
+ }
}
}
- var blockParents = [
- "IfStatement",
- "WhileStatement",
- "DoWhileStatement",
- "ForStatement",
- "ForInStatement",
- "ForOfStatement",
- "FunctionDeclaration",
- "FunctionExpression",
- "ArrowExpression",
- "CatchClause",
- "WithStatement"
- ];
-
- var indentableNodes = {
- BlockStatement: "body",
- Program: "body",
- ObjectExpression: "properties",
- ArrayExpression: "elements",
- SwitchStatement: "cases"
+ var indentPattern = {
+ normal: indentType === "space" ? /^ +/ : /^\t+/,
+ excludeCommas: indentType === "space" ? /^[ ,]+/ : /^[\t,]+/
};
- if (options.indentSwitchCase) {
- indentableNodes.SwitchCase = "consequent";
- }
+ var caseIndentStore = {};
- //--------------------------------------------------------------------------
- // Helpers
- //--------------------------------------------------------------------------
-
/**
- * Mark line to be checked
- * @param {Number} line - line number
+ * Reports a given indent violation and properly pluralizes the message
+ * @param {ASTNode} node Node violating the indent rule
+ * @param {int} needed Expected indentation character count
+ * @param {int} gotten Indentation character count in the actual node/code
+ * @param {Object=} loc Error line and column location
+ * @param {boolean} isLastNodeCheck Is the error for last node check
* @returns {void}
*/
- function markCheckLine(line) {
- linesToCheck[line].check = true;
- }
+ function report(node, needed, gotten, loc, isLastNodeCheck) {
+ var msgContext = {
+ needed: needed,
+ type: indentType,
+ characters: needed === 1 ? "character" : "characters",
+ gotten: gotten
+ };
+ var indentChar = indentType === "space" ? " " : "\t";
- /**
- * Mark line with targeted node to be checked
- * @param {ASTNode} checkNode - targeted node
- * @returns {void}
- */
- function markCheck(checkNode) {
- markCheckLine(checkNode.loc.start.line - 1);
- }
+ /**
+ * Responsible for fixing the indentation issue fix
+ * @returns {Function} function to be executed by the fixer
+ * @private
+ */
+ function getFixerFunction() {
+ var rangeToFix = [];
- /**
- * Sets pushing indent of current node
- * @param {ASTNode} node - targeted node
- * @param {Number} indents - indents count to push
- * @returns {void}
- */
- function markPush(node, indents) {
- linesToCheck[node.loc.start.line - 1].push.push(indents);
+ if (needed > gotten) {
+ var spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future
+
+ if (isLastNodeCheck === true) {
+ rangeToFix = [
+ node.range[1] - 1,
+ node.range[1] - 1
+ ];
+ } else {
+ rangeToFix = [
+ node.range[0],
+ node.range[0]
+ ];
+ }
+
+ return function(fixer) {
+ return fixer.insertTextBeforeRange(rangeToFix, spaces);
+ };
+ } else {
+ if (isLastNodeCheck === true) {
+ rangeToFix = [
+ node.range[1] - (gotten - needed) - 1,
+ node.range[1] - 1
+ ];
+ } else {
+ rangeToFix = [
+ node.range[0] - (gotten - needed),
+ node.range[0]
+ ];
+ }
+
+ return function(fixer) {
+ return fixer.removeRange(rangeToFix);
+ };
+ }
+ }
+
+ if (loc) {
+ context.report({
+ node: node,
+ loc: loc,
+ message: MESSAGE,
+ data: msgContext,
+ fix: getFixerFunction()
+ });
+ } else {
+ context.report({
+ node: node,
+ message: MESSAGE,
+ data: msgContext,
+ fix: getFixerFunction()
+ });
+ }
}
/**
- * Marks line as outdent, end of block statement for example
- * @param {ASTNode} node - targeted node
- * @param {Number} outdents - count of outedents in targeted line
- * @returns {void}
+ * Get node indent
+ * @param {ASTNode|Token} node Node to examine
+ * @param {boolean} [byLastLine=false] get indent of node's last line
+ * @param {boolean} [excludeCommas=false] skip comma on start of line
+ * @returns {int} Indent
*/
- function markPop(node, outdents) {
- linesToCheck[node.loc.end.line - 1].pop.push(outdents);
+ function getNodeIndent(node, byLastLine, excludeCommas) {
+ var token = byLastLine ? context.getLastToken(node) : context.getFirstToken(node);
+ var src = context.getSource(token, token.loc.start.column);
+ var regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal;
+ var indent = regExp.exec(src);
+
+ return indent ? indent[0].length : 0;
}
/**
- * Set alt push for current node
- * @param {ASTNode} node - targeted node
- * @returns {void}
+ * Checks node is the first in its own start line. By default it looks by start line.
+ * @param {ASTNode} node The node to check
+ * @param {boolean} [byEndLocation=false] Lookup based on start position or end
+ * @returns {boolean} true if its the first in the its start line
*/
- function markPushAlt(node) {
- linesToCheck[node.loc.start.line - 1].pushAltLine.push(node.loc.end.line - 1);
+ function isNodeFirstInLine(node, byEndLocation) {
+ var firstToken = byEndLocation === true ? context.getLastToken(node, 1) : context.getTokenBefore(node),
+ startLine = byEndLocation === true ? node.loc.end.line : node.loc.start.line,
+ endLine = firstToken ? firstToken.loc.end.line : -1;
+
+ return startLine !== endLine;
}
/**
- * Marks end of node block to be checked
- * and marks targeted node as indent pushing
- * @param {ASTNode} pushNode - targeted node
- * @param {Number} indents - indent count to push
+ * Check indent for nodes list
+ * @param {ASTNode[]} nodes list of node objects
+ * @param {int} indent needed indent
+ * @param {boolean} [excludeCommas=false] skip comma on start of line
* @returns {void}
*/
- function markPushAndEndCheck(pushNode, indents) {
- markPush(pushNode, indents);
- markCheckLine(pushNode.loc.end.line - 1);
+ function checkNodesIndent(nodes, indent, excludeCommas) {
+ nodes.forEach(function(node) {
+ var nodeIndent = getNodeIndent(node, false, excludeCommas);
+ if (
+ node.type !== "ArrayExpression" && node.type !== "ObjectExpression" &&
+ nodeIndent !== indent && isNodeFirstInLine(node)
+ ) {
+ report(node, indent, nodeIndent);
+ }
+ });
}
/**
- * Mark node as switch case statement
- * and set push\pop indentation changes
- * @param {ASTNode} caseNode - targeted node
- * @param {ASTNode[]} children - consequent child nodes of case node
+ * Check last node line indent this detects, that block closed correctly
+ * @param {ASTNode} node Node to examine
+ * @param {int} lastLineIndent needed indent
* @returns {void}
*/
- function markCase(caseNode, children) {
- var outdentNode = getCaseOutdent(children);
+ function checkLastNodeLineIndent(node, lastLineIndent) {
+ var lastToken = context.getLastToken(node);
+ var endIndent = getNodeIndent(lastToken, true);
- if (outdentNode) {
- // If a case statement has a `break` as a direct child and it is the
- // first one encountered, use it as the example for all future case indentation
- if (breakIndents === null) {
- breakIndents = (caseNode.loc.start.column === outdentNode.loc.start.column) ? 1 : 0;
- }
- markPop(outdentNode, breakIndents);
- } else {
- markPop(caseNode, 0);
+ if (endIndent !== lastLineIndent && isNodeFirstInLine(node, true)) {
+ report(
+ node,
+ lastLineIndent,
+ endIndent,
+ { line: lastToken.loc.start.line, column: lastToken.loc.start.column },
+ true
+ );
}
}
/**
- * Mark child nodes to be checked later of targeted node,
- * only if child node not in same line as targeted one
- * (if child and parent nodes wrote in single line)
- * @param {ASTNode} node - targeted node
+ * Check first node line indent is correct
+ * @param {ASTNode} node Node to examine
+ * @param {int} firstLineIndent needed indent
* @returns {void}
*/
- function markChildren(node) {
- getChildren(node).forEach(function(childNode) {
- if (childNode.loc.start.line !== node.loc.start.line || node.type === "Program") {
- markCheck(childNode);
- }
- });
+ function checkFirstNodeLineIndent(node, firstLineIndent) {
+ var startIndent = getNodeIndent(node, false);
+ if (startIndent !== firstLineIndent && isNodeFirstInLine(node)) {
+ report(
+ node,
+ firstLineIndent,
+ startIndent,
+ { line: node.loc.start.line, column: node.loc.start.column }
+ );
+ }
}
/**
- * Mark child block as scope pushing and mark to check
- * @param {ASTNode} node - target node
- * @param {String} property - target node property containing child
- * @returns {void}
+ * Returns the VariableDeclarator based on the current node
+ * if not present then return null
+ * @param {ASTNode} node node to examine
+ * @returns {ASTNode|void} if found then node otherwise null
*/
- function markAlternateBlockStatement(node, property) {
- var child = node[property];
- if (child && child.type === "BlockStatement") {
- markCheck(child);
+ function getVariableDeclaratorNode(node) {
+ var parent = node.parent;
+
+ while (parent.type !== "VariableDeclarator" && parent.type !== "Program") {
+ parent = parent.parent;
}
+
+ return parent.type === "VariableDeclarator" ? parent : null;
}
/**
- * Checks whether node is multiline or single line
- * @param {ASTNode} node - target node
- * @returns {boolean} - is multiline node
+ * Check to see if the node is part of the multi-line variable declaration.
+ * Also if its on the same line as the varNode
+ * @param {ASTNode} node node to check
+ * @param {ASTNode} varNode variable declaration node to check against
+ * @returns {boolean} True if all the above condition satisfy
*/
- function isMultiline(node) {
- return node.loc.start.line !== node.loc.end.line;
+ function isNodeInVarOnTop(node, varNode) {
+ return varNode &&
+ varNode.parent.loc.start.line === node.loc.start.line &&
+ varNode.parent.declarations.length > 1;
}
/**
- * Get switch case statement outdent node if any
- * @param {ASTNode[]} caseChildren - case statement childs
- * @returns {ASTNode} - outdent node
+ * Check to see if the argument before the callee node is multi-line and
+ * there should only be 1 argument before the callee node
+ * @param {ASTNode} node node to check
+ * @returns {boolean} True if arguments are multi-line
*/
- function getCaseOutdent(caseChildren) {
- var outdentNode;
- caseChildren.some(function(node) {
- if (node.type === "BreakStatement") {
- outdentNode = node;
- return true;
- }
- });
+ function isArgBeforeCalleeNodeMultiline(node) {
+ var parent = node.parent;
- return outdentNode;
+ if (parent.arguments.length >= 2 && parent.arguments[1] === node) {
+ return parent.arguments[0].loc.end.line > parent.arguments[0].loc.start.line;
+ }
+
+ return false;
}
/**
- * Returns block containing node
- * @param {ASTNode} node - targeted node
- * @returns {ASTNode} - block node
+ * Check indent for function block content
+ * @param {ASTNode} node node to examine
+ * @returns {void}
*/
- function getBlockNodeToMark(node) {
- var parent = node.parent;
+ function checkIndentInFunctionBlock(node) {
- // The parent of an else is the entire if/else block. To avoid over indenting
- // in the case of a non-block if with a block else, mark push where the else starts,
- // not where the if starts!
- if (parent.type === "IfStatement" && parent.alternate === node) {
- return node;
+ // Search first caller in chain.
+ // Ex.:
+ //
+ // Models <- Identifier
+ // .User
+ // .find()
+ // .exec(function() {
+ // // function body
+ // });
+ //
+ // Looks for 'Models'
+ var calleeNode = node.parent; // FunctionExpression
+ var indent;
+
+ if (calleeNode.parent &&
+ (calleeNode.parent.type === "Property" ||
+ calleeNode.parent.type === "ArrayExpression")) {
+ // If function is part of array or object, comma can be put at left
+ indent = getNodeIndent(calleeNode, false, true);
+ } else {
+ // If function is standalone, simple calculate indent
+ indent = getNodeIndent(calleeNode);
}
- // The end line to check of a do while statement needs to be the location of the
- // closing curly brace, not the while statement, to avoid marking the last line of
- // a multiline while as a line to check.
- if (parent.type === "DoWhileStatement") {
- return node;
+ if (calleeNode.parent.type === "CallExpression") {
+ var calleeParent = calleeNode.parent;
+
+ if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") {
+ if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) {
+ indent = getNodeIndent(calleeParent);
+ }
+ } else {
+ if (isArgBeforeCalleeNodeMultiline(calleeNode) &&
+ calleeParent.callee.loc.start.line === calleeParent.callee.loc.end.line &&
+ !isNodeFirstInLine(calleeNode)) {
+ indent = getNodeIndent(calleeParent);
+ }
+ }
}
- // Detect bare blocks: a block whose parent doesn"t expect blocks in its syntax specifically.
- if (blockParents.indexOf(parent.type) === -1) {
- return node;
+ // function body indent should be indent + indent size
+ indent += indentSize;
+
+ // check if the node is inside a variable
+ var parentVarNode = getVariableDeclaratorNode(node);
+ if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) {
+ indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind];
}
- return parent;
+ if (node.body.length > 0) {
+ checkNodesIndent(node.body, indent);
+ }
+
+ checkLastNodeLineIndent(node, indent - indentSize);
}
+
/**
- * Get node's children
- * @param {ASTNode} node - current node
- * @returns {ASTNode[]} - children
+ * Checks if the given node starts and ends on the same line
+ * @param {ASTNode} node The node to check
+ * @returns {boolean} Whether or not the block starts and ends on the same line.
*/
- function getChildren(node) {
- var childrenProperty = indentableNodes[node.type];
- return node[childrenProperty];
+ function isSingleLineNode(node) {
+ var lastToken = context.getLastToken(node),
+ startLine = node.loc.start.line,
+ endLine = lastToken.loc.end.line;
+
+ return startLine === endLine;
}
/**
- * Gets indentation in line `i`
- * @param {Number} i - number of line to get indentation
- * @returns {Number} - count of indentation symbols
+ * Check to see if the first element inside an array is an object and on the same line as the node
+ * If the node is not an array then it will return false.
+ * @param {ASTNode} node node to check
+ * @returns {boolean} success/failure
*/
- function getIndentationFromLine(i) {
- var rNotIndentChar = new RegExp("[^" + indentChar + "]");
- var firstContent = lines[i].search(rNotIndentChar);
- if (firstContent === -1) {
- firstContent = lines[i].length;
+ function isFirstArrayElementOnSameLine(node) {
+ if (node.type === "ArrayExpression" && node.elements[0]) {
+ return node.elements[0].loc.start.line === node.loc.start.line && node.elements[0].type === "ObjectExpression";
+ } else {
+ return false;
}
- return firstContent;
}
/**
- * Compares expected and actual indentation
- * and reports any violations
- * @param {ASTNode} node - node used only for reporting
+ * Check indent for array block content or object block content
+ * @param {ASTNode} node node to examine
* @returns {void}
*/
- function checkIndentations(node) {
- linesToCheck.forEach(function(line, i) {
- var actualIndentation = getIndentationFromLine(i);
- var expectedIndentation = getExpectedIndentation(line, actualIndentation);
+ function checkIndentInArrayOrObjectBlock(node) {
+ // Skip inline
+ if (isSingleLineNode(node)) {
+ return;
+ }
- if (line.check) {
+ var elements = (node.type === "ArrayExpression") ? node.elements : node.properties;
- if (actualIndentation !== expectedIndentation) {
- context.report(node,
- {line: i + 1, column: expectedIndentation},
- "Expected indentation of " + expectedIndentation + " characters.");
- // correct the indentation so that future lines
- // can be validated appropriately
- actualIndentation = expectedIndentation;
+ // filter out empty elements example would be [ , 2] so remove first element as espree considers it as null
+ elements = elements.filter(function(elem) {
+ return elem !== null;
+ });
+
+ // Skip if first element is in same line with this node
+ if (elements.length > 0 && elements[0].loc.start.line === node.loc.start.line) {
+ return;
+ }
+
+ var nodeIndent;
+ var elementsIndent;
+ var parentVarNode = getVariableDeclaratorNode(node);
+
+ // TODO - come up with a better strategy in future
+ if (isNodeFirstInLine(node)) {
+ var parent = node.parent;
+ var effectiveParent = parent;
+
+ if (parent.type === "MemberExpression") {
+ if (isNodeFirstInLine(parent)) {
+ effectiveParent = parent.parent.parent;
+ } else {
+ effectiveParent = parent.parent;
}
}
+ nodeIndent = getNodeIndent(effectiveParent);
+ if (parentVarNode && parentVarNode.loc.start.line !== node.loc.start.line) {
+ if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) {
+ nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
+ } else if (parent.loc.start.line !== node.loc.start.line && parentVarNode === parentVarNode.parent.declarations[0]) {
+ nodeIndent = nodeIndent + indentSize;
+ }
+ } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && effectiveParent.type !== "MemberExpression" && effectiveParent.type !== "ExpressionStatement" && effectiveParent.type !== "AssignmentExpression" && effectiveParent.type !== "Property") {
+ nodeIndent = nodeIndent + indentSize;
+ }
- if (line.push.length) {
- pushExpectedIndentations(line, actualIndentation);
+ elementsIndent = nodeIndent + indentSize;
+
+ checkFirstNodeLineIndent(node, nodeIndent);
+ } else {
+ nodeIndent = getNodeIndent(node);
+ elementsIndent = nodeIndent + indentSize;
+ }
+
+ // check if the node is a multiple variable declaration, if yes then make sure indentation takes into account
+ // variable indentation concept
+ if (isNodeInVarOnTop(node, parentVarNode)) {
+ elementsIndent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind];
+ }
+
+ // Comma can be placed before property name
+ checkNodesIndent(elements, elementsIndent, true);
+
+ if (elements.length > 0) {
+ // Skip last block line check if last item in same line
+ if (elements[elements.length - 1].loc.end.line === node.loc.end.line) {
+ return;
}
- });
+ }
+
+ checkLastNodeLineIndent(node, elementsIndent - indentSize);
}
/**
- * Counts expected indentation for given line number
- * @param {Number} line - line number
- * @param {Number} actual - actual indentation
- * @returns {number} - expected indentation
+ * Check if the node or node body is a BlockStatement or not
+ * @param {ASTNode} node node to test
+ * @returns {boolean} True if it or its body is a block statement
*/
- function getExpectedIndentation(line, actual) {
- var outdent = indentSize * Math.max.apply(null, line.pop);
+ function isNodeBodyBlock(node) {
+ return node.type === "BlockStatement" || (node.body && node.body.type === "BlockStatement") ||
+ (node.consequent && node.consequent.type === "BlockStatement");
+ }
- var idx = indentStack.length - 1;
- var expected = indentStack[idx];
+ /**
+ * Check indentation for blocks
+ * @param {ASTNode} node node to check
+ * @returns {void}
+ */
+ function blockIndentationCheck(node) {
+ // Skip inline blocks
+ if (isSingleLineNode(node)) {
+ return;
+ }
- if (!Array.isArray(expected)) {
- expected = [expected];
+ if (node.parent && (
+ node.parent.type === "FunctionExpression" ||
+ node.parent.type === "FunctionDeclaration" ||
+ node.parent.type === "ArrowFunctionExpression"
+ )) {
+ checkIndentInFunctionBlock(node);
+ return;
}
- expected = expected.map(function(value) {
- if (line.pop.length) {
- value -= outdent;
- }
+ var indent;
+ var nodesToCheck = [];
- return value;
- }).reduce(function(previous, current) {
- // when the expected is an array, resolve the value
- // back into a Number by checking both values are the actual indentation
- return actual === current ? current : previous;
- });
+ // For this statements we should check indent from statement begin
+ // (not from block begin)
+ var statementsWithProperties = [
+ "IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement"
+ ];
- indentStack[idx] = expected;
+ if (node.parent && statementsWithProperties.indexOf(node.parent.type) !== -1 && isNodeBodyBlock(node)) {
+ indent = getNodeIndent(node.parent);
+ } else {
+ indent = getNodeIndent(node);
+ }
- line.pop.forEach(function() {
- indentStack.pop();
- });
+ if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") {
+ nodesToCheck = [node.consequent];
+ } else if (util.isArray(node.body)) {
+ nodesToCheck = node.body;
+ } else {
+ nodesToCheck = [node.body];
+ }
- return expected;
+ if (nodesToCheck.length > 0) {
+ checkNodesIndent(nodesToCheck, indent + indentSize);
+ }
+
+ if (node.type === "BlockStatement") {
+ checkLastNodeLineIndent(node, indent);
+ }
}
/**
- * Store in stack expected indentations
- * @param {Number} line - current line
- * @param {Number} actualIndentation - actual indentation at current line
+ * Filter out the elements which are on the same line of each other or the node.
+ * basically have only 1 elements from each line except the variable declaration line.
+ * @param {ASTNode} node Variable declaration node
+ * @returns {ASTNode[]} Filtered elements
+ */
+ function filterOutSameLineVars(node) {
+ return node.declarations.reduce(function(finalCollection, elem) {
+ var lastElem = finalCollection[finalCollection.length - 1];
+
+ if ((elem.loc.start.line !== node.loc.start.line && !lastElem) ||
+ (lastElem && lastElem.loc.start.line !== elem.loc.start.line)) {
+ finalCollection.push(elem);
+ }
+
+ return finalCollection;
+ }, []);
+ }
+
+ /**
+ * Check indentation for variable declarations
+ * @param {ASTNode} node node to examine
* @returns {void}
*/
- function pushExpectedIndentations(line, actualIndentation) {
- var indents = Math.max.apply(null, line.push);
- var expected = actualIndentation + (indentSize * indents);
+ function checkIndentInVariableDeclarations(node) {
+ var elements = filterOutSameLineVars(node);
+ var nodeIndent = getNodeIndent(node);
+ var lastElement = elements[elements.length - 1];
- // when a line has alternate indentations, push an array of possible values
- // on the stack, to be resolved when checked against an actual indentation
- if (line.pushAltLine.length) {
- expected = [expected];
- line.pushAltLine.forEach(function(altLine) {
- expected.push(getIndentationFromLine(altLine) + (indentSize * indents));
- });
+ var elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind];
+
+ // Comma can be placed before declaration
+ checkNodesIndent(elements, elementsIndent, true);
+
+ // Only check the last line if there is any token after the last item
+ if (context.getLastToken(node).loc.end.line <= lastElement.loc.end.line) {
+ return;
}
- line.push.forEach(function() {
- indentStack.push(expected);
- });
+ var tokenBeforeLastElement = context.getTokenBefore(lastElement);
+
+ if (tokenBeforeLastElement.value === ",") {
+ // Special case for comma-first syntax where the semicolon is indented
+ checkLastNodeLineIndent(node, getNodeIndent(tokenBeforeLastElement));
+ } else {
+ checkLastNodeLineIndent(node, elementsIndent - indentSize);
+ }
}
- //--------------------------------------------------------------------------
- // Public
- //--------------------------------------------------------------------------
+ /**
+ * Check and decide whether to check for indentation for blockless nodes
+ * Scenarios are for or while statements without braces around them
+ * @param {ASTNode} node node to examine
+ * @returns {void}
+ */
+ function blockLessNodes(node) {
+ if (node.body.type !== "BlockStatement") {
+ blockIndentationCheck(node);
+ }
+ }
- return {
- "Program": function (node) {
- lines = context.getSourceLines();
- linesToCheck = lines.map(function () {
- return {
- push: [],
- pushAltLine: [],
- pop: [],
- check: false
- };
- });
+ /**
+ * Returns the expected indentation for the case statement
+ * @param {ASTNode} node node to examine
+ * @param {int} [switchIndent] indent for switch statement
+ * @returns {int} indent size
+ */
+ function expectedCaseIndent(node, switchIndent) {
+ var switchNode = (node.type === "SwitchStatement") ? node : node.parent;
+ var caseIndent;
- if (!isMultiline(node)) {
- return;
+ if (caseIndentStore[switchNode.loc.start.line]) {
+ return caseIndentStore[switchNode.loc.start.line];
+ } else {
+ if (typeof switchIndent === "undefined") {
+ switchIndent = getNodeIndent(switchNode);
}
- markChildren(node);
- },
- "Program:exit": function (node) {
- checkIndentations(node);
- },
+ if (switchNode.cases.length > 0 && options.SwitchCase === 0) {
+ caseIndent = switchIndent;
+ } else {
+ caseIndent = switchIndent + (indentSize * options.SwitchCase);
+ }
- "BlockStatement": function (node) {
- if (!isMultiline(node)) {
- return;
+ caseIndentStore[switchNode.loc.start.line] = caseIndent;
+ return caseIndent;
+ }
+ }
+
+ return {
+ "Program": function(node) {
+ if (node.body.length > 0) {
+ // Root nodes should have no indent
+ checkNodesIndent(node.body, getNodeIndent(node));
}
+ },
- markChildren(node);
- markPop(node, 1);
+ "BlockStatement": blockIndentationCheck,
- markPushAndEndCheck(getBlockNodeToMark(node), 1);
+ "WhileStatement": blockLessNodes,
+
+ "ForStatement": blockLessNodes,
+
+ "ForInStatement": blockLessNodes,
+
+ "ForOfStatement": blockLessNodes,
+
+ "DoWhileStatement": blockLessNodes,
+
+ "IfStatement": function(node) {
+ if (node.consequent.type !== "BlockStatement" && node.consequent.loc.start.line > node.loc.start.line) {
+ blockIndentationCheck(node);
+ }
},
- "IfStatement": function (node) {
- markAlternateBlockStatement(node, "alternate");
+ "VariableDeclaration": function(node) {
+ if (node.declarations[node.declarations.length - 1].loc.start.line > node.declarations[0].loc.start.line) {
+ checkIndentInVariableDeclarations(node);
+ }
},
- "TryStatement": function (node) {
- markAlternateBlockStatement(node, "handler");
- markAlternateBlockStatement(node, "finalizer");
+ "ObjectExpression": function(node) {
+ checkIndentInArrayOrObjectBlock(node);
},
- "SwitchStatement": function (node) {
- if (!isMultiline(node)) {
- return;
- }
+ "ArrayExpression": function(node) {
+ checkIndentInArrayOrObjectBlock(node);
+ },
- var indents = 1;
- var children = getChildren(node);
+ "SwitchStatement": function(node) {
+ // Switch is not a 'BlockStatement'
+ var switchIndent = getNodeIndent(node);
+ var caseIndent = expectedCaseIndent(node, switchIndent);
+ checkNodesIndent(node.cases, caseIndent);
- if (node.loc.start.column === children[0].loc.start.column) {
- indents = 0;
- }
- markChildren(node);
- markPop(node, indents);
- markPushAndEndCheck(node, indents);
+ checkLastNodeLineIndent(node, switchIndent);
},
- "SwitchCase": function (node) {
- if (!options.indentSwitchCase) {
+ "SwitchCase": function(node) {
+ // Skip inline cases
+ if (isSingleLineNode(node)) {
return;
}
+ var caseIndent = expectedCaseIndent(node);
+ checkNodesIndent(node.consequent, caseIndent + indentSize);
+ }
+ };
- if (!isMultiline(node)) {
- return;
+};
+
+module.exports.schema = [
+ {
+ "oneOf": [
+ {
+ "enum": ["tab"]
+ },
+ {
+ "type": "integer"
}
+ ]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "SwitchCase": {
+ "type": "integer"
+ },
+ "VariableDeclarator": {
+ "type": ["integer", "object"],
+ "properties": {
+ "var": {
+ "type": "integer"
+ },
+ "let": {
+ "type": "integer"
+ },
+ "const": {
+ "type": "integer"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+];
- var children = getChildren(node);
+},{"object-assign":108,"util":111}],153:[function(require,module,exports){
+/**
+ * @fileoverview A rule to control the style of variable initializations.
+ * @author Colin Ihrig
+ * @copyright 2015 Colin Ihrig. All rights reserved.
+ */
- if (children.length === 1 && children[0].type === "BlockStatement") {
- return;
- }
+"use strict";
- markPush(node, 1);
- markCheck(node);
- markChildren(node);
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
- markCase(node, children);
- },
+/**
+ * Checks whether or not a given node is a for loop.
+ * @param {ASTNode} block - A node to check.
+ * @returns {boolean} `true` when the node is a for loop.
+ */
+function isForLoop(block) {
+ return block.type === "ForInStatement" ||
+ block.type === "ForOfStatement" ||
+ block.type === "ForStatement";
+}
- // indentations inside of function expressions can be offset from
- // either the start of the function or the end of the function, therefore
- // mark all starting lines of functions as potential indentations
- "FunctionDeclaration": function (node) {
- markPushAlt(node);
- },
- "FunctionExpression": function (node) {
- markPushAlt(node);
+/**
+ * Checks whether or not a given declarator node has its initializer.
+ * @param {ASTNode} node - A declarator node to check.
+ * @returns {boolean} `true` when the node has its initializer.
+ */
+function isInitialized(node) {
+ var declaration = node.parent;
+ var block = declaration.parent;
+
+ if (isForLoop(block)) {
+ if (block.type === "ForStatement") {
+ return block.init === declaration;
}
+ return block.left === declaration;
+ }
+ return Boolean(node.init);
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var MODE_ALWAYS = "always",
+ MODE_NEVER = "never";
+
+ var mode = context.options[0] || MODE_ALWAYS;
+ var params = context.options[1] || {};
+ //--------------------------------------------------------------------------
+ // Public API
+ //--------------------------------------------------------------------------
+
+ return {
+ "VariableDeclaration:exit": function(node) {
+
+ var kind = node.kind,
+ declarations = node.declarations;
+
+ for (var i = 0; i < declarations.length; ++i) {
+ var declaration = declarations[i],
+ id = declaration.id,
+ initialized = isInitialized(declaration),
+ isIgnoredForLoop = params.ignoreForLoopInit && isForLoop(node.parent);
+ if (id.type !== "Identifier") {
+ continue;
+ }
+
+ if (mode === MODE_ALWAYS && !initialized) {
+ context.report(declaration, "Variable '" + id.name + "' should be initialized on declaration.");
+ } else if (mode === MODE_NEVER && kind !== "const" && initialized && !isIgnoredForLoop) {
+ context.report(declaration, "Variable '" + id.name + "' should not be initialized on declaration.");
+ }
+ }
+ }
};
+};
+module.exports.schema = {
+ "anyOf": [
+ {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ },
+ {
+ "enum": ["always"]
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 2
+ },
+ {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ },
+ {
+ "enum": ["never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "ignoreForLoopInit": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 3
+ }
+ ]
};
-},{}],157:[function(require,module,exports){
+},{}],154:[function(require,module,exports){
/**
+ * @fileoverview A rule to ensure consistent quotes used in jsx syntax.
+ * @author Mathias Schreck <https://github.com/lo1tuma>
+ * @copyright 2015 Mathias Schreck
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+var QUOTE_SETTINGS = {
+ "prefer-double": {
+ quote: "\"",
+ description: "singlequote"
+ },
+ "prefer-single": {
+ quote: "'",
+ description: "doublequote"
+ }
+};
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var quoteOption = context.options[0] || "prefer-double",
+ setting = QUOTE_SETTINGS[quoteOption];
+
+ /**
+ * Checks if the given string literal node uses the expected quotes
+ * @param {ASTNode} node - A string literal node.
+ * @returns {boolean} Whether or not the string literal used the expected quotes.
+ * @public
+ */
+ function usesExpectedQuotes(node) {
+ return node.value.indexOf(setting.quote) !== -1 || astUtils.isSurroundedBy(node.raw, setting.quote);
+ }
+
+ return {
+ "JSXAttribute": function(node) {
+ var attributeValue = node.value;
+
+ if (attributeValue && astUtils.isStringLiteral(attributeValue) && !usesExpectedQuotes(attributeValue)) {
+ context.report(attributeValue, "Unexpected usage of {{description}}.", setting);
+ }
+ }
+ };
+};
+
+module.exports.schema = [
+ {
+ "enum": [ "prefer-single", "prefer-double" ]
+ }
+];
+
+},{"../ast-utils":113}],155:[function(require,module,exports){
+/**
* @fileoverview Rule to specify spacing of object literal keys and values
* @author Brandon Mills
* @copyright 2014 Brandon Mills. All rights reserved.
*/
"use strict";
@@ -20609,29 +27784,10 @@
function containsLineTerminator(str) {
return /[\n\r\u2028\u2029]/.test(str);
}
/**
- * Gets an object literal property's key as the identifier name or string value.
- * @param {ASTNode} property Property node whose key to retrieve.
- * @returns {string} The property's key.
- */
-function getKey(property) {
- return property.key.name || property.key.value;
-}
-
-/**
- * Gets the number of characters in a key, including quotes around string keys.
- * @param {ASTNode} property Property of on object literal.
- * @returns {int} Width of the key, including string quotes where present.
- */
-function getKeyWidth(property) {
- var key = property.key;
- return (key.type === "Identifier" ? key.name : key.raw).length;
-}
-
-/**
* Gets the last element of an array.
* @param {Array} arr An array.
* @returns {any} Last element of arr.
*/
function last(arr) {
@@ -20643,11 +27799,11 @@
* @param {ASTNode} lastMember The last Property known to be in the group.
* @param {ASTNode} candidate The next Property that might be in the group.
* @returns {boolean} True if the candidate property is part of the group.
*/
function continuesPropertyGroup(lastMember, candidate) {
- var groupEndLine = lastMember.loc.end.line,
+ var groupEndLine = lastMember.loc.start.line,
candidateStartLine = candidate.loc.start.line,
comments, i;
if (candidateStartLine - groupEndLine <= 1) {
return true;
@@ -20671,17 +27827,26 @@
}
return false;
}
+/**
+ * Checks whether a node is contained on a single line.
+ * @param {ASTNode} node AST Node being evaluated.
+ * @returns {boolean} True if the node is a single line.
+ */
+function isSingleLine(node) {
+ return (node.loc.end.line === node.loc.start.line);
+}
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
var messages = {
- key: "{{error}} space after key \"{{key}}\".",
- value: "{{error}} space before value for key \"{{key}}\"."
+ key: "{{error}} space after {{computed}}key \"{{key}}\".",
+ value: "{{error}} space before value for {{computed}}key \"{{key}}\"."
};
module.exports = function(context) {
/**
@@ -20693,32 +27858,47 @@
* }
*/
var options = context.options[0] || {},
align = options.align,
+ mode = options.mode || "strict",
beforeColon = +!!options.beforeColon, // Defaults to false
afterColon = +!(options.afterColon === false); // Defaults to true
/**
- * Gets the whitespace around the colon in an object literal property.
- * @param {ASTNode} property Property node from an object literal.
- * @returns {Object} Whitespace before and after the property's colon.
+ * Starting from the given a node (a property.key node here) looks forward
+ * until it finds the last token before a colon punctuator and returns it.
+ * @param {ASTNode} node The node to start looking from.
+ * @returns {ASTNode} The last token before a colon punctuator.
*/
- function getPropertyWhitespace(property) {
- var whitespace = /^(\s*):(\s*)/.exec(context.getSource().slice(
- property.key.range[1], property.value.range[0]
- ));
+ function getLastTokenBeforeColon(node) {
+ var prevNode;
- if (whitespace) {
- return {
- beforeColon: whitespace[1],
- afterColon: whitespace[2]
- };
+ while (node && (node.type !== "Punctuator" || node.value !== ":")) {
+ prevNode = node;
+ node = context.getTokenAfter(node);
}
+
+ return prevNode;
}
/**
+ * Gets an object literal property's key as the identifier name or string value.
+ * @param {ASTNode} property Property node whose key to retrieve.
+ * @returns {string} The property's key.
+ */
+ function getKey(property) {
+ var key = property.key;
+
+ if (property.computed) {
+ return context.getSource().slice(key.range[0], key.range[1]);
+ }
+
+ return property.key.name || property.key.value;
+ }
+
+ /**
* Reports an appropriately-formatted error if spacing is incorrect on one
* side of the colon.
* @param {ASTNode} property Key-value pair in an object literal.
* @param {string} side Side being verified - either "key" or "value".
* @param {string} whitespace Actual whitespace string.
@@ -20729,24 +27909,89 @@
var diff = whitespace.length - expected,
key = property.key,
firstTokenAfterColon = context.getTokenAfter(key, 1),
location = side === "key" ? key.loc.start : firstTokenAfterColon.loc.start;
- if (diff && !(expected && containsLineTerminator(whitespace))) {
+ if ((diff && mode === "strict" || diff < 0 && mode === "minimum") &&
+ !(expected && containsLineTerminator(whitespace))
+ ) {
context.report(property[side], location, messages[side], {
error: diff > 0 ? "Extra" : "Missing",
+ computed: property.computed ? "computed " : "",
key: getKey(property)
});
}
}
/**
+ * Gets the number of characters in a key, including quotes around string
+ * keys and braces around computed property keys.
+ * @param {ASTNode} property Property of on object literal.
+ * @returns {int} Width of the key.
+ */
+ function getKeyWidth(property) {
+ var startToken, endToken;
+
+ // Ignore shorthand methods and properties, as they have no colon
+ if (property.method || property.shorthand) {
+ return 0;
+ }
+
+ startToken = context.getFirstToken(property);
+ endToken = getLastTokenBeforeColon(property.key);
+
+ return endToken.range[1] - startToken.range[0];
+ }
+
+ /**
+ * Gets the whitespace around the colon in an object literal property.
+ * @param {ASTNode} property Property node from an object literal.
+ * @returns {Object} Whitespace before and after the property's colon.
+ */
+ function getPropertyWhitespace(property) {
+ var whitespace = /(\s*):(\s*)/.exec(context.getSource().slice(
+ property.key.range[1], property.value.range[0]
+ ));
+
+ if (whitespace) {
+ return {
+ beforeColon: whitespace[1],
+ afterColon: whitespace[2]
+ };
+ }
+ }
+
+ /**
+ * Creates groups of properties.
+ * @param {ASTNode} node ObjectExpression node being evaluated.
+ * @returns {Array.<ASTNode[]>} Groups of property AST node lists.
+ */
+ function createGroups(node) {
+ if (node.properties.length === 1) {
+ return [node.properties];
+ }
+
+ return node.properties.reduce(function(groups, property) {
+ var currentGroup = last(groups),
+ prev = last(currentGroup);
+
+ if (!prev || continuesPropertyGroup(prev, property)) {
+ currentGroup.push(property);
+ } else {
+ groups.push([property]);
+ }
+
+ return groups;
+ }, [[]]);
+ }
+
+ /**
* Verifies correct vertical alignment of a group of properties.
* @param {ASTNode[]} properties List of Property AST nodes.
* @returns {void}
*/
- function verifyAlignment(properties) {
+ function verifyGroupAlignment(properties) {
var length = properties.length,
widths = properties.map(getKeyWidth), // Width of keys, including quotes
targetWidth = Math.max.apply(null, widths),
i, property, whitespace, width;
@@ -20771,48 +28016,506 @@
report(property, "value", whitespace.afterColon, afterColon);
}
}
}
+ /**
+ * Verifies vertical alignment, taking into account groups of properties.
+ * @param {ASTNode} node ObjectExpression node being evaluated.
+ * @returns {void}
+ */
+ function verifyAlignment(node) {
+ createGroups(node).forEach(function(group) {
+ verifyGroupAlignment(group);
+ });
+ }
+
+ /**
+ * Verifies spacing of property conforms to specified options.
+ * @param {ASTNode} node Property node being evaluated.
+ * @returns {void}
+ */
+ function verifySpacing(node) {
+ var whitespace = getPropertyWhitespace(node);
+ if (whitespace) { // Object literal getters/setters lack colons
+ report(node, "key", whitespace.beforeColon, beforeColon);
+ report(node, "value", whitespace.afterColon, afterColon);
+ }
+ }
+
+ /**
+ * Verifies spacing of each property in a list.
+ * @param {ASTNode[]} properties List of Property AST nodes.
+ * @returns {void}
+ */
+ function verifyListSpacing(properties) {
+ var length = properties.length;
+
+ for (var i = 0; i < length; i++) {
+ verifySpacing(properties[i]);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Public API
+ //--------------------------------------------------------------------------
+
if (align) { // Verify vertical alignment
return {
"ObjectExpression": function(node) {
- node.properties.reduce(function(groups, property) {
- var currentGroup = last(groups),
- prev = last(currentGroup);
-
- if (!prev || continuesPropertyGroup(prev, property)) {
- currentGroup.push(property);
- } else {
- groups.push([property]);
- }
-
- return groups;
- }, [[]]).forEach(function(group) {
- verifyAlignment(group);
- });
+ if (isSingleLine(node)) {
+ verifyListSpacing(node.properties);
+ } else {
+ verifyAlignment(node);
+ }
}
};
} else { // Strictly obey beforeColon and afterColon in each property
return {
- "Property": function (node) {
- var whitespace = getPropertyWhitespace(node);
- if (whitespace) { // Object literal getters/setters lack colons
- report(node, "key", whitespace.beforeColon, beforeColon);
- report(node, "value", whitespace.afterColon, afterColon);
+ "Property": function(node) {
+ verifySpacing(node);
+ }
+ };
+
+ }
+
+};
+
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "align": {
+ "enum": ["colon", "value"]
+ },
+ "mode": {
+ "enum": ["strict", "minimum"]
+ },
+ "beforeColon": {
+ "type": "boolean"
+ },
+ "afterColon": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],156:[function(require,module,exports){
+/**
+ * @fileoverview Rule to forbid mixing LF and LFCR line breaks.
+ * @author Erik Mueller
+ * @copyright 2015 Varun Verma. All rights reserverd.
+ * @copyright 2015 James Whitney. All rights reserved.
+ * @copyright 2015 Erik Mueller. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.",
+ EXPECTED_CRLF_MSG = "Expected linebreaks to be 'CRLF' but found 'LF'.";
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Builds a fix function that replaces text at the specified range in the source text.
+ * @param {int[]} range The range to replace
+ * @param {string} text The text to insert.
+ * @returns {function} Fixer function
+ * @private
+ */
+ function createFix(range, text) {
+ return function(fixer) {
+ return fixer.replaceTextRange(range, text);
+ };
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ "Program": function checkForlinebreakStyle(node) {
+ var linebreakStyle = context.options[0] || "unix",
+ expectedLF = linebreakStyle === "unix",
+ expectedLFChars = expectedLF ? "\n" : "\r\n",
+ source = context.getSource(),
+ pattern = /\r\n|\r|\n|\u2028|\u2029/g,
+ match,
+ index,
+ range;
+
+ var i = 0;
+ while ((match = pattern.exec(source)) !== null) {
+ i++;
+ if (match[0] === expectedLFChars) {
+ continue;
}
+
+ index = match.index;
+ range = [index, index + match[0].length];
+ context.report({
+ node: node,
+ loc: {
+ line: i,
+ column: context.getSourceLines()[i - 1].length
+ },
+ message: expectedLF ? EXPECTED_LF_MSG : EXPECTED_CRLF_MSG,
+ fix: createFix(range, expectedLFChars)
+ });
}
+ }
+ };
+};
+
+module.exports.schema = [
+ {
+ "enum": ["unix", "windows"]
+ }
+];
+
+},{}],157:[function(require,module,exports){
+/**
+ * @fileoverview Enforces empty lines around comments.
+ * @author Jamund Ferguson
+ * @copyright 2015 Mathieu M-Gosselin. All rights reserved.
+ * @copyright 2015 Jamund Ferguson. All rights reserved.
+ * @copyright 2015 Gyandeep Singh. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var assign = require("object-assign");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Return an array with with any line numbers that are empty.
+ * @param {Array} lines An array of each line of the file.
+ * @returns {Array} An array of line numbers.
+ */
+function getEmptyLineNums(lines) {
+ var emptyLines = lines.map(function(line, i) {
+ return {
+ code: line.trim(),
+ num: i + 1
};
+ }).filter(function(line) {
+ return !line.code;
+ }).map(function(line) {
+ return line.num;
+ });
+ return emptyLines;
+}
+/**
+ * Return an array with with any line numbers that contain comments.
+ * @param {Array} comments An array of comment nodes.
+ * @returns {Array} An array of line numbers.
+ */
+function getCommentLineNums(comments) {
+ var lines = [];
+ comments.forEach(function(token) {
+ var start = token.loc.start.line;
+ var end = token.loc.end.line;
+ lines.push(start, end);
+ });
+ return lines;
+}
+
+/**
+ * Determines if a value is an array.
+ * @param {number} val The value we wish to check for in the array..
+ * @param {Array} array An array.
+ * @returns {boolean} True if the value is in the array..
+ */
+function contains(val, array) {
+ return array.indexOf(val) > -1;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var options = context.options[0] ? assign({}, context.options[0]) : {};
+ options.beforeLineComment = options.beforeLineComment || false;
+ options.afterLineComment = options.afterLineComment || false;
+ options.beforeBlockComment = typeof options.beforeBlockComment !== "undefined" ? options.beforeBlockComment : true;
+ options.afterBlockComment = options.afterBlockComment || false;
+ options.allowBlockStart = options.allowBlockStart || false;
+ options.allowBlockEnd = options.allowBlockEnd || false;
+
+ /**
+ * Returns whether or not comments are not on lines starting with or ending with code
+ * @param {ASTNode} node The comment node to check.
+ * @returns {boolean} True if the comment is not alone.
+ */
+ function codeAroundComment(node) {
+
+ var lines = context.getSourceLines();
+
+ // Get the whole line and cut it off at the start of the comment
+ var startLine = lines[node.loc.start.line - 1];
+ var endLine = lines[node.loc.end.line - 1];
+
+ var preamble = startLine.slice(0, node.loc.start.column).trim();
+
+ // Also check after the comment
+ var postamble = endLine.slice(node.loc.end.column).trim();
+
+ // Should be false if there was only whitespace around the comment
+ return !!(preamble || postamble);
}
+ /**
+ * Returns whether or not comments are inside a node type or not.
+ * @param {ASTNode} node The Comment node.
+ * @param {ASTNode} parent The Comment parent node.
+ * @param {string} nodeType The parent type to check against.
+ * @returns {boolean} True if the comment is inside nodeType.
+ */
+ function isCommentInsideNodeType(node, parent, nodeType) {
+ return parent.type === nodeType ||
+ (parent.body && parent.body.type === nodeType) ||
+ (parent.consequent && parent.consequent.type === nodeType);
+ }
+
+ /**
+ * Returns whether or not comments are at the parent start or not.
+ * @param {ASTNode} node The Comment node.
+ * @param {string} nodeType The parent type to check against.
+ * @returns {boolean} True if the comment is at parent start.
+ */
+ function isCommentAtParentStart(node, nodeType) {
+ var ancestors = context.getAncestors();
+ var parent;
+
+ if (ancestors.length) {
+ parent = ancestors.pop();
+ }
+
+ return parent && isCommentInsideNodeType(node, parent, nodeType) &&
+ node.loc.start.line - parent.loc.start.line === 1;
+ }
+
+ /**
+ * Returns whether or not comments are at the parent end or not.
+ * @param {ASTNode} node The Comment node.
+ * @param {string} nodeType The parent type to check against.
+ * @returns {boolean} True if the comment is at parent end.
+ */
+ function isCommentAtParentEnd(node, nodeType) {
+ var ancestors = context.getAncestors();
+ var parent;
+
+ if (ancestors.length) {
+ parent = ancestors.pop();
+ }
+
+ return parent && isCommentInsideNodeType(node, parent, nodeType) &&
+ parent.loc.end.line - node.loc.end.line === 1;
+ }
+
+ /**
+ * Returns whether or not comments are at the block start or not.
+ * @param {ASTNode} node The Comment node.
+ * @returns {boolean} True if the comment is at block start.
+ */
+ function isCommentAtBlockStart(node) {
+ return isCommentAtParentStart(node, "ClassBody") || isCommentAtParentStart(node, "BlockStatement");
+ }
+
+ /**
+ * Returns whether or not comments are at the block end or not.
+ * @param {ASTNode} node The Comment node.
+ * @returns {boolean} True if the comment is at block end.
+ */
+ function isCommentAtBlockEnd(node) {
+ return isCommentAtParentEnd(node, "ClassBody") || isCommentAtParentEnd(node, "BlockStatement");
+ }
+
+ /**
+ * Returns whether or not comments are at the object start or not.
+ * @param {ASTNode} node The Comment node.
+ * @returns {boolean} True if the comment is at object start.
+ */
+ function isCommentAtObjectStart(node) {
+ return isCommentAtParentStart(node, "ObjectExpression") || isCommentAtParentStart(node, "ObjectPattern");
+ }
+
+ /**
+ * Returns whether or not comments are at the object end or not.
+ * @param {ASTNode} node The Comment node.
+ * @returns {boolean} True if the comment is at object end.
+ */
+ function isCommentAtObjectEnd(node) {
+ return isCommentAtParentEnd(node, "ObjectExpression") || isCommentAtParentEnd(node, "ObjectPattern");
+ }
+
+ /**
+ * Returns whether or not comments are at the array start or not.
+ * @param {ASTNode} node The Comment node.
+ * @returns {boolean} True if the comment is at array start.
+ */
+ function isCommentAtArrayStart(node) {
+ return isCommentAtParentStart(node, "ArrayExpression") || isCommentAtParentStart(node, "ArrayPattern");
+ }
+
+ /**
+ * Returns whether or not comments are at the array end or not.
+ * @param {ASTNode} node The Comment node.
+ * @returns {boolean} True if the comment is at array end.
+ */
+ function isCommentAtArrayEnd(node) {
+ return isCommentAtParentEnd(node, "ArrayExpression") || isCommentAtParentEnd(node, "ArrayPattern");
+ }
+
+ /**
+ * Checks if a comment node has lines around it (ignores inline comments)
+ * @param {ASTNode} node The Comment node.
+ * @param {Object} opts Options to determine the newline.
+ * @param {Boolean} opts.after Should have a newline after this line.
+ * @param {Boolean} opts.before Should have a newline before this line.
+ * @returns {void}
+ */
+ function checkForEmptyLine(node, opts) {
+
+ var lines = context.getSourceLines(),
+ numLines = lines.length + 1,
+ comments = context.getAllComments(),
+ commentLines = getCommentLineNums(comments),
+ emptyLines = getEmptyLineNums(lines),
+ commentAndEmptyLines = commentLines.concat(emptyLines);
+
+ var after = opts.after,
+ before = opts.before;
+
+ var prevLineNum = node.loc.start.line - 1,
+ nextLineNum = node.loc.end.line + 1,
+ commentIsNotAlone = codeAroundComment(node);
+
+ var blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node),
+ blockEndAllowed = options.allowBlockEnd && isCommentAtBlockEnd(node),
+ objectStartAllowed = options.allowObjectStart && isCommentAtObjectStart(node),
+ objectEndAllowed = options.allowObjectEnd && isCommentAtObjectEnd(node),
+ arrayStartAllowed = options.allowArrayStart && isCommentAtArrayStart(node),
+ arrayEndAllowed = options.allowArrayEnd && isCommentAtArrayEnd(node);
+
+ var exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed;
+ var exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed;
+
+ // ignore top of the file and bottom of the file
+ if (prevLineNum < 1) {
+ before = false;
+ }
+ if (nextLineNum >= numLines) {
+ after = false;
+ }
+
+ // we ignore all inline comments
+ if (commentIsNotAlone) {
+ return;
+ }
+
+ // check for newline before
+ if (!exceptionStartAllowed && before && !contains(prevLineNum, commentAndEmptyLines)) {
+ context.report(node, "Expected line before comment.");
+ }
+
+ // check for newline after
+ if (!exceptionEndAllowed && after && !contains(nextLineNum, commentAndEmptyLines)) {
+ context.report(node, "Expected line after comment.");
+ }
+
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+
+ "LineComment": function(node) {
+ if (options.beforeLineComment || options.afterLineComment) {
+ checkForEmptyLine(node, {
+ after: options.afterLineComment,
+ before: options.beforeLineComment
+ });
+ }
+ },
+
+ "BlockComment": function(node) {
+ if (options.beforeBlockComment || options.afterBlockComment) {
+ checkForEmptyLine(node, {
+ after: options.afterBlockComment,
+ before: options.beforeBlockComment
+ });
+ }
+ }
+
+ };
};
-},{}],158:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "beforeBlockComment": {
+ "type": "boolean"
+ },
+ "afterBlockComment": {
+ "type": "boolean"
+ },
+ "beforeLineComment": {
+ "type": "boolean"
+ },
+ "afterLineComment": {
+ "type": "boolean"
+ },
+ "allowBlockStart": {
+ "type": "boolean"
+ },
+ "allowBlockEnd": {
+ "type": "boolean"
+ },
+ "allowObjectStart": {
+ "type": "boolean"
+ },
+ "allowObjectEnd": {
+ "type": "boolean"
+ },
+ "allowArrayStart": {
+ "type": "boolean"
+ },
+ "allowArrayEnd": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"object-assign":108}],158:[function(require,module,exports){
/**
* @fileoverview A rule to set the maximum depth block can be nested in a function.
* @author Ian Christian Myers
* @copyright 2013 Ian Christian Myers. All rights reserved.
*/
@@ -20830,27 +28533,48 @@
//--------------------------------------------------------------------------
var functionStack = [],
maxDepth = context.options[0] || 4;
+ /**
+ * When parsing a new function, store it in our function stack
+ * @returns {void}
+ * @private
+ */
function startFunction() {
functionStack.push(0);
}
+ /**
+ * When parsing is done then pop out the reference
+ * @returns {void}
+ * @private
+ */
function endFunction() {
functionStack.pop();
}
+ /**
+ * Save the block and Evaluate the node
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function pushBlock(node) {
var len = ++functionStack[functionStack.length - 1];
if (len > maxDepth) {
context.report(node, "Blocks are nested too deeply ({{depth}}).",
{ depth: len });
}
}
+ /**
+ * Pop the saved block
+ * @returns {void}
+ * @private
+ */
function popBlock() {
functionStack[functionStack.length - 1]--;
}
//--------------------------------------------------------------------------
@@ -20893,10 +28617,16 @@
"Program:exit": endFunction
};
};
+module.exports.schema = [
+ {
+ "type": "integer"
+ }
+];
+
},{}],159:[function(require,module,exports){
/**
* @fileoverview Rule to check for max length on a line.
* @author Matt DuVall <http://www.mattduvall.com>
* @copyright 2013 Matt DuVall. All rights reserved.
@@ -20907,10 +28637,16 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ // takes some ideas from http://tools.ietf.org/html/rfc3986#appendix-B, however:
+ // - They're matching an entire string that we know is a URI
+ // - We're matching part of a string where we think there *might* be a URL
+ // - We're only concerned about URLs, as picking out any URI would cause too many false positives
+ // - We don't care about matching the entire URL, any small segment is fine
+ var URL_REGEXP = /[^:/?#]:\/\/[^?#]/;
/**
* Creates a string that is made up of repeating a given string a certain
* number of times. This uses exponentiation of squares to achieve significant
* performance gains over the more traditional implementation of such
@@ -20928,27 +28664,95 @@
}
}
return result;
}
- var tabWidth = context.options[1];
-
- var maxLength = context.options[0],
+ var maxLength = context.options[0] || 80,
+ tabWidth = context.options[1] || 4,
+ ignoreOptions = context.options[2] || {},
+ ignorePattern = ignoreOptions.ignorePattern || null,
+ ignoreComments = ignoreOptions.ignoreComments || false,
+ ignoreUrls = ignoreOptions.ignoreUrls || false,
tabString = stringRepeat(" ", tabWidth);
+ if (ignorePattern) {
+ ignorePattern = new RegExp(ignorePattern);
+ }
+
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
+
+ /**
+ * Tells if a given comment is trailing: it starts on the current line and
+ * extends to or past the end of the current line.
+ * @param {string} line The source line we want to check for a trailing comment on
+ * @param {number} lineNumber The one-indexed line number for line
+ * @param {ASTNode} comment The comment to inspect
+ * @returns {boolean} If the comment is trailing on the given line
+ */
+ function isTrailingComment(line, lineNumber, comment) {
+ return comment &&
+ (comment.loc.start.line <= lineNumber && lineNumber <= comment.loc.end.line) &&
+ (comment.loc.end.line > lineNumber || comment.loc.end.column === line.length);
+ }
+
+ /**
+ * Gets the line after the comment and any remaining trailing whitespace is
+ * stripped.
+ * @param {string} line The source line with a trailing comment
+ * @param {number} lineNumber The one-indexed line number this is on
+ * @param {ASTNode} comment The comment to remove
+ * @returns {string} Line without comment and trailing whitepace
+ */
+ function stripTrailingComment(line, lineNumber, comment) {
+ if (comment.loc.start.line < lineNumber) {
+ // this entire line is a comment
+ return "";
+ } else {
+ // loc.column is zero-indexed
+ return line.slice(0, comment.loc.start.column).replace(/\s+$/, "");
+ }
+ }
+
+ /**
+ * Check the program for max length
+ * @param {ASTNode} node Node to examine
+ * @returns {void}
+ * @private
+ */
function checkProgramForMaxLength(node) {
- var lines = context.getSourceLines();
+ // split (honors line-ending)
+ var lines = context.getSourceLines(),
+ // list of comments to ignore
+ comments = ignoreComments ? context.getAllComments() : [],
+ // we iterate over comments in parallel with the lines
+ commentsIndex = 0;
- // Replace the tabs
- // Split (honors line-ending)
- // Iterate
lines.forEach(function(line, i) {
+ // i is zero-indexed, line numbers are one-indexed
+ var lineNumber = i + 1;
+ // we can short-circuit the comment checks if we're already out of comments to check
+ if (commentsIndex < comments.length) {
+ // iterate over comments until we find one past the current line
+ do {
+ var comment = comments[++commentsIndex];
+ } while (comment && comment.loc.start.line <= lineNumber);
+ // and step back by one
+ comment = comments[--commentsIndex];
+ if (isTrailingComment(line, lineNumber, comment)) {
+ line = stripTrailingComment(line, lineNumber, comment);
+ }
+ }
+ if (ignorePattern && ignorePattern.test(line) ||
+ ignoreUrls && URL_REGEXP.test(line)) {
+ // ignore this line
+ return;
+ }
+ // replace the tabs
if (line.replace(/\t/g, tabString).length > maxLength) {
- context.report(node, { line: i + 1, col: 1 }, "Line " + (i + 1) + " exceeds the maximum line length of " + maxLength + ".");
+ context.report(node, { line: lineNumber, column: 0 }, "Line " + (i + 1) + " exceeds the maximum line length of " + maxLength + ".");
}
});
}
@@ -20960,10 +28764,36 @@
"Program": checkProgramForMaxLength
};
};
+module.exports.schema = [
+ {
+ "type": "integer",
+ "minimum": 0
+ },
+ {
+ "type": "integer",
+ "minimum": 0
+ },
+ {
+ "type": "object",
+ "properties": {
+ "ignorePattern": {
+ "type": "string"
+ },
+ "ignoreComments": {
+ "type": "boolean"
+ },
+ "ignoreUrls": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
},{}],160:[function(require,module,exports){
/**
* @fileoverview Rule to enforce a maximum number of nested callbacks.
* @author Ian Christian Myers
* @copyright 2013 Ian Christian Myers. All rights reserved.
@@ -20979,11 +28809,11 @@
//--------------------------------------------------------------------------
// Constants
//--------------------------------------------------------------------------
- var THRESHOLD = context.options[0];
+ var THRESHOLD = context.options[0] || 10;
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
@@ -21029,10 +28859,16 @@
"FunctionExpression:exit": popStack
};
};
+module.exports.schema = [
+ {
+ "type": "integer"
+ }
+];
+
},{}],161:[function(require,module,exports){
/**
* @fileoverview Rule to flag when a function has too many parameters
* @author Ilya Volodin
* @copyright 2014 Nicholas C. Zakas. All rights reserved.
@@ -21070,10 +28906,16 @@
"FunctionExpression": checkFunction
};
};
+module.exports.schema = [
+ {
+ "type": "integer"
+ }
+];
+
},{}],162:[function(require,module,exports){
/**
* @fileoverview A rule to set the maximum number of statements in a function.
* @author Ian Christian Myers
* @copyright 2013 Ian Christian Myers. All rights reserved.
@@ -21092,23 +28934,40 @@
//--------------------------------------------------------------------------
var functionStack = [],
maxStatements = context.options[0] || 10;
+ /**
+ * When parsing a new function, store it in our function stack
+ * @returns {void}
+ * @private
+ */
function startFunction() {
functionStack.push(0);
}
+ /**
+ * Evaluate the node at the end of function
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function endFunction(node) {
var count = functionStack.pop();
if (count > maxStatements) {
context.report(node, "This function has too many statements ({{count}}). Maximum allowed is {{max}}.",
{ count: count, max: maxStatements });
}
}
+ /**
+ * Increment the count of the functions
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function countStatements(node) {
functionStack[functionStack.length - 1] += node.body.length;
}
//--------------------------------------------------------------------------
@@ -21127,40 +28986,58 @@
"ArrowFunctionExpression:exit": endFunction
};
};
+module.exports.schema = [
+ {
+ "type": "integer"
+ }
+];
+
},{}],163:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of constructors without capital letters
* @author Nicholas C. Zakas
* @copyright 2014 Jordan Harband. All rights reserved.
* @copyright 2013-2014 Nicholas C. Zakas. All rights reserved.
*/
"use strict";
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var assign = require("object-assign");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
var CAPS_ALLOWED = [
- "Object",
+ "Array",
+ "Boolean",
+ "Date",
+ "Error",
"Function",
"Number",
+ "Object",
+ "RegExp",
"String",
- "Boolean",
- "Date",
- "Array",
- "Symbol",
- "RegExp"
+ "Symbol"
];
/**
* Ensure that if the key is provided, it must be an array.
* @param {Object} obj Object to check with `key`.
* @param {string} key Object key to check on `obj`.
* @param {*} fallback If obj[key] is not present, this will be returned.
* @returns {string[]} Returns obj[key] if it's an Array, otherwise `fallback`
*/
function checkArray(obj, key, fallback) {
+ /* istanbul ignore if */
if (Object.prototype.hasOwnProperty.call(obj, key) && !Array.isArray(obj[key])) {
throw new TypeError(key + ", if provided, must be an Array");
}
return obj[key] || fallback;
}
@@ -21195,13 +29072,14 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var config = context.options[0] || {};
- config.newIsCap = config.newIsCap === false ? false : true;
- config.capIsNew = config.capIsNew === false ? false : true;
+ var config = context.options[0] ? assign({}, context.options[0]) : {};
+ config.newIsCap = config.newIsCap !== false;
+ config.capIsNew = config.capIsNew !== false;
+ var skipProperties = config.properties === false;
var newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {});
var capIsNewExceptions = calculateCapIsNewExceptions(config);
@@ -21263,21 +29141,39 @@
* @param {ASTNode} node CallExpression node
* @param {string} calleeName Capitalized callee name from a CallExpression
* @returns {Boolean} Returns true if the callee may be capitalized
*/
function isCapAllowed(allowedMap, node, calleeName) {
- if (allowedMap[calleeName]) {
+ if (allowedMap[calleeName] || allowedMap[context.getSource(node.callee)]) {
return true;
}
+
if (calleeName === "UTC" && node.callee.type === "MemberExpression") {
// allow if callee is Date.UTC
return node.callee.object.type === "Identifier" &&
- node.callee.object.name === "Date";
+ node.callee.object.name === "Date";
}
- return false;
+
+ return skipProperties && node.callee.type === "MemberExpression";
}
+ /**
+ * Reports the given message for the given node. The location will be the start of the property or the callee.
+ * @param {ASTNode} node CallExpression or NewExpression node.
+ * @param {string} message The message to report.
+ * @returns {void}
+ */
+ function report(node, message) {
+ var callee = node.callee;
+
+ if (callee.type === "MemberExpression") {
+ callee = callee.property;
+ }
+
+ context.report(node, callee.loc.start, message);
+ }
+
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
if (config.newIsCap) {
@@ -21286,11 +29182,11 @@
var constructorName = extractNameFromExpression(node);
if (constructorName) {
var capitalization = getCap(constructorName);
var isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName);
if (!isAllowed) {
- context.report(node, "A constructor name should not start with a lowercase letter.");
+ report(node, "A constructor name should not start with a lowercase letter.");
}
}
};
}
@@ -21300,20 +29196,50 @@
var calleeName = extractNameFromExpression(node);
if (calleeName) {
var capitalization = getCap(calleeName);
var isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName);
if (!isAllowed) {
- context.report(node, "A function with a name starting with an uppercase letter should only be used as a constructor.");
+ report(node, "A function with a name starting with an uppercase letter should only be used as a constructor.");
}
}
};
}
return listeners;
};
-},{}],164:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "newIsCap": {
+ "type": "boolean"
+ },
+ "capIsNew": {
+ "type": "boolean"
+ },
+ "newIsCapExceptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "capIsNewExceptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "properties": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"object-assign":108}],164:[function(require,module,exports){
/**
* @fileoverview Rule to flag when using constructor without parentheses
* @author Ilya Volodin
*/
@@ -21338,67 +29264,345 @@
}
};
};
+module.exports.schema = [];
+
},{}],165:[function(require,module,exports){
/**
+ * @fileoverview Rule to check empty newline after "var" statement
+ * @author Gopal Venkatesan
+ * @copyright 2015 Gopal Venkatesan. All rights reserved.
+ * @copyright 2015 Casey Visco. All rights reserved.
+ * @copyright 2015 Ian VanSchooten. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var ALWAYS_MESSAGE = "Expected blank line after variable declarations.",
+ NEVER_MESSAGE = "Unexpected blank line after variable declarations.";
+
+ // Default `mode` to "always". This means that invalid options will also
+ // be treated as "always" and the only special case is "never"
+ var mode = context.options[0] === "never" ? "never" : "always";
+
+ // Cache starting and ending line numbers of comments for faster lookup
+ var commentEndLine = context.getAllComments().reduce(function(result, token) {
+ result[token.loc.start.line] = token.loc.end.line;
+ return result;
+ }, {});
+
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Determine if provided keyword is a variable declaration
+ * @private
+ * @param {string} keyword - keyword to test
+ * @returns {boolean} True if `keyword` is a type of var
+ */
+ function isVar(keyword) {
+ return keyword === "var" || keyword === "let" || keyword === "const";
+ }
+
+ /**
+ * Determine if provided keyword is a variant of for specifiers
+ * @private
+ * @param {string} keyword - keyword to test
+ * @returns {boolean} True if `keyword` is a variant of for specifier
+ */
+ function isForTypeSpecifier(keyword) {
+ return keyword === "ForStatement" || keyword === "ForInStatement" || keyword === "ForOfStatement";
+ }
+
+ /**
+ * Determine if provided keyword is an export specifiers
+ * @private
+ * @param {string} nodeType - nodeType to test
+ * @returns {boolean} True if `nodeType` is an export specifier
+ */
+ function isExportSpecifier(nodeType) {
+ return nodeType === "ExportNamedDeclaration" || nodeType === "ExportSpecifier" ||
+ nodeType === "ExportDefaultDeclaration" || nodeType === "ExportAllDeclaration";
+ }
+
+ /**
+ * Determine if provided nodeType is a function specifier
+ * @private
+ * @param {string} nodeType - nodeType to test
+ * @returns {boolean} True if `nodeType` is a function specifier
+ */
+ function isFunctionSpecifier(nodeType) {
+ return nodeType === "FunctionDeclaration" || nodeType === "FunctionExpression" ||
+ nodeType === "ArrowFunctionExpression";
+ }
+
+ /**
+ * Determine if provided node is the last of his parent
+ * @private
+ * @param {ASTNode} node - node to test
+ * @returns {boolean} True if `node` is last of his parent
+ */
+ function isLastNode(node) {
+ return node.parent.body[node.parent.body.length - 1] === node;
+ }
+
+ /**
+ * Determine if a token starts more than one line after a comment ends
+ * @param {token} token The token being checked
+ * @param {integer} commentStartLine The line number on which the comment starts
+ * @returns {boolean} True if `token` does not start immediately after a comment
+ */
+ function hasBlankLineAfterComment(token, commentStartLine) {
+ var commentEnd = commentEndLine[commentStartLine];
+ // If there's another comment, repeat check for blank line
+ if (commentEndLine[commentEnd + 1]) {
+ return hasBlankLineAfterComment(token, commentEnd + 1);
+ }
+ return (token.loc.start.line > commentEndLine[commentStartLine] + 1);
+ }
+
+ /**
+ * Checks that a blank line exists after a variable declaration when mode is
+ * set to "always", or checks that there is no blank line when mode is set
+ * to "never"
+ * @private
+ * @param {ASTNode} node - `VariableDeclaration` node to test
+ * @returns {void}
+ */
+ function checkForBlankLine(node) {
+ var lastToken = context.getLastToken(node),
+ nextToken = context.getTokenAfter(node),
+ nextLineNum = lastToken.loc.end.line + 1,
+ noNextLineToken,
+ hasNextLineComment;
+
+ // Ignore if there is no following statement
+ if (!nextToken) {
+ return;
+ }
+
+ // Ignore if parent of node is a for variant
+ if (isForTypeSpecifier(node.parent.type)) {
+ return;
+ }
+
+ // Ignore if parent of node is an export specifier
+ if (isExportSpecifier(node.parent.type)) {
+ return;
+ }
+
+ // Some coding styles use multiple `var` statements, so do nothing if
+ // the next token is a `var` statement.
+ if (nextToken.type === "Keyword" && isVar(nextToken.value)) {
+ return;
+ }
+
+ // Ignore if it is last statement in a function
+ if (node.parent.parent && isFunctionSpecifier(node.parent.parent.type) && isLastNode(node)) {
+ return;
+ }
+
+ // Next statement is not a `var`...
+ noNextLineToken = nextToken.loc.start.line > nextLineNum;
+ hasNextLineComment = (typeof commentEndLine[nextLineNum] !== "undefined");
+
+ if (mode === "never" && noNextLineToken && !hasNextLineComment) {
+ context.report(node, NEVER_MESSAGE, { identifier: node.name });
+ }
+
+ // Token on the next line, or comment without blank line
+ if (
+ mode === "always" && (
+ !noNextLineToken ||
+ hasNextLineComment && !hasBlankLineAfterComment(nextToken, nextLineNum)
+ )
+ ) {
+ context.report(node, ALWAYS_MESSAGE, { identifier: node.name });
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ "VariableDeclaration": checkForBlankLine
+ };
+
+};
+
+module.exports.schema = [
+ {
+ "enum": ["never", "always"]
+ }
+];
+
+},{}],166:[function(require,module,exports){
+/**
* @fileoverview Rule to flag use of alert, confirm, prompt
* @author Nicholas C. Zakas
+ * @copyright 2015 Mathias Schreck
+ * @copyright 2013 Nicholas C. Zakas
*/
"use strict";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
-function matchProhibited(name) {
- return name.match(/^(alert|confirm|prompt)$/);
+/**
+ * Checks if the given name is a prohibited identifier.
+ * @param {string} name The name to check
+ * @returns {boolean} Whether or not the name is prohibited.
+ */
+function isProhibitedIdentifier(name) {
+ return /^(alert|confirm|prompt)$/.test(name);
}
-function report(context, node, result) {
- context.report(node, "Unexpected {{name}}.", { name: result[1] });
+/**
+ * Reports the given node and identifier name.
+ * @param {RuleContext} context The ESLint rule context.
+ * @param {ASTNode} node The node to report on.
+ * @param {string} identifierName The name of the identifier.
+ * @returns {void}
+ */
+function report(context, node, identifierName) {
+ context.report(node, "Unexpected {{name}}.", { name: identifierName });
}
+/**
+ * Returns the property name of a MemberExpression.
+ * @param {ASTNode} memberExpressionNode The MemberExpression node.
+ * @returns {string|undefined} Returns the property name if available, undefined else.
+ */
+function getPropertyName(memberExpressionNode) {
+ if (memberExpressionNode.computed) {
+ if (memberExpressionNode.property.type === "Literal") {
+ return memberExpressionNode.property.value;
+ }
+ } else {
+ return memberExpressionNode.property.name;
+ }
+}
+/**
+ * Finds the escope reference in the given scope.
+ * @param {Object} scope The scope to search.
+ * @param {ASTNode} node The identifier node.
+ * @returns {Reference|undefined} Returns the found reference or undefined if none were found.
+ */
+function findReference(scope, node) {
+ var references = scope.references.filter(function(reference) {
+ return reference.identifier.range[0] === node.range[0] &&
+ reference.identifier.range[1] === node.range[1];
+ });
+
+ if (references.length === 1) {
+ return references[0];
+ }
+}
+
+/**
+ * Checks if the given identifier name is shadowed in the given global scope.
+ * @param {Object} globalScope The global scope.
+ * @param {string} identifierName The identifier name to check
+ * @returns {boolean} Whether or not the name is shadowed globally.
+ */
+function isGloballyShadowed(globalScope, identifierName) {
+ var variable = globalScope.set.get(identifierName);
+ return Boolean(variable && variable.defs.length > 0);
+}
+
+/**
+ * Checks if the given identifier node is shadowed in the given scope.
+ * @param {Object} scope The current scope.
+ * @param {Object} globalScope The global scope.
+ * @param {string} node The identifier node to check
+ * @returns {boolean} Whether or not the name is shadowed.
+ */
+function isShadowed(scope, globalScope, node) {
+ var reference = findReference(scope, node),
+ identifierName = node.name;
+
+ if (reference) {
+ if (reference.resolved || isGloballyShadowed(globalScope, identifierName)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Checks if the given identifier node is a ThisExpression in the global scope or the global window property.
+ * @param {Object} scope The current scope.
+ * @param {Object} globalScope The global scope.
+ * @param {string} node The identifier node to check
+ * @returns {boolean} Whether or not the node is a reference to the global object.
+ */
+function isGlobalThisReferenceOrGlobalWindow(scope, globalScope, node) {
+ if (scope.type === "global" && node.type === "ThisExpression") {
+ return true;
+ } else if (node.name === "window") {
+ return !isShadowed(scope, globalScope, node);
+ }
+
+ return false;
+}
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var globalScope;
return {
+ "Program": function() {
+ globalScope = context.getScope();
+ },
+
"CallExpression": function(node) {
+ var callee = node.callee,
+ identifierName,
+ currentScope = context.getScope();
- var result;
-
// without window.
- if (node.callee.type === "Identifier") {
+ if (callee.type === "Identifier") {
+ identifierName = callee.name;
- result = matchProhibited(node.callee.name);
-
- if (result) {
- report(context, node, result);
+ if (!isShadowed(currentScope, globalScope, callee) && isProhibitedIdentifier(callee.name)) {
+ report(context, node, identifierName);
}
- } else if (node.callee.type === "MemberExpression" && node.callee.property.type === "Identifier") {
+ } else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, globalScope, callee.object)) {
+ identifierName = getPropertyName(callee);
- result = matchProhibited(node.callee.property.name);
-
- if (result && node.callee.object.name === "window") {
- report(context, node, result);
+ if (isProhibitedIdentifier(identifierName)) {
+ report(context, node, identifierName);
}
-
}
}
};
};
-},{}],166:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],167:[function(require,module,exports){
/**
* @fileoverview Disallow construction of dense arrays using the Array constructor
* @author Matt DuVall <http://www.mattduvall.com/>
*/
@@ -21408,10 +29612,16 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ /**
+ * Disallow construction of dense arrays using the Array constructor
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function check(node) {
if (
node.arguments.length !== 1 &&
node.callee.type === "Identifier" &&
node.callee.name === "Array"
@@ -21425,12 +29635,104 @@
"NewExpression": check
};
};
-},{}],167:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],168:[function(require,module,exports){
/**
+ * @fileoverview A rule to warn against using arrow functions in conditions.
+ * @author Jxck <https://github.com/Jxck>
+ * @copyright 2015 Luke Karrys. All rights reserved.
+ * The MIT License (MIT)
+
+ * Copyright (c) 2015 Jxck
+
+ * 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 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.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether or not a node is an arrow function expression.
+ * @param {ASTNode} node - node to test
+ * @returns {boolean} `true` if the node is an arrow function expression.
+ */
+function isArrowFunction(node) {
+ return node.test && node.test.type === "ArrowFunctionExpression";
+}
+
+/**
+ * Checks whether or not a node is a conditional expression.
+ * @param {ASTNode} node - node to test
+ * @returns {boolean} `true` if the node is a conditional expression.
+ */
+function isConditional(node) {
+ return node.body && node.body.type === "ConditionalExpression";
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ /**
+ * Reports if a conditional statement is an arrow function.
+ * @param {ASTNode} node - A node to check and report.
+ * @returns {void}
+ */
+ function checkCondition(node) {
+ if (isArrowFunction(node)) {
+ context.report(node, "Arrow function `=>` used inside {{statementType}} instead of comparison operator.", {statementType: node.type});
+ }
+ }
+
+ /**
+ * Reports if an arrow function contains an ambiguous conditional.
+ * @param {ASTNode} node - A node to check and report.
+ * @returns {void}
+ */
+ function checkArrowFunc(node) {
+ if (isConditional(node)) {
+ context.report(node, "Arrow function used ambiguously with a conditional expression.");
+ }
+ }
+
+ return {
+ "IfStatement": checkCondition,
+ "WhileStatement": checkCondition,
+ "ForStatement": checkCondition,
+ "ConditionalExpression": checkCondition,
+ "ArrowFunctionExpression": checkArrowFunc
+ };
+};
+
+module.exports.schema = [];
+
+},{}],169:[function(require,module,exports){
+/**
* @fileoverview Rule to flag bitwise identifiers
* @author Nicholas C. Zakas
*/
"use strict";
@@ -21482,11 +29784,13 @@
"UnaryExpression": checkNodeForBitwiseOperator
};
};
-},{}],168:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],170:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of arguments.callee and arguments.caller.
* @author Nicholas C. Zakas
*/
@@ -21511,42 +29815,93 @@
}
};
};
-},{}],169:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],171:[function(require,module,exports){
/**
+ * @fileoverview Rule to flag use of an lexical declarations inside a case clause
+ * @author Erik Arvidsson
+ * @copyright 2015 Erik Arvidsson. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ /**
+ * Checks whether or not a node is a lexical declaration.
+ * @param {ASTNode} node A direct child statement of a switch case.
+ * @returns {boolean} Whether or not the node is a lexical declaration.
+ */
+ function isLexicalDeclaration(node) {
+ switch (node.type) {
+ case "FunctionDeclaration":
+ case "ClassDeclaration":
+ return true;
+ case "VariableDeclaration":
+ return node.kind !== "var";
+ default:
+ return false;
+ }
+ }
+
+ return {
+ "SwitchCase": function(node) {
+ for (var i = 0; i < node.consequent.length; i++) {
+ var statement = node.consequent[i];
+ if (isLexicalDeclaration(statement)) {
+ context.report({
+ node: node,
+ message: "Unexpected lexical declaration in case block."
+ });
+ }
+ }
+ }
+ };
+
+};
+
+module.exports.schema = [];
+
+},{}],172:[function(require,module,exports){
+/**
* @fileoverview Rule to flag variable leak in CatchClauses in IE 8 and earlier
* @author Ian Christian Myers
*/
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
+ /**
+ * Check if the parameters are been shadowed
+ * @param {object} scope current scope
+ * @param {string} name parameter name
+ * @returns {boolean} True is its been shadowed
+ */
function paramIsShadowing(scope, name) {
- var found = scope.variables.some(function(variable) {
- return variable.name === name;
- });
-
- if (found) {
- return true;
- }
-
- if (scope.upper) {
- return paramIsShadowing(scope.upper, name);
- }
-
- return false;
+ return astUtils.getVariableByName(scope, name) !== null;
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
@@ -21554,65 +29909,78 @@
return {
"CatchClause": function(node) {
var scope = context.getScope();
+ // When blockBindings is enabled, CatchClause creates its own scope
+ // so start from one upper scope to exclude the current node
+ if (scope.block === node) {
+ scope = scope.upper;
+ }
+
if (paramIsShadowing(scope, node.param.name)) {
context.report(node, "Value of '{{name}}' may be overwritten in IE 8 and earlier.",
{ name: node.param.name });
}
}
};
};
-},{}],170:[function(require,module,exports){
+module.exports.schema = [];
+
+},{"../ast-utils":113}],173:[function(require,module,exports){
/**
- * @fileoverview Rule to flag trailing commas in object literals.
- * @author Ian Christian Myers
+ * @fileoverview A rule to disallow modifying variables of class declarations
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- //-------------------------------------------------------------------------
- // Helpers
- //-------------------------------------------------------------------------
+ /**
+ * Finds and reports references that are non initializer and writable.
+ * @param {Variable} variable - A variable to check.
+ * @returns {void}
+ */
+ function checkVariable(variable) {
+ astUtils.getModifyingReferences(variable.references).forEach(function(reference) {
+ context.report(
+ reference.identifier,
+ "`{{name}}` is a class.",
+ {name: reference.identifier.name});
- function checkForTrailingComma(node) {
- var items = node.properties || node.elements,
- length = items.length,
- lastItem, penultimateToken;
+ });
+ }
- if (length) {
- lastItem = items[length - 1];
- if (lastItem) {
- penultimateToken = context.getLastToken(node, 1);
- if (penultimateToken.value === ",") {
- context.report(lastItem, penultimateToken.loc.start, "Trailing comma.");
- }
- }
- }
+ /**
+ * Finds and reports references that are non initializer and writable.
+ * @param {ASTNode} node - A ClassDeclaration/ClassExpression node to check.
+ * @returns {void}
+ */
+ function checkForClass(node) {
+ context.getDeclaredVariables(node).forEach(checkVariable);
}
- //--------------------------------------------------------------------------
- // Public API
- //--------------------------------------------------------------------------
-
return {
- "ObjectExpression": checkForTrailingComma,
- "ArrayExpression": checkForTrailingComma
+ "ClassDeclaration": checkForClass,
+ "ClassExpression": checkForClass
};
};
-},{}],171:[function(require,module,exports){
+module.exports.schema = [];
+
+},{"../ast-utils":113}],174:[function(require,module,exports){
/**
* @fileoverview Rule to flag assignment in a conditional statement's test expression
* @author Stephen Murray <spmurrayzzz>
*/
"use strict";
@@ -21649,15 +30017,15 @@
* @returns {?Object} The closest ancestor node that represents a conditional statement.
*/
function findConditionalAncestor(node) {
var currentAncestor = node;
- while ((currentAncestor = currentAncestor.parent)) {
+ do {
if (isConditionalTestExpression(currentAncestor)) {
return currentAncestor.parent;
}
- }
+ } while ((currentAncestor = currentAncestor.parent));
return null;
}
/**
@@ -21691,13 +30059,23 @@
* Check a conditional statement's test expression for top-level assignments that are not enclosed in parentheses.
* @param {!Object} node The node for the conditional statement.
* @returns {void}
*/
function testForAssign(node) {
- if (node.test && (node.test.type === "AssignmentExpression") && !isParenthesisedTwice(node.test)) {
+ if (node.test &&
+ (node.test.type === "AssignmentExpression") &&
+ (node.type === "ForStatement" ?
+ !isParenthesised(node.test) :
+ !isParenthesisedTwice(node.test)
+ )
+ ) {
// must match JSHint's error message
- context.report(node, "Expected a conditional expression and instead saw an assignment.");
+ context.report({
+ node: node,
+ loc: node.test.loc.start,
+ message: "Expected a conditional expression and instead saw an assignment."
+ });
}
}
/**
* Check whether an assignment expression is descended from a conditional statement's test expression.
@@ -21727,11 +30105,17 @@
"WhileStatement": testForAssign
};
};
-},{}],172:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["except-parens", "always"]
+ }
+];
+
+},{}],175:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of console object
* @author Nicholas C. Zakas
*/
@@ -21754,12 +30138,57 @@
}
};
};
-},{}],173:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],176:[function(require,module,exports){
/**
+ * @fileoverview A rule to disallow modifying variables that are declared using `const`
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ /**
+ * Finds and reports references that are non initializer and writable.
+ * @param {Variable} variable - A variable to check.
+ * @returns {void}
+ */
+ function checkVariable(variable) {
+ astUtils.getModifyingReferences(variable.references).forEach(function(reference) {
+ context.report(
+ reference.identifier,
+ "`{{name}}` is constant.",
+ {name: reference.identifier.name});
+ });
+ }
+
+ return {
+ "VariableDeclaration": function(node) {
+ if (node.kind === "const") {
+ context.getDeclaredVariables(node).forEach(checkVariable);
+ }
+ }
+ };
+
+};
+
+module.exports.schema = [];
+
+},{"../ast-utils":113}],177:[function(require,module,exports){
+/**
* @fileoverview Rule to flag use constant conditions
* @author Christian Schulz <http://rndm.de>
* @copyright 2014 Christian Schulz. All rights reserved.
*/
@@ -21793,11 +30222,11 @@
return isConstant(node.argument);
case "BinaryExpression":
case "LogicalExpression":
return isConstant(node.left) && isConstant(node.right);
case "AssignmentExpression":
- return isConstant(node.right);
+ return (node.operator === "=") && isConstant(node.right);
case "SequenceExpression":
return isConstant(node.expressions[node.expressions.length - 1]);
// no default
}
return false;
@@ -21827,12 +30256,39 @@
"ForStatement": checkConstantCondition
};
};
-},{}],174:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],178:[function(require,module,exports){
/**
+ * @fileoverview Rule to flag use of continue statement
+ * @author Borislav Zhivkov
+ * @copyright 2015 Borislav Zhivkov. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ return {
+ "ContinueStatement": function(node) {
+ context.report(node, "Unexpected use of continue statement");
+ }
+ };
+
+};
+
+module.exports.schema = [];
+
+},{}],179:[function(require,module,exports){
+/**
* @fileoverview Rule to forbid control charactes from regular expressions.
* @author Nicholas C. Zakas
*/
"use strict";
@@ -21841,10 +30297,16 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ /**
+ * Get the regex expression
+ * @param {ASTNode} node node to evaluate
+ * @returns {*} Regex if found else null
+ * @private
+ */
function getRegExp(node) {
if (node.value instanceof RegExp) {
return node.value;
} else if (typeof node.value === "string") {
@@ -21885,11 +30347,13 @@
}
};
};
-},{}],175:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],180:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of a debugger statement
* @author Nicholas C. Zakas
*/
@@ -21907,11 +30371,13 @@
}
};
};
-},{}],176:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],181:[function(require,module,exports){
/**
* @fileoverview Rule to flag when deleting variables
* @author Ilya Volodin
*/
@@ -21932,11 +30398,13 @@
}
};
};
-},{}],177:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],182:[function(require,module,exports){
/**
* @fileoverview Rule to check for ambiguous div operator in regexes
* @author Matt DuVall <http://www.mattduvall.com>
*/
@@ -21959,15 +30427,19 @@
}
};
};
-},{}],178:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],183:[function(require,module,exports){
/**
* @fileoverview Rule to flag duplicate arguments
* @author Jamund Ferguson
* @copyright 2015 Jamund Ferguson. All rights reserved.
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
@@ -21979,32 +30451,48 @@
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
+ * Checks whether or not a given definition is a parameter's.
+ * @param {escope.DefEntry} def - A definition to check.
+ * @returns {boolean} `true` if the definition is a parameter's.
+ */
+ function isParameter(def) {
+ return def.type === "Parameter";
+ }
+
+ /**
* Determines if a given node has duplicate parameters.
* @param {ASTNode} node The node to check.
* @returns {void}
* @private
*/
function checkParams(node) {
- var dups = {};
+ var variables = context.getDeclaredVariables(node);
+ var keyMap = Object.create(null);
- // loop through and find each duplicate param
- node.params.map(function(param) {
- return param.name;
- }).forEach(function(param, i, params) {
- var lastPos = params.lastIndexOf(param);
- if (i !== lastPos) {
- dups[param] = [i, lastPos];
+ for (var i = 0; i < variables.length; ++i) {
+ var variable = variables[i];
+
+ // TODO(nagashima): Remove this duplication check after https://github.com/estools/escope/pull/79
+ var key = "$" + variable.name; // to avoid __proto__.
+ if (!isParameter(variable.defs[0]) || keyMap[key]) {
+ continue;
}
- });
+ keyMap[key] = true;
- // log an error for each duplicate (not 2 for each)
- Object.keys(dups).forEach(function(currentParam) {
- context.report(node, "Duplicate param '{{key}}'.", { key: currentParam });
- });
+ // Checks and reports duplications.
+ var defs = variable.defs.filter(isParameter);
+ if (defs.length >= 2) {
+ context.report({
+ node: node,
+ message: "Duplicate param '{{name}}'.",
+ data: {name: variable.name}
+ });
+ }
+ }
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
@@ -22014,12 +30502,98 @@
"FunctionExpression": checkParams
};
};
-},{}],179:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],184:[function(require,module,exports){
/**
+ * @fileoverview A rule to disallow duplicate name in class members.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var stack = [];
+
+ /**
+ * Gets state of a given member name.
+ * @param {string} name - A name of a member.
+ * @param {boolean} isStatic - A flag which specifies that is a static member.
+ * @returns {object} A state of a given member name.
+ * - retv.init {boolean} A flag which shows the name is declared as normal member.
+ * - retv.get {boolean} A flag which shows the name is declared as getter.
+ * - retv.set {boolean} A flag which shows the name is declared as setter.
+ */
+ function getState(name, isStatic) {
+ var stateMap = stack[stack.length - 1];
+ var key = "$" + name; // to avoid "__proto__".
+
+ if (!stateMap[key]) {
+ stateMap[key] = {
+ nonStatic: {init: false, get: false, set: false},
+ static: {init: false, get: false, set: false}
+ };
+ }
+
+ return stateMap[key][isStatic ? "static" : "nonStatic"];
+ }
+
+ return {
+ // Initializes the stack of state of member declarations.
+ "Program": function() {
+ stack = [];
+ },
+
+ // Initializes state of member declarations for the class.
+ "ClassBody": function() {
+ stack.push(Object.create(null));
+ },
+
+ // Disposes the state for the class.
+ "ClassBody:exit": function() {
+ stack.pop();
+ },
+
+ // Reports the node if its name has been declared already.
+ "MethodDefinition": function(node) {
+ if (node.computed) {
+ return;
+ }
+
+ var name = node.key.name;
+ var state = getState(name, node.static);
+ var isDuplicate = false;
+ if (node.kind === "get") {
+ isDuplicate = (state.init || state.get);
+ state.get = true;
+ } else if (node.kind === "set") {
+ isDuplicate = (state.init || state.set);
+ state.set = true;
+ } else {
+ isDuplicate = (state.init || state.get || state.set);
+ state.init = true;
+ }
+
+ if (isDuplicate) {
+ context.report(node, "Duplicate name \"{{name}}\".", {name: name});
+ }
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{}],185:[function(require,module,exports){
+/**
* @fileoverview Rule to flag use of duplicate keys in an object.
* @author Ian Christian Myers
* @copyright 2013 Ian Christian Myers. All rights reserved.
* @copyright 2013 Nicholas C. Zakas. All rights reserved.
*/
@@ -22039,17 +30613,22 @@
// Object that will be a map of properties--safe because we will
// prefix all of the keys.
var nodeProps = Object.create(null);
node.properties.forEach(function(property) {
+
+ if (property.type !== "Property") {
+ return;
+ }
+
var keyName = property.key.name || property.key.value,
key = property.kind + "-" + keyName,
checkProperty = (!property.computed || property.key.type === "Literal");
if (checkProperty) {
if (nodeProps[key]) {
- context.report(node, "Duplicate key '{{key}}'.", { key: keyName });
+ context.report(node, property.loc.start, "Duplicate key '{{key}}'.", { key: keyName });
} else {
nodeProps[key] = true;
}
}
});
@@ -22057,12 +30636,49 @@
}
};
};
-},{}],180:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],186:[function(require,module,exports){
/**
+ * @fileoverview Rule to disallow a duplicate case label.
+ * @author Dieter Oberkofler
+ * @author Burak Yigit Kaya
+ * @copyright 2015 Dieter Oberkofler. All rights reserved.
+ * @copyright 2015 Burak Yigit Kaya. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ return {
+ "SwitchStatement": function(node) {
+ var mapping = {};
+
+ node.cases.forEach(function(switchCase) {
+ var key = context.getSource(switchCase.test);
+ if (mapping[key]) {
+ context.report(switchCase, "Duplicate case label.");
+ } else {
+ mapping[key] = switchCase;
+ }
+ });
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{}],187:[function(require,module,exports){
+/**
* @fileoverview Rule to flag `else` after a `return` in `if`
* @author Ian Christian Myers
*/
"use strict";
@@ -22140,53 +30756,74 @@
}
/**
* Check the consequent/body node to make sure it is not
* a ReturnStatement or an IfStatement that returns on both
- * code paths. If it is, display the context report.
+ * code paths.
*
* @param {Node} node The consequent or body node
* @param {Node} alternate The alternate node
- * @returns {void}
+ * @returns {boolean} `true` if it is a Return/If node that always returns.
*/
- function checkForReturnOrIf(node, alternate) {
- if (checkForReturn(node) || checkForIf(node)) {
- displayReport(alternate);
+ function checkForReturnOrIf(node) {
+ return checkForReturn(node) || checkForIf(node);
+ }
+
+
+ /**
+ * Check whether a node returns in every codepath.
+ * @param {Node} node The node to be checked
+ * @returns {boolean} `true` if it returns on every codepath.
+ */
+ function alwaysReturns(node) {
+ // If we have a BlockStatement, check each consequent body node.
+ if (node.type === "BlockStatement") {
+ return node.body.some(checkForReturnOrIf);
+ // If not a block statement, make sure the consequent isn't a ReturnStatement
+ // or an IfStatement with returns on both paths
+ } else {
+ return checkForReturnOrIf(node);
}
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
return {
- "IfStatement": function (node) {
- // Don't bother finding a ReturnStatement, if there's no `else`
- // or if the alternate is also an if (indicating an else if).
- if (hasElse(node)) {
- var consequent = node.consequent,
- alternate = node.alternate;
- // If we have a BlockStatement, check each consequent body node.
- if (consequent.type === "BlockStatement") {
- var body = consequent.body;
- body.forEach(function (bodyNode) {
- checkForReturnOrIf(bodyNode, alternate);
- });
- // If not a block statement, make sure the consequent isn't a ReturnStatement
- // or an IfStatement with returns on both paths
- } else {
- checkForReturnOrIf(consequent, alternate);
+ "IfStatement": function(node) {
+ var parent = context.getAncestors().pop(),
+ consequents,
+ alternate;
+
+ // Only "top-level" if statements are checked, meaning the first `if`
+ // in a `if-else-if-...` chain.
+ if (parent.type === "IfStatement" && parent.alternate === node) {
+ return;
+ }
+
+ for (consequents = []; node.type === "IfStatement"; node = node.alternate) {
+ if (!node.alternate) {
+ return;
}
+ consequents.push(node.consequent);
+ alternate = node.alternate;
}
+
+ if (consequents.every(alwaysReturns)) {
+ displayReport(alternate);
+ }
}
};
};
-},{}],181:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],188:[function(require,module,exports){
/**
* @fileoverview Rule to flag the use of empty character classes in regular expressions
* @author Ian Christian Myers
*/
@@ -22203,14 +30840,14 @@
2. `([^\\[]|\\.|\[([^\\\]]|\\.)+\])*`: regexp contents; 0 or more of the following
2.0. `[^\\[]`: any character that's not a `\` or a `[` (anything but escape sequences and character classes)
2.1. `\\.`: an escape sequence
2.2. `\[([^\\\]]|\\.)+\]`: a character class that isn't empty
3. `\/` the `/` that ends the regexp
-4. `[gimy]*`: optional regexp flags
+4. `[gimuy]*`: optional regexp flags
5. `$`: fix the match at the end of the string
*/
-var regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+\])*\/[gimy]*$/;
+var regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+\])*\/[gimuy]*$/;
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -22227,11 +30864,13 @@
};
};
-},{}],182:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],189:[function(require,module,exports){
/**
* @fileoverview Rule to flag when label is not used for a loop or switch
* @author Ilya Volodin
*/
@@ -22247,22 +30886,55 @@
"LabeledStatement": function(node) {
var type = node.body.type;
if (type !== "ForStatement" && type !== "WhileStatement" && type !== "DoWhileStatement" && type !== "SwitchStatement" && type !== "ForInStatement" && type !== "ForOfStatement") {
- context.report(node, "Unexpected label {{l}}", {l: node.label.name});
+ context.report(node, "Unexpected label \"{{l}}\"", {l: node.label.name});
}
}
};
};
-},{}],183:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],190:[function(require,module,exports){
/**
+ * @fileoverview Rule to disallow an empty pattern
+ * @author Alberto RodrÃguez
+ * @copyright 2015 Alberto RodrÃguez. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ return {
+ "ObjectPattern": function(node) {
+ if (node.properties.length === 0) {
+ context.report(node, "Unexpected empty object pattern.");
+ }
+ },
+ "ArrayPattern": function(node) {
+ if (node.elements.length === 0) {
+ context.report(node, "Unexpected empty array pattern.");
+ }
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{}],191:[function(require,module,exports){
+/**
* @fileoverview Rule to flag use of an empty block statement
* @author Nicholas C. Zakas
* @copyright Nicholas C. Zakas. All rights reserved.
+ * @copyright 2015 Dieter Oberkofler. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
@@ -22271,24 +30943,29 @@
module.exports = function(context) {
return {
"BlockStatement": function(node) {
- var ancestors = context.getAncestors(),
- parent = ancestors[ancestors.length - 1],
- parentType = parent.type,
- hasHandler = !!(parent.handler || (parent.handlers && parent.handlers.length)),
- isFinallyBlock = (parentType === "TryStatement") && (parent.finalizer === node);
+ var parent = node.parent,
+ parentType = parent.type;
- if (/Function|CatchClause/.test(parentType) ||
- (isFinallyBlock && !hasHandler)) {
+ // if the body is not empty, we can just return immediately
+ if (node.body.length !== 0) {
return;
}
- if (node.body.length === 0) {
- context.report(node, "Empty block statement.");
+ // a function is generally allowed to be empty
+ if (parentType === "FunctionDeclaration" || parentType === "FunctionExpression" || parentType === "ArrowFunctionExpression") {
+ return;
}
+
+ // any other block is only allowed to be empty, if it contains a comment
+ if (context.getComments(node).trailing.length > 0) {
+ return;
+ }
+
+ context.report(node, "Empty block statement.");
},
"SwitchStatement": function(node) {
if (typeof node.cases === "undefined" || node.cases.length === 0) {
@@ -22297,11 +30974,13 @@
}
};
};
-},{}],184:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],192:[function(require,module,exports){
/**
* @fileoverview Rule to flag comparisons to null without a type-checking
* operator.
* @author Ian Christian Myers
*/
@@ -22326,11 +31005,13 @@
}
};
};
-},{}],185:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],193:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of eval() statement
* @author Nicholas C. Zakas
* @copyright 2015 Mathias Schreck. All rights reserved.
* @copyright 2013 Nicholas C. Zakas. All rights reserved.
@@ -22352,54 +31033,52 @@
}
};
};
-},{}],186:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],194:[function(require,module,exports){
/**
* @fileoverview Rule to flag assignment of the exception parameter
* @author Stephen Murray <spmurrayzzz>
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var inCatch = false,
- exceptionName = null;
+ /**
+ * Finds and reports references that are non initializer and writable.
+ * @param {Variable} variable - A variable to check.
+ * @returns {void}
+ */
+ function checkVariable(variable) {
+ astUtils.getModifyingReferences(variable.references).forEach(function(reference) {
+ context.report(
+ reference.identifier,
+ "Do not assign to the exception parameter.");
+ });
+ }
return {
-
"CatchClause": function(node) {
- inCatch = true;
- exceptionName = node.param.name;
- },
-
- "CatchClause:exit": function() {
- inCatch = false;
- exceptionName = null;
- },
-
- "AssignmentExpression": function(node) {
-
- if (inCatch) {
-
- if (node.left.name === exceptionName) {
- context.report(node, "Do not assign to the exception parameter.");
- }
- }
+ context.getDeclaredVariables(node).forEach(checkVariable);
}
-
};
};
-},{}],187:[function(require,module,exports){
+module.exports.schema = [];
+
+},{"../ast-utils":113}],195:[function(require,module,exports){
/**
* @fileoverview Rule to flag adding properties to native object's prototypes.
* @author David Nelson
*/
@@ -22407,22 +31086,30 @@
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
-var BUILTINS = [
- "Object", "Function", "Array", "String", "Boolean", "Number", "Date",
- "RegExp", "Error", "EvalError", "RangeError", "ReferenceError",
- "SyntaxError", "TypeError", "URIError"
-];
+var globals = require("globals");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var config = context.options[0] || {};
+ var exceptions = config.exceptions || [];
+ var modifiedBuiltins = Object.keys(globals.builtin).filter(function(builtin) {
+ return builtin[0].toUpperCase() === builtin[0];
+ });
+
+ if (exceptions.length) {
+ modifiedBuiltins = modifiedBuiltins.filter(function(builtIn) {
+ return exceptions.indexOf(builtIn) === -1;
+ });
+ }
+
return {
// handle the Array.prototype.extra style case
"AssignmentExpression": function(node) {
var lhs = node.left, affectsProto;
@@ -22437,36 +31124,35 @@
if (!affectsProto) {
return;
}
- BUILTINS.forEach(function(builtin) {
+ modifiedBuiltins.forEach(function(builtin) {
if (lhs.object.object.name === builtin) {
context.report(node, builtin + " prototype is read only, properties should not be added.");
}
});
},
- // handle the Object.defineProperty(Array.prototype) case
+ // handle the Object.definePropert[y|ies](Array.prototype) case
"CallExpression": function(node) {
var callee = node.callee,
subject,
object;
- // only worry about Object.defineProperty
+ // only worry about Object.definePropert[y|ies]
if (callee.type === "MemberExpression" &&
callee.object.name === "Object" &&
- callee.property.name === "defineProperty") {
+ (callee.property.name === "defineProperty" || callee.property.name === "defineProperties")) {
// verify the object being added to is a native prototype
subject = node.arguments[0];
- object = subject.object;
-
+ object = subject && subject.object;
if (object &&
object.type === "Identifier" &&
- (BUILTINS.indexOf(object.name) > -1) &&
+ (modifiedBuiltins.indexOf(object.name) > -1) &&
subject.property.name === "prototype") {
context.report(node, object.name + " prototype is read only, properties should not be added.");
}
}
@@ -22474,15 +31160,32 @@
}
};
};
-},{}],188:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "uniqueItems": true
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"globals":100}],196:[function(require,module,exports){
/**
* @fileoverview Rule to flag unnecessary bind calls
* @author Bence Dányi <bence@danyi.me>
* @copyright 2014 Bence Dányi. All rights reserved.
+ * See LICENSE in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
@@ -22533,12 +31236,14 @@
found: 0
});
}
},
"CallExpression:exit": function(node) {
- var top = getTopScope();
- if (top.call === node && top.found === 0) {
+ var top = getTopScope(),
+ isArrowFunction = node.callee.type === "MemberExpression" && node.callee.object.type === "ArrowFunctionExpression";
+
+ if (top.call === node && (top.found === 0 || isArrowFunction)) {
context.report(node, "The function binding is unnecessary.");
scope.pop();
}
},
"ArrowFunctionExpression": incrementScopeDepth,
@@ -22555,11 +31260,13 @@
}
};
};
-},{}],189:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],197:[function(require,module,exports){
/**
* @fileoverview Rule to flag unnecessary double negation in Boolean contexts
* @author Brandon Mills
*/
@@ -22570,11 +31277,11 @@
//------------------------------------------------------------------------------
module.exports = function(context) {
return {
- "UnaryExpression": function (node) {
+ "UnaryExpression": function(node) {
var ancestors = context.getAncestors(),
parent = ancestors.pop(),
grandparent = ancestors.pop();
// Exit early if it's guaranteed not to match
@@ -22626,49 +31333,166 @@
}
};
};
-},{}],190:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],198:[function(require,module,exports){
/**
- * @fileoverview Disallow parenthesesisng higher precedence subexpressions.
+ * @fileoverview Disallow parenthesising higher precedence subexpressions.
* @author Michael Ficarra
* @copyright 2014 Michael Ficarra. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var ALL_NODES = context.options[0] !== "functions";
+
+ /**
+ * Determines if this rule should be enforced for a node given the current configuration.
+ * @param {ASTNode} node - The node to be checked.
+ * @returns {boolean} True if the rule should be enforced for this node.
+ * @private
+ */
+ function ruleApplies(node) {
+ return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
+ }
+
+ /**
+ * Determines if a node is surrounded by parentheses.
+ * @param {ASTNode} node - The node to be checked.
+ * @returns {boolean} True if the node is parenthesised.
+ * @private
+ */
function isParenthesised(node) {
var previousToken = context.getTokenBefore(node),
nextToken = context.getTokenAfter(node);
return previousToken && nextToken &&
previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
nextToken.value === ")" && nextToken.range[0] >= node.range[1];
}
+ /**
+ * Determines if a node is surrounded by parentheses twice.
+ * @param {ASTNode} node - The node to be checked.
+ * @returns {boolean} True if the node is doubly parenthesised.
+ * @private
+ */
function isParenthesisedTwice(node) {
var previousToken = context.getTokenBefore(node, 1),
nextToken = context.getTokenAfter(node, 1);
return isParenthesised(node) && previousToken && nextToken &&
previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
nextToken.value === ")" && nextToken.range[0] >= node.range[1];
}
+ /**
+ * Determines if a node is surrounded by (potentially) invalid parentheses.
+ * @param {ASTNode} node - The node to be checked.
+ * @returns {boolean} True if the node is incorrectly parenthesised.
+ * @private
+ */
+ function hasExcessParens(node) {
+ return ruleApplies(node) && isParenthesised(node);
+ }
+
+ /**
+ * Determines if a node that is expected to be parenthesised is surrounded by
+ * (potentially) invalid extra parentheses.
+ * @param {ASTNode} node - The node to be checked.
+ * @returns {boolean} True if the node is has an unexpected extra pair of parentheses.
+ * @private
+ */
+ function hasDoubleExcessParens(node) {
+ return ruleApplies(node) && isParenthesisedTwice(node);
+ }
+
+ /**
+ * Checks whether or not a given node is located at the head of ExpressionStatement.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} `true` if the node is located at the head of ExpressionStatement.
+ */
+ function isHeadOfExpressionStatement(node) {
+ var parent = node.parent;
+ while (parent) {
+ switch (parent.type) {
+ case "SequenceExpression":
+ if (parent.expressions[0] !== node || isParenthesised(node)) {
+ return false;
+ }
+ break;
+
+ case "UnaryExpression":
+ case "UpdateExpression":
+ if (parent.prefix || isParenthesised(node)) {
+ return false;
+ }
+ break;
+
+ case "BinaryExpression":
+ case "LogicalExpression":
+ if (parent.left !== node || isParenthesised(node)) {
+ return false;
+ }
+ break;
+
+ case "ConditionalExpression":
+ if (parent.test !== node || isParenthesised(node)) {
+ return false;
+ }
+ break;
+
+ case "CallExpression":
+ if (parent.callee !== node || isParenthesised(node)) {
+ return false;
+ }
+ break;
+
+ case "MemberExpression":
+ if (parent.object !== node || isParenthesised(node)) {
+ return false;
+ }
+ break;
+
+ case "ExpressionStatement":
+ return true;
+
+ default:
+ return false;
+ }
+
+ node = parent;
+ parent = parent.parent;
+ }
+
+ /* istanbul ignore next */
+ throw new Error("unreachable");
+ }
+
+ /**
+ * Get the precedence level based on the node type
+ * @param {ASTNode} node node to evaluate
+ * @returns {int} precedence level
+ * @private
+ */
function precedence(node) {
switch (node.type) {
case "SequenceExpression":
return 0;
case "AssignmentExpression":
+ case "ArrowFunctionExpression":
case "YieldExpression":
return 1;
case "ConditionalExpression":
return 3;
@@ -22732,121 +31556,180 @@
// no default
}
return 18;
}
+ /**
+ * Report the node
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function report(node) {
var previousToken = context.getTokenBefore(node);
context.report(node, previousToken.loc.start, "Gratuitous parentheses around expression.");
}
+ /**
+ * Evaluate Unary update
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function dryUnaryUpdate(node) {
- if (isParenthesised(node.argument) && precedence(node.argument) >= precedence(node)) {
+ if (hasExcessParens(node.argument) && precedence(node.argument) >= precedence(node)) {
report(node.argument);
}
}
+ /**
+ * Evaluate a new call
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function dryCallNew(node) {
- if (isParenthesised(node.callee) && precedence(node.callee) >= precedence(node) &&
- !(node.type === "CallExpression" && node.callee.type === "FunctionExpression")) {
+ if (hasExcessParens(node.callee) && precedence(node.callee) >= precedence(node) && !(
+ node.type === "CallExpression" &&
+ node.callee.type === "FunctionExpression" &&
+ // One set of parentheses are allowed for a function expression
+ !hasDoubleExcessParens(node.callee)
+ )) {
report(node.callee);
}
if (node.arguments.length === 1) {
- if (isParenthesisedTwice(node.arguments[0]) && precedence(node.arguments[0]) >= precedence({type: "AssignmentExpression"})) {
+ if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >= precedence({type: "AssignmentExpression"})) {
report(node.arguments[0]);
}
} else {
[].forEach.call(node.arguments, function(arg) {
- if (isParenthesised(arg) && precedence(arg) >= precedence({type: "AssignmentExpression"})) {
+ if (hasExcessParens(arg) && precedence(arg) >= precedence({type: "AssignmentExpression"})) {
report(arg);
}
});
}
}
+ /**
+ * Evaluate binary logicals
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function dryBinaryLogical(node) {
var prec = precedence(node);
- if (isParenthesised(node.left) && precedence(node.left) >= prec) {
+ if (hasExcessParens(node.left) && precedence(node.left) >= prec) {
report(node.left);
}
- if (isParenthesised(node.right) && precedence(node.right) > prec) {
+ if (hasExcessParens(node.right) && precedence(node.right) > prec) {
report(node.right);
}
}
return {
"ArrayExpression": function(node) {
[].forEach.call(node.elements, function(e) {
- if (e && isParenthesised(e) && precedence(e) >= precedence({type: "AssignmentExpression"})) {
+ if (e && hasExcessParens(e) && precedence(e) >= precedence({type: "AssignmentExpression"})) {
report(e);
}
});
},
+ "ArrowFunctionExpression": function(node) {
+ if (node.body.type !== "BlockStatement") {
+ if (node.body.type !== "ObjectExpression" && hasExcessParens(node.body) && precedence(node.body) >= precedence({type: "AssignmentExpression"})) {
+ report(node.body);
+ return;
+ }
+
+ // Object literals *must* be parenthesized
+ if (node.body.type === "ObjectExpression" && hasDoubleExcessParens(node.body)) {
+ report(node.body);
+ return;
+ }
+ }
+ },
"AssignmentExpression": function(node) {
- if (isParenthesised(node.right) && precedence(node.right) >= precedence(node)) {
+ if (hasExcessParens(node.right) && precedence(node.right) >= precedence(node)) {
report(node.right);
}
},
"BinaryExpression": dryBinaryLogical,
"CallExpression": dryCallNew,
"ConditionalExpression": function(node) {
- if (isParenthesised(node.test) && precedence(node.test) >= precedence({type: "LogicalExpression", operator: "||"})) {
+ if (hasExcessParens(node.test) && precedence(node.test) >= precedence({type: "LogicalExpression", operator: "||"})) {
report(node.test);
}
- if (isParenthesised(node.consequent) && precedence(node.consequent) >= precedence({type: "AssignmentExpression"})) {
+ if (hasExcessParens(node.consequent) && precedence(node.consequent) >= precedence({type: "AssignmentExpression"})) {
report(node.consequent);
}
- if (isParenthesised(node.alternate) && precedence(node.alternate) >= precedence({type: "AssignmentExpression"})) {
+ if (hasExcessParens(node.alternate) && precedence(node.alternate) >= precedence({type: "AssignmentExpression"})) {
report(node.alternate);
}
},
"DoWhileStatement": function(node) {
- if (isParenthesisedTwice(node.test)) {
+ if (hasDoubleExcessParens(node.test)) {
report(node.test);
}
},
"ExpressionStatement": function(node) {
var firstToken;
- if (isParenthesised(node.expression)) {
+ if (hasExcessParens(node.expression)) {
firstToken = context.getFirstToken(node.expression);
- if (firstToken.value !== "function" && firstToken.value !== "{") {
+
+ // Pure object literals ({}) do not need parentheses but
+ // member expressions do ({}.toString())
+ if ((
+ firstToken.value !== "{" ||
+ node.expression.type === "ObjectExpression"
+ ) &&
+ // For such as `(function(){}.foo.bar)`
+ (
+ firstToken.value !== "function" ||
+ node.expression.type === "FunctionExpression"
+ ) &&
+ // For such as `(class{}.foo.bar)`
+ (
+ firstToken.value !== "class" ||
+ node.expression.type === "ClassExpression"
+ )
+ ) {
report(node.expression);
}
}
},
"ForInStatement": function(node) {
- if (isParenthesised(node.right)) {
+ if (hasExcessParens(node.right)) {
report(node.right);
}
},
"ForOfStatement": function(node) {
- if (isParenthesised(node.right)) {
+ if (hasExcessParens(node.right)) {
report(node.right);
}
},
"ForStatement": function(node) {
- if (node.init && isParenthesised(node.init)) {
+ if (node.init && hasExcessParens(node.init)) {
report(node.init);
}
- if (node.test && isParenthesised(node.test)) {
+ if (node.test && hasExcessParens(node.test)) {
report(node.test);
}
- if (node.update && isParenthesised(node.update)) {
+ if (node.update && hasExcessParens(node.update)) {
report(node.update);
}
},
"IfStatement": function(node) {
- if (isParenthesisedTwice(node.test)) {
+ if (hasDoubleExcessParens(node.test)) {
report(node.test);
}
},
"LogicalExpression": dryBinaryLogical,
"MemberExpression": function(node) {
if (
- isParenthesised(node.object) &&
+ hasExcessParens(node.object) &&
precedence(node.object) >= precedence(node) &&
(
node.computed ||
!(
(node.object.type === "Literal" &&
@@ -22854,78 +31737,92 @@
/^[0-9]+$/.test(context.getFirstToken(node.object).value))
||
// RegExp literal is allowed to have parens (#1589)
(node.object.type === "Literal" && node.object.regex)
)
+ ) &&
+ !(
+ (node.object.type === "FunctionExpression" || node.object.type === "ClassExpression") &&
+ isHeadOfExpressionStatement(node) &&
+ !hasDoubleExcessParens(node.object)
)
) {
report(node.object);
}
+ if (node.computed && hasExcessParens(node.property)) {
+ report(node.property);
+ }
},
"NewExpression": dryCallNew,
"ObjectExpression": function(node) {
[].forEach.call(node.properties, function(e) {
var v = e.value;
- if (v && isParenthesised(v) && precedence(v) >= precedence({type: "AssignmentExpression"})) {
+ if (v && hasExcessParens(v) && precedence(v) >= precedence({type: "AssignmentExpression"})) {
report(v);
}
});
},
"ReturnStatement": function(node) {
- if (node.argument && isParenthesised(node.argument) &&
+ if (node.argument && hasExcessParens(node.argument) &&
// RegExp literal is allowed to have parens (#1589)
!(node.argument.type === "Literal" && node.argument.regex)) {
report(node.argument);
}
},
"SequenceExpression": function(node) {
[].forEach.call(node.expressions, function(e) {
- if (isParenthesised(e) && precedence(e) >= precedence(node)) {
+ if (hasExcessParens(e) && precedence(e) >= precedence(node)) {
report(e);
}
});
},
"SwitchCase": function(node) {
- if (node.test && isParenthesised(node.test)) {
+ if (node.test && hasExcessParens(node.test)) {
report(node.test);
}
},
"SwitchStatement": function(node) {
- if (isParenthesisedTwice(node.discriminant)) {
+ if (hasDoubleExcessParens(node.discriminant)) {
report(node.discriminant);
}
},
"ThrowStatement": function(node) {
- if (isParenthesised(node.argument)) {
+ if (hasExcessParens(node.argument)) {
report(node.argument);
}
},
"UnaryExpression": dryUnaryUpdate,
"UpdateExpression": dryUnaryUpdate,
"VariableDeclarator": function(node) {
- if (node.init && isParenthesised(node.init) &&
+ if (node.init && hasExcessParens(node.init) &&
precedence(node.init) >= precedence({type: "AssignmentExpression"}) &&
// RegExp literal is allowed to have parens (#1589)
!(node.init.type === "Literal" && node.init.regex)) {
report(node.init);
}
},
"WhileStatement": function(node) {
- if (isParenthesisedTwice(node.test)) {
+ if (hasDoubleExcessParens(node.test)) {
report(node.test);
}
},
"WithStatement": function(node) {
- if (isParenthesisedTwice(node.object)) {
+ if (hasDoubleExcessParens(node.object)) {
report(node.object);
}
}
};
};
-},{}],191:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["all", "functions"]
+ }
+];
+
+},{}],199:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of unnecessary semicolons
* @author Nicholas C. Zakas
*/
@@ -22935,114 +31832,90 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- return {
-
- "EmptyStatement": function(node) {
- context.report(node, "Unnecessary semicolon.");
- }
- };
-
-};
-
-},{}],192:[function(require,module,exports){
-/**
- * @fileoverview Rule to flag unnecessary strict directives.
- * @author Ian Christian Myers
- * @copyright 2014 Ian Christian Myers. All rights reserved.
- */
-"use strict";
-
-//------------------------------------------------------------------------------
-// Rule Definition
-//------------------------------------------------------------------------------
-
-module.exports = function(context) {
-
- function directives(block) {
- var ds = [], body = block.body, e, i, l;
-
- if (body) {
- for (i = 0, l = body.length; i < l; ++i) {
- e = body[i];
-
- if (
- e.type === "ExpressionStatement" &&
- e.expression.type === "Literal" &&
- typeof e.expression.value === "string"
- ) {
- ds.push(e.expression);
- } else {
- break;
- }
+ /**
+ * Reports an unnecessary semicolon error.
+ * @param {Node|Token} nodeOrToken - A node or a token to be reported.
+ * @returns {void}
+ */
+ function report(nodeOrToken) {
+ context.report({
+ node: nodeOrToken,
+ message: "Unnecessary semicolon.",
+ fix: function(fixer) {
+ return fixer.remove(nodeOrToken);
}
- }
-
- return ds;
+ });
}
- function isStrict(directive) {
- return directive.value === "use strict";
- }
-
- function checkForUnnecessaryUseStrict(node) {
- var useStrictDirectives = directives(node).filter(isStrict),
- scope,
- upper;
-
- switch (useStrictDirectives.length) {
- case 0:
- break;
-
- case 1:
- scope = context.getScope();
- upper = scope.upper;
-
- if (upper && upper.functionExpressionScope) {
- upper = upper.upper;
- }
-
- if (upper && upper.isStrict) {
- context.report(useStrictDirectives[0], "Unnecessary 'use strict'.");
- }
- break;
-
- default:
- context.report(useStrictDirectives[1], "Multiple 'use strict' directives.");
+ /**
+ * Checks for a part of a class body.
+ * This checks tokens from a specified token to a next MethodDefinition or the end of class body.
+ *
+ * @param {Token} firstToken - The first token to check.
+ * @returns {void}
+ */
+ function checkForPartOfClassBody(firstToken) {
+ for (var token = firstToken;
+ token.type === "Punctuator" && token.value !== "}";
+ token = context.getTokenAfter(token)
+ ) {
+ if (token.value === ";") {
+ report(token);
+ }
}
}
return {
+ /**
+ * Reports this empty statement, except if the parent node is a loop.
+ * @param {Node} node - A EmptyStatement node to be reported.
+ * @returns {void}
+ */
+ "EmptyStatement": function(node) {
+ var parent = node.parent,
+ allowedParentTypes = ["ForStatement", "ForInStatement", "ForOfStatement", "WhileStatement", "DoWhileStatement"];
- "Program": checkForUnnecessaryUseStrict,
-
- "ArrowFunctionExpression": function(node) {
- checkForUnnecessaryUseStrict(node.body);
+ if (allowedParentTypes.indexOf(parent.type) === -1) {
+ report(node);
+ }
},
- "FunctionExpression": function(node) {
- checkForUnnecessaryUseStrict(node.body);
+ /**
+ * Checks tokens from the head of this class body to the first MethodDefinition or the end of this class body.
+ * @param {Node} node - A ClassBody node to check.
+ * @returns {void}
+ */
+ "ClassBody": function(node) {
+ checkForPartOfClassBody(context.getFirstToken(node, 1)); // 0 is `{`.
},
- "FunctionDeclaration": function(node) {
- checkForUnnecessaryUseStrict(node.body);
+ /**
+ * Checks tokens from this MethodDefinition to the next MethodDefinition or the end of this class body.
+ * @param {Node} node - A MethodDefinition node of the start point.
+ * @returns {void}
+ */
+ "MethodDefinition": function(node) {
+ checkForPartOfClassBody(context.getTokenAfter(node));
}
};
};
-},{}],193:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],200:[function(require,module,exports){
/**
* @fileoverview Rule to flag fall-through cases in switch statements.
* @author Matt DuVall <http://mattduvall.com/>
*/
"use strict";
-var FALLTHROUGH_COMMENT = /falls\sthrough/;
+var FALLTHROUGH_COMMENT = /falls?\s?through/i;
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -23127,11 +32000,13 @@
}
};
};
-},{}],194:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],201:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of a leading/trailing decimal point in a numeric literal
* @author James Allardice
*/
@@ -23157,94 +32032,324 @@
}
};
};
-},{}],195:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],202:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of function declaration identifiers as variables.
* @author Ian Christian Myers
* @copyright 2013 Ian Christian Myers. All rights reserved.
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- //--------------------------------------------------------------------------
- // Helpers
- //--------------------------------------------------------------------------
+ var unresolved = Object.create(null);
- /*
- * Walk the scope chain looking for either a FunctionDeclaration or a
- * VariableDeclaration with the same name as left-hand side of the
- * AssignmentExpression. If we find the FunctionDeclaration first, then we
- * warn, because a FunctionDeclaration is trying to become a Variable or a
- * FunctionExpression. If we find a VariableDeclaration first, then we have
- * a legitimate shadow variable.
+ /**
+ * Collects unresolved references from the global scope, then creates a map to references from its name.
+ * Usage of the map is explained at `checkVariable(variable)`.
+ * @returns {void}
*/
- function checkIfIdentifierIsFunction(scope, name) {
- var variable,
- def,
- i,
- j;
+ function collectUnresolvedReferences() {
+ unresolved = Object.create(null);
- // Loop over all of the identifiers available in scope.
- for (i = 0; i < scope.variables.length; i++) {
- variable = scope.variables[i];
+ var references = context.getScope().through;
+ for (var i = 0; i < references.length; ++i) {
+ var reference = references[i];
+ var name = reference.identifier.name;
- // For each identifier, see if it was defined in _this_ scope.
- for (j = 0; j < variable.defs.length; j++) {
- def = variable.defs[j];
+ if (name in unresolved === false) {
+ unresolved[name] = [];
+ }
+ unresolved[name].push(reference);
+ }
+ }
- // Identifier is a function and was declared in this scope
- if (def.name.name === name && def.type === "FunctionName") {
- return true;
- }
+ /**
+ * Reports a reference if is non initializer and writable.
+ * @param {References} references - Collection of reference to check.
+ * @returns {void}
+ */
+ function checkReference(references) {
+ astUtils.getModifyingReferences(references).forEach(function(reference) {
+ context.report(
+ reference.identifier,
+ "'{{name}}' is a function.",
+ {name: reference.identifier.name});
+ });
+ }
- // Identifier is a variable and was declared in this scope. This
- // is a legitimate shadow variable.
- if (def.name.name === name) {
- return false;
- }
+ /**
+ * Finds and reports references that are non initializer and writable.
+ * @param {Variable} variable - A variable to check.
+ * @returns {void}
+ */
+ function checkVariable(variable) {
+ if (variable.defs[0].type === "FunctionName") {
+ // If the function is in global scope, its references are not resolved (by escope's design).
+ // So when references of the function are nothing, this checks in unresolved.
+ if (variable.references.length > 0) {
+ checkReference(variable.references);
+ } else if (unresolved[variable.name]) {
+ checkReference(unresolved[variable.name]);
}
}
+ }
- // Check the upper scope.
- if (scope.upper) {
- return checkIfIdentifierIsFunction(scope.upper, name);
- }
+ /**
+ * Checks parameters of a given function node.
+ * @param {ASTNode} node - A function node to check.
+ * @returns {void}
+ */
+ function checkForFunction(node) {
+ context.getDeclaredVariables(node).forEach(checkVariable);
+ }
- // We've reached the global scope and haven't found anything.
- return false;
+ return {
+ "Program": collectUnresolvedReferences,
+ "FunctionDeclaration": checkForFunction,
+ "FunctionExpression": checkForFunction
+ };
+
+};
+
+module.exports.schema = [];
+
+},{"../ast-utils":113}],203:[function(require,module,exports){
+/**
+ * @fileoverview A rule to disallow the type conversions with shorter notations.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+var INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/;
+
+/**
+ * Parses and normalizes an option object.
+ * @param {object} options - An option object to parse.
+ * @returns {object} The parsed and normalized option object.
+ */
+function parseOptions(options) {
+ options = options || {};
+ return {
+ boolean: "boolean" in options ? Boolean(options.boolean) : true,
+ number: "number" in options ? Boolean(options.number) : true,
+ string: "string" in options ? Boolean(options.string) : true
+ };
+}
+
+/**
+ * Checks whether or not a node is a double logical nigating.
+ * @param {ASTNode} node - An UnaryExpression node to check.
+ * @returns {boolean} Whether or not the node is a double logical nigating.
+ */
+function isDoubleLogicalNegating(node) {
+ return (
+ node.operator === "!" &&
+ node.argument.type === "UnaryExpression" &&
+ node.argument.operator === "!"
+ );
+}
+
+/**
+ * Checks whether or not a node is a binary negating of `.indexOf()` method calling.
+ * @param {ASTNode} node - An UnaryExpression node to check.
+ * @returns {boolean} Whether or not the node is a binary negating of `.indexOf()` method calling.
+ */
+function isBinaryNegatingOfIndexOf(node) {
+ return (
+ node.operator === "~" &&
+ node.argument.type === "CallExpression" &&
+ node.argument.callee.type === "MemberExpression" &&
+ node.argument.callee.property.type === "Identifier" &&
+ INDEX_OF_PATTERN.test(node.argument.callee.property.name)
+ );
+}
+
+/**
+ * Checks whether or not a node is a multiplying by one.
+ * @param {BinaryExpression} node - A BinaryExpression node to check.
+ * @returns {boolean} Whether or not the node is a multiplying by one.
+ */
+function isMultiplyByOne(node) {
+ return node.operator === "*" && (
+ node.left.type === "Literal" && node.left.value === 1 ||
+ node.right.type === "Literal" && node.right.value === 1
+ );
+}
+
+/**
+ * Checks whether the result of a node is numeric or not
+ * @param {ASTNode} node The node to test
+ * @returns {boolean} true if the node is a number literal or a `Number()`, `parseInt` or `parseFloat` call
+ */
+function isNumeric(node) {
+ return (
+ node.type === "Literal" && typeof node.value === "number" ||
+ node.type === "CallExpression" && (
+ node.callee.name === "Number" ||
+ node.callee.name === "parseInt" ||
+ node.callee.name === "parseFloat"
+ )
+ );
+}
+
+/**
+ * Returns the first non-numeric operand in a BinaryExpression. Designed to be
+ * used from bottom to up since it walks up the BinaryExpression trees using
+ * node.parent to find the result.
+ * @param {BinaryExpression} node The BinaryExpression node to be walked up on
+ * @returns {ASTNode|undefined} The first non-numeric item in the BinaryExpression tree or undefined
+ */
+function getNonNumericOperand(node) {
+ var left = node.left, right = node.right;
+
+ if (right.type !== "BinaryExpression" && !isNumeric(right)) {
+ return right;
}
- //--------------------------------------------------------------------------
- // Public API
- //--------------------------------------------------------------------------
+ if (left.type !== "BinaryExpression" && !isNumeric(left)) {
+ return left;
+ }
+}
+/**
+ * Checks whether or not a node is a concatenating with an empty string.
+ * @param {ASTNode} node - A BinaryExpression node to check.
+ * @returns {boolean} Whether or not the node is a concatenating with an empty string.
+ */
+function isConcatWithEmptyString(node) {
+ return node.operator === "+" && (
+ (node.left.type === "Literal" && node.left.value === "") ||
+ (node.right.type === "Literal" && node.right.value === "")
+ );
+}
+
+/**
+ * Checks whether or not a node is appended with an empty string.
+ * @param {ASTNode} node - An AssignmentExpression node to check.
+ * @returns {boolean} Whether or not the node is appended with an empty string.
+ */
+function isAppendEmptyString(node) {
+ return node.operator === "+=" && node.right.type === "Literal" && node.right.value === "";
+}
+
+/**
+ * Gets a node that is the left or right operand of a node, is not the specified literal.
+ * @param {ASTNode} node - A BinaryExpression node to get.
+ * @param {any} value - A literal value to check.
+ * @returns {ASTNode} A node that is the left or right operand of the node, is not the specified literal.
+ */
+function getOtherOperand(node, value) {
+ if (node.left.type === "Literal" && node.left.value === value) {
+ return node.right;
+ }
+ return node.left;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var options = parseOptions(context.options[0]);
+
return {
+ "UnaryExpression": function(node) {
+ // !!foo
+ if (options.boolean && isDoubleLogicalNegating(node)) {
+ context.report(
+ node,
+ "use `Boolean({{code}})` instead.",
+ {code: context.getSource(node.argument.argument)});
+ }
- "AssignmentExpression": function(node) {
- var scope = context.getScope(),
- name = node.left.name;
+ // ~foo.indexOf(bar)
+ if (options.boolean && isBinaryNegatingOfIndexOf(node)) {
+ context.report(
+ node,
+ "use `{{code}} !== -1` instead.",
+ {code: context.getSource(node.argument)});
+ }
- if (checkIfIdentifierIsFunction(scope, name)) {
- context.report(node, "'{{name}}' is a function.", { name: name });
+ // +foo
+ if (options.number && node.operator === "+" && !isNumeric(node.argument)) {
+ context.report(
+ node,
+ "use `Number({{code}})` instead.",
+ {code: context.getSource(node.argument)});
}
+ },
- }
+ // Use `:exit` to prevent double reporting
+ "BinaryExpression:exit": function(node) {
+ // 1 * foo
+ var nonNumericOperand = options.number && isMultiplyByOne(node) && getNonNumericOperand(node);
+ if (nonNumericOperand) {
+ context.report(
+ node,
+ "use `Number({{code}})` instead.",
+ {code: context.getSource(nonNumericOperand)});
+ }
- };
+ // "" + foo
+ if (options.string && isConcatWithEmptyString(node)) {
+ context.report(
+ node,
+ "use `String({{code}})` instead.",
+ {code: context.getSource(getOtherOperand(node, ""))});
+ }
+ },
+ "AssignmentExpression": function(node) {
+ // foo += ""
+ if (options.string && isAppendEmptyString(node)) {
+ context.report(
+ node,
+ "use `{{code}} = String({{code}})` instead.",
+ {code: context.getSource(getOtherOperand(node, ""))});
+ }
+ }
+ };
};
-},{}],196:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "boolean": {
+ "type": "boolean"
+ },
+ "number": {
+ "type": "boolean"
+ },
+ "string": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],204:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of implied eval via setTimeout and setInterval
* @author James Allardice
* @copyright 2015 Mathias Schreck. All rights reserved.
* @copyright 2013 James Allardice. All rights reserved.
@@ -23255,79 +32360,150 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var IMPLIED_EVAL = /set(?:Timeout|Interval)/;
+ var CALLEE_RE = /set(?:Timeout|Interval)|execScript/;
+ // Figures out if we should inspect a given binary expression. Is a stack of
+ // stacks, where the first element in each substack is a CallExpression.
+ var impliedEvalAncestorsStack = [];
+
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
- * Checks if the first argument of a given CallExpression node is a string literal.
- * @param {ASTNode} node The CallExpression node the check.
- * @returns {boolean} True if the first argument is a string literal, false if not.
+ * Get the last element of an array, without modifying arr, like pop(), but non-destructive.
+ * @param {array} arr What to inspect
+ * @returns {*} The last element of arr
+ * @private
*/
- function hasStringLiteralArgument(node) {
- var firstArgument = node.arguments[0];
-
- return firstArgument && firstArgument.type === "Literal" && typeof firstArgument.value === "string";
+ function last(arr) {
+ return arr ? arr[arr.length - 1] : null;
}
/**
- * Checks if the given MemberExpression node is window.setTimeout or window.setInterval.
+ * Checks if the given MemberExpression node is a potentially implied eval identifier on window.
* @param {ASTNode} node The MemberExpression node to check.
- * @returns {boolean} Whether or not the given node is window.set*.
+ * @returns {boolean} Whether or not the given node is potentially an implied eval.
+ * @private
*/
- function isSetMemberExpression(node) {
+ function isImpliedEvalMemberExpression(node) {
var object = node.object,
property = node.property,
- hasSetPropertyName = IMPLIED_EVAL.test(property.name) || IMPLIED_EVAL.test(property.value);
+ hasImpliedEvalName = CALLEE_RE.test(property.name) || CALLEE_RE.test(property.value);
- return object.name === "window" && hasSetPropertyName;
-
+ return object.name === "window" && hasImpliedEvalName;
}
/**
- * Determines if a node represents a call to setTimeout/setInterval with
- * a string argument.
- * @param {ASTNode} node The node to check.
+ * Determines if a node represents a call to a potentially implied eval.
+ *
+ * This checks the callee name and that there's an argument, but not the type of the argument.
+ *
+ * @param {ASTNode} node The CallExpression to check.
* @returns {boolean} True if the node matches, false if not.
* @private
*/
- function isImpliedEval(node) {
+ function isImpliedEvalCallExpression(node) {
var isMemberExpression = (node.callee.type === "MemberExpression"),
isIdentifier = (node.callee.type === "Identifier"),
- isSetMethod = (isIdentifier && IMPLIED_EVAL.test(node.callee.name)) ||
- (isMemberExpression && isSetMemberExpression(node.callee));
+ isImpliedEvalCallee =
+ (isIdentifier && CALLEE_RE.test(node.callee.name)) ||
+ (isMemberExpression && isImpliedEvalMemberExpression(node.callee));
- return isSetMethod && hasStringLiteralArgument(node);
+ return isImpliedEvalCallee && node.arguments.length;
}
+ /**
+ * Checks that the parent is a direct descendent of an potential implied eval CallExpression, and if the parent is a CallExpression, that we're the first argument.
+ * @param {ASTNode} node The node to inspect the parent of.
+ * @returns {boolean} Was the parent a direct descendent, and is the child therefore potentially part of a dangerous argument?
+ * @private
+ */
+ function hasImpliedEvalParent(node) {
+ // make sure our parent is marked
+ return node.parent === last(last(impliedEvalAncestorsStack)) &&
+ // if our parent is a CallExpression, make sure we're the first argument
+ (node.parent.type !== "CallExpression" || node === node.parent.arguments[0]);
+ }
+
+ /**
+ * Checks if our parent is marked as part of an implied eval argument. If
+ * so, collapses the top of impliedEvalAncestorsStack and reports on the
+ * original CallExpression.
+ * @param {ASTNode} node The CallExpression to check.
+ * @returns {boolean} True if the node matches, false if not.
+ * @private
+ */
+ function checkString(node) {
+ if (hasImpliedEvalParent(node)) {
+ // remove the entire substack, to avoid duplicate reports
+ var substack = impliedEvalAncestorsStack.pop();
+ context.report(substack[0], "Implied eval. Consider passing a function instead of a string.");
+ }
+ }
+
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
"CallExpression": function(node) {
- if (isImpliedEval(node)) {
- context.report(node, "Implied eval. Consider passing a function instead of a string.");
+ if (isImpliedEvalCallExpression(node)) {
+ // call expressions create a new substack
+ impliedEvalAncestorsStack.push([node]);
}
+ },
+
+ "CallExpression:exit": function(node) {
+ if (node === last(last(impliedEvalAncestorsStack))) {
+ // destroys the entire sub-stack, rather than just using
+ // last(impliedEvalAncestorsStack).pop(), as a CallExpression is
+ // always the bottom of a impliedEvalAncestorsStack substack.
+ impliedEvalAncestorsStack.pop();
+ }
+ },
+
+ "BinaryExpression": function(node) {
+ if (node.operator === "+" && hasImpliedEvalParent(node)) {
+ last(impliedEvalAncestorsStack).push(node);
+ }
+ },
+
+ "BinaryExpression:exit": function(node) {
+ if (node === last(last(impliedEvalAncestorsStack))) {
+ last(impliedEvalAncestorsStack).pop();
+ }
+ },
+
+ "Literal": function(node) {
+ if (typeof node.value === "string") {
+ checkString(node);
+ }
+ },
+
+ "TemplateLiteral": function(node) {
+ checkString(node);
}
};
};
-},{}],197:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],205:[function(require,module,exports){
/**
* @fileoverview Enforces or disallows inline comments.
* @author Greg Cochard
* @copyright 2014 Greg Cochard. All rights reserved.
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
@@ -23347,12 +32523,15 @@
var preamble = startLine.slice(0, node.loc.start.column).trim();
// Also check after the comment
var postamble = endLine.slice(node.loc.end.column).trim();
+ // Check that this comment isn't an ESLint directive
+ var isDirective = astUtils.isDirectiveComment(node);
+
// Should be empty if there was only whitespace around the comment
- if (preamble || postamble) {
+ if (!isDirective && (preamble || postamble)) {
context.report(node, "Unexpected comment inline with code.");
}
}
//--------------------------------------------------------------------------
@@ -23365,11 +32544,13 @@
"BlockComment": testCodeAroundComment
};
};
-},{}],198:[function(require,module,exports){
+module.exports.schema = [];
+
+},{"../ast-utils":113}],206:[function(require,module,exports){
/**
* @fileoverview Rule to enforce declarations in program or function body root.
* @author Brandon Mills
* @copyright 2014 Brandon Mills. All rights reserved.
*/
@@ -23439,11 +32620,17 @@
};
};
-},{}],199:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["functions", "both"]
+ }
+];
+
+},{}],207:[function(require,module,exports){
/**
* @fileoverview Validate strings passed to the RegExp constructor
* @author Michael Ficarra
* @copyright 2014 Michael Ficarra. All rights reserved.
*/
@@ -23459,21 +32646,33 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ /**
+ * Check if node is a string
+ * @param {ASTNode} node node to evaluate
+ * @returns {boolean} True if its a string
+ * @private
+ */
function isString(node) {
return node && node.type === "Literal" && typeof node.value === "string";
}
+ /**
+ * Validate strings passed to the RegExp constructor
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function check(node) {
if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) {
var flags = isString(node.arguments[1]) ? node.arguments[1].value : "";
try {
void new RegExp(node.arguments[0].value);
- } catch(e) {
+ } catch (e) {
context.report(node, e.message);
}
if (flags) {
@@ -23492,12 +32691,366 @@
"NewExpression": check
};
};
-},{"espree":"espree"}],200:[function(require,module,exports){
+module.exports.schema = [];
+
+},{"espree":"espree"}],208:[function(require,module,exports){
/**
+ * @fileoverview A rule to disallow `this` keywords outside of classes or class-like objects.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+var thisTagPattern = /^[\s\*]*@this/m;
+var anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/;
+var bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/;
+var arrayOrTypedArrayPattern = /Array$/;
+var arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/;
+
+/**
+ * Checks whether or not a node is a constructor.
+ * @param {ASTNode} node - A function node to check.
+ * @returns {boolean} Wehether or not a node is a constructor.
+ */
+function isES5Constructor(node) {
+ return (
+ node.id &&
+ node.id.name[0] === node.id.name[0].toLocaleUpperCase()
+ );
+}
+
+/**
+ * Finds a function node from ancestors of a node.
+ * @param {ASTNode} node - A start node to find.
+ * @returns {Node|null} A found function node.
+ */
+function getUpperFunction(node) {
+ while (node) {
+ if (anyFunctionPattern.test(node.type)) {
+ return node;
+ }
+ node = node.parent;
+ }
+ return null;
+}
+
+/**
+ * Checks whether or not a node is callee.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node is callee.
+ */
+function isCallee(node) {
+ return node.parent.type === "CallExpression" && node.parent.callee === node;
+}
+
+/**
+ * Checks whether or not a node is `Reclect.apply`.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node is a `Reclect.apply`.
+ */
+function isReflectApply(node) {
+ return (
+ node.type === "MemberExpression" &&
+ node.object.type === "Identifier" &&
+ node.object.name === "Reflect" &&
+ node.property.type === "Identifier" &&
+ node.property.name === "apply" &&
+ node.computed === false
+ );
+}
+
+/**
+ * Checks whether or not a node is `Array.from`.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node is a `Array.from`.
+ */
+function isArrayFrom(node) {
+ return (
+ node.type === "MemberExpression" &&
+ node.object.type === "Identifier" &&
+ arrayOrTypedArrayPattern.test(node.object.name) &&
+ node.property.type === "Identifier" &&
+ node.property.name === "from" &&
+ node.computed === false
+ );
+}
+
+/**
+ * Checks whether or not a node is a method which has `thisArg`.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node is a method which has `thisArg`.
+ */
+function isMethodWhichHasThisArg(node) {
+ while (node) {
+ if (node.type === "Identifier") {
+ return arrayMethodPattern.test(node.name);
+ }
+ if (node.type === "MemberExpression" && !node.computed) {
+ node = node.property;
+ continue;
+ }
+
+ break;
+ }
+
+ return false;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var stack = [],
+ sourceCode = context.getSourceCode();
+
+
+ /**
+ * Checks whether or not a node has a `@this` tag in its comments.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node has a `@this` tag in its comments.
+ */
+ function hasJSDocThisTag(node) {
+ var jsdocComment = sourceCode.getJSDocComment(node);
+ if (jsdocComment && thisTagPattern.test(jsdocComment.value)) {
+ return true;
+ }
+
+ // Checks `@this` in its leading comments for callbacks,
+ // because callbacks don't have its JSDoc comment.
+ // e.g.
+ // sinon.test(/* @this sinon.Sandbox */function() { this.spy(); });
+ return sourceCode.getComments(node).leading.some(function(comment) {
+ return thisTagPattern.test(comment.value);
+ });
+ }
+
+ /**
+ * Checks whether or not a node has valid `this`.
+ *
+ * First, this checks the node:
+ *
+ * - The function name starts with uppercase (it's a constructor).
+ * - The function has a JSDoc comment that has a @this tag.
+ *
+ * Next, this checks the location of the node.
+ * If the location is below, this judges `this` is valid.
+ *
+ * - The location is on an object literal.
+ * - The location assigns to a property.
+ * - The location is on an ES2015 class.
+ * - The location calls its `bind`/`call`/`apply` method directly.
+ * - The function is a callback of array methods (such as `.forEach()`) if `thisArg` is given.
+ *
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} A found function node.
+ */
+ function hasValidThis(node) {
+ if (isES5Constructor(node) || hasJSDocThisTag(node)) {
+ return true;
+ }
+
+ while (node) {
+ var parent = node.parent;
+ switch (parent.type) {
+ // Looks up the destination.
+ // e.g.
+ // obj.foo = nativeFoo || function foo() { ... };
+ case "LogicalExpression":
+ case "ConditionalExpression":
+ node = parent;
+ break;
+
+ // If the upper function is IIFE, checks the destination of the return value.
+ // e.g.
+ // obj.foo = (function() {
+ // // setup...
+ // return function foo() { ... };
+ // })();
+ case "ReturnStatement":
+ var func = getUpperFunction(parent);
+ if (func === null || !isCallee(func)) {
+ return false;
+ }
+ node = func.parent;
+ break;
+
+ // e.g.
+ // var obj = { foo() { ... } };
+ // var obj = { foo: function() { ... } };
+ case "Property":
+ return true;
+
+ // e.g.
+ // obj.foo = foo() { ... };
+ case "AssignmentExpression":
+ return (
+ parent.right === node &&
+ parent.left.type === "MemberExpression"
+ );
+
+ // e.g.
+ // class A { constructor() { ... } }
+ // class A { foo() { ... } }
+ // class A { get foo() { ... } }
+ // class A { set foo() { ... } }
+ // class A { static foo() { ... } }
+ case "MethodDefinition":
+ return !parent.static;
+
+ // e.g.
+ // var foo = function foo() { ... }.bind(obj);
+ // (function foo() { ... }).call(obj);
+ // (function foo() { ... }).apply(obj, []);
+ case "MemberExpression":
+ return (
+ parent.object === node &&
+ parent.property.type === "Identifier" &&
+ bindOrCallOrApplyPattern.test(parent.property.name) &&
+ isCallee(parent) &&
+ parent.parent.arguments.length > 0 &&
+ !astUtils.isNullOrUndefined(parent.parent.arguments[0])
+ );
+
+ // e.g.
+ // Reflect.apply(function() {}, obj, []);
+ // Array.from([], function() {}, obj);
+ // list.forEach(function() {}, obj);
+ case "CallExpression":
+ if (isReflectApply(parent.callee)) {
+ return (
+ parent.arguments.length === 3 &&
+ parent.arguments[0] === node &&
+ !astUtils.isNullOrUndefined(parent.arguments[1])
+ );
+ }
+ if (isArrayFrom(parent.callee)) {
+ return (
+ parent.arguments.length === 3 &&
+ parent.arguments[1] === node &&
+ !astUtils.isNullOrUndefined(parent.arguments[2])
+ );
+ }
+ if (isMethodWhichHasThisArg(parent.callee)) {
+ return (
+ parent.arguments.length === 2 &&
+ parent.arguments[0] === node &&
+ !astUtils.isNullOrUndefined(parent.arguments[1])
+ );
+ }
+ return false;
+
+ // Otherwise `this` is invalid.
+ default:
+ return false;
+ }
+ }
+
+ /* istanbul ignore next */
+ throw new Error("unreachable");
+ }
+
+ /**
+ * Gets the current checking context.
+ *
+ * The return value has a flag that whether or not `this` keyword is valid.
+ * The flag is initialized when got at the first time.
+ *
+ * @returns {{valid: boolean}}
+ * an object which has a flag that whether or not `this` keyword is valid.
+ */
+ stack.getCurrent = function() {
+ var current = this[this.length - 1];
+ if (!current.init) {
+ current.init = true;
+ current.valid = hasValidThis(current.node);
+ }
+ return current;
+ };
+
+ /**
+ * Pushs new checking context into the stack.
+ *
+ * The checking context is not initialized yet.
+ * Because most functions don't have `this` keyword.
+ * When `this` keyword was found, the checking context is initialized.
+ *
+ * @param {ASTNode} node - A function node that was entered.
+ * @returns {void}
+ */
+ function enterFunction(node) {
+ // `this` can be invalid only under strict mode.
+ stack.push({
+ init: !context.getScope().isStrict,
+ node: node,
+ valid: true
+ });
+ }
+
+ /**
+ * Pops the current checking context from the stack.
+ * @returns {void}
+ */
+ function exitFunction() {
+ stack.pop();
+ }
+
+ return {
+ // `this` is invalid only under strict mode.
+ // Modules is always strict mode.
+ "Program": function(node) {
+ var scope = context.getScope();
+ var features = context.ecmaFeatures;
+
+ stack.push({
+ init: true,
+ node: node,
+ valid: !(
+ scope.isStrict ||
+ features.modules ||
+ (features.globalReturn && scope.childScopes[0].isStrict)
+ )
+ });
+ },
+ "Program:exit": function() {
+ stack.pop();
+ },
+
+ "FunctionDeclaration": enterFunction,
+ "FunctionDeclaration:exit": exitFunction,
+ "FunctionExpression": enterFunction,
+ "FunctionExpression:exit": exitFunction,
+
+ // Reports if `this` of the current context is invalid.
+ "ThisExpression": function(node) {
+ var current = stack.getCurrent();
+ if (current && !current.valid) {
+ context.report(node, "Unexpected `this`.");
+ }
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{"../ast-utils":113}],209:[function(require,module,exports){
+/**
* @fileoverview Rule to disalow whitespace that is not a tab or space, whitespace inside strings and comments are allowed
* @author Jonathan Kingston
* @copyright 2014 Jonathan Kingston. All rights reserved.
*/
@@ -23507,11 +33060,12 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var irregularWhitespace = /[\u0085\u00A0\ufeff\f\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u202f\u205f\u3000]+/mg;
+ var irregularWhitespace = /[\u0085\u00A0\ufeff\f\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg,
+ irregularLineTerminators = /[\u2028\u2029]/mg;
// Module store of errors that we have found
var errors = [];
/**
@@ -23522,75 +33076,117 @@
*/
function removeStringError(node) {
var locStart = node.loc.start;
var locEnd = node.loc.end;
- errors = errors.filter(function (error) {
+ errors = errors.filter(function(error) {
var errorLoc = error[1];
if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) {
- if (errorLoc.column >= locStart.column && errorLoc.column <= locEnd.column) {
+ if (errorLoc.column >= locStart.column && (errorLoc.column <= locEnd.column || errorLoc.line < locEnd.line)) {
return false;
}
}
return true;
});
}
/**
- * Checks nodes for errors that we are choosing to ignore and calls the relevent methods to remove the errors
+ * Checks nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors
* @param {ASTNode} node to check for matching errors.
* @returns {void}
* @private
*/
function removeInvalidNodeErrors(node) {
if (typeof node.value === "string") {
// If we have irregular characters remove them from the errors list
- if (node.value.match(irregularWhitespace)) {
+ if (node.raw.match(irregularWhitespace) || node.raw.match(irregularLineTerminators)) {
removeStringError(node);
}
}
}
+ /**
+ * Checks the program source for irregular whitespace
+ * @param {ASTNode} node The program node
+ * @returns {void}
+ * @private
+ */
+ function checkForIrregularWhitespace(node) {
+ var sourceLines = context.getSourceLines();
+
+ sourceLines.forEach(function(sourceLine, lineIndex) {
+ var lineNumber = lineIndex + 1,
+ location,
+ match;
+
+ while ((match = irregularWhitespace.exec(sourceLine)) !== null) {
+ location = {
+ line: lineNumber,
+ column: match.index
+ };
+
+ errors.push([node, location, "Irregular whitespace not allowed"]);
+ }
+ });
+ }
+
+ /**
+ * Checks the program source for irregular line terminators
+ * @param {ASTNode} node The program node
+ * @returns {void}
+ * @private
+ */
+ function checkForIrregularLineTerminators(node) {
+ var source = context.getSource(),
+ sourceLines = context.getSourceLines(),
+ linebreaks = source.match(/\r\n|\r|\n|\u2028|\u2029/g),
+ lastLineIndex = -1,
+ lineIndex,
+ location,
+ match;
+
+ while ((match = irregularLineTerminators.exec(source)) !== null) {
+ lineIndex = linebreaks.indexOf(match[0], lastLineIndex + 1) || 0;
+
+ location = {
+ line: lineIndex + 1,
+ column: sourceLines[lineIndex].length
+ };
+
+ errors.push([node, location, "Irregular whitespace not allowed"]);
+ lastLineIndex = lineIndex;
+ }
+ }
+
return {
- "Program": function (node) {
+ "Program": function(node) {
/**
* As we can easily fire warnings for all white space issues with all the source its simpler to fire them here
* This means we can check all the application code without having to worry about issues caused in the parser tokens
* When writing this code also evaluating per node was missing out connecting tokens in some cases
* We can later filter the errors when they are found to be not an issue in nodes we don't care about
*/
- var sourceLines = context.getSourceLines();
- sourceLines.forEach(function (sourceLine, lineIndex) {
- var location,
- match = irregularWhitespace.exec(sourceLine);
-
- if (match !== null) {
- location = {
- line: lineIndex + 1,
- column: match.index
- };
-
- errors.push([node, location, "Irregular whitespace not allowed"]);
- }
- });
+ checkForIrregularWhitespace(node);
+ checkForIrregularLineTerminators(node);
},
+
"Identifier": removeInvalidNodeErrors,
"Literal": removeInvalidNodeErrors,
- "Statement": removeInvalidNodeErrors,
- "Expression": removeInvalidNodeErrors,
- "Program:exit": function () {
+ "Program:exit": function() {
// If we have any errors remaining report on them
- errors.forEach(function (error) {
- context.report.apply(this, error);
+ errors.forEach(function(error) {
+ context.report.apply(context, error);
});
}
};
};
-},{}],201:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],210:[function(require,module,exports){
/**
* @fileoverview Rule to flag usage of __iterator__ property
* @author Ian Christian Myers
*/
@@ -23614,50 +33210,45 @@
}
};
};
-},{}],202:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],211:[function(require,module,exports){
/**
* @fileoverview Rule to flag labels that are the same as an identifier
* @author Ian Christian Myers
*/
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
- function findIdentifier(scope, identifier) {
- var found = false;
-
- scope.variables.forEach(function(variable) {
- if (variable.name === identifier) {
- found = true;
- }
- });
-
- scope.references.forEach(function(reference) {
- if (reference.identifier.name === identifier) {
- found = true;
- }
- });
-
- // If we have not found the identifier in this scope, check the parent
- // scope.
- if (scope.upper && !found) {
- return findIdentifier(scope.upper, identifier);
- }
-
- return found;
+ /**
+ * Check if the identifier is present inside current scope
+ * @param {object} scope current scope
+ * @param {string} name To evaluate
+ * @returns {boolean} True if its present
+ * @private
+ */
+ function findIdentifier(scope, name) {
+ return astUtils.getVariableByName(scope, name) !== null;
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
@@ -23678,11 +33269,13 @@
};
};
-},{}],203:[function(require,module,exports){
+module.exports.schema = [];
+
+},{"../ast-utils":113}],212:[function(require,module,exports){
/**
* @fileoverview Disallow Labeled Statements
* @author Nicholas C. Zakas
*/
"use strict";
@@ -23722,38 +33315,121 @@
};
};
-},{}],204:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],213:[function(require,module,exports){
/**
* @fileoverview Rule to flag blocks with no reason to exist
* @author Brandon Mills
+ * @copyright 2015 Roberto Vidal. All rights reserved.
+ * @copyright 2014 Brandon Mills. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- return {
- "BlockStatement": function (node) {
- // Check for any occurrence of BlockStatement > BlockStatement or
- // Program > BlockStatement
- var parent = context.getAncestors().pop();
- if (parent.type === "BlockStatement" || parent.type === "Program") {
- context.report(node, "Block is nested inside another block.");
+ // A stack of lone blocks to be checked for block-level bindings
+ var loneBlocks = [],
+ ruleDef;
+
+ /**
+ * Reports a node as invalid.
+ * @param {ASTNode} node - The node to be reported.
+ * @returns {void}
+ */
+ function report(node) {
+ var parent = context.getAncestors().pop();
+ context.report(node, parent.type === "Program" ?
+ "Block is redundant." :
+ "Nested block is redundant."
+ );
+ }
+
+ /**
+ * Checks for any ocurrence of BlockStatement > BlockStatement or Program > BlockStatement
+ * @returns {boolean} True if the current node is a lone block.
+ */
+ function isLoneBlock() {
+ var parent = context.getAncestors().pop();
+ return parent.type === "BlockStatement" || parent.type === "Program";
+ }
+
+ /**
+ * Checks the enclosing block of the current node for block-level bindings,
+ * and "marks it" as valid if any.
+ * @returns {void}
+ */
+ function markLoneBlock() {
+ if (loneBlocks.length === 0) {
+ return;
+ }
+
+ var block = context.getAncestors().pop();
+
+ if (loneBlocks[loneBlocks.length - 1] === block) {
+ loneBlocks.pop();
+ }
+ }
+
+ // Default rule definition: report all lone blocks
+ ruleDef = {
+ BlockStatement: function(node) {
+ if (isLoneBlock(node)) {
+ report(node);
}
}
};
+ // ES6: report blocks without block-level bindings
+ if (context.ecmaFeatures.blockBindings || context.ecmaFeatures.classes) {
+ ruleDef = {
+ "BlockStatement": function(node) {
+ if (isLoneBlock(node)) {
+ loneBlocks.push(node);
+ }
+ },
+ "BlockStatement:exit": function(node) {
+ if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) {
+ loneBlocks.pop();
+ report(node);
+ }
+ }
+ };
+ }
+
+ if (context.ecmaFeatures.blockBindings) {
+ ruleDef.VariableDeclaration = function(node) {
+ if (node.kind === "let" || node.kind === "const") {
+ markLoneBlock(node);
+ }
+ };
+
+ ruleDef.FunctionDeclaration = function(node) {
+ if (context.getScope().isStrict) {
+ markLoneBlock(node);
+ }
+ };
+ }
+
+ if (context.ecmaFeatures.classes) {
+ ruleDef.ClassDeclaration = markLoneBlock;
+ }
+
+ return ruleDef;
};
-},{}],205:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],214:[function(require,module,exports){
/**
* @fileoverview Rule to disallow if as the only statmenet in an else block
* @author Brandon Mills
*/
"use strict";
@@ -23779,50 +33455,119 @@
}
};
};
-},{}],206:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],215:[function(require,module,exports){
/**
* @fileoverview Rule to flag creation of function inside a loop
* @author Ilya Volodin
* @copyright 2013 Ilya Volodin. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
-// Rule Definition
+// Helpers
//------------------------------------------------------------------------------
-module.exports = function(context) {
- var loopNodeTypes = [
- "ForStatement",
- "WhileStatement",
- "ForInStatement",
- "ForOfStatement",
- "DoWhileStatement"
- ];
+/**
+ * Gets the containing loop node of a specified node.
+ *
+ * We don't need to check nested functions, so this ignores those.
+ * `Scope.through` contains references of nested functions.
+ *
+ * @param {ASTNode} node - An AST node to get.
+ * @returns {ASTNode|null} The containing loop node of the specified node, or `null`.
+ */
+function getContainingLoopNode(node) {
+ var parent = node.parent;
+ while (parent) {
+ switch (parent.type) {
+ case "WhileStatement":
+ case "DoWhileStatement":
+ return parent;
- /**
- * Checks if the given node is a loop.
- * @param {ASTNode} node The AST node to check.
- * @returns {boolean} Whether or not the node is a loop.
- */
- function isLoop(node) {
- return loopNodeTypes.indexOf(node.type) > -1;
+ case "ForStatement":
+ // `init` is outside of the loop.
+ if (parent.init !== node) {
+ return parent;
+ }
+ break;
+
+ case "ForInStatement":
+ case "ForOfStatement":
+ // `right` is outside of the loop.
+ if (parent.right !== node) {
+ return parent;
+ }
+ break;
+
+ case "ArrowFunctionExpression":
+ case "FunctionExpression":
+ case "FunctionDeclaration":
+ // We don't need to check nested functions.
+ return null;
+
+ default:
+ break;
+ }
+
+ node = parent;
+ parent = node.parent;
}
+ return null;
+}
+
+/**
+ * Checks whether or not a reference refers to a variable that is block-binding in the loop.
+ * @param {ASTNode} loopNode - A containing loop node.
+ * @param {escope.Reference} reference - A reference to check.
+ * @returns {boolean} Whether or not a reference refers to a variable that is block-binding in the loop.
+ */
+function isBlockBindingsInLoop(loopNode, reference) {
+ // A reference to a `let`/`const` variable always has a resolved variable.
+ var variable = reference.resolved;
+ var definition = variable && variable.defs[0];
+ var declaration = definition && definition.parent;
+
+ return (
+ // Checks whether this is `let`/`const`.
+ declaration &&
+ declaration.type === "VariableDeclaration" &&
+ (declaration.kind === "let" || declaration.kind === "const") &&
+ // Checks whether this is in the loop.
+ declaration.range[0] > loopNode.range[0] &&
+ declaration.range[1] < loopNode.range[1]
+ );
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
/**
- * Reports if the given node has an ancestor node which is a loop.
+ * Reports such functions:
+ *
+ * - has an ancestor node which is a loop.
+ * - has a reference that refers to a variable that is block-binding in the loop.
+ *
* @param {ASTNode} node The AST node to check.
* @returns {boolean} Whether or not the node is within a loop.
*/
function checkForLoops(node) {
- var ancestors = context.getAncestors();
+ var loopNode = getContainingLoopNode(node);
+ if (!loopNode) {
+ return;
+ }
- if (ancestors.some(isLoop)) {
+ var references = context.getScope().through;
+ if (references.length > 0 && !references.every(isBlockBindingsInLoop.bind(null, loopNode))) {
context.report(node, "Don't make functions within a loop");
}
}
return {
@@ -23830,12 +33575,146 @@
"FunctionExpression": checkForLoops,
"FunctionDeclaration": checkForLoops
};
};
-},{}],207:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],216:[function(require,module,exports){
/**
+ * @fileoverview Rule to flag statements that use magic numbers (adapted from https://github.com/danielstjules/buddy.js)
+ * @author Vincent Lemeunier
+ * @copyright 2015 Vincent Lemeunier. All rights reserved.
+ *
+ * This rule was adapted from danielstjules/buddy.js
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Daniel St. Jules
+ *
+ * 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 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.
+ *
+ * See LICENSE file in root directory for full license.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var config = context.options[0] || {},
+ ignore = config.ignore || [0, 1, 2],
+ detectObjects = !!config.detectObjects,
+ enforceConst = !!config.enforceConst;
+
+ /**
+ * Returns whether the node is number literal
+ * @param {Node} node - the node literal being evaluated
+ * @returns {boolean} true if the node is a number literal
+ */
+ function isNumber(node) {
+ return typeof node.value === "number";
+ }
+
+ /**
+ * Returns whether the number should be ignored
+ * @param {number} num - the number
+ * @returns {boolean} true if the number should be ignored
+ */
+ function shouldIgnoreNumber(num) {
+ return ignore.indexOf(num) !== -1;
+ }
+
+
+ return {
+ "Literal": function(node) {
+ var parent = node.parent,
+ value = node.value,
+ raw = node.raw,
+ okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"];
+
+ if (!isNumber(node)) {
+ return;
+ }
+
+ if (parent.type === "UnaryExpression" && parent.operator === "-") {
+ node = parent;
+ parent = node.parent;
+ value = -value;
+ raw = "-" + raw;
+ }
+
+ if (shouldIgnoreNumber(value)) {
+ return;
+ }
+
+ // don't warn on parseInt() or Number.parseInt() radix
+ if (parent.type === "CallExpression" && node === parent.arguments[1] &&
+ (parent.callee.name === "parseInt" ||
+ parent.callee.type === "MemberExpression" &&
+ parent.callee.object.name === "Number" &&
+ parent.callee.property.name === "parseInt")
+ ) {
+ return;
+ }
+
+ if (parent.type === "VariableDeclarator") {
+ if (enforceConst && parent.parent.kind !== "const") {
+ context.report({
+ node: node,
+ message: "Number constants declarations must use 'const'"
+ });
+ }
+ } else if (okTypes.indexOf(parent.type) === -1) {
+ context.report({
+ node: node,
+ message: "No magic number: " + raw
+ });
+ }
+ }
+ };
+};
+
+module.exports.schema = [{
+ "type": "object",
+ "properties": {
+ "detectObjects": {
+ "type": "boolean"
+ },
+ "enforceConst": {
+ "type": "boolean"
+ },
+ "ignore": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ },
+ "uniqueItems": true
+ }
+ },
+ "additionalProperties": false
+}];
+
+},{}],217:[function(require,module,exports){
+/**
* @fileoverview Rule to enforce grouped require statements for Node.JS
* @author Raphael Pigulla
*/
"use strict";
@@ -23851,17 +33730,17 @@
*
* @returns {string[]} An array of built-in Node.js modules.
*/
function getBuiltinModules() {
// This list is generated using `require("repl")._builtinLibs.concat('repl').sort()`
- // This particular list was generated using node v0.11.9
+ // This particular list is as per nodejs v0.12.2 and iojs v0.7.1
return [
"assert", "buffer", "child_process", "cluster", "crypto",
"dgram", "dns", "domain", "events", "fs", "http", "https",
"net", "os", "path", "punycode", "querystring", "readline",
"repl", "smalloc", "stream", "string_decoder", "tls", "tty",
- "url", "util", "vm", "zlib"
+ "url", "util", "v8", "vm", "zlib"
];
}
var BUILTIN_MODULES = getBuiltinModules();
@@ -23940,11 +33819,11 @@
* @returns {boolean} True if the declarations are mixed, false if not.
*/
function isMixed(declarations) {
var contains = {};
- declarations.forEach(function (declaration) {
+ declarations.forEach(function(declaration) {
var type = getDeclarationType(declaration.init);
contains[type] = true;
});
return !!(
@@ -23960,11 +33839,11 @@
* @returns {boolean} True if the declarations are grouped, false if not.
*/
function isGrouped(declarations) {
var found = {};
- declarations.forEach(function (declaration) {
+ declarations.forEach(function(declaration) {
if (getDeclarationType(declaration.init) === DECL_REQUIRE) {
found[inferModuleType(declaration.init)] = true;
}
});
@@ -23973,12 +33852,18 @@
return {
"VariableDeclaration": function(node) {
- var grouping = !!context.options[0];
+ var grouping = false;
+ if (typeof context.options[0] === "object") {
+ grouping = context.options[0].grouping;
+ } else {
+ grouping = !!context.options[0];
+ }
+
if (isMixed(node.declarations)) {
context.report(
node,
"Do not mix 'require' and other declarations."
);
@@ -23991,55 +33876,124 @@
}
};
};
-},{}],208:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "oneOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "grouping": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ }
+];
+
+},{}],218:[function(require,module,exports){
/**
* @fileoverview Disallow mixed spaces and tabs for indentation
* @author Jary Niebur
* @copyright 2014 Nicholas C. Zakas. All rights reserved.
* @copyright 2014 Jary Niebur. All rights reserved.
+ * See LICENSE in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var smartTabs;
+ var smartTabs,
+ ignoredLocs = [];
switch (context.options[0]) {
case true: // Support old syntax, maybe add deprecation warning here
case "smart-tabs":
smartTabs = true;
break;
default:
smartTabs = false;
}
- var COMMENT_START = /^\s*\/\*/,
- MAYBE_COMMENT = /^\s*\*/;
+ /**
+ * Determines if a given line and column are before a location.
+ * @param {Location} loc The location object from an AST node.
+ * @param {int} line The line to check.
+ * @param {int} column The column to check.
+ * @returns {boolean} True if the line and column are before the location, false if not.
+ * @private
+ */
+ function beforeLoc(loc, line, column) {
+ if (line < loc.start.line) {
+ return true;
+ }
+ return line === loc.start.line && column < loc.start.column;
+ }
+ /**
+ * Determines if a given line and column are after a location.
+ * @param {Location} loc The location object from an AST node.
+ * @param {int} line The line to check.
+ * @param {int} column The column to check.
+ * @returns {boolean} True if the line and column are after the location, false if not.
+ * @private
+ */
+ function afterLoc(loc, line, column) {
+ if (line > loc.end.line) {
+ return true;
+ }
+ return line === loc.end.line && column > loc.end.column;
+ }
+
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
- "Program": function(node) {
+ "TemplateElement": function(node) {
+ ignoredLocs.push(node.loc);
+ },
+
+ "Program:exit": function(node) {
/*
* At least one space followed by a tab
* or the reverse before non-tab/-space
* characters begin.
*/
var regex = /^(?=[\t ]*(\t | \t))/,
match,
- lines = context.getSourceLines();
+ lines = context.getSourceLines(),
+ comments = context.getAllComments();
+ comments.forEach(function(comment) {
+ ignoredLocs.push(comment.loc);
+ });
+
+ ignoredLocs.sort(function(first, second) {
+ if (beforeLoc(first, second.start.line, second.start.column)) {
+ return 1;
+ }
+
+ if (beforeLoc(second, first.start.line, second.start.column)) {
+ return -1;
+ }
+
+ return 0;
+ });
+
if (smartTabs) {
/*
* At least one space followed by a tab
* before non-tab/-space characters begin.
*/
@@ -24048,24 +34002,40 @@
lines.forEach(function(line, i) {
match = regex.exec(line);
if (match) {
+ var lineNumber = i + 1,
+ column = match.index + 1;
- if (!MAYBE_COMMENT.test(line) && !COMMENT_START.test(lines[i - 1])) {
- context.report(node, { line: i + 1, column: match.index + 1 }, "Mixed spaces and tabs.");
+ for (var j = 0; j < ignoredLocs.length; j++) {
+ if (beforeLoc(ignoredLocs[j], lineNumber, column)) {
+ continue;
+ }
+ if (afterLoc(ignoredLocs[j], lineNumber, column)) {
+ continue;
+ }
+
+ return;
}
+ context.report(node, { line: lineNumber, column: column }, "Mixed spaces and tabs.");
}
});
}
};
};
-},{}],209:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["smart-tabs", true, false]
+ }
+];
+
+},{}],219:[function(require,module,exports){
/**
* @fileoverview Disallow use of multiple spaces.
* @author Nicholas C. Zakas
* @copyright 2015 Brandon Mills. All rights reserved.
* @copyright 2015 Nicholas C. Zakas. All rights reserved.
@@ -24084,11 +34054,11 @@
hasExceptions = true,
options = context.options[0],
lastCommentIndex = 0;
if (options && options.exceptions) {
- Object.keys(options.exceptions).forEach(function (key) {
+ Object.keys(options.exceptions).forEach(function(key) {
if (options.exceptions[key]) {
exceptions[key] = true;
} else {
delete exceptions[key];
}
@@ -24136,39 +34106,77 @@
var source = context.getSource(),
allComments = context.getAllComments(),
pattern = /[^\n\r\u2028\u2029 ] {2,}/g, // note: repeating space
token,
+ previousToken,
parent;
+
+ /**
+ * Creates a fix function that removes the multiple spaces between the two tokens
+ * @param {RuleFixer} leftToken left token
+ * @param {RuleFixer} rightToken right token
+ * @returns {function} fix function
+ * @private
+ */
+ function createFix(leftToken, rightToken) {
+ return function(fixer) {
+ return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");
+ };
+ }
+
while (pattern.test(source)) {
// do not flag anything inside of comments
if (!isIndexInComment(pattern.lastIndex, allComments)) {
token = context.getTokenByRangeStart(pattern.lastIndex);
-
if (token) {
+ previousToken = context.getTokenBefore(token);
+
if (hasExceptions) {
parent = context.getNodeByRangeIndex(pattern.lastIndex - 1);
}
if (!parent || !exceptions[parent.type]) {
- context.report(token, token.loc.start,
- "Multiple spaces found before '{{value}}'.",
- { value: token.value });
+ context.report({
+ node: token,
+ loc: token.loc.start,
+ message: "Multiple spaces found before '{{value}}'.",
+ data: { value: token.value },
+ fix: createFix(previousToken, token)
+ });
}
}
}
}
}
};
};
-},{}],210:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "object",
+ "patternProperties": {
+ "^([A-Z][a-z]*)+$": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],220:[function(require,module,exports){
/**
* @fileoverview Rule to flag when using multiline strings
* @author Ilya Volodin
* @copyright 2014 Nicholas C. Zakas. All rights reserved.
* @copyright 2013 Ilya Volodin. All rights reserved.
@@ -24207,11 +34215,13 @@
}
};
};
-},{}],211:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],221:[function(require,module,exports){
/**
* @fileoverview Disallows multiple blank lines.
* implementation adapted from the no-trailing-spaces rule.
* @author Greg Cochard
* @copyright 2014 Greg Cochard. All rights reserved.
@@ -24223,57 +34233,121 @@
//------------------------------------------------------------------------------
module.exports = function(context) {
// Use options.max or 2 as default
- var numLines = 2;
+ var max = 2,
+ maxEOF;
+ // store lines that appear empty but really aren't
+ var notEmpty = [];
+
if (context.options.length) {
- numLines = context.options[0].max;
+ max = context.options[0].max;
+ maxEOF = context.options[0].maxEOF;
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
- "Program": function checkBlankLines(node) {
+ "TemplateLiteral": function(node) {
+ var start = node.loc.start.line;
+ var end = node.loc.end.line;
+ while (start <= end) {
+ notEmpty.push(start);
+ start++;
+ }
+ },
+
+ "Program:exit": function checkBlankLines(node) {
var lines = context.getSourceLines(),
currentLocation = -1,
lastLocation,
blankCounter = 0,
location,
trimmedLines = lines.map(function(str) {
return str.trim();
- });
+ }),
+ firstOfEndingBlankLines;
+ // add the notEmpty lines in there with a placeholder
+ notEmpty.forEach(function(x, i) {
+ trimmedLines[i] = x;
+ });
+
+ if (typeof maxEOF === "undefined") {
+ // swallow the final newline, as some editors add it
+ // automatically and we don't want it to cause an issue
+ if (trimmedLines[trimmedLines.length - 1] === "") {
+ trimmedLines = trimmedLines.slice(0, -1);
+ }
+ firstOfEndingBlankLines = trimmedLines.length;
+ } else {
+ // save the number of the first of the last blank lines
+ firstOfEndingBlankLines = trimmedLines.length;
+ while (trimmedLines[firstOfEndingBlankLines - 1] === ""
+ && firstOfEndingBlankLines > 0) {
+ firstOfEndingBlankLines--;
+ }
+ }
+
// Aggregate and count blank lines
- do {
+ lastLocation = currentLocation;
+ currentLocation = trimmedLines.indexOf("", currentLocation + 1);
+ while (currentLocation !== -1) {
lastLocation = currentLocation;
currentLocation = trimmedLines.indexOf("", currentLocation + 1);
if (lastLocation === currentLocation - 1) {
blankCounter++;
} else {
- if (blankCounter >= numLines) {
- location = {
- line: lastLocation + 1,
- column: lines[lastLocation].length
- };
- context.report(node, location, "Multiple blank lines not allowed.");
+ location = {
+ line: lastLocation + 1,
+ column: 1
+ };
+ if (lastLocation < firstOfEndingBlankLines) {
+ // within the file, not at the end
+ if (blankCounter >= max) {
+ context.report(node, location,
+ "More than " + max + " blank " + (max === 1 ? "line" : "lines") + " not allowed.");
+ }
+ } else {
+ // inside the last blank lines
+ if (blankCounter >= maxEOF) {
+ context.report(node, location,
+ "Too many blank lines at the end of file. Max of " + maxEOF + " allowed.");
+ }
}
// Finally, reset the blank counter
blankCounter = 0;
}
- } while (currentLocation !== -1);
+ }
}
};
};
-},{}],212:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "max": {
+ "type": "integer"
+ },
+ "maxEOF": {
+ "type": "integer"
+ }
+ },
+ "required": ["max"],
+ "additionalProperties": false
+ }
+];
+
+},{}],222:[function(require,module,exports){
/**
* @fileoverview Rule to flag when re-assigning native objects
* @author Ilya Volodin
*/
@@ -24283,36 +34357,158 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var nativeObjects = ["Array", "Boolean", "Date", "decodeURI",
- "decodeURIComponent", "encodeURI", "encodeURIComponent",
- "Error", "eval", "EvalError", "Function", "isFinite",
- "isNaN", "JSON", "Math", "Number", "Object", "parseInt",
- "parseFloat", "RangeError", "ReferenceError", "RegExp",
- "String", "SyntaxError", "TypeError", "URIError",
- "Map", "NaN", "Set", "WeakMap", "Infinity", "undefined"];
+ var config = context.options[0];
+ var exceptions = (config && config.exceptions) || [];
+ /**
+ * Gets the names of writeable built-in variables.
+ * @param {escope.Scope} scope - A scope to get.
+ * @returns {object} A map that its key is variable names.
+ */
+ function getBuiltinGlobals(scope) {
+ return scope.variables.reduce(function(retv, variable) {
+ if (variable.writeable === false && variable.name !== "__proto__") {
+ retv[variable.name] = true;
+ }
+ return retv;
+ }, Object.create(null));
+ }
+
+ /**
+ * Reports if a given reference's name is same as native object's.
+ * @param {object} builtins - A map that its key is a variable name.
+ * @param {Reference} reference - A reference to check.
+ * @param {int} index - The index of the reference in the references.
+ * @param {Reference[]} references - The array that the reference belongs to.
+ * @returns {void}
+ */
+ function checkThroughReference(builtins, reference, index, references) {
+ var identifier = reference.identifier;
+
+ if (identifier &&
+ builtins[identifier.name] &&
+ exceptions.indexOf(identifier.name) === -1 &&
+ reference.init === false &&
+ reference.isWrite() &&
+ // Destructuring assignments can have multiple default value,
+ // so possibly there are multiple writeable references for the same identifier.
+ (index === 0 || references[index - 1].identifier !== identifier)
+ ) {
+ context.report(
+ identifier,
+ "{{name}} is a read-only native object.",
+ {name: identifier.name});
+ }
+ }
+
return {
+ // Checks assignments of global variables.
+ // References to implicit global variables are not resolved,
+ // so those are in the `through` of the global scope.
+ "Program": function() {
+ var globalScope = context.getScope();
+ var builtins = getBuiltinGlobals(globalScope);
+ globalScope.through.forEach(checkThroughReference.bind(null, builtins));
+ }
+ };
- "AssignmentExpression": function(node) {
- if (nativeObjects.indexOf(node.left.name) >= 0) {
- context.report(node, node.left.name + " is a read-only native object.");
+};
+
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "array",
+ "items": {"type": "string"},
+ "uniqueItems": true
}
},
+ "additionalProperties": false
+ }
+];
- "VariableDeclarator": function(node) {
- if (nativeObjects.indexOf(node.id.name) >= 0) {
- context.report(node, "Redefinition of '{{nativeObject}}'.", { nativeObject: node.id.name });
+},{}],223:[function(require,module,exports){
+/**
+ * @fileoverview Rule to disallow a negated condition
+ * @author Alberto RodrÃguez
+ * @copyright 2015 Alberto RodrÃguez. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ /**
+ * Determines if a given node is an if-else without a condition on the else
+ * @param {ASTNode} node The node to check.
+ * @returns {boolean} True if the node has an else without an if.
+ * @private
+ */
+ function hasElseWithoutCondition(node) {
+ return node.alternate && node.alternate.type !== "IfStatement";
+ }
+
+ /**
+ * Determines if a given node is a negated unary expression
+ * @param {Object} test The test object to check.
+ * @returns {boolean} True if the node is a negated unary expression.
+ * @private
+ */
+ function isNegatedUnaryExpression(test) {
+ return test.type === "UnaryExpression" && test.operator === "!";
+ }
+
+ /**
+ * Determines if a given node is a negated binary expression
+ * @param {Test} test The test to check.
+ * @returns {boolean} True if the node is a negated binary expression.
+ * @private
+ */
+ function isNegatedBinaryExpression(test) {
+ return test.type === "BinaryExpression" &&
+ (test.operator === "!=" || test.operator === "!==");
+ }
+
+ /**
+ * Determines if a given node has a negated if expression
+ * @param {ASTNode} node The node to check.
+ * @returns {boolean} True if the node has a negated if expression.
+ * @private
+ */
+ function isNegatedIf(node) {
+ return isNegatedUnaryExpression(node.test) || isNegatedBinaryExpression(node.test);
+ }
+
+ return {
+ "IfStatement": function(node) {
+ if (!hasElseWithoutCondition(node)) {
+ return;
}
+
+ if (isNegatedIf(node)) {
+ context.report(node, "Unexpected negated condition.");
+ }
+ },
+ "ConditionalExpression": function(node) {
+ if (isNegatedIf(node)) {
+ context.report(node, "Unexpected negated condition.");
+ }
}
};
-
};
-},{}],213:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],224:[function(require,module,exports){
/**
* @fileoverview A rule to disallow negated left operands of the `in` operator
* @author Michael Ficarra
*/
@@ -24333,11 +34529,13 @@
}
};
};
-},{}],214:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],225:[function(require,module,exports){
/**
* @fileoverview Rule to flag nested ternary expressions
* @author Ian Christian Myers
*/
@@ -24357,11 +34555,13 @@
}
}
};
};
-},{}],215:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],226:[function(require,module,exports){
/**
* @fileoverview Rule to flag when using new Function
* @author Ilya Volodin
*/
@@ -24371,22 +34571,36 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- return {
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
- "NewExpression": function(node) {
- if (node.callee.name === "Function") {
- context.report(node, "The Function constructor is eval.");
- }
+ /**
+ * Checks if the callee if the Function constructor, and if so, reports an issue.
+ * @param {ASTNode} node The node to check and report on
+ * @returns {void}
+ * @private
+ */
+ function validateCallee(node) {
+ if (node.callee.name === "Function") {
+ context.report(node, "The Function constructor is eval.");
}
+ }
+
+ return {
+ "NewExpression": validateCallee,
+ "CallExpression": validateCallee
};
};
-},{}],216:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],227:[function(require,module,exports){
/**
* @fileoverview A rule to disallow calls to the Object constructor
* @author Matt DuVall <http://www.mattduvall.com/>
*/
@@ -24407,11 +34621,13 @@
}
};
};
-},{}],217:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],228:[function(require,module,exports){
/**
* @fileoverview Rule to disallow use of new operator with the `require` function
* @author Wil Moore III
*/
@@ -24432,11 +34648,13 @@
}
};
};
-},{}],218:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],229:[function(require,module,exports){
/**
* @fileoverview Rule to flag when using constructor for wrapper objects
* @author Ilya Volodin
*/
@@ -24458,11 +34676,13 @@
}
};
};
-},{}],219:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],230:[function(require,module,exports){
/**
* @fileoverview Rule to flag statements with function invocation preceded by
* "new" and not part of assignment
* @author Ilya Volodin
*/
@@ -24485,11 +34705,13 @@
}
};
};
-},{}],220:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],231:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of an object property of the global object (Math and JSON) as a function
* @author James Allardice
*/
@@ -24513,11 +34735,13 @@
}
};
};
-},{}],221:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],232:[function(require,module,exports){
/**
* @fileoverview Rule to flag octal escape sequences in string literals.
* @author Ian Christian Myers
*/
@@ -24533,25 +34757,32 @@
"Literal": function(node) {
if (typeof node.value !== "string") {
return;
}
- var match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-7])/),
+
+ var match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/),
octalDigit;
if (match) {
octalDigit = match[2];
- context.report(node, "Don't use octal: '\\{{octalDigit}}'. Use '\\u....' instead.",
- { octalDigit: octalDigit });
+
+ // \0 is actually not considered an octal
+ if (match[2] !== "0" || typeof match[3] !== "undefined") {
+ context.report(node, "Don't use octal: '\\{{octalDigit}}'. Use '\\u....' instead.",
+ { octalDigit: octalDigit });
+ }
}
}
};
};
-},{}],222:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],233:[function(require,module,exports){
/**
* @fileoverview Rule to flag when initializing octal literal
* @author Ilya Volodin
*/
@@ -24572,12 +34803,152 @@
}
};
};
-},{}],223:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],234:[function(require,module,exports){
/**
+ * @fileoverview Disallow reassignment of function parameters.
+ * @author Nat Burns
+ * @copyright 2014 Nat Burns. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+var stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/;
+
+module.exports = function(context) {
+ var props = context.options[0] && Boolean(context.options[0].props);
+
+ /**
+ * Checks whether or not a reference modifies its variable.
+ * If the `props` option is `true`, this checks whether or not the reference modifies properties of its variable also.
+ * @param {Reference} reference - A reference to check.
+ * @returns {boolean} Whether or not the reference modifies its variable.
+ */
+ function isModifying(reference) {
+ if (reference.isWrite()) {
+ return true;
+ }
+
+ // Checks whether its property is modified.
+ if (props) {
+ var node = reference.identifier;
+ var parent = node.parent;
+ while (parent && !stopNodePattern.test(parent.type)) {
+ switch (parent.type) {
+ // e.g. foo.a = 0;
+ case "AssignmentExpression":
+ return parent.left === node;
+
+ // e.g. ++foo.a;
+ case "UpdateExpression":
+ return true;
+
+ // e.g. delete foo.a;
+ case "UnaryExpression":
+ if (parent.operator === "delete") {
+ return true;
+ }
+ break;
+
+ // EXCLUDES: e.g. cache.get(foo.a).b = 0;
+ case "CallExpression":
+ if (parent.callee !== node) {
+ return false;
+ }
+ break;
+
+ // EXCLUDES: e.g. cache[foo.a] = 0;
+ case "MemberExpression":
+ if (parent.property === node) {
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ node = parent;
+ parent = parent.parent;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Reports a reference if is non initializer and writable.
+ * @param {Reference} reference - A reference to check.
+ * @param {int} index - The index of the reference in the references.
+ * @param {Reference[]} references - The array that the reference belongs to.
+ * @returns {void}
+ */
+ function checkReference(reference, index, references) {
+ var identifier = reference.identifier;
+
+ if (identifier &&
+ !reference.init &&
+ isModifying(reference) &&
+ // Destructuring assignments can have multiple default value,
+ // so possibly there are multiple writeable references for the same identifier.
+ (index === 0 || references[index - 1].identifier !== identifier)
+ ) {
+ context.report(
+ identifier,
+ "Assignment to function parameter '{{name}}'.",
+ {name: identifier.name});
+ }
+ }
+
+ /**
+ * Finds and reports references that are non initializer and writable.
+ * @param {Variable} variable - A variable to check.
+ * @returns {void}
+ */
+ function checkVariable(variable) {
+ if (variable.defs[0].type === "Parameter") {
+ variable.references.forEach(checkReference);
+ }
+ }
+
+ /**
+ * Checks parameters of a given function node.
+ * @param {ASTNode} node - A function node to check.
+ * @returns {void}
+ */
+ function checkForFunction(node) {
+ context.getDeclaredVariables(node).forEach(checkVariable);
+ }
+
+ return {
+ // `:exit` is needed for the `node.parent` property of identifier nodes.
+ "FunctionDeclaration:exit": checkForFunction,
+ "FunctionExpression:exit": checkForFunction,
+ "ArrowFunctionExpression:exit": checkForFunction
+ };
+
+};
+
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "props": {"type": "boolean"}
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],235:[function(require,module,exports){
+/**
* @fileoverview Disallow string concatenation when using __dirname and __filename
* @author Nicholas C. Zakas
*/
"use strict";
@@ -24611,35 +34982,60 @@
};
};
-},{}],224:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],236:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of unary increment and decrement operators.
* @author Ian Christian Myers
+ * @author Brody McKee (github.com/mrmckeb)
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var config = context.options[0],
+ allowInForAfterthought = false;
+
+ if (typeof config === "object") {
+ allowInForAfterthought = config.allowForLoopAfterthoughts === true;
+ }
+
return {
"UpdateExpression": function(node) {
+ if (allowInForAfterthought && node.parent.type === "ForStatement") {
+ return;
+ }
context.report(node, "Unary operator '" + node.operator + "' used.");
}
};
};
-},{}],225:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "allowForLoopAfterthoughts": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],237:[function(require,module,exports){
/**
* @fileoverview Disallow the use of process.env()
* @author Vignesh Anand
* @copyright 2014 Vignesh Anand. All rights reserved.
*/
@@ -24665,11 +35061,13 @@
};
};
-},{}],226:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],238:[function(require,module,exports){
/**
* @fileoverview Disallow the use of process.exit()
* @author Nicholas C. Zakas
*/
"use strict";
@@ -24698,11 +35096,13 @@
};
};
-},{}],227:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],239:[function(require,module,exports){
/**
* @fileoverview Rule to flag usage of __proto__ property
* @author Ilya Volodin
*/
@@ -24726,11 +35126,13 @@
}
};
};
-},{}],228:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],240:[function(require,module,exports){
/**
* @fileoverview Rule to flag when the same variable is declared more then once.
* @author Ilya Volodin
*/
@@ -24739,35 +35141,93 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var options = {
+ builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals)
+ };
- function findVariables() {
- var scope = context.getScope();
-
+ /**
+ * Find variables in a given scope and flag redeclared ones.
+ * @param {Scope} scope - An escope scope object.
+ * @returns {void}
+ * @private
+ */
+ function findVariablesInScope(scope) {
scope.variables.forEach(function(variable) {
- if (variable.identifiers && variable.identifiers.length > 1) {
+ var hasBuiltin = options.builtinGlobals && "writeable" in variable;
+ var count = (hasBuiltin ? 1 : 0) + variable.identifiers.length;
+
+ if (count >= 2) {
variable.identifiers.sort(function(a, b) {
return a.range[1] - b.range[1];
});
- for (var i = 1, l = variable.identifiers.length; i < l; i++) {
- context.report(variable.identifiers[i], "{{a}} is already defined", {a: variable.name});
+ for (var i = (hasBuiltin ? 0 : 1), l = variable.identifiers.length; i < l; i++) {
+ context.report(
+ variable.identifiers[i],
+ "\"{{a}}\" is already defined",
+ {a: variable.name});
}
}
});
+
}
- return {
- "Program": findVariables,
- "FunctionExpression": findVariables,
- "FunctionDeclaration": findVariables
- };
+ /**
+ * Find variables in the current scope.
+ * @returns {void}
+ * @private
+ */
+ function checkForGlobal() {
+ var scope = context.getScope();
+
+ // Nodejs env or modules has a special scope.
+ if (context.ecmaFeatures.globalReturn || context.ecmaFeatures.modules) {
+ findVariablesInScope(scope.childScopes[0]);
+ } else {
+ findVariablesInScope(scope);
+ }
+ }
+
+ /**
+ * Find variables in the current scope.
+ * @returns {void}
+ * @private
+ */
+ function checkForBlock() {
+ findVariablesInScope(context.getScope());
+ }
+
+ if (context.ecmaFeatures.blockBindings) {
+ return {
+ "Program": checkForGlobal,
+ "BlockStatement": checkForBlock,
+ "SwitchStatement": checkForBlock
+ };
+ } else {
+ return {
+ "Program": checkForGlobal,
+ "FunctionDeclaration": checkForBlock,
+ "FunctionExpression": checkForBlock,
+ "ArrowFunctionExpression": checkForBlock
+ };
+ }
};
-},{}],229:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "builtinGlobals": {"type": "boolean"}
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],241:[function(require,module,exports){
/**
* @fileoverview Rule to count multiple spaces in regular expressions
* @author Matt DuVall <http://www.mattduvall.com/>
*/
@@ -24798,78 +35258,24 @@
}
};
};
-},{}],230:[function(require,module,exports){
-/**
- * @fileoverview Rule to disallow reserved words being used as keys
- * @author Emil Bay
- * @copyright 2014 Emil Bay. All rights reserved.
- */
+module.exports.schema = [];
-"use strict";
-
-//------------------------------------------------------------------------------
-// Rule Definition
-//------------------------------------------------------------------------------
-
-module.exports = function(context) {
-
- var MESSAGE = "Reserved word '{{key}}' used as key.";
-
- var reservedWords = [
- "abstract",
- "boolean", "break", "byte",
- "case", "catch", "char", "class", "const", "continue",
- "debugger", "default", "delete", "do", "double",
- "else", "enum", "export", "extends",
- "final", "finally", "float", "for", "function",
- "goto",
- "if", "implements", "import", "in", "instanceof", "int", "interface",
- "long",
- "native", "new",
- "package", "private", "protected", "public",
- "return",
- "short", "static", "super", "switch", "synchronized",
- "this", "throw", "throws", "transient", "try", "typeof",
- "var", "void", "volatile",
- "while", "with"
- ];
-
- return {
-
- "ObjectExpression": function(node) {
- node.properties.forEach(function(property) {
-
- if (property.key.type === "Identifier") {
- var keyName = property.key.name;
-
- if (reservedWords.indexOf("" + keyName) !== -1) {
- context.report(node, MESSAGE, { key: keyName });
- }
- }
-
- });
-
- }
- };
-
-};
-
-},{}],231:[function(require,module,exports){
+},{}],242:[function(require,module,exports){
/**
* @fileoverview Restrict usage of specified node modules.
* @author Christian Schulz
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
+module.exports = function(context) {
// trim restricted module names
var restrictedModules = context.options;
// if no modules are restricted we don't need to check the CallExpressions
if (restrictedModules.length === 0) {
@@ -24914,11 +35320,11 @@
return moduleName;
}
return {
- "CallExpression": function (node) {
+ "CallExpression": function(node) {
if (isRequireCall(node)) {
var restrictedModuleName = getRestrictedModuleName(node);
if (restrictedModuleName) {
context.report(node, "'{{moduleName}}' module is restricted from being used.", {
@@ -24928,41 +35334,133 @@
}
}
};
};
-},{}],232:[function(require,module,exports){
+module.exports.schema = {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ }
+ ],
+ "additionalItems": {
+ "type": "string"
+ },
+ "uniqueItems": true
+};
+
+},{}],243:[function(require,module,exports){
/**
+ * @fileoverview Rule to flag use of certain node types
+ * @author Burak Yigit Kaya
+ * @copyright 2015 Burak Yigit Kaya. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+var nodeTypes = require("espree").Syntax;
+
+module.exports = function(context) {
+ /**
+ * Generates a warning from the provided node, saying that node type is not allowed.
+ * @param {ASTNode} node The node to warn on
+ * @returns {void}
+ */
+ function warn(node) {
+ context.report(node, "Using \"{{type}}\" is not allowed.", node);
+ }
+
+ return context.options.reduce(function(result, nodeType) {
+ result[nodeType] = warn;
+
+ return result;
+ }, {});
+
+};
+
+module.exports.schema = {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ },
+ {
+ "enum": Object.keys(nodeTypes).map(function(k) {
+ return nodeTypes[k];
+ })
+ }
+ ],
+ "uniqueItems": true,
+ "minItems": 1
+};
+
+},{"espree":"espree"}],244:[function(require,module,exports){
+/**
* @fileoverview Rule to flag when return statement contains assignment
* @author Ilya Volodin
*/
"use strict";
//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether or not a node is an `AssignmentExpression`.
+ * @param {Node|null} node - A node to check.
+ * @returns {boolean} Whether or not the node is an `AssignmentExpression`.
+ */
+function isAssignment(node) {
+ return node && node.type === "AssignmentExpression";
+}
+
+/**
+ * Checks whether or not a node is enclosed in parentheses.
+ * @param {Node|null} node - A node to check.
+ * @param {RuleContext} context - The current context.
+ * @returns {boolean} Whether or not the node is enclosed in parentheses.
+ */
+function isEnclosedInParens(node, context) {
+ var prevToken = context.getTokenBefore(node);
+ var nextToken = context.getTokenAfter(node);
+
+ return prevToken.value === "(" && nextToken.value === ")";
+}
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var always = (context.options[0] || "except-parens") !== "except-parens";
return {
-
"ReturnStatement": function(node) {
- if (node.argument && node.argument.type === "AssignmentExpression") {
+ if (isAssignment(node.argument) && (always || !isEnclosedInParens(node.argument, context))) {
context.report(node, "Return statement should not contain assignment.");
}
}
};
-
};
-},{}],233:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["except-parens", "always"]
+ }
+];
+
+},{}],245:[function(require,module,exports){
/**
* @fileoverview Rule to flag when using javascript: urls
* @author Ilya Volodin
*/
-/*jshint scripturl: true */
-/*eslint no-script-url: 0*/
+/* jshint scripturl: true */
+/* eslint no-script-url: 0 */
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
@@ -24986,11 +35484,13 @@
}
};
};
-},{}],234:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],246:[function(require,module,exports){
/**
* @fileoverview Rule to flag comparison where left part is the same as the right
* part.
* @author Ilya Volodin
*/
@@ -25015,11 +35515,13 @@
}
};
};
-},{}],235:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],247:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of comma operator
* @author Brandon Mills
*/
@@ -25052,11 +35554,11 @@
* parens, e.g. the test of an if statement.
* @param {ASTNode} node - The AST node
* @returns {boolean} True if parens around node belong to parent node.
*/
function requiresExtraParens(node) {
- return node.parent && parenthesized[node.parent.type] != null &&
+ return node.parent && parenthesized[node.parent.type] &&
node === node.parent[parenthesized[node.parent.type]];
}
/**
* Check if a node is wrapped in parens.
@@ -25103,17 +35605,20 @@
if (isParenthesised(node)) {
return;
}
}
- context.report(node, "Unexpected use of comma operator.");
+ var child = context.getTokenAfter(node.expressions[0]);
+ context.report(node, child.loc.start, "Unexpected use of comma operator.");
}
};
};
-},{}],236:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],248:[function(require,module,exports){
/**
* @fileoverview Disallow shadowing of NaN, undefined, and Infinity (ES5 section 15.1.1)
* @author Michael Ficarra
* @copyright 2013 Michael Ficarra. All rights reserved.
*/
@@ -25125,10 +35630,16 @@
module.exports = function(context) {
var RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"];
+ /**
+ * Check if the node name is present inside the restricted list
+ * @param {ASTNode} id id to evaluate
+ * @returns {void}
+ * @private
+ */
function checkForViolation(id) {
if (RESTRICTED.indexOf(id.name) > -1) {
context.report(id, "Shadowing of global property \"" + id.name + "\".");
}
}
@@ -25148,190 +35659,200 @@
checkForViolation(node.id);
}
[].map.call(node.params, checkForViolation);
},
"FunctionDeclaration": function(node) {
- checkForViolation(node.id);
- [].map.call(node.params, checkForViolation);
+ if (node.id) {
+ checkForViolation(node.id);
+ [].map.call(node.params, checkForViolation);
+ }
},
"CatchClause": function(node) {
checkForViolation(node.param);
}
};
};
-},{}],237:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],249:[function(require,module,exports){
/**
* @fileoverview Rule to flag on declaring variables already declared in the outer scope
* @author Ilya Volodin
* @copyright 2013 Ilya Volodin. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
-// Rule Definition
+// Requirements
//------------------------------------------------------------------------------
-module.exports = function(context) {
+var astUtils = require("../ast-utils");
- /**
- * Checks if a variable is contained in the list of given scope variables.
- * @param {Object} variable The variable to check.
- * @param {Array} scopeVars The scope variables to look for.
- * @returns {boolean} Whether or not the variable is contains in the list of scope variables.
- */
- function isContainedInScopeVars(variable, scopeVars) {
- return scopeVars.some(function (scopeVar) {
- if (scopeVar.identifiers.length > 0) {
- return variable.name === scopeVar.name;
- }
- return false;
- });
- }
-
- /**
- * Checks if the given variables are shadowed in the given scope.
- * @param {Array} variables The variables to look for
- * @param {Object} scope The scope to be checked.
- * @returns {void}
- */
- function checkShadowsInScope(variables, scope) {
- variables.forEach(function (variable) {
- if (isContainedInScopeVars(variable, scope.variables) &&
- // "arguments" is a special case that has no identifiers (#1759)
- variable.identifiers.length > 0
- ) {
-
- context.report(variable.identifiers[0], "{{a}} is already declared in the upper scope.", {a: variable.name});
- }
- });
- }
-
- /**
- * Checks the current context for shadowed variables.
- * @returns {void}
- */
- function checkForShadows() {
- var scope = context.getScope(),
- variables = scope.variables;
-
- // iterate through the array of variables and find duplicates with the upper scope
- var upper = scope.upper;
- while (upper) {
- checkShadowsInScope(variables, upper);
- upper = upper.upper;
- }
- }
-
- return {
- "FunctionDeclaration": checkForShadows,
- "FunctionExpression": checkForShadows
- };
-
-};
-
-},{}],238:[function(require,module,exports){
-/**
- * @fileoverview Rule to disallow whitespace before the semicolon
- * @author Jonathan Kingston
- * @copyright 2015 Mathias Schreck
- * @copyright 2014 Jonathan Kingston
- */
-
-"use strict";
-
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var options = {
+ builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals),
+ hoist: (context.options[0] && context.options[0].hoist) || "functions",
+ allow: (context.options[0] && context.options[0].allow) || []
+ };
+
/**
- * Determines whether two adjacent tokens are have whitespace between them.
- * @param {Object} left - The left token object.
- * @param {Object} right - The right token object.
- * @returns {boolean} Whether or not there is space between the tokens.
+ * Check if variable name is allowed.
+ *
+ * @param {ASTNode} variable The variable to check.
+ * @returns {boolean} Whether or not the variable name is allowed.
*/
- function isSpaced(left, right) {
- return left.range[1] < right.range[0];
+ function isAllowed(variable) {
+ return options.allow.indexOf(variable.name) !== -1;
}
/**
- * Checks whether two tokens are on the same line.
- * @param {Object} left The leftmost token.
- * @param {Object} right The rightmost token.
- * @returns {boolean} True if the tokens are on the same line, false if not.
- * @private
+ * Checks if a variable of the class name in the class scope of ClassDeclaration.
+ *
+ * ClassDeclaration creates two variables of its name into its outer scope and its class scope.
+ * So we should ignore the variable in the class scope.
+ *
+ * @param {Object} variable The variable to check.
+ * @returns {boolean} Whether or not the variable of the class name in the class scope of ClassDeclaration.
*/
- function isSameLine(left, right) {
- return left.loc.end.line === right.loc.start.line;
+ function isDuplicatedClassNameVariable(variable) {
+ var block = variable.scope.block;
+ return block.type === "ClassDeclaration" && block.id === variable.identifiers[0];
}
/**
- * Checks if a given token has leading whitespace.
- * @param {Object} token The token to check.
- * @returns {boolean} True if the given token has leading space, false if not.
+ * Checks if a variable is inside the initializer of scopeVar.
+ *
+ * To avoid reporting at declarations such as `var a = function a() {};`.
+ * But it should report `var a = function(a) {};` or `var a = function() { function a() {} };`.
+ *
+ * @param {Object} variable The variable to check.
+ * @param {Object} scopeVar The scope variable to look for.
+ * @returns {boolean} Whether or not the variable is inside initializer of scopeVar.
*/
- function hasLeadingSpace(token) {
- var tokenBefore = context.getTokenBefore(token);
- return isSameLine(tokenBefore, token) && isSpaced(tokenBefore, token);
+ function isOnInitializer(variable, scopeVar) {
+ var outerScope = scopeVar.scope;
+ var outerDef = scopeVar.defs[0];
+ var outer = outerDef && outerDef.parent && outerDef.parent.range;
+ var innerScope = variable.scope;
+ var innerDef = variable.defs[0];
+ var inner = innerDef && innerDef.name.range;
+
+ return (
+ outer &&
+ inner &&
+ outer[0] < inner[0] &&
+ inner[1] < outer[1] &&
+ ((innerDef.type === "FunctionName" && innerDef.node.type === "FunctionExpression") || innerDef.node.type === "ClassExpression") &&
+ outerScope === innerScope.upper
+ );
}
/**
- * Checks if the given token is a semicolon.
- * @param {Token} token The token to check.
- * @returns {boolean} Whether or not the given token is a semicolon.
+ * Get a range of a variable's identifier node.
+ * @param {Object} variable The variable to get.
+ * @returns {Array|undefined} The range of the variable's identifier node.
*/
- function isSemicolon(token) {
- return token.type === "Punctuator" && token.value === ";";
+ function getNameRange(variable) {
+ var def = variable.defs[0];
+ return def && def.name.range;
}
/**
- * Reports if the given token has leading space.
- * @param {Token} token The semicolon token to check.
- * @param {ASTNode} node The corresponding node of the token.
- * @returns {void}
+ * Checks if a variable is in TDZ of scopeVar.
+ * @param {Object} variable The variable to check.
+ * @param {Object} scopeVar The variable of TDZ.
+ * @returns {boolean} Whether or not the variable is in TDZ of scopeVar.
*/
- function checkSemiTokenForLeadingSpace(token, node) {
- if (isSemicolon(token) && hasLeadingSpace(token)) {
- context.report(node, token.loc.start, "Unexpected whitespace before semicolon.");
- }
+ function isInTdz(variable, scopeVar) {
+ var outerDef = scopeVar.defs[0];
+ var inner = getNameRange(variable);
+ var outer = getNameRange(scopeVar);
+ return (
+ inner &&
+ outer &&
+ inner[1] < outer[0] &&
+ // Excepts FunctionDeclaration if is {"hoist":"function"}.
+ (options.hoist !== "functions" || !outerDef || outerDef.node.type !== "FunctionDeclaration")
+ );
}
/**
- * Checks leading space before the semicolon with the assumption that the last token is the semicolon.
- * @param {ASTNode} node The node to check.
+ * Checks the current context for shadowed variables.
+ * @param {Scope} scope - Fixme
* @returns {void}
*/
- function checkNode(node) {
- var token = context.getLastToken(node);
- checkSemiTokenForLeadingSpace(token, node);
+ function checkForShadows(scope) {
+ var variables = scope.variables;
+ for (var i = 0; i < variables.length; ++i) {
+ var variable = variables[i];
+
+ // Skips "arguments" or variables of a class name in the class scope of ClassDeclaration.
+ if (variable.identifiers.length === 0 ||
+ isDuplicatedClassNameVariable(variable) ||
+ isAllowed(variable)
+ ) {
+ continue;
+ }
+
+ // Gets shadowed variable.
+ var shadowed = astUtils.getVariableByName(scope.upper, variable.name);
+ if (shadowed &&
+ (shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) &&
+ !isOnInitializer(variable, shadowed) &&
+ !(options.hoist !== "all" && isInTdz(variable, shadowed))
+ ) {
+ context.report({
+ node: variable.identifiers[0],
+ message: "\"{{name}}\" is already declared in the upper scope.",
+ data: variable
+ });
+ }
+ }
}
return {
- "VariableDeclaration": checkNode,
- "ExpressionStatement": checkNode,
- "BreakStatement": checkNode,
- "ContinueStatement": checkNode,
- "DebuggerStatement": checkNode,
- "ReturnStatement": checkNode,
- "ThrowStatement": checkNode,
- "ForStatement": function (node) {
- if (node.init) {
- checkSemiTokenForLeadingSpace(context.getTokenAfter(node.init), node);
- }
+ "Program:exit": function() {
+ var globalScope = context.getScope();
+ var stack = globalScope.childScopes.slice();
+ var scope;
- if (node.test) {
- checkSemiTokenForLeadingSpace(context.getTokenAfter(node.test), node);
+ while (stack.length) {
+ scope = stack.pop();
+ stack.push.apply(stack, scope.childScopes);
+ checkForShadows(scope);
}
}
};
+
};
-},{}],239:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "builtinGlobals": {"type": "boolean"},
+ "hoist": {"enum": ["all", "functions", "never"]},
+ "allow": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],250:[function(require,module,exports){
/**
* @fileoverview Rule to check that spaced function application
* @author Matt DuVall <http://www.mattduvall.com>
*/
@@ -25341,34 +35862,55 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var sourceCode = context.getSourceCode();
+
+ /**
+ * Check if open space is present in a function name
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function detectOpenSpaces(node) {
- var lastCalleeToken = context.getLastToken(node.callee);
- var tokens = context.getTokens(node);
- var i = tokens.indexOf(lastCalleeToken), l = tokens.length;
- while (i < l && tokens[i].value !== "(") {
- ++i;
- }
- if (i >= l) {
+ var lastCalleeToken = sourceCode.getLastToken(node.callee),
+ prevToken = lastCalleeToken,
+ parenToken = sourceCode.getTokenAfter(lastCalleeToken);
+
+ if (sourceCode.getLastToken(node).value !== ")") {
return;
}
+
+ while (parenToken.value !== "(") {
+ prevToken = parenToken;
+ parenToken = sourceCode.getTokenAfter(parenToken);
+ }
+
// look for a space between the callee and the open paren
- if (tokens[i - 1].range[1] !== tokens[i].range[0]) {
- context.report(node, "Unexpected space between function name and paren.");
+ if (sourceCode.isSpaceBetweenTokens(prevToken, parenToken)) {
+ context.report({
+ node: node,
+ loc: lastCalleeToken.loc.start,
+ message: "Unexpected space between function name and paren.",
+ fix: function(fixer) {
+ return fixer.removeRange([prevToken.range[1], parenToken.range[0]]);
+ }
+ });
}
}
return {
"CallExpression": detectOpenSpaces,
"NewExpression": detectOpenSpaces
};
};
-},{}],240:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],251:[function(require,module,exports){
/**
* @fileoverview Disallow sparse arrays
* @author Nicholas C. Zakas
*/
"use strict";
@@ -25397,17 +35939,19 @@
};
};
-},{}],241:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],252:[function(require,module,exports){
/**
* @fileoverview Rule to check for properties whose identifier ends with the string Sync
* @author Matt DuVall<http://mattduvall.com/>
*/
-/*jshint node:true*/
+/* jshint node:true */
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
@@ -25427,11 +35971,13 @@
}
};
};
-},{}],242:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],253:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of ternary operators.
* @author Ian Christian Myers
*/
@@ -25451,31 +35997,216 @@
};
};
-},{}],243:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],254:[function(require,module,exports){
/**
+ * @fileoverview A rule to disallow using `this`/`super` before `super()`.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ /**
+ * Searches a class node that a node is belonging to.
+ * @param {Node} node - A node to start searching.
+ * @returns {ClassDeclaration|ClassExpression|null} the found class node, or `null`.
+ */
+ function getClassInAncestor(node) {
+ while (node) {
+ if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
+ return node;
+ }
+ node = node.parent;
+ }
+ /* istanbul ignore next */
+ return null;
+ }
+
+ /**
+ * Checks whether or not a node is the null literal.
+ * @param {Node} node - A node to check.
+ * @returns {boolean} whether or not a node is the null literal.
+ */
+ function isNullLiteral(node) {
+ return node && node.type === "Literal" && node.value === null;
+ }
+
+ /**
+ * Checks whether or not a node is the callee of a call expression.
+ * @param {Node} node - A node to check.
+ * @returns {boolean} whether or not a node is the callee of a call expression.
+ */
+ function isCallee(node) {
+ return node && node.parent.type === "CallExpression" && node.parent.callee === node;
+ }
+
+ /**
+ * Checks whether or not the current traversal context is before `super()`.
+ * @param {object} item - A checking context.
+ * @returns {boolean} whether or not the current traversal context is before `super()`.
+ */
+ function isBeforeSuperCalling(item) {
+ return (
+ item &&
+ item.scope === context.getScope().variableScope.upper.variableScope &&
+ item.superCalled === false
+ );
+ }
+
+ var stack = [];
+
+ return {
+ /**
+ * Start checking.
+ * @param {MethodDefinition} node - A target node.
+ * @returns {void}
+ */
+ "MethodDefinition": function(node) {
+ if (node.kind !== "constructor") {
+ return;
+ }
+ stack.push({
+ thisOrSuperBeforeSuperCalled: [],
+ superCalled: false,
+ scope: context.getScope().variableScope
+ });
+ },
+
+ /**
+ * Treats the result of checking and reports invalid `this`/`super`.
+ * @param {MethodDefinition} node - A target node.
+ * @returns {void}
+ */
+ "MethodDefinition:exit": function(node) {
+ if (node.kind !== "constructor") {
+ return;
+ }
+ var result = stack.pop();
+
+ // Skip if it has no extends or `extends null`.
+ var classNode = getClassInAncestor(node);
+ if (!classNode || !classNode.superClass || isNullLiteral(classNode.superClass)) {
+ return;
+ }
+
+ // Reports.
+ result.thisOrSuperBeforeSuperCalled.forEach(function(thisOrSuper) {
+ var type = (thisOrSuper.type === "Super" ? "super" : "this");
+ context.report(thisOrSuper, "\"{{type}}\" is not allowed before super()", {type: type});
+ });
+ },
+
+ /**
+ * Marks the node if is before `super()`.
+ * @param {ThisExpression} node - A target node.
+ * @returns {void}
+ */
+ "ThisExpression": function(node) {
+ var item = stack[stack.length - 1];
+ if (isBeforeSuperCalling(item)) {
+ item.thisOrSuperBeforeSuperCalled.push(node);
+ }
+ },
+
+ /**
+ * Marks the node if is before `super()`. (exclude `super()` itself)
+ * @param {Super} node - A target node.
+ * @returns {void}
+ */
+ "Super": function(node) {
+ var item = stack[stack.length - 1];
+ if (isBeforeSuperCalling(item) && isCallee(node) === false) {
+ item.thisOrSuperBeforeSuperCalled.push(node);
+ }
+ },
+
+ /**
+ * Marks `super()` called.
+ * To catch `super(this.a);`, marks on `CallExpression:exit`.
+ * @param {CallExpression} node - A target node.
+ * @returns {void}
+ */
+ "CallExpression:exit": function(node) {
+ var item = stack[stack.length - 1];
+ if (isBeforeSuperCalling(item) && node.callee.type === "Super") {
+ item.superCalled = true;
+ }
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{}],255:[function(require,module,exports){
+/**
* @fileoverview Rule to restrict what can be thrown as an exception.
* @author Dieter Oberkofler
+ * @copyright 2015 Ian VanSchooten. All rights reserved.
* @copyright 2015 Dieter Oberkofler. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Determine if a node has a possiblity to be an Error object
+ * @param {ASTNode} node ASTNode to check
+ * @returns {boolean} True if there is a chance it contains an Error obj
+ */
+function couldBeError(node) {
+ switch (node.type) {
+ case "Identifier":
+ case "CallExpression":
+ case "NewExpression":
+ case "MemberExpression":
+ case "TaggedTemplateExpression":
+ case "YieldExpression":
+ return true; // possibly an error object.
+
+ case "AssignmentExpression":
+ return couldBeError(node.right);
+
+ case "SequenceExpression":
+ var exprs = node.expressions;
+ return exprs.length !== 0 && couldBeError(exprs[exprs.length - 1]);
+
+ case "LogicalExpression":
+ return couldBeError(node.left) || couldBeError(node.right);
+
+ case "ConditionalExpression":
+ return couldBeError(node.consequent) || couldBeError(node.alternate);
+
+ default:
+ return false;
+ }
+}
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
return {
"ThrowStatement": function(node) {
-
- if (node.argument.type === "Literal") {
- context.report(node, "Do not throw a literal.");
+ if (!couldBeError(node.argument)) {
+ context.report(node, "Expected an object to be thrown.");
} else if (node.argument.type === "Identifier") {
if (node.argument.name === "undefined") {
context.report(node, "Do not throw undefined.");
}
}
@@ -25484,62 +36215,126 @@
};
};
-},{}],244:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],256:[function(require,module,exports){
/**
* @fileoverview Disallow trailing spaces at the end of lines.
* @author Nodeca Team <https://github.com/nodeca>
+ * @copyright 2015 Greg Cochard
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var TRAILER = "[ \t\u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]+$";
+ var BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]",
+ SKIP_BLANK = "^" + BLANK_CLASS + "*$",
+ NONBLANK = BLANK_CLASS + "+$";
+ var options = context.options[0] || {},
+ skipBlankLines = options.skipBlankLines || false;
+
+ /**
+ * Report the error message
+ * @param {ASTNode} node node to report
+ * @param {int[]} location range information
+ * @param {int[]} fixRange Range based on the whole program
+ * @returns {void}
+ */
+ function report(node, location, fixRange) {
+ // Passing node is a bit dirty, because message data will contain
+ // big text in `source`. But... who cares :) ?
+ // One more kludge will not make worse the bloody wizardry of this plugin.
+ context.report({
+ node: node,
+ loc: location,
+ message: "Trailing spaces not allowed.",
+ fix: function(fixer) {
+ return fixer.removeRange(fixRange);
+ }
+ });
+ }
+
+
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
"Program": function checkTrailingSpaces(node) {
- // Let's hack. Since Esprima does not return whitespace nodes,
- // fetch the source code and do black magic via regexps.
+ // Let's hack. Since Espree does not return whitespace nodes,
+ // fetch the source code and do matching via regexps.
var src = context.getSource(),
- re = new RegExp(TRAILER, "mg"),
- match, lines, location;
+ re = new RegExp(NONBLANK),
+ skipMatch = new RegExp(SKIP_BLANK),
+ matches, lines = src.split(/\r?\n/),
+ linebreaks = context.getSource().match(/\r\n|\r|\n|\u2028|\u2029/g),
+ location,
+ totalLength = 0,
+ fixRange = [];
- while ((match = re.exec(src)) !== null) {
- lines = src.slice(0, re.lastIndex).split(/\r?\n/g);
+ for (var i = 0, ii = lines.length; i < ii; i++) {
+ matches = re.exec(lines[i]);
- location = {
- line: lines.length,
- column: lines[lines.length - 1].length - match[0].length + 1
- };
+ // Always add linebreak length to line length to accommodate for line break (\n or \r\n)
+ // Because during the fix time they also reserve one spot in the array.
+ // Usually linebreak length is 2 for \r\n (CRLF) and 1 for \n (LF)
+ var linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1;
+ var lineLength = lines[i].length + linebreakLength;
- // Passing node is a bit dirty, because message data will contain
- // big text in `source`. But... who cares :) ?
- // One more kludge will not make worse the bloody wizardry of this plugin.
- context.report(node, location, "Trailing spaces not allowed.");
+ if (matches) {
+
+ // If the line has only whitespace, and skipBlankLines
+ // is true, don't report it
+ if (skipBlankLines && skipMatch.test(lines[i])) {
+ continue;
+ }
+ location = {
+ line: i + 1,
+ column: matches.index
+ };
+
+ fixRange = [totalLength + location.column, totalLength + lineLength - linebreakLength];
+
+ report(node, location, fixRange);
+ }
+
+ totalLength += lineLength;
}
}
};
};
-},{}],245:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "skipBlankLines": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],257:[function(require,module,exports){
/**
* @fileoverview Rule to flag when initializing to undefined
* @author Ilya Volodin
+ * @copyright 2013 Ilya Volodin. All rights reserved.
+ * See LICENSE in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
@@ -25549,34 +36344,50 @@
module.exports = function(context) {
return {
"VariableDeclarator": function(node) {
- var name = node.id.name;
- var init = node.init && node.init.name;
+ var name = node.id.name,
+ init = node.init && node.init.name;
- if (init === "undefined") {
+ if (init === "undefined" && node.parent.kind !== "const") {
context.report(node, "It's not necessary to initialize '{{name}}' to undefined.", { name: name });
}
}
};
};
-},{}],246:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],258:[function(require,module,exports){
/**
* @fileoverview Rule to flag references to undeclared variables.
* @author Mark Macdonald
* @copyright 2015 Nicholas C. Zakas. All rights reserved.
* @copyright 2013 Mark Macdonald. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+/**
+ * Check if a variable is an implicit declaration
+ * @param {ASTNode} variable node to evaluate
+ * @returns {boolean} True if its an implicit declaration
+ * @private
+ */
function isImplicitGlobal(variable) {
return variable.defs.every(function(def) {
return def.type === "ImplicitGlobalVariable";
});
}
@@ -25586,22 +36397,17 @@
* @param {Scope} scope The scope in which to search.
* @param {Reference} ref The reference to find in the scope.
* @returns {Variable} The variable, or null if ref refers to an undeclared variable.
*/
function getDeclaredGlobalVariable(scope, ref) {
- var declaredGlobal = null;
- scope.variables.some(function(variable) {
- if (variable.name === ref.identifier.name) {
- // If it's an implicit global, it must have a `writeable` field (indicating it was declared)
- if (!isImplicitGlobal(variable) || {}.hasOwnProperty.call(variable, "writeable")) {
- declaredGlobal = variable;
- return true;
- }
- }
- return false;
- });
- return declaredGlobal;
+ var variable = astUtils.getVariableByName(scope, ref.identifier.name);
+
+ // If it's an implicit global, it must have a `writeable` field (indicating it was declared)
+ if (variable && (!isImplicitGlobal(variable) || hasOwnProperty.call(variable, "writeable"))) {
+ return variable;
+ }
+ return null;
}
/**
* Checks if the given node is the argument of a typeof operator.
* @param {ASTNode} node The AST node being checked.
@@ -25610,88 +36416,62 @@
function hasTypeOfOperator(node) {
var parent = node.parent;
return parent.type === "UnaryExpression" && parent.operator === "typeof";
}
-/**
- * Checks if a node name match the JSX tag convention.
- * @param {String} name - Name of the node to check.
- * @returns {boolean} Whether or not the node name match the JSX tag convention.
- */
-var tagConvention = /^[a-z]|\-/;
-function isTagName(name) {
- return tagConvention.test(name);
-}
-
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var NOT_DEFINED_MESSAGE = "'{{name}}' is not defined.",
- READ_ONLY_MESSAGE = "'{{name}}' is read only.";
+ var NOT_DEFINED_MESSAGE = "\"{{name}}\" is not defined.",
+ READ_ONLY_MESSAGE = "\"{{name}}\" is read only.";
- /**
- * Compare an identifier with the variables declared in the scope
- * @param {ASTNode} node - Identifier or JSXIdentifier node
- * @returns {void}
- */
- function checkIdentifierInJSX(node) {
- var scope = context.getScope(),
- variables = scope.variables,
- i,
- len;
+ var options = context.options[0];
+ var considerTypeOf = options && options.typeof === true || false;
- while (scope.type !== "global") {
- scope = scope.upper;
- variables = scope.variables.concat(variables);
- }
-
- for (i = 0, len = variables.length; i < len; i++) {
-
- if (variables[i].name === node.name) {
- return;
- }
- }
-
- context.report(node, NOT_DEFINED_MESSAGE, { name: node.name });
- }
-
return {
- "Program:exit": function(/*node*/) {
+ "Program:exit": function(/* node */) {
var globalScope = context.getScope();
globalScope.through.forEach(function(ref) {
var variable = getDeclaredGlobalVariable(globalScope, ref),
name = ref.identifier.name;
- if (hasTypeOfOperator(ref.identifier)) {
+ if (hasTypeOfOperator(ref.identifier) && !considerTypeOf) {
return;
}
if (!variable) {
context.report(ref.identifier, NOT_DEFINED_MESSAGE, { name: name });
} else if (ref.isWrite() && variable.writeable === false) {
context.report(ref.identifier, READ_ONLY_MESSAGE, { name: name });
}
});
- },
- "JSXOpeningElement": function(node) {
- if (!isTagName(node.name.name)) {
- checkIdentifierInJSX(node.name);
- }
}
};
};
-},{}],247:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "typeof": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],259:[function(require,module,exports){
/**
* @fileoverview Rule to flag references to the undefined variable.
* @author Michael Ficarra
*/
"use strict";
@@ -25714,11 +36494,13 @@
}
};
};
-},{}],248:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],260:[function(require,module,exports){
/**
* @fileoverview Rule to flag trailing underscores in variable declarations.
* @author Matt DuVall <http://www.mattduvall.com>
*/
@@ -25728,52 +36510,104 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var ALLOWED_VARIABLES = context.options[0] && context.options[0].allow ? context.options[0].allow : [];
+
//-------------------------------------------------------------------------
// Helpers
//-------------------------------------------------------------------------
+ /**
+ * Check if identifier is present inside the allowed option
+ * @param {string} identifier name of the node
+ * @returns {boolean} true if its is present
+ * @private
+ */
+ function isAllowed(identifier) {
+ return ALLOWED_VARIABLES.some(function(ident) {
+ return ident === identifier;
+ });
+ }
+
+ /**
+ * Check if identifier has a underscore at the end
+ * @param {ASTNode} identifier node to evaluate
+ * @returns {boolean} true if its is present
+ * @private
+ */
function hasTrailingUnderscore(identifier) {
var len = identifier.length;
return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_");
}
+ /**
+ * Check if identifier is a special case member expression
+ * @param {ASTNode} identifier node to evaluate
+ * @returns {boolean} true if its is a special case
+ * @private
+ */
function isSpecialCaseIdentifierForMemberExpression(identifier) {
return identifier === "__proto__";
}
+ /**
+ * Check if identifier is a special case variable expression
+ * @param {ASTNode} identifier node to evaluate
+ * @returns {boolean} true if its is a special case
+ * @private
+ */
function isSpecialCaseIdentifierInVariableExpression(identifier) {
// Checks for the underscore library usage here
return identifier === "_";
}
+ /**
+ * Check if function has a underscore at the end
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function checkForTrailingUnderscoreInFunctionDeclaration(node) {
- var identifier = node.id.name;
+ if (node.id) {
+ var identifier = node.id.name;
- if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier)) {
- context.report(node, "Unexpected dangling '_' in '" + identifier + "'.");
+ if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) {
+ context.report(node, "Unexpected dangling \"_\" in \"" + identifier + "\".");
+ }
}
}
+ /**
+ * Check if variable expression has a underscore at the end
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function checkForTrailingUnderscoreInVariableExpression(node) {
var identifier = node.id.name;
if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) &&
- !isSpecialCaseIdentifierInVariableExpression(identifier)) {
- context.report(node, "Unexpected dangling '_' in '" + identifier + "'.");
+ !isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) {
+ context.report(node, "Unexpected dangling \"_\" in \"" + identifier + "\".");
}
}
+ /**
+ * Check if member expression has a underscore at the end
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function checkForTrailingUnderscoreInMemberExpression(node) {
var identifier = node.property.name;
if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) &&
- !isSpecialCaseIdentifierForMemberExpression(identifier)) {
- context.report(node, "Unexpected dangling '_' in '" + identifier + "'.");
+ !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) {
+ context.report(node, "Unexpected dangling \"_\" in \"" + identifier + "\".");
}
}
//--------------------------------------------------------------------------
// Public API
@@ -25785,22 +36619,168 @@
"MemberExpression": checkForTrailingUnderscoreInMemberExpression
};
};
-},{}],249:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],261:[function(require,module,exports){
/**
+ * @fileoverview Rule to spot scenarios where a newline looks like it is ending a statement, but is not.
+ * @author Glen Mailer
+ * @copyright 2015 Glen Mailer
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+module.exports = function(context) {
+
+ var FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call.";
+ var PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access.";
+
+ /**
+ * Check to see if the bracket prior to the node is continuing the previous
+ * line's expression
+ * @param {ASTNode} node The node to check.
+ * @param {string} msg The error message to use.
+ * @returns {void}
+ * @private
+ */
+ function checkForBreakBefore(node, msg) {
+ var tokens = context.getTokensBefore(node, 2);
+ var paren = tokens[1];
+ var before = tokens[0];
+ if (paren.loc.start.line !== before.loc.end.line) {
+ context.report(node, paren.loc.start, msg, { char: paren.value });
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Public API
+ //--------------------------------------------------------------------------
+
+ return {
+
+ "MemberExpression": function(node) {
+ if (!node.computed) {
+ return;
+ }
+
+ checkForBreakBefore(node.property, PROPERTY_MESSAGE);
+ },
+
+ "CallExpression": function(node) {
+ if (node.arguments.length === 0) {
+ return;
+ }
+
+ checkForBreakBefore(node.arguments[0], FUNCTION_MESSAGE);
+ }
+ };
+
+};
+
+module.exports.schema = [];
+
+},{}],262:[function(require,module,exports){
+/**
+ * @fileoverview Rule to flag no-unneeded-ternary
+ * @author Gyandeep Singh
+ * @copyright 2015 Gyandeep Singh. All rights reserved.
+ * @copyright 2015 Michael Ficarra. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var options = context.options[0] || {};
+ var defaultAssignment = options.defaultAssignment !== false;
+
+ /**
+ * Test if the node is a boolean literal
+ * @param {ASTNode} node - The node to report.
+ * @returns {boolean} True if the its a boolean literal
+ * @private
+ */
+ function isBooleanLiteral(node) {
+ return node.type === "Literal" && typeof node.value === "boolean";
+ }
+
+ /**
+ * Test if the node matches the pattern id ? id : expression
+ * @param {ASTNode} node - The ConditionalExpression to check.
+ * @returns {boolean} True if the pattern is matched, and false otherwise
+ * @private
+ */
+ function matchesDefaultAssignment(node) {
+ return node.test.type === "Identifier" &&
+ node.consequent.type === "Identifier" &&
+ node.test.name === node.consequent.name;
+ }
+
+ return {
+
+ "ConditionalExpression": function(node) {
+ if (isBooleanLiteral(node.alternate) && isBooleanLiteral(node.consequent)) {
+ context.report(node, node.consequent.loc.start, "Unnecessary use of boolean literals in conditional expression");
+ } else if (!defaultAssignment && matchesDefaultAssignment(node)) {
+ context.report(node, node.consequent.loc.start, "Unnecessary use of conditional expression for default assignment");
+ }
+ }
+ };
+};
+
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "defaultAssignment": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],263:[function(require,module,exports){
+/**
* @fileoverview Checks for unreachable code due to return, throws, break, and continue.
* @author Joel Feenstra
*/
"use strict";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
-
+/**
+ * Report the node
+ * @param {object} context Current context as passed to the rule
+ * @param {ASTNode} node node to evaluate
+ * @param {string} unreachableType Type of the statement
+ * @returns {void}
+ * @private
+ */
function report(context, node, unreachableType) {
var keyword;
switch (unreachableType) {
case "BreakStatement":
keyword = "break";
@@ -25839,11 +36819,11 @@
node.declarations.every(function(declaration) {
return declaration.type === "VariableDeclarator" && declaration.init === null;
});
}
- /*
+ /**
* Verifies that the given node is the last node or followed exclusively by
* hoisted declarations
* @param {ASTNode} node Node that should be the last node
* @returns {void}
* @private
@@ -25883,11 +36863,13 @@
"BreakStatement": checkNode
};
};
-},{}],250:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],264:[function(require,module,exports){
/**
* @fileoverview Flag expressions in statement position that do not side effect
* @author Michael Ficarra
* @copyright 2013 Michael Ficarra. All rights reserved.
*/
@@ -25896,14 +36878,17 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var config = context.options[0] || {},
+ allowShortCircuit = config.allowShortCircuit || false,
+ allowTernary = config.allowTernary || false;
/**
* @param {ASTNode} node - any node
- * @returns {Boolean} whether the given node structurally represents a directive
+ * @returns {boolean} whether the given node structurally represents a directive
*/
function looksLikeDirective(node) {
return node.type === "ExpressionStatement" &&
node.expression.type === "Literal" && typeof node.expression.value === "string";
}
@@ -25931,226 +36916,416 @@
}
/**
* @param {ASTNode} node - any node
* @param {ASTNode[]} ancestors - the given node's ancestors
- * @returns {Boolean} whether the given node is considered a directive in its current position
+ * @returns {boolean} whether the given node is considered a directive in its current position
*/
function isDirective(node, ancestors) {
var parent = ancestors[ancestors.length - 1],
grandparent = ancestors[ancestors.length - 2];
return (parent.type === "Program" || parent.type === "BlockStatement" &&
(/Function/.test(grandparent.type))) &&
directives(parent).indexOf(node) >= 0;
}
- return {
- "ExpressionStatement": function(node) {
+ /**
+ * Determines whether or not a given node is a valid expression. Recurses on short circuit eval and ternary nodes if enabled by flags.
+ * @param {ASTNode} node - any node
+ * @returns {boolean} whether the given node is a valid expression
+ */
+ function isValidExpression(node) {
+ if (allowTernary) {
+ // Recursive check for ternary and logical expressions
+ if (node.type === "ConditionalExpression") {
+ return isValidExpression(node.consequent) && isValidExpression(node.alternate);
+ }
+ }
+ if (allowShortCircuit) {
+ if (node.type === "LogicalExpression") {
+ return isValidExpression(node.right);
+ }
+ }
- var type = node.expression.type,
- ancestors = context.getAncestors();
+ return /^(?:Assignment|Call|New|Update|Yield)Expression$/.test(node.type) ||
+ (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0);
+ }
- if (
- !/^(?:Assignment|Call|New|Update|Yield)Expression$/.test(type) &&
- (type !== "UnaryExpression" || ["delete", "void"].indexOf(node.expression.operator) < 0) &&
- !isDirective(node, ancestors)
- ) {
+ return {
+ "ExpressionStatement": function(node) {
+ if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors())) {
context.report(node, "Expected an assignment or function call and instead saw an expression.");
}
}
};
};
-},{}],251:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "allowShortCircuit": {
+ "type": "boolean"
+ },
+ "allowTernary": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],265:[function(require,module,exports){
/**
* @fileoverview Rule to flag declared but unused variables
* @author Ilya Volodin
*/
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var escape = require("escape-string-regexp");
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var MESSAGE = "{{name}} is defined but never used";
+ var MESSAGE = "\"{{name}}\" is defined but never used";
var config = {
vars: "all",
args: "after-used"
};
- if (context.options[0]) {
- if (typeof context.options[0] === "string") {
- config.vars = context.options[0];
+ var firstOption = context.options[0];
+
+ if (firstOption) {
+ if (typeof firstOption === "string") {
+ config.vars = firstOption;
} else {
- config.vars = context.options[0].vars || config.vars;
- config.args = context.options[0].args || config.args;
+ config.vars = firstOption.vars || config.vars;
+ config.args = firstOption.args || config.args;
+
+ if (firstOption.varsIgnorePattern) {
+ config.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern);
+ }
+
+ if (firstOption.argsIgnorePattern) {
+ config.argsIgnorePattern = new RegExp(firstOption.argsIgnorePattern);
+ }
}
}
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
/**
* Determines if a given variable is being exported from a module.
- * @param {Variable} variable EScope variable object.
+ * @param {Variable} variable - EScope variable object.
* @returns {boolean} True if the variable is exported, false if not.
* @private
*/
function isExported(variable) {
var definition = variable.defs[0];
if (definition) {
- definition = definition.node;
- if (definition.type === "VariableDeclarator") {
- definition = definition.parent;
+ var node = definition.node;
+ if (node.type === "VariableDeclarator") {
+ node = node.parent;
+ } else if (definition.type === "Parameter") {
+ return false;
}
- return definition.parent.type.indexOf("Export") === 0;
+ return node.parent.type.indexOf("Export") === 0;
} else {
return false;
}
}
/**
- * @param {Reference} ref - an escope Reference
+ * Determines if a reference is a read operation.
+ * @param {Reference} ref - An escope Reference
* @returns {Boolean} whether the given reference represents a read operation
+ * @private
*/
function isReadRef(ref) {
return ref.isRead();
}
/**
- * Gets an array of local variables without read references.
- * @param {Scope} scope - an escope Scope object
- * @returns {Variable[]} most of the local variables with no read references
+ * Determine if an identifier is referencing an enclosing function name.
+ * @param {Reference} ref - The reference to check.
+ * @param {ASTNode[]} nodes - The candidate function nodes.
+ * @returns {boolean} True if it's a self-reference, false if not.
+ * @private
*/
- function getUnusedLocals(scope) {
- var unused = [];
+ function isSelfReference(ref, nodes) {
+ var scope = ref.from;
+
+ while (scope) {
+ if (nodes.indexOf(scope.block) >= 0) {
+ return true;
+ }
+
+ scope = scope.upper;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines if the variable is used.
+ * @param {Variable} variable - The variable to check.
+ * @param {Reference[]} references - The variable references to check.
+ * @returns {boolean} True if the variable is used
+ */
+ function isUsedVariable(variable, references) {
+ var functionNodes = variable.defs.filter(function(def) {
+ return def.type === "FunctionName";
+ }).map(function(def) {
+ return def.node;
+ }),
+ isFunctionDefinition = functionNodes.length > 0;
+
+ return references.some(function(ref) {
+ return isReadRef(ref) && !(isFunctionDefinition && isSelfReference(ref, functionNodes));
+ });
+ }
+
+ /**
+ * Gets unresolved references.
+ * They contains var's, function's, and explicit global variable's.
+ * If `config.vars` is not "all", returns empty map.
+ * @param {Scope} scope - the global scope.
+ * @returns {object} Unresolved references. Keys of the object is its variable name. Values of the object is an array of its references.
+ * @private
+ */
+ function collectUnresolvedReferences(scope) {
+ var unresolvedRefs = Object.create(null);
+
+ if (config.vars === "all") {
+ for (var i = 0, l = scope.through.length; i < l; ++i) {
+ var ref = scope.through[i];
+ var name = ref.identifier.name;
+
+ if (isReadRef(ref)) {
+ if (!unresolvedRefs[name]) {
+ unresolvedRefs[name] = [];
+ }
+ unresolvedRefs[name].push(ref);
+ }
+ }
+ }
+
+ return unresolvedRefs;
+ }
+
+ /**
+ * Gets an array of variables without read references.
+ * @param {Scope} scope - an escope Scope object.
+ * @param {object} unresolvedRefs - a map of each variable name and its references.
+ * @param {Variable[]} unusedVars - an array that saving result.
+ * @returns {Variable[]} unused variables of the scope and descendant scopes.
+ * @private
+ */
+ function collectUnusedVariables(scope, unresolvedRefs, unusedVars) {
var variables = scope.variables;
+ var childScopes = scope.childScopes;
+ var i, l;
- if (scope.type !== "global" && scope.type !== "TDZ") {
- for (var i = 0, l = variables.length; i < l; ++i) {
+ if (scope.type !== "TDZ" && (scope.type !== "global" || config.vars === "all")) {
+ for (i = 0, l = variables.length; i < l; ++i) {
+ var variable = variables[i];
- // skip function expression names
- if (scope.functionExpressionScope || variables[i].eslintJSXUsed) {
+ // skip a variable of class itself name in the class scope
+ if (scope.type === "class" && scope.block.id === variable.identifiers[0]) {
continue;
}
- // skip implicit "arguments" variable
- if (scope.type === "function" && variables[i].name === "arguments" && variables[i].identifiers.length === 0) {
+ // skip function expression names and variables marked with markVariableAsUsed()
+ if (scope.functionExpressionScope || variable.eslintUsed) {
continue;
}
- var type = variables[i].defs[0].type;
-
- // skip catch variables
- if (type === "CatchClause") {
+ // skip implicit "arguments" variable
+ if (scope.type === "function" && variable.name === "arguments" && variable.identifiers.length === 0) {
continue;
}
- // if "args" option is "none", skip any parameter
- if (config.args === "none" && type === "Parameter") {
- continue;
- }
- // if "args" option is "after-used", skip all but the last parameter
- if (config.args === "after-used" && type === "Parameter" && variables[i].defs[0].index < variables[i].defs[0].node.params.length - 1) {
- continue;
+ // explicit global variables don't have definitions.
+ var def = variable.defs[0];
+ if (def) {
+ var type = def.type;
+
+ // skip catch variables
+ if (type === "CatchClause") {
+ continue;
+ }
+
+ if (type === "Parameter") {
+ // skip any setter argument
+ if (def.node.parent.type === "Property" && def.node.parent.kind === "set") {
+ continue;
+ }
+
+ // if "args" option is "none", skip any parameter
+ if (config.args === "none") {
+ continue;
+ }
+
+ // skip ignored parameters
+ if (config.argsIgnorePattern && config.argsIgnorePattern.test(def.name.name)) {
+ continue;
+ }
+
+ // if "args" option is "after-used", skip all but the last parameter
+ if (config.args === "after-used" && def.index < def.node.params.length - 1) {
+ continue;
+ }
+ } else {
+ // skip ignored variables
+ if (config.varsIgnorePattern && config.varsIgnorePattern.test(def.name.name)) {
+ continue;
+ }
+ }
}
- if (variables[i].references.filter(isReadRef).length === 0 && !isExported(variables[i])) {
- unused.push(variables[i]);
+ // On global, variables without let/const/class are unresolved.
+ var references = (scope.type === "global" ? unresolvedRefs[variable.name] : null) || variable.references;
+ if (!isUsedVariable(variable, references) && !isExported(variable)) {
+ unusedVars.push(variable);
}
}
}
- return [].concat.apply(unused, scope.childScopes.map(getUnusedLocals));
+ for (i = 0, l = childScopes.length; i < l; ++i) {
+ collectUnusedVariables(childScopes[i], unresolvedRefs, unusedVars);
+ }
+
+ return unusedVars;
}
/**
- * @param {String} nodeName - Name of the node to check.
- * @returns {void}
+ * Gets the index of a given variable name in a given comment.
+ * @param {escope.Variable} variable - A variable to get.
+ * @param {ASTNode} comment - A comment node which includes the variable name.
+ * @returns {number} The index of the variable name's location.
*/
- function flagVariableAsUsedInJSX(nodeName) {
- var scope = context.getScope(),
- variables = scope.variables,
- i,
- len;
+ function getColumnInComment(variable, comment) {
+ var namePattern = new RegExp("[\\s,]" + escape(variable.name) + "(?:$|[\\s,:])", "g");
- while (scope.type !== "global") {
- scope = scope.upper;
- variables = [].concat.apply(scope.variables, variables);
- }
+ // To ignore the first text "global".
+ namePattern.lastIndex = comment.value.indexOf("global") + 6;
- // mark JSXIdentifiers with a special flag
- for (i = 0, len = variables.length; i < len; i++) {
- if (variables[i].name === nodeName) {
- variables[i].eslintJSXUsed = true;
- break;
- }
+ // Search a given variable name.
+ var match = namePattern.exec(comment.value);
+ return match ? match.index + 1 : 0;
+ }
+
+ /**
+ * Creates the correct location of a given variables.
+ * The location is at its name string in a `/*global` comment.
+ *
+ * @param {escope.Variable} variable - A variable to get its location.
+ * @returns {{line: number, column: number}} The location object for the variable.
+ */
+ function getLocation(variable) {
+ var comment = variable.eslintExplicitGlobalComment;
+ var baseLoc = comment.loc.start;
+ var column = getColumnInComment(variable, comment);
+ var prefix = comment.value.slice(0, column);
+ var lineInComment = (prefix.match(/\n/g) || []).length;
+
+ if (lineInComment > 0) {
+ column -= 1 + prefix.lastIndexOf("\n");
+ } else {
+ // 2 is for `/*`
+ column += baseLoc.column + 2;
}
+
+ return {
+ line: baseLoc.line + lineInComment,
+ column: column
+ };
}
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
return {
"Program:exit": function(programNode) {
var globalScope = context.getScope();
- var unused = getUnusedLocals(globalScope);
- var i, l;
+ var unresolvedRefs = collectUnresolvedReferences(globalScope);
+ var unusedVars = collectUnusedVariables(globalScope, unresolvedRefs, []);
- // determine unused globals
- if (config.vars === "all") {
- var unresolvedRefs = globalScope.through.filter(isReadRef).map(function(ref) {
- return ref.identifier.name;
- });
+ for (var i = 0, l = unusedVars.length; i < l; ++i) {
+ var unusedVar = unusedVars[i];
- for (i = 0, l = globalScope.variables.length; i < l; ++i) {
- if (unresolvedRefs.indexOf(globalScope.variables[i].name) < 0 &&
- !globalScope.variables[i].eslintJSXUsed && !isExported(globalScope.variables[i])) {
- unused.push(globalScope.variables[i]);
- }
+ if (unusedVar.eslintUsed) {
+ continue; // explicitly exported variables
+ } else if (unusedVar.eslintExplicitGlobal) {
+ context.report(programNode, getLocation(unusedVar), MESSAGE, unusedVar);
+ } else if (unusedVar.defs.length > 0) {
+ context.report(unusedVar.identifiers[0], MESSAGE, unusedVar);
}
}
+ }
+ };
- for (i = 0, l = unused.length; i < l; ++i) {
- if (unused[i].eslintExplicitGlobal) {
- context.report(programNode, MESSAGE, unused[i]);
- } else if (unused[i].defs.length > 0) {
+};
- // TODO: Remove when https://github.com/estools/escope/issues/49 is resolved
- if (unused[i].defs[0].type === "ClassName") {
- continue;
+module.exports.schema = [
+ {
+ "oneOf": [
+ {
+ "enum": ["all", "local"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "vars": {
+ "enum": ["all", "local"]
+ },
+ "varsIgnorePattern": {
+ "type": "string"
+ },
+ "args": {
+ "enum": ["all", "after-used", "none"]
+ },
+ "argsIgnorePattern": {
+ "type": "string"
}
-
- context.report(unused[i].identifiers[0], MESSAGE, unused[i]);
}
}
- },
+ ]
+ }
+];
- "JSXExpressionContainer": function(node) {
- if (node.expression.type === "Identifier") {
- flagVariableAsUsedInJSX(node.expression.name);
- }
- },
-
- "JSXIdentifier": function(node) {
- flagVariableAsUsedInJSX(node.name);
- }
- };
-
-};
-
-},{}],252:[function(require,module,exports){
+},{"escape-string-regexp":74}],266:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of variables before they are defined
* @author Ilya Volodin
* @copyright 2013 Ilya Volodin. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
var NO_FUNC = "nofunc";
@@ -26158,60 +37333,285 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- function findDeclaration(name, scope) {
- // try searching in the current scope first
- for (var i = 0, l = scope.variables.length; i < l; i++) {
- if (scope.variables[i].name === name) {
- return scope.variables[i];
- }
- }
- // check if there's upper scope and call recursivly till we find the variable
- if (scope.upper) {
- return findDeclaration(name, scope.upper);
- }
- }
-
- function findVariables() {
- var scope = context.getScope();
+ /**
+ * Finds and validates all variables in a given scope.
+ * @param {Scope} scope The scope object.
+ * @returns {void}
+ * @private
+ */
+ function findVariablesInScope(scope) {
var typeOption = context.options[0];
+ /**
+ * Report the node
+ * @param {object} reference reference object
+ * @param {ASTNode} declaration node to evaluate
+ * @returns {void}
+ * @private
+ */
function checkLocationAndReport(reference, declaration) {
if (typeOption !== NO_FUNC || declaration.defs[0].type !== "FunctionName") {
if (declaration.identifiers[0].range[1] > reference.identifier.range[1]) {
- context.report(reference.identifier, "{{a}} was used before it was defined", {a: reference.identifier.name});
+ context.report(reference.identifier, "\"{{a}}\" was used before it was defined", {a: reference.identifier.name});
}
}
}
scope.references.forEach(function(reference) {
// if the reference is resolved check for declaration location
// if not, it could be function invocation, try to find manually
if (reference.resolved && reference.resolved.identifiers.length > 0) {
checkLocationAndReport(reference, reference.resolved);
} else {
- var declaration = findDeclaration(reference.identifier.name, scope);
+ var declaration = astUtils.getVariableByName(scope, reference.identifier.name);
// if there're no identifiers, this is a global environment variable
if (declaration && declaration.identifiers.length !== 0) {
checkLocationAndReport(reference, declaration);
}
}
});
}
+
+ /**
+ * Validates variables inside of a node's scope.
+ * @param {ASTNode} node The node to check.
+ * @returns {void}
+ * @private
+ */
+ function findVariables() {
+ var scope = context.getScope();
+ findVariablesInScope(scope);
+ }
+
+ var ruleDefinition = {
+ "Program": function() {
+ var scope = context.getScope();
+ findVariablesInScope(scope);
+
+ // both Node.js and Modules have an extra scope
+ if (context.ecmaFeatures.globalReturn || context.ecmaFeatures.modules) {
+ findVariablesInScope(scope.childScopes[0]);
+ }
+ }
+ };
+
+ if (context.ecmaFeatures.blockBindings) {
+ ruleDefinition.BlockStatement = ruleDefinition.SwitchStatement = findVariables;
+
+ ruleDefinition.ArrowFunctionExpression = function(node) {
+ if (node.body.type !== "BlockStatement") {
+ findVariables(node);
+ }
+ };
+ } else {
+ ruleDefinition.FunctionExpression = ruleDefinition.FunctionDeclaration = ruleDefinition.ArrowFunctionExpression = findVariables;
+ }
+
+ return ruleDefinition;
+};
+
+module.exports.schema = [
+ {
+ "enum": ["nofunc"]
+ }
+];
+
+},{"../ast-utils":113}],267:[function(require,module,exports){
+/**
+ * @fileoverview A rule to disallow unnecessary `.call()` and `.apply()`.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether or not a node is a `.call()`/`.apply()`.
+ * @param {ASTNode} node - A CallExpression node to check.
+ * @returns {boolean} Whether or not the node is a `.call()`/`.apply()`.
+ */
+function isCallOrNonVariadicApply(node) {
+ return (
+ node.callee.type === "MemberExpression" &&
+ node.callee.property.type === "Identifier" &&
+ node.callee.computed === false &&
+ (
+ (node.callee.property.name === "call" && node.arguments.length >= 1) ||
+ (node.callee.property.name === "apply" && node.arguments.length === 2 && node.arguments[1].type === "ArrayExpression")
+ )
+ );
+}
+
+/**
+ * Checks whether or not the tokens of two given nodes are same.
+ * @param {ASTNode} left - A node 1 to compare.
+ * @param {ASTNode} right - A node 2 to compare.
+ * @param {RuleContext} context - The ESLint rule context object.
+ * @returns {boolean} the source code for the given node.
+ */
+function equalTokens(left, right, context) {
+ var tokensL = context.getTokens(left);
+ var tokensR = context.getTokens(right);
+
+ if (tokensL.length !== tokensR.length) {
+ return false;
+ }
+ for (var i = 0; i < tokensL.length; ++i) {
+ if (tokensL[i].type !== tokensR[i].type ||
+ tokensL[i].value !== tokensR[i].value
+ ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Checks whether or not `thisArg` is not changed by `.call()`/`.apply()`.
+ * @param {ASTNode|null} expectedThis - The node that is the owner of the applied function.
+ * @param {ASTNode} thisArg - The node that is given to the first argument of the `.call()`/`.apply()`.
+ * @param {RuleContext} context - The ESLint rule context object.
+ * @returns {boolean} Whether or not `thisArg` is not changed by `.call()`/`.apply()`.
+ */
+function isValidThisArg(expectedThis, thisArg, context) {
+ if (!expectedThis) {
+ return astUtils.isNullOrUndefined(thisArg);
+ }
+ return equalTokens(expectedThis, thisArg, context);
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
return {
- "Program": findVariables,
- "FunctionExpression": findVariables,
- "FunctionDeclaration": findVariables,
- "ArrowFunctionExpression": findVariables
+ "CallExpression": function(node) {
+ if (!isCallOrNonVariadicApply(node)) {
+ return;
+ }
+
+ var applied = node.callee.object;
+ var expectedThis = (applied.type === "MemberExpression") ? applied.object : null;
+ var thisArg = node.arguments[0];
+
+ if (isValidThisArg(expectedThis, thisArg, context)) {
+ context.report(
+ node,
+ "unnecessary \".{{name}}()\".",
+ {name: node.callee.property.name});
+ }
+ }
};
};
-},{}],253:[function(require,module,exports){
+module.exports.schema = [];
+
+},{"../ast-utils":113}],268:[function(require,module,exports){
/**
+ * @fileoverview disallow unncessary concatenation of template strings
+ * @author Henry Zhu
+ * @copyright 2015 Henry Zhu. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether or not a given node is a concatenation.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} `true` if the node is a concatenation.
+ */
+function isConcatenation(node) {
+ return node.type === "BinaryExpression" && node.operator === "+";
+}
+
+/**
+ * Get's the right most node on the left side of a BinaryExpression with + operator.
+ * @param {ASTNode} node - A BinaryExpression node to check.
+ * @returns {ASTNode} node
+ */
+function getLeft(node) {
+ var left = node.left;
+ while (isConcatenation(left)) {
+ left = left.right;
+ }
+ return left;
+}
+
+/**
+ * Get's the left most node on the right side of a BinaryExpression with + operator.
+ * @param {ASTNode} node - A BinaryExpression node to check.
+ * @returns {ASTNode} node
+ */
+function getRight(node) {
+ var right = node.right;
+ while (isConcatenation(right)) {
+ right = right.left;
+ }
+ return right;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ return {
+ BinaryExpression: function(node) {
+ // check if not concatenation
+ if (node.operator !== "+") {
+ return;
+ }
+
+ // account for the `foo + "a" + "b"` case
+ var left = getLeft(node);
+ var right = getRight(node);
+
+ if (astUtils.isStringLiteral(left) &&
+ astUtils.isStringLiteral(right) &&
+ astUtils.isTokenOnSameLine(left, right)
+ ) {
+ // move warning location to operator
+ var operatorToken = context.getTokenAfter(left);
+ while (operatorToken.value !== "+") {
+ operatorToken = context.getTokenAfter(operatorToken);
+ }
+
+ context.report(
+ node,
+ operatorToken.loc.start,
+ "Unexpected string concatenation of literals.");
+ }
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{"../ast-utils":113}],269:[function(require,module,exports){
+/**
* @fileoverview Rule to check for the usage of var.
* @author Jamund Ferguson
* @copyright 2014 Jamund Ferguson. All rights reserved.
*/
@@ -26222,21 +37622,23 @@
//------------------------------------------------------------------------------
module.exports = function(context) {
return {
- "VariableDeclaration": function (node) {
+ "VariableDeclaration": function(node) {
if (node.kind === "var") {
context.report(node, "Unexpected var, use let or const instead.");
}
}
};
};
-},{}],254:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],270:[function(require,module,exports){
/**
* @fileoverview Rule to disallow use of void operator.
* @author Mike Sidorov
* @copyright 2014 Mike Sidorov. All rights reserved.
*/
@@ -26260,27 +37662,32 @@
}
};
};
-},{}],255:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],271:[function(require,module,exports){
/**
* @fileoverview Rule that warns about used warning comments
* @author Alexander Schmidt <https://github.com/lxanders>
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
+module.exports = function(context) {
var configuration = context.options[0] || {},
warningTerms = configuration.terms || ["todo", "fixme", "xxx"],
location = configuration.location || "start",
+ selfConfigRegEx = /\bno-warning-comments\b/,
warningRegExps;
/**
* Convert a warning term into a RegExp which will match a comment containing that whole word in the specified
* location ("start" or "anywhere"). If the term starts or ends with non word characters, then the match will not
@@ -26317,11 +37724,11 @@
* @returns {Array} All matched warning terms for this comment.
*/
function commentContainsWarningTerm(comment) {
var matches = [];
- warningRegExps.forEach(function (regex, index) {
+ warningRegExps.forEach(function(regex, index) {
if (regex.test(comment)) {
matches.push(warningTerms[index]);
}
});
@@ -26332,25 +37739,47 @@
* Checks the specified node for matching warning comments and reports them.
* @param {ASTNode} node The AST node being checked.
* @returns {void} undefined.
*/
function checkComment(node) {
+ if (astUtils.isDirectiveComment(node) && selfConfigRegEx.test(node.value)) {
+ return;
+ }
+
var matches = commentContainsWarningTerm(node.value);
- matches.forEach(function (matchedTerm) {
- context.report(node, "Unexpected " + matchedTerm + " comment.");
+ matches.forEach(function(matchedTerm) {
+ context.report(node, "Unexpected \"" + matchedTerm + "\" comment.");
});
}
warningRegExps = warningTerms.map(convertToRegExp);
return {
"BlockComment": checkComment,
"LineComment": checkComment
};
};
-},{}],256:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "terms": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "location": {
+ "enum": ["start", "anywhere"]
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],272:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of with statement
* @author Nicholas C. Zakas
*/
@@ -26368,55 +37797,362 @@
}
};
};
-},{}],257:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],273:[function(require,module,exports){
/**
- * @fileoverview Rule to flag wrapping non-iife in parens
- * @author Ilya Volodin
- * @copyright 2013 Ilya Volodin. All rights reserved.
+ * @fileoverview Disallows or enforces spaces inside of object literals.
+ * @author Jamund Ferguson
+ * @copyright 2014 Brandyn Bennett. All rights reserved.
+ * @copyright 2014 Michael Ficarra. No rights reserved.
+ * @copyright 2014 Vignesh Anand. All rights reserved.
+ * @copyright 2015 Jamund Ferguson. All rights reserved.
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
-
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var spaced = context.options[0] === "always",
+ sourceCode = context.getSourceCode();
/**
- * Checks a function expression to see if its surrounded by parens.
- * @param {ASTNode} node The node to check.
+ * Determines whether an option is set, relative to the spacing option.
+ * If spaced is "always", then check whether option is set to false.
+ * If spaced is "never", then check whether option is set to true.
+ * @param {Object} option - The option to exclude.
+ * @returns {boolean} Whether or not the property is excluded.
+ */
+ function isOptionSet(option) {
+ return context.options[1] ? context.options[1][option] === !spaced : false;
+ }
+
+ var options = {
+ spaced: spaced,
+ arraysInObjectsException: isOptionSet("arraysInObjects"),
+ objectsInObjectsException: isOptionSet("objectsInObjects")
+ };
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Reports that there shouldn't be a space after the first token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportNoBeginningSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.end,
+ message: "There should be no space after '" + token.value + "'",
+ fix: function(fixer) {
+ var nextToken = context.getSourceCode().getTokenAfter(token);
+ return fixer.removeRange([token.range[1], nextToken.range[0]]);
+ }
+ });
+ }
+
+ /**
+ * Reports that there shouldn't be a space before the last token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportNoEndingSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "There should be no space before '" + token.value + "'",
+ fix: function(fixer) {
+ var previousToken = context.getSourceCode().getTokenBefore(token);
+ return fixer.removeRange([previousToken.range[1], token.range[0]]);
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a space after the first token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredBeginningSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.end,
+ message: "A space is required after '" + token.value + "'",
+ fix: function(fixer) {
+ return fixer.insertTextAfter(token, " ");
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a space before the last token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredEndingSpace(node, token) {
+ context.report({
+ node: node,
+ loc: token.loc.start,
+ message: "A space is required before '" + token.value + "'",
+ fix: function(fixer) {
+ return fixer.insertTextBefore(token, " ");
+ }
+ });
+ }
+
+ /**
+ * Determines if spacing in curly braces is valid.
+ * @param {ASTNode} node The AST node to check.
+ * @param {Token} first The first token to check (should be the opening brace)
+ * @param {Token} second The second token to check (should be first after the opening brace)
+ * @param {Token} penultimate The penultimate token to check (should be last before closing brace)
+ * @param {Token} last The last token to check (should be closing brace)
* @returns {void}
- * @private
*/
- function checkFunction(node) {
- var ancestors = context.getAncestors(),
- previousToken, nextToken;
+ function validateBraceSpacing(node, first, second, penultimate, last) {
+ var closingCurlyBraceMustBeSpaced =
+ options.arraysInObjectsException && penultimate.value === "]" ||
+ options.objectsInObjectsException && penultimate.value === "}"
+ ? !options.spaced : options.spaced,
+ firstSpaced, lastSpaced;
- if (!/CallExpression|NewExpression/.test(ancestors.pop().type)) {
- previousToken = context.getTokenBefore(node);
- nextToken = context.getTokenAfter(node);
- if (previousToken.value === "(" && nextToken.value === ")") {
- context.report(node, "Wrapping non-IIFE function literals in parens is unnecessary.");
+ if (astUtils.isTokenOnSameLine(first, second)) {
+ firstSpaced = sourceCode.isSpaceBetweenTokens(first, second);
+ if (options.spaced && !firstSpaced) {
+ reportRequiredBeginningSpace(node, first);
}
+ if (!options.spaced && firstSpaced) {
+ reportNoBeginningSpace(node, first);
+ }
}
+
+ if (astUtils.isTokenOnSameLine(penultimate, last)) {
+ lastSpaced = sourceCode.isSpaceBetweenTokens(penultimate, last);
+ if (closingCurlyBraceMustBeSpaced && !lastSpaced) {
+ reportRequiredEndingSpace(node, last);
+ }
+ if (!closingCurlyBraceMustBeSpaced && lastSpaced) {
+ reportNoEndingSpace(node, last);
+ }
+ }
}
+ /**
+ * Reports a given object node if spacing in curly braces is invalid.
+ * @param {ASTNode} node - An ObjectExpression or ObjectPattern node to check.
+ * @returns {void}
+ */
+ function checkForObject(node) {
+ if (node.properties.length === 0) {
+ return;
+ }
+
+ var first = sourceCode.getFirstToken(node),
+ last = sourceCode.getLastToken(node),
+ second = sourceCode.getTokenAfter(first),
+ penultimate = sourceCode.getTokenBefore(last);
+
+ validateBraceSpacing(node, first, second, penultimate, last);
+ }
+
+ /**
+ * Reports a given import node if spacing in curly braces is invalid.
+ * @param {ASTNode} node - An ImportDeclaration node to check.
+ * @returns {void}
+ */
+ function checkForImport(node) {
+ if (node.specifiers.length === 0) {
+ return;
+ }
+
+ var firstSpecifier = node.specifiers[0],
+ lastSpecifier = node.specifiers[node.specifiers.length - 1];
+
+ if (lastSpecifier.type !== "ImportSpecifier") {
+ return;
+ }
+ if (firstSpecifier.type !== "ImportSpecifier") {
+ firstSpecifier = node.specifiers[1];
+ }
+
+ var first = sourceCode.getTokenBefore(firstSpecifier),
+ last = sourceCode.getTokenAfter(lastSpecifier);
+
+ // to support a trailing comma.
+ if (last.value === ",") {
+ last = sourceCode.getTokenAfter(last);
+ }
+
+ var second = sourceCode.getTokenAfter(first),
+ penultimate = sourceCode.getTokenBefore(last);
+
+ validateBraceSpacing(node, first, second, penultimate, last);
+ }
+
+ /**
+ * Reports a given export node if spacing in curly braces is invalid.
+ * @param {ASTNode} node - An ExportNamedDeclaration node to check.
+ * @returns {void}
+ */
+ function checkForExport(node) {
+ if (node.specifiers.length === 0) {
+ return;
+ }
+
+ var firstSpecifier = node.specifiers[0],
+ lastSpecifier = node.specifiers[node.specifiers.length - 1],
+ first = sourceCode.getTokenBefore(firstSpecifier),
+ last = sourceCode.getTokenAfter(lastSpecifier);
+
+ // to support a trailing comma.
+ if (last.value === ",") {
+ last = sourceCode.getTokenAfter(last);
+ }
+
+ var second = sourceCode.getTokenAfter(first),
+ penultimate = sourceCode.getTokenBefore(last);
+
+ validateBraceSpacing(node, first, second, penultimate, last);
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
return {
- "ArrowFunctionExpression": checkFunction,
- "FunctionExpression": checkFunction
+ // var {x} = y;
+ ObjectPattern: checkForObject,
+
+ // var y = {x: 'y'}
+ ObjectExpression: checkForObject,
+
+ // import {y} from 'x';
+ ImportDeclaration: checkForImport,
+
+ // export {name} from 'yo';
+ ExportNamedDeclaration: checkForExport
};
};
-},{}],258:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "arraysInObjects": {
+ "type": "boolean"
+ },
+ "objectsInObjects": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],274:[function(require,module,exports){
/**
- * @fileoverview A rule to ensure the use of a single variable declaration.
+ * @fileoverview Rule to enforce concise object methods and properties.
+ * @author Jamund Ferguson
+ * @copyright 2015 Jamund Ferguson. All rights reserved.
+ */
+
+"use strict";
+
+var OPTIONS = {
+ always: "always",
+ never: "never",
+ methods: "methods",
+ properties: "properties"
+};
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var APPLY = context.options[0] || OPTIONS.always;
+ var APPLY_TO_METHODS = APPLY === OPTIONS.methods || APPLY === OPTIONS.always;
+ var APPLY_TO_PROPS = APPLY === OPTIONS.properties || APPLY === OPTIONS.always;
+ var APPLY_NEVER = APPLY === OPTIONS.never;
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ "Property": function(node) {
+ var isConciseProperty = node.method || node.shorthand,
+ type;
+
+ // if we're "never" and concise we should warn now
+ if (APPLY_NEVER && isConciseProperty) {
+ type = node.method ? "method" : "property";
+ context.report(node, "Expected longform " + type + " syntax.");
+ }
+
+ // at this point if we're concise or if we're "never" we can leave
+ if (APPLY_NEVER || isConciseProperty) {
+ return;
+ }
+
+ // getters, setters and computed properties are ignored
+ if (node.kind === "get" || node.kind === "set" || node.computed) {
+ return;
+ }
+
+ if (node.value.type === "FunctionExpression" && !node.value.id && APPLY_TO_METHODS) {
+
+ // {x: function(){}} should be written as {x() {}}
+ context.report(node, "Expected method shorthand.");
+ } else if (node.value.type === "Identifier" && node.key.name === node.value.name && APPLY_TO_PROPS) {
+
+ // {x: x} should be written as {x}
+ context.report(node, "Expected property shorthand.");
+ } else if (node.value.type === "Identifier" && node.key.type === "Literal" && node.key.value === node.value.name && APPLY_TO_PROPS) {
+
+ // {"x": x} should be written as {x}
+ context.report(node, "Expected property shorthand.");
+ }
+ }
+ };
+
+};
+
+module.exports.schema = [
+ {
+ "enum": ["always", "methods", "properties", "never"]
+ }
+];
+
+},{}],275:[function(require,module,exports){
+/**
+ * @fileoverview A rule to control the use of single variable declarations.
* @author Ian Christian Myers
+ * @copyright 2015 Ian VanSchooten. All rights reserved.
+ * @copyright 2015 Joey Baker. All rights reserved.
+ * @copyright 2015 Danny Fritz. All rights reserved.
* @copyright 2013 Ian Christian Myers. All rights reserved.
*/
"use strict";
@@ -26424,53 +38160,310 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var MODE_ALWAYS = "always",
+ MODE_NEVER = "never";
+
+ var mode = context.options[0] || MODE_ALWAYS;
+
+ var options = {
+ };
+
+ if (typeof mode === "string") { // simple options configuration with just a string
+ options.var = { uninitialized: mode, initialized: mode};
+ options.let = { uninitialized: mode, initialized: mode};
+ options.const = { uninitialized: mode, initialized: mode};
+ } else if (typeof mode === "object") { // options configuration is an object
+ if (mode.hasOwnProperty("var") && typeof mode.var === "string") {
+ options.var = { uninitialized: mode.var, initialized: mode.var};
+ }
+ if (mode.hasOwnProperty("let") && typeof mode.let === "string") {
+ options.let = { uninitialized: mode.let, initialized: mode.let};
+ }
+ if (mode.hasOwnProperty("const") && typeof mode.const === "string") {
+ options.const = { uninitialized: mode.const, initialized: mode.const};
+ }
+ if (mode.hasOwnProperty("uninitialized")) {
+ if (!options.var) {
+ options.var = {};
+ }
+ if (!options.let) {
+ options.let = {};
+ }
+ if (!options.const) {
+ options.const = {};
+ }
+ options.var.uninitialized = mode.uninitialized;
+ options.let.uninitialized = mode.uninitialized;
+ options.const.uninitialized = mode.uninitialized;
+ }
+ if (mode.hasOwnProperty("initialized")) {
+ if (!options.var) {
+ options.var = {};
+ }
+ if (!options.let) {
+ options.let = {};
+ }
+ if (!options.const) {
+ options.const = {};
+ }
+ options.var.initialized = mode.initialized;
+ options.let.initialized = mode.initialized;
+ options.const.initialized = mode.initialized;
+ }
+ }
+
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
var functionStack = [];
+ var blockStack = [];
+ /**
+ * Increments the blockStack counter.
+ * @returns {void}
+ * @private
+ */
+ function startBlock() {
+ blockStack.push({
+ let: {initialized: false, uninitialized: false},
+ const: {initialized: false, uninitialized: false}
+ });
+ }
+
+ /**
+ * Increments the functionStack counter.
+ * @returns {void}
+ * @private
+ */
function startFunction() {
- functionStack.push(false);
+ functionStack.push({initialized: false, uninitialized: false});
+ startBlock();
}
+ /**
+ * Decrements the blockStack counter.
+ * @returns {void}
+ * @private
+ */
+ function endBlock() {
+ blockStack.pop();
+ }
+
+ /**
+ * Decrements the functionStack counter.
+ * @returns {void}
+ * @private
+ */
function endFunction() {
functionStack.pop();
+ endBlock();
}
- function checkDeclarations(node) {
- if (functionStack[functionStack.length - 1]) {
- context.report(node, "Combine this with the previous 'var' statement.");
- } else {
- functionStack[functionStack.length - 1] = true;
+ /**
+ * Records whether initialized or uninitialized variables are defined in current scope.
+ * @param {string} statementType node.kind, one of: "var", "let", or "const"
+ * @param {ASTNode[]} declarations List of declarations
+ * @param {Object} currentScope The scope being investigated
+ * @returns {void}
+ * @private
+ */
+ function recordTypes(statementType, declarations, currentScope) {
+ for (var i = 0; i < declarations.length; i++) {
+ if (declarations[i].init === null) {
+ if (options[statementType] && options[statementType].uninitialized === MODE_ALWAYS) {
+ currentScope.uninitialized = true;
+ }
+ } else {
+ if (options[statementType] && options[statementType].initialized === MODE_ALWAYS) {
+ currentScope.initialized = true;
+ }
+ }
}
}
+ /**
+ * Determines the current scope (function or block)
+ * @param {string} statementType node.kind, one of: "var", "let", or "const"
+ * @returns {Object} The scope associated with statementType
+ */
+ function getCurrentScope(statementType) {
+ var currentScope;
+ if (statementType === "var") {
+ currentScope = functionStack[functionStack.length - 1];
+ } else if (statementType === "let") {
+ currentScope = blockStack[blockStack.length - 1].let;
+ } else if (statementType === "const") {
+ currentScope = blockStack[blockStack.length - 1].const;
+ }
+ return currentScope;
+ }
+
+ /**
+ * Counts the number of initialized and uninitialized declarations in a list of declarations
+ * @param {ASTNode[]} declarations List of declarations
+ * @returns {Object} Counts of 'uninitialized' and 'initialized' declarations
+ * @private
+ */
+ function countDeclarations(declarations) {
+ var counts = { uninitialized: 0, initialized: 0 };
+ for (var i = 0; i < declarations.length; i++) {
+ if (declarations[i].init === null) {
+ counts.uninitialized++;
+ } else {
+ counts.initialized++;
+ }
+ }
+ return counts;
+ }
+
+ /**
+ * Determines if there is more than one var statement in the current scope.
+ * @param {string} statementType node.kind, one of: "var", "let", or "const"
+ * @param {ASTNode[]} declarations List of declarations
+ * @returns {boolean} Returns true if it is the first var declaration, false if not.
+ * @private
+ */
+ function hasOnlyOneStatement(statementType, declarations) {
+
+ var declarationCounts = countDeclarations(declarations);
+ var currentOptions = options[statementType] || {};
+ var currentScope = getCurrentScope(statementType);
+
+ if (currentOptions.uninitialized === MODE_ALWAYS && currentOptions.initialized === MODE_ALWAYS) {
+ if (currentScope.uninitialized || currentScope.initialized) {
+ return false;
+ }
+ }
+
+ if (declarationCounts.uninitialized > 0) {
+ if (currentOptions.uninitialized === MODE_ALWAYS && currentScope.uninitialized) {
+ return false;
+ }
+ }
+ if (declarationCounts.initialized > 0) {
+ if (currentOptions.initialized === MODE_ALWAYS && currentScope.initialized) {
+ return false;
+ }
+ }
+ recordTypes(statementType, declarations, currentScope);
+ return true;
+ }
+
+
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
return {
"Program": startFunction,
"FunctionDeclaration": startFunction,
"FunctionExpression": startFunction,
"ArrowFunctionExpression": startFunction,
+ "BlockStatement": startBlock,
+ "ForStatement": startBlock,
+ "ForInStatement": startBlock,
+ "ForOfStatement": startBlock,
+ "SwitchStatement": startBlock,
- "VariableDeclaration": checkDeclarations,
+ "VariableDeclaration": function(node) {
+ var parent = node.parent,
+ type, declarations, declarationCounts;
+ type = node.kind;
+ if (!options[type]) {
+ return;
+ }
+
+ declarations = node.declarations;
+ declarationCounts = countDeclarations(declarations);
+
+ // always
+ if (!hasOnlyOneStatement(type, declarations)) {
+ if (options[type].initialized === MODE_ALWAYS && options[type].uninitialized === MODE_ALWAYS) {
+ context.report(node, "Combine this with the previous '" + type + "' statement.");
+ } else {
+ if (options[type].initialized === MODE_ALWAYS) {
+ context.report(node, "Combine this with the previous '" + type + "' statement with initialized variables.");
+ }
+ if (options[type].uninitialized === MODE_ALWAYS) {
+ context.report(node, "Combine this with the previous '" + type + "' statement with uninitialized variables.");
+ }
+ }
+ }
+ // never
+ if (parent.type !== "ForStatement" || parent.init !== node) {
+ var totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized;
+ if (totalDeclarations > 1) {
+ // both initialized and uninitialized
+ if (options[type].initialized === MODE_NEVER && options[type].uninitialized === MODE_NEVER) {
+ context.report(node, "Split '" + type + "' declarations into multiple statements.");
+ // initialized
+ } else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) {
+ context.report(node, "Split initialized '" + type + "' declarations into multiple statements.");
+ // uninitialized
+ } else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) {
+ context.report(node, "Split uninitialized '" + type + "' declarations into multiple statements.");
+ }
+ }
+ }
+ },
+
+ "ForStatement:exit": endBlock,
+ "ForOfStatement:exit": endBlock,
+ "ForInStatement:exit": endBlock,
+ "SwitchStatement:exit": endBlock,
+ "BlockStatement:exit": endBlock,
"Program:exit": endFunction,
"FunctionDeclaration:exit": endFunction,
"FunctionExpression:exit": endFunction,
"ArrowFunctionExpression:exit": endFunction
};
};
-},{}],259:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "oneOf": [
+ {
+ "enum": ["always", "never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "var": {
+ "enum": ["always", "never"]
+ },
+ "let": {
+ "enum": ["always", "never"]
+ },
+ "const": {
+ "enum": ["always", "never"]
+ }
+ },
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "initialized": {
+ "enum": ["always", "never"]
+ },
+ "uninitialized": {
+ "enum": ["always", "never"]
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ }
+];
+
+},{}],276:[function(require,module,exports){
/**
* @fileoverview Rule to replace assignment expressions with operator assignment
* @author Brandon Mills
* @copyright 2014 Brandon Mills. All rights reserved.
*/
@@ -26580,12 +38573,167 @@
"AssignmentExpression": context.options[0] !== "never" ? verify : prohibit
};
};
-},{}],260:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ }
+];
+
+},{}],277:[function(require,module,exports){
/**
+ * @fileoverview Operator linebreak - enforces operator linebreak style of two types: after and before
+ * @author Benoît Zugmeyer
+ * @copyright 2015 Benoît Zugmeyer. All rights reserved.
+ */
+
+"use strict";
+
+var assign = require("object-assign"),
+ astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ var usedDefaultGlobal = !context.options[0];
+ var globalStyle = context.options[0] || "after";
+ var options = context.options[1] || {};
+ var styleOverrides = options.overrides ? assign({}, options.overrides) : {};
+
+ if (usedDefaultGlobal && !styleOverrides["?"]) {
+ styleOverrides["?"] = "before";
+ }
+
+ if (usedDefaultGlobal && !styleOverrides[":"]) {
+ styleOverrides[":"] = "before";
+ }
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Checks the operator placement
+ * @param {ASTNode} node The node to check
+ * @param {ASTNode} leftSide The node that comes before the operator in `node`
+ * @private
+ * @returns {void}
+ */
+ function validateNode(node, leftSide) {
+ var leftToken = context.getLastToken(leftSide);
+ var operatorToken = context.getTokenAfter(leftToken);
+
+ // When the left part of a binary expression is a single expression wrapped in
+ // parentheses (ex: `(a) + b`), leftToken will be the last token of the expression
+ // and operatorToken will be the closing parenthesis.
+ // The leftToken should be the last closing parenthesis, and the operatorToken
+ // should be the token right after that.
+ while (operatorToken.value === ")") {
+ leftToken = operatorToken;
+ operatorToken = context.getTokenAfter(operatorToken);
+ }
+
+ var rightToken = context.getTokenAfter(operatorToken);
+ var operator = operatorToken.value;
+ var style = styleOverrides[operator] || globalStyle;
+
+ // if single line
+ if (astUtils.isTokenOnSameLine(leftToken, operatorToken) &&
+ astUtils.isTokenOnSameLine(operatorToken, rightToken)) {
+
+ return;
+
+ } else if (!astUtils.isTokenOnSameLine(leftToken, operatorToken) &&
+ !astUtils.isTokenOnSameLine(operatorToken, rightToken)) {
+
+ // lone operator
+ context.report(node, {
+ line: operatorToken.loc.end.line,
+ column: operatorToken.loc.end.column
+ }, "Bad line breaking before and after '" + operator + "'.");
+
+ } else if (style === "before" && astUtils.isTokenOnSameLine(leftToken, operatorToken)) {
+
+ context.report(node, {
+ line: operatorToken.loc.end.line,
+ column: operatorToken.loc.end.column
+ }, "'" + operator + "' should be placed at the beginning of the line.");
+
+ } else if (style === "after" && astUtils.isTokenOnSameLine(operatorToken, rightToken)) {
+
+ context.report(node, {
+ line: operatorToken.loc.end.line,
+ column: operatorToken.loc.end.column
+ }, "'" + operator + "' should be placed at the end of the line.");
+
+ } else if (style === "none") {
+
+ context.report(node, {
+ line: operatorToken.loc.end.line,
+ column: operatorToken.loc.end.column
+ }, "There should be no line break before or after '" + operator + "'");
+
+ }
+ }
+
+ /**
+ * Validates a binary expression using `validateNode`
+ * @param {BinaryExpression|LogicalExpression|AssignmentExpression} node node to be validated
+ * @returns {void}
+ */
+ function validateBinaryExpression(node) {
+ validateNode(node, node.left);
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+ "BinaryExpression": validateBinaryExpression,
+ "LogicalExpression": validateBinaryExpression,
+ "AssignmentExpression": validateBinaryExpression,
+ "VariableDeclarator": function(node) {
+ if (node.init) {
+ validateNode(node, node.id);
+ }
+ },
+ "ConditionalExpression": function(node) {
+ validateNode(node, node.test);
+ validateNode(node, node.consequent);
+ }
+ };
+};
+
+module.exports.schema = [
+ {
+ "enum": ["after", "before", "none", null]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "overrides": {
+ "type": "object",
+ "properties": {
+ "anyOf": {
+ "type": "string",
+ "enum": ["after", "before", "none"]
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113,"object-assign":108}],278:[function(require,module,exports){
+/**
* @fileoverview A rule to ensure blank lines within blocks.
* @author Mathias Schreck <https://github.com/lo1tuma>
* @copyright 2014 Mathias Schreck. All rights reserved.
*/
@@ -26593,171 +38741,966 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
+module.exports = function(context) {
var requirePadding = context.options[0] !== "never";
+ var ALWAYS_MESSAGE = "Block must be padded by blank lines.",
+ NEVER_MESSAGE = "Block must not be padded by blank lines.";
+
/**
+ * Retrieves an array of all comments defined inside the given node.
+ * @param {ASTNode} node The AST node.
+ * @returns {ASTNode[]} An array of comment nodes.
+ */
+ function getCommentsInNode(node) {
+ var allComments = context.getAllComments();
+
+ return allComments.filter(function(comment) {
+ return node.range[0] < comment.range[0] &&
+ node.range[1] > comment.range[1];
+ });
+ }
+
+ /**
+ * Checks if the location of a node or token is before the location of another node or token
+ * @param {ASTNode|Token} a The node or token to check if its location is before b.
+ * @param {ASTNode|Token} b The node or token which will be compared with a.
+ * @returns {boolean} True if a is located before b.
+ */
+ function isLocatedBefore(a, b) {
+ return a.range[1] < b.range[0];
+ }
+
+ /**
* Checks if the given non empty block node has a blank line before its first child node.
* @param {ASTNode} node The AST node of a BlockStatement.
* @returns {boolean} Whether or not the block starts with a blank line.
*/
- function isNonEmptyBlockTopPadded(node) {
+ function isBlockTopPadded(node) {
var blockStart = node.loc.start.line,
first = node.body[0],
firstLine = first.loc.start.line,
expectedFirstLine = blockStart + 2,
- leadingComments = context.getComments(first).leading;
+ comments = getCommentsInNode(node),
+ firstComment = comments[0];
- if (leadingComments.length > 0) {
- firstLine = leadingComments[0].loc.start.line;
+ if (firstComment && isLocatedBefore(firstComment, first)) {
+ firstLine = firstComment.loc.start.line;
}
return expectedFirstLine <= firstLine;
}
/**
* Checks if the given non empty block node has a blank line after its last child node.
* @param {ASTNode} node The AST node of a BlockStatement.
* @returns {boolean} Whether or not the block ends with a blank line.
*/
- function isNonEmptyBlockBottomPadded(node) {
+ function isBlockBottomPadded(node) {
var blockEnd = node.loc.end.line,
last = node.body[node.body.length - 1],
- lastLine = last.loc.end.line,
+ lastToken = context.getLastToken(last),
+ lastLine = lastToken.loc.end.line,
expectedLastLine = blockEnd - 2,
- trailingComments = context.getComments(last).trailing;
+ comments = getCommentsInNode(node),
+ lastComment = comments[comments.length - 1];
- if (trailingComments.length > 0) {
- lastLine = trailingComments[trailingComments.length - 1].loc.end.line;
+ if (lastComment && isLocatedBefore(lastToken, lastComment)) {
+ lastLine = lastComment.loc.end.line;
}
return lastLine <= expectedLastLine;
}
/**
- * Checks if the given non empty block node starts AND ends with a blank line.
- * @param {ASTNode} node The AST node of a BlockStatement.
- * @returns {boolean} Whether or not the block starts and ends with a blank line.
- */
- function isNonEmptyBlockPadded(node) {
- return isNonEmptyBlockTopPadded(node) && isNonEmptyBlockBottomPadded(node);
- }
-
- /**
- * Checks if the given non empty block node starts OR ends with a blank line.
- * @param {ASTNode} node The AST node of a BlockStatement.
- * @returns {boolean} Whether or not the block starts and ends with a blank line.
- */
- function hasNonEmptyBlockExtraPadding(node) {
- return isNonEmptyBlockTopPadded(node) || isNonEmptyBlockBottomPadded(node);
- }
-
- /**
* Checks the given BlockStatement node to be padded if the block is not empty.
* @param {ASTNode} node The AST node of a BlockStatement.
* @returns {void} undefined.
*/
function checkPadding(node) {
if (node.body.length > 0) {
+
+ var blockHasTopPadding = isBlockTopPadded(node),
+ blockHasBottomPadding = isBlockBottomPadded(node);
+
if (requirePadding) {
- if (!isNonEmptyBlockPadded(node)) {
- context.report(node, "Block must be padded by blank lines.");
+ if (!blockHasTopPadding) {
+ context.report(node, ALWAYS_MESSAGE);
}
+
+ if (!blockHasBottomPadding) {
+ context.report(node, node.loc.end, ALWAYS_MESSAGE);
+ }
} else {
- if (hasNonEmptyBlockExtraPadding(node)) {
- context.report(node, "Block must not be padded by blank lines.");
+ if (blockHasTopPadding) {
+ context.report(node, NEVER_MESSAGE);
}
+
+ if (blockHasBottomPadding) {
+ context.report(node, node.loc.end, NEVER_MESSAGE);
+ }
}
}
}
return {
"BlockStatement": checkPadding
};
};
-},{}],261:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ }
+];
+
+},{}],279:[function(require,module,exports){
/**
+ * @fileoverview A rule to suggest using arrow functions as callbacks.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether or not a given variable is a function name.
+ * @param {escope.Variable} variable - A variable to check.
+ * @returns {boolean} `true` if the variable is a function name.
+ */
+function isFunctionName(variable) {
+ return variable && variable.defs[0].type === "FunctionName";
+}
+
+/**
+ * Checks whether or not a given MetaProperty node equals to a given value.
+ * @param {ASTNode} node - A MetaProperty node to check.
+ * @param {string} metaName - The name of `MetaProperty.meta`.
+ * @param {string} propertyName - The name of `MetaProperty.property`.
+ * @returns {boolean} `true` if the node is the specific value.
+ */
+function checkMetaProperty(node, metaName, propertyName) {
+ // TODO: Remove this if block after https://github.com/eslint/espree/issues/206 was fixed.
+ if (typeof node.meta === "string") {
+ return node.meta === metaName && node.property === propertyName;
+ }
+ return node.meta.name === metaName && node.property.name === propertyName;
+}
+
+/**
+ * Gets the variable object of `arguments` which is defined implicitly.
+ * @param {escope.Scope} scope - A scope to get.
+ * @returns {escope.Variable} The found variable object.
+ */
+function getVariableOfArguments(scope) {
+ var variables = scope.variables;
+ for (var i = 0; i < variables.length; ++i) {
+ var variable = variables[i];
+ if (variable.name === "arguments") {
+ // If there was a parameter which is named "arguments", the implicit "arguments" is not defined.
+ // So does fast return with null.
+ return (variable.identifiers.length === 0) ? variable : null;
+ }
+ }
+
+ /* istanbul ignore next */
+ return null;
+}
+
+/**
+ * Checkes whether or not a given node is a callback.
+ * @param {ASTNode} node - A node to check.
+ * @returns {object}
+ * {boolean} retv.isCallback - `true` if the node is a callback.
+ * {boolean} retv.isLexicalThis - `true` if the node is with `.bind(this)`.
+ */
+function getCallbackInfo(node) {
+ var retv = {isCallback: false, isLexicalThis: false};
+ var parent = node.parent;
+ while (node) {
+ switch (parent.type) {
+ // Checks parents recursively.
+ case "LogicalExpression":
+ case "ConditionalExpression":
+ break;
+
+ // Checks whether the parent node is `.bind(this)` call.
+ case "MemberExpression":
+ if (parent.object === node &&
+ !parent.property.computed &&
+ parent.property.type === "Identifier" &&
+ parent.property.name === "bind" &&
+ parent.parent.type === "CallExpression" &&
+ parent.parent.callee === parent
+ ) {
+ retv.isLexicalThis = (
+ parent.parent.arguments.length === 1 &&
+ parent.parent.arguments[0].type === "ThisExpression"
+ );
+ node = parent;
+ parent = parent.parent;
+ } else {
+ return retv;
+ }
+ break;
+
+ // Checks whether the node is a callback.
+ case "CallExpression":
+ case "NewExpression":
+ if (parent.callee !== node) {
+ retv.isCallback = true;
+ }
+ return retv;
+
+ default:
+ return retv;
+ }
+
+ node = parent;
+ parent = parent.parent;
+ }
+
+ /* istanbul ignore next */
+ throw new Error("unreachable");
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ // {Array<{this: boolean, super: boolean, meta: boolean}>}
+ // - this - A flag which shows there are one or more ThisExpression.
+ // - super - A flag which shows there are one or more Super.
+ // - meta - A flag which shows there are one or more MethProperty.
+ var stack = [];
+
+ /**
+ * Pushes new function scope with all `false` flags.
+ * @returns {void}
+ */
+ function enterScope() {
+ stack.push({this: false, super: false, meta: false});
+ }
+
+ /**
+ * Pops a function scope from the stack.
+ * @returns {{this: boolean, super: boolean, meta: boolean}} The information of the last scope.
+ */
+ function exitScope() {
+ return stack.pop();
+ }
+
+ return {
+ // Reset internal state.
+ Program: function() {
+ stack = [];
+ },
+
+ // If there are below, it cannot replace with arrow functions merely.
+ ThisExpression: function() {
+ var info = stack[stack.length - 1];
+ if (info) {
+ info.this = true;
+ }
+ },
+ Super: function() {
+ var info = stack[stack.length - 1];
+ if (info) {
+ info.super = true;
+ }
+ },
+ MetaProperty: function(node) {
+ var info = stack[stack.length - 1];
+ if (info && checkMetaProperty(node, "new", "target")) {
+ info.meta = true;
+ }
+ },
+
+ // To skip nested scopes.
+ FunctionDeclaration: enterScope,
+ "FunctionDeclaration:exit": exitScope,
+
+ // Main.
+ FunctionExpression: enterScope,
+ "FunctionExpression:exit": function(node) {
+ var scopeInfo = exitScope();
+
+ // Skip generators.
+ if (node.generator) {
+ return;
+ }
+
+ // Skip recursive functions.
+ var nameVar = context.getDeclaredVariables(node)[0];
+ if (isFunctionName(nameVar) && nameVar.references.length > 0) {
+ return;
+ }
+
+ // Skip if it's using arguments.
+ var variable = getVariableOfArguments(context.getScope());
+ if (variable && variable.references.length > 0) {
+ return;
+ }
+
+ // Reports if it's a callback which can replace with arrows.
+ var callbackInfo = getCallbackInfo(node);
+ if (callbackInfo.isCallback &&
+ (!scopeInfo.this || callbackInfo.isLexicalThis) &&
+ !scopeInfo.super &&
+ !scopeInfo.meta
+ ) {
+ context.report(node, "Unexpected function expression.");
+ }
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{}],280:[function(require,module,exports){
+/**
+ * @fileoverview A rule to suggest using of const declaration for variables that are never modified after declared.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ /**
+ * Checks whether a reference is the initializer.
+ * @param {Reference} reference - A reference to check.
+ * @returns {boolean} Whether or not the reference is the initializer.
+ */
+ function isInitializer(reference) {
+ return reference.init === true;
+ }
+
+ /**
+ * Checks whether a reference is read-only or the initializer.
+ * @param {Reference} reference - A reference to check.
+ * @returns {boolean} Whether or not the reference is read-only or the initializer.
+ */
+ function isReadOnlyOrInitializer(reference) {
+ return reference.isReadOnly() || reference.init === true;
+ }
+
+ /**
+ * Searches and reports variables that are never modified after declared.
+ * @param {Scope} scope - A scope of the search domain.
+ * @returns {void}
+ */
+ function checkForVariables(scope) {
+ // Skip the TDZ type.
+ if (scope.type === "TDZ") {
+ return;
+ }
+
+ var variables = scope.variables;
+ for (var i = 0, end = variables.length; i < end; ++i) {
+ var variable = variables[i];
+ var def = variable.defs[0];
+ var declaration = def && def.parent;
+ var statement = declaration && declaration.parent;
+ var references = variable.references;
+ var identifier = variable.identifiers[0];
+
+ if (statement &&
+ identifier &&
+ declaration.type === "VariableDeclaration" &&
+ declaration.kind === "let" &&
+ (statement.type !== "ForStatement" || statement.init !== declaration) &&
+ references.some(isInitializer) &&
+ references.every(isReadOnlyOrInitializer)
+ ) {
+ context.report(
+ identifier,
+ "`{{name}}` is never modified, use `const` instead.",
+ {name: identifier.name});
+ }
+ }
+ }
+
+ /**
+ * Adds multiple items to the tail of an array.
+ * @param {any[]} array - A destination to add.
+ * @param {any[]} values - Items to be added.
+ * @returns {void}
+ */
+ var pushAll = Function.apply.bind(Array.prototype.push);
+
+ return {
+ "Program:exit": function() {
+ var stack = [context.getScope()];
+ while (stack.length) {
+ var scope = stack.pop();
+ pushAll(stack, scope.childScopes);
+
+ checkForVariables(scope);
+ }
+ }
+ };
+
+};
+
+module.exports.schema = [];
+
+},{}],281:[function(require,module,exports){
+/**
+ * @fileoverview Rule to suggest using "Reflect" api over Function/Object methods
+ * @author Keith Cirkel <http://keithcirkel.co.uk>
+ * @copyright 2015 Keith Cirkel. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var existingNames = {
+ "apply": "Function.prototype.apply",
+ "call": "Function.prototype.call",
+ "defineProperty": "Object.defineProperty",
+ "getOwnPropertyDescriptor": "Object.getOwnPropertyDescriptor",
+ "getPrototypeOf": "Object.getPrototypeOf",
+ "setPrototypeOf": "Object.setPrototypeOf",
+ "isExtensible": "Object.isExtensible",
+ "getOwnPropertyNames": "Object.getOwnPropertyNames",
+ "preventExtensions": "Object.preventExtensions"
+ };
+
+ var reflectSubsitutes = {
+ "apply": "Reflect.apply",
+ "call": "Reflect.apply",
+ "defineProperty": "Reflect.defineProperty",
+ "getOwnPropertyDescriptor": "Reflect.getOwnPropertyDescriptor",
+ "getPrototypeOf": "Reflect.getPrototypeOf",
+ "setPrototypeOf": "Reflect.setPrototypeOf",
+ "isExtensible": "Reflect.isExtensible",
+ "getOwnPropertyNames": "Reflect.getOwnPropertyNames",
+ "preventExtensions": "Reflect.preventExtensions"
+ };
+
+ var exceptions = (context.options[0] || {}).exceptions || [];
+
+ /**
+ * Reports the Reflect violation based on the `existing` and `substitute`
+ * @param {Object} node The node that violates the rule.
+ * @param {string} existing The existing method name that has been used.
+ * @param {string} substitute The Reflect substitute that should be used.
+ * @returns {void}
+ */
+ function report(node, existing, substitute) {
+ context.report(node, "Avoid using {{existing}}, instead use {{substitute}}", {
+ existing: existing,
+ substitute: substitute
+ });
+ }
+
+ return {
+ "CallExpression": function(node) {
+ var methodName = (node.callee.property || {}).name;
+ var isReflectCall = (node.callee.object || {}).name === "Reflect";
+ var hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName);
+ var userConfiguredException = exceptions.indexOf(methodName) !== -1;
+ if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) {
+ report(node, existingNames[methodName], reflectSubsitutes[methodName]);
+ }
+ },
+ "UnaryExpression": function(node) {
+ var isDeleteOperator = node.operator === "delete";
+ var targetsIdentifier = node.argument.type === "Identifier";
+ var userConfiguredException = exceptions.indexOf("delete") !== -1;
+ if (isDeleteOperator && !targetsIdentifier && !userConfiguredException) {
+ report(node, "the delete keyword", "Reflect.deleteProperty");
+ }
+ }
+ };
+
+};
+
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "apply",
+ "call",
+ "delete",
+ "defineProperty",
+ "getOwnPropertyDescriptor",
+ "getPrototypeOf",
+ "setPrototypeOf",
+ "isExtensible",
+ "getOwnPropertyNames",
+ "preventExtensions"
+ ]
+ },
+ "uniqueItems": true
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],282:[function(require,module,exports){
+/**
+ * @fileoverview A rule to suggest using of the spread operator instead of `.apply()`.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether or not a node is a `.apply()` for variadic.
+ * @param {ASTNode} node - A CallExpression node to check.
+ * @returns {boolean} Whether or not the node is a `.apply()` for variadic.
+ */
+function isVariadicApplyCalling(node) {
+ return (
+ node.callee.type === "MemberExpression" &&
+ node.callee.property.type === "Identifier" &&
+ node.callee.property.name === "apply" &&
+ node.callee.computed === false &&
+ node.arguments.length === 2 &&
+ node.arguments[1].type !== "ArrayExpression"
+ );
+}
+
+/**
+ * Checks whether or not the tokens of two given nodes are same.
+ * @param {ASTNode} left - A node 1 to compare.
+ * @param {ASTNode} right - A node 2 to compare.
+ * @param {RuleContext} context - The ESLint rule context object.
+ * @returns {boolean} the source code for the given node.
+ */
+function equalTokens(left, right, context) {
+ var tokensL = context.getTokens(left);
+ var tokensR = context.getTokens(right);
+
+ if (tokensL.length !== tokensR.length) {
+ return false;
+ }
+ for (var i = 0; i < tokensL.length; ++i) {
+ if (tokensL[i].type !== tokensR[i].type ||
+ tokensL[i].value !== tokensR[i].value
+ ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Checks whether or not `thisArg` is not changed by `.apply()`.
+ * @param {ASTNode|null} expectedThis - The node that is the owner of the applied function.
+ * @param {ASTNode} thisArg - The node that is given to the first argument of the `.apply()`.
+ * @param {RuleContext} context - The ESLint rule context object.
+ * @returns {boolean} Whether or not `thisArg` is not changed by `.apply()`.
+ */
+function isValidThisArg(expectedThis, thisArg, context) {
+ if (!expectedThis) {
+ return astUtils.isNullOrUndefined(thisArg);
+ }
+ return equalTokens(expectedThis, thisArg, context);
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ return {
+ "CallExpression": function(node) {
+ if (!isVariadicApplyCalling(node)) {
+ return;
+ }
+
+ var applied = node.callee.object;
+ var expectedThis = (applied.type === "MemberExpression") ? applied.object : null;
+ var thisArg = node.arguments[0];
+
+ if (isValidThisArg(expectedThis, thisArg, context)) {
+ context.report(node, "use the spread operator instead of the \".apply()\".");
+ }
+ }
+ };
+};
+
+module.exports.schema = [];
+
+},{"../ast-utils":113}],283:[function(require,module,exports){
+/**
+ * @fileoverview A rule to suggest using template literals instead of string concatenation.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether or not a given node is a concatenation.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} `true` if the node is a concatenation.
+ */
+function isConcatenation(node) {
+ return node.type === "BinaryExpression" && node.operator === "+";
+}
+
+/**
+ * Gets the top binary expression node for concatenation in parents of a given node.
+ * @param {ASTNode} node - A node to get.
+ * @returns {ASTNode} the top binary expression node in parents of a given node.
+ */
+function getTopConcatBinaryExpression(node) {
+ while (isConcatenation(node.parent)) {
+ node = node.parent;
+ }
+ return node;
+}
+
+/**
+ * Checks whether or not a given binary expression has non string literals.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} `true` if the node has non string literals.
+ */
+function hasNonStringLiteral(node) {
+ if (isConcatenation(node)) {
+ // `left` is deeper than `right` normally.
+ return hasNonStringLiteral(node.right) || hasNonStringLiteral(node.left);
+ }
+ return !astUtils.isStringLiteral(node);
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var done = Object.create(null);
+
+ /**
+ * Reports if a given node is string concatenation with non string literals.
+ *
+ * @param {ASTNode} node - A node to check.
+ * @returns {void}
+ */
+ function checkForStringConcat(node) {
+ if (!astUtils.isStringLiteral(node) || !isConcatenation(node.parent)) {
+ return;
+ }
+
+ var topBinaryExpr = getTopConcatBinaryExpression(node.parent);
+
+ // Checks whether or not this node had been checked already.
+ if (done[topBinaryExpr.range[0]]) {
+ return;
+ }
+ done[topBinaryExpr.range[0]] = true;
+
+ if (hasNonStringLiteral(topBinaryExpr)) {
+ context.report(
+ topBinaryExpr,
+ "Unexpected string concatenation.");
+ }
+ }
+
+ return {
+ Program: function() {
+ done = Object.create(null);
+ },
+
+ Literal: checkForStringConcat,
+ TemplateLiteral: checkForStringConcat
+ };
+};
+
+module.exports.schema = [];
+
+},{"../ast-utils":113}],284:[function(require,module,exports){
+/**
* @fileoverview Rule to flag non-quoted property names in object literals.
* @author Mathias Bynens <http://mathiasbynens.be/>
* @copyright 2014 Brandon Mills. All rights reserved.
+ * @copyright 2015 Tomasz Olędzki. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
-var espree = require("espree");
+var espree = require("espree"),
+ keywords = require("../util/keywords");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var MODE = context.options[0];
+ var MODE = context.options[0],
+ KEYWORDS = context.options[1] && context.options[1].keywords,
+ CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false,
+ NUMBERS = context.options[1] && context.options[1].numbers,
+ MESSAGE_UNNECESSARY = "Unnecessarily quoted property `{{property}}` found.",
+ MESSAGE_UNQUOTED = "Unquoted property `{{property}}` found.",
+ MESSAGE_NUMERIC = "Unquoted number literal `{{property}}` used as key.",
+ MESSAGE_RESERVED = "Unquoted reserved word `{{property}}` used as key.";
+
+
/**
+ * Checks whether a certain string constitutes an ES3 token
+ * @param {string} tokenStr - The string to be checked.
+ * @returns {boolean} `true` if it is an ES3 token.
+ */
+ function isKeyword(tokenStr) {
+ return keywords.indexOf(tokenStr) >= 0;
+ }
+
+ /**
+ * Checks if an espree-tokenized key has redundant quotes (i.e. whether quotes are unnecessary)
+ * @param {espreeTokens} tokens The espree-tokenized node key
+ * @param {boolean} [skipNumberLiterals=false] Indicates whether number literals should be checked
+ * @returns {boolean} Whether or not a key has redundant quotes.
+ * @private
+ */
+ function areQuotesRedundant(tokens, skipNumberLiterals) {
+ return tokens.length === 1 &&
+ (["Identifier", "Keyword", "Null", "Boolean"].indexOf(tokens[0].type) >= 0 ||
+ (tokens[0].type === "Numeric" && !skipNumberLiterals && "" + +tokens[0].value === tokens[0].value));
+ }
+
+ /**
* Ensures that a property's key is quoted only when necessary
* @param {ASTNode} node Property AST node
* @returns {void}
*/
- function asNeeded(node) {
+ function checkUnnecessaryQuotes(node) {
var key = node.key,
+ isKeywordToken,
tokens;
+ if (node.method || node.computed || node.shorthand) {
+ return;
+ }
+
if (key.type === "Literal" && typeof key.value === "string") {
try {
tokens = espree.tokenize(key.value);
} catch (e) {
return;
}
- if (tokens.length === 1 &&
- (["Identifier", "Null", "Boolean"].indexOf(tokens[0].type) >= 0 ||
- (tokens[0].type === "Numeric" && "" + +tokens[0].value === tokens[0].value))
- ) {
- context.report(node, "Unnecessarily quoted property `{{value}}` found.", key);
+ if (tokens.length !== 1) {
+ return;
}
+
+ isKeywordToken = isKeyword(tokens[0].value);
+
+ if (isKeywordToken && KEYWORDS) {
+ return;
+ }
+
+ if (CHECK_UNNECESSARY && areQuotesRedundant(tokens, NUMBERS)) {
+ context.report(node, MESSAGE_UNNECESSARY, {property: key.value});
+ }
+ } else if (KEYWORDS && key.type === "Identifier" && isKeyword(key.name)) {
+ context.report(node, MESSAGE_RESERVED, {property: key.name});
+ } else if (NUMBERS && key.type === "Literal" && typeof key.value === "number") {
+ context.report(node, MESSAGE_NUMERIC, {property: key.value});
}
}
/**
* Ensures that a property's key is quoted
* @param {ASTNode} node Property AST node
* @returns {void}
*/
- function always(node) {
+ function checkOmittedQuotes(node) {
var key = node.key;
- if (!(key.type === "Literal" && typeof key.value === "string")) {
- context.report(node, "Unquoted property `{{key}}` found.", {
- key: key.name || key.value
+ if (!node.method && !node.computed && !node.shorthand && !(key.type === "Literal" && typeof key.value === "string")) {
+ context.report(node, MESSAGE_UNQUOTED, {
+ property: key.name || key.value
});
}
}
+ /**
+ * Ensures that an object's keys are consistently quoted, optionally checks for redundancy of quotes
+ * @param {ASTNode} node Property AST node
+ * @param {boolean} checkQuotesRedundancy Whether to check quotes' redundancy
+ * @returns {void}
+ */
+ function checkConsistency(node, checkQuotesRedundancy) {
+ var quotes = false,
+ lackOfQuotes = false,
+ necessaryQuotes = false;
+
+ node.properties.forEach(function(property) {
+ var key = property.key,
+ tokens;
+
+ if (!key || property.method || property.computed || property.shorthand) {
+ return;
+ }
+
+ if (key.type === "Literal" && typeof key.value === "string") {
+
+ quotes = true;
+
+ if (checkQuotesRedundancy) {
+ try {
+ tokens = espree.tokenize(key.value);
+ } catch (e) {
+ necessaryQuotes = true;
+ return;
+ }
+
+ necessaryQuotes = necessaryQuotes || !areQuotesRedundant(tokens) || KEYWORDS && isKeyword(tokens[0].value);
+ }
+ } else if (KEYWORDS && checkQuotesRedundancy && key.type === "Identifier" && isKeyword(key.name)) {
+ necessaryQuotes = true;
+ context.report(node, "Properties should be quoted as `{{property}}` is a reserved word.", {property: key.name});
+ } else {
+ lackOfQuotes = true;
+ }
+
+ if (quotes && lackOfQuotes) {
+ context.report(node, "Inconsistently quoted property `{{key}}` found.", {
+ key: key.name || key.value
+ });
+ }
+ });
+
+ if (checkQuotesRedundancy && quotes && !necessaryQuotes) {
+ context.report(node, "Properties shouldn't be quoted as all quotes are redundant.");
+ }
+ }
+
return {
- "Property": MODE === "as-needed" ? asNeeded : always
+ "Property": function(node) {
+ if (MODE === "always" || !MODE) {
+ checkOmittedQuotes(node);
+ }
+ if (MODE === "as-needed") {
+ checkUnnecessaryQuotes(node);
+ }
+ },
+ "ObjectExpression": function(node) {
+ if (MODE === "consistent") {
+ checkConsistency(node, false);
+ }
+ if (MODE === "consistent-as-needed") {
+ checkConsistency(node, true);
+ }
+ }
};
};
-},{"espree":"espree"}],262:[function(require,module,exports){
+module.exports.schema = {
+ "anyOf": [
+ {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ },
+ {
+ "enum": ["always", "as-needed", "consistent", "consistent-as-needed"]
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 2
+ },
+ {
+ "type": "array",
+ "items": [
+ {
+ "enum": [0, 1, 2]
+ },
+ {
+ "enum": ["always", "as-needed", "consistent", "consistent-as-needed"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "keywords": {
+ "type": "boolean"
+ },
+ "unnecessary": {
+ "type": "boolean"
+ },
+ "numbers": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 3
+ }
+ ]
+};
+
+},{"../util/keywords":313,"espree":"espree"}],285:[function(require,module,exports){
/**
* @fileoverview A rule to choose between single and double quote marks
* @author Matt DuVall <http://www.mattduvall.com/>, Brandon Payton
+ * @copyright 2013 Matt DuVall. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
var QUOTE_SETTINGS = {
"double": {
@@ -26767,69 +39710,181 @@
},
"single": {
quote: "'",
alternateQuote: "\"",
description: "singlequote"
+ },
+ "backtick": {
+ quote: "`",
+ alternateQuote: "\"",
+ description: "backtick"
}
};
+/**
+ * Switches quoting of javascript string between ' " and `
+ * escaping and unescaping as necessary.
+ * Only escaping of the minimal set of characters is changed.
+ * Note: escaping of newlines when switching from backtick to other quotes is not handled.
+ * @param {string} str - A string to convert.
+ * @returns {string} The string with changed quotes.
+ * @private
+ */
+QUOTE_SETTINGS.double.convert =
+QUOTE_SETTINGS.single.convert =
+QUOTE_SETTINGS.backtick.convert = function(str) {
+ var newQuote = this.quote;
+ var oldQuote = str[0];
+ if (newQuote === oldQuote) {
+ return str;
+ }
+ return newQuote + str.slice(1, -1).replace(/\\(\${|\r\n?|\n|.)|["'`]|\${|(\r\n?|\n)/g, function(match, escaped, newline) {
+ if (escaped === oldQuote || oldQuote === "`" && escaped === "${") {
+ return escaped; // unescape
+ }
+ if (match === newQuote || newQuote === "`" && match === "${") {
+ return "\\" + match; // escape
+ }
+ if (newline && oldQuote === "`") {
+ return "\\n"; // escape newlines
+ }
+ return match;
+ }) + newQuote;
+};
-var AVOID_ESCAPE = "avoid-escape";
+var AVOID_ESCAPE = "avoid-escape",
+ FUNCTION_TYPE = /^(?:Arrow)?Function(?:Declaration|Expression)$/;
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ /**
+ * Determines if a given node is part of JSX syntax.
+ * @param {ASTNode} node The node to check.
+ * @returns {boolean} True if the node is a JSX node, false if not.
+ * @private
+ */
+ function isJSXElement(node) {
+ return node.type.indexOf("JSX") === 0;
+ }
/**
- * Validate that a string passed in is surrounded by the specified character
- * @param {string} val The text to check.
- * @param {string} character The character to see if it's surrounded by.
- * @returns {boolean} True if the text is surrounded by the character, false if not.
+ * Checks whether or not a given node is a directive.
+ * The directive is a `ExpressionStatement` which has only a string literal.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node is a directive.
* @private
*/
- function isSurroundedBy(val, character) {
- return val[0] === character && val[val.length - 1] === character;
+ function isDirective(node) {
+ return (
+ node.type === "ExpressionStatement" &&
+ node.expression.type === "Literal" &&
+ typeof node.expression.value === "string"
+ );
}
/**
- * Determines if a given node is part of JSX syntax.
- * @param {ASTNode} node The node to check.
- * @returns {boolean} True if the node is a JSX node, false if not.
+ * Checks whether or not a given node is a part of directive prologues.
+ * See also: http://www.ecma-international.org/ecma-262/6.0/#sec-directive-prologues-and-the-use-strict-directive
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node is a part of directive prologues.
* @private
*/
- function isJSXElement(node) {
- return node.type.indexOf("JSX") === 0;
+ function isPartOfDirectivePrologue(node) {
+ var block = node.parent.parent;
+ if (block.type !== "Program" && (block.type !== "BlockStatement" || !FUNCTION_TYPE.test(block.parent.type))) {
+ return false;
+ }
+
+ // Check the node is at a prologue.
+ for (var i = 0; i < block.body.length; ++i) {
+ var statement = block.body[i];
+
+ if (statement === node.parent) {
+ return true;
+ }
+ if (!isDirective(statement)) {
+ break;
+ }
+ }
+
+ return false;
}
+ /**
+ * Checks whether or not a given node is allowed as non backtick.
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} Whether or not the node is allowed as non backtick.
+ * @private
+ */
+ function isAllowedAsNonBacktick(node) {
+ var parent = node.parent;
+
+ switch (parent.type) {
+ // Directive Prologues.
+ case "ExpressionStatement":
+ return isPartOfDirectivePrologue(node);
+
+ // LiteralPropertyName.
+ case "Property":
+ return parent.key === node && !parent.computed;
+
+ // ModuleSpecifier.
+ case "ImportDeclaration":
+ case "ExportNamedDeclaration":
+ case "ExportAllDeclaration":
+ return parent.source === node;
+
+ // Others don't allow.
+ default:
+ return false;
+ }
+ }
+
return {
"Literal": function(node) {
var val = node.value,
rawVal = node.raw,
quoteOption = context.options[0],
- settings = QUOTE_SETTINGS[quoteOption],
+ settings = QUOTE_SETTINGS[quoteOption || "double"],
avoidEscape = context.options[1] === AVOID_ESCAPE,
isValid;
if (settings && typeof val === "string") {
- isValid = isJSXElement(node.parent) || isSurroundedBy(rawVal, settings.quote);
+ isValid = (quoteOption === "backtick" && isAllowedAsNonBacktick(node)) || isJSXElement(node.parent) || astUtils.isSurroundedBy(rawVal, settings.quote);
if (!isValid && avoidEscape) {
- isValid = isSurroundedBy(rawVal, settings.alternateQuote) && rawVal.indexOf(settings.quote) >= 0;
+ isValid = astUtils.isSurroundedBy(rawVal, settings.alternateQuote) && rawVal.indexOf(settings.quote) >= 0;
}
if (!isValid) {
- context.report(node, "Strings must use " + settings.description + ".");
+ context.report({
+ node: node,
+ message: "Strings must use " + settings.description + ".",
+ fix: function(fixer) {
+ return fixer.replaceText(node, settings.convert(node.raw));
+ }
+ });
}
}
}
};
};
-},{}],263:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["single", "double", "backtick"]
+ },
+ {
+ "enum": ["avoid-escape"]
+ }
+];
+
+},{"../ast-utils":113}],286:[function(require,module,exports){
/**
* @fileoverview Rule to flag use of parseInt without a radix argument
* @author James Allardice
*/
@@ -26839,55 +39894,259 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var MODE_ALWAYS = "always",
+ MODE_AS_NEEDED = "as-needed";
+
+ var mode = context.options[0] || MODE_ALWAYS;
+
return {
"CallExpression": function(node) {
var radix;
- if (node.callee.name === "parseInt") {
+ if (!(node.callee.name === "parseInt" || (
+ node.callee.type === "MemberExpression" &&
+ node.callee.object.name === "Number" &&
+ node.callee.property.name === "parseInt"
+ )
+ )) {
+ return;
+ }
- if (node.arguments.length < 2) {
- context.report(node, "Missing radix parameter.");
- } else {
+ if (node.arguments.length === 0) {
+ context.report({
+ node: node,
+ message: "Missing parameters."
+ });
+ } else if (node.arguments.length < 2 && mode === MODE_ALWAYS) {
+ context.report({
+ node: node,
+ message: "Missing radix parameter."
+ });
+ } else if (node.arguments.length > 1 && mode === MODE_AS_NEEDED &&
+ (node.arguments[1] && node.arguments[1].type === "Literal" &&
+ node.arguments[1].value === 10)
+ ) {
+ context.report({
+ node: node,
+ message: "Redundant radix parameter."
+ });
+ } else {
- radix = node.arguments[1];
+ radix = node.arguments[1];
- // don't allow non-numeric literals or undefined
- if ((radix.type === "Literal" && typeof radix.value !== "number") ||
- (radix.type === "Identifier" && radix.name === "undefined")
- ) {
- context.report(node, "Invalid radix parameter.");
- }
+ // don't allow non-numeric literals or undefined
+ if (radix &&
+ ((radix.type === "Literal" && typeof radix.value !== "number") ||
+ (radix.type === "Identifier" && radix.name === "undefined"))
+ ) {
+ context.report({
+ node: node,
+ message: "Invalid radix parameter."
+ });
}
+ }
+ }
+ };
+
+};
+
+module.exports.schema = [
+ {
+ "enum": ["always", "as-needed"]
+ }
+];
+
+
+},{}],287:[function(require,module,exports){
+/**
+ * @fileoverview Rule to check for jsdoc presence.
+ * @author Gyandeep Singh
+ * @copyright 2015 Gyandeep Singh. All rights reserved.
+ */
+"use strict";
+
+var assign = require("object-assign");
+
+module.exports = function(context) {
+ var source = context.getSourceCode();
+ var DEFAULT_OPTIONS = {
+ "FunctionDeclaration": true,
+ "MethodDefinition": false,
+ "ClassDeclaration": false
+ };
+ var options = assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {});
+
+ /**
+ * Report the error message
+ * @param {ASTNode} node node to report
+ * @returns {void}
+ */
+ function report(node) {
+ context.report(node, "Missing JSDoc comment.");
+ }
+
+ /**
+ * Check if the jsdoc comment is present for class methods
+ * @param {ASTNode} node node to examine
+ * @returns {void}
+ */
+ function checkClassMethodJsDoc(node) {
+ if (node.parent.type === "MethodDefinition") {
+ var jsdocComment = source.getJSDocComment(node);
+
+ if (!jsdocComment) {
+ report(node);
}
}
+ }
+
+ /**
+ * Check if the jsdoc comment is present or not.
+ * @param {ASTNode} node node to examine
+ * @returns {void}
+ */
+ function checkJsDoc(node) {
+ var jsdocComment = source.getJSDocComment(node);
+
+ if (!jsdocComment) {
+ report(node);
+ }
+ }
+
+ return {
+ "FunctionDeclaration": function(node) {
+ if (options.FunctionDeclaration) {
+ checkJsDoc(node);
+ }
+ },
+ "FunctionExpression": function(node) {
+ if (options.MethodDefinition) {
+ checkClassMethodJsDoc(node);
+ }
+ },
+ "ClassDeclaration": function(node) {
+ if (options.ClassDeclaration) {
+ checkJsDoc(node);
+ }
+ }
};
+};
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "require": {
+ "type": "object",
+ "properties": {
+ "ClassDeclaration": {
+ "type": "boolean"
+ },
+ "MethodDefinition": {
+ "type": "boolean"
+ },
+ "FunctionDeclaration": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"object-assign":108}],288:[function(require,module,exports){
+/**
+ * @fileoverview Rule to flag the generator functions that does not have yield.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var stack = [];
+
+ /**
+ * If the node is a generator function, start counting `yield` keywords.
+ * @param {Node} node - A function node to check.
+ * @returns {void}
+ */
+ function beginChecking(node) {
+ if (node.generator) {
+ stack.push(0);
+ }
+ }
+
+ /**
+ * If the node is a generator function, end counting `yield` keywords, then
+ * reports result.
+ * @param {Node} node - A function node to check.
+ * @returns {void}
+ */
+ function endChecking(node) {
+ if (!node.generator) {
+ return;
+ }
+
+ var countYield = stack.pop();
+ if (countYield === 0 && node.body.body.length > 0) {
+ context.report(
+ node,
+ "This generator function does not have `yield`.");
+ }
+ }
+
+ return {
+ "FunctionDeclaration": beginChecking,
+ "FunctionDeclaration:exit": endChecking,
+ "FunctionExpression": beginChecking,
+ "FunctionExpression:exit": endChecking,
+
+ // Increases the count of `yield` keyword.
+ "YieldExpression": function() {
+ /* istanbul ignore else */
+ if (stack.length > 0) {
+ stack[stack.length - 1] += 1;
+ }
+ }
+ };
};
-},{}],264:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],289:[function(require,module,exports){
/**
* @fileoverview Validates spacing before and after semicolon
* @author Mathias Schreck
* @copyright 2015 Mathias Schreck
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
+module.exports = function(context) {
var config = context.options[0],
requireSpaceBefore = false,
- requireSpaceAfter = true;
+ requireSpaceAfter = true,
+ sourceCode = context.getSourceCode();
if (typeof config === "object") {
if (config.hasOwnProperty("before")) {
requireSpaceBefore = config.before;
}
@@ -26895,61 +40154,64 @@
requireSpaceAfter = config.after;
}
}
/**
- * Determines whether two adjacent tokens are have whitespace between them.
- * @param {Object} left - The left token object.
- * @param {Object} right - The right token object.
- * @returns {boolean} Whether or not there is space between the tokens.
- */
- function isSpaced(left, right) {
- return left.range[1] < right.range[0];
- }
-
- /**
- * Checks whether two tokens are on the same line.
- * @param {Object} left The leftmost token.
- * @param {Object} right The rightmost token.
- * @returns {boolean} True if the tokens are on the same line, false if not.
- * @private
- */
- function isSameLine(left, right) {
- return left.loc.end.line === right.loc.start.line;
- }
-
- /**
* Checks if a given token has leading whitespace.
* @param {Object} token The token to check.
* @returns {boolean} True if the given token has leading space, false if not.
*/
function hasLeadingSpace(token) {
var tokenBefore = context.getTokenBefore(token);
- return tokenBefore && isSameLine(tokenBefore, token) && isSpaced(tokenBefore, token);
+ return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && sourceCode.isSpaceBetweenTokens(tokenBefore, token);
}
/**
* Checks if a given token has trailing whitespace.
* @param {Object} token The token to check.
* @returns {boolean} True if the given token has trailing space, false if not.
*/
function hasTrailingSpace(token) {
var tokenAfter = context.getTokenAfter(token);
- return tokenAfter && isSameLine(token, tokenAfter) && isSpaced(token, tokenAfter);
+ return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && sourceCode.isSpaceBetweenTokens(token, tokenAfter);
}
/**
* Checks if the given token is the last token in its line.
* @param {Token} token The token to check.
* @returns {boolean} Whether or not the token is the last in its line.
*/
function isLastTokenInCurrentLine(token) {
var tokenAfter = context.getTokenAfter(token);
- return !(tokenAfter && isSameLine(token, tokenAfter));
+ return !(tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter));
}
/**
+ * Checks if the given token is the first token in its line
+ * @param {Token} token The token to check.
+ * @returns {boolean} Whether or not the token is the first in its line.
+ */
+ function isFirstTokenInCurrentLine(token) {
+ var tokenBefore = context.getTokenBefore(token);
+ return !(tokenBefore && astUtils.isTokenOnSameLine(token, tokenBefore));
+ }
+
+ /**
+ * Checks if the next token of a given token is a closing parenthesis.
+ * @param {Token} token The token to check.
+ * @returns {boolean} Whether or not the next token of a given token is a closing parenthesis.
+ */
+ function isBeforeClosingParen(token) {
+ var nextToken = context.getTokenAfter(token);
+ return (
+ nextToken &&
+ nextToken.type === "Punctuator" &&
+ (nextToken.value === "}" || nextToken.value === ")")
+ );
+ }
+
+ /**
* Checks if the given token is a semicolon.
* @param {Token} token The token to check.
* @returns {boolean} Whether or not the given token is a semicolon.
*/
function isSemicolon(token) {
@@ -26976,11 +40238,11 @@
if (requireSpaceBefore) {
context.report(node, location, "Missing whitespace before semicolon.");
}
}
- if (!isLastTokenInCurrentLine(token)) {
+ if (!isFirstTokenInCurrentLine(token) && !isLastTokenInCurrentLine(token) && !isBeforeClosingParen(token)) {
if (hasTrailingSpace(token)) {
if (!requireSpaceAfter) {
context.report(node, location, "Unexpected whitespace after semicolon.");
}
} else {
@@ -27008,11 +40270,11 @@
"BreakStatement": checkNode,
"ContinueStatement": checkNode,
"DebuggerStatement": checkNode,
"ReturnStatement": checkNode,
"ThrowStatement": checkNode,
- "ForStatement": function (node) {
+ "ForStatement": function(node) {
if (node.init) {
checkSemicolonSpacing(context.getTokenAfter(node.init), node);
}
if (node.test) {
@@ -27020,78 +40282,145 @@
}
}
};
};
-},{}],265:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "before": {
+ "type": "boolean"
+ },
+ "after": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],290:[function(require,module,exports){
/**
* @fileoverview Rule to flag missing semicolons.
* @author Nicholas C. Zakas
+ * @copyright 2013 Nicholas C. Zakas. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
+
module.exports = function(context) {
- var OPT_OUT_PATTERN = /[\[\(\/\+\-]/;
+ var OPT_OUT_PATTERN = /[\[\(\/\+\-]/; // One of [(/+-
- var always = context.options[0] !== "never";
+ var always = context.options[0] !== "never",
+ sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
+ * Reports a semicolon error with appropriate location and message.
+ * @param {ASTNode} node The node with an extra or missing semicolon.
+ * @returns {void}
+ */
+ function report(node) {
+ var message,
+ fix,
+ lastToken = sourceCode.getLastToken(node),
+ loc = lastToken.loc;
+
+ if (always) {
+ message = "Missing semicolon.";
+ loc = loc.end;
+ fix = function(fixer) {
+ return fixer.insertTextAfter(lastToken, ";");
+ };
+ } else {
+ message = "Extra semicolon.";
+ loc = loc.start;
+ fix = function(fixer) {
+ return fixer.remove(lastToken);
+ };
+ }
+
+ context.report({
+ node: node,
+ loc: loc,
+ message: message,
+ fix: fix
+ });
+
+ }
+
+ /**
+ * Checks whether a token is a semicolon punctuator.
+ * @param {Token} token The token.
+ * @returns {boolean} True if token is a semicolon punctuator.
+ */
+ function isSemicolon(token) {
+ return (token.type === "Punctuator" && token.value === ";");
+ }
+
+ /**
* Check if a semicolon is unnecessary, only true if:
* - next token is on a new line and is not one of the opt-out tokens
* - next token is a valid statement divider
* @param {Token} lastToken last token of current node.
- * @param {Token} nextToken next token after current node.
* @returns {boolean} whether the semicolon is unnecessary.
*/
- function isUnnecessarySemicolon(lastToken, nextToken) {
+ function isUnnecessarySemicolon(lastToken) {
+ var isDivider, isOptOutToken, lastTokenLine, nextToken, nextTokenLine;
- var lastTokenLine = lastToken.loc.end.line,
- nextTokenLine = nextToken && nextToken.loc.start.line,
- isOptOutToken = nextToken && OPT_OUT_PATTERN.test(nextToken.value),
- isDivider = nextToken && (nextToken.value === "}" || nextToken.value === ";");
+ if (!isSemicolon(lastToken)) {
+ return false;
+ }
+ nextToken = context.getTokenAfter(lastToken);
+
+ if (!nextToken) {
+ return true;
+ }
+
+ lastTokenLine = lastToken.loc.end.line;
+ nextTokenLine = nextToken.loc.start.line;
+ isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value);
+ isDivider = (nextToken.value === "}" || nextToken.value === ";");
+
return (lastTokenLine !== nextTokenLine && !isOptOutToken) || isDivider;
}
/**
* Checks a node to see if it's followed by a semicolon.
* @param {ASTNode} node The node to check.
* @returns {void}
*/
function checkForSemicolon(node) {
- var lastToken = context.getLastToken(node),
- nextToken = context.getTokenAfter(node);
+ var lastToken = context.getLastToken(node);
if (always) {
- if (lastToken.type !== "Punctuator" || lastToken.value !== ";") {
- context.report(node, lastToken.loc.end, "Missing semicolon.");
+ if (!isSemicolon(lastToken)) {
+ report(node);
}
} else {
- if (lastToken.type === "Punctuator" &&
- lastToken.value === ";" &&
- isUnnecessarySemicolon(lastToken, nextToken)
- ) {
- context.report(node, node.loc.end, "Extra semicolon.");
+ if (isUnnecessarySemicolon(lastToken)) {
+ report(node);
}
}
}
/**
* Checks to see if there's a semicolon after a variable declaration.
* @param {ASTNode} node The node to check.
* @returns {void}
*/
function checkForSemicolonForVariableDeclaration(node) {
-
var ancestors = context.getAncestors(),
parentIndex = ancestors.length - 1,
parent = ancestors[parentIndex];
if ((parent.type !== "ForStatement" || parent.init !== node) &&
@@ -27109,32 +40438,37 @@
"VariableDeclaration": checkForSemicolonForVariableDeclaration,
"ExpressionStatement": checkForSemicolon,
"ReturnStatement": checkForSemicolon,
"ThrowStatement": checkForSemicolon,
+ "DoWhileStatement": checkForSemicolon,
"DebuggerStatement": checkForSemicolon,
"BreakStatement": checkForSemicolon,
"ContinueStatement": checkForSemicolon,
- "EmptyStatement": function (node) {
- var lastToken, nextToken;
-
- if (!always) {
- lastToken = context.getLastToken(node);
- nextToken = context.getTokenAfter(node) || context.getLastToken(node);
-
- if (isUnnecessarySemicolon(lastToken, nextToken)) {
- context.report(node, "Extra semicolon.");
- }
+ "ImportDeclaration": checkForSemicolon,
+ "ExportAllDeclaration": checkForSemicolon,
+ "ExportNamedDeclaration": function(node) {
+ if (!node.declaration) {
+ checkForSemicolon(node);
}
-
-
+ },
+ "ExportDefaultDeclaration": function(node) {
+ if (!/(?:Class|Function)Declaration/.test(node.declaration.type)) {
+ checkForSemicolon(node);
+ }
}
};
};
-},{}],266:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ }
+];
+
+},{}],291:[function(require,module,exports){
/**
* @fileoverview Rule to require sorting of variables within a single Variable Declaration block
* @author Ilya Volodin
*/
@@ -27150,10 +40484,14 @@
ignoreCase = configuration.ignoreCase || false;
return {
"VariableDeclaration": function(node) {
node.declarations.reduce(function(memo, decl) {
+ if (decl.id.type === "ObjectPattern" || decl.id.type === "ArrayPattern") {
+ return memo;
+ }
+
var lastVariableName = memo.id.name,
currenVariableName = decl.id.name;
if (ignoreCase) {
lastVariableName = lastVariableName.toLowerCase();
@@ -27169,56 +40507,23 @@
}, node.declarations[0]);
}
};
};
-},{}],267:[function(require,module,exports){
-/**
- * @fileoverview Rule to enforce consistent spacing after function names
- * @author Roberto Vidal
- * @copyright 2014 Roberto Vidal. All rights reserved.
- */
-"use strict";
-
-//------------------------------------------------------------------------------
-// Rule Definition
-//------------------------------------------------------------------------------
-
-module.exports = function(context) {
-
- var requiresSpace = context.options[0] === "always";
-
- /**
- * Reports if the give named function node has the correct spacing after its name
- *
- * @param {ASTNode} node The node to which the potential problem belongs.
- * @returns {void}
- */
- function check(node) {
- var tokens = context.getFirstTokens(node, 3),
- hasSpace = tokens[1].range[1] < tokens[2].range[0];
-
- if (hasSpace !== requiresSpace) {
- context.report(node, "Function name \"{{name}}\" must {{not}}be followed by whitespace.", {
- name: node.id.name,
- not: requiresSpace ? "" : "not "
- });
- }
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "ignoreCase": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
}
+];
- return {
- "FunctionDeclaration": check,
- "FunctionExpression": function (node) {
- if (node.id) {
- check(node);
- }
- }
- };
-
-};
-
-},{}],268:[function(require,module,exports){
+},{}],292:[function(require,module,exports){
/**
* @fileoverview Rule to enforce the number of spaces after certain keywords
* @author Nick Fisher
* @copyright 2014 Nick Fisher. All rights reserved.
*/
@@ -27240,18 +40545,50 @@
* @param {Token} left The first token.
* @param {Token} right The second token
* @returns {void}
*/
function checkTokens(node, left, right) {
+ if (right.type !== "Punctuator") {
+ return;
+ }
+
var hasSpace = left.range[1] < right.range[0],
value = left.value;
if (hasSpace !== requiresSpace) {
- context.report(node, "Keyword \"{{value}}\" must {{not}}be followed by whitespace.", {
- value: value,
- not: requiresSpace ? "" : "not "
+ context.report({
+ node: node,
+ loc: left.loc.end,
+ message: "Keyword \"{{value}}\" must {{not}}be followed by whitespace.",
+ data: {
+ value: value,
+ not: requiresSpace ? "" : "not "
+ },
+ fix: function(fixer) {
+ if (requiresSpace) {
+ return fixer.insertTextAfter(left, " ");
+ } else {
+ return fixer.removeRange([left.range[1], right.range[0]]);
+ }
+ }
});
+ } else if (left.loc.end.line !== right.loc.start.line) {
+ context.report({
+ node: node,
+ loc: left.loc.end,
+ message: "Keyword \"{{value}}\" must not be followed by a newline.",
+ data: {
+ value: value
+ },
+ fix: function(fixer) {
+ var text = "";
+ if (requiresSpace) {
+ text = " ";
+ }
+ return fixer.replaceTextRange([left.range[1], right.range[0]], text);
+ }
+ });
}
}
/**
* Check if the given node (`if`, `for`, `while`, etc), has the correct spacing after it.
@@ -27262,95 +40599,124 @@
var tokens = context.getFirstTokens(node, 2);
checkTokens(node, tokens[0], tokens[1]);
}
return {
- "IfStatement": function (node) {
+ "IfStatement": function(node) {
check(node);
// check the `else`
if (node.alternate && node.alternate.type !== "IfStatement") {
checkTokens(node.alternate, context.getTokenBefore(node.alternate), context.getFirstToken(node.alternate));
}
},
"ForStatement": check,
"ForOfStatement": check,
"ForInStatement": check,
"WhileStatement": check,
- "DoWhileStatement": function (node) {
+ "DoWhileStatement": function(node) {
check(node);
// check the `while`
- var whileTokens = context.getTokensBefore(node.test, 2);
+ var whileTokens = context.getTokensAfter(node.body, 2);
checkTokens(node, whileTokens[0], whileTokens[1]);
},
"SwitchStatement": check,
- "TryStatement": function (node) {
+ "TryStatement": function(node) {
check(node);
// check the `finally`
if (node.finalizer) {
checkTokens(node.finalizer, context.getTokenBefore(node.finalizer), context.getFirstToken(node.finalizer));
}
},
- "CatchStatement": check,
+ "CatchClause": check,
"WithStatement": check
};
};
-},{}],269:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ }
+];
+
+},{}],293:[function(require,module,exports){
/**
* @fileoverview A rule to ensure whitespace before blocks.
* @author Mathias Schreck <https://github.com/lo1tuma>
* @copyright 2014 Mathias Schreck. All rights reserved.
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
- var requireSpace = context.options[0] !== "never";
+module.exports = function(context) {
+ var config = context.options[0],
+ sourceCode = context.getSourceCode(),
+ checkFunctions = true,
+ checkKeywords = true;
- /**
- * Determines whether two adjacent tokens are have whitespace between them.
- * @param {Object} left - The left token object.
- * @param {Object} right - The right token object.
- * @returns {boolean} Whether or not there is space between the tokens.
- */
- function isSpaced(left, right) {
- return left.range[1] < right.range[0];
+ if (typeof config === "object") {
+ checkFunctions = config.functions !== "never";
+ checkKeywords = config.keywords !== "never";
+ } else if (config === "never") {
+ checkFunctions = false;
+ checkKeywords = false;
}
/**
- * Determines whether two adjacent tokens are on the same line.
- * @param {Object} left - The left token object.
- * @param {Object} right - The right token object.
- * @returns {boolean} Whether or not the tokens are on the same line.
+ * Checks whether or not a given token is an arrow operator (=>).
+ *
+ * @param {Token} token - A token to check.
+ * @returns {boolean} `true` if the token is an arrow operator.
*/
- function isSameLine(left, right) {
- return left.loc.start.line === right.loc.start.line;
+ function isArrow(token) {
+ return token.type === "Punctuator" && token.value === "=>";
}
/**
* Checks the given BlockStatement node has a preceding space if it doesn’t start on a new line.
* @param {ASTNode|Token} node The AST node of a BlockStatement.
* @returns {void} undefined.
*/
function checkPrecedingSpace(node) {
var precedingToken = context.getTokenBefore(node),
- hasSpace;
+ hasSpace,
+ parent,
+ requireSpace;
- if (precedingToken && isSameLine(precedingToken, node)) {
- hasSpace = isSpaced(precedingToken, node);
+ if (precedingToken && !isArrow(precedingToken) && astUtils.isTokenOnSameLine(precedingToken, node)) {
+ hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node);
+ parent = context.getAncestors().pop();
+ if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") {
+ requireSpace = checkFunctions;
+ } else {
+ requireSpace = checkKeywords;
+ }
if (requireSpace) {
if (!hasSpace) {
- context.report(node, "Missing space before opening brace.");
+ context.report({
+ node: node,
+ message: "Missing space before opening brace.",
+ fix: function(fixer) {
+ return fixer.insertTextBefore(node, " ");
+ }
+ });
}
} else {
if (hasSpace) {
- context.report(node, "Unexpected space before opening brace.");
+ context.report({
+ node: node,
+ message: "Unexpected space before opening brace.",
+ fix: function(fixer) {
+ return fixer.removeRange([precedingToken.range[1], node.range[0]]);
+ }
+ });
}
}
}
}
@@ -27374,30 +40740,55 @@
checkPrecedingSpace(openingBrace);
}
return {
"BlockStatement": checkPrecedingSpace,
+ "ClassBody": checkPrecedingSpace,
"SwitchStatement": checkSpaceBeforeCaseBlock
};
};
-},{}],270:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "oneOf": [
+ {
+ "enum": ["always", "never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "keywords": {
+ "enum": ["always", "never"]
+ },
+ "functions": {
+ "enum": ["always", "never"]
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ }
+];
+
+},{"../ast-utils":113}],294:[function(require,module,exports){
/**
- * @fileoverview Rule to validate spacing before function parentheses.
+ * @fileoverview Rule to validate spacing before function paren.
* @author Mathias Schreck <https://github.com/lo1tuma>
* @copyright 2015 Mathias Schreck
+ * See LICENSE in root directory for full license.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
var configuration = context.options[0],
+ sourceCode = context.getSourceCode(),
requireAnonymousFunctionSpacing = true,
requireNamedFunctionSpacing = true;
if (typeof configuration === "object") {
requireAnonymousFunctionSpacing = configuration.anonymous !== "never";
@@ -27406,20 +40797,10 @@
requireAnonymousFunctionSpacing = false;
requireNamedFunctionSpacing = false;
}
/**
- * Determines whether two adjacent tokens are have whitespace between them.
- * @param {Object} left - The left token object.
- * @param {Object} right - The right token object.
- * @returns {boolean} Whether or not there is space between the tokens.
- */
- function isSpaced(left, right) {
- return left.range[1] < right.range[0];
- }
-
- /**
* Determines whether a function has a name.
* @param {ASTNode} node The function node.
* @returns {boolean} Whether the function has a name.
*/
function isNamedFunction(node) {
@@ -27427,568 +40808,554 @@
if (node.id) {
return true;
}
- parent = context.getAncestors().pop();
- return parent.type === "Property" && (
- parent.kind === "get" ||
- parent.kind === "set" ||
- parent.method
- );
+ parent = node.parent;
+ return parent.type === "MethodDefinition" ||
+ (parent.type === "Property" &&
+ (
+ parent.kind === "get" ||
+ parent.kind === "set" ||
+ parent.method
+ )
+ );
}
/**
* Validates the spacing before function parentheses.
* @param {ASTNode} node The node to be validated.
* @returns {void}
*/
function validateSpacingBeforeParentheses(node) {
var isNamed = isNamedFunction(node),
- tokens,
leftToken,
rightToken,
location;
if (node.generator && !isNamed) {
return;
}
- tokens = context.getTokens(node);
-
- if (node.generator) {
- leftToken = tokens[2];
- rightToken = tokens[3];
- } else if (isNamed) {
- if (node.id) {
- leftToken = tokens[1];
- rightToken = tokens[2];
- } else {
- // Object methods are named but don't have an id
- leftToken = context.getTokenBefore(node);
- rightToken = tokens[0];
- }
- } else {
- leftToken = tokens[0];
- rightToken = tokens[1];
+ rightToken = sourceCode.getFirstToken(node);
+ while (rightToken.value !== "(") {
+ rightToken = sourceCode.getTokenAfter(rightToken);
}
-
+ leftToken = context.getTokenBefore(rightToken);
location = leftToken.loc.end;
- if (isSpaced(leftToken, rightToken)) {
+ if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) {
if ((isNamed && !requireNamedFunctionSpacing) || (!isNamed && !requireAnonymousFunctionSpacing)) {
- context.report(node, location, "Unexpected space before function parentheses.");
+ context.report({
+ node: node,
+ loc: location,
+ message: "Unexpected space before function parentheses.",
+ fix: function(fixer) {
+ return fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
+ }
+ });
}
} else {
if ((isNamed && requireNamedFunctionSpacing) || (!isNamed && requireAnonymousFunctionSpacing)) {
- context.report(node, location, "Missing space before function parentheses.");
+ context.report({
+ node: node,
+ loc: location,
+ message: "Missing space before function parentheses.",
+ fix: function(fixer) {
+ return fixer.insertTextAfter(leftToken, " ");
+ }
+ });
}
}
}
return {
"FunctionDeclaration": validateSpacingBeforeParentheses,
"FunctionExpression": validateSpacingBeforeParentheses
};
};
-},{}],271:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "oneOf": [
+ {
+ "enum": ["always", "never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "anonymous": {
+ "enum": ["always", "never"]
+ },
+ "named": {
+ "enum": ["always", "never"]
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ }
+];
+
+},{}],295:[function(require,module,exports){
/**
- * @fileoverview Disallows or enforces spaces inside of brackets.
- * @author Ian Christian Myers
- * @copyright 2014 Brandyn Bennett. All rights reserved.
- * @copyright 2014 Michael Ficarra. No rights reserved.
- * @copyright 2014 Vignesh Anand. All rights reserved.
+ * @fileoverview Require or disallow spaces before keywords
+ * @author Marko Raatikka
+ * @copyright 2015 Marko Raatikka. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
+var ERROR_MSG_SPACE_EXPECTED = "Missing space before keyword \"{{keyword}}\".";
+var ERROR_MSG_NO_SPACE_EXPECTED = "Unexpected space before keyword \"{{keyword}}\".";
+
module.exports = function(context) {
- var spaced = context.options[0] === "always";
- /**
- * Determines whether an option is set, relative to the spacing option.
- * If spaced is "always", then check whether option is set to false.
- * If spaced is "never", then check whether option is set to true.
- * @param {Object} option - The option to exclude.
- * @returns {boolean} Whether or not the property is excluded.
- */
- function isOptionSet(option) {
- return context.options[1] != null ? context.options[1][option] === !spaced : false;
- }
+ var sourceCode = context.getSourceCode();
- var options = {
- spaced: spaced,
- singleElementException: isOptionSet("singleValue"),
- objectsInArraysException: isOptionSet("objectsInArrays"),
- arraysInArraysException: isOptionSet("arraysInArrays"),
- arraysInObjectsException: isOptionSet("arraysInObjects"),
- objectsInObjectsException: isOptionSet("objectsInObjects"),
- propertyNameException: isOptionSet("propertyName")
- };
+ var SPACE_REQUIRED = context.options[0] !== "never";
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
- * Determines whether two adjacent tokens are have whitespace between them.
- * @param {Object} left - The left token object.
- * @param {Object} right - The right token object.
- * @returns {boolean} Whether or not there is space between the tokens.
+ * Report the error message
+ * @param {ASTNode} node node to report
+ * @param {string} message Error message to be displayed
+ * @param {object} data Data object for the rule message
+ * @returns {void}
*/
- function isSpaced(left, right) {
- return left.range[1] < right.range[0];
+ function report(node, message, data) {
+ context.report({
+ node: node,
+ message: message,
+ data: data,
+ fix: function(fixer) {
+ if (SPACE_REQUIRED) {
+ return fixer.insertTextBefore(node, " ");
+ } else {
+ var tokenBefore = context.getTokenBefore(node);
+ return fixer.removeRange([tokenBefore.range[1], node.range[0]]);
+ }
+ }
+ });
}
/**
- * Determines whether two adjacent tokens are on the same line.
- * @param {Object} left - The left token object.
- * @param {Object} right - The right token object.
- * @returns {boolean} Whether or not the tokens are on the same line.
+ * Check if a token meets the criteria
+ *
+ * @param {ASTNode} node The node to check
+ * @param {Object} left The left-hand side token of the node
+ * @param {Object} right The right-hand side token of the node
+ * @param {Object} options See check()
+ * @returns {void}
*/
- function isSameLine(left, right) {
- return left.loc.start.line === right.loc.start.line;
- }
+ function checkTokens(node, left, right, options) {
- /**
- * Reports that there shouldn't be a space after the first token
- * @param {ASTNode} node - The node to report in the event of an error.
- * @param {Token} token - The token to use for the report.
- * @returns {void}
- */
- function reportNoBeginningSpace(node, token) {
- context.report(node, token.loc.start,
- "There should be no space after '" + token.value + "'");
- }
+ if (!left) {
+ return;
+ }
- /**
- * Reports that there shouldn't be a space before the last token
- * @param {ASTNode} node - The node to report in the event of an error.
- * @param {Token} token - The token to use for the report.
- * @returns {void}
- */
- function reportNoEndingSpace(node, token) {
- context.report(node, token.loc.start,
- "There should be no space before '" + token.value + "'");
- }
+ if (left.type === "Keyword") {
+ return;
+ }
- /**
- * Reports that there should be a space after the first token
- * @param {ASTNode} node - The node to report in the event of an error.
- * @param {Token} token - The token to use for the report.
- * @returns {void}
- */
- function reportRequiredBeginningSpace(node, token) {
- context.report(node, token.loc.start,
- "A space is required after '" + token.value + "'");
- }
+ if (!SPACE_REQUIRED && typeof options.requireSpace === "undefined") {
+ return;
+ }
- /**
- * Reports that there should be a space before the last token
- * @param {ASTNode} node - The node to report in the event of an error.
- * @param {Token} token - The token to use for the report.
- * @returns {void}
- */
- function reportRequiredEndingSpace(node, token) {
- context.report(node, token.loc.start,
- "A space is required before '" + token.value + "'");
- }
+ options = options || {};
+ options.allowedPrecedingChars = options.allowedPrecedingChars || [ "{" ];
+ options.requireSpace = typeof options.requireSpace === "undefined" ? SPACE_REQUIRED : options.requireSpace;
+ var hasSpace = sourceCode.isSpaceBetweenTokens(left, right);
+ var spaceOk = hasSpace === options.requireSpace;
- //--------------------------------------------------------------------------
- // Public
- //--------------------------------------------------------------------------
+ if (spaceOk) {
+ return;
+ }
- return {
-
- MemberExpression: function(node) {
- if (!node.computed) {
- return;
+ if (!astUtils.isTokenOnSameLine(left, right)) {
+ if (!options.requireSpace) {
+ report(node, ERROR_MSG_NO_SPACE_EXPECTED, { keyword: right.value });
}
+ return;
+ }
- var property = node.property,
- before = context.getTokenBefore(property),
- first = context.getFirstToken(property),
- last = context.getLastToken(property),
- after = context.getTokenAfter(property);
+ if (!options.requireSpace) {
+ report(node, ERROR_MSG_NO_SPACE_EXPECTED, { keyword: right.value });
+ return;
+ }
- var propertyNameMustBeSpaced = options.propertyNameException ?
- !options.spaced : options.spaced;
+ if (options.allowedPrecedingChars.indexOf(left.value) !== -1) {
+ return;
+ }
- if (isSameLine(before, first)) {
- if (propertyNameMustBeSpaced) {
- if (!isSpaced(before, first) && isSameLine(before, first)) {
- reportRequiredBeginningSpace(node, before);
- }
- } else {
- if (isSpaced(before, first)) {
- reportNoBeginningSpace(node, before);
- }
- }
- }
+ report(node, ERROR_MSG_SPACE_EXPECTED, { keyword: right.value });
- if (isSameLine(last, after)) {
- if (propertyNameMustBeSpaced) {
- if (!isSpaced(last, after) && isSameLine(last, after)) {
- reportRequiredEndingSpace(node, after);
- }
- } else {
- if (isSpaced(last, after)) {
- reportNoEndingSpace(node, after);
- }
- }
- }
- },
+ }
- ArrayExpression: function(node) {
- if (node.elements.length === 0) {
- return;
- }
+ /**
+ * Get right and left tokens of a node and check to see if they meet the given criteria
+ *
+ * @param {ASTNode} node The node to check
+ * @param {Object} options Options to validate the node against
+ * @param {Array} options.allowedPrecedingChars Characters that can precede the right token
+ * @param {Boolean} options.requireSpace Whether or not the right token needs to be
+ * preceded by a space
+ * @returns {void}
+ */
+ function check(node, options) {
- var first = context.getFirstToken(node),
- second = context.getFirstToken(node, 1),
- penultimate = context.getLastToken(node, 1),
- last = context.getLastToken(node);
+ options = options || {};
- var openingBracketMustBeSpaced =
- options.objectsInArraysException && second.value === "{" ||
- options.arraysInArraysException && second.value === "[" ||
- options.singleElementException && node.elements.length === 1
- ? !options.spaced : options.spaced;
+ var left = context.getTokenBefore(node);
+ var right = context.getFirstToken(node);
- var closingBracketMustBeSpaced =
- options.objectsInArraysException && penultimate.value === "}" ||
- options.arraysInArraysException && penultimate.value === "]" ||
- options.singleElementException && node.elements.length === 1
- ? !options.spaced : options.spaced;
+ checkTokens(node, left, right, options);
- if (isSameLine(first, second)) {
- if (openingBracketMustBeSpaced && !isSpaced(first, second)) {
- reportRequiredBeginningSpace(node, first);
- }
- if (!openingBracketMustBeSpaced && isSpaced(first, second)) {
- reportNoBeginningSpace(node, first);
- }
- }
+ }
- if (isSameLine(penultimate, last)) {
- if (closingBracketMustBeSpaced && !isSpaced(penultimate, last)) {
- reportRequiredEndingSpace(node, last);
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ return {
+
+ "IfStatement": function(node) {
+ // if
+ check(node);
+ // else
+ if (node.alternate) {
+ var tokens = context.getTokensBefore(node.alternate, 2);
+ if (tokens[0].value === "}") {
+ check(tokens[1], { requireSpace: SPACE_REQUIRED });
}
- if (!closingBracketMustBeSpaced && isSpaced(penultimate, last)) {
- reportNoEndingSpace(node, last);
- }
}
},
+ "ForStatement": check,
+ "ForInStatement": check,
+ "WhileStatement": check,
+ "DoWhileStatement": function(node) {
+ var whileNode = context.getTokenAfter(node.body);
+ // do
+ check(node);
+ // while
+ check(whileNode, { requireSpace: SPACE_REQUIRED });
+ },
+ "SwitchStatement": function(node) {
+ // switch
+ check(node);
+ // case/default
+ node.cases.forEach(function(caseNode) {
+ check(caseNode);
+ });
+ },
+ "ThrowStatement": check,
+ "TryStatement": function(node) {
+ // try
+ check(node);
+ // finally
+ if (node.finalizer) {
+ check(context.getTokenBefore(node.finalizer), { requireSpace: SPACE_REQUIRED });
+ }
+ },
+ "CatchClause": function(node) {
+ check(node, { requireSpace: SPACE_REQUIRED });
+ },
+ "WithStatement": check,
+ "VariableDeclaration": function(node) {
+ check(node, { allowedPrecedingChars: [ "(", "{" ] });
+ },
+ "ReturnStatement": check,
+ "BreakStatement": check,
+ "LabeledStatement": check,
+ "ContinueStatement": check,
+ "FunctionDeclaration": check,
+ "FunctionExpression": function(node) {
+ var left = context.getTokenBefore(node);
+ var right = context.getFirstToken(node);
- ObjectExpression: function(node) {
- if (node.properties.length === 0) {
+ // If it's a method, a getter, or a setter, the first token is not the `function` keyword.
+ if (right.type !== "Keyword") {
return;
}
- var first = context.getFirstToken(node),
- second = context.getFirstToken(node, 1),
- penultimate = context.getLastToken(node, 1),
- last = context.getLastToken(node);
+ checkTokens(node, left, right, { allowedPrecedingChars: [ "(", "{" ] });
+ },
+ "YieldExpression": function(node) {
+ check(node, { allowedPrecedingChars: [ "(", "{" ] });
+ },
+ "ForOfStatement": check,
+ "ClassBody": function(node) {
- var closingCurlyBraceMustBeSpaced =
- options.arraysInObjectsException && penultimate.value === "]" ||
- options.objectsInObjectsException && penultimate.value === "}"
- ? !options.spaced : options.spaced;
-
- if (isSameLine(first, second)) {
- if (options.spaced && !isSpaced(first, second)) {
- reportRequiredBeginningSpace(node, first);
- }
- if (!options.spaced && isSpaced(first, second)) {
- reportNoBeginningSpace(node, first);
- }
+ // Find the 'class' token
+ while (node.value !== "class") {
+ node = context.getTokenBefore(node);
}
- if (isSameLine(penultimate, last)) {
- if (closingCurlyBraceMustBeSpaced && !isSpaced(penultimate, last)) {
- reportRequiredEndingSpace(node, last);
- }
- if (!closingCurlyBraceMustBeSpaced && isSpaced(penultimate, last)) {
- reportNoEndingSpace(node, last);
- }
- }
+ check(node);
}
-
};
};
-},{}],272:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ }
+];
+
+},{"../ast-utils":113}],296:[function(require,module,exports){
/**
* @fileoverview Disallows or enforces spaces inside of parentheses.
* @author Jonathan Rajavuori
* @copyright 2014 David Clark. All rights reserved.
* @copyright 2014 Jonathan Rajavuori. All rights reserved.
*/
"use strict";
+var astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
var MISSING_SPACE_MESSAGE = "There must be a space inside this paren.",
REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.",
- exceptionsArray = (context.options.length === 2) ? context.options[1].exceptions : [],
+ ALWAYS = context.options[0] === "always",
+
+ exceptionsArrayOptions = (context.options.length === 2) ? context.options[1].exceptions : [],
options = {},
- rejectedSpaceRegExp,
- missingSpaceRegExp,
- spaceChecks;
+ exceptions;
- if (exceptionsArray && exceptionsArray.length) {
- options.braceException = exceptionsArray.indexOf("{}") !== -1 || false;
- options.bracketException = exceptionsArray.indexOf("[]") !== -1 || false;
- options.parenException = exceptionsArray.indexOf("()") !== -1 || false;
- options.empty = exceptionsArray.indexOf("empty") !== -1 || false;
+ if (exceptionsArrayOptions.length) {
+ options.braceException = exceptionsArrayOptions.indexOf("{}") !== -1;
+ options.bracketException = exceptionsArrayOptions.indexOf("[]") !== -1;
+ options.parenException = exceptionsArrayOptions.indexOf("()") !== -1;
+ options.empty = exceptionsArrayOptions.indexOf("empty") !== -1;
}
/**
- * Used with the `never` option to produce, given the exception options,
- * two regular expressions to check for missing and rejected spaces.
+ * Produces an object with the opener and closer exception values
* @param {Object} opts The exception options
- * @returns {Object} `missingSpace` and `rejectedSpace` regular expressions
+ * @returns {Object} `openers` and `closers` exception values
* @private
*/
- function getNeverChecks(opts) {
- var missingSpaceOpeners = [],
- missingSpaceClosers = [],
- rejectedSpaceOpeners = [" ", "\\n", "\\r"],
- rejectedSpaceClosers = [" ", "\\n", "\\r"],
- missingSpaceCheck,
- rejectedSpaceCheck;
-
- // Populate openers and closers
- if (opts.braceException) {
- missingSpaceOpeners.push("\\{");
- missingSpaceClosers.push("\\}");
- rejectedSpaceOpeners.push("\\{");
- rejectedSpaceClosers.push("\\}");
+ function getExceptions() {
+ var openers = [],
+ closers = [];
+ if (options.braceException) {
+ openers.push("{");
+ closers.push("}");
}
- if (opts.bracketException) {
- missingSpaceOpeners.push("\\[");
- missingSpaceClosers.push("\\]");
- rejectedSpaceOpeners.push("\\[");
- rejectedSpaceClosers.push("\\]");
- }
- if (opts.parenException) {
- missingSpaceOpeners.push("\\(");
- missingSpaceClosers.push("\\)");
- rejectedSpaceOpeners.push("\\(");
- rejectedSpaceClosers.push("\\)");
- }
- if (opts.empty) {
- missingSpaceOpeners.push("\\)");
- missingSpaceClosers.push("\\(");
- rejectedSpaceOpeners.push("\\)");
- rejectedSpaceClosers.push("\\(");
- }
- if (missingSpaceOpeners.length) {
- missingSpaceCheck = "\\((" + missingSpaceOpeners.join("|") + ")";
- if (missingSpaceClosers.length) {
- missingSpaceCheck += "|";
- }
+ if (options.bracketException) {
+ openers.push("[");
+ closers.push("]");
}
- if (missingSpaceClosers.length) {
- missingSpaceCheck += "(" + missingSpaceClosers.join("|") + ")\\)";
- }
- // compose the rejected regexp
- rejectedSpaceCheck = "\\( +[^" + rejectedSpaceOpeners.join("") + "]";
- rejectedSpaceCheck += "|[^" + rejectedSpaceClosers.join("") + "] +\\)";
-
- return {
- // e.g. \((\{)|(\})\) --- where {} is an exception
- missingSpace: missingSpaceCheck || ".^",
- // e.g. \( +[^ \n\r\{]|[^ \n\r\}] +\) --- where {} is an exception
- rejectedSpace: rejectedSpaceCheck
- };
- }
-
- /**
- * Used with the `always` option to produce, given the exception options,
- * two regular expressions to check for missing and rejected spaces.
- * @param {Object} opts The exception options
- * @returns {Object} `missingSpace` and `rejectedSpace` regular expressions
- * @private
- */
- function getAlwaysChecks(opts) {
- var missingSpaceOpeners = [" ", "\\)", "\\r", "\\n"],
- missingSpaceClosers = [" ", "\\(", "\\r", "\\n"],
- rejectedSpaceOpeners = [],
- rejectedSpaceClosers = [],
- missingSpaceCheck,
- rejectedSpaceCheck;
-
- // Populate openers and closers
- if (opts.braceException) {
- missingSpaceOpeners.push("\\{");
- missingSpaceClosers.push("\\}");
- rejectedSpaceOpeners.push(" \\{");
- rejectedSpaceClosers.push("\\} ");
+ if (options.parenException) {
+ openers.push("(");
+ closers.push(")");
}
- if (opts.bracketException) {
- missingSpaceOpeners.push("\\[");
- missingSpaceClosers.push("\\]");
- rejectedSpaceOpeners.push(" \\[");
- rejectedSpaceClosers.push("\\] ");
- }
- if (opts.parenException) {
- missingSpaceOpeners.push("\\(");
- missingSpaceClosers.push("\\)");
- rejectedSpaceOpeners.push(" \\(");
- rejectedSpaceClosers.push("\\) ");
- }
- if (opts.empty) {
- rejectedSpaceOpeners.push(" \\)");
- rejectedSpaceClosers.push("\\( ");
- }
- // compose the allowed regexp
- missingSpaceCheck = "\\([^" + missingSpaceOpeners.join("") + "]";
- missingSpaceCheck += "|[^" + missingSpaceClosers.join("") + "]\\)";
-
- // compose the rejected regexp
- if (rejectedSpaceOpeners.length) {
- rejectedSpaceCheck = "\\((" + rejectedSpaceOpeners.join("|") + ")";
- if (rejectedSpaceClosers.length) {
- rejectedSpaceCheck += "|";
- }
+ if (options.empty) {
+ openers.push(")");
+ closers.push("(");
}
- if (rejectedSpaceClosers.length) {
- rejectedSpaceCheck += "(" + rejectedSpaceClosers.join("|") + ")\\)";
- }
return {
- // e.g. \([^ \)\r\n\{]|[^ \(\r\n\}]\) --- where {} is an exception
- missingSpace: missingSpaceCheck,
- // e.g. \(( \{})|(\} )\) --- where {} is an excpetion
- rejectedSpace: rejectedSpaceCheck || ".^"
+ openers: openers,
+ closers: closers
};
}
- spaceChecks = (context.options[0] === "always") ? getAlwaysChecks(options) : getNeverChecks(options);
- missingSpaceRegExp = new RegExp(spaceChecks.missingSpace, "mg");
- rejectedSpaceRegExp = new RegExp(spaceChecks.rejectedSpace, "mg");
-
-
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
+ var sourceCode = context.getSourceCode();
- var skipRanges = [];
-
/**
- * Adds the range of a node to the set to be skipped when checking parens
- * @param {ASTNode} node The node to skip
- * @returns {void}
- * @private
+ * Determines if a token is one of the exceptions for the opener paren
+ * @param {Object} token The token to check
+ * @returns {boolean} True if the token is one of the exceptions for the opener paren
*/
- function addSkipRange(node) {
- skipRanges.push(node.range);
+ function isOpenerException(token) {
+ return token.type === "Punctuator" && exceptions.openers.indexOf(token.value) >= 0;
}
/**
- * Sorts the skipRanges array. Must be called before shouldSkip
- * @returns {void}
- * @private
+ * Determines if a token is one of the exceptions for the closer paren
+ * @param {Object} token The token to check
+ * @returns {boolean} True if the token is one of the exceptions for the closer paren
*/
- function sortSkipRanges() {
- skipRanges.sort(function (a, b) {
- return a[0] - b[0];
- });
+ function isCloserException(token) {
+ return token.type === "Punctuator" && exceptions.closers.indexOf(token.value) >= 0;
}
/**
- * Checks if a certain position in the source should be skipped
- * @param {Number} pos The 0-based index in the source
- * @returns {boolean} whether the position should be skipped
- * @private
+ * Determines if an opener paren should have a missing space after it
+ * @param {Object} left The paren token
+ * @param {Object} right The token after it
+ * @returns {boolean} True if the paren should have a space
*/
- function shouldSkip(pos) {
- var i, len, range;
- for (i = 0, len = skipRanges.length; i < len; i += 1) {
- range = skipRanges[i];
- if (pos < range[0]) {
- break;
- } else if (pos < range[1]) {
- return true;
+ function shouldOpenerHaveSpace(left, right) {
+ if (sourceCode.isSpaceBetweenTokens(left, right)) {
+ return false;
+ }
+
+ if (ALWAYS) {
+ if (right.type === "Punctuator" && right.value === ")") {
+ return false;
}
+ return !isOpenerException(right);
+ } else {
+ return isOpenerException(right);
}
- return false;
}
+ /**
+ * Determines if an closer paren should have a missing space after it
+ * @param {Object} left The token before the paren
+ * @param {Object} right The paren token
+ * @returns {boolean} True if the paren should have a space
+ */
+ function shouldCloserHaveSpace(left, right) {
+ if (left.type === "Punctuator" && left.value === "(") {
+ return false;
+ }
- //--------------------------------------------------------------------------
- // Public
- //--------------------------------------------------------------------------
+ if (sourceCode.isSpaceBetweenTokens(left, right)) {
+ return false;
+ }
- return {
+ if (ALWAYS) {
+ return !isCloserException(left);
+ } else {
+ return isCloserException(left);
+ }
+ }
- "Program:exit": function checkParenSpaces(node) {
+ /**
+ * Determines if an opener paren should not have an existing space after it
+ * @param {Object} left The paren token
+ * @param {Object} right The token after it
+ * @returns {boolean} True if the paren should reject the space
+ */
+ function shouldOpenerRejectSpace(left, right) {
+ if (right.type === "Line") {
+ return false;
+ }
- var nextMatch,
- nextLine,
- column,
- line = 1,
- source = context.getSource(),
- pos = 0;
+ if (!astUtils.isTokenOnSameLine(left, right)) {
+ return false;
+ }
- function checkMatch(match, message) {
- if (source.charAt(match.index) !== "(") {
- // Matched a closing paren pattern
- match.index += 1;
- }
+ if (!sourceCode.isSpaceBetweenTokens(left, right)) {
+ return false;
+ }
- if (!shouldSkip(match.index)) {
- while ((nextLine = source.indexOf("\n", pos)) !== -1 && nextLine < match.index) {
- pos = nextLine + 1;
- line += 1;
- }
- column = match.index - pos;
+ if (ALWAYS) {
+ return isOpenerException(right);
+ } else {
+ return !isOpenerException(right);
+ }
+ }
- context.report(node, { line: line, column: column }, message);
- }
- }
+ /**
+ * Determines if an closer paren should not have an existing space after it
+ * @param {Object} left The token before the paren
+ * @param {Object} right The paren token
+ * @returns {boolean} True if the paren should reject the space
+ */
+ function shouldCloserRejectSpace(left, right) {
+ if (left.type === "Punctuator" && left.value === "(") {
+ return false;
+ }
- sortSkipRanges();
+ if (!astUtils.isTokenOnSameLine(left, right)) {
+ return false;
+ }
- while ((nextMatch = rejectedSpaceRegExp.exec(source)) !== null) {
- checkMatch(nextMatch, REJECTED_SPACE_MESSAGE);
- }
+ if (!sourceCode.isSpaceBetweenTokens(left, right)) {
+ return false;
+ }
- while ((nextMatch = missingSpaceRegExp.exec(source)) !== null) {
- checkMatch(nextMatch, MISSING_SPACE_MESSAGE);
- }
+ if (ALWAYS) {
+ return isCloserException(left);
+ } else {
+ return !isCloserException(left);
+ }
+ }
- },
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+ return {
+ "Program": function checkParenSpaces(node) {
+ var tokens, prevToken, nextToken;
+ exceptions = getExceptions();
+ tokens = sourceCode.tokensAndComments;
- // These nodes can contain parentheses that this rule doesn't care about
+ tokens.forEach(function(token, i) {
+ prevToken = tokens[i - 1];
+ nextToken = tokens[i + 1];
- LineComment: addSkipRange,
+ if (token.type !== "Punctuator") {
+ return;
+ }
- BlockComment: addSkipRange,
+ if (token.value !== "(" && token.value !== ")") {
+ return;
+ }
- Literal: addSkipRange
-
+ if (token.value === "(" && shouldOpenerHaveSpace(token, nextToken)) {
+ context.report(node, token.loc.end, MISSING_SPACE_MESSAGE);
+ } else if (token.value === "(" && shouldOpenerRejectSpace(token, nextToken)) {
+ context.report(node, token.loc.end, REJECTED_SPACE_MESSAGE);
+ } else if (token.value === ")" && shouldCloserHaveSpace(prevToken, token)) {
+ context.report(node, token.loc.end, MISSING_SPACE_MESSAGE);
+ } else if (token.value === ")" && shouldCloserRejectSpace(prevToken, token)) {
+ context.report(node, token.loc.end, REJECTED_SPACE_MESSAGE);
+ }
+ });
+ }
};
};
-},{}],273:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "array",
+ "items": {
+ "enum": ["{}", "[]", "()", "empty"]
+ },
+ "uniqueItems": true
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"../ast-utils":113}],297:[function(require,module,exports){
/**
* @fileoverview Require spaces around infix operators
* @author Michael Ficarra
*/
"use strict";
@@ -27996,66 +41363,147 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ var int32Hint = context.options[0] ? context.options[0].int32Hint === true : false;
var OPERATORS = [
"*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in",
"instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=",
"+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=",
"?", ":", ","
];
- function isSpaced(left, right) {
+ /**
+ * Returns the first token which violates the rule
+ * @param {ASTNode} left - The left node of the main node
+ * @param {ASTNode} right - The right node of the main node
+ * @returns {object} The violator token or null
+ * @private
+ */
+ function getFirstNonSpacedToken(left, right) {
var op, tokens = context.getTokensBetween(left, right, 1);
for (var i = 1, l = tokens.length - 1; i < l; ++i) {
op = tokens[i];
if (
op.type === "Punctuator" &&
OPERATORS.indexOf(op.value) >= 0 &&
(tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0])
) {
- return false;
+ return op;
}
}
- return true;
+ return null;
}
- function report(node) {
- context.report(node, "Infix operators must be spaced.");
+ /**
+ * Reports an AST node as a rule violation
+ * @param {ASTNode} mainNode - The node to report
+ * @param {object} culpritToken - The token which has a problem
+ * @returns {void}
+ * @private
+ */
+ function report(mainNode, culpritToken) {
+ context.report({
+ node: mainNode,
+ loc: culpritToken.loc.start,
+ message: "Infix operators must be spaced.",
+ fix: function(fixer) {
+ var previousToken = context.getTokenBefore(culpritToken);
+ var afterToken = context.getTokenAfter(culpritToken);
+ var fixString = "";
+
+ if (culpritToken.range[0] - previousToken.range[1] === 0) {
+ fixString = " ";
+ }
+
+ fixString += culpritToken.value;
+
+ if (afterToken.range[0] - culpritToken.range[1] === 0) {
+ fixString += " ";
+ }
+
+ return fixer.replaceText(culpritToken, fixString);
+ }
+ });
}
+ /**
+ * Check if the node is binary then report
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function checkBinary(node) {
- if (!isSpaced(node.left, node.right)) {
- report(node);
+ var nonSpacedNode = getFirstNonSpacedToken(node.left, node.right);
+
+ if (nonSpacedNode) {
+ if (!(int32Hint && context.getSource(node).substr(-2) === "|0")) {
+ report(node, nonSpacedNode);
+ }
}
}
+ /**
+ * Check if the node is conditional
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function checkConditional(node) {
- if (!isSpaced(node.test, node.consequent) || !isSpaced(node.consequent, node.alternate)) {
- report(node);
+ var nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent);
+ var nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate);
+
+ if (nonSpacedConsequesntNode) {
+ report(node, nonSpacedConsequesntNode);
+ } else if (nonSpacedAlternateNode) {
+ report(node, nonSpacedAlternateNode);
}
}
+ /**
+ * Check if the node is a variable
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function checkVar(node) {
- if (node.init && !isSpaced(node.id, node.init)) {
- report(node);
+ var nonSpacedNode;
+
+ if (node.init) {
+ nonSpacedNode = getFirstNonSpacedToken(node.id, node.init);
+ if (nonSpacedNode) {
+ report(node, nonSpacedNode);
+ }
}
}
return {
"AssignmentExpression": checkBinary,
+ "AssignmentPattern": checkBinary,
"BinaryExpression": checkBinary,
"LogicalExpression": checkBinary,
"ConditionalExpression": checkConditional,
"VariableDeclarator": checkVar
};
};
-},{}],274:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "int32Hint": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],298:[function(require,module,exports){
/**
* @fileoverview Require spaces following return, throw, and case
* @author Michael Ficarra
*/
"use strict";
@@ -28064,16 +41512,28 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
+ /**
+ * Check if the node for spaces
+ * @param {ASTNode} node node to evaluate
+ * @returns {void}
+ * @private
+ */
function check(node) {
var tokens = context.getFirstTokens(node, 2),
value = tokens[0].value;
if (tokens[0].range[1] >= tokens[1].range[0]) {
- context.report(node, "Keyword \"" + value + "\" must be followed by whitespace.");
+ context.report({
+ node: node,
+ message: "Keyword \"" + value + "\" must be followed by whitespace.",
+ fix: function(fixer) {
+ return fixer.insertTextAfterRange(tokens[0].range, " ");
+ }
+ });
}
}
return {
"ReturnStatement": function(node) {
@@ -28089,11 +41549,13 @@
"ThrowStatement": check
};
};
-},{}],275:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],299:[function(require,module,exports){
/**
* @fileoverview This rule shoud require or disallow spaces before or after unary operations.
* @author Marcin Kumorek
* @copyright 2014 Marcin Kumorek. All rights reserved.
*/
@@ -28109,28 +41571,20 @@
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
- * Check if the parent unary operator is "!" in order to know if it's "!!" convert to Boolean or just "!" negation
+ * Check if the node is the first "!" in a "!!" convert to Boolean expression
* @param {ASTnode} node AST node
- * @returns {boolean} Whether or not the parent is unary "!" operator
+ * @returns {boolean} Whether or not the node is first "!" in "!!"
*/
- function isParentUnaryBangExpression(node) {
- return node && node.parent && node.parent.type === "UnaryExpression" && node.parent.operator === "!";
+ function isFirstBangInBangBangExpression(node) {
+ return node && node.type === "UnaryExpression" && node.argument.operator === "!" &&
+ node.argument && node.argument.type === "UnaryExpression" && node.argument.operator === "!";
}
/**
- * Checks if the type is a unary word expression
- * @param {string} type value of AST token
- * @returns {boolean} Whether the word is in the list of known words
- */
- function isWordExpression(type) {
- return ["delete", "new", "typeof", "void"].indexOf(type) !== -1;
- }
-
- /**
* Check if the node's child argument is an "ObjectExpression"
* @param {ASTnode} node AST node
* @returns {boolean} Whether or not the argument's type is "ObjectExpression"
*/
function isArgumentObjectExpression(node) {
@@ -28140,22 +41594,37 @@
/**
* Check Unary Word Operators for spaces after the word operator
* @param {ASTnode} node AST node
* @param {object} firstToken first token from the AST node
* @param {object} secondToken second token from the AST node
+ * @param {string} word The word to be used for reporting
* @returns {void}
*/
- function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken) {
+ function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, word) {
+ word = word || firstToken.value;
+
if (options.words) {
if (secondToken.range[0] === firstToken.range[1]) {
- context.report(node, "Unary word operator \"" + firstToken.value + "\" must be followed by whitespace.");
+ context.report({
+ node: node,
+ message: "Unary word operator \"" + word + "\" must be followed by whitespace.",
+ fix: function(fixer) {
+ return fixer.insertTextAfter(firstToken, " ");
+ }
+ });
}
}
if (!options.words && isArgumentObjectExpression(node)) {
if (secondToken.range[0] > firstToken.range[1]) {
- context.report(node, "Unexpected space after unary word operator \"" + firstToken.value + "\".");
+ context.report({
+ node: node,
+ message: "Unexpected space after unary word operator \"" + word + "\".",
+ fix: function(fixer) {
+ return fixer.removeRange([firstToken.range[1], secondToken.range[0]]);
+ }
+ });
}
}
}
/**
@@ -28166,36 +41635,60 @@
function checkForSpaces(node) {
var tokens = context.getFirstTokens(node, 2),
firstToken = tokens[0],
secondToken = tokens[1];
- if (isWordExpression(firstToken.value)) {
+ if ((node.type === "NewExpression" || node.prefix) && firstToken.type === "Keyword") {
checkUnaryWordOperatorForSpaces(node, firstToken, secondToken);
return void 0;
}
if (options.nonwords) {
if (node.prefix) {
- if (isParentUnaryBangExpression(node)) {
+ if (isFirstBangInBangBangExpression(node)) {
return void 0;
}
if (firstToken.range[1] === secondToken.range[0]) {
- context.report(node, "Unary operator \"" + firstToken.value + "\" must be followed by whitespace.");
+ context.report({
+ node: node,
+ message: "Unary operator \"" + firstToken.value + "\" must be followed by whitespace.",
+ fix: function(fixer) {
+ return fixer.insertTextAfter(firstToken, " ");
+ }
+ });
}
} else {
if (firstToken.range[1] === secondToken.range[0]) {
- context.report(node, "Space is required before unary expressions \"" + secondToken.value + "\".");
+ context.report({
+ node: node,
+ message: "Space is required before unary expressions \"" + secondToken.value + "\".",
+ fix: function(fixer) {
+ return fixer.insertTextBefore(secondToken, " ");
+ }
+ });
}
}
} else {
if (node.prefix) {
if (secondToken.range[0] > firstToken.range[1]) {
- context.report(node, "Unexpected space after unary operator \"" + firstToken.value + "\".");
+ context.report({
+ node: node,
+ message: "Unexpected space after unary operator \"" + firstToken.value + "\".",
+ fix: function(fixer) {
+ return fixer.removeRange([firstToken.range[1], secondToken.range[0]]);
+ }
+ });
}
} else {
if (secondToken.range[0] > firstToken.range[1]) {
- context.report(node, "Unexpected space before unary operator \"" + secondToken.value + "\".");
+ context.report({
+ node: node,
+ message: "Unexpected space before unary operator \"" + secondToken.value + "\".",
+ fix: function(fixer) {
+ return fixer.removeRange([firstToken.range[1], secondToken.range[0]]);
+ }
+ });
}
}
}
}
@@ -28204,89 +41697,297 @@
//--------------------------------------------------------------------------
return {
"UnaryExpression": checkForSpaces,
"UpdateExpression": checkForSpaces,
- "NewExpression": checkForSpaces
+ "NewExpression": checkForSpaces,
+ "YieldExpression": function(node) {
+ var tokens = context.getFirstTokens(node, 3),
+ word = "yield";
+
+ if (!node.argument) {
+ return;
+ }
+
+ if (node.delegate) {
+ word += "*";
+ checkUnaryWordOperatorForSpaces(node, tokens[1], tokens[2], word);
+ } else {
+ checkUnaryWordOperatorForSpaces(node, tokens[0], tokens[1], word);
+ }
+ }
};
};
-},{}],276:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "words": {
+ "type": "boolean"
+ },
+ "nonwords": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],300:[function(require,module,exports){
/**
- * @fileoverview Enforces or disallows a space beginning a single-line comment.
- * @author Greg Cochard
+ * @fileoverview Source code for spaced-comments rule
+ * @author Gyandeep Singh
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ * @copyright 2015 Gyandeep Singh. All rights reserved.
* @copyright 2014 Greg Cochard. All rights reserved.
*/
"use strict";
+var escapeStringRegexp = require("escape-string-regexp");
+
//------------------------------------------------------------------------------
-// Rule Definition
+// Helpers
//------------------------------------------------------------------------------
-module.exports = function(context) {
+/**
+ * Escapes the control characters of a given string.
+ * @param {string} s - A string to escape.
+ * @returns {string} An escaped string.
+ */
+function escape(s) {
+ var isOneChar = s.length === 1;
+ s = escapeStringRegexp(s);
+ return isOneChar ? s : "(?:" + s + ")";
+}
- // Unless the first option is never, require a space
- var requireSpace = context.options[0] !== "never";
+/**
+ * Escapes the control characters of a given string.
+ * And adds a repeat flag.
+ * @param {string} s - A string to escape.
+ * @returns {string} An escaped string.
+ */
+function escapeAndRepeat(s) {
+ return escape(s) + "+";
+}
- // Default to match anything, so all will fail if there are no exceptions
- var exceptionMatcher = new RegExp(" ");
+/**
+ * Parses `markers` option.
+ * If markers don't include `"*"`, this adds `"*"` to allow JSDoc comments.
+ * @param {string[]} [markers] - A marker list.
+ * @returns {string[]} A marker list.
+ */
+function parseMarkersOption(markers) {
+ markers = markers ? markers.slice(0) : [];
- // Grab the exceptions array and build a RegExp matcher for it
- var hasExceptions = context.options.length === 2;
- var unescapedExceptions = hasExceptions ? context.options[1].exceptions : [];
- var exceptions;
+ // `*` is a marker for JSDoc comments.
+ if (markers.indexOf("*") === -1) {
+ markers.push("*");
+ }
- if (unescapedExceptions.length) {
- exceptions = unescapedExceptions.map(function(s) {
- return s.replace(/([.*+?${}()|\^\[\]\/\\])/g, "\\$1");
- });
- exceptionMatcher = new RegExp("(^(" + exceptions.join(")+$)|(^(") + ")+$)");
+ return markers;
+}
+
+/**
+ * Creates RegExp object for `always` mode.
+ * Generated pattern is below:
+ *
+ * 1. First, a marker or nothing.
+ * 2. Next, a space or an exception pattern sequence.
+ *
+ * @param {string[]} markers - A marker list.
+ * @param {string[]} exceptions - A exception pattern list.
+ * @returns {RegExp} A RegExp object for `always` mode.
+ */
+function createAlwaysStylePattern(markers, exceptions) {
+ var pattern = "^";
+
+ // A marker or nothing.
+ // ["*"] ==> "\*?"
+ // ["*", "!"] ==> "(?:\*|!)?"
+ // ["*", "/", "!<"] ==> "(?:\*|\/|(?:!<))?" ==> https://jex.im/regulex/#!embed=false&flags=&re=(%3F%3A%5C*%7C%5C%2F%7C(%3F%3A!%3C))%3F
+ if (markers.length === 1) {
+ // the marker.
+ pattern += escape(markers[0]);
+ } else {
+ // one of markers.
+ pattern += "(?:";
+ pattern += markers.map(escape).join("|");
+ pattern += ")";
}
+ pattern += "?"; // or nothing.
+ // A space or an exception pattern sequence.
+ // [] ==> "\s"
+ // ["-"] ==> "(?:\s|\-+$)"
+ // ["-", "="] ==> "(?:\s|(?:\-+|=+)$)"
+ // ["-", "=", "--=="] ==> "(?:\s|(?:\-+|=+|(?:\-\-==)+)$)" ==> https://jex.im/regulex/#!embed=false&flags=&re=(%3F%3A%5Cs%7C(%3F%3A%5C-%2B%7C%3D%2B%7C(%3F%3A%5C-%5C-%3D%3D)%2B)%24)
+ if (exceptions.length === 0) {
+ // a space.
+ pattern += "\\s";
+ } else {
+ // a space or...
+ pattern += "(?:\\s|";
+ if (exceptions.length === 1) {
+ // a sequence of the exception pattern.
+ pattern += escapeAndRepeat(exceptions[0]);
+ } else {
+ // a sequence of one of exception patterns.
+ pattern += "(?:";
+ pattern += exceptions.map(escapeAndRepeat).join("|");
+ pattern += ")";
+ }
+ pattern += "(?:$|[\n\r]))"; // the sequence continues until the end.
+ }
+ return new RegExp(pattern);
+}
- //--------------------------------------------------------------------------
- // Public
- //--------------------------------------------------------------------------
+/**
+ * Creates RegExp object for `never` mode.
+ * Generated pattern is below:
+ *
+ * 1. First, a marker or nothing (captured).
+ * 2. Next, a space or a tab.
+ *
+ * @param {string[]} markers - A marker list.
+ * @returns {RegExp} A RegExp object for `never` mode.
+ */
+function createNeverStylePattern(markers) {
+ var pattern = "^(" + markers.map(escape).join("|") + ")?[ \t]";
+ return new RegExp(pattern);
+}
- return {
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
- "LineComment": function checkCommentForSpace(node) {
+module.exports = function(context) {
+ // Unless the first option is never, require a space
+ var requireSpace = context.options[0] !== "never";
- if (requireSpace) {
+ // Parse the second options.
+ // If markers don't include `"*"`, it's added automatically for JSDoc comments.
+ var config = context.options[1] || {};
+ var styleRules = ["block", "line"].reduce(function(rule, type) {
+ var markers = parseMarkersOption(config[type] && config[type].markers || config.markers);
+ var exceptions = config[type] && config[type].exceptions || config.exceptions || [];
- // If length is zero, ignore it
- if (node.value.length === 0) {
- return;
- }
+ // Create RegExp object for valid patterns.
+ rule[type] = {
+ regex: requireSpace ? createAlwaysStylePattern(markers, exceptions) : createNeverStylePattern(markers),
+ hasExceptions: exceptions.length > 0
+ };
- // Space expected and not found
- if (node.value.indexOf(" ") !== 0 && node.value.indexOf("\t") !== 0) {
+ return rule;
+ }, {});
- /*
- * Do two tests; one for space starting the line,
- * and one for a comment comprised only of exceptions
- */
- if (hasExceptions && !exceptionMatcher.test(node.value)) {
- context.report(node, "Expected exception block, space or tab after // in comment.");
- } else if (!hasExceptions) {
- context.report(node, "Expected space or tab after // in comment.");
- }
- }
+ /**
+ * Reports a given comment if it's invalid.
+ * @param {ASTNode} node - a comment node to check.
+ * @returns {void}
+ */
+ function checkCommentForSpace(node) {
+ var type = node.type.toLowerCase(),
+ rule = styleRules[type],
+ commentIdentifier = type === "block" ? "/*" : "//";
- } else {
+ // Ignores empty comments.
+ if (node.value.length === 0) {
+ return;
+ }
- if (node.value.indexOf(" ") === 0 || node.value.indexOf("\t") === 0) {
- context.report(node, "Unexpected space or tab after // in comment.");
+ // Checks.
+ if (requireSpace) {
+ if (!rule.regex.test(node.value)) {
+ if (rule.hasExceptions) {
+ context.report(node, "Expected exception block, space or tab after \"" + commentIdentifier + "\" in comment.");
+ } else {
+ context.report(node, "Expected space or tab after \"" + commentIdentifier + "\" in comment.");
}
}
+ } else {
+ var matched = rule.regex.exec(node.value);
+ if (matched) {
+ if (!matched[1]) {
+ context.report(node, "Unexpected space or tab after \"" + commentIdentifier + "\" in comment.");
+ } else {
+ context.report(node, "Unexpected space or tab after marker (" + matched[1] + ") in comment.");
+ }
+ }
}
+ }
+ return {
+
+ "LineComment": checkCommentForSpace,
+ "BlockComment": checkCommentForSpace
+
};
};
-},{}],277:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "markers": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "line": {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "markers": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": false
+ },
+ "block": {
+ "type": "object",
+ "properties": {
+ "exceptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "markers": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"escape-string-regexp":74}],301:[function(require,module,exports){
/**
* @fileoverview Rule to control usage of strict mode directives.
* @author Brandon Mills
* @copyright 2015 Brandon Mills. All rights reserved.
* @copyright 2013-2014 Nicholas C. Zakas. All rights reserved.
@@ -28302,11 +42003,13 @@
var messages = {
function: "Use the function form of \"use strict\".",
global: "Use the global form of \"use strict\".",
multiple: "Multiple \"use strict\" directives.",
never: "Strict mode is not permitted.",
- unnecessary: "Unnecessary \"use strict\" directive."
+ unnecessary: "Unnecessary \"use strict\" directive.",
+ unnecessaryInModules: "\"use strict\" is unnecessary inside of modules.",
+ unnecessaryInClasses: "\"use strict\" is unnecessary inside of classes."
};
/**
* Gets all of the Use Strict Directives in the Directive Prologue of a group of
* statements.
@@ -28338,14 +42041,11 @@
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
- var mode = context.options[0],
- isModule = context.ecmaFeatures.modules,
- modes = {},
- scopes = [];
+ var mode = context.options[0];
/**
* Report a node or array of nodes with a given message.
* @param {(ASTNode|ASTNode[])} nodes Node or nodes to report.
* @param {string} message Message to display.
@@ -28362,140 +42062,114 @@
context.report(nodes, message);
}
}
//--------------------------------------------------------------------------
- // "deprecated" mode (default)
+ // "never" mode
//--------------------------------------------------------------------------
- /**
- * Determines if a given node is "use strict".
- * @param {ASTNode} node The node to check.
- * @returns {boolean} True if the node is a strict pragma, false if not.
- * @void
- */
- function isStrictPragma(node) {
- return (node && node.type === "ExpressionStatement" &&
- node.expression.value === "use strict");
+ if (mode === "never") {
+ return {
+ "Program": function(node) {
+ report(getUseStrictDirectives(node.body), messages.never);
+ },
+ "FunctionDeclaration": function(node) {
+ report(getUseStrictDirectives(node.body.body), messages.never);
+ },
+ "FunctionExpression": function(node) {
+ report(getUseStrictDirectives(node.body.body), messages.never);
+ },
+ "ArrowFunctionExpression": function(node) {
+ if (node.body.type === "BlockStatement") {
+ report(getUseStrictDirectives(node.body.body), messages.never);
+ }
+ }
+ };
}
- /**
- * When you enter a scope, push the strict value from the previous scope
- * onto the stack.
- * @param {ASTNode} node The AST node being checked.
- * @returns {void}
- * @private
- */
- function enterScope(node) {
-
- var isStrict = false,
- isProgram = (node.type === "Program"),
- isParentGlobal = scopes.length === 1,
- isParentStrict = scopes.length ? scopes[scopes.length - 1] : false;
-
- // look for the "use strict" pragma
- if (isModule) {
- isStrict = true;
- } else if (isProgram) {
- isStrict = isStrictPragma(node.body[0]) || isParentStrict;
- } else {
- isStrict = node.body.body && isStrictPragma(node.body.body[0]) || isParentStrict;
- }
-
- scopes.push(isStrict);
-
- // never warn if the parent is strict or the function is strict
- if (!isParentStrict && !isStrict && isParentGlobal) {
- context.report(node, "Missing \"use strict\" statement.");
- }
- }
-
- /**
- * When you exit a scope, pop off the top scope and see if it's true or
- * false.
- * @returns {void}
- * @private
- */
- function exitScope() {
- scopes.pop();
- }
-
- modes.deprecated = {
- "Program": enterScope,
- "FunctionDeclaration": enterScope,
- "FunctionExpression": enterScope,
- "ArrowFunctionExpression": enterScope,
-
- "Program:exit": exitScope,
- "FunctionDeclaration:exit": exitScope,
- "FunctionExpression:exit": exitScope,
- "ArrowFunctionExpression:exit": exitScope
- };
-
//--------------------------------------------------------------------------
- // "never" mode
+ // If this is modules, all "use strict" directives are unnecessary.
//--------------------------------------------------------------------------
- modes.never = {
- "Program": function(node) {
- report(getUseStrictDirectives(node.body), messages.never);
- },
- "FunctionDeclaration": function(node) {
- report(getUseStrictDirectives(node.body.body), messages.never);
- },
- "FunctionExpression": function(node) {
- report(getUseStrictDirectives(node.body.body), messages.never);
- }
- };
+ if (context.ecmaFeatures.modules) {
+ return {
+ "Program": function(node) {
+ report(getUseStrictDirectives(node.body), messages.unnecessaryInModules);
+ },
+ "FunctionDeclaration": function(node) {
+ report(getUseStrictDirectives(node.body.body), messages.unnecessaryInModules);
+ },
+ "FunctionExpression": function(node) {
+ report(getUseStrictDirectives(node.body.body), messages.unnecessaryInModules);
+ },
+ "ArrowFunctionExpression": function(node) {
+ if (node.body.type === "BlockStatement") {
+ report(getUseStrictDirectives(node.body.body), messages.unnecessaryInModules);
+ }
+ }
+ };
+ }
//--------------------------------------------------------------------------
// "global" mode
//--------------------------------------------------------------------------
- modes.global = {
- "Program": function(node) {
- var useStrictDirectives = getUseStrictDirectives(node.body);
+ if (mode === "global") {
+ return {
+ "Program": function(node) {
+ var useStrictDirectives = getUseStrictDirectives(node.body);
- if (!isModule && node.body.length && useStrictDirectives.length < 1) {
- report(node, messages.global);
- } else if (isModule) {
- report(useStrictDirectives, messages.unnecessary);
- } else {
- report(useStrictDirectives.slice(1), messages.multiple);
+ if (node.body.length > 0 && useStrictDirectives.length === 0) {
+ report(node, messages.global);
+ } else {
+ report(useStrictDirectives.slice(1), messages.multiple);
+ }
+ },
+ "FunctionDeclaration": function(node) {
+ report(getUseStrictDirectives(node.body.body), messages.global);
+ },
+ "FunctionExpression": function(node) {
+ report(getUseStrictDirectives(node.body.body), messages.global);
+ },
+ "ArrowFunctionExpression": function(node) {
+ if (node.body.type === "BlockStatement") {
+ report(getUseStrictDirectives(node.body.body), messages.global);
+ }
}
- },
- "FunctionDeclaration": function(node) {
- report(getUseStrictDirectives(node.body.body), messages.global);
- },
- "FunctionExpression": function(node) {
- report(getUseStrictDirectives(node.body.body), messages.global);
- }
- };
+ };
+ }
//--------------------------------------------------------------------------
- // "function" mode
+ // "function" mode (Default)
//--------------------------------------------------------------------------
+ var scopes = [],
+ classScopes = [];
+
/**
* Entering a function pushes a new nested scope onto the stack. The new
* scope is true if the nested function is strict mode code.
* @param {ASTNode} node The function declaration or expression.
* @returns {void}
*/
function enterFunction(node) {
- var useStrictDirectives = getUseStrictDirectives(node.body.body),
- isParentGlobal = scopes.length === 0,
- isParentStrict = isModule || (scopes.length && scopes[scopes.length - 1]),
- isStrict = useStrictDirectives.length > 0 || isModule;
+ var isInClass = classScopes.length > 0,
+ isParentGlobal = scopes.length === 0 && classScopes.length === 0,
+ isParentStrict = scopes.length > 0 && scopes[scopes.length - 1],
+ isNotBlock = node.body.type !== "BlockStatement",
+ useStrictDirectives = isNotBlock ? [] : getUseStrictDirectives(node.body.body),
+ isStrict = useStrictDirectives.length > 0;
if (isStrict) {
- if (isParentStrict && useStrictDirectives.length) {
+ if (isParentStrict) {
report(useStrictDirectives[0], messages.unnecessary);
+ } else if (isInClass) {
+ report(useStrictDirectives[0], messages.unnecessaryInClasses);
}
report(useStrictDirectives.slice(1), messages.multiple);
- } else if (isParentGlobal && !isModule) {
+ } else if (isParentGlobal) {
report(node, messages.function);
}
scopes.push(isParentStrict || isStrict);
}
@@ -28506,25 +42180,40 @@
*/
function exitFunction() {
scopes.pop();
}
- modes.function = {
+ return {
"Program": function(node) {
report(getUseStrictDirectives(node.body), messages.function);
},
+
+ // Inside of class bodies are always strict mode.
+ "ClassBody": function() {
+ classScopes.push(true);
+ },
+ "ClassBody:exit": function() {
+ classScopes.pop();
+ },
+
"FunctionDeclaration": enterFunction,
"FunctionExpression": enterFunction,
+ "ArrowFunctionExpression": enterFunction,
+
"FunctionDeclaration:exit": exitFunction,
- "FunctionExpression:exit": exitFunction
+ "FunctionExpression:exit": exitFunction,
+ "ArrowFunctionExpression:exit": exitFunction
};
-
- return modes[mode || "deprecated"];
-
};
-},{}],278:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["never", "global", "function"]
+ }
+];
+
+},{}],302:[function(require,module,exports){
/**
* @fileoverview Rule to flag comparisons to the value NaN
* @author James Allardice
* @copyright 2014 Jordan Harband. All rights reserved.
* @copyright 2013 James Allardice. All rights reserved.
@@ -28534,23 +42223,25 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
+module.exports = function(context) {
return {
- "BinaryExpression": function (node) {
+ "BinaryExpression": function(node) {
if (/^(?:[<>]|[!=]=)=?$/.test(node.operator) && (node.left.name === "NaN" || node.right.name === "NaN")) {
context.report(node, "Use the isNaN function to compare with NaN.");
}
}
};
};
-},{}],279:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],303:[function(require,module,exports){
/**
* @fileoverview Validates JSDoc comments are syntactically correct
* @author Nicholas C. Zakas
* @copyright 2014 Nicholas C. Zakas. All rights reserved.
*/
@@ -28568,30 +42259,46 @@
module.exports = function(context) {
var options = context.options[0] || {},
prefer = options.prefer || {},
+ sourceCode = context.getSourceCode(),
// these both default to true, so you have to explicitly make them false
- requireReturn = options.requireReturn === false ? false : true,
+ requireReturn = options.requireReturn !== false,
requireParamDescription = options.requireParamDescription !== false,
- requireReturnDescription = options.requireReturnDescription !== false;
+ requireReturnDescription = options.requireReturnDescription !== false,
+ requireReturnType = options.requireReturnType !== false;
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
// Using a stack to store if a function returns or not (handling nested functions)
var fns = [];
/**
+ * Check if node type is a Class
+ * @param {ASTNode} node node to check.
+ * @returns {boolean} True is its a class
+ * @private
+ */
+ function isTypeClass(node) {
+ return node.type === "ClassExpression" || node.type === "ClassDeclaration";
+ }
+
+ /**
* When parsing a new function, store it in our function stack.
+ * @param {ASTNode} node A function node to check.
* @returns {void}
* @private
*/
- function startFunction() {
- fns.push({returnPresent: false});
+ function startFunction(node) {
+ fns.push({
+ returnPresent: (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") ||
+ isTypeClass(node)
+ });
}
/**
* Indicate that return has been found in the current function.
* @param {ASTNode} node The return node.
@@ -28605,20 +42312,31 @@
functionState.returnPresent = true;
}
}
/**
+ * Check if return tag type is void or undefined
+ * @param {Object} tag JSDoc tag
+ * @returns {boolean} True if its of type void or undefined
+ * @private
+ */
+ function isValidReturnType(tag) {
+ return tag.type === null || tag.type.name === "void" || tag.type.type === "UndefinedLiteral";
+ }
+
+ /**
* Validate the JSDoc node and output warnings if anything is wrong.
* @param {ASTNode} node The AST node to check.
* @returns {void}
* @private
*/
function checkJSDoc(node) {
- var jsdocNode = context.getJSDocComment(node),
+ var jsdocNode = sourceCode.getJSDocComment(node),
functionData = fns.pop(),
hasReturns = false,
hasConstructor = false,
+ isOverride = false,
params = Object.create(null),
jsdoc;
// make sure only to validate JSDoc comments
if (jsdocNode) {
@@ -28643,10 +42361,12 @@
jsdoc.tags.forEach(function(tag) {
switch (tag.title) {
case "param":
+ case "arg":
+ case "argument":
if (!tag.type) {
context.report(jsdocNode, "Missing JSDoc parameter type for '{{name}}'.", { name: tag.name });
}
if (!tag.description && requireParamDescription) {
@@ -28665,15 +42385,15 @@
hasReturns = true;
if (!requireReturn && !functionData.returnPresent && tag.type.name !== "void" && tag.type.name !== "undefined") {
context.report(jsdocNode, "Unexpected @" + tag.title + " tag; function has no return statement.");
} else {
- if (!tag.type) {
+ if (requireReturnType && !tag.type) {
context.report(jsdocNode, "Missing JSDoc return type.");
}
- if (tag.type.name !== "void" && !tag.description && requireReturnDescription) {
+ if (!isValidReturnType(tag) && !tag.description && requireReturnDescription) {
context.report(jsdocNode, "Missing JSDoc return description.");
}
}
break;
@@ -28681,44 +42401,62 @@
case "constructor":
case "class":
hasConstructor = true;
break;
+ case "override":
+ case "inheritdoc":
+ isOverride = true;
+ break;
+
// no default
}
// check tag preferences
- if (prefer.hasOwnProperty(tag.title)) {
+ if (prefer.hasOwnProperty(tag.title) && tag.title !== prefer[tag.title]) {
context.report(jsdocNode, "Use @{{name}} instead.", { name: prefer[tag.title] });
}
});
// check for functions missing @returns
- if (!hasReturns && !hasConstructor) {
+ if (!isOverride && !hasReturns && !hasConstructor && node.parent.kind !== "get" && !isTypeClass(node)) {
if (requireReturn || functionData.returnPresent) {
- context.report(jsdocNode, "Missing JSDoc @returns for function.");
+ context.report(jsdocNode, "Missing JSDoc @" + (prefer.returns || "returns") + " for function.");
}
}
// check the parameters
var jsdocParams = Object.keys(params);
- node.params.forEach(function(param, i) {
- var name = param.name;
+ if (node.params) {
+ node.params.forEach(function(param, i) {
+ var name = param.name;
- if (jsdocParams[i] && (name !== jsdocParams[i])) {
- context.report(jsdocNode, "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.", {
- name: name,
- jsdocName: jsdocParams[i]
- });
- } else if (!params[name]) {
- context.report(jsdocNode, "Missing JSDoc for parameter '{{name}}'.", {
- name: name
- });
+ // TODO(nzakas): Figure out logical things to do with destructured, default, rest params
+ if (param.type === "Identifier") {
+ if (jsdocParams[i] && (name !== jsdocParams[i])) {
+ context.report(jsdocNode, "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.", {
+ name: name,
+ jsdocName: jsdocParams[i]
+ });
+ } else if (!params[name] && !isOverride) {
+ context.report(jsdocNode, "Missing JSDoc for parameter '{{name}}'.", {
+ name: name
+ });
+ }
+ }
+ });
+ }
+
+ if (options.matchDescription) {
+ var regex = new RegExp(options.matchDescription);
+
+ if (!regex.test(jsdoc.description)) {
+ context.report(jsdocNode, "JSDoc description does not satisfy the regex pattern.");
}
- });
+ }
}
}
@@ -28728,19 +42466,53 @@
return {
"ArrowFunctionExpression": startFunction,
"FunctionExpression": startFunction,
"FunctionDeclaration": startFunction,
+ "ClassExpression": startFunction,
+ "ClassDeclaration": startFunction,
"ArrowFunctionExpression:exit": checkJSDoc,
"FunctionExpression:exit": checkJSDoc,
"FunctionDeclaration:exit": checkJSDoc,
+ "ClassExpression:exit": checkJSDoc,
+ "ClassDeclaration:exit": checkJSDoc,
"ReturnStatement": addReturn
};
};
-},{"doctrine":9}],280:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "type": "object",
+ "properties": {
+ "prefer": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "requireReturn": {
+ "type": "boolean"
+ },
+ "requireParamDescription": {
+ "type": "boolean"
+ },
+ "requireReturnDescription": {
+ "type": "boolean"
+ },
+ "matchDescription": {
+ "type": "string"
+ },
+ "requireReturnType": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{"doctrine":10}],304:[function(require,module,exports){
/**
* @fileoverview Ensures that the results of typeof are compared against a valid string
* @author Ian Christian Myers
*/
"use strict";
@@ -28758,11 +42530,11 @@
// Public
//--------------------------------------------------------------------------
return {
- "UnaryExpression": function (node) {
+ "UnaryExpression": function(node) {
var parent, sibling;
if (node.operator === "typeof") {
parent = context.getAncestors().pop();
@@ -28778,11 +42550,13 @@
};
};
-},{}],281:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],305:[function(require,module,exports){
/**
* @fileoverview Rule to enforce var declarations are only at the top of a function.
* @author Danny Fritz
* @author Gyandeep Singh
* @copyright 2014 Danny Fritz. All rights reserved.
@@ -28792,11 +42566,11 @@
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
+module.exports = function(context) {
var errorMessage = "All \"var\" declarations must be at the top of the function scope.";
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
@@ -28809,21 +42583,31 @@
return node.type === "ExpressionStatement" &&
node.expression.type === "Literal" && typeof node.expression.value === "string";
}
/**
+ * Check to see if its a ES6 import declaration
+ * @param {ASTNode} node - any node
+ * @returns {Boolean} whether the given node represents a import declaration
+ */
+ function looksLikeImport(node) {
+ return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" ||
+ node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier";
+ }
+
+ /**
* Checks whether this variable is on top of the block body
* @param {ASTNode} node - The node to check
* @param {ASTNode[]} statements - collection of ASTNodes for the parent node block
* @returns {Boolean} True if var is on top otherwise false
*/
function isVarOnTop(node, statements) {
var i = 0, l = statements.length;
// skip over directives
for (; i < l; ++i) {
- if (!looksLikeDirective(statements[i])) {
+ if (!looksLikeDirective(statements[i]) && !looksLikeImport(statements[i])) {
break;
}
}
for (; i < l; ++i) {
@@ -28866,28 +42650,30 @@
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
return {
- "VariableDeclaration": function (node) {
+ "VariableDeclaration": function(node) {
var ancestors = context.getAncestors();
var parent = ancestors.pop();
var grandParent = ancestors.pop();
- if (node.kind === "var") {// check variable is `var` type and not `let` or `const`
- if (parent.type === "Program") {// That means its a global variable
+ if (node.kind === "var") { // check variable is `var` type and not `let` or `const`
+ if (parent.type === "Program") { // That means its a global variable
globalVarCheck(node, parent);
} else {
blockScopeVarCheck(node, parent, grandParent);
}
}
}
};
};
-},{}],282:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],306:[function(require,module,exports){
/**
* @fileoverview Rule to flag when IIFE is not wrapped in parens
* @author Ilya Volodin
* @copyright 2013 Ilya Volodin. All rights reserved.
*/
@@ -28900,10 +42686,16 @@
module.exports = function(context) {
var style = context.options[0] || "outside";
+ /**
+ * Check if the node is wrapped in ()
+ * @param {ASTNode} node node to evaluate
+ * @returns {boolean} True if it is wrapped
+ * @private
+ */
function wrapped(node) {
var previousToken = context.getTokenBefore(node),
nextToken = context.getTokenAfter(node);
return previousToken && previousToken.value === "(" &&
nextToken && nextToken.value === ")";
@@ -28927,11 +42719,17 @@
}
};
};
-},{}],283:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["outside", "inside", "any"]
+ }
+];
+
+},{}],307:[function(require,module,exports){
/**
* @fileoverview Rule to flag when regex literals are not wrapped in parens
* @author Matt DuVall <http://www.mattduvall.com>
*/
@@ -28965,11 +42763,13 @@
}
};
};
-},{}],284:[function(require,module,exports){
+module.exports.schema = [];
+
+},{}],308:[function(require,module,exports){
/**
* @fileoverview Rule to require or disallow yoda comparisons
* @author Nicholas C. Zakas
* @copyright 2014 Nicholas C. Zakas. All rights reserved.
* @copyright 2014 Brandon Mills. All rights reserved.
@@ -28988,10 +42788,19 @@
function isComparisonOperator(operator) {
return (/^(==|===|!=|!==|<|>|<=|>=)$/).test(operator);
}
/**
+ * Determines whether an operator is an equality operator.
+ * @param {String} operator The operator to check.
+ * @returns {boolean} Whether or not it is an equality operator.
+ */
+function isEqualityOperator(operator) {
+ return (/^(==|===)$/).test(operator);
+}
+
+/**
* Determines whether an operator is one used in a range test.
* Allowed operators are `<` and `<=`.
* @param {String} operator The operator to check.
* @returns {boolean} Whether the operator is used in range tests.
*/
@@ -29062,24 +42871,27 @@
case "MemberExpression":
// x[0] = x[0]
// x[y] = x[y]
// x.y = x.y
return same(a.object, b.object) && same(a.property, b.property);
+ case "ThisExpression":
+ return true;
default:
return false;
}
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
-module.exports = function (context) {
+module.exports = function(context) {
// Default to "never" (!always) if no option
var always = (context.options[0] === "always");
var exceptRange = (context.options[1] && context.options[1].exceptRange);
+ var onlyEquality = (context.options[1] && context.options[1].onlyEquality);
/**
* Determines whether node represents a range test.
* A range test is a "between" test like `(0 <= x && x < 1)` or an "outside"
* test like `(x < 0 || 1 <= x)`. It must be wrapped in parentheses, and
@@ -29153,10 +42965,12 @@
"BinaryExpression": always ? function(node) {
// Comparisons must always be yoda-style: if ("blue" === color)
if (
(node.right.type === "Literal" || looksLikeLiteral(node.right)) &&
+ !(node.left.type === "Literal" || looksLikeLiteral(node.left)) &&
+ !(!isEqualityOperator(node.operator) && onlyEquality) &&
isComparisonOperator(node.operator) &&
!(exceptRange && isRangeTest(context.getAncestors().pop()))
) {
context.report(node, "Expected literal to be on the left side of " + node.operator + ".");
}
@@ -29164,10 +42978,12 @@
} : function(node) {
// Comparisons must never be yoda-style (default)
if (
(node.left.type === "Literal" || looksLikeLiteral(node.left)) &&
+ !(node.right.type === "Literal" || looksLikeLiteral(node.right)) &&
+ !(!isEqualityOperator(node.operator) && onlyEquality) &&
isComparisonOperator(node.operator) &&
!(exceptRange && isRangeTest(context.getAncestors().pop()))
) {
context.report(node, "Expected literal to be on the right side of " + node.operator + ".");
}
@@ -29175,11 +42991,29 @@
}
};
};
-},{}],285:[function(require,module,exports){
+module.exports.schema = [
+ {
+ "enum": ["always", "never"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "exceptRange": {
+ "type": "boolean"
+ },
+ "onlyEquality": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+];
+
+},{}],309:[function(require,module,exports){
(function (process){
/**
* @fileoverview Tracks performance of individual rules.
* @author Brandon Mills
* @copyright 2014 Brandon Mills. All rights reserved.
@@ -29190,15 +43024,31 @@
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/* istanbul ignore next */
+/**
+ * Align the string to left
+ * @param {string} str string to evaluate
+ * @param {int} len length of the string
+ * @param {string} ch delimiter character
+ * @returns {string} modified string
+ * @private
+ */
function alignLeft(str, len, ch) {
return str + new Array(len - str.length + 1).join(ch || " ");
}
/* istanbul ignore next */
+/**
+ * Align the string to right
+ * @param {string} str string to evaluate
+ * @param {int} len length of the string
+ * @param {string} ch delimiter character
+ * @returns {string} modified string
+ * @private
+ */
function alignRight(str, len, ch) {
return new Array(len - str.length + 1).join(ch || " ") + str;
}
//------------------------------------------------------------------------------
@@ -29209,10 +43059,16 @@
var HEADERS = ["Rule", "Time (ms)", "Relative"];
var ALIGN = [alignLeft, alignRight, alignRight];
/* istanbul ignore next */
+/**
+ * display the data
+ * @param {object} data Data object to be displayed
+ * @returns {string} modified string
+ * @private
+ */
function display(data) {
var total = 0;
var rows = Object.keys(data)
.map(function(key) {
var time = data[key];
@@ -29261,10 +43117,17 @@
/* istanbul ignore next */
module.exports = (function() {
var data = Object.create(null);
+ /**
+ * Time the run
+ * @param {*} key key from the data object
+ * @param {Function} fn function to be called
+ * @returns {Function} function to be executed
+ * @private
+ */
function time(key, fn) {
if (typeof data[key] === "undefined") {
data[key] = 0;
}
@@ -29288,11 +43151,11 @@
};
}());
}).call(this,require('_process'))
-},{"_process":6}],286:[function(require,module,exports){
+},{"_process":109}],310:[function(require,module,exports){
/**
* @fileoverview Object to handle access and retrieval of tokens.
* @author Brandon Mills
* @copyright 2014 Nicholas C. Zakas. All rights reserved.
* @copyright 2014 Brandon Mills. All rights reserved.
@@ -29491,87 +43354,747 @@
};
return api;
};
-},{}],287:[function(require,module,exports){
+},{}],311:[function(require,module,exports){
/**
- * @fileoverview Common utilities.
+ * @fileoverview The event generator for comments.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
+
"use strict";
//------------------------------------------------------------------------------
-// Constants
+// Helpers
//------------------------------------------------------------------------------
-var PLUGIN_NAME_PREFIX = "eslint-plugin-";
+/**
+ * Check collection of comments to prevent double event for comment as
+ * leading and trailing, then emit event if passing
+ * @param {ASTNode[]} comments - Collection of comment nodes
+ * @param {EventEmitter} emitter - The event emitter which is the destination of events.
+ * @param {Object[]} locs - List of locations of previous comment nodes
+ * @param {string} eventName - Event name postfix
+ * @returns {void}
+ */
+function emitComments(comments, emitter, locs, eventName) {
+ if (comments.length > 0) {
+ comments.forEach(function(node) {
+ var index = locs.indexOf(node.loc);
+ if (index >= 0) {
+ locs.splice(index, 1);
+ } else {
+ locs.push(node.loc);
+ emitter.emit(node.type + eventName, node);
+ }
+ });
+ }
+}
+/**
+ * Shortcut to check and emit enter of comment nodes
+ * @param {CommentEventGenerator} generator - A generator to emit.
+ * @param {ASTNode[]} comments - Collection of comment nodes
+ * @returns {void}
+ */
+function emitCommentsEnter(generator, comments) {
+ emitComments(
+ comments,
+ generator.emitter,
+ generator.commentLocsEnter,
+ "Comment");
+}
+
+/**
+ * Shortcut to check and emit exit of comment nodes
+ * @param {CommentEventGenerator} generator - A generator to emit.
+ * @param {ASTNode[]} comments Collection of comment nodes
+ * @returns {void}
+ */
+function emitCommentsExit(generator, comments) {
+ emitComments(
+ comments,
+ generator.emitter,
+ generator.commentLocsExit,
+ "Comment:exit");
+}
+
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
+
/**
- * Merges two objects together and assigns the result to the initial object. Can be used for shallow cloning.
- * @param {Object} target of the cloning operation
- * @param {Object} source object
- * @returns {void}
+ * The event generator for comments.
+ * This is the decorator pattern.
+ * This generates events of comments before/after events which are generated the original generator.
+ *
+ * @param {EventGenerator} originalEventGenerator - An event generator which is the decoration target.
+ * @param {SourceCode} sourceCode - A source code which has comments.
+ * @returns {CommentEventGenerator} new instance.
*/
-exports.mixin = function(target, source) {
- Object.keys(source).forEach(function(key) {
- target[key] = source[key];
- });
+function CommentEventGenerator(originalEventGenerator, sourceCode) {
+ this.original = originalEventGenerator;
+ this.emitter = originalEventGenerator.emitter;
+ this.sourceCode = sourceCode;
+ this.commentLocsEnter = [];
+ this.commentLocsExit = [];
+}
+
+CommentEventGenerator.prototype = {
+ constructor: CommentEventGenerator,
+
+ /**
+ * Emits an event of entering comments.
+ * @param {ASTNode} node - A node which was entered.
+ * @returns {void}
+ */
+ enterNode: function enterNode(node) {
+ var comments = this.sourceCode.getComments(node);
+
+ emitCommentsEnter(this, comments.leading);
+ this.original.enterNode(node);
+ emitCommentsEnter(this, comments.trailing);
+ },
+
+ /**
+ * Emits an event of leaving comments.
+ * @param {ASTNode} node - A node which was left.
+ * @returns {void}
+ */
+ leaveNode: function leaveNode(node) {
+ var comments = this.sourceCode.getComments(node);
+
+ emitCommentsExit(this, comments.trailing);
+ this.original.leaveNode(node);
+ emitCommentsExit(this, comments.leading);
+ }
};
+module.exports = CommentEventGenerator;
+
+},{}],312:[function(require,module,exports){
/**
- * Merges two config objects. This will not only add missing keys, but will also modify values to match.
- * @param {Object} base config object
- * @param {Object} custom config object. Overrides in this config object will take priority over base.
- * @returns {Object} merged config object.
+ * @fileoverview Patch for estraverse
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ * See LICENSE file in root directory for full license.
*/
-exports.mergeConfigs = function mergeConfigs(base, custom) {
+"use strict";
- Object.keys(custom).forEach(function (key) {
- var property = custom[key];
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
- if (key === "plugins") {
- if (!base[key]) {
- base[key] = [];
+var estraverse = require("estraverse"),
+ jsxKeys = require("estraverse-fb/keys");
+
+//------------------------------------------------------------------------------
+// Helers
+//------------------------------------------------------------------------------
+
+var experimentalKeys = {
+ ExperimentalRestProperty: ["argument"],
+ ExperimentalSpreadProperty: ["argument"]
+};
+
+/**
+ * Adds a given keys to Syntax and VisitorKeys of estraverse.
+ *
+ * @param {object} keys - Key definitions to add.
+ * This is an object as map.
+ * Keys are the node type.
+ * Values are an array of property names to visit.
+ * @returns {void}
+ */
+function installKeys(keys) {
+ for (var key in keys) {
+ if (keys.hasOwnProperty(key)) {
+ estraverse.Syntax[key] = key;
+ if (keys[key]) {
+ estraverse.VisitorKeys[key] = keys[key];
}
+ }
+ }
+}
- property.forEach(function (plugin) {
- // skip duplicates
- if (base[key].indexOf(plugin) === -1) {
- base[key].push(plugin);
+// Add JSX node types.
+installKeys(jsxKeys);
+// Add Experimental node types.
+installKeys(experimentalKeys);
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+module.exports = estraverse;
+
+},{"estraverse":89,"estraverse-fb/keys":88}],313:[function(require,module,exports){
+/**
+ * @fileoverview A shared list of ES3 keywords.
+ * @author Josh Perez
+ * @copyright 2015 Jose Roberto Vidal. All rights reserved.
+ */
+"use strict";
+
+module.exports = [
+ "abstract",
+ "boolean",
+ "break",
+ "byte",
+ "case",
+ "catch",
+ "char",
+ "class",
+ "const",
+ "continue",
+ "debugger",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "else",
+ "enum",
+ "export",
+ "extends",
+ "false",
+ "final",
+ "finally",
+ "float",
+ "for",
+ "function",
+ "goto",
+ "if",
+ "implements",
+ "import",
+ "in",
+ "instanceof",
+ "int",
+ "interface",
+ "long",
+ "native",
+ "new",
+ "null",
+ "package",
+ "private",
+ "protected",
+ "public",
+ "return",
+ "short",
+ "static",
+ "super",
+ "switch",
+ "synchronized",
+ "this",
+ "throw",
+ "throws",
+ "transient",
+ "true",
+ "try",
+ "typeof",
+ "var",
+ "void",
+ "volatile",
+ "while",
+ "with"
+];
+
+},{}],314:[function(require,module,exports){
+/**
+ * @fileoverview The event generator for AST nodes.
+ * @author Toru Nagashima
+ * @copyright 2015 Toru Nagashima. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+/**
+ * The event generator for AST nodes.
+ * This implements below interface.
+ *
+ * ```ts
+ * interface EventGenerator {
+ * emitter: EventEmitter;
+ * enterNode(node: ASTNode): void;
+ * leaveNode(node: ASTNode): void;
+ * }
+ * ```
+ *
+ * @param {EventEmitter} emitter - An event emitter which is the destination of events.
+ * @returns {NodeEventGenerator} new instance.
+ */
+function NodeEventGenerator(emitter) {
+ this.emitter = emitter;
+}
+
+NodeEventGenerator.prototype = {
+ constructor: NodeEventGenerator,
+
+ /**
+ * Emits an event of entering AST node.
+ * @param {ASTNode} node - A node which was entered.
+ * @returns {void}
+ */
+ enterNode: function enterNode(node) {
+ this.emitter.emit(node.type, node);
+ },
+
+ /**
+ * Emits an event of leaving AST node.
+ * @param {ASTNode} node - A node which was left.
+ * @returns {void}
+ */
+ leaveNode: function leaveNode(node) {
+ this.emitter.emit(node.type + ":exit", node);
+ }
+};
+
+module.exports = NodeEventGenerator;
+
+},{}],315:[function(require,module,exports){
+/**
+ * @fileoverview An object that creates fix commands for rules.
+ * @author Nicholas C. Zakas
+ * @copyright 2015 Nicholas C. Zakas. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+// none!
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Creates a fix command that inserts text at the specified index in the source text.
+ * @param {int} index The 0-based index at which to insert the new text.
+ * @param {string} text The text to insert.
+ * @returns {Object} The fix command.
+ * @private
+ */
+function insertTextAt(index, text) {
+ return {
+ range: [index, index],
+ text: text
+ };
+}
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+/**
+ * Creates code fixing commands for rules.
+ * @constructor
+ */
+function RuleFixer() {
+ Object.freeze(this);
+}
+
+RuleFixer.prototype = {
+ constructor: RuleFixer,
+
+ /**
+ * Creates a fix command that inserts text after the given node or token.
+ * The fix is not applied until applyFixes() is called.
+ * @param {ASTNode|Token} nodeOrToken The node or token to insert after.
+ * @param {string} text The text to insert.
+ * @returns {Object} The fix command.
+ */
+ insertTextAfter: function(nodeOrToken, text) {
+ return this.insertTextAfterRange(nodeOrToken.range, text);
+ },
+
+ /**
+ * Creates a fix command that inserts text after the specified range in the source text.
+ * The fix is not applied until applyFixes() is called.
+ * @param {int[]} range The range to replace, first item is start of range, second
+ * is end of range.
+ * @param {string} text The text to insert.
+ * @returns {Object} The fix command.
+ */
+ insertTextAfterRange: function(range, text) {
+ return insertTextAt(range[1], text);
+ },
+
+ /**
+ * Creates a fix command that inserts text before the given node or token.
+ * The fix is not applied until applyFixes() is called.
+ * @param {ASTNode|Token} nodeOrToken The node or token to insert before.
+ * @param {string} text The text to insert.
+ * @returns {Object} The fix command.
+ */
+ insertTextBefore: function(nodeOrToken, text) {
+ return this.insertTextBeforeRange(nodeOrToken.range, text);
+ },
+
+ /**
+ * Creates a fix command that inserts text before the specified range in the source text.
+ * The fix is not applied until applyFixes() is called.
+ * @param {int[]} range The range to replace, first item is start of range, second
+ * is end of range.
+ * @param {string} text The text to insert.
+ * @returns {Object} The fix command.
+ */
+ insertTextBeforeRange: function(range, text) {
+ return insertTextAt(range[0], text);
+ },
+
+ /**
+ * Creates a fix command that replaces text at the node or token.
+ * The fix is not applied until applyFixes() is called.
+ * @param {ASTNode|Token} nodeOrToken The node or token to remove.
+ * @param {string} text The text to insert.
+ * @returns {Object} The fix command.
+ */
+ replaceText: function(nodeOrToken, text) {
+ return this.replaceTextRange(nodeOrToken.range, text);
+ },
+
+ /**
+ * Creates a fix command that replaces text at the specified range in the source text.
+ * The fix is not applied until applyFixes() is called.
+ * @param {int[]} range The range to replace, first item is start of range, second
+ * is end of range.
+ * @param {string} text The text to insert.
+ * @returns {Object} The fix command.
+ */
+ replaceTextRange: function(range, text) {
+ return {
+ range: range,
+ text: text
+ };
+ },
+
+ /**
+ * Creates a fix command that removes the node or token from the source.
+ * The fix is not applied until applyFixes() is called.
+ * @param {ASTNode|Token} nodeOrToken The node or token to remove.
+ * @returns {Object} The fix command.
+ */
+ remove: function(nodeOrToken) {
+ return this.removeRange(nodeOrToken.range);
+ },
+
+ /**
+ * Creates a fix command that removes the specified range of text from the source.
+ * The fix is not applied until applyFixes() is called.
+ * @param {int[]} range The range to remove, first item is start of range, second
+ * is end of range.
+ * @returns {Object} The fix command.
+ */
+ removeRange: function(range) {
+ return {
+ range: range,
+ text: ""
+ };
+ }
+
+};
+
+
+module.exports = RuleFixer;
+
+},{}],316:[function(require,module,exports){
+/**
+ * @fileoverview Abstraction of JavaScript source code.
+ * @author Nicholas C. Zakas
+ * @copyright 2015 Nicholas C. Zakas. All rights reserved.
+ * See LICENSE file in root directory for full license.
+ */
+"use strict";
+/* eslint no-underscore-dangle: 0*/
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+var createTokenStore = require("../token-store.js"),
+ estraverse = require("./estraverse"),
+ assign = require("object-assign");
+
+//------------------------------------------------------------------------------
+// Private
+//------------------------------------------------------------------------------
+
+/**
+ * Validates that the given AST has the required information.
+ * @param {ASTNode} ast The Program node of the AST to check.
+ * @throws {Error} If the AST doesn't contain the correct information.
+ * @returns {void}
+ * @private
+ */
+function validate(ast) {
+
+ if (!ast.tokens) {
+ throw new Error("AST is missing the tokens array.");
+ }
+
+ if (!ast.comments) {
+ throw new Error("AST is missing the comments array.");
+ }
+
+ if (!ast.loc) {
+ throw new Error("AST is missing location information.");
+ }
+
+ if (!ast.range) {
+ throw new Error("AST is missing range information");
+ }
+}
+
+/**
+ * Finds a JSDoc comment node in an array of comment nodes.
+ * @param {ASTNode[]} comments The array of comment nodes to search.
+ * @param {int} line Line number to look around
+ * @returns {ASTNode} The node if found, null if not.
+ * @private
+ */
+function findJSDocComment(comments, line) {
+
+ if (comments) {
+ for (var i = comments.length - 1; i >= 0; i--) {
+ if (comments[i].type === "Block" && comments[i].value.charAt(0) === "*") {
+
+ if (line - comments[i].loc.end.line <= 1) {
+ return comments[i];
+ } else {
+ break;
}
- });
- return;
+ }
}
+ }
- if (Array.isArray(base[key]) && !Array.isArray(property) && typeof property === "number") {
- // assume that we are just overriding first attribute
- base[key][0] = custom[key];
- return;
- }
+ return null;
+}
- if (typeof property === "object" && !Array.isArray(property) && property !== null) {
- // base[key] might not exist, so be careful with recursion here
- base[key] = mergeConfigs(base[key] || {}, custom[key]);
- } else {
- base[key] = custom[key];
- }
- });
+/**
+ * Check to see if its a ES6 export declaration
+ * @param {ASTNode} astNode - any node
+ * @returns {boolean} whether the given node represents a export declaration
+ * @private
+ */
+function looksLikeExport(astNode) {
+ return astNode.type === "ExportDefaultDeclaration" || astNode.type === "ExportNamedDeclaration" ||
+ astNode.type === "ExportAllDeclaration" || astNode.type === "ExportSpecifier";
+}
- return base;
-};
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
/**
- * Removes the prefix `eslint-plugin-` from a plugin name.
- * @param {string} pluginName The name of the plugin which may have the prefix.
- * @returns {string} The name of the plugin without prefix.
+ * Represents parsed source code.
+ * @param {string} text The source code text.
+ * @param {ASTNode} ast The Program node of the AST representing the code.
+ * @constructor
*/
-exports.removePluginPrefix = function removePluginPrefix(pluginName) {
- return pluginName.indexOf(PLUGIN_NAME_PREFIX) === 0 ? pluginName.substring(PLUGIN_NAME_PREFIX.length) : pluginName;
+function SourceCode(text, ast) {
+
+ validate(ast);
+
+ /**
+ * The original text source code.
+ * @type string
+ */
+ this.text = text;
+
+ /**
+ * The parsed AST for the source code.
+ * @type ASTNode
+ */
+ this.ast = ast;
+
+ /**
+ * The source code split into lines according to ECMA-262 specification.
+ * This is done to avoid each rule needing to do so separately.
+ * @type string[]
+ */
+ this.lines = text.split(/\r\n|\r|\n|\u2028|\u2029/g);
+
+ this.tokensAndComments = ast.tokens.concat(ast.comments).sort(function(left, right) {
+ return left.range[0] - right.range[0];
+ });
+
+ // create token store methods
+ var tokenStore = createTokenStore(ast.tokens);
+ Object.keys(tokenStore).forEach(function(methodName) {
+ this[methodName] = tokenStore[methodName];
+ }, this);
+
+ var tokensAndCommentsStore = createTokenStore(this.tokensAndComments);
+ this.getTokenOrCommentBefore = tokensAndCommentsStore.getTokenBefore;
+ this.getTokenOrCommentAfter = tokensAndCommentsStore.getTokenAfter;
+
+ // don't allow modification of this object
+ Object.freeze(this);
+ Object.freeze(this.lines);
+}
+
+SourceCode.prototype = {
+ constructor: SourceCode,
+
+ /**
+ * Gets the source code for the given node.
+ * @param {ASTNode=} node The AST node to get the text for.
+ * @param {int=} beforeCount The number of characters before the node to retrieve.
+ * @param {int=} afterCount The number of characters after the node to retrieve.
+ * @returns {string} The text representing the AST node.
+ */
+ getText: function(node, beforeCount, afterCount) {
+ if (node) {
+ return (this.text !== null) ? this.text.slice(Math.max(node.range[0] - (beforeCount || 0), 0),
+ node.range[1] + (afterCount || 0)) : null;
+ } else {
+ return this.text;
+ }
+
+ },
+
+ /**
+ * Gets the entire source text split into an array of lines.
+ * @returns {Array} The source text as an array of lines.
+ */
+ getLines: function() {
+ return this.lines;
+ },
+
+ /**
+ * Retrieves an array containing all comments in the source code.
+ * @returns {ASTNode[]} An array of comment nodes.
+ */
+ getAllComments: function() {
+ return this.ast.comments;
+ },
+
+ /**
+ * Gets all comments for the given node.
+ * @param {ASTNode} node The AST node to get the comments for.
+ * @returns {Object} The list of comments indexed by their position.
+ * @public
+ */
+ getComments: function(node) {
+
+ var leadingComments = node.leadingComments || [],
+ trailingComments = node.trailingComments || [];
+
+ /*
+ * espree adds a "comments" array on Program nodes rather than
+ * leadingComments/trailingComments. Comments are only left in the
+ * Program node comments array if there is no executable code.
+ */
+ if (node.type === "Program") {
+ if (node.body.length === 0) {
+ leadingComments = node.comments;
+ }
+ }
+
+ return {
+ leading: leadingComments,
+ trailing: trailingComments
+ };
+ },
+
+ /**
+ * Retrieves the JSDoc comment for a given node.
+ * @param {ASTNode} node The AST node to get the comment for.
+ * @returns {ASTNode} The BlockComment node containing the JSDoc for the
+ * given node or null if not found.
+ * @public
+ */
+ getJSDocComment: function(node) {
+
+ var parent = node.parent,
+ line = node.loc.start.line;
+
+ switch (node.type) {
+ case "FunctionDeclaration":
+ if (looksLikeExport(parent)) {
+ return findJSDocComment(parent.leadingComments, line);
+ } else {
+ return findJSDocComment(node.leadingComments, line);
+ }
+ break;
+
+ case "ClassDeclaration":
+ return findJSDocComment(node.leadingComments, line);
+
+ case "ClassExpression":
+ return findJSDocComment(parent.parent.leadingComments, line);
+
+ case "ArrowFunctionExpression":
+ case "FunctionExpression":
+
+ if (parent.type !== "CallExpression" && parent.type !== "NewExpression") {
+ while (parent && !parent.leadingComments && !/Function/.test(parent.type)) {
+ parent = parent.parent;
+ }
+
+ return parent && (parent.type !== "FunctionDeclaration") ? findJSDocComment(parent.leadingComments, line) : null;
+ }
+
+ // falls through
+
+ default:
+ return null;
+ }
+ },
+
+ /**
+ * Gets the deepest node containing a range index.
+ * @param {int} index Range index of the desired node.
+ * @returns {ASTNode} The node if found or null if not found.
+ */
+ getNodeByRangeIndex: function(index) {
+ var result = null;
+
+ estraverse.traverse(this.ast, {
+ enter: function(node, parent) {
+ if (node.range[0] <= index && index < node.range[1]) {
+ result = assign({ parent: parent }, node);
+ } else {
+ this.skip();
+ }
+ },
+ leave: function(node) {
+ if (node === result) {
+ this.break();
+ }
+ }
+ });
+
+ return result;
+ },
+
+ /**
+ * Determines if two tokens have at least one whitespace character
+ * between them. This completely disregards comments in making the
+ * determination, so comments count as zero-length substrings.
+ * @param {Token} first The token to check after.
+ * @param {Token} second The token to check before.
+ * @returns {boolean} True if there is only space between tokens, false
+ * if there is anything other than whitespace between tokens.
+ */
+ isSpaceBetweenTokens: function(first, second) {
+ var text = this.text.slice(first.range[1], second.range[0]);
+ return /\s/.test(text.replace(/\/\*.*?\*\//g, ""));
+ }
};
-exports.PLUGIN_NAME_PREFIX = PLUGIN_NAME_PREFIX;
-},{}]},{},[132])(132)
+module.exports = SourceCode;
+
+},{"../token-store.js":310,"./estraverse":312,"object-assign":108}]},{},[116])(116)
});
\ No newline at end of file