在循环中使用本机浏览器模式对话框会导致潜在的无限执行吗?

Could using native browser modal dialogs in a loop lead to potentially infinite execution?

我在 JSBin 上尝试了一些代码并得到了奇怪的结果。 应该可以工作 - 这是一个使用 Window.prompt 的简单循环。它确实使用 Stack Snippets 执行了正确的次数:

for (let i = 0; i < 3; i++) {
  console.log(`i: ${i}`);
  
  let foo = prompt('Enter anyting - it will be echoed.');
  
  console.log(`echo: ${foo}`);
}

on JSBin it only runs for one iteration。如果你打开浏览器控制台,有一个警告信息:

Exiting potential infinite loop at line 1. To disable loop protection: add "// noprotect" to your code

这让我想知道...什么潜在的无限循环?对我来说,似乎没有任何东西可以导致无限执行。关于代码的唯一“奇怪”之处是通过 prompt 的模态对话框。我尝试使用 Window.alert:

for (let i = 0; i < 3; i++) {
  console.log(`i: ${i}`);
  
  alert("maximum three alerts");
  let foo = "some input";
  
  console.log(`echo: ${foo}`);
}

the same thing happens on JSBin as before - 执行单循环时控制台中显示相同的警告。

删除模态对话框does lead to the loop executing normally

for (let i = 0; i < 3; i++) {
  console.log(`i: ${i}`);
  
  let foo = "some input";
  
  console.log(`echo: ${foo}`);
}

那么,JSBin 使用的分析 是否正确 具有模态对话框会导致无限循环,如果是的话 - 如何以及何时会发生?或者这只是误报?

问题不在于您正在使用浏览器的对话框创建无限循环,JSBin 用于执行脚本的库使用超时作为启发式方法来检查无限循环。

查看控制台,我们可以看到此超时定义在 runner.js. The GitHub repo for JSBin actually explains how this is done (render.js):

// Rewrite loops to detect infiniteness.
// This is done by rewriting the for/while/do loops to perform a check at
// the start of each iteration.

不幸的是,我没能找到重写循环的代码,但它很可能会重写你的循环,使其看起来像

let loopStart = Date.now();

for (let i = 0; i < 3; i++) {
  if ((Date.now() - loopStart) >= MAX_LOOP_DURATION) {
    loopProtect.hit();

    break;
  }

  console.log(`i: ${i}`);

  let foo = prompt('Enter anyting - it will be echoed.');

  console.log(`echo: ${foo}`);
}