在线咨询
QQ咨询
服务热线
服务热线:13125520620
TOP

深入出不来nodejs源码-内置模块引入再探

发布时间:2018-7-2 浏览:3561

 
我发现每次细看源码都能发现我之前写的一些东西是错误的,去改掉吧,又很不协调,不改吧,看着又脑阔疼……
 
  所以,这一节再探,是对之前一些说法的纠正,另外再缝缝补补一些新的内容。
 
  错误在哪呢?在之前的初探中,有这么一块代码:
 
 
 ame);
 
  当时,我的理解是这样的:
 
 辅助函数则是加载了internal/bootstrap中的两个JS文件,加载的时候参数传入了C++代码生成的特殊对象。
 
  但是在我调试这块代码的时候,发现根本没有任何readFile的痕迹,才发现事情并没有那么简单,也就是说这个地方压根就没有加载对应的JS文件。
 
  那么问题来了,既然没有加载这个JS文件,那这个文件有什么意义?何处加载的?
 
  第一个问题,我猜大概是开发者想让我们直观的了解到加载了什么东西,所以以文件的形式保留在文件夹中方便查看。
 
  第二个问题,根据注释,可以很快的知道答案,但是当时哪里注意那么多哟。
 
  简单讲,这个文件的内容以静态的字符串的形式定义在node_javascript.h中,内容则在node_javascript.cc中,并使用node_js2c进行JS代码到C++代码的转换。
 
  
 
  问题的答案很简单,探索过程对我来说还是挺心酸的,这里一共有两行代码,首先看第一行。
 
  FIXED_ONE_BYTE_STRING是一个宏,这里暂不讨论内部实现,根据参数和返回类型可以简单判断这是一个转换函数,可以将const char*类型转换成Local<String>类型,至于Local是什么,可以参考我上一节内容,或者查阅其他的资料。
 
  对于第二行代码,需要关注的是LoaderBootstrapperSource这个方法,进去之后会发现又是一个调用:
 
 
  几个内部的属性作用非常明朗,注释都有写。
 
  暂时不去深入了解ToStringChecked方法的内部实现,从返回类型来看,最终也是生成一个Local<String>类型的方法,而这个String的源头,就是上面另外一个变量raw_internal_bootstrap_loaders_value。
 
  这个东西是这么定义的:
 
 
  很长很长的一个数组,uint8_t是unsigned char的别名,也就是说,这是一个超长的char数组。
 
  根据C++的基础知识,数组的名字本质上是一个指针,指向数组的第一个值,而数组的值又恰好是char类型的,所以说,对该值进行reinterpret_cast<const char*>的转换是不会有问题的。
 
  那么另外一个问题是,const char*更为熟知的类型是string字符串,这里一个数字数组是怎么变成字符串的?
 
  干想果然是浪费时间的,我把这个大数组弄到本地自己打印了一下,发现输出的内容竟然是:
 
 
 
  怎么感觉这么熟悉,翻开JS文件,果然……
 
 
 
  简单思考后,原来这里是因为ASCII表转换,把对应的一个个字符转换成了数字保存在字符数组中,真的是恶心啊。
 
  那么问题就解决了,加载的辅助JS文件内容其实是以字符数组保存在C++中的,获取完整内容后通过对JS到C++的转换,然后执行对应的代码。
 
 
 
  既然完成了JS文件内容、文件名的内容获取,下一步就是构建对应的函数体,方法就是GetBootstrapper,源码简化后如下:
 
 
// 静态公共方法 专门负责生成初始化辅助函数体
// env => 上下文环境
// source => JS格式的函数字符串
 
 
  这里省略了一些无关的错误处理,比较关键的几步可以看注释描述,有几点需要特殊说明一下:
 
1、关于EscapableHandleScope,正常情况下都是使用的HandleScope来管理作用域的Local,但是如果函数需要返回临时创建的Local,在返回前Local已经被V8的GC进行了处理,这里必须使用EscapableHandleScope类创建一个特殊的scope,并在最后调用Escape方法将指定的Local返回。
 
2、返回类型的Local<Value>,如果有看过上一节对于V8引擎一些基本概念的讲解,应该会发现Value是所有数据类型的根类,在对类型进行CHECK后再强制转换可以保证类型安全。
 
 
 
  最后看一眼ExecuteString方法:
 
}
 
  这里同样省略一些无关代码,可以发现,处理过程非常直白,直接利用Script类对字符串进行编译解析,然后返回执行完后生成的函数体。
 
  对于"internal/bootstrap/node.js"的加载过程也类似,就不再重复了。
 
  目前得到了函数体,但是并没有执行,后面再分析这块内容。
 
 
 

TAG
软件定制,软件开发,瀚森HANSEN,辽宁,沈阳,抚顺
0
该内容对我有帮助