Ищет ли интерпретатор узла основные модули (скажем, «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). Итак, как узел связывает метод в javascript с методом, определенным в файле c/c++?
вот выдержка из файла _tls_common.js, в котором используется метод loadPKCS12:
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 просто возвращает уже загруженный модуль из кеша. Фактическая загрузка внутреннего модуля явно происходит в коде С++.
Как NodeJS позволяет ссылаться на код C++ в JS?
Эта возможность частично исходит от движка V8, который предоставляет возможность создавать конструкции JS и управлять ими на C++, и частично от NodeJS/LibUV, которые создают оболочку поверх V8 для обеспечения среды выполнения. Документация о таких модулях узла может быть доступ здесь. Как указано в документации, эти модули C++ можно использовать в файле JS, потребовав их, как и любой другой обычный модуль JS.
Однако ваш пример использования функции c++ в JS (loadPKCS12
) является более частным случаем внутренней функциональности c++ в NodeJS. loadPKCS12
вызывается для объекта SecureContext
, импортированного из модуля crypto
c++. Если вы перейдете по ссылке на импорт SecureContext в _tls_common.js
выше, вы увидите, что криптография не загружается с использованием require()
, вместо этого используется специальный (глобальный) метод internalBinding
для получения ссылки. В Последняя линия в файле node_crypto.cc
прописан инициализатор для внутреннего модуля crypto
. Следуя цепочке инициализации, node::crypto::Initialize
вызывает node::crypto::SecureContext::Initialize
, который создает шаблон функции, назначает соответствующие методы прототипа и экспортирует его в target
. В конце концов эти экспортированные функции из мира C++ импортируются и используются в JS-World с помощью internalBinding
.
js2c.py не меняет программу Logic in JS на эквивалентную программу Logic in C++. Он выводит строковое представление кода JS, хранящегося в массиве символов. который потенциально может быть скомпилирован с помощью другой программы на С++. Например, если код JS был var foo = 'bar'
, js2c.py выведет что-то вроде: char prog[] = { 'v', 'a', 'r', ' ', '=', ' ', '\', 'b', 'a', 'r' };
. Это всего лишь строковое представление кода JS в синтаксисе c/c++. Это все еще должно быть оценено и выполнено движком JS. Пользовательский код JavaScript не подвергается такому преобразованию перед выполнением.
Ах...!!! А как насчет модулей npm, на которые есть ссылки в нашем коде? Они так же переводятся?
А как насчет исходного кода приложения? Преобразуется ли исходный код JavaScript в массивы символов в стиле C? Спасибо, что ответили на мои вопросы кстати :)
js2c.py
не проявляется при нормальном выполнении любой программы NodeJS. AAMOF, при обычном выполнении JS-файлов с помощью NodeJS питон вообще не нужен (js2c.py
— скрипт на питоне). Он используется только во время компиляции разработчиками модулей С++, которым необходимо сохранять фрагменты JS в коде С++, который может быть оценен как JavaScript с помощью версии 8 во время выполнения. Сам сценарий не играет никакой роли во время выполнения.
конвертирует ли js2c.py все «необходимые» модули в нашем js-коде в его эквивалент c/c++? Как насчет кода, который мы пишем поверх среды выполнения узла? Позаботится ли js2c.py о его переводе?