summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-12-22 16:53:42 +0100
committerMichaël Zasso <targos@protonmail.com>2018-01-11 09:48:05 +0100
commit3dc30632755713179f345f4af024bd904c6162d0 (patch)
treef28c4f6dd6dfc5992edf301449d1a371d229755b /tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js
parenta2c7085dd4a8e60d1a47572aca8bb6fcb7a32f88 (diff)
downloadandroid-node-v8-3dc30632755713179f345f4af024bd904c6162d0.tar.gz
android-node-v8-3dc30632755713179f345f4af024bd904c6162d0.tar.bz2
android-node-v8-3dc30632755713179f345f4af024bd904c6162d0.zip
tools: move eslint from tools to tools/node_modules
This is required because we need to add the babel-eslint dependency and it has to be able to resolve "eslint". babel-eslint is required to support future ES features such as async iterators and import.meta. Refs: https://github.com/nodejs/node/pull/17755 PR-URL: https://github.com/nodejs/node/pull/17820 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js')
-rw-r--r--tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js124
1 files changed, 124 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js b/tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js
new file mode 100644
index 0000000000..d2a6b5df10
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js
@@ -0,0 +1,124 @@
+/**
+ * @fileoverview restrict values that can be used as Promise rejection reasons
+ * @author Teddy Katz
+ */
+"use strict";
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "require using Error objects as Promise rejection reasons",
+ category: "Best Practices",
+ recommended: false
+ },
+ fixable: null,
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allowEmptyReject: { type: "boolean" }
+ },
+ additionalProperties: false
+ }
+ ]
+ },
+
+ create(context) {
+
+ const ALLOW_EMPTY_REJECT = context.options.length && context.options[0].allowEmptyReject;
+
+ //----------------------------------------------------------------------
+ // Helpers
+ //----------------------------------------------------------------------
+
+ /**
+ * Checks the argument of a reject() or Promise.reject() CallExpression, and reports it if it can't be an Error
+ * @param {ASTNode} callExpression A CallExpression node which is used to reject a Promise
+ * @returns {void}
+ */
+ function checkRejectCall(callExpression) {
+ if (!callExpression.arguments.length && ALLOW_EMPTY_REJECT) {
+ return;
+ }
+ if (
+ !callExpression.arguments.length ||
+ !astUtils.couldBeError(callExpression.arguments[0]) ||
+ callExpression.arguments[0].type === "Identifier" && callExpression.arguments[0].name === "undefined"
+ ) {
+ context.report({
+ node: callExpression,
+ message: "Expected the Promise rejection reason to be an Error."
+ });
+ }
+ }
+
+ /**
+ * Determines whether a function call is a Promise.reject() call
+ * @param {ASTNode} node A CallExpression node
+ * @returns {boolean} `true` if the call is a Promise.reject() call
+ */
+ function isPromiseRejectCall(node) {
+ return node.callee.type === "MemberExpression" &&
+ node.callee.object.type === "Identifier" && node.callee.object.name === "Promise" &&
+ node.callee.property.type === "Identifier" && node.callee.property.name === "reject";
+ }
+
+ //----------------------------------------------------------------------
+ // Public
+ //----------------------------------------------------------------------
+
+ return {
+
+ // Check `Promise.reject(value)` calls.
+ CallExpression(node) {
+ if (isPromiseRejectCall(node)) {
+ checkRejectCall(node);
+ }
+ },
+
+ /*
+ * Check for `new Promise((resolve, reject) => {})`, and check for reject() calls.
+ * This function is run on "NewExpression:exit" instead of "NewExpression" to ensure that
+ * the nodes in the expression already have the `parent` property.
+ */
+ "NewExpression:exit"(node) {
+ if (
+ node.callee.type === "Identifier" && node.callee.name === "Promise" &&
+ node.arguments.length && astUtils.isFunction(node.arguments[0]) &&
+ node.arguments[0].params.length > 1 && node.arguments[0].params[1].type === "Identifier"
+ ) {
+ context.getDeclaredVariables(node.arguments[0])
+
+ /*
+ * Find the first variable that matches the second parameter's name.
+ * If the first parameter has the same name as the second parameter, then the variable will actually
+ * be "declared" when the first parameter is evaluated, but then it will be immediately overwritten
+ * by the second parameter. It's not possible for an expression with the variable to be evaluated before
+ * the variable is overwritten, because functions with duplicate parameters cannot have destructuring or
+ * default assignments in their parameter lists. Therefore, it's not necessary to explicitly account for
+ * this case.
+ */
+ .find(variable => variable.name === node.arguments[0].params[1].name)
+
+ // Get the references to that variable.
+ .references
+
+ // Only check the references that read the parameter's value.
+ .filter(ref => ref.isRead())
+
+ // Only check the references that are used as the callee in a function call, e.g. `reject(foo)`.
+ .filter(ref => ref.identifier.parent.type === "CallExpression" && ref.identifier === ref.identifier.parent.callee)
+
+ // Check the argument of the function call to determine whether it's an Error.
+ .forEach(ref => checkRejectCall(ref.identifier.parent));
+ }
+ }
+ };
+ }
+};