Socket
Socket
Sign inDemoInstall

eslint-plugin-promise

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-promise - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

2

package.json
{
"name": "eslint-plugin-promise",
"version": "2.0.1",
"version": "3.0.0",
"description": "Enforce best practices for JavaScript promises",

@@ -5,0 +5,0 @@ "keywords": [

@@ -64,2 +64,3 @@ # eslint-plugin-promise

myPromise.then(doSomething); // could be either
myPromise.then((b) => { if (b) { return "yes" } else { return "no" } });
```

@@ -72,2 +73,3 @@

myPromise.then(() => { doSomething(); });
myPromise.then((b) => { if (b) { return "yes" } else { forgotToReturn(); } });
```

@@ -74,0 +76,0 @@

@@ -11,26 +11,108 @@ function isFunctionWithBlockStatement (node) {

function isReturnOrThrowStatement (node) {
return node.type === 'ReturnStatement' || node.type === 'ThrowStatement'
function isThenCallExpression (node) {
return (
node.type === 'CallExpression' &&
node.callee.type === 'MemberExpression' &&
node.callee.property.name === 'then'
)
}
function isFirstArgument (node) {
return (
node.parent &&
node.parent.arguments &&
node.parent.arguments[0] === node
)
}
function isInlineThenFunctionExpression (node) {
return (
isFunctionWithBlockStatement(node) &&
isThenCallExpression(node.parent) &&
isFirstArgument(node)
)
}
function peek (arr) {
return arr[arr.length - 1]
}
module.exports = {
create: function (context) {
// funcInfoStack is a stack representing the stack of currently executing
// functions
// funcInfoStack[i].branchIDStack is a stack representing the currently
// executing branches ("codePathSegment"s) within the given function
// funcInfoStack[i].branchInfoMap is an object representing information
// about all branches within the given function
// funcInfoStack[i].branchInfoMap[j].good is a boolean representing whether
// the given branch explictly `return`s or `throw`s. It starts as `false`
// for every branch and is updated to `true` if a `return` or `throw`
// statement is found
// funcInfoStack[i].branchInfoMap[j].loc is a eslint SourceLocation object
// for the given branch
// example:
// funcInfoStack = [ { branchIDStack: [ 's1_1' ],
// branchInfoMap:
// { s1_1:
// { good: false,
// loc: <loc> } } },
// { branchIDStack: ['s2_1', 's2_4'],
// branchInfoMap:
// { s2_1:
// { good: false,
// loc: <loc> },
// s2_2:
// { good: true,
// loc: <loc> },
// s2_4:
// { good: false,
// loc: <loc> } } } ]
var funcInfoStack = []
function markCurrentBranchAsGood () {
var funcInfo = peek(funcInfoStack)
var currentBranchID = peek(funcInfo.branchIDStack)
funcInfo.branchInfoMap[currentBranchID].good = true
}
return {
MemberExpression: function (node) {
var firstArg, body, lastStatement
ReturnStatement: markCurrentBranchAsGood,
ThrowStatement: markCurrentBranchAsGood,
if (node.property.name !== 'then' || node.parent.type !== 'CallExpression') {
return
}
onCodePathSegmentStart: function (segment, node) {
var funcInfo = peek(funcInfoStack)
funcInfo.branchIDStack.push(segment.id)
funcInfo.branchInfoMap[segment.id] = {good: false, loc: node.loc}
},
firstArg = node.parent.arguments[0]
if (!firstArg || !isFunctionWithBlockStatement(firstArg)) {
onCodePathSegmentEnd: function (segment, node) {
var funcInfo = peek(funcInfoStack)
funcInfo.branchIDStack.pop()
},
onCodePathStart: function (path, node) {
funcInfoStack.push({
branchIDStack: [],
branchInfoMap: {}
})
},
onCodePathEnd: function (path, node) {
var funcInfo = funcInfoStack.pop()
if (!isInlineThenFunctionExpression(node)) {
return
}
body = firstArg.body.body
lastStatement = body[body.length - 1]
if (!lastStatement || !isReturnOrThrowStatement(lastStatement)) {
context.report(node, 'Each then() should return a value or throw')
}
var finalBranchIDs = path.finalSegments.map(x => x.id)
finalBranchIDs.forEach((id) => {
var branch = funcInfo.branchInfoMap[id]
if (!branch.good) {
context.report({
message: 'Each then() should return a value or throw',
loc: branch.loc
})
}
})
}

@@ -37,0 +119,0 @@ }

@@ -12,2 +12,3 @@ 'use strict'

{ code: 'hey.then(x => ({}))', parserOptions: parserOptions },
{ code: 'hey.then(x => { return; })', parserOptions: parserOptions },
{ code: 'hey.then(x => { return x * 10 })', parserOptions: parserOptions },

@@ -23,3 +24,7 @@ { code: 'hey.then(function() { return 42; })', parserOptions: parserOptions },

{ code: 'hey.then(x => { if (!x) { throw new Error("no x"); } return x; })', parserOptions: parserOptions },
{ code: 'hey.then(x => { if (x) { return x; } throw new Error("no x"); })', parserOptions: parserOptions }
{ code: 'hey.then(x => { if (x) { return x; } throw new Error("no x"); })', parserOptions: parserOptions },
{ code: 'hey.then(x => { var f = function() { }; return f; })', parserOptions: parserOptions },
{ code: 'hey.then(x => { if (x) { return x; } else { return x; } })', parserOptions: parserOptions },
{ code: 'hey.then(x => { return x; var y = "unreachable"; })', parserOptions: parserOptions },
{ code: 'hey.then(x => { return; }, err=>{ log(err); })', parserOptions: parserOptions }
],

@@ -46,6 +51,26 @@

{
code: 'hey.then(function() { return; }).then(function() { })',
errors: [ { message: message } ]
},
{
code: 'hey.then(function() { doSomethingWicked(); })',
errors: [ { message: message } ]
},
{
code: 'hey.then(function() { if (x) { return x; } })',
errors: [ { message: message } ]
},
{
code: 'hey.then(function() { if (x) { return x; } else { }})',
errors: [ { message: message } ]
},
{
code: 'hey.then(function() { if (x) { } else { return x; }})',
errors: [ { message: message } ]
},
{
code: 'hey.then(function() { if (x) { return you.then(function() { return x; }); } })',
errors: [ { message: message } ]
}
]
})

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc