Wrapping regex's with proxies isn't working

# Angel Scull (8 years ago)

Hello,

I’ve tried this code and seems that there is some weird type checking somewhere that causes this exception.

TypeError: Method RegExp.prototype.exec called on incompatible receiver [object Object]

let pattern = /^[a-zA-Z0-9-.]+@[a-zA-Z0-9-]+(.?[a-zA-Z0-9-_]*).[a-zA-Z]{2,3}$/;

let patternProxy = new Proxy(pattern,{});

patternProxy.test('myusername at mycompany.com')

# Michał Wadas (8 years ago)

It's probably implementation issue and you should report it to SpiderMonkey/V8/Chacra team.

# Claude Pache (8 years ago)

Le 10 nov. 2016 à 14:59, Angel Scull <scull06 at gmail.com> a écrit :

Hello,

I’ve tried this code and seems that there is some weird type checking somewhere that causes this exception.

TypeError: Method RegExp.prototype.exec called on incompatible receiver [object Object]

let pattern = /^[a-zA-Z0-9-.]+@[a-zA-Z0-9-]+(.?[a-zA-Z0-9-_]*).[a-zA-Z]{2,3}$/;

let patternProxy = new Proxy(pattern,{});

patternProxy.test('myusername at mycompany.com')

This is because the exec method of pattern is internally called with patternProxy as its receiver (i.e, its "this argument"), and patternProxy is not a regexp. This is a general issue with proxies, and not a bug.

A simple adhoc workaround is to bind the exec method of that particular pattern to pattern itself:

pattern.exec = pattern.exec.bind(pattern)
# Isiah Meadows (8 years ago)

This could be resolved by checking the underlying non-proxy object and using that one's internal slots instead, in each language-level method that checks that.

# Claude Pache (8 years ago)

Le 10 nov. 2016 à 15:50, Isiah Meadows <isiahmeadows at gmail.com> a écrit :

This could be resolved by checking the underlying non-proxy object and using that one's internal slots instead, in each language-level method that checks that.

Such semantics could make impossible to write impermeable proxies for some objects, e.g.

let s = new Set
let sProxy = new Proxy(s, { /* .... */ })
Set.prototype.add.call(sProxy, "foo") // will add "foo" to `s`, even if you were careful enough to intercept `sProxy.add("foo")`
Set.prototype.has.call(sProxy, "bar") // will reveal whether "bar" is in `s`
# Isiah Meadows (8 years ago)

The complaint here is that it's impermeable when it would be preferred not to be. I personally have never yet needed a proxy where nothing else would suffice, so I pretty much have no stake in this discussion.

# Allen Wirfs-Brock (8 years ago)

On Nov 10, 2016, at 1:10 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

The complaint here is that it's impermeable when it would be preferred not to be. I personally have never yet needed a proxy where nothing else would suffice, so I pretty much have no stake in this discussion.

This issue is well known to the proxy champions and has been repeatedly discussed on es-discuss and in TC39 meeting notes and presentations. Anybody who wants to talk about this, should first come up to speed with all that background.

The fundamental issue is that the default hander semantics is not transparent to methods that implicitly or explicitly depend upon the identity of the target object. Such identify dependencies include access to specification (or implementation) defined internal slots or any other mechanisms such as WeakMap lookup using a method's this value as the key.

There are various schemes by which proxy handlers can explicitly deal with these issue. For example, by defining a handler that implements a membrane around the target object.