Skip to content

Instantly share code, notes, and snippets.

@buhichan
Last active October 15, 2020 00:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save buhichan/892ab71dd6261c0eedb813324774e935 to your computer and use it in GitHub Desktop.
Save buhichan/892ab71dd6261c0eedb813324774e935 to your computer and use it in GitHub Desktop.
js get free variables hack
/**
* some insane hack, just want to avoid using expensive parser.
*/
export function getFreeVariables(expr:string, knownSymbols:Record<string,unknown>){
const freeVariables = new Set<string>();
//eslint-disable-next-line
const anyThingPrimitive = ()=>{};
Object.defineProperties(anyThingPrimitive, {
[Symbol.toPrimitive]:{
value: ()=>{
return 1
},
},
[Symbol.toStringTag]:{
value: ()=>{
return ""
}
}
})
const anyThing2:unknown = new Proxy(anyThingPrimitive,{
get(target, prop){
if(prop === Symbol.unscopables){
return undefined
}
if(prop in target){
return (target as unknown as Record<string,unknown>)[prop as string]
}
return anyThing2
},
apply(target, thisArg, args){
return anyThing2
}
})
const anyThing = new Proxy(anyThingPrimitive,{
has(target, prop){
if(prop === 'unsafe___THIS____func'){
return false
}
if(prop === 'arguments'){
return false
}
if(prop in knownSymbols){
return false
}
return true;
},
get(target, prop){
if(prop === Symbol.unscopables){
return undefined
}
if(prop in target){
return (target as unknown as Record<string,unknown>)[prop as string]
}
freeVariables.add(prop as string)
return anyThing2
},
apply(target, thisArg, args){
return anyThing2
}
})
{
const unsafe___THIS____func = new Function(`with (arguments[0]) { with (arguments[1]) { return ${expr} } }`);
unsafe___THIS____func(anyThing, knownSymbols);
}
return [...freeVariables];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment