如何检测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 加上最后自己的验证
Nov 04 Javascript
Colortip基于jquery的信息提示框插件在IE6下面的显示问题修正方法
Dec 06 Javascript
javascript文件中引用依赖的js文件的方法
Mar 17 Javascript
jQuery+jsp下拉框联动获取本地数据的方法(附源码)
Dec 03 Javascript
jquery日历插件datepicker用法分析
Jan 22 Javascript
jQuery的实例及必知重要的jQuery选择器详解
May 20 Javascript
jQuery简单注册和禁用全局事件的方法
Jul 25 Javascript
Jquery遍历select option和添加移除option的实现方法
Aug 26 Javascript
JS 设置Cookie 有效期 检测cookie
Jun 15 Javascript
JavaScript简单实现关键字文本搜索高亮显示功能示例
Jul 25 Javascript
Jquery使用each函数实现遍历及数组处理
Jul 14 jQuery
Node.js web 应用如何封装到Docker容器中
Sep 01 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快速统计某个数据库中每张表的数据量
2012/09/04 PHP
详解php的魔术方法__get()和__set()使用介绍
2012/09/19 PHP
php生成缩略图示例代码分享(使用gd库实现)
2014/01/20 PHP
PHP中in_array的隐式转换的解决方法
2018/03/06 PHP
PHP设计模式之装饰器模式定义与用法详解
2018/04/02 PHP
Aster vs Newbee BO5 第一场2.19
2021/03/10 DOTA
jQuery总体架构的理解分析
2011/03/07 Javascript
简单的前端js+ajax 购物车框架(入门篇)
2011/10/29 Javascript
JS无法捕获滚动条上的mouse up事件的原因猜想
2012/03/21 Javascript
JQuery插件Style定制化方法的分析与比较
2012/05/03 Javascript
原生Js实现简易烟花爆炸效果的方法
2015/03/20 Javascript
javascript实现五星评分功能
2015/11/10 Javascript
jQuery中的siblings用法实例分析
2015/12/24 Javascript
基于JS如何实现类似QQ好友头像hover时显示资料卡的效果(推荐)
2016/06/09 Javascript
AngularJS基础 ng-copy 指令实例代码
2016/08/01 Javascript
jquery做个日期选择适用于手机端示例
2017/01/10 Javascript
[01:29:42]Liquid vs VP Supermajor决赛 BO 第一场 6.10
2018/07/05 DOTA
利用Python破解验证码实例详解
2016/12/08 Python
解决出现Incorrect integer value: '' for column 'id' at row 1的问题
2017/10/29 Python
对Python 获取类的成员变量及临时变量的方法详解
2019/01/22 Python
Python内置random模块生成随机数的方法
2019/05/31 Python
Python变量访问权限控制详解
2019/06/29 Python
python之pexpect实现自动交互的例子
2019/07/25 Python
django 实现将本地图片存入数据库,并能显示在web上的示例
2019/08/07 Python
浅析python,PyCharm,Anaconda三者之间的关系
2019/11/27 Python
django框架F&Q 聚合与分组操作示例
2019/12/12 Python
Python count函数使用方法实例解析
2020/03/23 Python
pandas分批读取大数据集教程
2020/06/06 Python
python获取linux系统信息的三种方法
2020/10/14 Python
香港百佳网上超级市场:PARKNSHOP.com
2020/06/10 全球购物
工程管理英文求职信
2014/03/18 职场文书
学生会干部自我鉴定2014
2014/09/18 职场文书
普通党员自我剖析材料
2014/10/07 职场文书
会议开幕词
2015/01/28 职场文书
Python爬虫入门案例之爬取去哪儿旅游景点攻略以及可视化分析
2021/10/16 Python
利用Redis实现点赞功能的示例代码
2022/06/28 Redis