在编译所有C/C++文件之前,编译程序需要将所有的JavaScript模块文件编译为C/C++代码,此时是否直接将其便以为可执行代码了呢?其实不是。
## 1.转存为C/C++代码
Node采用了V8附带的js2c.py工具,将所有内置的JavaScript代码(src/node.js和lib/*.js)转换成C++里的数组,生成node_natives.h头文件,相关代码如下:
~~~
namespace node{
const char node_native[]={47,47,..};
const char dgram_native[]={47,47,..};
const char console_native[]={47,47,..};
const char buffer_native[]={47,47,..};
const char querystring_native[]={47,42,..};
...
struct _native{
const char* name;
const char* source;
size_t source_len;
};
static const struct _native natives[]={
{"node",node_native,sizeof(node_native)-1},
{"dgram",dgram_native,sizeof(dgram_native)-1},
...
};
}
~~~
在这个过程中,JavaScript代码以字符串的形式存储在node命名空间中,是不可直接执行的。在启动Node进程时,JavaScript代码直接加载进内存中。在加载的过程中,JavaScript核心模块经历标识符分析后直接定位到内存中,比普通的文件模块从磁盘中一处一处查找要快很多。
## 2.编译JavaScript核心模块
lib目录下的所有模块文件也没有定义require、module、exports这些变量。在引入JavaScript核心模块的过程中,也经历了头尾包装的过程,然后才执行和导出了exports对象。与文件模块有区别的地方在于:获取源码的方式(核心模块是从内存中加载的)以及缓存执行结果的位置。
JavaScript核心模块的定义如下面的代码所示,源文件通过process.binding('natives')取出,编译成功的模块缓存到NativeModule._cahce对象上,文件模块则要缓存到Module._cache对象上:
~~~
function NativeModule(id){
this.filename = id + '.js';
this.id = id;
this.exports = {};
this.loaded = false;
}
NativeModule._source=process.binding('natives');
NativeModule._cache = {};
~~~
- 目录
- 第1章 Node 简介
- 1.1 Node 的诞生历程
- 1.2 Node 的命名与起源
- 1.2.1 为什么是 JavaScript
- 1.2.2 为什么叫 Node
- 1.3 Node给JavaScript带来的意义
- 1.4 Node 的特点
- 1.4.1 异步 I/O
- 1.4.2 事件与回调函数
- 1.4.3 单线程
- 1.4.4 跨平台
- 1.5 Node 的应用场景
- 1.5.1 I/O 密集型
- 1.5.2 是否不擅长CPU密集型业务
- 1.5.3 与遗留系统和平共处
- 1.5.4 分布式应用
- 1.6 Node 的使用者
- 1.7 参考资源
- 第2章 模块机制
- 2.1 CommonJS 规范
- 2.1.1 CommonJS 的出发点
- 2.1.2 CommonJS 的模块规范
- 2.2 Node 的模块实现
- 2.2.1 优先从缓存加载
- 2.2.2 路径分析和文件定位
- 2.2.3 模块编译
- 2.3 核心模块
- 2.3.1 JavaScript核心模块的编译过程
- 2.3.2 C/C++核心模块的编译过程
- 2.3.3 核心模块的引入流程
- 2.3.4 编写核心模块
- 2.4 C/C++扩展模块
- 2.4.1 前提条件
- 2.4.2 C/C++扩展模块的编写
- 2.4.3 C/C++扩展模块的编译
- 2.4.2 C/C++扩展模块的加载
- 2.5 模块调用栈
- 2.6 包与NPM
- 2.6.1 包结构
- 2.6.2 包描述文件与NPM
- 2.6.3 NPM常用功能
- 2.6.4 局域NPM
- 2.6.5 NPM潜在问题
- 2.7 前后端共用模块
- 2.7.1 模块的侧重点
- 2.7.2 AMD规范
- 2.7.3 CMD规范
- 2.7.4 兼容多种模块规范
- 2.8 总结
- 2.9 参考资源
- 第3章 异步I/O
- 3.1 为什么要异步I/O
- 3.1.1 用户体验
- 3.1.2 资源分配
- 3.2 异步I/O实现现状
- 3.2.1 异步I/O与非阻塞I/O
- 3.2.2 理想的非阻塞异步I/O
- 3.2.3 现实的异步I/O
- 3.3 Node的异步I/O
- 3.3.1 事件循环
- 3.3.2 观察者
- 3.3.3 请求对象
- 3.3.4 执行回调
- 3.3.5 小结
- 3.4 非I/O的异步API
- 3.4.1 定时器
- 3.5 事件驱动与高性能服务器