如何检测JavaScript中的死循环示例详解


Posted in Javascript onAugust 30, 2020

前言

如果我们需要执行用户写的代码,如和避免死循环?我们最近遇到了这个问题,因为写错代码很常见,所以我们进行了一下尝试。

如何检测JavaScript中的死循环示例详解

首先我们需要使用iframe

这主要是安全考虑,我们需要一个sandbox环境来执行JavaScript,避免影响到整体。iframe的sandbox属性可以用来禁止弹窗等等,非常有用。

地址可以选择Blob url,不过blob url会持有当前web page的origin,如果用户拷贝一些乱七八糟的代码不小心执行的话,会有安全问题。所以最终决定用data URI。

iframe的执行仍然在同一个thread

iframe中执行了代码,发生死循环的时候,浏览器还是死掉了,因为iframe和parent还是在同一个thread。也就是说,我们无法在parent中进行timeout检测,因为检测代码在死循环发生时永远不会被执行。

Web Worker可行但不支持DOM API

如果是纯粹的JavaScript代码,或许用web worker可以,但是我们需要DOM API,所以Web Worker也不在考虑范围之中。

看来只能修改用户代码了

假设大多数死循环都是由while/for引起的,如果我们能插入一些代码并在每一次循环中进行检测,我们也许就可以根据某些条件提前终止循环。

比如这样的代码

function abc() {
 while (true) {
  console.log(Date.now())
 }
}

如果我们插入一个 __detectInfiniteLoop() 方法,并在while loop里面调用的话,就可以在loop 10000次的时候报错终止执行。

let __count = 0
const __detectInfiniteLoop = () => {
 if (__count > 10000) {
  throw new Error('Infinite Loop detected')
 }
 __count += 1
}

function abc() {
 while (true) {
  console.log(Date.now())
  __detectInfiniteLoop()
 }
}

操作AST在合适位置插入代码

通过字符串匹配来编辑代码细节太复杂容易出错,我们可以用编辑AST的方式,实际上非常简单。

用到babel的3个package。

  1. @babel/parser - parse 代码为AST
  2. @babel/traverse - 搜索 for/while loop
  3. @babel/generator - 生成插入后的代码

首先 parse用户的代码为AST

import { parse } from '@babel/parser'
const ast = parse(code)

然后我们准备一下需要插入的代码。

代码有两部分,第一部分是function定义,实际上可以在头部插入,所以字符串就够了。第二部分是function的调用,这部分需要插入到AST中,所以也需要parse一下。

const prefix = `
 let __count = 0
 const __detectInfiniteLoop = () => {
  if (__count > 10000) {
   throw new Error('Infinite Loop detected')
  }
  __count += 1
 }
`

const detector = parse(`__detectInfiniteLoop()`)

接下来就找到 while/for/do..while 的位置,然后插入detector的调用。

import traverse from '@babel/traverse'
traverse(ast, {
 ForStatement: function (path) {
  path.node.body.body.push(...detector.program.body)
 },
 WhileStatement: function (path) {
  path.node.body.body.push(...detector.program.body)
 },
 DoWhileStatement: function (path) {
  path.node.body.body.push(...detector.program.body)
 }
})

AST修改好了,最后一步就是生成最终的代码,然后放到iframe中执行。

import generate from '@babel/generator'
const newCode = prefix + generate(ast).code

如何检测JavaScript中的死循环示例详解

如愿以偿!撒花!

最后

这个方法不是完美的,不过满足了我们自己的需求。你可以根据需要进行一下调整。

到此这篇关于如何检测JavaScript中的死循环的文章就介绍到这了,更多相关检测JavaScript死循环内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
基于jQuery的固定表格头部的代码(IE6,7,8测试通过)
May 18 Javascript
javascript full screen 全屏显示页面元素的方法
Sep 27 Javascript
jQuery实现表格颜色交替显示的方法
Mar 09 Javascript
基于jquery实现省市区三级联动效果
Dec 25 Javascript
一次$.getJSON不执行的简单记录
Jul 19 Javascript
js 性能优化之算法和流程控制
Feb 15 Javascript
JS三目运算(三元运算)方法详解
Mar 01 Javascript
基于jQuery实现瀑布流页面
Apr 11 jQuery
详解js删除数组中的指定元素
Oct 31 Javascript
CryptoJS中AES实现前后端通用加解密技术
Dec 18 Javascript
js核心基础之构造函数constructor用法实例分析
May 11 Javascript
Express结合Webpack的全栈自动刷新
May 23 Javascript
JavaScript中CreateTextFile函数
Aug 30 #Javascript
详解vue组件之间的通信
Aug 30 #Javascript
如何阻止移动端浏览器点击图片浏览
Aug 29 #Javascript
JavaScript事件委托实现原理及优点进行
Aug 29 #Javascript
JS如何判断对象是否包含某个属性
Aug 29 #Javascript
JS获取当前时间戳方法解析
Aug 29 #Javascript
JS PHP字符串截取函数实现原理解析
Aug 29 #Javascript
You might like
php部分常见问题总结
2008/03/27 PHP
hadoop常见错误以及处理方法详解
2013/06/19 PHP
PHP 匿名函数与注意事项详细介绍
2016/11/26 PHP
php workerman定时任务的实现代码
2018/12/23 PHP
使用PHP开发留言板功能
2019/11/19 PHP
jQuery的强大选择器小结
2009/12/27 Javascript
jquery全选/全不选/反选另一种实现方法(配合原生js)
2013/04/07 Javascript
jQuery简易图片放大特效示例代码
2014/06/09 Javascript
javascript实现阻止iOS APP中的链接打开Safari浏览器
2014/06/12 Javascript
JavaScript导出Excel实例详解
2014/11/25 Javascript
node.js中的fs.lstat方法使用说明
2014/12/16 Javascript
JavaScript动态添加列的方法
2015/03/25 Javascript
js实现String.Fomat的实例代码
2016/09/02 Javascript
教你用十行node.js代码读取docx的文本
2017/03/08 Javascript
微信小程序城市选择及搜索功能的方法
2019/03/22 Javascript
vue实现标签云效果的方法详解
2019/08/28 Javascript
vue+vant-UI框架实现购物车的复选框全选和反选功能
2019/11/05 Javascript
Vue props中Object和Array设置默认值操作
2020/07/30 Javascript
[57:41]Secret vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python完全新手教程
2007/02/08 Python
Python读写txt文本文件的操作方法全解析
2016/06/26 Python
Python实现读取Properties配置文件的方法
2018/03/29 Python
Python 使用PIL numpy 实现拼接图片的示例
2018/05/08 Python
python 自定义对象的打印方法
2019/01/12 Python
Python实现SQL注入检测插件实例代码
2019/02/02 Python
python 多进程并行编程 ProcessPoolExecutor的实现
2019/10/11 Python
Python实现i人事自动打卡的示例代码
2020/01/09 Python
windows下Pycharm安装opencv的多种方法
2020/03/05 Python
Python中openpyxl实现vlookup函数的实例
2020/10/28 Python
大学毕业生简单自荐信
2013/11/05 职场文书
总经理助理职责
2014/02/04 职场文书
护士求职自荐信范文
2014/03/19 职场文书
公司周年庆典标语
2014/10/07 职场文书
婚礼女方父母答谢词
2015/01/04 职场文书
女儿满月酒致辞
2015/07/29 职场文书
关于html选择框创建占位符的问题
2021/06/09 HTML / CSS