Skip to content

issue-2088 plan: a get-flavoured method_definition can smuggle a this-using function through its return value #2638

Description

@carlos-alm

What

Found in round 18 of the plan (PR #2612, docs/plans/issue-2088.md).

literalHasUnmodeledThisReference's method_definition arm proved safety only via subtreeContainsThisKeyword — sound for an ordinary method, not for a GETTER. A getter's own body can be entirely free of the this keyword while still RETURNING a value that, once the property is accessed and the result called (T.k()), gets this bound to the receiver — per ordinary member-expression-callee semantics, independent of anything the getter's own body does:

function fnA(){ return 41; }
function runImpl(){ return this.alpha(); }
const T = { alpha: fnA, get run(){ return runImpl; } };
T.run();            // → 41: fnA invoked via this.alpha(), this === T

Closed (round 18) by treating a get-flavoured method_definition as escaping unconditionally, regardless of what its own body contains. A plain method and a setter are unaffected — a setter's return value is never called (assignment expressions evaluate to the assigned value, never to what the setter returns), so subtreeContainsThisKeyword remains sound for it.

Direction

OVER-escape. This is a new, deliberate narrowing, not a safety gap: an entirely harmless getter (get value(){ return 42; }) now also makes its literal escape, because resolving what a getter returns — to any bounded number of hops — would still be incomplete (a returned call expression, inline function expression, or further property read could each independently be this-using, unlike the identifier-valued pair/shorthand arms' own single, positively-enumerable resolution target). This costs recall only, matching the same "detect the shape, fail safe outright" trade-off round 9's spread_element exclusion and round 10's/round 13's shadow/reassignment exclusions already accept elsewhere in this same design.

Suggested next step

Not required for issue #2088 to ship soundly (the exclusion is disclosed and conservative). If pursued: resolve a getter's own return expression the same way resolveIdentifierValueThisReference resolves an identifier-valued pair, when the getter's body is exactly return <identifier>; — but this still leaves every other return-expression shape (call, inline function, member access) unresolved, so the getter arm would remain partially unconditional regardless. Would need its own focused round and its own review, per this plan's own precedent for #2625/#2627/#2631.

Where

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions