如何检测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 相关文章推荐
JS网络游戏-(模拟城市webgame)提供的一些例子下载
Oct 14 Javascript
javascript使用onclick事件改变选中行的颜色
Dec 30 Javascript
第一次接触神奇的Bootstrap表单
Jul 27 Javascript
javascript中href和replace的比较(详解)
Nov 25 Javascript
Vue组件开发初探
Feb 14 Javascript
webpack 打包压缩js和css的方法示例
Mar 20 Javascript
js实现前面自动补全位数的方法
Oct 10 Javascript
webpack 静态资源集中输出的方法示例
Nov 09 Javascript
详解Vue3.0 前的 TypeScript 最佳入门实践
Jun 18 Javascript
JavaScript常用内置对象用法分析
Jul 09 Javascript
JavaScript变量基本使用方法实例分析
Nov 15 Javascript
详细谈谈JavaScript中循环之间的差异
Aug 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
BBS(php & mysql)完整版(八)
2006/10/09 PHP
PHP 高手之路(三)
2006/10/09 PHP
Windows下XDebug 手工配置与使用说明
2010/07/11 PHP
PHP中使用匿名函数操作数据库的例子
2014/11/17 PHP
php实现登陆模块功能示例
2016/10/20 PHP
php获取开始与结束日期之间所有日期的方法
2016/11/29 PHP
浅谈ThinkPHP5.0版本和ThinkPHP3.2版本的区别
2017/06/17 PHP
PHP信号处理机制的操作代码讲解
2019/04/19 PHP
JavaScript中两个感叹号的作用说明
2011/12/28 Javascript
JS+CSS实现一个气泡提示框
2013/08/18 Javascript
js字符串转换成数字与数字转换成字符串的实现方法
2014/01/08 Javascript
jquery自定义滚动条插件示例分享
2014/02/21 Javascript
jQuery的缓存机制浅析
2014/06/07 Javascript
jQuery截取指定长度字符串代码
2014/08/21 Javascript
javascript操作数组详解
2014/12/17 Javascript
JS实现文字放大效果的方法
2015/03/03 Javascript
详解JavaScript中Date.UTC()方法的使用
2015/06/12 Javascript
Javascript DOM事件操作小结(监听鼠标点击、释放,悬停、离开等)
2017/01/20 Javascript
jQueryUI Sortable 应用Demo(分享)
2017/09/07 jQuery
python中使用百度音乐搜索的api下载指定歌曲的lrc歌词
2014/07/18 Python
Python制作爬虫抓取美女图
2016/01/20 Python
pip安装时ReadTimeoutError的解决方法
2018/06/12 Python
Python集中化管理平台Ansible介绍与YAML简介
2019/06/12 Python
pandas条件组合筛选和按范围筛选的示例代码
2019/08/26 Python
浅谈Python类中的self到底是干啥的
2019/11/11 Python
Django ValuesQuerySet转json方式
2020/03/16 Python
django迁移文件migrations的实现
2020/03/31 Python
python数据分析工具之 matplotlib详解
2020/04/09 Python
利用HTML5中的Canvas绘制一张笑脸的教程
2015/05/07 HTML / CSS
香奈儿美国官网:CHANEL美国
2020/05/20 全球购物
Ajax和javascript的区别
2013/07/20 面试题
前台文员的岗位职责
2013/11/14 职场文书
机械制造专业大学生自我鉴定
2014/09/19 职场文书
委托公证书格式
2015/01/26 职场文书
学术会议邀请函
2015/01/30 职场文书
Nginx下SSL证书安装部署步骤介绍
2021/12/06 Servers