Controlling access to global variables via an ES6 proxy
The following function evalCode()
traces the global variables that are accessed while evaluating a piece of JavaScript code.
// Simple solution
const _glob = typeof global !== 'undefined' ? global : self;
function evalCode(code) {
const func = new Function ('proxy',
`with (proxy) {${code}}`); // (A)
const proxy = new Proxy(_glob, {
get(target, propKey, receiver) {
console.log(`GET ${String(propKey)}`); // (B)
return Reflect.get(target, propKey, receiver);
},
set(target, propKey, value, receiver) { // (C)
console.log(`SET ${String(propKey)}=${value}`);
return Reflect.set(target, propKey, value, receiver);
},
});
return func(proxy);
}
The way this works is as follows:
- The
with
statement wrapped around the code (line A) means that every variable access that “leaves” the scope of the code becomes a property access ofproxy
. - The proxy observes what properties are accessed via its handler, which traps the operations “get” (line B) and “set” (line C),
Unsing evalCode()
:
> evalCode('String.prototype')
GET Symbol(Symbol.unscopables)
GET String
undefined
> evalCode('String = 123')
GET Symbol(Symbol.unscopables)
SET String=123
undefined
Explanations:
- We don’t return what
code
does, which is why the result isundefined
. Symbol.unscopables
shows up, becausewith
checks its operand for a property with this key to determine which properties it should not expose as variables to its body. This mechanism is explained in “Exploring ES6”.
This is very hacky! with
is a deprecated sloppy mode feature that is used in conjunction with a brand new ES6 feature.
Source of this hack: Vue.js, explained by qgustavor on reddit.
Further reading
- Chapter “Metaprogramming with proxies” in ”Exploring ES6”.
- Section “Property key
Symbol.unscopables
” in Exploring ES6”. - Blog post “ES proposal: global” (demonstrates how to properly access the global object)
Comments
Post a Comment