简体   繁体   中英

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

Have an in browser code-editor (ace) that compiles user-written code on the fly for p5.js. Researching how to prevent infinite loops and learned that a few such editors use babel-standalone together with loop-protect . To avoid issues with the timed loop flag (default 100ms), there's a plugin called transform-prevent-infinite-loops.js used by repl.it which instead limits number of iterations.

Both look great and want to test them out, but am failing to figure out how to use either (both CommonJS modules) with babel-standalone, particuarly when not using a bundler or nodejs. I was optomistic that there's a way to load these plugins directly, since I don't need my own code parsed, just analyze code waiting as a variable string. Got the inline lolizer plugin example working – but the above infinite loop protecting plugins are far more complex and unfortunately the docs don't seem to mention importing external plugins with stand-alone. Is it possible to use these without a bundler or nodejs?

Basic setup: https://pastebin.com/LEYx8Kr4


Previously shared other attempts tried, but reducing to a single question as suggested.

Basic setup w/ web-worker: https://pastebin.com/NgAPZzCX

Also on the pastebin is an attempt using a web-worker route , however seems it doesn't support DOM API , where p5.js functions are introduced. To solve this, tried doing some fancy regex to strip the code down to just the loops, but then you're missing variables, ie. if the loop count was loopCount instead of 10 .

Ultimate goal is getting a red flag if there's an infinite loop to prevent recompiling bad code that would overwrite what's currently running (live-coding environment). The web-worker route provided that and if I understand babel correctly, it wouldn't flag it, but actually changes the code being compiled to catch that infinite loop... is there yet another technique to consider or maybe a hybrid of it all?

I am working on a repl for my library and am already using babel standalone.

This question was spot-on for me as it helped me to solve the issue using the linked babel plugin from react.

if you declare somewhere your plugin 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)
        }
      },
    },
  }
}

then it is simple to add it to babel standalone

update your pastebin example: (this is a guess, I have not tested it)

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

I am using es6, so my code does it this way:

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

This post helped me immensely, hope my comment helps someone else too

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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