如何检测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知识点整理
Jan 30 Javascript
js实现鼠标划过给div加透明度的方法
May 25 Javascript
如何实现移动端浏览器不显示 pc 端的广告
Oct 15 Javascript
Javascript的比较汇总
Jul 25 Javascript
Highcharts学习之数据列
Aug 03 Javascript
Angularjs CURD 详解及实例代码
Sep 14 Javascript
jquery精度计算代码 jquery指定精确小数位
Feb 06 Javascript
AngularJs 延时器、计时器实例代码
Sep 16 Javascript
JS实现的3des+base64加密解密算法完整示例
May 18 Javascript
详解Vue Elementui中的Tag与页面其它元素相互交互的两三事
Sep 25 Javascript
基于layui实现高级搜索(筛选)功能
Jul 26 Javascript
关于vue的列表图片选中打钩操作
Sep 09 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中使用Oracle数据库(5)
2006/10/09 PHP
php var_export与var_dump 输出的不同
2013/08/09 PHP
PHP堆栈调试操作简单示例
2018/06/15 PHP
ext 同步和异步示例代码
2009/09/18 Javascript
jQuery.extend 函数的详细用法
2012/06/27 Javascript
改变文件域的样式实现思路同时兼容ie、firefox
2013/10/23 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
基于jQuery实现简单的折叠菜单效果
2015/11/23 Javascript
JS判断是否长按某一键的方法
2016/03/02 Javascript
BootStrap Fileinput的使用教程
2016/12/30 Javascript
Node.js中用D3.js的方法示例
2017/01/16 Javascript
ionic2 tabs 图标自定义实例
2017/03/08 Javascript
js实现股票实时刷新数据案例
2017/05/14 Javascript
Nodejs + Websocket 指定发送及群聊的实现
2020/01/09 NodeJs
如何基于filter实现网站整体变灰功能
2020/04/17 Javascript
[02:40]DOTA2超级联赛专访430 从小就爱玩对抗性游戏
2013/06/18 DOTA
[03:10]2014DOTA2 TI马来劲旅Titan首战告捷目标只是8强
2014/07/10 DOTA
[01:09]2014DOTA2国际邀请赛 TI4西雅图DOTA2 中国美女coser加油助威
2014/07/20 DOTA
[01:06]DOTA2小知识课堂 Ep.01 TP出门不要忘记帮队友灌瓶哦
2019/12/05 DOTA
Python urls.py的三种配置写法实例详解
2017/04/28 Python
python shell根据ip获取主机名代码示例
2017/11/25 Python
解决Tensorflow使用pip安装后没有model目录的问题
2018/06/13 Python
python获取中文字符串长度的方法
2018/11/14 Python
python实现简单图片物体标注工具
2019/03/18 Python
python将字符串转变成dict格式的实现
2019/11/18 Python
通过实例简单了解Python sys.argv[]使用方法
2020/08/04 Python
如何在python中实现线性回归
2020/08/10 Python
美国翻新电子产品商店:The Store
2019/10/08 全球购物
输入N,打印N*N矩阵
2012/02/20 面试题
节能减排倡议书
2014/04/15 职场文书
关于青春的演讲稿
2014/05/05 职场文书
煤矿安全生产标语
2014/06/06 职场文书
升职自荐信范文
2015/03/27 职场文书
pytorch 中nn.Dropout的使用说明
2021/05/20 Python
Nginx设置HTTPS的方法步骤 443证书配置方法
2022/03/21 Servers
Python进程间的通信之语法学习
2022/04/11 Python