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()
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.
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.
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.
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.
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());
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With