Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function Proxy .toString() Errors

I am trying to call .toString() on a function proxy.

Simply creating a function proxy and calling toString causes "TypeError: Function.prototype.toString is not generic", setting the toString to return the source of the original causes "RangeError: Maximum call stack size exceeded", but creating a get trap for toString works.

Why does simply setting the toString function not work, but making a get trap does?

function wrap(source) {
 return(new Proxy(source, {}))
}
wrap(function() { }).toString()

function wrap(source) {
 let proxy = new Proxy(source, {})
 proxy.toString = function() {
  return(source.toString())
 }
 return(proxy)
}
wrap(function() { }).toString()

function wrap(source) {
 return(new Proxy(source, {
  get(target, key) {
   if(key == "toString") {
    return(function() {
     return(source.toString())
    })
   } else {
    return(Reflect.get(source, key))
} } })) }
wrap(function() { }).toString()
like image 695
Daniel Herr Avatar asked Jul 08 '16 06:07

Daniel Herr


People also ask

What is the function toString () method?

For user-defined Function objects, the toString method returns a string containing the source text segment which was used to define the function. JavaScript calls the toString method automatically when a Function is to be represented as a text value, e.g. when a function is concatenated with a string.

Can we override toString method in JavaScript?

Overriding toString for custom objectsYou can create a function to be called in place of the default toString() method. The toString() function you create should return a string value.

What is a proxy function?

The Proxy object allows you to create an object that can be used in place of the original object, but which may redefine fundamental Object operations like getting, setting, and defining properties. Proxy objects are commonly used to log property accesses, validate, format, or sanitize inputs, and so on.

What is proxy in JavaScript?

Proxy is an object in javascript which wraps an object or a function and monitors it via something called target. Irrespective of the wrapped object or function existence. Proxy are similar to meta programming in other languages.


2 Answers

I was having the same issue. I finally figured out that it's an issue with this. Add a get trap to your handler, bind the proxied object as this on the proxied property if it's a function, and it seems to work okay:

function wrap(source) {
    return new Proxy(source, {
        get: function (target, name) {
            const property = target[name];
            return (typeof property === 'function') 
                ? property.bind(target)
                : property;
        }
    });
}

console.log(wrap(function () {}).toString());
like image 185
Steve Kehlet Avatar answered Oct 21 '22 14:10

Steve Kehlet


TypeError: Function.prototype.toString is not generic

Seems like Function.prototype.toString is not supposed to be called on Proxy.

proxy.toString = function() {

This assignment to proxy is passed to the source object as you do not have trap for assignment. If you check source.hasOwnProperty('toString') you'll get true. When you add get trap, you don't change toString method and don't add it into source object, so it works.

The other possible solution is

function wrap(source) {
  let proxy = new Proxy(source, {})
  proxy.toString = Function.prototype.toString.bind(source)
  return proxy
}
like image 27
Qwertiy Avatar answered Oct 21 '22 15:10

Qwertiy