SlideShare ist ein Scribd-Unternehmen logo
1 von 43
Downloaden Sie, um offline zu lesen
Wind.js
⽆无障碍调试与排错
   赵劼 - 2012.9
关于我
• 赵劼 / ⽼老赵 / Jeffrey Zhao / 赵姐夫
• ⽇日写代码三百⾏行,不辞⻓长作程序员
• 博客:http://blog.zhaojie.me/
• 微博:@⽼老赵
• F#, JavaScript, Scala, C#, Python, .NET, Mono...
• 痛恨Java语⾔言
Wind.js

• eval后的代码⽆无法调试?
• 混淆后的代码不易理解?
• 堆栈信息混乱?
eval代码调试
代码调试

• 很久很久以前:alert
• 过了⼀一段时间:console.log
• 其实从IE 5时代开始便可以调试代码
两个问题


• eval出来的代码可以调试吗?
• Node.js可以调试吗?
调试eval的代码

• 代码末尾://@	
  sourceUrl=<path>
• ⽀支持浏览器
 •   Chrome
 •   Safari
 •   Firefox (Firebug)
调试Node.js代码

• Eclipse
• Eclipse Debugger Plugin for V8
• 启动程序
 • node	
  -­‐-­‐debug[=port]	
  app.js
 • node	
  -­‐-­‐debug-­‐brk[=port]	
  app.js


                                        Using Eclipse as Node Applications Debugger
调试混淆代码
调试混淆代码
格式化以后
配合Source Map
Source Map

• 记录⺫⽬目标代码到源代码的映射
• JSON格式 + 编码后的映射数据
• Source Map V3 Spec
Source Map

  • 记录⺫⽬目标代码到源代码的映射
  • JSON格式 + 编码后的映射数据
  • Source Map V3 Spec
脚本末尾加上://@	
  sourceMappingURL=<path>,或
脚本请求头加上:X-­‐SourceMap:	
  <path>
深⼊入Source Map
Source Map V3
{
	
  	
  	
  	
  "version":	
  3,
	
  	
  	
  	
  "file":	
  "all.min.js",
	
  	
  	
  	
  "lineCount":	
  37,
	
  	
  	
  	
  "sources":	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  "wind-­‐core.js",
	
  	
  	
  	
  	
  	
  	
  	
  "wind-­‐builderbase.js",
	
  	
  	
  	
  	
  	
  	
  	
  "wind-­‐async.js",
	
  	
  	
  	
  	
  	
  	
  	
  "sorting-­‐animations.aot.js"
	
  	
  	
  	
  ],
	
  	
  	
  	
  "names":	
  [	
  "Wind",	
  "_",	
  "isArray",	
  "obj",	
  ...	
  ],
	
  	
  	
  	
  "mappings":	
  "AAAC,SAAS,EAAG,CAGT,IAAIA,	
  ..."
}
解码 mappings 字段

• ⽤用分号区分“⾏行”,逗号区分“段”。
• Base64 Variable-Length Quantity 编码
• 节省空间,⽐比V2节省50%左右
确定代码⾏行号

AABBC;	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  第1⾏行
KAUYM,GAKoEF;	
  	
  //	
  第2⾏行
CCDD,	
  ...;	
  	
  	
  	
  	
  //	
  第3⾏行
...
...
Base64 VLQ解码
KAUYM,GAKoEF
Base64 VLQ解码
KAUYM,GAKoEF
        >>




[10,	
  0,	
  20,	
  24,	
  12],	
  [6,	
  0,	
  10,	
  40,	
  4,	
  5]
Base64 VLQ解码
KAUYM,GAKoEF
        >>




[10,	
  0,	
  20,	
  24,	
  12],	
  [6,	
  0,	
  10,	
  40,	
  4,	
  5]
        >>




[001010,	
  000000,	
  010100,	
  011000,	
  001100],	
  
[000110,	
  000000,	
  001010,	
  101000,	
  000100,	
  000101]
Base64 VLQ解码
KAUYM,GAKoEF
        >>




[10,	
  0,	
  20,	
  24,	
  12],	
  [6,	
  0,	
  10,	
  40,	
  4,	
  5]
        >>




                                            最低N-­‐1位为数据位
[001010,	
  000000,	
  010100,	
  011000,	
  001100],	
  
                                   01000,	
  	
  00100
[000110,	
  000000,	
  001010,	
  101000,	
  000100,	
  000101]
                                          最⾼高位表⽰示是否“连接后续数据”
Base64 VLQ解码
KAUYM,GAKoEF
        >>




[10,	
  0,	
  20,	
  24,	
  12],	
  [6,	
  0,	
  10,	
  40,	
  4,	
  5]
        >>




                                            最低N-­‐1位为数据位
[001010,	
  000000,	
  010100,	
  011000,	
  001100],	
  
                                   01000,	
  	
  00100
[000110,	
  000000,	
  001010,	
  101000,	
  000100,	
  000101]
                                          最⾼高位表⽰示是否“连接后续数据”
        >>




[1010,	
  0,	
  10100,	
  11000,	
  1100],	
  
[110,	
  0,	
  1010,	
  10001000,	
  101]
数据解码
[1010,	
  0,	
  10100,	
  11000,	
  1100],	
  
[110,	
  0,	
  1010,	
  10001000,	
  101]
数据解码
[1010,	
  0,	
  10100,	
  11000,	
  1100],	
  
[110,	
  0,	
  1010,	
  10001000,	
  101]
            最⾼高N-­‐1位为数据位              最低位为符号位
数据解码
[1010,	
  0,	
  10100,	
  11000,	
  1100],	
  
[110,	
  0,	
  1010,	
  10001000,	
  101]
               最⾼高N-­‐1位为数据位                    最低位为符号位
     >>




[5,	
  0,	
  10,	
  12,	
  6],	
  [3,	
  0,	
  5,	
  68,	
  -­‐2]
数据解码
[1010,	
  0,	
  10100,	
  11000,	
  1100],	
  
[110,	
  0,	
  1010,	
  10001000,	
  101]
               最⾼高N-­‐1位为数据位                    最低位为符号位
     >>




[5,	
  0,	
  10,	
  12,	
  6],	
  [3,	
  0,	
  5,	
  68,	
  -­‐2]
     >>




[5,	
  0,	
  10,	
  12,	
  6],	
  [8,	
  0,	
  15,	
  80,	
  4]
含义

//	
  已确定⾏行号
[
	
  5,	
  	
  	
  //	
  列号
	
  0,	
  	
  	
  //	
  源⽂文件,从sources查找
	
  10,	
  	
  //	
  源⽂文件内⾏行号
	
  12,	
  	
  //	
  源⽂文件内列号
	
  6	
  	
  	
  	
  //	
  源⽂文件内标⽰示符,从names查找
]
⽆无需⼿手动分析

• Google Closure Compiler可以⽣生成V2版
 Source Map格式,未编码的明⽂文数据

• 使⽤用Mozilla的SourceMap项⺫⽬目读取或⽣生成
 Source Map⽂文件
堆栈定位
传统JS错误堆栈
    128:   var baz = function () {
    129:       throw new Error("Hello World");
    130:   };
    131:
    132:   var bar = function () {
    133:       baz();
    134:   };
    135:
    136:   var foo = function () {
    137:       bar();
    138:   };
    139:
    140:   foo();
传统JS错误堆栈
                                            128:   var baz = function () {
                                            129:       throw new Error("Hello World");
                                            130:   };
                                            131:
                                            132:   var bar = function () {
                                            133:       baz();
                                            134:   };
                                            135:
                                            136:   var foo = function () {
                                            137:       bar();
                                            138:   };
                                            139:
Error: Hello World
                                            140:  foo();
    at baz (.../test.js:129:11)
    at bar (.../test.js:133:5)
    at foo (.../test.js:137:5)
    at Object.<anonymous> (.../test.js:140:1)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    ...
传统JS错误堆栈
                                            128:   var baz = function () {
                                            129:       throw new Error("Hello World");
                                            130:   };
                                            131:
                                            132:   var bar = function () {
                                            133:       baz();
                                            134:   };
                                            135:
                                            136:   var foo = function () {
                                            137:       bar();
                                            138:   };
                                            139:
Error: Hello World
                                            140:  foo();
    at baz (.../test.js:129:11)
    at bar (.../test.js:133:5)
    at foo (.../test.js:137:5)
    at Object.<anonymous> (.../test.js:140:1)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    ...
Wind.js错误堆栈
 128:   var test = eval(..., function () {
 129:        var a = null;
 130:        a.b();
 131:   }));
 132:
 133:   test().on("failure", function () {
 134:       console.log(this.error.stack);
 135:   }).start();
Wind.js错误堆栈
               128:   var test = eval(..., function () {
               129:        var a = null;
               130:        a.b();
               131:   }));
               132:
               133:   test().on("failure", function () {
               134:       console.log(this.error.stack);
               135:   }).start();



TypeError: Cannot call method 'b' of null
    at eval (wind/anonymous_0.js:6:37)
    at Object.BuilderBase.Delay.next (.../wind-async.js:143:46)
    at Object.AsyncBuilder.Start [as _delegate] (.../wind-async:652:22)
    at Object.Task.start (.../wind-async.js:196:22)
    at Object.<anonymous> (.../test.js:135:4)
    ...
Wind.js错误堆栈
               128:   var test = eval(..., function () {
               129:        var a = null;
               130:        a.b();
               131:   }));
               132:
               133:   test().on("failure", function () {
               134:       console.log(this.error.stack);
               135:   }).start();



TypeError: Cannot call method 'b' of null
    at eval (wind/anonymous_0.js:6:37) ???
             wind/anonymous_0.js:6:37
    at Object.BuilderBase.Delay.next (.../wind-async.js:143:46)
    at Object.AsyncBuilder.Start [as _delegate] (.../wind-async:652:22)
    at Object.Task.start (.../wind-async.js:196:22)
    at Object.<anonymous> (.../test.js:135:4)
    ...
指向⺫⽬目标堆栈
01:   /* function () { */    (function () {
02:                              var _builder_$0 = Wind.builders["async"];
03:                              return _builder_$0.Start(this,
04:                                  _builder_$0.Delay(function () {
05:   /*      var a = null; */           var a = null;
06:   /*      a.b(); */                  a.b();
07:                                      return _builder_$0.Normal();
08:                                  })
09:                              );
10:   /* } */                })
11:   //@ sourceURL=wind/anonymous_2.js




TypeError: Cannot call method 'b' of null
    at eval (wind/anonymous_0.js:6:37)
    at Object.BuilderBase.Delay.next (.../wind-async.js:143:46)
    at Object.AsyncBuilder.Start [as _delegate] (.../wind-async:652:22)
    ...
指向⺫⽬目标堆栈
01:   /* function () { */    (function () {
02:                              var _builder_$0 = Wind.builders["async"];
03:                              return _builder_$0.Start(this,
04:                                  _builder_$0.Delay(function () {
05:   /*      var a = null; */           var a = null;
06:   /*      a.b(); */                  a.b();
07:                                      return _builder_$0.Normal();
08:                                  })
09:                              );
10:   /* } */                })
11:   //@ sourceURL=wind/anonymous_2.js




TypeError: Cannot call method 'b' of null
             wind/anonymous_0.js:6:37
    at eval (wind/anonymous_0.js:6:37)
    at Object.BuilderBase.Delay.next (.../wind-async.js:143:46)
    at Object.AsyncBuilder.Start [as _delegate] (.../wind-async:652:22)
    ...
有办法修复吗?
有办法修复吗?


当然有,编译器掌握了所有
 输⼊入和输出的对应关系。
总结

• 调试eval出的代码不是问题
• 混淆后的代码可以利⽤用Source Map直接
 定位到原始代码

• Wind.js编译器充分了解⺫⽬目标代码与原始
 代码的位置关系,可⽤用于堆栈定位
Q &A
谢谢

Weitere ähnliche Inhalte

Was ist angesagt?

lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7Justin Lin
 
基于原型的JavaScript面向对象编程
基于原型的JavaScript面向对象编程基于原型的JavaScript面向对象编程
基于原型的JavaScript面向对象编程zhangdaiping
 
JavaScript 教程
JavaScript 教程JavaScript 教程
JavaScript 教程Bobby Zhou
 
Python learn guide
Python learn guidePython learn guide
Python learn guiderobin yang
 
Python 于 webgame 的应用
Python 于 webgame 的应用Python 于 webgame 的应用
Python 于 webgame 的应用勇浩 赖
 
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...彼得潘 Pan
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型keelii
 
在開始工作以前,我以為我會寫扣。
在開始工作以前,我以為我會寫扣。在開始工作以前,我以為我會寫扣。
在開始工作以前,我以為我會寫扣。Chih-Hsuan Kuo
 
Java8 lambda
Java8 lambdaJava8 lambda
Java8 lambdakoji lin
 
Swift 程序语言介绍
Swift 程序语言介绍Swift 程序语言介绍
Swift 程序语言介绍明 李
 
JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1Sheng-Han Su
 
Sigreturn Oriented Programming
Sigreturn Oriented ProgrammingSigreturn Oriented Programming
Sigreturn Oriented ProgrammingAngel Boy
 
從 Singleton 談 constructor
從 Singleton 談 constructor從 Singleton 談 constructor
從 Singleton 談 constructorLuba Tang
 
JAVA内存泄漏及诊断
JAVA内存泄漏及诊断JAVA内存泄漏及诊断
JAVA内存泄漏及诊断ivannotes
 
Arduino應用系統設計 - Arduino程式快速入門
Arduino應用系統設計 - Arduino程式快速入門Arduino應用系統設計 - Arduino程式快速入門
Arduino應用系統設計 - Arduino程式快速入門吳錫修 (ShyiShiou Wu)
 
Arduino L2
Arduino L2Arduino L2
Arduino L2mmiwwcom
 
LazyRecord: The Fast ORM for PHP
LazyRecord: The Fast ORM for PHPLazyRecord: The Fast ORM for PHP
LazyRecord: The Fast ORM for PHPLin Yo-An
 

Was ist angesagt? (20)

Node way
Node wayNode way
Node way
 
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
 
基于原型的JavaScript面向对象编程
基于原型的JavaScript面向对象编程基于原型的JavaScript面向对象编程
基于原型的JavaScript面向对象编程
 
JavaScript 教程
JavaScript 教程JavaScript 教程
JavaScript 教程
 
Python learn guide
Python learn guidePython learn guide
Python learn guide
 
Python 于 webgame 的应用
Python 于 webgame 的应用Python 于 webgame 的应用
Python 于 webgame 的应用
 
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型
 
在開始工作以前,我以為我會寫扣。
在開始工作以前,我以為我會寫扣。在開始工作以前,我以為我會寫扣。
在開始工作以前,我以為我會寫扣。
 
Java8 lambda
Java8 lambdaJava8 lambda
Java8 lambda
 
nodeMCU IOT教學02 - Lua語言
nodeMCU IOT教學02 - Lua語言nodeMCU IOT教學02 - Lua語言
nodeMCU IOT教學02 - Lua語言
 
Swift 程序语言介绍
Swift 程序语言介绍Swift 程序语言介绍
Swift 程序语言介绍
 
Ooredis
OoredisOoredis
Ooredis
 
JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1
 
Sigreturn Oriented Programming
Sigreturn Oriented ProgrammingSigreturn Oriented Programming
Sigreturn Oriented Programming
 
從 Singleton 談 constructor
從 Singleton 談 constructor從 Singleton 談 constructor
從 Singleton 談 constructor
 
JAVA内存泄漏及诊断
JAVA内存泄漏及诊断JAVA内存泄漏及诊断
JAVA内存泄漏及诊断
 
Arduino應用系統設計 - Arduino程式快速入門
Arduino應用系統設計 - Arduino程式快速入門Arduino應用系統設計 - Arduino程式快速入門
Arduino應用系統設計 - Arduino程式快速入門
 
Arduino L2
Arduino L2Arduino L2
Arduino L2
 
LazyRecord: The Fast ORM for PHP
LazyRecord: The Fast ORM for PHPLazyRecord: The Fast ORM for PHP
LazyRecord: The Fast ORM for PHP
 

Ähnlich wie Wind.js无障碍调试与排错

Node.js开发体验
Node.js开发体验Node.js开发体验
Node.js开发体验QLeelulu
 
Ian 20151002 es2015
Ian 20151002 es2015Ian 20151002 es2015
Ian 20151002 es2015LearningTech
 
Erlang Practice
Erlang PracticeErlang Practice
Erlang Practicelitaocheng
 
學好 node.js 不可不知的事
學好 node.js 不可不知的事學好 node.js 不可不知的事
學好 node.js 不可不知的事Ben Lue
 
Node getting-started
Node getting-startedNode getting-started
Node getting-startedlylijincheng
 
Html5移动web应用开发(PhoneGap)
Html5移动web应用开发(PhoneGap)Html5移动web应用开发(PhoneGap)
Html5移动web应用开发(PhoneGap)amd6400
 
Html5移动web应用开发(PhoneGap)
Html5移动web应用开发(PhoneGap)Html5移动web应用开发(PhoneGap)
Html5移动web应用开发(PhoneGap)amd6400
 
Ruby程式語言入門導覽
Ruby程式語言入門導覽Ruby程式語言入門導覽
Ruby程式語言入門導覽Mu-Fan Teng
 
Talking about exploit writing
Talking about exploit writingTalking about exploit writing
Talking about exploit writingsbha0909
 
twMVC#44 讓我們用 k6 來進行壓測吧
twMVC#44 讓我們用 k6 來進行壓測吧twMVC#44 讓我們用 k6 來進行壓測吧
twMVC#44 讓我們用 k6 來進行壓測吧twMVC
 
181201_CoAP_coding365
181201_CoAP_coding365181201_CoAP_coding365
181201_CoAP_coding365Peter Yi
 
JCConf2015: groovy to gradle
 JCConf2015: groovy to gradle JCConf2015: groovy to gradle
JCConf2015: groovy to gradleChing Yi Chan
 
Mongodb
MongodbMongodb
Mongodbbj
 
D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版Jackson Tian
 
Node.js在淘宝的应用实践
Node.js在淘宝的应用实践Node.js在淘宝的应用实践
Node.js在淘宝的应用实践taobao.com
 
NodeJS快速服务端开发 朝沐金风 Shanghai
NodeJS快速服务端开发 朝沐金风 ShanghaiNodeJS快速服务端开发 朝沐金风 Shanghai
NodeJS快速服务端开发 朝沐金风 ShanghaiJackson Tian
 
HTML5移动WEB应用程序开发(PhoneGap)
HTML5移动WEB应用程序开发(PhoneGap)HTML5移动WEB应用程序开发(PhoneGap)
HTML5移动WEB应用程序开发(PhoneGap)amd6400
 
HTML5移动应用开发分享会(PhoneGap)
HTML5移动应用开发分享会(PhoneGap)HTML5移动应用开发分享会(PhoneGap)
HTML5移动应用开发分享会(PhoneGap)amd6400
 

Ähnlich wie Wind.js无障碍调试与排错 (20)

Node.js开发体验
Node.js开发体验Node.js开发体验
Node.js开发体验
 
Ian 20151002 es2015
Ian 20151002 es2015Ian 20151002 es2015
Ian 20151002 es2015
 
Erlang Practice
Erlang PracticeErlang Practice
Erlang Practice
 
學好 node.js 不可不知的事
學好 node.js 不可不知的事學好 node.js 不可不知的事
學好 node.js 不可不知的事
 
Node getting-started
Node getting-startedNode getting-started
Node getting-started
 
Arduino程式快速入門
Arduino程式快速入門Arduino程式快速入門
Arduino程式快速入門
 
Html5移动web应用开发(PhoneGap)
Html5移动web应用开发(PhoneGap)Html5移动web应用开发(PhoneGap)
Html5移动web应用开发(PhoneGap)
 
Html5移动web应用开发(PhoneGap)
Html5移动web应用开发(PhoneGap)Html5移动web应用开发(PhoneGap)
Html5移动web应用开发(PhoneGap)
 
Ruby程式語言入門導覽
Ruby程式語言入門導覽Ruby程式語言入門導覽
Ruby程式語言入門導覽
 
Talking about exploit writing
Talking about exploit writingTalking about exploit writing
Talking about exploit writing
 
Arduino程式快速入門
Arduino程式快速入門Arduino程式快速入門
Arduino程式快速入門
 
twMVC#44 讓我們用 k6 來進行壓測吧
twMVC#44 讓我們用 k6 來進行壓測吧twMVC#44 讓我們用 k6 來進行壓測吧
twMVC#44 讓我們用 k6 來進行壓測吧
 
181201_CoAP_coding365
181201_CoAP_coding365181201_CoAP_coding365
181201_CoAP_coding365
 
JCConf2015: groovy to gradle
 JCConf2015: groovy to gradle JCConf2015: groovy to gradle
JCConf2015: groovy to gradle
 
Mongodb
MongodbMongodb
Mongodb
 
D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版
 
Node.js在淘宝的应用实践
Node.js在淘宝的应用实践Node.js在淘宝的应用实践
Node.js在淘宝的应用实践
 
NodeJS快速服务端开发 朝沐金风 Shanghai
NodeJS快速服务端开发 朝沐金风 ShanghaiNodeJS快速服务端开发 朝沐金风 Shanghai
NodeJS快速服务端开发 朝沐金风 Shanghai
 
HTML5移动WEB应用程序开发(PhoneGap)
HTML5移动WEB应用程序开发(PhoneGap)HTML5移动WEB应用程序开发(PhoneGap)
HTML5移动WEB应用程序开发(PhoneGap)
 
HTML5移动应用开发分享会(PhoneGap)
HTML5移动应用开发分享会(PhoneGap)HTML5移动应用开发分享会(PhoneGap)
HTML5移动应用开发分享会(PhoneGap)
 

Mehr von jeffz

深入浅出Jscex
深入浅出Jscex深入浅出Jscex
深入浅出Jscexjeffz
 
Mono for .NET Developers
Mono for .NET DevelopersMono for .NET Developers
Mono for .NET Developersjeffz
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programmingjeffz
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)jeffz
 
Jscex: Write Sexy JavaScript
Jscex: Write Sexy JavaScriptJscex: Write Sexy JavaScript
Jscex: Write Sexy JavaScriptjeffz
 
单点登录解决方案的架构与实现
单点登录解决方案的架构与实现单点登录解决方案的架构与实现
单点登录解决方案的架构与实现jeffz
 
Documentation Insight技术架构与开发历程
Documentation Insight技术架构与开发历程Documentation Insight技术架构与开发历程
Documentation Insight技术架构与开发历程jeffz
 
Windows Phone应用开发心得
Windows Phone应用开发心得Windows Phone应用开发心得
Windows Phone应用开发心得jeffz
 
分布式版本管理
分布式版本管理分布式版本管理
分布式版本管理jeffz
 
使用.NET构建轻量级分布式框架
使用.NET构建轻量级分布式框架使用.NET构建轻量级分布式框架
使用.NET构建轻量级分布式框架jeffz
 
针对iPad平台的高性能网站架构
针对iPad平台的高性能网站架构针对iPad平台的高性能网站架构
针对iPad平台的高性能网站架构jeffz
 
企业开发领域的语言特性
企业开发领域的语言特性企业开发领域的语言特性
企业开发领域的语言特性jeffz
 
The Evolution of Async-Programming on .NET Platform (TUP, Full)
The Evolution of Async-Programming on .NET Platform (TUP, Full)The Evolution of Async-Programming on .NET Platform (TUP, Full)
The Evolution of Async-Programming on .NET Platform (TUP, Full)jeffz
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)jeffz
 
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)jeffz
 
大话程序员可用的算法
大话程序员可用的算法大话程序员可用的算法
大话程序员可用的算法jeffz
 
面向对象与生活
面向对象与生活面向对象与生活
面向对象与生活jeffz
 
Windows内核技术介绍
Windows内核技术介绍Windows内核技术介绍
Windows内核技术介绍jeffz
 
响应式编程及框架
响应式编程及框架响应式编程及框架
响应式编程及框架jeffz
 
F#语言对异步程序设计的支持
F#语言对异步程序设计的支持F#语言对异步程序设计的支持
F#语言对异步程序设计的支持jeffz
 

Mehr von jeffz (20)

深入浅出Jscex
深入浅出Jscex深入浅出Jscex
深入浅出Jscex
 
Mono for .NET Developers
Mono for .NET DevelopersMono for .NET Developers
Mono for .NET Developers
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programming
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)
 
Jscex: Write Sexy JavaScript
Jscex: Write Sexy JavaScriptJscex: Write Sexy JavaScript
Jscex: Write Sexy JavaScript
 
单点登录解决方案的架构与实现
单点登录解决方案的架构与实现单点登录解决方案的架构与实现
单点登录解决方案的架构与实现
 
Documentation Insight技术架构与开发历程
Documentation Insight技术架构与开发历程Documentation Insight技术架构与开发历程
Documentation Insight技术架构与开发历程
 
Windows Phone应用开发心得
Windows Phone应用开发心得Windows Phone应用开发心得
Windows Phone应用开发心得
 
分布式版本管理
分布式版本管理分布式版本管理
分布式版本管理
 
使用.NET构建轻量级分布式框架
使用.NET构建轻量级分布式框架使用.NET构建轻量级分布式框架
使用.NET构建轻量级分布式框架
 
针对iPad平台的高性能网站架构
针对iPad平台的高性能网站架构针对iPad平台的高性能网站架构
针对iPad平台的高性能网站架构
 
企业开发领域的语言特性
企业开发领域的语言特性企业开发领域的语言特性
企业开发领域的语言特性
 
The Evolution of Async-Programming on .NET Platform (TUP, Full)
The Evolution of Async-Programming on .NET Platform (TUP, Full)The Evolution of Async-Programming on .NET Platform (TUP, Full)
The Evolution of Async-Programming on .NET Platform (TUP, Full)
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
 
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)
 
大话程序员可用的算法
大话程序员可用的算法大话程序员可用的算法
大话程序员可用的算法
 
面向对象与生活
面向对象与生活面向对象与生活
面向对象与生活
 
Windows内核技术介绍
Windows内核技术介绍Windows内核技术介绍
Windows内核技术介绍
 
响应式编程及框架
响应式编程及框架响应式编程及框架
响应式编程及框架
 
F#语言对异步程序设计的支持
F#语言对异步程序设计的支持F#语言对异步程序设计的支持
F#语言对异步程序设计的支持
 

Wind.js无障碍调试与排错

  • 2. 关于我 • 赵劼 / ⽼老赵 / Jeffrey Zhao / 赵姐夫 • ⽇日写代码三百⾏行,不辞⻓长作程序员 • 博客:http://blog.zhaojie.me/ • 微博:@⽼老赵 • F#, JavaScript, Scala, C#, Python, .NET, Mono... • 痛恨Java语⾔言
  • 7. 调试eval的代码 • 代码末尾://@  sourceUrl=<path> • ⽀支持浏览器 • Chrome • Safari • Firefox (Firebug)
  • 8. 调试Node.js代码 • Eclipse • Eclipse Debugger Plugin for V8 • 启动程序 • node  -­‐-­‐debug[=port]  app.js • node  -­‐-­‐debug-­‐brk[=port]  app.js Using Eclipse as Node Applications Debugger
  • 13. Source Map • 记录⺫⽬目标代码到源代码的映射 • JSON格式 + 编码后的映射数据 • Source Map V3 Spec
  • 14. Source Map • 记录⺫⽬目标代码到源代码的映射 • JSON格式 + 编码后的映射数据 • Source Map V3 Spec 脚本末尾加上://@  sourceMappingURL=<path>,或 脚本请求头加上:X-­‐SourceMap:  <path>
  • 16. Source Map V3 {        "version":  3,        "file":  "all.min.js",        "lineCount":  37,        "sources":  [                  "wind-­‐core.js",                "wind-­‐builderbase.js",                "wind-­‐async.js",                "sorting-­‐animations.aot.js"        ],        "names":  [  "Wind",  "_",  "isArray",  "obj",  ...  ],        "mappings":  "AAAC,SAAS,EAAG,CAGT,IAAIA,  ..." }
  • 17. 解码 mappings 字段 • ⽤用分号区分“⾏行”,逗号区分“段”。 • Base64 Variable-Length Quantity 编码 • 节省空间,⽐比V2节省50%左右
  • 18. 确定代码⾏行号 AABBC;                  //  第1⾏行 KAUYM,GAKoEF;    //  第2⾏行 CCDD,  ...;          //  第3⾏行 ... ...
  • 20. Base64 VLQ解码 KAUYM,GAKoEF >> [10,  0,  20,  24,  12],  [6,  0,  10,  40,  4,  5]
  • 21. Base64 VLQ解码 KAUYM,GAKoEF >> [10,  0,  20,  24,  12],  [6,  0,  10,  40,  4,  5] >> [001010,  000000,  010100,  011000,  001100],   [000110,  000000,  001010,  101000,  000100,  000101]
  • 22. Base64 VLQ解码 KAUYM,GAKoEF >> [10,  0,  20,  24,  12],  [6,  0,  10,  40,  4,  5] >> 最低N-­‐1位为数据位 [001010,  000000,  010100,  011000,  001100],   01000,    00100 [000110,  000000,  001010,  101000,  000100,  000101] 最⾼高位表⽰示是否“连接后续数据”
  • 23. Base64 VLQ解码 KAUYM,GAKoEF >> [10,  0,  20,  24,  12],  [6,  0,  10,  40,  4,  5] >> 最低N-­‐1位为数据位 [001010,  000000,  010100,  011000,  001100],   01000,    00100 [000110,  000000,  001010,  101000,  000100,  000101] 最⾼高位表⽰示是否“连接后续数据” >> [1010,  0,  10100,  11000,  1100],   [110,  0,  1010,  10001000,  101]
  • 24. 数据解码 [1010,  0,  10100,  11000,  1100],   [110,  0,  1010,  10001000,  101]
  • 25. 数据解码 [1010,  0,  10100,  11000,  1100],   [110,  0,  1010,  10001000,  101] 最⾼高N-­‐1位为数据位 最低位为符号位
  • 26. 数据解码 [1010,  0,  10100,  11000,  1100],   [110,  0,  1010,  10001000,  101] 最⾼高N-­‐1位为数据位 最低位为符号位 >> [5,  0,  10,  12,  6],  [3,  0,  5,  68,  -­‐2]
  • 27. 数据解码 [1010,  0,  10100,  11000,  1100],   [110,  0,  1010,  10001000,  101] 最⾼高N-­‐1位为数据位 最低位为符号位 >> [5,  0,  10,  12,  6],  [3,  0,  5,  68,  -­‐2] >> [5,  0,  10,  12,  6],  [8,  0,  15,  80,  4]
  • 28. 含义 //  已确定⾏行号 [  5,      //  列号  0,      //  源⽂文件,从sources查找  10,    //  源⽂文件内⾏行号  12,    //  源⽂文件内列号  6        //  源⽂文件内标⽰示符,从names查找 ]
  • 29. ⽆无需⼿手动分析 • Google Closure Compiler可以⽣生成V2版 Source Map格式,未编码的明⽂文数据 • 使⽤用Mozilla的SourceMap项⺫⽬目读取或⽣生成 Source Map⽂文件
  • 31. 传统JS错误堆栈 128: var baz = function () { 129: throw new Error("Hello World"); 130: }; 131: 132: var bar = function () { 133: baz(); 134: }; 135: 136: var foo = function () { 137: bar(); 138: }; 139: 140: foo();
  • 32. 传统JS错误堆栈 128: var baz = function () { 129: throw new Error("Hello World"); 130: }; 131: 132: var bar = function () { 133: baz(); 134: }; 135: 136: var foo = function () { 137: bar(); 138: }; 139: Error: Hello World 140: foo(); at baz (.../test.js:129:11) at bar (.../test.js:133:5) at foo (.../test.js:137:5) at Object.<anonymous> (.../test.js:140:1) at Module._compile (module.js:449:26) at Object.Module._extensions..js (module.js:467:10) ...
  • 33. 传统JS错误堆栈 128: var baz = function () { 129: throw new Error("Hello World"); 130: }; 131: 132: var bar = function () { 133: baz(); 134: }; 135: 136: var foo = function () { 137: bar(); 138: }; 139: Error: Hello World 140: foo(); at baz (.../test.js:129:11) at bar (.../test.js:133:5) at foo (.../test.js:137:5) at Object.<anonymous> (.../test.js:140:1) at Module._compile (module.js:449:26) at Object.Module._extensions..js (module.js:467:10) ...
  • 34. Wind.js错误堆栈 128: var test = eval(..., function () { 129: var a = null; 130: a.b(); 131: })); 132: 133: test().on("failure", function () { 134: console.log(this.error.stack); 135: }).start();
  • 35. Wind.js错误堆栈 128: var test = eval(..., function () { 129: var a = null; 130: a.b(); 131: })); 132: 133: test().on("failure", function () { 134: console.log(this.error.stack); 135: }).start(); TypeError: Cannot call method 'b' of null at eval (wind/anonymous_0.js:6:37) at Object.BuilderBase.Delay.next (.../wind-async.js:143:46) at Object.AsyncBuilder.Start [as _delegate] (.../wind-async:652:22) at Object.Task.start (.../wind-async.js:196:22) at Object.<anonymous> (.../test.js:135:4) ...
  • 36. Wind.js错误堆栈 128: var test = eval(..., function () { 129: var a = null; 130: a.b(); 131: })); 132: 133: test().on("failure", function () { 134: console.log(this.error.stack); 135: }).start(); TypeError: Cannot call method 'b' of null at eval (wind/anonymous_0.js:6:37) ??? wind/anonymous_0.js:6:37 at Object.BuilderBase.Delay.next (.../wind-async.js:143:46) at Object.AsyncBuilder.Start [as _delegate] (.../wind-async:652:22) at Object.Task.start (.../wind-async.js:196:22) at Object.<anonymous> (.../test.js:135:4) ...
  • 37. 指向⺫⽬目标堆栈 01: /* function () { */ (function () { 02: var _builder_$0 = Wind.builders["async"]; 03: return _builder_$0.Start(this, 04: _builder_$0.Delay(function () { 05: /* var a = null; */ var a = null; 06: /* a.b(); */ a.b(); 07: return _builder_$0.Normal(); 08: }) 09: ); 10: /* } */ }) 11: //@ sourceURL=wind/anonymous_2.js TypeError: Cannot call method 'b' of null at eval (wind/anonymous_0.js:6:37) at Object.BuilderBase.Delay.next (.../wind-async.js:143:46) at Object.AsyncBuilder.Start [as _delegate] (.../wind-async:652:22) ...
  • 38. 指向⺫⽬目标堆栈 01: /* function () { */ (function () { 02: var _builder_$0 = Wind.builders["async"]; 03: return _builder_$0.Start(this, 04: _builder_$0.Delay(function () { 05: /* var a = null; */ var a = null; 06: /* a.b(); */ a.b(); 07: return _builder_$0.Normal(); 08: }) 09: ); 10: /* } */ }) 11: //@ sourceURL=wind/anonymous_2.js TypeError: Cannot call method 'b' of null wind/anonymous_0.js:6:37 at eval (wind/anonymous_0.js:6:37) at Object.BuilderBase.Delay.next (.../wind-async.js:143:46) at Object.AsyncBuilder.Start [as _delegate] (.../wind-async:652:22) ...
  • 41. 总结 • 调试eval出的代码不是问题 • 混淆后的代码可以利⽤用Source Map直接 定位到原始代码 • Wind.js编译器充分了解⺫⽬目标代码与原始 代码的位置关系,可⽤用于堆栈定位
  • 42. Q &A