节点解释器是否在节点二进制文件中寻找核心模块(比如“fs”)?如果是,这些模块是否打包为js文件。我们的代码中引用的核心模块是否先转换为 c/c++ 代码,然后再执行?例如,我在 _tls_common.js ( https://github.com/nodejs/node/blob/master/lib/_tls_common.js ) 文件中看到一个名为“loadPKCS12”的方法,我看到这个方法的唯一地方是引用/定义在“node_crypto.cc”文件(https://github.com/nodejs/node/blob/master/src/node_crypto.cc)中。那么 node 如何将 javascript 中的方法与 c/c++ 文件中定义的方法链接起来呢?
这是使用“loadPKCS12”方法的 _tls_common.js 文件的摘录:
if (passphrase) {
c.context.loadPKCS12(buf, toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
}
}
} else {
const buf = toBuf(options.pfx);
const passphrase = options.passphrase;
if (passphrase) {
c.context.loadPKCS12(buf, toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
这里提出了两个不同(但看似相关)的问题。第一个是:“核心模块如何工作?”。第二个是“NodeJS 如何让 C++ 代码在 JavaScript 中被引用和执行?”。让我们一一拿下。
核心模块如何工作?
核心模块用 NodeJS 二进制文件打包。而且,虽然它们与二进制文件一起打包,但它们在打包之前不会转换为 C++ 代码。内部模块在节点进程的引导过程中加载到内存中。当程序执行时,可以说require('fs')
,require 函数只是从缓存中返回已经加载的模块。内部模块的实际加载显然发生在 c++ 代码中。
NodeJS 如何让 C++ 代码在 JS 中被引用?
这种能力部分来自 V8 引擎,它公开了在 C++ 中创建和管理 JS 构造的能力,部分来自 NodeJS / LibUV,它们在 V8 之上创建了一个包装器以提供执行环境。可以在此处访问有关此类节点模块的文档。正如文档所述,这些 c++ 模块可以通过要求在 JS 文件中使用,就像任何其他普通的 JS 模块一样。
但是,您在 JS ( loadPKCS12
) 中使用 c++ 函数的示例是 NodeJS 内部 c++ 功能的更特殊情况。loadPKCS12
在SecureContext
从crypto
c++ 模块导入的对象上调用。如果您按照_tls_common.js
上面的SecureContext 导入链接,您将看到加密不是使用 加载的require()
,而是使用特殊(全局)方法internalBinding
来获取引用。在文件的最后一行,注册node_crypto.cc
了内部模块的初始化程序crypto
。在初始化链之后,node::crypto::Initialize
调用node::crypto::SecureContext::Initialize
创建函数模板,分配适当的原型方法并将其导出到target
. 最终这些从 C++ 世界导出的功能被导入并在 JS-World 中使用internalBinding
.
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句