Node.js源码学习-模块

Node.js底层有三个重要部分

node

libuv 建立事件循环

v8 引擎以及JS/C++对象转换

node提供的模块 fs os net process等

libuv是一个神器,事件循环,适合状态机驱动的架构,单独学习。

v8的请看google的官方API文档。

今天主要看一下node的模块。

 

1.js2c.py

node内置了很多js文件,包括主程序 src/node.js和模块文件lib/*.js。js2py是把每一个js文件都生成一个源码数组,存放在node_natives.h中。

node_native

node_native.h中,每个js文件对应一个数组,源码以const char数组的形式存放。

 

node_native在映射完毕后,变成了这样一个数组。

2.node_javascript.cc

node_javascript.cc include了node_native.h,并提供两个方法:

MainSource(),只有一句

return OneByteString(env->isolate(), node_native, sizeof(node_native) - 1);

返回node_native映射的js文件,即node.js,转换成了一个v8::handle类型。node_native_1

 

 

图:node_native,node.js映射后的数组。

DefineJavaScript(env, target)

将所有js文件映射到Object型的target(不包括node.js)

target->Set(name, source)

综上,node_javascript.cc做了两件事,返回node.js的v8::handle,

返回lib/*.js的Object,{name: v8::handle, name: v8::handle .....}

现在所有js文件都被转换成了v8::handle。

3.node.cc

node.cc是nodejs的main文件,这里我们先认识一个node世界中的风云人物,process。

 

 

在node.cc的CreateEnvironment函数中,process出生了,下面我们从源码看看process是个什么?被赋予了哪些属性?

从上面这段代码可以看出process的原始属性,FunctionTemplate,很明显,是js里的一个function,function的name为process。

现在JS世界中已经多了一个叫process的function,那么它是在哪里成长的呢?

 

在node.cc的LoadEnvironment函数中,

运行MainSource

拿到了node.js的返回f_value,即node.js函数,入参为process的闭包函数,

(function(process) {})

验明正身,执行node.js闭包函数,最后一句做JS的同学看着肯定很眼熟,这不就是

(function(process){}).call(global, process)

 

4.fs.js

这里通过一个fs模块的创建与加载,来展示process呼风唤雨的能力。

首先规规矩矩的加载了几个模块,然后突然出现了binding

Binding在node.cc中实现

主要逻辑为,查看cache中是否有这个模块,如果没有就新建一个。

新建模块:如果存在builtin,则使用nm_context_register_func方法注册到cache中,如果是常量,cache中注册常量,如果是natives,绑定所有lib/*.js。

在fs中,process.binding找到了fs,是一个builtin模块。这个模块在node_file.cc中实现,最后通过NODE_MODULE_CONTEXT_AWARE_BUILTIN注册到builtin。

Binding函数完成了js上调用C++模块。

 

5.node.js

node.js中通过一个NativeModules来管理js模块,

 

process.binding('natives'),将所有内置js模块绑定到_source上。

之后可以通过require方法来拿到这些模块。

先检查cache,如果cache没有,就在process.moduleLoadList中增加一个,然后缓存,执行.

缓存就是把模块放到_cache中,compile函数

通过C++模块contextify运行了这段js。

 

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注