bids-validator
bids-validator copied to clipboard
interface to execute selectors/checks directly as javascript
The generated context will need to be in the namespace of the executed code. Not sure what kind of jailing features browser/deno api have.
http://blog.namangoel.com/replacing-eval-with-a-web-worker https://stackoverflow.com/questions/69276975/deno-classic-workers-are-not-supported
Proof of concept:
export function evalCheck(toExec: string, context: any): void{
let code = `
self.onmessage = (e) => {
Object.keys(e.data).map((key) => {
globalThis[key] = e.data[key]
});
try {
let result = ${toExec}
self.postMessage(result)
} catch (error) {
console.log(error)
console.log('inner error')
}
self.close();
};
`
const blob = new Blob([code], { type: 'text/javascript' });
let blobURL = URL.createObjectURL(blob);
var worker = new Worker(blobURL, {type: "module", deno: true});
worker.addEventListener('message', function(e) {
console.log(e.data)
})
worker.addEventListener('error', function(e) {
console.log("error")
})
worker.postMessage(context)
}
evalCheck('x + 1', {x: 1})
evalCheck('bad; format --', {x: 3})
When testing with deno had to run with --unstable
.
- updated to expose context values as variables in worker through globalThis.
this
was undefined in the worker function.
I think the issue with this is going to be passing the context into the worker will be fairly expensive for how many evaluations this will perform across a large dataset.
Maybe this will do:
const evalConstructor = (src: string): Function =>
new Function('context', `with (context) { return ${src} }`)
const safeHas = () => true
const safeGet = (target: any, prop: any) =>
prop === Symbol.unscopables ? undefined : target[prop]
function evalCheck(src: string, context: Record<string, any>) {
const test = evalConstructor(src)
const safeContext = new Proxy(context, { has: safeHas, get: safeGet })
try {
return test(safeContext)
} catch (error) {
console.error(error)
}
}
Example:
const context = {
test: 'value',
}
console.log(evalCheck('1 + 1', context))
> 2
console.log(evalCheck('bad; format --', context))
> undefined
console.log(evalCheck('fetch', context))
> undefined
console.log(evalCheck('test === "value"', context))
> true
Wow way better. That proxy/with combination is something else.
Wow way better. That proxy/with combination is something else.
I think the main problem is making sure the proxy behaves with a deeper object but shouldn't be too hard to generalize it.