Node.js測試

根據上篇自己編譯好的node.exe運行測試實例

當然最簡單的就是helloworld

將該代碼

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

保存爲hello.js

運行node.exe hello.js

D:\pbase>node.exe hello.js
Server running at http://127.0.0.1:1337/

瀏覽器訪問http://localhost:1337返回

hello world.


遺憾的是:上述的node.exe是直接從nodejs.org上下載的,自己編譯的node.exe運行是出錯如下:

huareal@gpx /cygdrive/d/pbase/node-v0.10.16/Debug
# ./node.exe hello.js

node.js:853
      throw new Error('No such native module ' + id);
            ^
Error: No such native module events
    at Function.NativeModule.require (node.js:853:13)
    at startup (node.js:31:37)
    at node.js:901:3
應該是node.js腳本在執行到行853報錯了

第一:

  function startup() {

   .....

    if (!NativeModule.exists(id)) {
      throw new Error('No such native module ' + id);   //出錯行
    }

//錯誤的入口在startup方法

startup();

實現看看Node.js裏面有什麼

一個匿名函數,傳入參數process[線程]

(function(process) {
  this.global = this;

  function startup() {}

var EventEmitter = NativeModule.require('events').EventEmitter;//通過NativeModule獲取events的事件發射器

    process.__proto__ = Object.create(EventEmitter.prototype, {  //創建process的__proto__
      constructor: {
        value: process.constructor
      }
    });
    EventEmitter.call(process);//事件發射器調用process來處理

   //接下來的startup的處理

    startup.processFatal();

    startup.globalVariables();
    startup.globalTimeouts();
    startup.globalConsole();

    startup.processAssert();
    startup.processConfig();
    startup.processNextTick();
    startup.processStdio();
    startup.processKillAndExit();
    startup.processSignalHandlers();

    startup.processChannel();

    startup.resolveArgv0();

   關注如下的方法

startup.processSignalHandlers = function() {

    var addListener = process.addListener;
    var removeListener = process.removeListener;  

 process.on = process.addListener = function(type, listener) {
      if (isSignal(type) &&
          !signalWraps.hasOwnProperty(type)) {
        var Signal = process.binding('signal_wrap').Signal;
        var wrap = new Signal();

        wrap.unref();

        wrap.onsignal = function() { process.emit(type); };

        var signum = startup.lazyConstants()[type];
        var r = wrap.start(signum);
        if (r) {
          wrap.close();
          throw errnoException(process._errno, 'uv_signal_start');
        }

        signalWraps[type] = wrap;
      }

      return addListener.apply(this, arguments);
    };

    process.removeListener = function(type, listener) {
      var ret = removeListener.apply(this, arguments);
      if (isSignal(type)) {
        assert(signalWraps.hasOwnProperty(type));

        if (this.listeners(type).length === 0) {
          signalWraps[type].close();
          delete signalWraps[type];
        }
      }

      return ret;
    };

 

接下來是一個minimal module system

  // core modules found in lib/*.js. All core modules are compiled into the
  // node binary, so they can be loaded faster.

 

function NativeModule(id) {
    this.filename = id + '.js';
    this.id = id;
    this.exports = {};
    this.loaded = false;
  }

  NativeModule._source = process.binding('natives');
  NativeModule._cache = {};

   NativeModule.require = function(id) {
    if (id == 'native_module') {
      return NativeModule;
    }

   var cached = NativeModule.getCached(id);
    if (cached) {
      return cached.exports;
    }

    if (!NativeModule.exists(id)) {
      throw new Error('No such native module ' + id);
    }

    process.moduleLoadList.push('NativeModule ' + id);

    var nativeModule = new NativeModule(id);

    nativeModule.cache();
    nativeModule.compile();

    return nativeModule.exports;
  };

  關注NativeModule的兩個prototype函數

  NativeModule.prototype.compile = function() {
    var source = NativeModule.getSource(this.id);
    source = NativeModule.wrap(source);

    var fn = runInThisContext(source, this.filename, true);
    fn(this.exports, NativeModule.require, this, this.filename);

    this.loaded = true;
  };

  NativeModule.prototype.cache = function() {
    NativeModule._cache[this.id] = this;
  };

 反思:從Node.js的內部對象process,startup,NativeModule

  在JavaScript的對象層面抽象了一些服務對象,而這些對象藉助於V8引擎和操作系統的底層實現

然後編譯對應的javascript代碼,實現服務端框架

在lib下面有具體的javascript代碼

根據node.js的說明,這些js代碼,應該被編譯到二進制代碼中,此前的錯誤應該是沒有把這部分的代碼編譯進入導致的。

 上一篇的編譯錯誤

1>  系統找不到指定的路徑。
1>  node_js2c
1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(151,5): error MSB6006: “cmd.exe”已退出,代碼爲 1。
========== 生成: 成功 0 個,失敗 1 個,最新 0 個,跳過 0 個 ==========

node_js2c的失敗,就導致了該部分的代碼無法正常運行

嘗試編譯

huareal@gpx /cygdrive/d/pbase/node-v0.10.16/tools
# ./js2c.py node_natives.c ../lib/*.*

編譯生成的node_natives.c大小達到2.57m

分析代碼跟node_natives.h中的內容差不多,看來應該把node.js也包含在lib中,全部編譯爲node_natives.h

將src/node.js複製到lib目錄下

然後運行

# ./js2c.py node_natives.h ../lib/*.*

將生成的node_natives.h複製到src目錄下,重新編譯

運行./node.exe hello.js

# ./node.exe hello.js

node.js:309
    config = config.split('\n').slice(1).join('\n').replace(/'/g, '"');
                    ^
TypeError: Cannot call method 'split' of undefined
    at Function.startup.processConfig (node.js:309:21)
    at startup (node.js:50:13)
    at node.js:901:3

 

對應的代碼出錯行在node.js的50行

startup.processConfig();

 嘗試屏蔽node.js中的該行代碼

    // strip the gyp comment line at the beginning
    //config = config.split('\n').slice(1).join('\n').replace(/'/g, '"');

重新生成node_natives.h

編譯測試

$ ./node.exe hello.js

undefined:1
undefined
^
SyntaxError: Unexpected token u
    at Object.parse (native)
    at Function.startup.processConfig (node.js:311:27)
    at startup (node.js:50:13)
    at node.js:901:3

有些莫名的錯誤,乾脆屏蔽代碼如下

  startup.processConfig = function() {
    // used for `process.config`, but not a real module
    var config = NativeModule._source.config;
    delete NativeModule._source.config;

    // strip the gyp comment line at the beginning
    //config = config.split('\n').slice(1).join('\n').replace(/'/g, '"');

    /**
    process.config = JSON.parse(config, function(key, value) {
      if (value === 'true') return true;
      if (value === 'false') return false;
      return value;
    });
    */
  };

重新編譯測試

huareal@gpx /cygdrive/d/pbase/node-v0.10.16/Debug
$ ./node.exe hello.js
Server running at http://127.0.0.1:1337/

訪問測試:

成功hello world.

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章