mirror of https://github.com/nodejs/node.git
tools: update ESLint to 3.5.0
PR-URL: https://github.com/nodejs/node/pull/8478 Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
a6b1f175c2
commit
2da2625ad1
File diff suppressed because it is too large
Load Diff
|
@ -111,6 +111,7 @@ These folks keep the project moving and are resources for help.
|
|||
* Gyandeep Singh ([@gyandeeps](https://github.com/gyandeeps))
|
||||
* Toru Nagashima ([@mysticatea](https://github.com/mysticatea))
|
||||
* Alberto Rodríguez ([@alberto](https://github.com/alberto))
|
||||
* Kai Cataldo ([@kaicataldo](https://github.com/kaicataldo))
|
||||
|
||||
### Development Team
|
||||
|
||||
|
@ -118,7 +119,6 @@ These folks keep the project moving and are resources for help.
|
|||
* Jamund Ferguson ([@xjamundx](https://github.com/xjamundx))
|
||||
* Ian VanSchooten ([@ianvs](https://github.com/ianvs))
|
||||
* Burak Yiğit Kaya ([@byk](https://github.com/byk))
|
||||
* Kai Cataldo ([@kaicataldo](https://github.com/kaicataldo))
|
||||
* Michael Ficarra ([@michaelficarra](https://github.com/michaelficarra))
|
||||
* Mark Pedrotti ([@pedrottimark](https://github.com/pedrottimark))
|
||||
* Oleg Gaidarenko ([@markelog](https://github.com/markelog))
|
||||
|
@ -128,6 +128,7 @@ These folks keep the project moving and are resources for help.
|
|||
* Alexej Yaroshevich ([@zxqfox](https://github.com/zxqfox))
|
||||
* Kevin Partington ([@platinumazure](https://github.com/platinumazure))
|
||||
* Vitor Balocco ([@vitorbal](https://github.com/vitorbal))
|
||||
* James Henry ([@JamesHenry](https://github.com/JamesHenry))
|
||||
|
||||
## Releases
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
"no-restricted-globals": "off",
|
||||
"no-restricted-imports": "off",
|
||||
"no-restricted-modules": "off",
|
||||
"no-restricted-properties": "off",
|
||||
"no-restricted-syntax": "off",
|
||||
"no-return-assign": "off",
|
||||
"no-script-url": "off",
|
||||
|
@ -171,7 +172,9 @@
|
|||
"key-spacing": "off",
|
||||
"keyword-spacing": "off",
|
||||
"linebreak-style": "off",
|
||||
"line-comment-position": "off",
|
||||
"lines-around-comment": "off",
|
||||
"lines-around-directive": "off",
|
||||
"max-depth": "off",
|
||||
"max-len": "off",
|
||||
"max-lines": "off",
|
||||
|
@ -196,6 +199,7 @@
|
|||
"padded-blocks": "off",
|
||||
"prefer-arrow-callback": "off",
|
||||
"prefer-const": "off",
|
||||
"prefer-numeric-literals": "off",
|
||||
"prefer-reflect": "off",
|
||||
"prefer-rest-params": "off",
|
||||
"prefer-spread": "off",
|
||||
|
|
|
@ -680,5 +680,40 @@ module.exports = {
|
|||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get directives from directive prologue of a Program or Function node.
|
||||
* @param {ASTNode} node - The node to check.
|
||||
* @returns {ASTNode[]} The directives found in the directive prologue.
|
||||
*/
|
||||
getDirectivePrologue(node) {
|
||||
const directives = [];
|
||||
|
||||
// Directive prologues only occur at the top of files or functions.
|
||||
if (
|
||||
node.type === "Program" ||
|
||||
node.type === "FunctionDeclaration" ||
|
||||
node.type === "FunctionExpression" ||
|
||||
|
||||
// Do not check arrow functions with implicit return.
|
||||
// `() => "use strict";` returns the string `"use strict"`.
|
||||
(node.type === "ArrowFunctionExpression" && node.body.type === "BlockStatement")
|
||||
) {
|
||||
const statements = node.type === "Program" ? node.body : node.body.body;
|
||||
|
||||
for (const statement of statements) {
|
||||
if (
|
||||
statement.type === "ExpressionStatement" &&
|
||||
statement.expression.type === "Literal"
|
||||
) {
|
||||
directives.push(statement);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return directives;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -114,6 +114,16 @@ module.exports = {
|
|||
longName = pluginNamespace + PLUGIN_NAME_PREFIX + pluginNameWithoutPrefix;
|
||||
let plugin = null;
|
||||
|
||||
if (pluginName.match(/\s+/)) {
|
||||
const whitespaceError = new Error("Whitespace found in plugin name '" + pluginName + "'");
|
||||
|
||||
whitespaceError.messageTemplate = "whitespace-found";
|
||||
whitespaceError.messageData = {
|
||||
pluginName: longName
|
||||
};
|
||||
throw whitespaceError;
|
||||
}
|
||||
|
||||
if (!plugins[shortName]) {
|
||||
try {
|
||||
plugin = require(longName);
|
||||
|
|
|
@ -598,10 +598,11 @@ module.exports = (function() {
|
|||
* as possible
|
||||
* @param {string} text The text to parse.
|
||||
* @param {Object} config The ESLint configuration object.
|
||||
* @param {string} filePath The path to the file being parsed.
|
||||
* @returns {ASTNode} The AST if successful or null if not.
|
||||
* @private
|
||||
*/
|
||||
function parse(text, config) {
|
||||
function parse(text, config, filePath) {
|
||||
|
||||
let parser,
|
||||
parserOptions = {
|
||||
|
@ -610,7 +611,8 @@ module.exports = (function() {
|
|||
raw: true,
|
||||
tokens: true,
|
||||
comment: true,
|
||||
attachComment: true
|
||||
attachComment: true,
|
||||
filePath
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -783,7 +785,8 @@ module.exports = (function() {
|
|||
shebang = captured;
|
||||
return "//" + captured;
|
||||
}),
|
||||
config
|
||||
config,
|
||||
currentFilename
|
||||
);
|
||||
|
||||
if (ast) {
|
||||
|
@ -974,7 +977,7 @@ module.exports = (function() {
|
|||
}
|
||||
|
||||
if (opts) {
|
||||
message = message.replace(/\{\{\s*(.+?)\s*\}\}/g, function(fullMatch, term) {
|
||||
message = message.replace(/\{\{\s*([^{}]+?)\s*\}\}/g, function(fullMatch, term) {
|
||||
if (term in opts) {
|
||||
return opts[term];
|
||||
}
|
||||
|
|
|
@ -75,7 +75,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "There should be no space after '" + token.value + "'.",
|
||||
message: "There should be no space after '{{tokenValue}}'.",
|
||||
data: {
|
||||
tokenValue: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
const nextToken = sourceCode.getTokenAfter(token);
|
||||
|
||||
|
@ -94,7 +97,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "There should be no space before '" + token.value + "'.",
|
||||
message: "There should be no space before '{{tokenValue}}'.",
|
||||
data: {
|
||||
tokenValue: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
const previousToken = sourceCode.getTokenBefore(token);
|
||||
|
||||
|
@ -113,7 +119,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "A space is required after '" + token.value + "'.",
|
||||
message: "A space is required after '{{tokenValue}}'.",
|
||||
data: {
|
||||
tokenValue: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextAfter(token, " ");
|
||||
}
|
||||
|
@ -130,7 +139,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "A space is required before '" + token.value + "'.",
|
||||
message: "A space is required before '{{tokenValue}}'.",
|
||||
data: {
|
||||
tokenValue: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextBefore(token, " ");
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ module.exports = {
|
|||
node,
|
||||
message: requireForBlockBodyNoParensMessage,
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(token, "(" + token.value + ")");
|
||||
return fixer.replaceText(token, `(${token.value})`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ module.exports = {
|
|||
node,
|
||||
message,
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(token, "(" + token.value + ")");
|
||||
return fixer.replaceText(token, `(${token.value})`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -51,16 +51,18 @@ module.exports = {
|
|||
* @returns {Object} Tokens of arrow and before/after arrow.
|
||||
*/
|
||||
function getTokens(node) {
|
||||
let t = sourceCode.getFirstToken(node);
|
||||
let before;
|
||||
let arrow = sourceCode.getTokenBefore(node.body);
|
||||
|
||||
while (t.type !== "Punctuator" || t.value !== "=>") {
|
||||
before = t;
|
||||
t = sourceCode.getTokenAfter(t);
|
||||
// skip '(' tokens.
|
||||
while (arrow.value !== "=>") {
|
||||
arrow = sourceCode.getTokenBefore(arrow);
|
||||
}
|
||||
const after = sourceCode.getTokenAfter(t);
|
||||
|
||||
return { before, arrow: t, after };
|
||||
return {
|
||||
before: sourceCode.getTokenBefore(arrow),
|
||||
arrow,
|
||||
after: sourceCode.getTokenAfter(arrow)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -97,7 +97,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: openBrace.loc.start,
|
||||
message: message + " after '{'.",
|
||||
message: "{{message}} after '{'.",
|
||||
data: {
|
||||
message
|
||||
},
|
||||
fix(fixer) {
|
||||
if (always) {
|
||||
return fixer.insertTextBefore(firstToken, " ");
|
||||
|
@ -111,7 +114,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: closeBrace.loc.start,
|
||||
message: message + " before '}'.",
|
||||
message: "{{message}} before '}'.",
|
||||
data: {
|
||||
message
|
||||
},
|
||||
fix(fixer) {
|
||||
if (always) {
|
||||
return fixer.insertTextAfter(lastToken, " ");
|
||||
|
|
|
@ -53,7 +53,13 @@ module.exports = {
|
|||
const methodUsesThis = stack.pop();
|
||||
|
||||
if (isInstanceMethod(node.parent) && !methodUsesThis) {
|
||||
context.report(node, "Expected 'this' to be used by class method '" + node.parent.key.name + "'.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Expected 'this' to be used by class method '{{classMethod}}'.",
|
||||
data: {
|
||||
classMethod: node.parent.key.name
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,8 +97,11 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
message: options[dir] ?
|
||||
"A space is required " + dir + " ','." :
|
||||
"There should be no space " + dir + " ','."
|
||||
"A space is required {{dir}} ','." :
|
||||
"There should be no space {{dir}} ','.",
|
||||
data: {
|
||||
dir
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ module.exports = {
|
|||
category: "Stylistic Issues",
|
||||
recommended: false
|
||||
},
|
||||
|
||||
fixable: "code",
|
||||
schema: [
|
||||
{
|
||||
enum: ["first", "last"]
|
||||
|
@ -61,6 +61,49 @@ module.exports = {
|
|||
return !!token && (token.type === "Punctuator") && (token.value === ",");
|
||||
}
|
||||
|
||||
/**
|
||||
* Modified text based on the style
|
||||
* @param {string} styleType Style type
|
||||
* @param {string} text Source code text
|
||||
* @returns {string} modified text
|
||||
* @private
|
||||
*/
|
||||
function getReplacedText(styleType, text) {
|
||||
switch (styleType) {
|
||||
case "between":
|
||||
return `,${text.replace("\n", "")}`;
|
||||
|
||||
case "first":
|
||||
return `${text},`;
|
||||
|
||||
case "last":
|
||||
return `,${text}`;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the fixer function for a given style.
|
||||
* @param {string} styleType comma style
|
||||
* @param {ASTNode} previousItemToken The token to check.
|
||||
* @param {ASTNode} commaToken The token to check.
|
||||
* @param {ASTNode} currentItemToken The token to check.
|
||||
* @returns {Function} Fixer function
|
||||
* @private
|
||||
*/
|
||||
function getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken) {
|
||||
const text =
|
||||
sourceCode.text.slice(previousItemToken.range[1], commaToken.range[0]) +
|
||||
sourceCode.text.slice(commaToken.range[1], currentItemToken.range[0]);
|
||||
const range = [previousItemToken.range[1], currentItemToken.range[0]];
|
||||
|
||||
return function(fixer) {
|
||||
return fixer.replaceTextRange(range, getReplacedText(styleType, text));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the spacing around single items in lists.
|
||||
* @param {Token} previousItemToken The last token from the previous item.
|
||||
|
@ -82,21 +125,35 @@ module.exports = {
|
|||
!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 ','.");
|
||||
context.report({
|
||||
node: reportItem,
|
||||
loc: {
|
||||
line: commaToken.loc.end.line,
|
||||
column: commaToken.loc.start.column
|
||||
},
|
||||
message: "Bad line breaking before and after ','.",
|
||||
fix: getFixerFunction("between", previousItemToken, commaToken, currentItemToken)
|
||||
});
|
||||
|
||||
} else if (style === "first" && !astUtils.isTokenOnSameLine(commaToken, currentItemToken)) {
|
||||
|
||||
context.report(reportItem, "',' should be placed first.");
|
||||
context.report({
|
||||
node: reportItem,
|
||||
message: "',' should be placed first.",
|
||||
fix: getFixerFunction(style, previousItemToken, 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.");
|
||||
context.report({
|
||||
node: reportItem,
|
||||
loc: {
|
||||
line: commaToken.loc.end.line,
|
||||
column: commaToken.loc.end.column
|
||||
},
|
||||
message: "',' should be placed last.",
|
||||
fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "There should be no space after '" + token.value + "'.",
|
||||
message: "There should be no space after '{{tokenValue}}'.",
|
||||
data: {
|
||||
tokenValue: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.removeRange([token.range[1], tokenAfter.range[0]]);
|
||||
}
|
||||
|
@ -64,7 +67,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "There should be no space before '" + token.value + "'.",
|
||||
message: "There should be no space before '{{tokenValue}}'.",
|
||||
data: {
|
||||
tokenValue: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.removeRange([tokenBefore.range[1], token.range[0]]);
|
||||
}
|
||||
|
@ -81,7 +87,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "A space is required after '" + token.value + "'.",
|
||||
message: "A space is required after '{{tokenValue}}'.",
|
||||
data: {
|
||||
tokenValue: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextAfter(token, " ");
|
||||
}
|
||||
|
@ -98,7 +107,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "A space is required before '" + token.value + "'.",
|
||||
message: "A space is required before '{{tokenValue}}'.",
|
||||
data: {
|
||||
tokenValue: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextBefore(token, " ");
|
||||
}
|
||||
|
|
|
@ -145,9 +145,16 @@ module.exports = {
|
|||
if (!funcInfo.hasReturn) {
|
||||
funcInfo.hasReturn = true;
|
||||
funcInfo.hasReturnValue = hasReturnValue;
|
||||
funcInfo.message = "Expected " + (hasReturnValue ? "a" : "no") + " return value.";
|
||||
funcInfo.message = "Expected {{which}} return value.";
|
||||
funcInfo.data = {
|
||||
which: hasReturnValue ? "a" : "no"
|
||||
};
|
||||
} else if (funcInfo.hasReturnValue !== hasReturnValue) {
|
||||
context.report({node, message: funcInfo.message});
|
||||
context.report({
|
||||
node,
|
||||
message: funcInfo.message,
|
||||
data: funcInfo.data
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ module.exports = {
|
|||
message: "Expected { after '{{name}}'{{suffix}}.",
|
||||
data: {
|
||||
name,
|
||||
suffix: (suffix ? " " + suffix : "")
|
||||
suffix: (suffix ? ` ${suffix}` : "")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ module.exports = {
|
|||
message: "Unnecessary { after '{{name}}'{{suffix}}.",
|
||||
data: {
|
||||
name,
|
||||
suffix: (suffix ? " " + suffix : "")
|
||||
suffix: (suffix ? ` ${suffix}` : "")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -32,12 +32,15 @@ module.exports = {
|
|||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
fixable: "code"
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const options = context.options[0] || {};
|
||||
const allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords;
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
let allowPattern;
|
||||
|
||||
|
@ -51,18 +54,62 @@ module.exports = {
|
|||
node.computed &&
|
||||
node.property.type === "Literal" &&
|
||||
validIdentifier.test(node.property.value) &&
|
||||
(allowKeywords || keywords.indexOf("" + node.property.value) === -1)
|
||||
(allowKeywords || keywords.indexOf(String(node.property.value)) === -1)
|
||||
) {
|
||||
if (!(allowPattern && allowPattern.test(node.property.value))) {
|
||||
context.report(node.property, "[" + JSON.stringify(node.property.value) + "] is better written in dot notation.");
|
||||
context.report({
|
||||
node: node.property,
|
||||
message: "[{{propertyValue}}] is better written in dot notation.",
|
||||
data: {
|
||||
propertyValue: JSON.stringify(node.property.value)
|
||||
},
|
||||
fix(fixer) {
|
||||
const leftBracket = sourceCode.getTokenBefore(node.property);
|
||||
const rightBracket = sourceCode.getTokenAfter(node.property);
|
||||
const textBeforeProperty = sourceCode.text.slice(leftBracket.range[1], node.property.range[0]);
|
||||
const textAfterProperty = sourceCode.text.slice(node.property.range[1], rightBracket.range[0]);
|
||||
|
||||
if (textBeforeProperty.trim() || textAfterProperty.trim()) {
|
||||
|
||||
// Don't perform any fixes if there are comments inside the brackets.
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
[leftBracket.range[0], rightBracket.range[1]],
|
||||
`.${node.property.value}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (
|
||||
!allowKeywords &&
|
||||
!node.computed &&
|
||||
keywords.indexOf("" + node.property.name) !== -1
|
||||
keywords.indexOf(String(node.property.name)) !== -1
|
||||
) {
|
||||
context.report(node.property, "." + node.property.name + " is a syntax error.");
|
||||
context.report({
|
||||
node: node.property,
|
||||
message: ".{{propertyName}} is a syntax error.",
|
||||
data: {
|
||||
propertyName: node.property.name
|
||||
},
|
||||
fix(fixer) {
|
||||
const dot = sourceCode.getTokenBefore(node.property);
|
||||
const textAfterDot = sourceCode.text.slice(dot.range[1], node.property.range[0]);
|
||||
|
||||
if (textAfterDot.trim()) {
|
||||
|
||||
// Don't perform any fixes if there are comments between the dot and the property name.
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
[dot.range[0], node.property.range[1]],
|
||||
`[${textAfterDot}"${node.property.name}"]`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -87,11 +87,16 @@ module.exports = {
|
|||
const spaceRequired = mode[side];
|
||||
const node = after ? leftToken : rightToken;
|
||||
const type = spaceRequired ? "Missing" : "Unexpected";
|
||||
const message = type + " space " + side + " *.";
|
||||
const message = "{{type}} space {{side}} *.";
|
||||
const data = {
|
||||
type,
|
||||
side
|
||||
};
|
||||
|
||||
context.report({
|
||||
node,
|
||||
message,
|
||||
data,
|
||||
fix(fixer) {
|
||||
if (spaceRequired) {
|
||||
if (after) {
|
||||
|
|
|
@ -73,6 +73,46 @@ module.exports = {
|
|||
MemberExpression: {
|
||||
type: "integer",
|
||||
minimum: 0
|
||||
},
|
||||
FunctionDeclaration: {
|
||||
type: "object",
|
||||
properties: {
|
||||
parameters: {
|
||||
oneOf: [
|
||||
{
|
||||
type: "integer",
|
||||
minimum: 0
|
||||
},
|
||||
{
|
||||
enum: ["first"]
|
||||
}
|
||||
]
|
||||
},
|
||||
body: {
|
||||
type: "integer",
|
||||
minimum: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
FunctionExpression: {
|
||||
type: "object",
|
||||
properties: {
|
||||
parameters: {
|
||||
oneOf: [
|
||||
{
|
||||
type: "integer",
|
||||
minimum: 0
|
||||
},
|
||||
{
|
||||
enum: ["first"]
|
||||
}
|
||||
]
|
||||
},
|
||||
body: {
|
||||
type: "integer",
|
||||
minimum: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
|
@ -84,6 +124,8 @@ module.exports = {
|
|||
|
||||
const MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}.";
|
||||
const DEFAULT_VARIABLE_INDENT = 1;
|
||||
const DEFAULT_PARAMETER_INDENT = null; // For backwards compatibility, don't check parameter indentation unless specified in the config
|
||||
const DEFAULT_FUNCTION_BODY_INDENT = 1;
|
||||
|
||||
let indentType = "space";
|
||||
let indentSize = 4;
|
||||
|
@ -94,7 +136,15 @@ module.exports = {
|
|||
let: DEFAULT_VARIABLE_INDENT,
|
||||
const: DEFAULT_VARIABLE_INDENT
|
||||
},
|
||||
outerIIFEBody: null
|
||||
outerIIFEBody: null,
|
||||
FunctionDeclaration: {
|
||||
parameters: DEFAULT_PARAMETER_INDENT,
|
||||
body: DEFAULT_FUNCTION_BODY_INDENT
|
||||
},
|
||||
FunctionExpression: {
|
||||
parameters: DEFAULT_PARAMETER_INDENT,
|
||||
body: DEFAULT_FUNCTION_BODY_INDENT
|
||||
}
|
||||
};
|
||||
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
@ -131,6 +181,14 @@ module.exports = {
|
|||
if (typeof opts.MemberExpression === "number") {
|
||||
options.MemberExpression = opts.MemberExpression;
|
||||
}
|
||||
|
||||
if (typeof opts.FunctionDeclaration === "object") {
|
||||
Object.assign(options.FunctionDeclaration, opts.FunctionDeclaration);
|
||||
}
|
||||
|
||||
if (typeof opts.FunctionExpression === "object") {
|
||||
Object.assign(options.FunctionExpression, opts.FunctionExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +226,7 @@ module.exports = {
|
|||
let rangeToFix = [];
|
||||
|
||||
if (needed > gotten) {
|
||||
const spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future
|
||||
const spaces = indentChar.repeat(needed - gotten);
|
||||
|
||||
if (isLastNodeCheck === true) {
|
||||
rangeToFix = [
|
||||
|
@ -492,11 +550,15 @@ module.exports = {
|
|||
}
|
||||
|
||||
// function body indent should be indent + indent size, unless this
|
||||
// is the outer IIFE and that option is enabled.
|
||||
// is a FunctionDeclaration, FunctionExpression, or outer IIFE and the corresponding options are enabled.
|
||||
let functionOffset = indentSize;
|
||||
|
||||
if (options.outerIIFEBody !== null && isOuterIIFE(calleeNode)) {
|
||||
functionOffset = options.outerIIFEBody * indentSize;
|
||||
} else if (calleeNode.type === "FunctionExpression") {
|
||||
functionOffset = options.FunctionExpression.body * indentSize;
|
||||
} else if (calleeNode.type === "FunctionDeclaration") {
|
||||
functionOffset = options.FunctionDeclaration.body * indentSize;
|
||||
}
|
||||
indent += functionOffset;
|
||||
|
||||
|
@ -884,6 +946,28 @@ module.exports = {
|
|||
const caseIndent = expectedCaseIndent(node);
|
||||
|
||||
checkNodesIndent(node.consequent, caseIndent + indentSize);
|
||||
},
|
||||
|
||||
FunctionDeclaration(node) {
|
||||
if (isSingleLineNode(node)) {
|
||||
return;
|
||||
}
|
||||
if (options.FunctionDeclaration.parameters === "first" && node.params.length) {
|
||||
checkNodesIndent(node.params.slice(1), node.params[0].loc.start.column);
|
||||
} else if (options.FunctionDeclaration.parameters !== null) {
|
||||
checkNodesIndent(node.params, indentSize * options.FunctionDeclaration.parameters);
|
||||
}
|
||||
},
|
||||
|
||||
FunctionExpression(node) {
|
||||
if (isSingleLineNode(node)) {
|
||||
return;
|
||||
}
|
||||
if (options.FunctionExpression.parameters === "first" && node.params.length) {
|
||||
checkNodesIndent(node.params.slice(1), node.params[0].loc.start.column);
|
||||
} else if (options.FunctionExpression.parameters !== null) {
|
||||
checkNodesIndent(node.params, indentSize * options.FunctionExpression.parameters);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -114,9 +114,21 @@ module.exports = {
|
|||
}
|
||||
|
||||
if (mode === MODE_ALWAYS && !initialized) {
|
||||
context.report(declaration, "Variable '" + id.name + "' should be initialized on declaration.");
|
||||
context.report({
|
||||
node: declaration,
|
||||
message: "Variable '{{idName}}' should be initialized on declaration.",
|
||||
data: {
|
||||
idName: id.name
|
||||
}
|
||||
});
|
||||
} else if (mode === MODE_NEVER && kind !== "const" && initialized && !isIgnoredForLoop) {
|
||||
context.report(declaration, "Variable '" + id.name + "' should not be initialized on declaration.");
|
||||
context.report({
|
||||
node: declaration,
|
||||
message: "Variable '{{idName}}' should not be initialized on declaration.",
|
||||
data: {
|
||||
idName: id.name
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,10 @@ module.exports = {
|
|||
if (attributeValue && astUtils.isStringLiteral(attributeValue) && !usesExpectedQuotes(attributeValue)) {
|
||||
context.report({
|
||||
node: attributeValue,
|
||||
message: "Unexpected usage of " + setting.description + ".",
|
||||
message: "Unexpected usage of {{description}}.",
|
||||
data: {
|
||||
description: setting.description
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(attributeValue, setting.convert(attributeValue.raw));
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ function initOptions(toOptions, fromOptions) {
|
|||
if (toOptions.multiLine.align) {
|
||||
toOptions.align = {
|
||||
on: toOptions.multiLine.align.on,
|
||||
mode: toOptions.multiLine.mode,
|
||||
mode: toOptions.multiLine.align.mode || toOptions.multiLine.mode,
|
||||
beforeColon: toOptions.multiLine.align.beforeColon,
|
||||
afterColon: toOptions.multiLine.align.afterColon
|
||||
};
|
||||
|
@ -289,6 +289,9 @@ module.exports = {
|
|||
multiLine: {
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
enum: ["strict", "minimum"]
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean"
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@ const KEYS = keywords.concat(["as", "await", "from", "get", "let", "of", "set",
|
|||
KEYS.sort();
|
||||
for (let i = 1; i < KEYS.length; ++i) {
|
||||
if (KEYS[i] === KEYS[i - 1]) {
|
||||
throw new Error("Duplication was found in the keyword list: " + KEYS[i]);
|
||||
throw new Error(`Duplication was found in the keyword list: ${KEYS[i]}`);
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* @fileoverview Rule to enforce the position of line comments
|
||||
* @author Alberto Rodríguez
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: "enforce position of line comments",
|
||||
category: "Stylistic Issues",
|
||||
recommended: false
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
enum: ["above", "beside"]
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
position: {
|
||||
enum: ["above", "beside"]
|
||||
},
|
||||
ignorePattern: {
|
||||
type: "string"
|
||||
},
|
||||
applyDefaultPatterns: {
|
||||
type: "boolean"
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const DEFAULT_IGNORE_PATTERN = "^\\s*(?:eslint|jshint\\s+|jslint\\s+|istanbul\\s+|globals?\\s+|exported\\s+|jscs|falls?\\s?through)";
|
||||
const options = context.options[0];
|
||||
|
||||
let above,
|
||||
ignorePattern,
|
||||
applyDefaultPatterns = true;
|
||||
|
||||
if (!options || typeof option === "string") {
|
||||
above = !options || options === "above";
|
||||
|
||||
} else {
|
||||
above = options.position === "above";
|
||||
ignorePattern = options.ignorePattern;
|
||||
applyDefaultPatterns = options.applyDefaultPatterns !== false;
|
||||
}
|
||||
|
||||
const defaultIgnoreRegExp = new RegExp(DEFAULT_IGNORE_PATTERN);
|
||||
const customIgnoreRegExp = new RegExp(ignorePattern);
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
LineComment(node) {
|
||||
if (applyDefaultPatterns && defaultIgnoreRegExp.test(node.value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ignorePattern && customIgnoreRegExp.test(node.value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const previous = sourceCode.getTokenOrCommentBefore(node);
|
||||
const isOnSameLine = previous && previous.loc.end.line === node.loc.start.line;
|
||||
|
||||
if (above) {
|
||||
if (isOnSameLine) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Expected comment to be above code."
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (!isOnSameLine) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Expected comment to be beside code."
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* @fileoverview Require or disallow newlines around directives.
|
||||
* @author Kai Cataldo
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const astUtils = require("../ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: "require or disallow newlines around directives",
|
||||
category: "Stylistic Issues",
|
||||
recommended: false
|
||||
},
|
||||
schema: [{
|
||||
oneOf: [
|
||||
{
|
||||
enum: ["always", "never"]
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
before: {
|
||||
enum: ["always", "never"]
|
||||
},
|
||||
after: {
|
||||
enum: ["always", "never"]
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
minProperties: 2
|
||||
}
|
||||
]
|
||||
}]
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const config = context.options[0] || "always";
|
||||
const expectLineBefore = typeof config === "string" ? config : config.before;
|
||||
const expectLineAfter = typeof config === "string" ? config : config.after;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check if node is preceded by a blank newline.
|
||||
* @param {ASTNode} node Node to check.
|
||||
* @returns {boolean} Whether or not the passed in node is preceded by a blank newline.
|
||||
*/
|
||||
function hasNewlineBefore(node) {
|
||||
const tokenBefore = sourceCode.getTokenOrCommentBefore(node);
|
||||
const tokenLineBefore = tokenBefore ? tokenBefore.loc.end.line : 0;
|
||||
|
||||
return node.loc.start.line - tokenLineBefore >= 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if node is followed by a blank newline.
|
||||
* @param {ASTNode} node Node to check.
|
||||
* @returns {boolean} Whether or not the passed in node is followed by a blank newline.
|
||||
*/
|
||||
function hasNewlineAfter(node) {
|
||||
const tokenAfter = sourceCode.getTokenOrCommentAfter(node);
|
||||
|
||||
return tokenAfter.loc.start.line - node.loc.end.line >= 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report errors for newlines around directives.
|
||||
* @param {ASTNode} node Node to check.
|
||||
* @param {string} location Whether the error was found before or after the directive.
|
||||
* @param {boolean} expected Whether or not a newline was expected or unexpected.
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportError(node, location, expected) {
|
||||
context.report({
|
||||
node,
|
||||
message: "{{expected}} newline {{location}} \"{{value}}\" directive.",
|
||||
data: {
|
||||
expected: expected ? "Expected" : "Unexpected",
|
||||
value: node.expression.value,
|
||||
location
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check lines around directives in node
|
||||
* @param {ASTNode} node - node to check
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkDirectives(node) {
|
||||
const directives = astUtils.getDirectivePrologue(node);
|
||||
|
||||
if (!directives.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstDirective = directives[0];
|
||||
const hasTokenOrCommentBefore = !!sourceCode.getTokenOrCommentBefore(firstDirective);
|
||||
|
||||
// Only check before the first directive if it is preceded by a comment or if it is at the top of
|
||||
// the file and expectLineBefore is set to "never". This is to not force a newline at the top of
|
||||
// the file if there are no comments as well as for compatibility with padded-blocks.
|
||||
if (
|
||||
firstDirective.leadingComments && firstDirective.leadingComments.length ||
|
||||
|
||||
// Shebangs are not added to leading comments but are accounted for by the following.
|
||||
node.type === "Program" && hasTokenOrCommentBefore
|
||||
) {
|
||||
if (expectLineBefore === "always" && !hasNewlineBefore(firstDirective)) {
|
||||
reportError(firstDirective, "before", true);
|
||||
}
|
||||
|
||||
if (expectLineBefore === "never" && hasNewlineBefore(firstDirective)) {
|
||||
reportError(firstDirective, "before", false);
|
||||
}
|
||||
} else if (
|
||||
node.type === "Program" &&
|
||||
expectLineBefore === "never" &&
|
||||
!hasTokenOrCommentBefore &&
|
||||
hasNewlineBefore(firstDirective)
|
||||
) {
|
||||
reportError(firstDirective, "before", false);
|
||||
}
|
||||
|
||||
const lastDirective = directives[directives.length - 1];
|
||||
const statements = node.type === "Program" ? node.body : node.body.body;
|
||||
|
||||
// Do not check after the last directive if the body only
|
||||
// contains a directive prologue and isn't followed by a comment to ensure
|
||||
// this rule behaves well with padded-blocks.
|
||||
if (lastDirective === statements[statements.length - 1] && !lastDirective.trailingComments) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectLineAfter === "always" && !hasNewlineAfter(lastDirective)) {
|
||||
reportError(lastDirective, "after", true);
|
||||
}
|
||||
|
||||
if (expectLineAfter === "never" && hasNewlineAfter(lastDirective)) {
|
||||
reportError(lastDirective, "after", false);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
Program: checkDirectives,
|
||||
FunctionDeclaration: checkDirectives,
|
||||
FunctionExpression: checkDirectives,
|
||||
ArrowFunctionExpression: checkDirectives
|
||||
};
|
||||
}
|
||||
};
|
|
@ -30,9 +30,15 @@ const OPTIONS_SCHEMA = {
|
|||
ignoreComments: {
|
||||
type: "boolean"
|
||||
},
|
||||
ignoreStrings: {
|
||||
type: "boolean"
|
||||
},
|
||||
ignoreUrls: {
|
||||
type: "boolean"
|
||||
},
|
||||
ignoreTemplateLiterals: {
|
||||
type: "boolean"
|
||||
},
|
||||
ignoreTrailingComments: {
|
||||
type: "boolean"
|
||||
}
|
||||
|
@ -121,6 +127,8 @@ module.exports = {
|
|||
const maxLength = options.code || 80,
|
||||
tabWidth = options.tabWidth || 4,
|
||||
ignoreComments = options.ignoreComments || false,
|
||||
ignoreStrings = options.ignoreStrings || false,
|
||||
ignoreTemplateLiterals = options.ignoreTemplateLiterals || false,
|
||||
ignoreTrailingComments = options.ignoreTrailingComments || options.ignoreComments || false,
|
||||
ignoreUrls = options.ignoreUrls || false,
|
||||
maxCommentLength = options.comments;
|
||||
|
@ -179,6 +187,59 @@ module.exports = {
|
|||
return line.slice(0, comment.loc.start.column).replace(/\s+$/, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that an array exists at [key] on `object`, and add `value` to it.
|
||||
*
|
||||
* @param {Object} object the object to mutate
|
||||
* @param {string} key the object's key
|
||||
* @param {*} value the value to add
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function ensureArrayAndPush(object, key, value) {
|
||||
if (!Array.isArray(object[key])) {
|
||||
object[key] = [];
|
||||
}
|
||||
object[key].push(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an array containing all strings (" or ') in the source code.
|
||||
*
|
||||
* @returns {ASTNode[]} An array of string nodes.
|
||||
*/
|
||||
function getAllStrings() {
|
||||
return sourceCode.ast.tokens.filter(function(token) {
|
||||
return token.type === "String";
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an array containing all template literals in the source code.
|
||||
*
|
||||
* @returns {ASTNode[]} An array of template literal nodes.
|
||||
*/
|
||||
function getAllTemplateLiterals() {
|
||||
return sourceCode.ast.tokens.filter(function(token) {
|
||||
return token.type === "Template";
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A reducer to group an AST node by line number, both start and end.
|
||||
*
|
||||
* @param {Object} acc the accumulator
|
||||
* @param {ASTNode} node the AST node in question
|
||||
* @returns {Object} the modified accumulator
|
||||
* @private
|
||||
*/
|
||||
function groupByLineNumber(acc, node) {
|
||||
ensureArrayAndPush(acc, node.loc.start.line, node);
|
||||
ensureArrayAndPush(acc, node.loc.end.line, node);
|
||||
return acc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the program for max length
|
||||
* @param {ASTNode} node Node to examine
|
||||
|
@ -196,6 +257,12 @@ module.exports = {
|
|||
// we iterate over comments in parallel with the lines
|
||||
let commentsIndex = 0;
|
||||
|
||||
const strings = getAllStrings(sourceCode);
|
||||
const stringsByLine = strings.reduce(groupByLineNumber, {});
|
||||
|
||||
const templateLiterals = getAllTemplateLiterals(sourceCode);
|
||||
const templateLiteralsByLine = templateLiterals.reduce(groupByLineNumber, {});
|
||||
|
||||
lines.forEach(function(line, i) {
|
||||
|
||||
// i is zero-indexed, line numbers are one-indexed
|
||||
|
@ -229,7 +296,10 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
if (ignorePattern && ignorePattern.test(line) ||
|
||||
ignoreUrls && URL_REGEXP.test(line)) {
|
||||
ignoreUrls && URL_REGEXP.test(line) ||
|
||||
ignoreStrings && stringsByLine[lineNumber] ||
|
||||
ignoreTemplateLiterals && templateLiteralsByLine[lineNumber]
|
||||
) {
|
||||
|
||||
// ignore this line
|
||||
return;
|
||||
|
@ -242,9 +312,25 @@ module.exports = {
|
|||
}
|
||||
|
||||
if (lineIsComment && lineLength > maxCommentLength) {
|
||||
context.report(node, { line: lineNumber, column: 0 }, "Line " + (i + 1) + " exceeds the maximum comment line length of " + maxCommentLength + ".");
|
||||
context.report({
|
||||
node,
|
||||
loc: { line: lineNumber, column: 0 },
|
||||
message: "Line {{lineNumber}} exceeds the maximum comment line length of {{maxCommentLength}}.",
|
||||
data: {
|
||||
lineNumber: i + 1,
|
||||
maxCommentLength
|
||||
}
|
||||
});
|
||||
} else if (lineLength > maxLength) {
|
||||
context.report(node, { line: lineNumber, column: 0 }, "Line " + (i + 1) + " exceeds the maximum line length of " + maxLength + ".");
|
||||
context.report({
|
||||
node,
|
||||
loc: { line: lineNumber, column: 0 },
|
||||
message: "Line {{lineNumber}} exceeds the maximum line length of {{maxLength}}.",
|
||||
data: {
|
||||
lineNumber: i + 1,
|
||||
maxLength
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -35,9 +35,11 @@ module.exports = {
|
|||
const sourceCode = context.getSourceCode(),
|
||||
options = context.options[0] || {},
|
||||
maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1,
|
||||
message = "This line has too many statements. Maximum allowed is " + maxStatementsPerLine + ".";
|
||||
message = "This line has {{numberOfStatementsOnThisLine}} {{statements}}. Maximum allowed is {{maxStatementsPerLine}}.";
|
||||
|
||||
let lastStatementLine = 0,
|
||||
numberOfStatementsOnThisLine = 0;
|
||||
numberOfStatementsOnThisLine = 0,
|
||||
firstExtraStatement;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
@ -45,6 +47,26 @@ module.exports = {
|
|||
|
||||
const SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/;
|
||||
|
||||
/**
|
||||
* Reports with the first extra statement, and clears it.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportFirstExtraStatementAndClear() {
|
||||
if (firstExtraStatement) {
|
||||
context.report({
|
||||
node: firstExtraStatement,
|
||||
message,
|
||||
data: {
|
||||
numberOfStatementsOnThisLine,
|
||||
maxStatementsPerLine,
|
||||
statements: numberOfStatementsOnThisLine === 1 ? "statement" : "statements",
|
||||
}
|
||||
});
|
||||
}
|
||||
firstExtraStatement = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the actual last token of a given node.
|
||||
*
|
||||
|
@ -83,13 +105,14 @@ module.exports = {
|
|||
if (line === lastStatementLine) {
|
||||
numberOfStatementsOnThisLine += 1;
|
||||
} else {
|
||||
reportFirstExtraStatementAndClear();
|
||||
numberOfStatementsOnThisLine = 1;
|
||||
lastStatementLine = line;
|
||||
}
|
||||
|
||||
// Reports if the node violated this rule.
|
||||
if (numberOfStatementsOnThisLine === maxStatementsPerLine + 1) {
|
||||
context.report({node, message});
|
||||
firstExtraStatement = firstExtraStatement || node;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,6 +127,7 @@ module.exports = {
|
|||
|
||||
// Update state.
|
||||
if (line !== lastStatementLine) {
|
||||
reportFirstExtraStatementAndClear();
|
||||
numberOfStatementsOnThisLine = 1;
|
||||
lastStatementLine = line;
|
||||
}
|
||||
|
@ -161,12 +185,21 @@ module.exports = {
|
|||
"ExportNamedDeclaration:exit": leaveStatement,
|
||||
"ExportDefaultDeclaration:exit": leaveStatement,
|
||||
"ExportAllDeclaration:exit": leaveStatement,
|
||||
"Program:exit": reportFirstExtraStatementAndClear,
|
||||
|
||||
// For backward compatibility.
|
||||
// Empty blocks should be warned if `{max: 0}` was given.
|
||||
BlockStatement: function reportIfZero(node) {
|
||||
if (maxStatementsPerLine === 0 && node.body.length === 0) {
|
||||
context.report({node, message});
|
||||
context.report({
|
||||
node,
|
||||
message,
|
||||
data: {
|
||||
numberOfStatementsOnThisLine: 0,
|
||||
maxStatementsPerLine,
|
||||
statements: "statements",
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -37,7 +37,7 @@ 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");
|
||||
throw new TypeError(`${key}, if provided, must be an Array`);
|
||||
}
|
||||
return obj[key] || fallback;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,44 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks whether the given token is an opening parenthesis or not.
|
||||
*
|
||||
* @param {Token} token - The token to check.
|
||||
* @returns {boolean} `true` if the token is an opening parenthesis.
|
||||
*/
|
||||
function isOpeningParen(token) {
|
||||
return token.type === "Punctuator" && token.value === "(";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given token is an closing parenthesis or not.
|
||||
*
|
||||
* @param {Token} token - The token to check.
|
||||
* @returns {boolean} `true` if the token is an closing parenthesis.
|
||||
*/
|
||||
function isClosingParen(token) {
|
||||
return token.type === "Punctuator" && token.value === ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given node is inside of another given node.
|
||||
*
|
||||
* @param {ASTNode|Token} inner - The inner node to check.
|
||||
* @param {ASTNode|Token} outer - The outer node to check.
|
||||
* @returns {boolean} `true` if the `inner` is in `outer`.
|
||||
*/
|
||||
function isInRange(inner, outer) {
|
||||
const ir = inner.range;
|
||||
const or = outer.range;
|
||||
|
||||
return or[0] <= ir[0] && ir[1] <= or[1];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -17,25 +55,31 @@ module.exports = {
|
|||
recommended: false
|
||||
},
|
||||
|
||||
schema: []
|
||||
schema: [],
|
||||
|
||||
fixable: "code"
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
return {
|
||||
|
||||
NewExpression(node) {
|
||||
const tokens = sourceCode.getTokens(node);
|
||||
const prenticesTokens = tokens.filter(function(token) {
|
||||
return token.value === "(" || token.value === ")";
|
||||
});
|
||||
let token = sourceCode.getTokenAfter(node.callee);
|
||||
|
||||
if (prenticesTokens.length < 2) {
|
||||
context.report(node, "Missing '()' invoking a constructor.");
|
||||
// Skip ')'
|
||||
while (token && isClosingParen(token)) {
|
||||
token = sourceCode.getTokenAfter(token);
|
||||
}
|
||||
|
||||
if (!(token && isOpeningParen(token) && isInRange(token, node))) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Missing '()' invoking a constructor.",
|
||||
fix: fixer => fixer.insertTextAfter(node, "()")
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ module.exports = {
|
|||
category: "Stylistic Issues",
|
||||
recommended: false
|
||||
},
|
||||
|
||||
fixable: "whitespace",
|
||||
schema: []
|
||||
},
|
||||
|
||||
|
@ -103,14 +103,13 @@ module.exports = {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks whether node is preceded by a newline
|
||||
* @param {ASTNode} node - node to check
|
||||
* @returns {boolean} Whether or not the node is preceded by a newline
|
||||
* Returns the line number of the token before the node that is passed in as an argument
|
||||
* @param {ASTNode} node - The node to use as the start of the calculation
|
||||
* @returns {number} Line number of the token before `node`
|
||||
* @private
|
||||
*/
|
||||
function hasNewlineBefore(node) {
|
||||
const tokenBefore = sourceCode.getTokenBefore(node),
|
||||
lineNumNode = node.loc.start.line;
|
||||
function getLineNumberOfTokenBefore(node) {
|
||||
const tokenBefore = sourceCode.getTokenBefore(node);
|
||||
let lineNumTokenBefore;
|
||||
|
||||
/**
|
||||
|
@ -127,11 +126,58 @@ module.exports = {
|
|||
lineNumTokenBefore = 0; // global return at beginning of script
|
||||
}
|
||||
|
||||
return lineNumTokenBefore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether node is preceded by a newline
|
||||
* @param {ASTNode} node - node to check
|
||||
* @returns {boolean} Whether or not the node is preceded by a newline
|
||||
* @private
|
||||
*/
|
||||
function hasNewlineBefore(node) {
|
||||
const lineNumNode = node.loc.start.line;
|
||||
const lineNumTokenBefore = getLineNumberOfTokenBefore(node);
|
||||
const commentLines = calcCommentLines(node, lineNumTokenBefore);
|
||||
|
||||
return (lineNumNode - lineNumTokenBefore - commentLines) > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether it is safe to apply a fix to a given return statement.
|
||||
*
|
||||
* The fix is not considered safe if the given return statement has leading comments,
|
||||
* as we cannot safely determine if the newline should be added before or after the comments.
|
||||
* For more information, see: https://github.com/eslint/eslint/issues/5958#issuecomment-222767211
|
||||
*
|
||||
* @param {ASTNode} node - The return statement node to check.
|
||||
* @returns {boolean} `true` if it can fix the node.
|
||||
* @private
|
||||
*/
|
||||
function canFix(node) {
|
||||
const leadingComments = sourceCode.getComments(node).leading;
|
||||
const lastLeadingComment = leadingComments[leadingComments.length - 1];
|
||||
const tokenBefore = sourceCode.getTokenBefore(node);
|
||||
|
||||
if (leadingComments.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the last leading comment ends in the same line as the previous token and
|
||||
// does not share a line with the `return` node, we can consider it safe to fix.
|
||||
// Example:
|
||||
// function a() {
|
||||
// var b; //comment
|
||||
// return;
|
||||
// }
|
||||
if (lastLeadingComment.loc.end.line === tokenBefore.loc.end.line &&
|
||||
lastLeadingComment.loc.end.line !== node.loc.start.line) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
@ -141,7 +187,16 @@ module.exports = {
|
|||
if (!isFirstNode(node) && !hasNewlineBefore(node)) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Expected newline before return statement."
|
||||
message: "Expected newline before return statement.",
|
||||
fix(fixer) {
|
||||
if (canFix(node)) {
|
||||
const tokenBefore = sourceCode.getTokenBefore(node);
|
||||
const newlines = node.loc.start.line === tokenBefore.loc.end.line ? "\n\n" : "\n";
|
||||
|
||||
return fixer.insertTextBefore(node, newlines);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,11 +69,14 @@ module.exports = {
|
|||
}
|
||||
|
||||
if (depth > ignoreChainWithDepth && callee.property.loc.start.line === callee.object.loc.end.line) {
|
||||
context.report(
|
||||
callee.property,
|
||||
callee.property.loc.start,
|
||||
"Expected line break before `" + getPropertyText(callee) + "`."
|
||||
);
|
||||
context.report({
|
||||
node: callee.property,
|
||||
loc: callee.property.loc.start,
|
||||
message: "Expected line break before `{{callee}}`.",
|
||||
data: {
|
||||
callee: getPropertyText(callee)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("../ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -36,30 +42,89 @@ module.exports = {
|
|||
},
|
||||
|
||||
create(context) {
|
||||
const options = context.options[0] || {};
|
||||
const allowed = options.allow || [];
|
||||
|
||||
/**
|
||||
* Checks whether the given reference is 'console' or not.
|
||||
*
|
||||
* @param {escope.Reference} reference - The reference to check.
|
||||
* @returns {boolean} `true` if the reference is 'console'.
|
||||
*/
|
||||
function isConsole(reference) {
|
||||
const id = reference.identifier;
|
||||
|
||||
return id && id.name === "console";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the property name of the given MemberExpression node
|
||||
* is allowed by options or not.
|
||||
*
|
||||
* @param {ASTNode} node - The MemberExpression node to check.
|
||||
* @returns {boolean} `true` if the property name of the node is allowed.
|
||||
*/
|
||||
function isAllowed(node) {
|
||||
const propertyName = astUtils.getStaticPropertyName(node);
|
||||
|
||||
return propertyName && allowed.indexOf(propertyName) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given reference is a member access which is not
|
||||
* allowed by options or not.
|
||||
*
|
||||
* @param {escope.Reference} reference - The reference to check.
|
||||
* @returns {boolean} `true` if the reference is a member access which
|
||||
* is not allowed by options.
|
||||
*/
|
||||
function isMemberAccessExceptAllowed(reference) {
|
||||
const node = reference.identifier;
|
||||
const parent = node.parent;
|
||||
|
||||
return (
|
||||
parent.type === "MemberExpression" &&
|
||||
parent.object === node &&
|
||||
!isAllowed(parent)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports the given reference as a violation.
|
||||
*
|
||||
* @param {escope.Reference} reference - The reference to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(reference) {
|
||||
const node = reference.identifier.parent;
|
||||
|
||||
context.report({
|
||||
node,
|
||||
loc: node.loc,
|
||||
message: "Unexpected console statement."
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
"Program:exit"() {
|
||||
const scope = context.getScope();
|
||||
const consoleVar = astUtils.getVariableByName(scope, "console");
|
||||
const shadowed = consoleVar && consoleVar.defs.length > 0;
|
||||
|
||||
MemberExpression(node) {
|
||||
/* 'scope.through' includes all references to undefined
|
||||
* variables. If the variable 'console' is not defined, it uses
|
||||
* 'scope.through'.
|
||||
*/
|
||||
const references = consoleVar
|
||||
? consoleVar.references
|
||||
: scope.through.filter(isConsole);
|
||||
|
||||
if (node.object.name === "console") {
|
||||
let blockConsole = true;
|
||||
|
||||
if (context.options.length > 0) {
|
||||
const allowedProperties = context.options[0].allow;
|
||||
const passedProperty = node.property.name;
|
||||
const propertyIsAllowed = (allowedProperties.indexOf(passedProperty) > -1);
|
||||
|
||||
if (propertyIsAllowed) {
|
||||
blockConsole = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockConsole) {
|
||||
context.report(node, "Unexpected console statement.");
|
||||
}
|
||||
if (!shadowed) {
|
||||
references
|
||||
.filter(isMemberAccessExceptAllowed)
|
||||
.forEach(report);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -88,13 +88,15 @@ module.exports = {
|
|||
.map(function(x) {
|
||||
const match = x.match(stringControlCharWithoutSlash) || [x];
|
||||
|
||||
return "\\" + match[0];
|
||||
return `\\${match[0]}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return controlChars.map(function(x) {
|
||||
return "\\x" + ("0" + x.charCodeAt(0).toString(16)).slice(-2);
|
||||
const hexCode = `0${x.charCodeAt(0).toString(16)}`.slice(-2);
|
||||
|
||||
return `\\x${hexCode}`;
|
||||
}).concat(stringControlChars);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ module.exports = {
|
|||
*/
|
||||
function getState(name, isStatic) {
|
||||
const stateMap = stack[stack.length - 1];
|
||||
const key = "$" + name; // to avoid "__proto__".
|
||||
const key = `$${name}`; // to avoid "__proto__".
|
||||
|
||||
if (!stateMap[key]) {
|
||||
stateMap[key] = {
|
||||
|
|
|
@ -37,8 +37,11 @@ function checkAndReport(context, node, value, array, message) {
|
|||
if (array.indexOf(value) !== -1) {
|
||||
context.report({
|
||||
node,
|
||||
message: "'{{module}}' " + message,
|
||||
data: {module: value}
|
||||
message: "'{{module}}' {{message}}",
|
||||
data: {
|
||||
module: value,
|
||||
message
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,7 +146,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: node.body.loc.start,
|
||||
message: "Unexpected empty " + SHOW_KIND[kind] + "."
|
||||
message: "Unexpected empty {{kind}}.",
|
||||
data: {
|
||||
kind: SHOW_KIND[kind]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,13 @@ module.exports = {
|
|||
|
||||
modifiedBuiltins.forEach(function(builtin) {
|
||||
if (lhs.object.object.name === builtin) {
|
||||
context.report(node, builtin + " prototype is read only, properties should not be added.");
|
||||
context.report({
|
||||
node,
|
||||
message: "{{builtin}} prototype is read only, properties should not be added.",
|
||||
data: {
|
||||
builtin
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -98,7 +104,13 @@ module.exports = {
|
|||
(modifiedBuiltins.indexOf(object.name) > -1) &&
|
||||
subject.property.name === "prototype") {
|
||||
|
||||
context.report(node, object.name + " prototype is read only, properties should not be added.");
|
||||
context.report({
|
||||
node,
|
||||
message: "{{objectName}} prototype is read only, properties should not be added.",
|
||||
data: {
|
||||
objectName: object.name
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@ module.exports = {
|
|||
recommended: false
|
||||
},
|
||||
|
||||
schema: []
|
||||
schema: [],
|
||||
|
||||
fixable: "code"
|
||||
},
|
||||
|
||||
create(context) {
|
||||
|
@ -27,10 +29,18 @@ module.exports = {
|
|||
|
||||
if (typeof node.value === "number") {
|
||||
if (node.raw.indexOf(".") === 0) {
|
||||
context.report(node, "A leading decimal point can be confused with a dot.");
|
||||
context.report({
|
||||
node,
|
||||
message: "A leading decimal point can be confused with a dot.",
|
||||
fix: fixer => fixer.insertTextBefore(node, "0")
|
||||
});
|
||||
}
|
||||
if (node.raw.indexOf(".") === node.raw.length - 1) {
|
||||
context.report(node, "A trailing decimal point can be confused with a dot.");
|
||||
context.report({
|
||||
node,
|
||||
message: "A trailing decimal point can be confused with a dot.",
|
||||
fix: fixer => fixer.insertTextAfter(node, "0")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const astUtils = require("../ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -105,6 +107,26 @@ function getNonNumericOperand(node) {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a node is a string literal or not.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {boolean} Whether or not the passed in node is a
|
||||
* string literal or not.
|
||||
*/
|
||||
function isStringLiteral(node) {
|
||||
return astUtils.isStringLiteral(node) && node.type !== "TemplateLiteral";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a node is an empty string literal or not.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {boolean} Whether or not the passed in node is an
|
||||
* empty string literal or not.
|
||||
*/
|
||||
function isEmptyString(node) {
|
||||
return isStringLiteral(node) && node.value === "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not a node is a concatenating with an empty string.
|
||||
* @param {ASTNode} node - A BinaryExpression node to check.
|
||||
|
@ -112,8 +134,8 @@ function getNonNumericOperand(node) {
|
|||
*/
|
||||
function isConcatWithEmptyString(node) {
|
||||
return node.operator === "+" && (
|
||||
(node.left.type === "Literal" && node.left.value === "") ||
|
||||
(node.right.type === "Literal" && node.right.value === "")
|
||||
(isEmptyString(node.left) && !isStringLiteral(node.right)) ||
|
||||
(isEmptyString(node.right) && !isStringLiteral(node.left))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -123,20 +145,16 @@ function isConcatWithEmptyString(node) {
|
|||
* @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 === "";
|
||||
return node.operator === "+=" && isEmptyString(node.right);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Returns the operand that is not an empty string from a flagged BinaryExpression.
|
||||
* @param {ASTNode} node - The flagged BinaryExpression node to check.
|
||||
* @returns {ASTNode} The operand that is not an empty string from a flagged BinaryExpression.
|
||||
*/
|
||||
function getOtherOperand(node, value) {
|
||||
if (node.left.type === "Literal" && node.left.value === value) {
|
||||
return node.right;
|
||||
}
|
||||
return node.left;
|
||||
function getNonEmptyOperand(node) {
|
||||
return isEmptyString(node.left) ? node.right : node.left;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -151,6 +169,7 @@ module.exports = {
|
|||
recommended: false
|
||||
},
|
||||
|
||||
fixable: "code",
|
||||
schema: [{
|
||||
type: "object",
|
||||
properties: {
|
||||
|
@ -179,6 +198,25 @@ module.exports = {
|
|||
const options = parseOptions(context.options[0]);
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
/**
|
||||
* Reports an error and autofixes the node
|
||||
* @param {ASTNode} node - An ast node to report the error on.
|
||||
* @param {string} recommendation - The recommended code for the issue
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(node, recommendation) {
|
||||
context.report({
|
||||
node,
|
||||
message: "use `{{recommendation}}` instead.",
|
||||
data: {
|
||||
recommendation
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(node, recommendation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
UnaryExpression(node) {
|
||||
let operatorAllowed;
|
||||
|
@ -186,31 +224,25 @@ module.exports = {
|
|||
// !!foo
|
||||
operatorAllowed = options.allow.indexOf("!!") >= 0;
|
||||
if (!operatorAllowed && options.boolean && isDoubleLogicalNegating(node)) {
|
||||
context.report(
|
||||
node,
|
||||
"use `Boolean({{code}})` instead.", {
|
||||
code: sourceCode.getText(node.argument.argument)
|
||||
});
|
||||
const recommendation = `Boolean(${sourceCode.getText(node.argument.argument)})`;
|
||||
|
||||
report(node, recommendation);
|
||||
}
|
||||
|
||||
// ~foo.indexOf(bar)
|
||||
operatorAllowed = options.allow.indexOf("~") >= 0;
|
||||
if (!operatorAllowed && options.boolean && isBinaryNegatingOfIndexOf(node)) {
|
||||
context.report(
|
||||
node,
|
||||
"use `{{code}} !== -1` instead.", {
|
||||
code: sourceCode.getText(node.argument)
|
||||
});
|
||||
const recommendation = `${sourceCode.getText(node.argument)} !== -1`;
|
||||
|
||||
report(node, recommendation);
|
||||
}
|
||||
|
||||
// +foo
|
||||
operatorAllowed = options.allow.indexOf("+") >= 0;
|
||||
if (!operatorAllowed && options.number && node.operator === "+" && !isNumeric(node.argument)) {
|
||||
context.report(
|
||||
node,
|
||||
"use `Number({{code}})` instead.", {
|
||||
code: sourceCode.getText(node.argument)
|
||||
});
|
||||
const recommendation = `Number(${sourceCode.getText(node.argument)})`;
|
||||
|
||||
report(node, recommendation);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -223,21 +255,17 @@ module.exports = {
|
|||
const nonNumericOperand = !operatorAllowed && options.number && isMultiplyByOne(node) && getNonNumericOperand(node);
|
||||
|
||||
if (nonNumericOperand) {
|
||||
context.report(
|
||||
node,
|
||||
"use `Number({{code}})` instead.", {
|
||||
code: sourceCode.getText(nonNumericOperand)
|
||||
});
|
||||
const recommendation = `Number(${sourceCode.getText(nonNumericOperand)})`;
|
||||
|
||||
report(node, recommendation);
|
||||
}
|
||||
|
||||
// "" + foo
|
||||
operatorAllowed = options.allow.indexOf("+") >= 0;
|
||||
if (!operatorAllowed && options.string && isConcatWithEmptyString(node)) {
|
||||
context.report(
|
||||
node,
|
||||
"use `String({{code}})` instead.", {
|
||||
code: sourceCode.getText(getOtherOperand(node, ""))
|
||||
});
|
||||
const recommendation = `String(${sourceCode.getText(getNonEmptyOperand(node))})`;
|
||||
|
||||
report(node, recommendation);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -247,11 +275,10 @@ module.exports = {
|
|||
const operatorAllowed = options.allow.indexOf("+") >= 0;
|
||||
|
||||
if (!operatorAllowed && options.string && isAppendEmptyString(node)) {
|
||||
context.report(
|
||||
node,
|
||||
"use `{{code}} = String({{code}})` instead.", {
|
||||
code: sourceCode.getText(getOtherOperand(node, ""))
|
||||
});
|
||||
const code = sourceCode.getText(getNonEmptyOperand(node));
|
||||
const recommendation = `${code} = String(${code})`;
|
||||
|
||||
report(node, recommendation);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -66,21 +66,30 @@ module.exports = {
|
|||
let flags = isString(node.arguments[1]) ? node.arguments[1].value : "";
|
||||
|
||||
if (allowedFlags) {
|
||||
flags = flags.replace(new RegExp("[" + allowedFlags + "]", "gi"), "");
|
||||
flags = flags.replace(new RegExp(`[${allowedFlags}]`, "gi"), "");
|
||||
}
|
||||
|
||||
try {
|
||||
void new RegExp(node.arguments[0].value);
|
||||
} catch (e) {
|
||||
context.report(node, e.message + ".");
|
||||
context.report({
|
||||
node,
|
||||
message: `${e.message}.`
|
||||
});
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
|
||||
try {
|
||||
espree.parse("/./" + flags, context.parserOptions);
|
||||
espree.parse(`/./${flags}`, context.parserOptions);
|
||||
} catch (ex) {
|
||||
context.report(node, "Invalid flags supplied to RegExp constructor '" + flags + "'.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Invalid flags supplied to RegExp constructor '{{flags}}'.",
|
||||
data: {
|
||||
flags
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ module.exports = {
|
|||
node = parent;
|
||||
parent = node.parent;
|
||||
value = -value;
|
||||
raw = "-" + raw;
|
||||
raw = `-${raw}`;
|
||||
}
|
||||
|
||||
if (shouldIgnoreNumber(value) ||
|
||||
|
@ -131,11 +131,16 @@ module.exports = {
|
|||
message: "Number constants declarations must use 'const'."
|
||||
});
|
||||
}
|
||||
} else if (okTypes.indexOf(parent.type) === -1 ||
|
||||
(parent.type === "AssignmentExpression" && parent.operator !== "=")) {
|
||||
} else if (
|
||||
okTypes.indexOf(parent.type) === -1 ||
|
||||
(parent.type === "AssignmentExpression" && parent.left.type === "Identifier")
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
message: "No magic number: " + raw + "."
|
||||
message: "No magic number: {{raw}}.",
|
||||
data: {
|
||||
raw
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,18 +173,23 @@ module.exports = {
|
|||
const left = (parent.left === node) ? node : parent;
|
||||
const right = (parent.left !== node) ? node : parent;
|
||||
const message =
|
||||
"Unexpected mix of '" + left.operator + "' and '" +
|
||||
right.operator + "'.";
|
||||
"Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'.";
|
||||
const data = {
|
||||
leftOperator: left.operator,
|
||||
rightOperator: right.operator
|
||||
};
|
||||
|
||||
context.report({
|
||||
node: left,
|
||||
loc: getOperatorToken(left).loc.start,
|
||||
message
|
||||
message,
|
||||
data
|
||||
});
|
||||
context.report({
|
||||
node: right,
|
||||
loc: getOperatorToken(right).loc.start,
|
||||
message
|
||||
message,
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: node.loc.start,
|
||||
message: "Too many blank lines at the beginning of file. Max of " + maxBOF + " allowed.",
|
||||
message: "Too many blank lines at the beginning of file. Max of {{maxBOF}} allowed.",
|
||||
data: {
|
||||
maxBOF
|
||||
},
|
||||
fix
|
||||
});
|
||||
}
|
||||
|
@ -162,7 +165,7 @@ module.exports = {
|
|||
} else {
|
||||
const location = {
|
||||
line: lastLocation + 1,
|
||||
column: 1
|
||||
column: 0
|
||||
};
|
||||
|
||||
if (lastLocation < firstOfEndingBlankLines) {
|
||||
|
@ -176,7 +179,11 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: location,
|
||||
message: "More than " + max + " blank " + (max === 1 ? "line" : "lines") + " not allowed.",
|
||||
message: "More than {{max}} blank {{lines}} not allowed.",
|
||||
data: {
|
||||
max,
|
||||
lines: (max === 1 ? "line" : "lines")
|
||||
},
|
||||
fix
|
||||
});
|
||||
}
|
||||
|
@ -190,7 +197,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: location,
|
||||
message: "Too many blank lines at the end of file. Max of " + maxEOF + " allowed.",
|
||||
message: "Too many blank lines at the end of file. Max of {{maxEOF}} allowed.",
|
||||
data: {
|
||||
maxEOF
|
||||
},
|
||||
fix
|
||||
});
|
||||
}
|
||||
|
|
|
@ -46,7 +46,13 @@ module.exports = {
|
|||
if (allowInForAfterthought && node.parent.type === "ForStatement") {
|
||||
return;
|
||||
}
|
||||
context.report(node, "Unary operator '" + node.operator + "' used.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Unary operator '{{operator}}' used.",
|
||||
data: {
|
||||
operator: node.operator
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -35,7 +35,18 @@ module.exports = {
|
|||
regexResults = multipleSpacesRegex.exec(value);
|
||||
|
||||
if (regexResults !== null) {
|
||||
context.report(node, "Spaces are hard to count. Use {" + regexResults[0].length + "}.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Spaces are hard to count. Use {{{count}}}.",
|
||||
data: {
|
||||
count: regexResults[0].length
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* TODO: (platinumazure) Fix message to use rule message
|
||||
* substitution when api.report is fixed in lib/eslint.js.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* @fileoverview Rule to disallow certain object properties
|
||||
* @author Will Klein & Eli White
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const astUtils = require("../ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: "disallow certain properties on certain objects",
|
||||
category: "Node.js and CommonJS",
|
||||
recommended: false
|
||||
},
|
||||
|
||||
schema: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
object: {
|
||||
type: "string"
|
||||
},
|
||||
property: {
|
||||
type: "string"
|
||||
},
|
||||
message: {
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
additionalProperties: false,
|
||||
required: [
|
||||
"object",
|
||||
"property"
|
||||
]
|
||||
},
|
||||
uniqueItems: true
|
||||
}
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const restrictedCalls = context.options;
|
||||
|
||||
if (restrictedCalls.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const restrictedProperties = restrictedCalls.reduce(function(restrictions, option) {
|
||||
const objectName = option.object;
|
||||
const propertyName = option.property;
|
||||
|
||||
if (!restrictions.has(objectName)) {
|
||||
restrictions.set(objectName, new Map());
|
||||
}
|
||||
|
||||
restrictions.get(objectName).set(propertyName, {
|
||||
message: option.message
|
||||
});
|
||||
|
||||
return restrictions;
|
||||
}, new Map());
|
||||
|
||||
return {
|
||||
MemberExpression(node) {
|
||||
const objectName = node.object && node.object.name;
|
||||
const propertyName = astUtils.getStaticPropertyName(node);
|
||||
const matchedObject = restrictedProperties.get(objectName);
|
||||
const matchedObjectProperty = matchedObject && matchedObject.get(propertyName);
|
||||
|
||||
if (matchedObjectProperty) {
|
||||
const message = matchedObjectProperty.message ? " " + matchedObjectProperty.message : "";
|
||||
|
||||
context.report(node, "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}", {
|
||||
objectName,
|
||||
propertyName,
|
||||
message
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
|
@ -31,7 +31,13 @@ module.exports = {
|
|||
*/
|
||||
function checkForViolation(id) {
|
||||
if (RESTRICTED.indexOf(id.name) > -1) {
|
||||
context.report(id, "Shadowing of global property '" + id.name + "'.");
|
||||
context.report({
|
||||
node: id,
|
||||
message: "Shadowing of global property '{{idName}}'.",
|
||||
data: {
|
||||
idName: id.name
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,13 @@ module.exports = {
|
|||
syncRegex = /.*Sync$/;
|
||||
|
||||
if (syncRegex.exec(propertyName) !== null) {
|
||||
context.report(node, "Unexpected sync method: '" + propertyName + "'.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected sync method: '{{propertyName}}'.",
|
||||
data: {
|
||||
propertyName
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -35,8 +35,8 @@ module.exports = {
|
|||
const sourceCode = context.getSourceCode();
|
||||
|
||||
const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]",
|
||||
SKIP_BLANK = "^" + BLANK_CLASS + "*$",
|
||||
NONBLANK = BLANK_CLASS + "+$";
|
||||
SKIP_BLANK = `^${BLANK_CLASS}*$`,
|
||||
NONBLANK = `${BLANK_CLASS}+$`;
|
||||
|
||||
const options = context.options[0] || {},
|
||||
skipBlankLines = options.skipBlankLines || false;
|
||||
|
|
|
@ -107,7 +107,13 @@ module.exports = {
|
|||
const identifier = node.id.name;
|
||||
|
||||
if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) {
|
||||
context.report(node, "Unexpected dangling '_' in '" + identifier + "'.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected dangling '_' in '{{identifier}}'.",
|
||||
data: {
|
||||
identifier
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +129,13 @@ module.exports = {
|
|||
|
||||
if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) &&
|
||||
!isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) {
|
||||
context.report(node, "Unexpected dangling '_' in '" + identifier + "'.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected dangling '_' in '{{identifier}}'.",
|
||||
data: {
|
||||
identifier
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +154,13 @@ module.exports = {
|
|||
!(isMemberOfThis && allowAfterThis) &&
|
||||
!(isMemberOfSuper && allowAfterSuper) &&
|
||||
!isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) {
|
||||
context.report(node, "Unexpected dangling '_' in '" + identifier + "'.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected dangling '_' in '{{identifier}}'.",
|
||||
data: {
|
||||
identifier
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,10 @@ module.exports = {
|
|||
function check(node) {
|
||||
if (isInFinallyBlock(node, node.label)) {
|
||||
context.report({
|
||||
message: "Unsafe usage of " + node.type + ".",
|
||||
message: "Unsafe usage of {{nodeType}}.",
|
||||
data: {
|
||||
nodeType: node.type
|
||||
},
|
||||
node,
|
||||
line: node.loc.line,
|
||||
column: node.loc.column
|
||||
|
|
|
@ -514,7 +514,7 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function getColumnInComment(variable, comment) {
|
||||
const namePattern = new RegExp("[\\s,]" + lodash.escapeRegExp(variable.name) + "(?:$|[\\s,:])", "g");
|
||||
const namePattern = new RegExp(`[\\s,]${lodash.escapeRegExp(variable.name)}(?:$|[\\s,:])`, "g");
|
||||
|
||||
// To ignore the first text "global".
|
||||
namePattern.lastIndex = comment.value.indexOf("global") + 6;
|
||||
|
|
|
@ -90,7 +90,10 @@ module.exports = {
|
|||
line: node.loc.start.line,
|
||||
column: node.loc.start.column + elm.index
|
||||
},
|
||||
message: "Unnecessary escape character: " + elm[0] + "."
|
||||
message: "Unnecessary escape character: {{character}}.",
|
||||
data: {
|
||||
character: elm[0]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,13 @@ module.exports = {
|
|||
const matches = commentContainsWarningTerm(node.value);
|
||||
|
||||
matches.forEach(function(matchedTerm) {
|
||||
context.report(node, "Unexpected '" + matchedTerm + "' comment.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected '{{matchedTerm}}' comment.",
|
||||
data: {
|
||||
matchedTerm
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "There should be no space after '" + token.value + "'.",
|
||||
message: "There should be no space after '{{token}}'.",
|
||||
data: {
|
||||
token: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
const nextToken = context.getSourceCode().getTokenAfter(token);
|
||||
|
||||
|
@ -93,7 +96,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "There should be no space before '" + token.value + "'.",
|
||||
message: "There should be no space before '{{token}}'.",
|
||||
data: {
|
||||
token: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
const previousToken = context.getSourceCode().getTokenBefore(token);
|
||||
|
||||
|
@ -112,7 +118,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "A space is required after '" + token.value + "'.",
|
||||
message: "A space is required after '{{token}}'.",
|
||||
data: {
|
||||
token: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextAfter(token, " ");
|
||||
}
|
||||
|
@ -129,7 +138,10 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
loc: token.loc.start,
|
||||
message: "A space is required before '" + token.value + "'.",
|
||||
message: "A space is required before '{{token}}'.",
|
||||
data: {
|
||||
token: token.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextBefore(token, " ");
|
||||
}
|
||||
|
|
|
@ -237,17 +237,20 @@ module.exports = {
|
|||
|
||||
context.report({
|
||||
node,
|
||||
message: "Expected longform " + type + " syntax.",
|
||||
message: "Expected longform {{type}} syntax.",
|
||||
data: {
|
||||
type
|
||||
},
|
||||
fix(fixer) {
|
||||
if (node.method) {
|
||||
if (node.value.generator) {
|
||||
return fixer.replaceTextRange([node.range[0], node.key.range[1]], node.key.name + ": function*");
|
||||
return fixer.replaceTextRange([node.range[0], node.key.range[1]], `${node.key.name}: function*`);
|
||||
}
|
||||
|
||||
return fixer.insertTextAfter(node.key, ": function");
|
||||
}
|
||||
|
||||
return fixer.insertTextAfter(node.key, ": " + node.key.name);
|
||||
return fixer.insertTextAfter(node.key, `: ${node.key.name}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -289,7 +292,7 @@ module.exports = {
|
|||
if (node.value.generator) {
|
||||
return fixer.replaceTextRange(
|
||||
[node.key.range[0], node.value.range[0] + "function*".length],
|
||||
"*[" + node.key.name + "]"
|
||||
`*[${node.key.name}]`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -307,7 +310,7 @@ module.exports = {
|
|||
if (node.value.generator) {
|
||||
return fixer.replaceTextRange(
|
||||
[node.key.range[0], node.value.range[0] + "function*".length],
|
||||
"*" + node.key.name
|
||||
`*${node.key.name}`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -279,16 +279,34 @@ module.exports = {
|
|||
// 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.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Combine this with the previous '{{type}}' statement.",
|
||||
data: {
|
||||
type
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (options[type].initialized === MODE_ALWAYS) {
|
||||
context.report(node, "Combine this with the previous '" + type + "' statement with initialized variables.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Combine this with the previous '{{type}}' statement with initialized variables.",
|
||||
data: {
|
||||
type
|
||||
}
|
||||
});
|
||||
}
|
||||
if (options[type].uninitialized === MODE_ALWAYS) {
|
||||
if (node.parent.left === node && (node.parent.type === "ForInStatement" || node.parent.type === "ForOfStatement")) {
|
||||
return;
|
||||
}
|
||||
context.report(node, "Combine this with the previous '" + type + "' statement with uninitialized variables.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
|
||||
data: {
|
||||
type
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -302,15 +320,33 @@ module.exports = {
|
|||
if (options[type].initialized === MODE_NEVER && options[type].uninitialized === MODE_NEVER) {
|
||||
|
||||
// both initialized and uninitialized
|
||||
context.report(node, "Split '" + type + "' declarations into multiple statements.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Split '{{type}}' declarations into multiple statements.",
|
||||
data: {
|
||||
type
|
||||
}
|
||||
});
|
||||
} else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) {
|
||||
|
||||
// initialized
|
||||
context.report(node, "Split initialized '" + type + "' declarations into multiple statements.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Split initialized '{{type}}' declarations into multiple statements.",
|
||||
data: {
|
||||
type
|
||||
}
|
||||
});
|
||||
} else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) {
|
||||
|
||||
// uninitialized
|
||||
context.report(node, "Split uninitialized '" + type + "' declarations into multiple statements.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Split uninitialized '{{type}}' declarations into multiple statements.",
|
||||
data: {
|
||||
type
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,31 +98,59 @@ module.exports = {
|
|||
!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 + "'.");
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
line: operatorToken.loc.end.line,
|
||||
column: operatorToken.loc.end.column
|
||||
},
|
||||
message: "Bad line breaking before and after '{{operator}}'.",
|
||||
data: {
|
||||
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.");
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
line: operatorToken.loc.end.line,
|
||||
column: operatorToken.loc.end.column
|
||||
},
|
||||
message: "'{{operator}}' should be placed at the beginning of the line.",
|
||||
data: {
|
||||
operator
|
||||
}
|
||||
});
|
||||
|
||||
} 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.");
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
line: operatorToken.loc.end.line,
|
||||
column: operatorToken.loc.end.column
|
||||
},
|
||||
message: "'{{operator}}' should be placed at the end of the line.",
|
||||
data: {
|
||||
operator
|
||||
}
|
||||
});
|
||||
|
||||
} 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 + "'.");
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
line: operatorToken.loc.end.line,
|
||||
column: operatorToken.loc.end.column
|
||||
},
|
||||
message: "There should be no line break before or after '{{operator}}'.",
|
||||
data: {
|
||||
operator
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,6 +115,17 @@ function getCallbackInfo(node) {
|
|||
throw new Error("unreachable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a simple list of parameters contains any duplicates. This does not handle complex
|
||||
parameter lists (e.g. with destructuring), since complex parameter lists are a SyntaxError with duplicate
|
||||
parameter names anyway. Instead, it always returns `false` for complex parameter lists.
|
||||
* @param {ASTNode[]} paramsList The list of parameters for a function
|
||||
* @returns {boolean} `true` if the list of parameters contains any duplicates
|
||||
*/
|
||||
function hasDuplicateParams(paramsList) {
|
||||
return paramsList.every(param => param.type === "Identifier") && paramsList.length !== new Set(paramsList.map(param => param.name)).size;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -140,7 +151,9 @@ module.exports = {
|
|||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
fixable: "code"
|
||||
},
|
||||
|
||||
create(context) {
|
||||
|
@ -148,6 +161,7 @@ module.exports = {
|
|||
|
||||
const allowUnboundThis = options.allowUnboundThis !== false; // default to true
|
||||
const allowNamedFunctions = options.allowNamedFunctions;
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
/*
|
||||
* {Array<{this: boolean, super: boolean, meta: boolean}>}
|
||||
|
@ -246,7 +260,33 @@ module.exports = {
|
|||
!scopeInfo.super &&
|
||||
!scopeInfo.meta
|
||||
) {
|
||||
context.report(node, "Unexpected function expression.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected function expression.",
|
||||
fix(fixer) {
|
||||
if ((!callbackInfo.isLexicalThis && scopeInfo.this) || hasDuplicateParams(node.params)) {
|
||||
|
||||
// If the callback function does not have .bind(this) and contains a reference to `this`, there
|
||||
// is no way to determine what `this` should be, so don't perform any fixes.
|
||||
// If the callback function has duplicates in its list of parameters (possible in sloppy mode),
|
||||
// don't replace it with an arrow function, because this is a SyntaxError with arrow functions.
|
||||
return null;
|
||||
}
|
||||
|
||||
const paramsLeftParen = node.params.length ? sourceCode.getTokenBefore(node.params[0]) : sourceCode.getTokenBefore(node.body, 1);
|
||||
const paramsRightParen = sourceCode.getTokenBefore(node.body);
|
||||
const paramsFullText = sourceCode.text.slice(paramsLeftParen.range[0], paramsRightParen.range[1]);
|
||||
|
||||
if (callbackInfo.isLexicalThis) {
|
||||
|
||||
// If the callback function has `.bind(this)`, replace it with an arrow function and remove the binding.
|
||||
return fixer.replaceText(node.parent.parent, paramsFullText + " => " + sourceCode.getText(node.body));
|
||||
}
|
||||
|
||||
// Otherwise, only replace the `function` keyword and parameters with the arrow function parameters.
|
||||
return fixer.replaceTextRange([node.start, node.body.start], paramsFullText + " => ");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* @fileoverview Rule to disallow `parseInt()` in favor of binary, octal, and hexadecimal literals
|
||||
* @author Annie Zhang, Henry Zhu
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: "disallow `parseInt()` in favor of binary, octal, and hexadecimal literals",
|
||||
category: "ECMAScript 6",
|
||||
recommended: false
|
||||
},
|
||||
|
||||
schema: []
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const radixMap = {
|
||||
2: "binary",
|
||||
8: "octal",
|
||||
16: "hexadecimal"
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
|
||||
CallExpression(node) {
|
||||
|
||||
// doesn't check parseInt() if it doesn't have a radix argument
|
||||
if (node.arguments.length !== 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only error if the radix is 2, 8, or 16
|
||||
const radixName = radixMap[node.arguments[1].value];
|
||||
|
||||
if (node.callee.type === "Identifier" &&
|
||||
node.callee.name === "parseInt" &&
|
||||
radixName &&
|
||||
node.arguments[0].type === "Literal"
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Use {{radixName}} literals instead of parseInt().",
|
||||
data: {
|
||||
radixName
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
|
@ -97,7 +97,7 @@ module.exports = {
|
|||
function areQuotesRedundant(rawKey, tokens, skipNumberLiterals) {
|
||||
return tokens.length === 1 && tokens[0].start === 0 && tokens[0].end === rawKey.length &&
|
||||
(["Identifier", "Keyword", "Null", "Boolean"].indexOf(tokens[0].type) >= 0 ||
|
||||
(tokens[0].type === "Numeric" && !skipNumberLiterals && "" + +tokens[0].value === tokens[0].value));
|
||||
(tokens[0].type === "Numeric" && !skipNumberLiterals && String(+tokens[0].value) === tokens[0].value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -56,7 +56,7 @@ QUOTE_SETTINGS.backtick.convert = function(str) {
|
|||
return escaped; // unescape
|
||||
}
|
||||
if (match === newQuote || newQuote === "`" && match === "${") {
|
||||
return "\\" + match; // escape
|
||||
return `\\${match}`; // escape
|
||||
}
|
||||
if (newline && oldQuote === "`") {
|
||||
return "\\n"; // escape newlines
|
||||
|
@ -225,7 +225,10 @@ module.exports = {
|
|||
if (!isValid) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Strings must use " + settings.description + ".",
|
||||
message: "Strings must use {{description}}.",
|
||||
data: {
|
||||
description: settings.description
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(node, settings.convert(node.raw));
|
||||
}
|
||||
|
@ -246,7 +249,10 @@ module.exports = {
|
|||
if (shouldWarn) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Strings must use " + settings.description + ".",
|
||||
message: "Strings must use {{description}}.",
|
||||
data: {
|
||||
description: settings.description,
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(node, settings.convert(sourceCode.getText(node)));
|
||||
}
|
||||
|
|
|
@ -100,7 +100,10 @@ module.exports = {
|
|||
if (secondToken.range[0] === firstToken.range[1]) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Unary word operator '" + word + "' must be followed by whitespace.",
|
||||
message: "Unary word operator '{{word}}' must be followed by whitespace.",
|
||||
data: {
|
||||
word
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextAfter(firstToken, " ");
|
||||
}
|
||||
|
@ -121,7 +124,10 @@ module.exports = {
|
|||
if (secondToken.range[0] > firstToken.range[1]) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected space after unary word operator '" + word + "'.",
|
||||
message: "Unexpected space after unary word operator '{{word}}'.",
|
||||
data: {
|
||||
word
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.removeRange([firstToken.range[1], secondToken.range[0]]);
|
||||
}
|
||||
|
@ -185,7 +191,10 @@ module.exports = {
|
|||
if (firstToken.range[1] === secondToken.range[0]) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Unary operator '" + firstToken.value + "' must be followed by whitespace.",
|
||||
message: "Unary operator '{{operator}}' must be followed by whitespace.",
|
||||
data: {
|
||||
operator: firstToken.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextAfter(firstToken, " ");
|
||||
}
|
||||
|
@ -195,7 +204,10 @@ module.exports = {
|
|||
if (firstToken.range[1] === secondToken.range[0]) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Space is required before unary expressions '" + secondToken.value + "'.",
|
||||
message: "Space is required before unary expressions '{{token}}'.",
|
||||
data: {
|
||||
token: secondToken.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.insertTextBefore(secondToken, " ");
|
||||
}
|
||||
|
@ -216,7 +228,10 @@ module.exports = {
|
|||
if (secondToken.range[0] > firstToken.range[1]) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected space after unary operator '" + firstToken.value + "'.",
|
||||
message: "Unexpected space after unary operator '{{operator}}'.",
|
||||
data: {
|
||||
operator: firstToken.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.removeRange([firstToken.range[1], secondToken.range[0]]);
|
||||
}
|
||||
|
@ -226,7 +241,10 @@ module.exports = {
|
|||
if (secondToken.range[0] > firstToken.range[1]) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Unexpected space before unary operator '" + secondToken.value + "'.",
|
||||
message: "Unexpected space before unary operator '{{operator}}'.",
|
||||
data: {
|
||||
operator: secondToken.value
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.removeRange([firstToken.range[1], secondToken.range[0]]);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ function escape(s) {
|
|||
const isOneChar = s.length === 1;
|
||||
|
||||
s = lodash.escapeRegExp(s);
|
||||
return isOneChar ? s : "(?:" + s + ")";
|
||||
return isOneChar ? s : `(?:${s})`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,7 +29,7 @@ function escape(s) {
|
|||
* @returns {string} An escaped string.
|
||||
*/
|
||||
function escapeAndRepeat(s) {
|
||||
return escape(s) + "+";
|
||||
return `${escape(s)}+`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,7 +144,7 @@ function createAlwaysStylePattern(markers, exceptions) {
|
|||
* @returns {RegExp} A RegExp object for `never` mode.
|
||||
*/
|
||||
function createNeverStylePattern(markers) {
|
||||
const pattern = "^(" + markers.map(escape).join("|") + ")?[ \t]+";
|
||||
const pattern = `^(${markers.map(escape).join("|")})?[ \t]+`;
|
||||
|
||||
return new RegExp(pattern);
|
||||
}
|
||||
|
@ -248,9 +248,9 @@ module.exports = {
|
|||
// Create RegExp object for valid patterns.
|
||||
rule[type] = {
|
||||
beginRegex: requireSpace ? createAlwaysStylePattern(markers, exceptions) : createNeverStylePattern(markers),
|
||||
endRegex: balanced && requireSpace ? new RegExp(createExceptionsPattern(exceptions) + "$") : new RegExp(endNeverPattern),
|
||||
endRegex: balanced && requireSpace ? new RegExp(`${createExceptionsPattern(exceptions)}$`) : new RegExp(endNeverPattern),
|
||||
hasExceptions: exceptions.length > 0,
|
||||
markers: new RegExp("^(" + markers.map(escape).join("|") + ")")
|
||||
markers: new RegExp(`^(${markers.map(escape).join("|")})`)
|
||||
};
|
||||
|
||||
return rule;
|
||||
|
@ -261,9 +261,10 @@ module.exports = {
|
|||
* @param {ASTNode} node - A comment node to check.
|
||||
* @param {string} message - An error message to report.
|
||||
* @param {Array} match - An array of match results for markers.
|
||||
* @param {string} refChar - Character used for reference in the error message.
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportBegin(node, message, match) {
|
||||
function reportBegin(node, message, match, refChar) {
|
||||
const type = node.type.toLowerCase(),
|
||||
commentIdentifier = type === "block" ? "/*" : "//";
|
||||
|
||||
|
@ -283,7 +284,8 @@ module.exports = {
|
|||
return fixer.replaceTextRange([start, end], commentIdentifier + (match[1] ? match[1] : ""));
|
||||
}
|
||||
},
|
||||
message
|
||||
message,
|
||||
data: { refChar }
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -336,9 +338,9 @@ module.exports = {
|
|||
const marker = hasMarker ? commentIdentifier + hasMarker[0] : commentIdentifier;
|
||||
|
||||
if (rule.hasExceptions) {
|
||||
reportBegin(node, "Expected exception block, space or tab after '" + marker + "' in comment.", hasMarker);
|
||||
reportBegin(node, "Expected exception block, space or tab after '{{refChar}}' in comment.", hasMarker, marker);
|
||||
} else {
|
||||
reportBegin(node, "Expected space or tab after '" + marker + "' in comment.", hasMarker);
|
||||
reportBegin(node, "Expected space or tab after '{{refChar}}' in comment.", hasMarker, marker);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,9 +350,9 @@ module.exports = {
|
|||
} else {
|
||||
if (beginMatch) {
|
||||
if (!beginMatch[1]) {
|
||||
reportBegin(node, "Unexpected space or tab after '" + commentIdentifier + "' in comment.", beginMatch);
|
||||
reportBegin(node, "Unexpected space or tab after '{{refChar}}' in comment.", beginMatch, commentIdentifier);
|
||||
} else {
|
||||
reportBegin(node, "Unexpected space or tab after marker (" + beginMatch[1] + ") in comment.", beginMatch);
|
||||
reportBegin(node, "Unexpected space or tab after marker ({{refChar}}) in comment.", beginMatch, beginMatch[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,10 @@ module.exports = {
|
|||
) {
|
||||
context.report({
|
||||
loc: token.loc.start,
|
||||
message: prefix + " space(s) before '}'.",
|
||||
message: "{{prefix}} space(s) before '}'.",
|
||||
data: {
|
||||
prefix
|
||||
},
|
||||
fix(fixer) {
|
||||
if (always) {
|
||||
return fixer.insertTextBefore(token, " ");
|
||||
|
@ -89,7 +92,10 @@ module.exports = {
|
|||
line: token.loc.end.line,
|
||||
column: token.loc.end.column - 2
|
||||
},
|
||||
message: prefix + " space(s) after '${'.",
|
||||
message: "{{prefix}} space(s) after '${'.",
|
||||
data: {
|
||||
prefix
|
||||
},
|
||||
fix(fixer) {
|
||||
if (always) {
|
||||
return fixer.insertTextAfter(token, " ");
|
||||
|
|
|
@ -279,7 +279,13 @@ module.exports = {
|
|||
hasReturns = true;
|
||||
|
||||
if (!requireReturn && !functionData.returnPresent && (tag.type === null || !isValidReturnType(tag)) && !isAbstract) {
|
||||
context.report(jsdocNode, "Unexpected @" + tag.title + " tag; function has no return statement.");
|
||||
context.report({
|
||||
node: jsdocNode,
|
||||
message: "Unexpected @{{title}} tag; function has no return statement.",
|
||||
data: {
|
||||
title: tag.title
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (requireReturnType && !tag.type) {
|
||||
context.report(jsdocNode, "Missing JSDoc return type.");
|
||||
|
@ -330,7 +336,13 @@ module.exports = {
|
|||
node.parent.kind !== "get" && node.parent.kind !== "constructor" &&
|
||||
node.parent.kind !== "set" && !isTypeClass(node)) {
|
||||
if (requireReturn || functionData.returnPresent) {
|
||||
context.report(jsdocNode, "Missing JSDoc @" + (prefer.returns || "returns") + " for function.");
|
||||
context.report({
|
||||
node: jsdocNode,
|
||||
message: "Missing JSDoc @{{returns}} for function.",
|
||||
data: {
|
||||
returns: prefer.returns || "returns"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@ module.exports = {
|
|||
recommended: false
|
||||
},
|
||||
|
||||
schema: []
|
||||
schema: [],
|
||||
|
||||
fixable: "code"
|
||||
},
|
||||
|
||||
create(context) {
|
||||
|
@ -36,7 +38,11 @@ module.exports = {
|
|||
|
||||
if (grandparent.type === "MemberExpression" && grandparent.object === node &&
|
||||
(!source || source.value !== "(")) {
|
||||
context.report(node, "Wrap the regexp literal in parens to disambiguate the slash.");
|
||||
context.report({
|
||||
node,
|
||||
message: "Wrap the regexp literal in parens to disambiguate the slash.",
|
||||
fix: fixer => fixer.replaceText(node, `(${sourceCode.getText(node)})`)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,11 +68,15 @@ module.exports = {
|
|||
const spaceRequired = mode[side];
|
||||
const node = after ? leftToken : rightToken;
|
||||
const type = spaceRequired ? "Missing" : "Unexpected";
|
||||
const message = type + " space " + side + " *.";
|
||||
const message = "{{type}} space {{side}} *.";
|
||||
|
||||
context.report({
|
||||
node,
|
||||
message,
|
||||
data: {
|
||||
type,
|
||||
side
|
||||
},
|
||||
fix(fixer) {
|
||||
if (spaceRequired) {
|
||||
if (after) {
|
||||
|
|
|
@ -69,7 +69,7 @@ function getNormalizedLiteral(node) {
|
|||
return {
|
||||
type: "Literal",
|
||||
value: -node.argument.value,
|
||||
raw: "-" + node.argument.value
|
||||
raw: `-${node.argument.value}`
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,13 @@ module.exports = {
|
|||
isComparisonOperator(node.operator) &&
|
||||
!(exceptRange && isRangeTest(context.getAncestors().pop()))
|
||||
) {
|
||||
context.report(node, "Expected literal to be on the left side of " + node.operator + ".");
|
||||
context.report({
|
||||
node,
|
||||
message: "Expected literal to be on the left side of {{operator}}.",
|
||||
data: {
|
||||
operator: node.operator
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} : function(node) {
|
||||
|
@ -247,7 +253,13 @@ module.exports = {
|
|||
isComparisonOperator(node.operator) &&
|
||||
!(exceptRange && isRangeTest(context.getAncestors().pop()))
|
||||
) {
|
||||
context.report(node, "Expected literal to be on the right side of " + node.operator + ".");
|
||||
context.report({
|
||||
node,
|
||||
message: "Expected literal to be on the right side of {{operator}}.",
|
||||
data: {
|
||||
operator: node.operator
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -104,28 +104,22 @@ function resolveFileGlobPatterns(patterns, options) {
|
|||
* @returns {string[]} Resolved absolute filenames.
|
||||
*/
|
||||
function listFilesToProcess(globPatterns, options) {
|
||||
options = options || { ignore: true };
|
||||
const files = [],
|
||||
added = {};
|
||||
|
||||
const cwd = (options && options.cwd) || process.cwd();
|
||||
|
||||
options = options || { ignore: true, dotfiles: true };
|
||||
const ignoredPaths = new IgnoredPaths(options);
|
||||
const globOptions = {
|
||||
nodir: true,
|
||||
cwd
|
||||
};
|
||||
const shouldIgnore = ignoredPaths.getIgnoredFoldersGlobChecker();
|
||||
|
||||
/**
|
||||
* Executes the linter on a file defined by the `filename`. Skips
|
||||
* unsupported file extensions and any files that are already linted.
|
||||
* @param {string} filename The file to be processed
|
||||
* @param {boolean} shouldWarnIgnored Whether or not a report should be made if
|
||||
* the file is ignored
|
||||
* @param {IgnoredPaths} ignoredPaths An instance of IgnoredPaths
|
||||
* @returns {void}
|
||||
*/
|
||||
function addFile(filename, shouldWarnIgnored) {
|
||||
function addFile(filename, shouldWarnIgnored, ignoredPaths) {
|
||||
let ignored = false;
|
||||
let isSilentlyIgnored;
|
||||
|
||||
|
@ -160,10 +154,24 @@ function listFilesToProcess(globPatterns, options) {
|
|||
const file = path.resolve(cwd, pattern);
|
||||
|
||||
if (shell.test("-f", file)) {
|
||||
addFile(fs.realpathSync(file), !shell.test("-d", file));
|
||||
const ignoredPaths = new IgnoredPaths(options);
|
||||
|
||||
addFile(fs.realpathSync(file), !shell.test("-d", file), ignoredPaths);
|
||||
} else {
|
||||
|
||||
// regex to find .hidden or /.hidden patterns, but not ./relative or ../relative
|
||||
const globIncludesDotfiles = /(?:(?:^\.)|(?:[\/\\]\.))[^\/\\\.].*/.test(pattern);
|
||||
|
||||
const ignoredPaths = new IgnoredPaths(Object.assign({}, options, {dotfiles: options.dotfiles || globIncludesDotfiles}));
|
||||
const shouldIgnore = ignoredPaths.getIgnoredFoldersGlobChecker();
|
||||
const globOptions = {
|
||||
nodir: true,
|
||||
dot: true,
|
||||
cwd,
|
||||
};
|
||||
|
||||
new GlobSync(pattern, globOptions, shouldIgnore).found.forEach(function(globMatch) {
|
||||
addFile(path.resolve(cwd, globMatch), false);
|
||||
addFile(path.resolve(cwd, globMatch), false, ignoredPaths);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
ESLint couldn't find the plugin "<%- pluginName %>". because there is whitespace in the name. Please check your configuration and remove all whitespace from the plugin name.
|
||||
|
||||
If you still can't figure out the problem, please stop by https://gitter.im/eslint/eslint to chat with the team.
|
|
@ -23,7 +23,7 @@
|
|||
*
|
||||
*/
|
||||
/**
|
||||
* bluebird build version 3.4.3
|
||||
* bluebird build version 3.4.6
|
||||
* Features enabled: core
|
||||
* Features disabled: race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each
|
||||
*/
|
||||
|
@ -624,14 +624,16 @@ Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) {
|
|||
Promise.onPossiblyUnhandledRejection = function (fn) {
|
||||
var domain = getDomain();
|
||||
possiblyUnhandledRejection =
|
||||
typeof fn === "function" ? (domain === null ? fn : domain.bind(fn))
|
||||
typeof fn === "function" ? (domain === null ?
|
||||
fn : util.domainBind(domain, fn))
|
||||
: undefined;
|
||||
};
|
||||
|
||||
Promise.onUnhandledRejectionHandled = function (fn) {
|
||||
var domain = getDomain();
|
||||
unhandledRejectionHandled =
|
||||
typeof fn === "function" ? (domain === null ? fn : domain.bind(fn))
|
||||
typeof fn === "function" ? (domain === null ?
|
||||
fn : util.domainBind(domain, fn))
|
||||
: undefined;
|
||||
};
|
||||
|
||||
|
@ -671,7 +673,20 @@ var fireDomEvent = (function() {
|
|||
var event = new CustomEvent("CustomEvent");
|
||||
util.global.dispatchEvent(event);
|
||||
return function(name, event) {
|
||||
var domEvent = new CustomEvent(name.toLowerCase(), event);
|
||||
var domEvent = new CustomEvent(name.toLowerCase(), {
|
||||
detail: event,
|
||||
cancelable: true
|
||||
});
|
||||
return !util.global.dispatchEvent(domEvent);
|
||||
};
|
||||
} else if (typeof Event === "function") {
|
||||
var event = new Event("CustomEvent");
|
||||
util.global.dispatchEvent(event);
|
||||
return function(name, event) {
|
||||
var domEvent = new Event(name.toLowerCase(), {
|
||||
cancelable: true
|
||||
});
|
||||
domEvent.detail = event;
|
||||
return !util.global.dispatchEvent(domEvent);
|
||||
};
|
||||
} else {
|
||||
|
@ -1427,7 +1442,7 @@ return {
|
|||
|
||||
},{"./errors":9,"./util":21}],8:[function(_dereq_,module,exports){
|
||||
"use strict";
|
||||
module.exports = function(Promise, tryConvertToPromise) {
|
||||
module.exports = function(Promise) {
|
||||
function returner() {
|
||||
return this.value;
|
||||
}
|
||||
|
@ -1437,7 +1452,6 @@ function thrower() {
|
|||
|
||||
Promise.prototype["return"] =
|
||||
Promise.prototype.thenReturn = function (value) {
|
||||
value = tryConvertToPromise(value);
|
||||
if (value instanceof Promise) value.suppressUnhandledRejections();
|
||||
return this._then(
|
||||
returner, undefined, undefined, {value: value}, undefined);
|
||||
|
@ -1462,13 +1476,11 @@ Promise.prototype.catchThrow = function (reason) {
|
|||
|
||||
Promise.prototype.catchReturn = function (value) {
|
||||
if (arguments.length <= 1) {
|
||||
value = tryConvertToPromise(value);
|
||||
if (value instanceof Promise) value.suppressUnhandledRejections();
|
||||
return this._then(
|
||||
undefined, returner, undefined, {value: value}, undefined);
|
||||
} else {
|
||||
var _value = arguments[1];
|
||||
_value = tryConvertToPromise(_value);
|
||||
if (_value instanceof Promise) _value.suppressUnhandledRejections();
|
||||
var handler = function() {return _value;};
|
||||
return this.caught(value, handler);
|
||||
|
@ -1792,7 +1804,8 @@ return PassThroughHandlerContext;
|
|||
},{"./util":21}],12:[function(_dereq_,module,exports){
|
||||
"use strict";
|
||||
module.exports =
|
||||
function(Promise, PromiseArray, tryConvertToPromise, INTERNAL) {
|
||||
function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async,
|
||||
getDomain) {
|
||||
var util = _dereq_("./util");
|
||||
var canEvaluate = util.canEvaluate;
|
||||
var tryCatch = util.tryCatch;
|
||||
|
@ -1834,25 +1847,35 @@ if (canEvaluate) {
|
|||
var name = "Holder$" + total;
|
||||
|
||||
|
||||
var code = "return function(tryCatch, errorObj, Promise) { \n\
|
||||
var code = "return function(tryCatch, errorObj, Promise, async) { \n\
|
||||
'use strict'; \n\
|
||||
function [TheName](fn) { \n\
|
||||
[TheProperties] \n\
|
||||
this.fn = fn; \n\
|
||||
this.asyncNeeded = true; \n\
|
||||
this.now = 0; \n\
|
||||
} \n\
|
||||
\n\
|
||||
[TheName].prototype._callFunction = function(promise) { \n\
|
||||
promise._pushContext(); \n\
|
||||
var ret = tryCatch(this.fn)([ThePassedArguments]); \n\
|
||||
promise._popContext(); \n\
|
||||
if (ret === errorObj) { \n\
|
||||
promise._rejectCallback(ret.e, false); \n\
|
||||
} else { \n\
|
||||
promise._resolveCallback(ret); \n\
|
||||
} \n\
|
||||
}; \n\
|
||||
\n\
|
||||
[TheName].prototype.checkFulfillment = function(promise) { \n\
|
||||
var now = ++this.now; \n\
|
||||
if (now === [TheTotal]) { \n\
|
||||
promise._pushContext(); \n\
|
||||
var callback = this.fn; \n\
|
||||
var ret = tryCatch(callback)([ThePassedArguments]); \n\
|
||||
promise._popContext(); \n\
|
||||
if (ret === errorObj) { \n\
|
||||
promise._rejectCallback(ret.e, false); \n\
|
||||
if (this.asyncNeeded) { \n\
|
||||
async.invoke(this._callFunction, this, promise); \n\
|
||||
} else { \n\
|
||||
promise._resolveCallback(ret); \n\
|
||||
this._callFunction(promise); \n\
|
||||
} \n\
|
||||
\n\
|
||||
} \n\
|
||||
}; \n\
|
||||
\n\
|
||||
|
@ -1861,7 +1884,7 @@ if (canEvaluate) {
|
|||
}; \n\
|
||||
\n\
|
||||
return [TheName]; \n\
|
||||
}(tryCatch, errorObj, Promise); \n\
|
||||
}(tryCatch, errorObj, Promise, async); \n\
|
||||
";
|
||||
|
||||
code = code.replace(/\[TheName\]/g, name)
|
||||
|
@ -1870,8 +1893,8 @@ if (canEvaluate) {
|
|||
.replace(/\[TheProperties\]/g, assignment)
|
||||
.replace(/\[CancellationCode\]/g, cancellationCode);
|
||||
|
||||
return new Function("tryCatch", "errorObj", "Promise", code)
|
||||
(tryCatch, errorObj, Promise);
|
||||
return new Function("tryCatch", "errorObj", "Promise", "async", code)
|
||||
(tryCatch, errorObj, Promise, async);
|
||||
};
|
||||
|
||||
var holderClasses = [];
|
||||
|
@ -1912,6 +1935,7 @@ Promise.join = function () {
|
|||
maybePromise._then(callbacks[i], reject,
|
||||
undefined, ret, holder);
|
||||
promiseSetters[i](maybePromise, holder);
|
||||
holder.asyncNeeded = false;
|
||||
} else if (((bitField & 33554432) !== 0)) {
|
||||
callbacks[i].call(ret,
|
||||
maybePromise._value(), holder);
|
||||
|
@ -1924,7 +1948,14 @@ Promise.join = function () {
|
|||
callbacks[i].call(ret, maybePromise, holder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret._isFateSealed()) {
|
||||
if (holder.asyncNeeded) {
|
||||
var domain = getDomain();
|
||||
if (domain !== null) {
|
||||
holder.fn = util.domainBind(domain, holder.fn);
|
||||
}
|
||||
}
|
||||
ret._setAsyncGuaranteed();
|
||||
ret._setOnCancel(holder);
|
||||
}
|
||||
|
@ -2312,7 +2343,8 @@ Promise.prototype._then = function (
|
|||
|
||||
async.invoke(settler, target, {
|
||||
handler: domain === null ? handler
|
||||
: (typeof handler === "function" && domain.bind(handler)),
|
||||
: (typeof handler === "function" &&
|
||||
util.domainBind(domain, handler)),
|
||||
promise: promise,
|
||||
receiver: receiver,
|
||||
value: value
|
||||
|
@ -2448,11 +2480,11 @@ Promise.prototype._addCallbacks = function (
|
|||
this._receiver0 = receiver;
|
||||
if (typeof fulfill === "function") {
|
||||
this._fulfillmentHandler0 =
|
||||
domain === null ? fulfill : domain.bind(fulfill);
|
||||
domain === null ? fulfill : util.domainBind(domain, fulfill);
|
||||
}
|
||||
if (typeof reject === "function") {
|
||||
this._rejectionHandler0 =
|
||||
domain === null ? reject : domain.bind(reject);
|
||||
domain === null ? reject : util.domainBind(domain, reject);
|
||||
}
|
||||
} else {
|
||||
var base = index * 4 - 4;
|
||||
|
@ -2460,11 +2492,11 @@ Promise.prototype._addCallbacks = function (
|
|||
this[base + 3] = receiver;
|
||||
if (typeof fulfill === "function") {
|
||||
this[base + 0] =
|
||||
domain === null ? fulfill : domain.bind(fulfill);
|
||||
domain === null ? fulfill : util.domainBind(domain, fulfill);
|
||||
}
|
||||
if (typeof reject === "function") {
|
||||
this[base + 1] =
|
||||
domain === null ? reject : domain.bind(reject);
|
||||
domain === null ? reject : util.domainBind(domain, reject);
|
||||
}
|
||||
}
|
||||
this._setLength(index + 1);
|
||||
|
@ -2778,12 +2810,12 @@ _dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection,
|
|||
debug);
|
||||
_dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug);
|
||||
_dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug);
|
||||
_dereq_("./direct_resolve")(Promise, tryConvertToPromise);
|
||||
_dereq_("./direct_resolve")(Promise);
|
||||
_dereq_("./synchronous_inspection")(Promise);
|
||||
_dereq_("./join")(
|
||||
Promise, PromiseArray, tryConvertToPromise, INTERNAL, debug);
|
||||
Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain);
|
||||
Promise.Promise = Promise;
|
||||
Promise.version = "3.4.3";
|
||||
Promise.version = "3.4.6";
|
||||
|
||||
util.toFastProperties(Promise);
|
||||
util.toFastProperties(Promise.prototype);
|
||||
|
@ -3110,7 +3142,7 @@ if (util.isNode && typeof MutationObserver === "undefined") {
|
|||
} else if ((typeof MutationObserver !== "undefined") &&
|
||||
!(typeof window !== "undefined" &&
|
||||
window.navigator &&
|
||||
window.navigator.standalone)) {
|
||||
(window.navigator.standalone || window.cordova))) {
|
||||
schedule = (function() {
|
||||
var div = document.createElement("div");
|
||||
var opts = {attributes: true};
|
||||
|
@ -3671,6 +3703,10 @@ function getNativePromise() {
|
|||
}
|
||||
}
|
||||
|
||||
function domainBind(self, cb) {
|
||||
return self.bind(cb);
|
||||
}
|
||||
|
||||
var ret = {
|
||||
isClass: isClass,
|
||||
isIdentifier: isIdentifier,
|
||||
|
@ -3703,7 +3739,8 @@ var ret = {
|
|||
isNode: isNode,
|
||||
env: env,
|
||||
global: globalObject,
|
||||
getNativePromise: getNativePromise
|
||||
getNativePromise: getNativePromise,
|
||||
domainBind: domainBind
|
||||
};
|
||||
ret.isRecentNode = ret.isNode && (function() {
|
||||
var version = process.versions.node.split(".").map(Number);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -23,7 +23,7 @@
|
|||
*
|
||||
*/
|
||||
/**
|
||||
* bluebird build version 3.4.3
|
||||
* bluebird build version 3.4.6
|
||||
* Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each
|
||||
*/
|
||||
!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.Promise=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 _dereq_=="function"&&_dereq_;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 _dereq_=="function"&&_dereq_;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
|
||||
|
@ -771,14 +771,16 @@ Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) {
|
|||
Promise.onPossiblyUnhandledRejection = function (fn) {
|
||||
var domain = getDomain();
|
||||
possiblyUnhandledRejection =
|
||||
typeof fn === "function" ? (domain === null ? fn : domain.bind(fn))
|
||||
typeof fn === "function" ? (domain === null ?
|
||||
fn : util.domainBind(domain, fn))
|
||||
: undefined;
|
||||
};
|
||||
|
||||
Promise.onUnhandledRejectionHandled = function (fn) {
|
||||
var domain = getDomain();
|
||||
unhandledRejectionHandled =
|
||||
typeof fn === "function" ? (domain === null ? fn : domain.bind(fn))
|
||||
typeof fn === "function" ? (domain === null ?
|
||||
fn : util.domainBind(domain, fn))
|
||||
: undefined;
|
||||
};
|
||||
|
||||
|
@ -818,7 +820,20 @@ var fireDomEvent = (function() {
|
|||
var event = new CustomEvent("CustomEvent");
|
||||
util.global.dispatchEvent(event);
|
||||
return function(name, event) {
|
||||
var domEvent = new CustomEvent(name.toLowerCase(), event);
|
||||
var domEvent = new CustomEvent(name.toLowerCase(), {
|
||||
detail: event,
|
||||
cancelable: true
|
||||
});
|
||||
return !util.global.dispatchEvent(domEvent);
|
||||
};
|
||||
} else if (typeof Event === "function") {
|
||||
var event = new Event("CustomEvent");
|
||||
util.global.dispatchEvent(event);
|
||||
return function(name, event) {
|
||||
var domEvent = new Event(name.toLowerCase(), {
|
||||
cancelable: true
|
||||
});
|
||||
domEvent.detail = event;
|
||||
return !util.global.dispatchEvent(domEvent);
|
||||
};
|
||||
} else {
|
||||
|
@ -1574,7 +1589,7 @@ return {
|
|||
|
||||
},{"./errors":12,"./util":36}],10:[function(_dereq_,module,exports){
|
||||
"use strict";
|
||||
module.exports = function(Promise, tryConvertToPromise) {
|
||||
module.exports = function(Promise) {
|
||||
function returner() {
|
||||
return this.value;
|
||||
}
|
||||
|
@ -1584,7 +1599,6 @@ function thrower() {
|
|||
|
||||
Promise.prototype["return"] =
|
||||
Promise.prototype.thenReturn = function (value) {
|
||||
value = tryConvertToPromise(value);
|
||||
if (value instanceof Promise) value.suppressUnhandledRejections();
|
||||
return this._then(
|
||||
returner, undefined, undefined, {value: value}, undefined);
|
||||
|
@ -1609,13 +1623,11 @@ Promise.prototype.catchThrow = function (reason) {
|
|||
|
||||
Promise.prototype.catchReturn = function (value) {
|
||||
if (arguments.length <= 1) {
|
||||
value = tryConvertToPromise(value);
|
||||
if (value instanceof Promise) value.suppressUnhandledRejections();
|
||||
return this._then(
|
||||
undefined, returner, undefined, {value: value}, undefined);
|
||||
} else {
|
||||
var _value = arguments[1];
|
||||
_value = tryConvertToPromise(_value);
|
||||
if (_value instanceof Promise) _value.suppressUnhandledRejections();
|
||||
var handler = function() {return _value;};
|
||||
return this.caught(value, handler);
|
||||
|
@ -1638,8 +1650,8 @@ function PromiseMapSeries(promises, fn) {
|
|||
}
|
||||
|
||||
Promise.prototype.each = function (fn) {
|
||||
return this.mapSeries(fn)
|
||||
._then(promiseAllThis, undefined, undefined, this, undefined);
|
||||
return PromiseReduce(this, fn, INTERNAL, 0)
|
||||
._then(promiseAllThis, undefined, undefined, this, undefined);
|
||||
};
|
||||
|
||||
Promise.prototype.mapSeries = function (fn) {
|
||||
|
@ -1647,13 +1659,14 @@ Promise.prototype.mapSeries = function (fn) {
|
|||
};
|
||||
|
||||
Promise.each = function (promises, fn) {
|
||||
return PromiseMapSeries(promises, fn)
|
||||
._then(promiseAllThis, undefined, undefined, promises, undefined);
|
||||
return PromiseReduce(promises, fn, INTERNAL, 0)
|
||||
._then(promiseAllThis, undefined, undefined, promises, undefined);
|
||||
};
|
||||
|
||||
Promise.mapSeries = PromiseMapSeries;
|
||||
};
|
||||
|
||||
|
||||
},{}],12:[function(_dereq_,module,exports){
|
||||
"use strict";
|
||||
var es5 = _dereq_("./es5");
|
||||
|
@ -2209,7 +2222,8 @@ Promise.spawn = function (generatorFunction) {
|
|||
},{"./errors":12,"./util":36}],17:[function(_dereq_,module,exports){
|
||||
"use strict";
|
||||
module.exports =
|
||||
function(Promise, PromiseArray, tryConvertToPromise, INTERNAL) {
|
||||
function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async,
|
||||
getDomain) {
|
||||
var util = _dereq_("./util");
|
||||
var canEvaluate = util.canEvaluate;
|
||||
var tryCatch = util.tryCatch;
|
||||
|
@ -2251,25 +2265,35 @@ if (canEvaluate) {
|
|||
var name = "Holder$" + total;
|
||||
|
||||
|
||||
var code = "return function(tryCatch, errorObj, Promise) { \n\
|
||||
var code = "return function(tryCatch, errorObj, Promise, async) { \n\
|
||||
'use strict'; \n\
|
||||
function [TheName](fn) { \n\
|
||||
[TheProperties] \n\
|
||||
this.fn = fn; \n\
|
||||
this.asyncNeeded = true; \n\
|
||||
this.now = 0; \n\
|
||||
} \n\
|
||||
\n\
|
||||
[TheName].prototype._callFunction = function(promise) { \n\
|
||||
promise._pushContext(); \n\
|
||||
var ret = tryCatch(this.fn)([ThePassedArguments]); \n\
|
||||
promise._popContext(); \n\
|
||||
if (ret === errorObj) { \n\
|
||||
promise._rejectCallback(ret.e, false); \n\
|
||||
} else { \n\
|
||||
promise._resolveCallback(ret); \n\
|
||||
} \n\
|
||||
}; \n\
|
||||
\n\
|
||||
[TheName].prototype.checkFulfillment = function(promise) { \n\
|
||||
var now = ++this.now; \n\
|
||||
if (now === [TheTotal]) { \n\
|
||||
promise._pushContext(); \n\
|
||||
var callback = this.fn; \n\
|
||||
var ret = tryCatch(callback)([ThePassedArguments]); \n\
|
||||
promise._popContext(); \n\
|
||||
if (ret === errorObj) { \n\
|
||||
promise._rejectCallback(ret.e, false); \n\
|
||||
if (this.asyncNeeded) { \n\
|
||||
async.invoke(this._callFunction, this, promise); \n\
|
||||
} else { \n\
|
||||
promise._resolveCallback(ret); \n\
|
||||
this._callFunction(promise); \n\
|
||||
} \n\
|
||||
\n\
|
||||
} \n\
|
||||
}; \n\
|
||||
\n\
|
||||
|
@ -2278,7 +2302,7 @@ if (canEvaluate) {
|
|||
}; \n\
|
||||
\n\
|
||||
return [TheName]; \n\
|
||||
}(tryCatch, errorObj, Promise); \n\
|
||||
}(tryCatch, errorObj, Promise, async); \n\
|
||||
";
|
||||
|
||||
code = code.replace(/\[TheName\]/g, name)
|
||||
|
@ -2287,8 +2311,8 @@ if (canEvaluate) {
|
|||
.replace(/\[TheProperties\]/g, assignment)
|
||||
.replace(/\[CancellationCode\]/g, cancellationCode);
|
||||
|
||||
return new Function("tryCatch", "errorObj", "Promise", code)
|
||||
(tryCatch, errorObj, Promise);
|
||||
return new Function("tryCatch", "errorObj", "Promise", "async", code)
|
||||
(tryCatch, errorObj, Promise, async);
|
||||
};
|
||||
|
||||
var holderClasses = [];
|
||||
|
@ -2329,6 +2353,7 @@ Promise.join = function () {
|
|||
maybePromise._then(callbacks[i], reject,
|
||||
undefined, ret, holder);
|
||||
promiseSetters[i](maybePromise, holder);
|
||||
holder.asyncNeeded = false;
|
||||
} else if (((bitField & 33554432) !== 0)) {
|
||||
callbacks[i].call(ret,
|
||||
maybePromise._value(), holder);
|
||||
|
@ -2341,7 +2366,14 @@ Promise.join = function () {
|
|||
callbacks[i].call(ret, maybePromise, holder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret._isFateSealed()) {
|
||||
if (holder.asyncNeeded) {
|
||||
var domain = getDomain();
|
||||
if (domain !== null) {
|
||||
holder.fn = util.domainBind(domain, holder.fn);
|
||||
}
|
||||
}
|
||||
ret._setAsyncGuaranteed();
|
||||
ret._setOnCancel(holder);
|
||||
}
|
||||
|
@ -2369,23 +2401,27 @@ var getDomain = Promise._getDomain;
|
|||
var util = _dereq_("./util");
|
||||
var tryCatch = util.tryCatch;
|
||||
var errorObj = util.errorObj;
|
||||
var EMPTY_ARRAY = [];
|
||||
var async = Promise._async;
|
||||
|
||||
function MappingPromiseArray(promises, fn, limit, _filter) {
|
||||
this.constructor$(promises);
|
||||
this._promise._captureStackTrace();
|
||||
var domain = getDomain();
|
||||
this._callback = domain === null ? fn : domain.bind(fn);
|
||||
this._callback = domain === null ? fn : util.domainBind(domain, fn);
|
||||
this._preservedValues = _filter === INTERNAL
|
||||
? new Array(this.length())
|
||||
: null;
|
||||
this._limit = limit;
|
||||
this._inFlight = 0;
|
||||
this._queue = limit >= 1 ? [] : EMPTY_ARRAY;
|
||||
this._init$(undefined, -2);
|
||||
this._queue = [];
|
||||
async.invoke(this._asyncInit, this, undefined);
|
||||
}
|
||||
util.inherits(MappingPromiseArray, PromiseArray);
|
||||
|
||||
MappingPromiseArray.prototype._asyncInit = function() {
|
||||
this._init$(undefined, -2);
|
||||
};
|
||||
|
||||
MappingPromiseArray.prototype._init = function () {};
|
||||
|
||||
MappingPromiseArray.prototype._promiseFulfilled = function (value, index) {
|
||||
|
@ -2955,7 +2991,8 @@ Promise.prototype._then = function (
|
|||
|
||||
async.invoke(settler, target, {
|
||||
handler: domain === null ? handler
|
||||
: (typeof handler === "function" && domain.bind(handler)),
|
||||
: (typeof handler === "function" &&
|
||||
util.domainBind(domain, handler)),
|
||||
promise: promise,
|
||||
receiver: receiver,
|
||||
value: value
|
||||
|
@ -3091,11 +3128,11 @@ Promise.prototype._addCallbacks = function (
|
|||
this._receiver0 = receiver;
|
||||
if (typeof fulfill === "function") {
|
||||
this._fulfillmentHandler0 =
|
||||
domain === null ? fulfill : domain.bind(fulfill);
|
||||
domain === null ? fulfill : util.domainBind(domain, fulfill);
|
||||
}
|
||||
if (typeof reject === "function") {
|
||||
this._rejectionHandler0 =
|
||||
domain === null ? reject : domain.bind(reject);
|
||||
domain === null ? reject : util.domainBind(domain, reject);
|
||||
}
|
||||
} else {
|
||||
var base = index * 4 - 4;
|
||||
|
@ -3103,11 +3140,11 @@ Promise.prototype._addCallbacks = function (
|
|||
this[base + 3] = receiver;
|
||||
if (typeof fulfill === "function") {
|
||||
this[base + 0] =
|
||||
domain === null ? fulfill : domain.bind(fulfill);
|
||||
domain === null ? fulfill : util.domainBind(domain, fulfill);
|
||||
}
|
||||
if (typeof reject === "function") {
|
||||
this[base + 1] =
|
||||
domain === null ? reject : domain.bind(reject);
|
||||
domain === null ? reject : util.domainBind(domain, reject);
|
||||
}
|
||||
}
|
||||
this._setLength(index + 1);
|
||||
|
@ -3421,12 +3458,12 @@ _dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection,
|
|||
debug);
|
||||
_dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug);
|
||||
_dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug);
|
||||
_dereq_("./direct_resolve")(Promise, tryConvertToPromise);
|
||||
_dereq_("./direct_resolve")(Promise);
|
||||
_dereq_("./synchronous_inspection")(Promise);
|
||||
_dereq_("./join")(
|
||||
Promise, PromiseArray, tryConvertToPromise, INTERNAL, debug);
|
||||
Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain);
|
||||
Promise.Promise = Promise;
|
||||
Promise.version = "3.4.3";
|
||||
Promise.version = "3.4.6";
|
||||
_dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
|
||||
_dereq_('./call_get.js')(Promise);
|
||||
_dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug);
|
||||
|
@ -4247,27 +4284,37 @@ var tryCatch = util.tryCatch;
|
|||
function ReductionPromiseArray(promises, fn, initialValue, _each) {
|
||||
this.constructor$(promises);
|
||||
var domain = getDomain();
|
||||
this._fn = domain === null ? fn : domain.bind(fn);
|
||||
this._fn = domain === null ? fn : util.domainBind(domain, fn);
|
||||
if (initialValue !== undefined) {
|
||||
initialValue = Promise.resolve(initialValue);
|
||||
initialValue._attachCancellationCallback(this);
|
||||
}
|
||||
this._initialValue = initialValue;
|
||||
this._currentCancellable = null;
|
||||
this._eachValues = _each === INTERNAL ? [] : undefined;
|
||||
if(_each === INTERNAL) {
|
||||
this._eachValues = Array(this._length);
|
||||
} else if (_each === 0) {
|
||||
this._eachValues = null;
|
||||
} else {
|
||||
this._eachValues = undefined;
|
||||
}
|
||||
this._promise._captureStackTrace();
|
||||
this._init$(undefined, -5);
|
||||
}
|
||||
util.inherits(ReductionPromiseArray, PromiseArray);
|
||||
|
||||
ReductionPromiseArray.prototype._gotAccum = function(accum) {
|
||||
if (this._eachValues !== undefined && accum !== INTERNAL) {
|
||||
if (this._eachValues !== undefined &&
|
||||
this._eachValues !== null &&
|
||||
accum !== INTERNAL) {
|
||||
this._eachValues.push(accum);
|
||||
}
|
||||
};
|
||||
|
||||
ReductionPromiseArray.prototype._eachComplete = function(value) {
|
||||
this._eachValues.push(value);
|
||||
if (this._eachValues !== null) {
|
||||
this._eachValues.push(value);
|
||||
}
|
||||
return this._eachValues;
|
||||
};
|
||||
|
||||
|
@ -4419,7 +4466,7 @@ if (util.isNode && typeof MutationObserver === "undefined") {
|
|||
} else if ((typeof MutationObserver !== "undefined") &&
|
||||
!(typeof window !== "undefined" &&
|
||||
window.navigator &&
|
||||
window.navigator.standalone)) {
|
||||
(window.navigator.standalone || window.cordova))) {
|
||||
schedule = (function() {
|
||||
var div = document.createElement("div");
|
||||
var opts = {attributes: true};
|
||||
|
@ -5498,6 +5545,10 @@ function getNativePromise() {
|
|||
}
|
||||
}
|
||||
|
||||
function domainBind(self, cb) {
|
||||
return self.bind(cb);
|
||||
}
|
||||
|
||||
var ret = {
|
||||
isClass: isClass,
|
||||
isIdentifier: isIdentifier,
|
||||
|
@ -5530,7 +5581,8 @@ var ret = {
|
|||
isNode: isNode,
|
||||
env: env,
|
||||
global: globalObject,
|
||||
getNativePromise: getNativePromise
|
||||
getNativePromise: getNativePromise,
|
||||
domainBind: domainBind
|
||||
};
|
||||
ret.isRecentNode = ret.isNode && (function() {
|
||||
var version = process.versions.node.split(".").map(Number);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -14,20 +14,20 @@
|
|||
]
|
||||
],
|
||||
"_from": "bluebird@>=3.1.1 <4.0.0",
|
||||
"_id": "bluebird@3.4.3",
|
||||
"_id": "bluebird@3.4.6",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/bluebird",
|
||||
"_nodeVersion": "6.4.0",
|
||||
"_nodeVersion": "5.6.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-16-east.internal.npmjs.com",
|
||||
"tmp": "tmp/bluebird-3.4.3.tgz_1472108494164_0.43675709678791463"
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/bluebird-3.4.6.tgz_1472763137386_0.698919479502365"
|
||||
},
|
||||
"_npmUser": {
|
||||
"name": "esailija",
|
||||
"email": "petka_antonov@hotmail.com"
|
||||
},
|
||||
"_npmVersion": "3.10.3",
|
||||
"_npmVersion": "3.6.0",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "bluebird@^3.1.1",
|
||||
|
@ -41,8 +41,8 @@
|
|||
"_requiredBy": [
|
||||
"/table"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.3.tgz",
|
||||
"_shasum": "1bdf56bb9336f4206f0f4efb7bedd5b5e9392058",
|
||||
"_resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz",
|
||||
"_shasum": "01da8d821d87813d158967e743d5fe6c62cf8c0f",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "bluebird@^3.1.1",
|
||||
"_where": "/Users/trott/io.js/tools/node_modules/table",
|
||||
|
@ -85,15 +85,15 @@
|
|||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "1bdf56bb9336f4206f0f4efb7bedd5b5e9392058",
|
||||
"tarball": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.3.tgz"
|
||||
"shasum": "01da8d821d87813d158967e743d5fe6c62cf8c0f",
|
||||
"tarball": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz"
|
||||
},
|
||||
"files": [
|
||||
"js/browser",
|
||||
"js/release",
|
||||
"LICENSE"
|
||||
],
|
||||
"gitHead": "64326d7ec06dd2839d9704b13969320e3dfb63e0",
|
||||
"gitHead": "b466418e1d8cafd93c807f84b4dceee715c70b35",
|
||||
"homepage": "https://github.com/petkaantonov/bluebird",
|
||||
"keywords": [
|
||||
"promise",
|
||||
|
@ -133,5 +133,5 @@
|
|||
"prepublish": "npm run generate-browser-core && npm run generate-browser-full",
|
||||
"test": "node tools/test.js"
|
||||
},
|
||||
"version": "3.4.3"
|
||||
"version": "3.4.6"
|
||||
}
|
||||
|
|
|
@ -73,6 +73,10 @@ function isArrayish (arr) {
|
|||
return /Array\]$/.test(Object.prototype.toString.call(arr))
|
||||
}
|
||||
|
||||
function isBufferish (p) {
|
||||
return typeof p === 'string' || isArrayish(p) || (p && typeof p.subarray === 'function')
|
||||
}
|
||||
|
||||
function stringConcat (parts) {
|
||||
var strings = []
|
||||
var needsToString = false
|
||||
|
@ -82,8 +86,10 @@ function stringConcat (parts) {
|
|||
strings.push(p)
|
||||
} else if (Buffer.isBuffer(p)) {
|
||||
strings.push(p)
|
||||
} else if (isBufferish(p)) {
|
||||
strings.push(new Buffer(p))
|
||||
} else {
|
||||
strings.push(Buffer(p))
|
||||
strings.push(new Buffer(String(p)))
|
||||
}
|
||||
}
|
||||
if (Buffer.isBuffer(parts[0])) {
|
||||
|
@ -101,10 +107,11 @@ function bufferConcat (parts) {
|
|||
var p = parts[i]
|
||||
if (Buffer.isBuffer(p)) {
|
||||
bufs.push(p)
|
||||
} else if (typeof p === 'string' || isArrayish(p)
|
||||
|| (p && typeof p.subarray === 'function')) {
|
||||
bufs.push(Buffer(p))
|
||||
} else bufs.push(Buffer(String(p)))
|
||||
} else if (isBufferish(p)) {
|
||||
bufs.push(new Buffer(p))
|
||||
} else {
|
||||
bufs.push(new Buffer(String(p)))
|
||||
}
|
||||
}
|
||||
return Buffer.concat(bufs)
|
||||
}
|
||||
|
@ -121,7 +128,7 @@ function u8Concat (parts) {
|
|||
var len = 0
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (typeof parts[i] === 'string') {
|
||||
parts[i] = Buffer(parts[i])
|
||||
parts[i] = new Buffer(parts[i])
|
||||
}
|
||||
len += parts[i].length
|
||||
}
|
||||
|
|
|
@ -14,16 +14,20 @@
|
|||
]
|
||||
],
|
||||
"_from": "concat-stream@>=1.4.6 <2.0.0",
|
||||
"_id": "concat-stream@1.5.1",
|
||||
"_id": "concat-stream@1.5.2",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/concat-stream",
|
||||
"_nodeVersion": "4.0.0",
|
||||
"_npmUser": {
|
||||
"name": "maxogden",
|
||||
"email": "max@maxogden.com"
|
||||
"_nodeVersion": "4.4.3",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/concat-stream-1.5.2.tgz_1472715196934_0.010375389130786061"
|
||||
},
|
||||
"_npmVersion": "2.14.2",
|
||||
"_npmUser": {
|
||||
"name": "mafintosh",
|
||||
"email": "mathiasbuus@gmail.com"
|
||||
},
|
||||
"_npmVersion": "2.15.9",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "concat-stream@^1.4.6",
|
||||
|
@ -37,8 +41,8 @@
|
|||
"_requiredBy": [
|
||||
"/eslint"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz",
|
||||
"_shasum": "f3b80acf9e1f48e3875c0688b41b6c31602eea1c",
|
||||
"_resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz",
|
||||
"_shasum": "708978624d856af41a5a741defdd261da752c266",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "concat-stream@^1.4.6",
|
||||
"_where": "/Users/trott/io.js/tools/node_modules/eslint",
|
||||
|
@ -60,8 +64,8 @@
|
|||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "f3b80acf9e1f48e3875c0688b41b6c31602eea1c",
|
||||
"tarball": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz"
|
||||
"shasum": "708978624d856af41a5a741defdd261da752c266",
|
||||
"tarball": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz"
|
||||
},
|
||||
"engines": [
|
||||
"node >= 0.8"
|
||||
|
@ -69,11 +73,15 @@
|
|||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "522adc12d82f57c691a5f946fbc8ba08718dcdcb",
|
||||
"gitHead": "731fedd137eae89d066c249fdca070f8f16afbb8",
|
||||
"homepage": "https://github.com/maxogden/concat-stream#readme",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "mafintosh",
|
||||
"email": "mathiasbuus@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "maxogden",
|
||||
"email": "max@maxogden.com"
|
||||
|
@ -111,5 +119,5 @@
|
|||
"android-browser/4.2..latest"
|
||||
]
|
||||
},
|
||||
"version": "1.5.1"
|
||||
"version": "1.5.2"
|
||||
}
|
||||
|
|
|
@ -89,6 +89,8 @@ By default `concat-stream` will give you back the same data type as the type of
|
|||
|
||||
If you don't specify an encoding, and the types can't be inferred (e.g. you write things that aren't in the list above), it will try to convert concat them into a `Buffer`.
|
||||
|
||||
If nothing is written to `writable` then `data` will be an empty array `[]`.
|
||||
|
||||
# error handling
|
||||
|
||||
`concat-stream` does not handle errors for you, so you must handle errors on whatever streams you pipe into `concat-stream`. This is a general rule when programming with node.js streams: always handle errors on each and every stream. Since `concat-stream` is not itself a stream it does not emit errors.
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
},
|
||||
"dist": {
|
||||
"shasum": "b369d6fb5dbc13eecf524f91b070feedc357cf34",
|
||||
"tarball": "http://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz"
|
||||
"tarball": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz"
|
||||
},
|
||||
"gitHead": "f126057628423458636dec9df3d621843b9ac55e",
|
||||
"homepage": "https://github.com/thlorenz/deep-is",
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "0d2bbd8827eb5fb4ba8f97fbfea50d43db21ea81",
|
||||
"tarball": "http://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.1.tgz"
|
||||
"tarball": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.1.tgz"
|
||||
},
|
||||
"gitHead": "b8b62d44e3b9f8134095c8fb6a5697e371b36867",
|
||||
"homepage": "https://github.com/medikoo/es6-weak-map#readme",
|
||||
|
|
|
@ -1 +1,7 @@
|
|||
module.exports = require('util').inherits
|
||||
try {
|
||||
var util = require('util');
|
||||
if (typeof util.inherits !== 'function') throw '';
|
||||
module.exports = util.inherits;
|
||||
} catch (e) {
|
||||
module.exports = require('./inherits_browser.js');
|
||||
}
|
||||
|
|
|
@ -14,15 +14,20 @@
|
|||
]
|
||||
],
|
||||
"_from": "inherits@>=2.0.1 <2.1.0",
|
||||
"_id": "inherits@2.0.1",
|
||||
"_id": "inherits@2.0.3",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/inherits",
|
||||
"_nodeVersion": "6.5.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-16-east.internal.npmjs.com",
|
||||
"tmp": "tmp/inherits-2.0.3.tgz_1473295776489_0.08142363070510328"
|
||||
},
|
||||
"_npmUser": {
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
},
|
||||
"_npmVersion": "1.3.8",
|
||||
"_npmVersion": "3.10.7",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "inherits@~2.0.1",
|
||||
|
@ -38,8 +43,8 @@
|
|||
"/glob",
|
||||
"/readable-stream"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
|
||||
"_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
|
||||
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"_shasum": "633c2c83e3da42a502f52466022480f4208261de",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "inherits@~2.0.1",
|
||||
"_where": "/Users/trott/io.js/tools/node_modules/concat-stream",
|
||||
|
@ -49,12 +54,19 @@
|
|||
},
|
||||
"dependencies": {},
|
||||
"description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
|
||||
"devDependencies": {},
|
||||
"devDependencies": {
|
||||
"tap": "^7.1.0"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
|
||||
"tarball": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
"shasum": "633c2c83e3da42a502f52466022480f4208261de",
|
||||
"tarball": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
|
||||
},
|
||||
"files": [
|
||||
"inherits.js",
|
||||
"inherits_browser.js"
|
||||
],
|
||||
"gitHead": "e05d0fb27c61a3ec687214f0476386b765364d5f",
|
||||
"homepage": "https://github.com/isaacs/inherits#readme",
|
||||
"keywords": [
|
||||
"inheritance",
|
||||
|
@ -84,5 +96,5 @@
|
|||
"scripts": {
|
||||
"test": "node test"
|
||||
},
|
||||
"version": "2.0.1"
|
||||
"version": "2.0.3"
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "d225ec23132e89edd38fda767472e62e65f1106d",
|
||||
"tarball": "http://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz"
|
||||
"tarball": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "6477582b8214d602346094567003be8a9eac04dc",
|
||||
"tarball": "http://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz"
|
||||
"tarball": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
},
|
||||
"dist": {
|
||||
"shasum": "57fe1c4e48474edd65b09911f26b1cd4095dda84",
|
||||
"tarball": "http://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
|
||||
"tarball": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
|
||||
},
|
||||
"gitHead": "0a85ea5b6b1264ea1cdecc6e5cf186adbb3ffc50",
|
||||
"homepage": "https://github.com/mikolalysenko/is-property",
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "c020f529c5282adfdd233d91d4b181c3d686dc4b",
|
||||
"tarball": "http://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
|
||||
"tarball": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
|
|
@ -49,3 +49,31 @@ function load (cb) {
|
|||
})
|
||||
}
|
||||
```
|
||||
|
||||
## `once.strict(func)`
|
||||
|
||||
Throw an error if the function is called twice.
|
||||
|
||||
Some functions are expected to be called only once. Using `once` for them would
|
||||
potentially hide logical errors.
|
||||
|
||||
In the example below, the `greet` function has to call the callback only once:
|
||||
|
||||
```javascript
|
||||
function greet (name, cb) {
|
||||
// return is missing from the if statement
|
||||
// when no name is passed, the callback is called twice
|
||||
if (!name) cb('Hello anonymous')
|
||||
cb('Hello ' + name)
|
||||
}
|
||||
|
||||
function log (msg) {
|
||||
console.log(msg)
|
||||
}
|
||||
|
||||
// this will print 'Hello anonymous' but the logical error will be missed
|
||||
greet(null, once(msg))
|
||||
|
||||
// once.strict will print 'Hello anonymous' and throw an error when the callback will be called the second time
|
||||
greet(null, once.strict(msg))
|
||||
```
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
var wrappy = require('wrappy')
|
||||
module.exports = wrappy(once)
|
||||
module.exports.strict = wrappy(onceStrict)
|
||||
|
||||
once.proto = once(function () {
|
||||
Object.defineProperty(Function.prototype, 'once', {
|
||||
|
@ -8,6 +9,13 @@ once.proto = once(function () {
|
|||
},
|
||||
configurable: true
|
||||
})
|
||||
|
||||
Object.defineProperty(Function.prototype, 'onceStrict', {
|
||||
value: function () {
|
||||
return onceStrict(this)
|
||||
},
|
||||
configurable: true
|
||||
})
|
||||
})
|
||||
|
||||
function once (fn) {
|
||||
|
@ -19,3 +27,16 @@ function once (fn) {
|
|||
f.called = false
|
||||
return f
|
||||
}
|
||||
|
||||
function onceStrict (fn) {
|
||||
var f = function () {
|
||||
if (f.called)
|
||||
throw new Error(f.onceError)
|
||||
f.called = true
|
||||
return f.value = fn.apply(this, arguments)
|
||||
}
|
||||
var name = fn.name || 'Function wrapped with `once`'
|
||||
f.onceError = name + " shouldn't be called more than once"
|
||||
f.called = false
|
||||
return f
|
||||
}
|
||||
|
|
|
@ -14,16 +14,20 @@
|
|||
]
|
||||
],
|
||||
"_from": "once@>=1.3.0 <2.0.0",
|
||||
"_id": "once@1.3.3",
|
||||
"_id": "once@1.4.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/once",
|
||||
"_nodeVersion": "4.0.0",
|
||||
"_nodeVersion": "6.5.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/once-1.4.0.tgz_1473196269128_0.537820661207661"
|
||||
},
|
||||
"_npmUser": {
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
},
|
||||
"_npmVersion": "3.3.2",
|
||||
"_npmVersion": "3.10.7",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "once@^1.3.0",
|
||||
|
@ -39,8 +43,8 @@
|
|||
"/inflight",
|
||||
"/run-async"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
|
||||
"_shasum": "b2e261557ce4c314ec8304f3fa82663e4297ca20",
|
||||
"_resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"_shasum": "583b1aa775961d4b113ac17d9c50baef9dd76bd1",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "once@^1.3.0",
|
||||
"_where": "/Users/trott/io.js/tools/node_modules/glob",
|
||||
|
@ -57,19 +61,19 @@
|
|||
},
|
||||
"description": "Run a function exactly one time",
|
||||
"devDependencies": {
|
||||
"tap": "^1.2.0"
|
||||
"tap": "^7.0.1"
|
||||
},
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"dist": {
|
||||
"shasum": "b2e261557ce4c314ec8304f3fa82663e4297ca20",
|
||||
"tarball": "https://registry.npmjs.org/once/-/once-1.3.3.tgz"
|
||||
"shasum": "583b1aa775961d4b113ac17d9c50baef9dd76bd1",
|
||||
"tarball": "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
|
||||
},
|
||||
"files": [
|
||||
"once.js"
|
||||
],
|
||||
"gitHead": "2ad558657e17fafd24803217ba854762842e4178",
|
||||
"gitHead": "0e614d9f5a7e6f0305c625f6b581f6d80b33b8a6",
|
||||
"homepage": "https://github.com/isaacs/once#readme",
|
||||
"keywords": [
|
||||
"once",
|
||||
|
@ -95,5 +99,5 @@
|
|||
"scripts": {
|
||||
"test": "tap test/*.js"
|
||||
},
|
||||
"version": "1.3.3"
|
||||
"version": "1.4.0"
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "263dada66ab3f2fb10bf7f9d24dd8f3e570ef912",
|
||||
"tarball": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
|
||||
"tarball": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "21932a549f5e52ffd9a827f570e04be62a97da54",
|
||||
"tarball": "http://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz"
|
||||
"tarball": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "867ac74e3864187b1d3d47d996a78ec5c8830777",
|
||||
"tarball": "http://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz"
|
||||
"tarball": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz"
|
||||
},
|
||||
"homepage": "https://github.com/substack/typedarray",
|
||||
"keywords": [
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "450d4dc9fa70de732762fbd2d4a28981419a0ccf",
|
||||
"tarball": "http://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||
"tarball": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||
},
|
||||
"gitHead": "475fb6857cd23fafff20c1be846c1350abf8e6d4",
|
||||
"homepage": "https://github.com/TooTallNate/util-deprecate",
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
]
|
||||
],
|
||||
"_from": "eslint@latest",
|
||||
"_id": "eslint@3.4.0",
|
||||
"_id": "eslint@3.5.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/eslint",
|
||||
"_nodeVersion": "4.4.7",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/eslint-3.4.0.tgz_1472234173647_0.17217218782752752"
|
||||
"host": "packages-16-east.internal.npmjs.com",
|
||||
"tmp": "tmp/eslint-3.5.0.tgz_1473451101299_0.8081250376999378"
|
||||
},
|
||||
"_npmUser": {
|
||||
"name": "eslint",
|
||||
|
@ -41,8 +41,8 @@
|
|||
"_requiredBy": [
|
||||
"#USER"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/eslint/-/eslint-3.4.0.tgz",
|
||||
"_shasum": "af5984007bd3f1fb1b3b6b01a0a22eda0ec7a9f4",
|
||||
"_resolved": "https://registry.npmjs.org/eslint/-/eslint-3.5.0.tgz",
|
||||
"_shasum": "22fc9f780ea5bca1306fab2b6d3336b0fa62c754",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "eslint",
|
||||
"_where": "/Users/trott/io.js/tools",
|
||||
|
@ -133,8 +133,8 @@
|
|||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "af5984007bd3f1fb1b3b6b01a0a22eda0ec7a9f4",
|
||||
"tarball": "https://registry.npmjs.org/eslint/-/eslint-3.4.0.tgz"
|
||||
"shasum": "22fc9f780ea5bca1306fab2b6d3336b0fa62c754",
|
||||
"tarball": "https://registry.npmjs.org/eslint/-/eslint-3.5.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
|
@ -147,7 +147,7 @@
|
|||
"lib",
|
||||
"messages"
|
||||
],
|
||||
"gitHead": "faab36e519ce8caf428da4567766e699464a2316",
|
||||
"gitHead": "18be52eab695f0d78d19b349fefb09db19751d51",
|
||||
"homepage": "http://eslint.org",
|
||||
"keywords": [
|
||||
"ast",
|
||||
|
@ -194,5 +194,5 @@
|
|||
"release": "node Makefile.js release",
|
||||
"test": "node Makefile.js test"
|
||||
},
|
||||
"version": "3.4.0"
|
||||
"version": "3.5.0"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue