suman
suman copied to clipboard
create blocks with isolated scope
something like this:
before:
it.cb('sync test', t => {
t.assert.equal(++count, 2);
t.assert.equal(t.supply.three, 3);
t.done()
});
after:
const v = true;
it.cb('sync test', isolated(t => {
// v is not defined
t.assert.equal(++count, 2);
t.assert.equal(t.supply.three, 3);
t.done()
}));
this is done, but an improved way to cover all function types might look like:
function parseArguments(str, offset = 0, depth = 0) {
const openIndex = str.indexOf('(', offset);
const closeIndex = str.indexOf(')', offset);
return (openIndex >= 0 && openIndex < closeIndex)
? parseArguments(str, openIndex + 1, depth + 1)
: (depth > 0)
? parseArguments(str, closeIndex + 1, depth - 1)
: str.slice(0, closeIndex)
}
function isolated (fn) {
let str = Function.prototype.toString.call(fn);
let args, body;
if (/^(?:function\s*\S*\s*)?\(/.test(str)) {
const offset = str.indexOf('(') + 1;
args = parseArguments(str.slice(offset));
str = str.slice(offset + args.length + 1);
} else {
const offset = str.indexOf('=');
args = str.slice(0, offset).trim();
str = str.slice(offset);
}
if (/^\s*(?:=>)?\s*{/.test(str)) {
body = str.slice(str.indexOf('{') + 1, str.lastIndexOf('}'));
} else {
body = 'return ' + str.slice(str.indexOf('>') + 1).trim()
}
// 'use strict' directive prevents leaking scope
return eval(`'use strict';(function(${args}){${body}})`);
}
let processed = [
isolated(function named ({ h }, i = () => {}) {
console.log(h);
return i;
}),
isolated(({ h }, i = () => {}) => {
console.log(h);
return i;
}),
isolated(h => {
console.log(h);
}),
isolated(({ h }, i = () => {}) => (
console.log(h),
i
)),
isolated(h =>
console.log(h)
)
];
processed.forEach((fn) => console.log(fn.toString()))
see:
https://stackoverflow.com/questions/48071628/create-helper-function-to-run-a-function-in-an-isolated-scope/48073135
or this:
function isolated (fn) {
return new Function(`
with (new Proxy({}, {
has() { return true; },
get(target, property) {
if (typeof property !== 'string') return target[property];
throw new ReferenceError(property + ' accessed from isolated scope');
}
})) return ${Function.prototype.toString.call(fn)}
`).call(new Proxy(function(){}, new Proxy({}, {
get() { throw new ReferenceError('this accessed from isolated scope'); }
})));
}