Skip to content

Instantly share code, notes, and snippets.

@suyanhanx
Forked from buhichan/get_free_vars.ts
Created August 27, 2020 09:26
Show Gist options
  • Save suyanhanx/59ea1bf1cb233d2f824df16e723b4452 to your computer and use it in GitHub Desktop.
Save suyanhanx/59ea1bf1cb233d2f824df16e723b4452 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