0

Using React-native on android. However, I think my question applies to any javascript environment.

I am constructing a function from text sent from the server (there are good reasons for it).

function helper_called_from_dynamic (arg1)
{
  console.log('helper called ',arg1);
}

export class MyInvoker
{
  constructor ()
  {
    this._funcProps={};
  }

  initialize ( item )
  {
    this._funcProps["df1"]=new Function (["inArg1"],item.fnBody);
  }

  call_dynamic_func (fnName,arg1)
  { 
    return this._funcProps[fnName](arg1);
  }
}

The fnBody has the following: " return helper_called_from_dynamic(inArg1); "

my invocation via MyInvoker is the following

let invInst = new MyInvoker();
let item={fnBody:"return helper_called_from_dynamic(inArg1); "};
invInst.initialize(item);
invInst.call_dynamic_func("df1","somearg");

I am getting an error (from react-native, but again, I suspect it would be common to all other javascript environments):

cannot find variable: helper_called_from_dynamic

Is it possible to get this to work? That is allowing the dynamically created functions to call other functions? Or do I have to resort to 'eval' ?

V P
  • 845
  • 10
  • 28
  • Is `this._funcProps` defined? `this._funcProps["df1]=new Function (["inArg1"],item.fnBody);`; missing `"` after `"df1`? e.g., `this._funcProps["df1"] = new Function (["inArg1"],item.fnBody);` – guest271314 Jul 17 '16 at 22:43
  • Could you JS code be running through a minification/uglify step that drops the `helper_called_from_dynamic` function because its not used? I'd put a breakpoint in your `initialize` and see if `helper_called_from_dynamic` is in scope. – go-oleg Jul 17 '16 at 22:50
  • You are also calling `invInst.call_dynamic_function("df1","somearg");` where function in class is `call_dynamic_func` without "tion" – guest271314 Jul 17 '16 at 22:58
  • My guess is that `helper_called_from_dynamic` was not actually declared in global scope, like it is in [my JSFiddle test](https://jsfiddle.net/unezt28k/) – 4castle Jul 17 '16 at 22:59
  • `new Function` constructs functions in the global scope. Your `helper_called_from_dynamic` is declared in the module scope. Make the evaled code only call methods of arguments, make the helper global (not advised), or [inject it manually in the eval scope](http://stackoverflow.com/a/24032179/1048572) – Bergi Jul 17 '16 at 23:47
  • @4castle is window. syntax required to make a function declaration global? I thought just declaring it as I did would be enough. I do not believe window. is available in React-native either, that's why I tried to stay away from browser-centric constructs. But is it really the case that 'window.' is absolute necessity for a function to be collable by another globally scoped function (my understanding is that functions created with Function are globally scoped) ? – V P Jul 18 '16 at 00:15
  • @VP No, the `window.` syntax is only necessary if your code is not in the global scope. I did that just to make it explicit, but you can also do it [like this JSFiddle](https://jsfiddle.net/unezt28k/1/) (In JSFiddle you have to modify the JavaScript settings in order for the code to execute in global scope) – 4castle Jul 18 '16 at 01:33

1 Answers1

1

Solution hinted by @Bergi worked for me. The suggestion

Make the evaled code only call methods of arguments

is what I had done, and that worked. I should have thought about it before posting, but it had not occured to me at the time. Instead of making the helper function global, I attached it to an instance of a class, and passed that instance as an argument to the dynamic function.

Here is the detail

export class MyHelpers
{
 helper_called_from_dynamic (arg1)
 {
   console.log('helper called ',arg1);
 }
}

export class MyInvoker
{
  constructor ()
  {
    this._funcProps={};
    this._myHelpers=new MyHelpers();
  }

  initialize ( item )
  {
    this._funcProps["df1"]=new Function (["inArg1","iHelper"],item.fnBody);
  }

  call_dynamic_func (fnName,arg1)
  { 
    return this._funcProps[fnName](arg1,this._myHelpers);
  }
}

Then the body of the dynamic function now can access the helper_called_from_dynamic :

let invInst = new MyInvoker();
let item={fnBody:"return iHelper.helper_called_from_dynamic(inArg1); "};
invInst.initialize(item);
invInst.call_dynamic_func("df1","somearg");
V P
  • 845
  • 10
  • 28