Repository: ember-cli/eslint-plugin-ember
Pull request #1431 (2022-02-13 04:25:17)

Fix crash in `jquery-ember-run` rule
The included test demonstrates a case that would trigger an assertion within eslint. 

It's not correct to try to `report(expression.callee)` without checking first that the expression is a CallExpression. Lots of other kinds of nodes can appear here instead, and they will cause us to pass undefined to `report()`, which generates the assertion within eslint.

The refactoring into two helper functions here was forced by the complexity eslint rule this repo uses.


Patch:
diff --git a/lib/rules/jquery-ember-run.js b/lib/rules/jquery-ember-run.js
index c4ac1f64..35aab5fc 100644
--- a/lib/rules/jquery-ember-run.js
+++ b/lib/rules/jquery-ember-run.js
@@ -53,6 +53,30 @@ module.exports = {
     let importedEmberName;
     const importedRunloopFunctions = [];
 
+    // Check for imported call to: bind()
+    function isBindCall(expression) {
+      return (
+        types.isCallExpression(expression) &&
+        expression.callee.type === 'Identifier' &&
+        importedRunloopFunctions.includes(expression.callee.name)
+      );
+    }
+
+    // Check for old-style: Ember.run.bind()
+    function isEmberBindCall(expression) {
+      return (
+        types.isCallExpression(expression) &&
+        expression.callee.type === 'MemberExpression' &&
+        expression.callee.property.type === 'Identifier' &&
+        EMBER_RUNLOOP_FUNCTIONS.includes(expression.callee.property.name) &&
+        expression.callee.object.type === 'MemberExpression' &&
+        expression.callee.object.property.type === 'Identifier' &&
+        expression.callee.object.property.name === 'run' &&
+        expression.callee.object.object.type === 'Identifier' &&
+        expression.callee.object.object.name === importedEmberName
+      );
+    }
+
     function checkJqueryCall(node) {
       if (
         // Check to see if this jquery call looks like: $(...).on(() => { ... }));
@@ -69,27 +93,12 @@ module.exports = {
           const fnExpressions = utils.findNodes(fnBody, 'ExpressionStatement');
           for (const fnExpression of fnExpressions) {
             const expression = fnExpression.expression;
-
-            // Check for imported call to: bind()
-            const isBindCall =
-              types.isCallExpression(expression) &&
-              expression.callee.type === 'Identifier' &&
-              importedRunloopFunctions.includes(expression.callee.name);
-
-            // Check for old-style: Ember.run.bind()
-            const isEmberBindCall =
-              types.isCallExpression(expression) &&
-              expression.callee.type === 'MemberExpression' &&
-              expression.callee.property.type === 'Identifier' &&
-              EMBER_RUNLOOP_FUNCTIONS.includes(expression.callee.property.name) &&
-              expression.callee.object.type === 'MemberExpression' &&
-              expression.callee.object.property.type === 'Identifier' &&
-              expression.callee.object.property.name === 'run' &&
-              expression.callee.object.object.type === 'Identifier' &&
-              expression.callee.object.object.name === importedEmberName;
-
-            if (!isBindCall && !isEmberBindCall) {
-              report(expression.callee);
+            if (!isBindCall(expression) && !isEmberBindCall(expression)) {
+              if (types.isCallExpression(expression)) {
+                report(expression.callee);
+              } else {
+                report(expression);
+              }
             }
           }
         }


Test patch:
diff --git a/tests/lib/rules/jquery-ember-run.js b/tests/lib/rules/jquery-ember-run.js
index 59795722..9237040a 100644
--- a/tests/lib/rules/jquery-ember-run.js
+++ b/tests/lib/rules/jquery-ember-run.js
@@ -93,6 +93,12 @@ eslintTester.run('jquery-ember-run', rule, {
       output: null,
       errors: [{ message: ERROR_MESSAGE, type: 'Identifier' }],
     },
+    {
+      // With assignment
+      code: 'import $ from "jquery"; $("#item").on("click", () => { this.value = 1; });',
+      output: null,
+      errors: [{ message: ERROR_MESSAGE, type: 'AssignmentExpression' }],
+    },
     {
       // With not from Ember
       code: 'import $ from "jquery"; $("#item").on("click", () => { notEmber.run.bind(); });',