@@ -18,6 +18,7 @@ export class FunctionLoader implements IFunctionLoader {
1818        [ k : string ] : { 
1919            info : FunctionInfo ; 
2020            func : Function ; 
21+             thisArg : unknown ; 
2122        } ; 
2223    }  =  { } ; 
2324
@@ -42,15 +43,11 @@ export class FunctionLoader implements IFunctionLoader {
4243            script  =  require ( scriptFilePath ) ; 
4344        } 
4445        const  entryPoint  =  < string > ( metadata  &&  metadata . entryPoint ) ; 
45-         const  userFunction  =  getEntryPoint ( script ,  entryPoint ) ; 
46-         if  ( typeof  userFunction  !==  'function' )  { 
47-             throw  new  InternalException ( 
48-                 'The resolved entry point is not a function and cannot be invoked by the functions runtime. Make sure the function has been correctly exported.' 
49-             ) ; 
50-         } 
46+         const  [ userFunction ,  thisArg ]  =  getEntryPoint ( script ,  entryPoint ) ; 
5147        this . #loadedFunctions[ functionId ]  =  { 
5248            info : new  FunctionInfo ( metadata ) , 
5349            func : userFunction , 
50+             thisArg, 
5451        } ; 
5552    } 
5653
@@ -66,7 +63,8 @@ export class FunctionLoader implements IFunctionLoader {
6663    getFunc ( functionId : string ) : Function  { 
6764        const  loadedFunction  =  this . #loadedFunctions[ functionId ] ; 
6865        if  ( loadedFunction  &&  loadedFunction . func )  { 
69-             return  loadedFunction . func ; 
66+             // `bind` is necessary to set the `this` arg, but it's also nice because it makes a clone of the function, preventing this invocation from affecting future invocations 
67+             return  loadedFunction . func . bind ( loadedFunction . thisArg ) ; 
7068        }  else  { 
7169            throw  new  InternalException ( `Function code for '${ functionId }  ) ; 
7270        } 
@@ -83,9 +81,10 @@ export class FunctionLoader implements IFunctionLoader {
8381    } 
8482} 
8583
86- function  getEntryPoint ( f : any ,  entryPoint ?: string ) : Function  { 
84+ function  getEntryPoint ( f : any ,  entryPoint ?: string ) : [ Function ,  unknown ]  { 
85+     let  thisArg : unknown ; 
8786    if  ( f  !==  null  &&  typeof  f  ===  'object' )  { 
88-         const   obj  =  f ; 
87+         thisArg  =  f ; 
8988        if  ( entryPoint )  { 
9089            // the module exports multiple functions 
9190            // and an explicit entry point was named 
@@ -99,12 +98,6 @@ function getEntryPoint(f: any, entryPoint?: string): Function {
9998            // 'run' or 'index' by convention 
10099            f  =  f . run  ||  f . index ; 
101100        } 
102- 
103-         if  ( typeof  f  ===  'function' )  { 
104-             return  function  ( )  { 
105-                 return  f . apply ( obj ,  arguments ) ; 
106-             } ; 
107-         } 
108101    } 
109102
110103    if  ( ! f )  { 
@@ -116,7 +109,11 @@ function getEntryPoint(f: any, entryPoint?: string): Function {
116109            "you must indicate the entry point, either by naming it 'run' or 'index', or by naming it "  + 
117110            "explicitly via the 'entryPoint' metadata property." ; 
118111        throw  new  InternalException ( msg ) ; 
112+     }  else  if  ( typeof  f  !==  'function' )  { 
113+         throw  new  InternalException ( 
114+             'The resolved entry point is not a function and cannot be invoked by the functions runtime. Make sure the function has been correctly exported.' 
115+         ) ; 
119116    } 
120117
121-     return  f ; 
118+     return  [ f ,   thisArg ] ; 
122119} 
0 commit comments