I'm trying to use Proxy and the `with` statement to redirect access to the global object.
The problem is that, Proxy doesn't seem to have any handler for property creation which is done without object accessor or `Object.defineProperty()`. e.g. `prop = 123` instead of `obj.prop = 123`
My current code is like this.
const fakeGlobal = {console: console};
fakeGlobal.globalThis = fakeGlobal;
const proxy = new Proxy(fakeGlobal, {
has(tgt, key) {
//return key in tgt //initial code
return true
},
get(tgt, key) {
return tgt[key]
},
set(tgt, key, val) {
tgt[key] = val;
return true
}
});
with (proxy) {
prop = 123;
}
With that code, the proxy's `has()` handler is called, then the `set`
handler is called. The object creation happens between of those two
handlers, and is done internally by the JS engine without calling `Object.defineProperty()`.
Because the `prop` property doesn't yet exist in `fakeGlobal` object, the property is created in the outer scope object, which is the actual global object.
For sandboxing purpose, the `has()` handler has to return `true` whether the given property name actually exist in the `fakeGlobal` object or not. i.e.
has(tgt, key) {
return true
},
However, it will breaks the `in` operator functionality if it's used to simply check for a property presence in the `fakeGlobal` object. It also prevents an exception to occur if the sandboxed code refers to a non
existing property which is without any object accessor. e.g.
const prop = nonExistingProp;
Without sandboxing, that code would throw a ReferenceError exception as expected. But if it's run in the sandbox, no exception will occur - which is not how it should be.
So, is there a way to work around this problem?
If the combination of Proxy and the `with` statement is simply not
sufficient for sandboxing, what's a better method other than to implement an interpreter?
I'm having trouble understanding your goal. Can you share more than just
the tactics?
Are you avoiding modules?
Are you trying to create your own version of the ECMAScript ShadowRealm proposal?
<https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md>
On Sat, 20 Aug 2022 17:17:46 -0700 (PDT), Michael Haufe (TNO) wrote:
I'm having trouble understanding your goal. Can you share more than just the tactics?I'm trying to create a JS sandbox without the need of a separate browser Window object.
Are you avoiding modules?
No. The code can be anything.
Are you trying to create your own version of the ECMAScript ShadowRealm proposal?
<https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md>I'm not aware of that. What I'm trying to achieve is not based on that. That proposal does much more than what I want.
I'm trying to use Proxy and the `with` statement to redirect access to the global object.
The problem is that, Proxy doesn't seem to have any handler for property creation which is done without object accessor or
`Object.defineProperty()`. e.g. `prop = 123` instead of `obj.prop = 123`
is one of the reasons why it is *deprecated* since ECMAScript Edition 5,
and *code containing it cannot even be executed* in Strict Mode.
This has nothing to do with the capabilities of the Proxy object because its instance does not even "see" that write access.
You can determine whether a property is being created in the set handler
of the Proxy instance:
On Mon, 22 Aug 2022 01:08:06 +0200, Thomas 'PointedEars' Lahn wrote:
is one of the reasons why it is *deprecated* since ECMAScript Edition 5,
Yet, ECMAScript later added `Symbol.unscopables` to support `with`.
and *code containing it cannot even be executed* in Strict Mode.
I'm using `with`, so I don't use Strict mode in the first place.
This has nothing to do with the capabilities of the Proxy object because
its instance does not even "see" that write access.
That is correct. It's not supposed to and can not be the job for Proxy.
And that's the problem, because Proxy doesn't have a way to intercept property creation.
You can determine whether a property is being created in the “set”
handler of the Proxy instance:
That's not possible, because `set()` will only be called if the JS engine already know that the property exists as reported by `has()`.
The usual caveats for the “in” statement and ES 6+ features apply.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 374 |
Nodes: | 16 (2 / 14) |
Uptime: | 46:52:54 |
Calls: | 7,970 |
Calls today: | 1 |
Files: | 13,017 |
Messages: | 5,818,619 |