@@ -850,6 +850,32 @@ describe('JavaScript parser', () => {
850850 expect ( def . line ) . toBe ( 2 ) ;
851851 expect ( def . endLine ) . toBe ( 4 ) ;
852852 } ) ;
853+
854+ // .call/.apply/.bind narrowing (#1406)
855+ // All args flow into the delegated function, not as callbacks for the current scope.
856+ // This-rebinding (fn::this → ctx) is handled by extractThisCallBindingsWalk instead.
857+ it ( 'emits nothing for .call() — args flow into the delegated function, not the current scope' , ( ) => {
858+ const symbols = parseJS ( `Array.prototype.forEach.call(collection, handler);` ) ;
859+ expect ( symbols . calls ) . not . toContainEqual ( expect . objectContaining ( { name : 'handler' } ) ) ;
860+ expect ( symbols . calls ) . not . toContainEqual ( expect . objectContaining ( { name : 'collection' } ) ) ;
861+ } ) ;
862+
863+ it ( 'emits nothing for .apply() — second arg is an arguments array, not a callback' , ( ) => {
864+ const symbols = parseJS ( `fn.apply(ctx, handler);` ) ;
865+ expect ( symbols . calls ) . not . toContainEqual ( expect . objectContaining ( { name : 'handler' } ) ) ;
866+ expect ( symbols . calls ) . not . toContainEqual ( expect . objectContaining ( { name : 'ctx' } ) ) ;
867+ } ) ;
868+
869+ it ( 'emits nothing for .call() with only the this-context arg' , ( ) => {
870+ const symbols = parseJS ( `fn.call(ctx);` ) ;
871+ expect ( symbols . calls ) . not . toContainEqual ( expect . objectContaining ( { name : 'ctx' } ) ) ;
872+ } ) ;
873+
874+ it ( 'emits nothing for .bind() — all args are absorbed into the partial application' , ( ) => {
875+ const symbols = parseJS ( `Promise.resolve.bind(null, transform);` ) ;
876+ expect ( symbols . calls ) . not . toContainEqual ( expect . objectContaining ( { name : 'transform' } ) ) ;
877+ expect ( symbols . calls ) . not . toContainEqual ( expect . objectContaining ( { name : 'null' } ) ) ;
878+ } ) ;
853879 } ) ;
854880
855881 describe ( 'Phase 8.3f: object-destructuring rest parameter binding extraction' , ( ) => {
0 commit comments