且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

创建辅助函数以在隔离范围内运行函数

更新时间:2022-06-27 05:53:53

我写了的版本isolated()处理任何非 bind ed用户定义的函数表达式并抛出作用域访问的自定义错误:

I wrote a version of isolated() that handles any non-binded user-defined function expression and throws custom errors for scoped accesses:

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');
      },
      set (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'); }
  })));
}

// test functions
[
  () => arguments, // fail
  () => this, // pass, no way to intercept this
  () => this.foo, // fail
  () => this.foo = 'bar', // fail
  () => this(), // fail
  () => new this, // fail
  h => h, // pass
  h => i, // fail
  (a, b) => b > a ? b : a, // pass
].forEach(fn => {
  const isolate = isolated(fn);
  console.log(isolate.toString());

  try {
    isolate();
    console.log('passed');
  } catch (error) {
    console.log(`${error.name}: ${error.message}`);
  }
})

这种实现稍微简单一些,因此比尝试解析用户定义函数的参数和主体更不容易出错。

This implementation is somewhat simpler, and therefore much less error-prone than attempting to parse the parameters and body of a user-defined function.

with 语句是一种相对简单的方法,用于捕获强制隔离函数中的任何作用域引用并抛出的ReferenceError 。它通过将一个代理中间件插入到作用域中,并使用一个get陷阱来拦截已访问的作用域变量名称。

The with statement is a relatively simplistic means of catching any scoped references within the forcibly isolated function and throwing a ReferenceError. It does so by inserting a Proxy intermediate into the scope with a get trap that intercepts the scoped variable name that was accessed.

作为函数上下文传递的代理是唯一有点难以实现的部分,也是不完整的。这是必要的,因为作为 with 语句的范围提供的代理不会拦截对这个关键字,所以上下文也必须明确包装,以拦截并抛出孤立箭头函数内的 this 的任何间接用法。

The Proxy that is passed as the context of the function was the only part that was a bit tricky to implement, and also incomplete. It was necessary because the Proxy provided as the scope to the with statement does not intercept accesses to the this keyword, so the context must also be wrapped explicitly in order to intercept and throw on any indirect usage of this inside an isolated arrow function.