fix(linter/no-eval): resolve this binding for functions returned from an IIFE#23643
fix(linter/no-eval): resolve this binding for functions returned from an IIFE#23643shulaoda wants to merge 1 commit into
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
camc314
left a comment
There was a problem hiding this comment.
can we add a test case via a rule for this on?
how is this function used?
237e84e to
7c7de6d
Compare
is_callee always return false|
Good call — done, and it pointed to a better fix.
The isolated I've fixed both and added a rule test. For example, under obj.foo = (function() { return function() { this.eval('foo'); }; })()is now correctly not reported (the returned function's I've updated the PR title/description accordingly. |
What
is_callee(inast_util.rs) is used only byis_default_this_binding, which is used only by theno-evalrule to decide whetherthisinthis.eval(...)refers to the global object.Two coupled bugs in that path are fixed here:
is_calleealways returnedfalse. Its closure parameter was namednode, shadowing the outernode, sonode.kind().span()referred to the parentCallExpressionrather than the node under test.callee.span().contains_inclusive(...)then compared the callee span against the whole call-expression span — impossible — so it never reported an actual callee.The traversal in
is_default_this_bindingnever stepped above the call. After theis_calleecheck, the loop didcurrent_node = parent(theReturnStatement/ arrow) instead of continuing from above the call site (ESLint doesnode = func.parent/node = parent.parent), so it always bottomed out atreturn true. This masked fix (1) entirely.Effect
With both fixed,
no-evalno longer false-positives on a function returned from an immediately-invoked function and assigned to a member, which matches ESLint:The returned function's
thisis bound toobj, not the global object, sothis.evalis not indirect eval. Previously this was reported; now it is not.Test
Added a
no-evalpasscase for the above. The wholeno-evalsuite still passes. (A buggyis_calleefalls through theSome(func) if is_callee(...)guard toreturn true, re-flagging the case, so the rule test covers both fixes.)