真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Node.js 源碼分析

title: Node.js 源碼分析 - 加載 js 文件
date: 2018-11-30 21:04:49
tags:
    - Node.js
    - Node.js 源碼分析
    - 源碼分析
categories:
    - Node.js 源碼分析


此文最初于四年前發(fā)布在個(gè)人站上的,現(xiàn)遷移至此重發(fā),原鏈接:https://laogen.site/nodejs/nodejs-src/bootstrap-js/
《Node.js 源碼分析》 系列目錄頁(yè):https://laogen.site/nodejs/nodejs-src/index/

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:國(guó)際域名空間、網(wǎng)頁(yè)空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、興平網(wǎng)站維護(hù)、網(wǎng)站推廣。

提出問(wèn)題

了解 js 文件加載前的準(zhǔn)備工作

在《從 main 函數(shù)開(kāi)始》這篇中說(shuō)到了 LoadEnvironment() 函數(shù)負(fù)責(zé)加載 js 代碼,但并沒(méi)有繼續(xù)說(shuō)明加載細(xì)節(jié)。

這篇從 LoadEnvironment() 開(kāi)始探究 js 代碼加載的詳細(xì)過(guò)程。

LoadEnvironment()

LoadEnvironment() 的邏輯分兩部分:

  1. 加載并執(zhí)行兩個(gè) js 文件:loaders.js node.js,執(zhí)行后得到兩個(gè)啟動(dòng)函數(shù);
  2. 分別調(diào)用這兩個(gè)啟動(dòng)函數(shù):loaders_bootstrapper() 和 node_bootstrapper();

這段代碼比較長(zhǎng),我們把不影響主邏輯的代碼省略掉,然后直接在代碼中以注釋的形式來(lái)解釋:

void LoadEnvironment(Environment* env) {
  // ...
  
  /************************************************************/
  /**** 第一步.加載并執(zhí)行兩個(gè) js 文件:`loaders.js` `node.js`****/
  /************************************************************/

  // The bootstrapper scripts are lib/internal/bootstrap/loaders.js and
  // lib/internal/bootstrap/node.js, each included as a static C string
  // defined in node_javascript.h, generated in node_javascript.cc by
  // node_js2c.

  // 這兩個(gè) js 文件在 node 構(gòu)建過(guò)程中就被轉(zhuǎn)換成了 C++ 代碼,即以 C++ 字符串的
  // 形式存在于 C++ 代碼中,根據(jù)這個(gè)文件名就可以直接獲取相應(yīng)的 js 代碼字符串;

  // loaders.js 的文件名
  Local loaders_name =
      FIXED_ONE_BYTE_STRING(env->isolate(), "internal/bootstrap/loaders.js");
  
  // 執(zhí)行 loaders.js 得到函數(shù): `loaders_bootstrapper`
  MaybeLocal loaders_bootstrapper =
      GetBootstrapper(env, LoadersBootstrapperSource(env), loaders_name);

  // node.js 文件名
  Local node_name =
      FIXED_ONE_BYTE_STRING(env->isolate(), "internal/bootstrap/node.js");

  // 執(zhí)行 loaders.js 得到函數(shù): `loaders_bootstrapper`
  MaybeLocal node_bootstrapper =
      GetBootstrapper(env, NodeBootstrapperSource(env), node_name);

  // 上面代碼中:LoadersBootstrapperSource() & NodeBootstrapperSource() 是
  // 在 /src/node_javascript.h 頭文件中聲明的,node 源碼中并沒(méi)有它們的具體實(shí)現(xiàn),
  // 它們的實(shí)現(xiàn)代碼是在 node 本身構(gòu)建過(guò)程中生成的;
  // 至于 GetBootstrapper(),它的作用是編譯&執(zhí)行 js 代碼,返回執(zhí)行結(jié)果。

  if (loaders_bootstrapper.IsEmpty() || node_bootstrapper.IsEmpty()) {
    return;
  }

  Local global = env->context()->Global();
  // ...
  // Expose the global object as a property on itself
  // (Allows you to set stuff on `global` from anywhere in JavaScript.)
  global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global);

  /*************************************************************************/
  /* 第二步.分別調(diào)用這兩個(gè)啟動(dòng)函數(shù):loaders_bootstrapper、node_bootstrapper ****/
  /*************************************************************************/

  // Create binding loaders
  // 基于 GetBinding() 函數(shù)模板 創(chuàng)建 get_binding_fn 函數(shù)
  Local get_binding_fn =
      env->NewFunctionTemplate(GetBinding)->GetFunction(env->context())
          .ToLocalChecked();

  // 基于 GetLinkedBinding() 函數(shù)模板 創(chuàng)建 get_linked_binding_fn 函數(shù)
  Local get_linked_binding_fn =
      env->NewFunctionTemplate(GetLinkedBinding)->GetFunction(env->context())
          .ToLocalChecked();

  // 基于 GetInternalBinding() 函數(shù)模板 創(chuàng)建 get_internal_binding_fn 函數(shù)
  Local get_internal_binding_fn =
      env->NewFunctionTemplate(GetInternalBinding)->GetFunction(env->context())
          .ToLocalChecked();

  // 上面三個(gè)函數(shù)會(huì)作為 調(diào)用 loaders_bootstrapper() 時(shí)的參數(shù)。
  Local loaders_bootstrapper_args[] = {
    env->process_object(),
    get_binding_fn,
    get_linked_binding_fn,
    get_internal_binding_fn,
    Boolean::New(env->isolate(),
                 env->options()->debug_options->break_node_first_line)
  };

  // loaders_bootstrapper() 調(diào)用結(jié)果將保存在這個(gè)變量,
  // 接下來(lái),它將被作為參數(shù)傳給另一個(gè)啟動(dòng)函數(shù):node_bootstrapper()
  Local bootstrapped_loaders;

  // 調(diào)用啟動(dòng)函數(shù) loaders_bootstrapper()
  if (!ExecuteBootstrapper(env, loaders_bootstrapper.ToLocalChecked(),
                           arraysize(loaders_bootstrapper_args),
                           loaders_bootstrapper_args,
                           &bootstrapped_loaders)) {
    return;
  }

  // Bootstrap Node.js
  Local bootstrapper = Object::New(env->isolate());
  SetupBootstrapObject(env, bootstrapper);
  Local bootstrapped_node;
  Local node_bootstrapper_args[] = {
    env->process_object(),
    bootstrapper,
    bootstrapped_loaders
  };
  // 調(diào)用啟動(dòng)函數(shù) loaders_bootstrapper()
  if (!ExecuteBootstrapper(env, node_bootstrapper.ToLocalChecked(),
                           arraysize(node_bootstrapper_args),
                           node_bootstrapper_args,
                           &bootstrapped_node)) {
    return;
  }
}

總結(jié)

LoadEnvironment() 主要是調(diào)用了兩個(gè) 啟動(dòng)函數(shù)(Bootstrapper)

  • loaders_bootstrapper()
  • node_bootstrapper()

其中 loaders_bootstrapper() 主要實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的模塊加載機(jī)制名為 NativeModule,主要用于加載內(nèi)部模塊的,會(huì)在 node_bootstrapper() 中用到;

而在 node_bootstrapper() 則加載并執(zhí)行了用戶的 js 文件(也就是通常的 app.js 或 index.js)。

這兩個(gè)啟動(dòng)函數(shù)分別定義在 /lib/internal/bootstrap/loaders.js/lib/internal/bootstrap/node.js 文件中;

接下來(lái)的兩篇文,會(huì)分別對(duì)這兩個(gè)文件進(jìn)行詳細(xì)的探究,弄清楚 js 文件加載執(zhí)行的細(xì)節(jié);

Maslow (wangfugen@126.com), laf.js 作者。

lafyun.com 開(kāi)源云開(kāi)發(fā)平臺(tái),前端變?nèi)珬?,無(wú)需服務(wù)端。


網(wǎng)站題目: Node.js 源碼分析
文章URL:http://weahome.cn/article/dsojhgs.html

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部