Skip to content

feat(resolver): track Function.bind/call/apply for receiver-typed resolution (JS) #1318

@carlos-alm

Description

@carlos-alm

Source

Jelly micro-test benchmark (PR #1304). fun scores 29% recall (4/14 named edges). The 10 missed edges all involve bind, call, or apply.

Pattern

// bind: sets 'this' for the returned function
var x = { a: function() {} };
var f = function() { return this.a; }.bind(x);
f()();  // f() returns x.a → calling it calls x.a
// Expected edge: x.a called from the return-of-f call site

// call: sets 'this' for one invocation
function foo(b) { return this(b); }
(foo.call((a) => a, () => {}))();
// this = (a) => a, so this(b) calls the first arg with b

// apply: sets 'this' and spreads args array
function bar(c) { return this(c); }
function baz() {
    return bar.apply((d) => d, arguments);  // this = (d) => d
}
var q = baz(() => {});
q();

What's needed

  1. f.bind(ctx): track that the bound function's this is ctx; when the bound function accesses this.prop, resolve through ctx's type
  2. f.call(ctx, args...): treat as calling f with this = ctx
  3. f.apply(ctx, argsArray): same as call but args come from array

These require interprocedural this-context tracking. A useful first step: at least resolve the direct callee when f is a known function literal (not through this access).

Impact

  • 10 named edges in the fun fixture
  • bind/call/apply appear in ~40% of real-world higher-order JS code
  • Partial win available: tracking f.call(ctx, arg1) as f(arg1) (ignoring this) already recovers direct call edges

Fixture

tests/benchmarks/resolution/fixtures/jelly-micro/fun/fun.js

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions