Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify object to use as global scope in new Function constructor?

Is there a way in Javascript to specify an object to use as the global scope when creating a function using new Function(...)?

For instance, consider a string

  var str = "return foo()";  // user supplied, generated by a trusted program

we can create a function with this string, passing in certain arguments

  var fn = new Function(str);
  var result = fn() 

This works if foo is defined in the global scope, either window in a browser or GLOBAL.global in Node.js.

But is there a way to give this newly created function an object, e.g. {foo: function() { return 42; }} and tell it to use that as the global scope?

The motivation here is the universe of possible functions that might be assumed to exist on the global scope is unknown. I'd like to define an object using ES6 Proxy that provides default implementations to unanticipated functions, and pass that object in to be used as the global scope within the function.

I know it's possible to explicitly define and pass in specific arguments, e.g.

  var fn = new Function("foo", str);
  var result = fn(function() { return "bar"; })

but that won't work as i'd like to handle methods we didn't anticipate.

It's also possible to pass in an object, e.g.

 var scope = { foo: function() { return 42; }
 var fn = new Function("scope", str);
 var result = fn(scope)

but that won't work as the string says "return foo()" not "return scope.foo()"

Define a scope for javascript Function constructor

EDIT

Answer suggested from comments by @ChiragRavindra and @RobG...

 var str = "return 'sand'+foo(); "  
 var o = {foo: function() { return "bar"}}
 var fn = new Function("obj", "with (obj) { " + str + "}")
 fn = fn.bind(o,o)
 fn(str) //==> "sandbar"
like image 928
prototype Avatar asked Oct 27 '25 03:10

prototype


1 Answers

Yes, you can. Define a Proxy that resolves every property with a function. So, to implement your second example, we can do this:

function factory (string) {
  const callable = new Function(`with(this){${string}}`);

  return function fn (method) {
    return callable.call(new Proxy({}, {
      has () { return true; },
      get (target, key) { if (typeof key !== 'symbol') return method; }
    }));
  };
}

const fn = factory('return foo()');
const result = fn(() => 42);

console.log(result);
like image 137
Patrick Roberts Avatar answered Oct 28 '25 18:10

Patrick Roberts



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!