繁体   English   中英

JS 无限循环保护,如何在没有节点或 web-worker 的情况下使用带有 DOM 的 babel-standalone 插件?

[英]JS infinite loop protection, how to use babel-standalone plugins without node or web-worker with DOM?

有一个浏览器内代码编辑器 (ace),可以为 p5.js 动态编译用户编写的代码。 研究如何防止无限循环并了解到一些这样的编辑器将babel-standaloneloop-protect一起使用。 为了避免定时循环标志(默认 100 毫秒)的问题,repl.it 使用了一个名为transform-prevent-infinite-loops.js的插件,它限制了迭代次数。

两者看起来都很棒并且想要测试它们,但是我无法弄清楚如何将任何一个(两个 CommonJS 模块)与 babel-standalone 一起使用,特别是在不使用捆绑器或 nodejs 时。 我很乐观地认为有一种方法可以直接加载这些插件,因为我不需要解析自己的代码,只需将等待的代码分析为变量字符串。 让内联lolizer插件示例正常工作 - 但上述无限循环保护插件要复杂得多,不幸的是,文档似乎没有提到独立导入外部插件。 是否可以在没有捆绑程序或 nodejs 的情况下使用这些?

基本设置: https://pastebin.com/LEYx8Kr4


以前分享过其他尝试,但按照建议减少到一个问题。

带有网络工作者的基本设置: https://pastebin.com/NgAPZzCX

在 pastebin 上还尝试使用web-worker route ,但似乎它不支持DOM API ,其中引入了 p5.js 函数。 为了解决这个问题,尝试做一些花哨的正则表达式来将代码剥离到循环中,但是你缺少变量,即。 如果循环计数是loopCount而不是10

如果存在无限循环以防止重新编译会覆盖当前正在运行的代码(实时编码环境)的错误代码,最终目标是得到一个危险信号。 web-worker 路由提供了这一点,如果我正确理解 babel,它不会标记它,但实际上会更改正在编译的代码以捕获该无限循环......是否还有另一种技术需要考虑,或者可能是这一切的混合?

我正在为我的库开发一个 repl,并且已经在独立使用 babel。

这个问题对我来说是正确的,因为它帮助我使用来自 react 的链接 babel 插件解决了这个问题。

如果你在某处声明你的插件 function

const preventInfiniteLoops = ({ types: t, template }) => {
  const buildGuard = template(`
    if (ITERATOR++ > MAX_ITERATIONS) {
      throw new RangeError(
        'Potential infinite loop: exceeded ' +
        MAX_ITERATIONS +
        ' iterations.'
      );
    }
  `)

  return {
    visitor: {
      'WhileStatement|ForStatement|DoWhileStatement': (path, file) => {
        // An iterator that is incremented with each iteration
        const iterator = path.scope.parent.generateUidIdentifier('loopIt')
        const iteratorInit = t.numericLiteral(0)
        path.scope.parent.push({
          id: iterator,
          init: iteratorInit,
        })
        // If statement and throw error if it matches our criteria
        const guard = buildGuard({
          ITERATOR: iterator,
          MAX_ITERATIONS: t.numericLiteral(MAX_SOURCE_ITERATIONS),
        })
        // No block statment e.g. `while (1) 1;`
        if (!path.get('body').isBlockStatement()) {
          const statement = path.get('body').node
          path.get('body').replaceWith(t.blockStatement([guard, statement]))
        } else {
          path.get('body').unshiftContainer('body', guard)
        }
      },
    },
  }
}

然后将其添加到独立的 babel 很简单

更新您的 pastebin 示例:(这是一个猜测,我没有测试过)

Babel.availablePlugins['preventInfiniteLoops'] = preventInfiniteLoops
let output = Babel.transform(codeIn.value, { presets: [], plugins: ['preventInfiniteLoops']}).code;

我正在使用 es6,所以我的代码是这样做的:

import { availablePlugins } from '@babel/standalone'
availablePlugins['preventInfiniteLoops'] = preventInfiniteLoops

这篇文章对我帮助很大,希望我的评论也能帮助其他人

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM