根据上篇自己编译好的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.