我们先看一下C/C++和java的调试原理
C/C++调试原理:目前比较流行的调试工具是 GDB 和微软的 Visual Studio 自带的 debugger,在这种 debugger 中,首先,需要编译一个“ debug ”模式的程序,将调试语句编译到该程序中。其次,在调试过程中,debugger 将会深层接入程序的运行,掌握和控制运行态的一些信息,并将这些信息及时返回。
Java调试原理:Java的调试使用Java 虚拟机工具接口(Java Virtual Machine Tool Interface,JVMTI)提供的调试接口。包括进入一个函数,进入一个语句的事件,得到当前上下文的API等等,你只要注册了这些事件,调用这些API即可。
从上面可以看出,调试的方式主要有两种,一种是自己写编辑,在目标文件中加入调试代码,由调试代码来做调试工作,另一种是运行该语言的容器本身提供了调试接口。
我们再来看javascript的调试。
目前的javascript调试工具也是用的第二种调试方式,IE和firefox分别提供了javascript的调试接口。
以firefox为例,它提供的调试接口是:jsdIDebuggerService,我们可以向它注入一些调试的钩子,来实现调试,它提供的调试钩子主要有:
钩子类 | 说明 |
breakpointHook | Called when the engine encounters a breakpoint. |
debuggerHook | Called when the engine encounters the debugger keyword. |
debugHook | Called when the errorHook returns false. |
errorHook | Called when an error or warning occurs. |
functionHook | Called before and after a function is called. |
interruptHook | Called before the next PC is executed. |
scriptHook | Called when a jsdIScript is created or destroyed. |
throwHook | Called when an exception is thrown (even if it will be caught.) |
topLevelHook | Called before and after a toplevel script is evaluated. |
包括firebug,venkman,ATF,aptana等调试工具都是实现这些钩子类来做调试的,譬如要做错误定位,就要实现errorHook,errorHook有一个方法
onError(message, fileName, lineNo, pos, flags, errnum, exc)就给出了错误信息,错误文件,行号,位置,等信息。只要向jsdIDebuggerService上注册errorHook,firefox发生js错误时就会调用该方法。
这种调试技术目前已经成熟,但是却都是只能在单个浏览器上调试,我们要在其它浏览器上调试还是比较困难的。
开源项目Javascript Debug Toolkit用另一种原理做了跨浏览器调试javascript的工具,和C/C++的调试一样,它先把javascript编译为带调试代码的目标文件,在浏览器中运行,只要这些调试代码能够做到跨浏览器,整个调试工具就能跨浏览器了。
我们看一下Javascript Debug Toolkit是如何工作的。来看一个例子。
源代码 |
function test(a,b){ var c = a + b; return c; } |
目标调试代码 |
jsdebug("test.js",1);function test(a,b){ jsdebug("test.js",2); var c = a + b; jsdebug("test.js",3); return c; jsdebug("test.js",4);} |
这样在每一行代码执行前都会调用jsdebug函数,该函数可以向调试服务器发调试通知,可以把当前的context传给调试服务器,调试服务器与调试代码进行交互(通过ajax技术),包括单步执行,跟进,跟出等都会可以实现。
这种技术的最大好处就是跨浏览器,目前已经能够在ie,firefox,safari,chrome,opera以及一些掌机浏览器上调试javascript。相信这种技术也会很快被使用起来,会有更多跨浏览器的javascript调试工具出现。
javascript调试原理(一)中讲了javascript的调试原理,本单给出一个javascript调试的客户端模拟实现:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> </HEAD> <BODY> <textarea id="jsstr" readonly style="width:400px;height:200px"> function test(){ var a = test1(); var b = test2(); var c = "result is " + a + b; alert(c); } function test1(){ return "test1-->abc"; } function test2(){ return "test2-->abc"; } test(); </textarea> <div id="result"> </div> <script> var debugStr = ""; function jsdebug(resource,line,evalFunc){ var lines = debugStr.split("\n"); var jsLine = lines[line-1]; lines[line-1] = "当前行:--->" + jsLine; var arr = [ "调试代码:", lines.join("\n") ]; var result = document.getElementById("result"); result.innerHTML = result.innerHTML + "<br>执行到第" + line + "行: -->" + jsLine; alert(arr.join("\n")); } function debug(str){ var lines = str.split("\n"); debugStr = str; var codes = []; for(var i=0;i<lines.length;i++){ codes[i] = "jsdebug('test'," + (i+1) + ",function(text){return eval(text)});" + lines[i]; } eval(codes.join('\n')); } debug(document.getElementById('jsstr').value); </script> </BODY> </HTML>
只要把其中的alert换成同步的ajax请求,一可以实现每句执行时把当前的行号,context等 信息传给调试服务器。
Javascript Debug Toolkit的客户端原理是在这个基础上的,下一篇将展开讲一下这种原理会遇到的问题及解决方法。
javascript调试原理(二)中给出一个模拟客户端调试的例子,在客户端有两个问题:
1.如何获得当前的context?
2.如何做resume,stepinto,stepreturn,stepover?
本章围绕着这两个问题展开讨论
1.如何获得当前的context
我们先看一段代码:
function test(){ this.a = "a"; var b = "b"; }
那么在进入test之后,如何获得a和b的值呢?
a的值比较简单,只要把this传过去,通过for...in语句就可以获得,但是b呢?它相当于一个私有变量,在外面是不能访问的,要访问b只能通过在b所在的作用域中获得,因此我们在插入前面的每一行中要加上一个eval函数,eval函数的作用域是当前行的,所以可以获得当前行的上下文。所以在第二章中才会在每一行加上
function(text){try{return eval(text)}catch(e){}});
我们把a,b,c加上看一下效果
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> </HEAD> <BODY> <textarea id="jsstr" readonly style="width:400px;height:200px">function test(){ var a = test1(); var b = test2(); var c = "result is " + a + b; alert(c); } function test1(){ return "test1-->abc"; } function test2(){ return "test2-->abc"; } test();</textarea> <div id="result"> </div> <script> var debugStr = ""; function jsdebug(resource,line,evalFunc){ var lines = debugStr.split("\n"); var jsLine = lines[line-1]; lines[line-1] = "当前行:--->" + jsLine; var arr = [ "调试代码:", lines.join("\n"), "==========context===========", "a = " + evalFunc("a"), "b = " + evalFunc("b"), "c = " + evalFunc("c"), ]; var result = document.getElementById("result"); result.innerHTML = result.innerHTML + "<br>执行到第" + line + "行: -->" + jsLine; alert(arr.join("\n")); } function debug(str){ var lines = str.split("\n"); debugStr = str; var codes = []; for(var i=0;i<lines.length;i++){ codes[i] = "jsdebug('test'," + (i+1) + ",function(text){try{return eval(text)}catch(e){}});" + lines[i]; } eval(codes.join('\n')); } debug(document.getElementById('jsstr').value); </script> </BODY> </HTML>
在执行到第3,4,5行的时候可以看到a,b,c的值
这里又有一个问题:我怎么知道函数中有哪些变量?
这就要用到arguments.callee.caller了,把函数当成一个字条串解析,解析出函数的输入参数及定义的变量,就能拿到一个变量名的集合,然后再一个一个地取值。具体的算法这里就不给出了。
再说第二个问题,如何控制stepinto,stepreturn,resume
我们需要在客户端维护一个函数的调用栈,这个栈中记录着每一步的调用,在执行的时候根据栈中存的信息和当前的上下文比较,就能拿到当前语句究竟是stepover还是stepinto还是stepreturn。
那么如何做resume呢,客户端维护一份断点列表,执行每一句的时候判断是否到了断点,不在断点就继续执行,到了断点就停止。
这部分内容也不再给出详细代码,请参照Javascript Debug Toolkit的源代码
开源项目--跨浏览器的javascript调试工具Javascript Debug Toolkit(jsdt)
http://code.google.com/p/jsdt/
jsdt是一个eclipse的插件,要求在eclipse3.2,jre1.5以上运行,可以进行跨浏览器的javascript调试。
jsdt在eclipse中设置断点,在浏览器中运行,执行到断点时自行中断到调试器
jsdt可以单步调试,可以查看当前函数的context
jsdt可跨浏览器调试,目前的浏览器ie,firefox,safari,chrome都支持,其中,因为chrome的bug,css和image不能正常显示
调试的效果图如下:
设置断点
中断
stepOver
stepInto
stepReturn
jsdt包含以下几个部分
1.js引擎,基于rhino引擎,解析js,确定哪一行可以加断点,哪一行不能加断点
2.jsdt server,是一个http服务器,接管客户端的所有请求
3.jsdt client,客户端引擎
4.jsdt debug implement,实现了一套eclipse插件的接口和ui,譬如设置断点等。
jsdt的基本原理如下:
1.jsdt提供一个http代理,把要访问的文件或url的地址转换成jsdt的server地址
2.jsdt的server在送给浏览器的每一行javascript代码前加上调试的代码,该调试代码发送ajax请求到jsdt的server,将当前的上下文送给jsdt
3.jsdt根据上下文在eclipse中中断,显示上下文等。
4.jsdt根据用户的指令(resume,stepinto,stepover,stepreturn)等回答ajax请求
5.jsdt的客户端引擎根据server发的指令进行下一步操作
原文转载自:http://www.iteye.com/topic/299025
相关推荐
day13-javascript调试原理.md
JavaScript调试技术是开发过程中不可或缺的一环,特别是在复杂的前端应用中,有效的调试手段能极大地提高开发效率,找出并修复隐藏的错误...不过,理解基本的JavaScript调试原理和技巧,无论使用哪种工具都能事半功倍。
为了解决这个问题,出现了专门针对IE的JavaScript调试工具,例如“IE插件 JavaScript 调试工具”。这款插件允许开发者更高效地定位和修复JavaScript代码中的错误,提高开发效率。 JavaScript调试工具通常具备以下...
本文介绍了如何创建一个简易的JavaScript调试包(Debug包),名为jscript.debug.js,该调试包的主要功能包括对象属性的遍历显示以及灵活的日志记录系统。下面将详细阐述这两个功能的实现原理和使用方法。 首先,...
JavaScript调试工具是开发JavaScript应用程序时不可或缺的利器,它们帮助开发者追踪代码执行流程,查找并修复错误,提升代码质量。在众多的JavaScript调试工具中,有一种备受推崇,它提供了丰富的功能和友好的用户...
了解和处理JavaScript运行时可能出现的错误,如TypeError、RangeError等,以及如何利用console工具、断点和debugger语句进行程序调试,对于开发过程中的问题排查至关重要。 八、DOM操作与事件处理 在Web开发中,...
JavaScript是Web开发中的核心语言,而Firebug是早期开发者们...虽然现在有更多现代的开发者工具,如Chrome DevTools和Firefox Developer Tools,但了解并掌握Firebug的使用方法,对于理解前端调试原理仍然大有裨益。
JavaScript检测是否开启了控制台(调试工具) 测试后在chrome有效 不少人防止别人趴源码,一般采用检测按键F12之类的,但是这些基本没什么用 现在介绍一个方法,非常管用,可以检测到你是否开启了控制台程序,可以...
Firebug的JavaScript调试功能是其核心特色之一。它支持以下操作: - **设置断点**:在代码中设置断点,控制代码执行流程,便于逐行检查。 - **查看调用栈**:显示当前执行上下文,了解函数调用顺序。 - **变量监视*...
JavaScript 工具库如jQuery、React、Vue等,它们的核心原理在于对JavaScript原生API的封装和优化,提供了诸如DOM操作、事件处理、动画效果、Ajax请求等常用功能,同时引入模块化、异步编程和面向对象或函数式编程的...
而 "install-companionjs-v0.5.exe" 则是核心的JavaScript调试工具,版本号为v0.5,这表明它是一个经过多次改进的版本,旨在提高调试效率和用户体验。 install-companionjs 是一个专门为IE7设计的JavaScript调试...
JavaScript是Web开发中...以上只是JavaScript核心原理的一部分,深入学习还包括ES规范的新特性和最佳实践,以及性能优化、调试技巧等内容。理解并熟练运用这些知识点,将有助于提升你在JavaScript开发领域的专业素养。
本资源"JavaScript核心原理解析"旨在深入探讨JavaScript的核心概念和技术,帮助开发者掌握其内在机制,从而更好地运用和优化代码。以下是对该资源内容的详细解析: 1. **变量与数据类型** - JavaScript 是动态类型...
3. install-companionjs-v0.5.5.exe:这个文件名看起来像是一个JavaScript调试的伴侣工具的安装程序,可能是一个第三方插件或扩展,用于增强IE的JavaScript调试能力。"v0.5.5"表示该工具的版本号,说明它是经过多次...
8. **错误处理与调试**:学习如何有效地处理JavaScript和Ajax请求中的错误,以及使用浏览器的开发者工具进行调试,是提升开发效率和代码质量的重要环节。 9. **jQuery与Ajax**:jQuery是一个流行的JavaScript库,...
现代JavaScript教程是一个全面的学习资源,旨在帮助开发者深入理解JavaScript这一重要的编程语言。JavaScript,作为Web开发的核心技术之一,被广泛用于构建交互式的网页和应用程序。本教程覆盖了从基础概念到高级...
第一部分讨论一般性的 JavaScript主题,包括 JavaScript的简史、好的编码习惯、调试技巧和工具等;第二部分是 10个具体项目,每一章都会提出一个不同的应用,分析其内在的工作原理,然后提供能够提高读者技巧的练习...
* JavaScript的错误处理和调试 * JavaScript的编程风格和best practice 阮一峰JavaScript教程是一本系统和全面的JavaScript教程,涵盖了JavaScript语言的核心语法和各种应用场景,适合初学者和中级开发者使用。
JavaScript作用域原理是编程中的重要概念,它关乎变量的可见性、生命周期以及代码组织。本文将深入探讨JavaScript的作用域机制,特别是预编译的概念。在理解这些知识点之前,建议先回顾一下JavaScript的基础语法。 ...