mirror of https://github.com/nodejs/node.git
commit
7a8c729830
2
AUTHORS
2
AUTHORS
|
@ -162,3 +162,5 @@ Koichi Kobayashi <koichik@improvement.jp>
|
|||
Daniel Gröber <dxld@darkboxed.org>
|
||||
Konstantin Käfer <github@kkaefer.com>
|
||||
Richard Rodger <richard@ricebridge.com>
|
||||
Andreas Reich <andreas@reich.name>
|
||||
Dean McNamee <dean@gmail.com>
|
||||
|
|
27
ChangeLog
27
ChangeLog
|
@ -1,4 +1,29 @@
|
|||
2011.03.02, Version 0.4.2 (stable)
|
||||
2011.03.18, Version 0.4.3 (stable)
|
||||
|
||||
* Don't decrease server connection counter again if destroy() is called more
|
||||
than once GH-431 (Andreas Reich, Anders Conbere)
|
||||
|
||||
* Documentation improvements (koichik)
|
||||
|
||||
* Fix bug with setMaxListeners GH-682
|
||||
|
||||
* Start up memory footprint improvement. (Tom Hughes)
|
||||
|
||||
* Solaris improvements.
|
||||
|
||||
* Buffer::Length(Buffer*) should not invoke itself recursively GH-759 (Ben
|
||||
Noordhuis)
|
||||
|
||||
* TLS: Advertise support for client certs GH-774 (Theo Schlossnagle)
|
||||
|
||||
* HTTP Agent bugs: GH-787, GH-784, GH-803.
|
||||
|
||||
* Don't call GetMemoryUsage every 5 seconds.
|
||||
|
||||
* Upgrade V8 to 3.1.8.3
|
||||
|
||||
|
||||
2011.03.02, Version 0.4.2 (stable), 39280e1b5731f3fcd8cc42ad41b86cdfdcb6d58b
|
||||
|
||||
* Improve docs.
|
||||
|
||||
|
|
|
@ -1153,7 +1153,7 @@ void DeferredInlineSmiOperation::GenerateNonSmiInput() {
|
|||
}
|
||||
// Check that the *signed* result fits in a smi. Not necessary for AND, SAR
|
||||
// if the shift if more than 0 or SHR if the shit is more than 1.
|
||||
if (!( (op_ == Token::AND) ||
|
||||
if (!( (op_ == Token::AND && value_ >= 0) ||
|
||||
((op_ == Token::SAR) && (shift_value > 0)) ||
|
||||
((op_ == Token::SHR) && (shift_value > 1)))) {
|
||||
__ add(r3, int32, Operand(0x40000000), SetCC);
|
||||
|
@ -1414,8 +1414,10 @@ void CodeGenerator::SmiOperation(Token::Value op,
|
|||
default: UNREACHABLE();
|
||||
}
|
||||
deferred->BindExit();
|
||||
TypeInfo result_type =
|
||||
(op == Token::BIT_AND) ? TypeInfo::Smi() : TypeInfo::Integer32();
|
||||
TypeInfo result_type = TypeInfo::Integer32();
|
||||
if (op == Token::BIT_AND && int_value >= 0) {
|
||||
result_type = TypeInfo::Smi();
|
||||
}
|
||||
frame_->EmitPush(tos, result_type);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -115,7 +115,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
|
|||
patcher.masm()->mov(v8::internal::lr, v8::internal::pc);
|
||||
patcher.masm()->ldr(v8::internal::pc, MemOperand(v8::internal::pc, -4));
|
||||
#endif
|
||||
patcher.Emit(Debug::debug_break_return()->entry());
|
||||
patcher.Emit(Debug::debug_break_slot()->entry());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -703,38 +703,40 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
|
|||
return result;
|
||||
}
|
||||
|
||||
FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
|
||||
FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
|
||||
CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
|
||||
HistogramTimerScope timer(&Counters::parse_lazy);
|
||||
Handle<String> source(String::cast(script_->source()));
|
||||
Counters::total_parse_size.Increment(source->length());
|
||||
|
||||
Handle<SharedFunctionInfo> shared_info = info->shared_info();
|
||||
// Initialize parser state.
|
||||
source->TryFlatten();
|
||||
if (source->IsExternalTwoByteString()) {
|
||||
ExternalTwoByteStringUC16CharacterStream stream(
|
||||
Handle<ExternalTwoByteString>::cast(source),
|
||||
info->start_position(),
|
||||
info->end_position());
|
||||
shared_info->start_position(),
|
||||
shared_info->end_position());
|
||||
FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
|
||||
return result;
|
||||
} else {
|
||||
GenericStringUC16CharacterStream stream(source,
|
||||
info->start_position(),
|
||||
info->end_position());
|
||||
shared_info->start_position(),
|
||||
shared_info->end_position());
|
||||
FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
||||
FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
|
||||
UC16CharacterStream* source,
|
||||
ZoneScope* zone_scope) {
|
||||
Handle<SharedFunctionInfo> shared_info = info->shared_info();
|
||||
scanner_.Initialize(source);
|
||||
ASSERT(target_stack_ == NULL);
|
||||
|
||||
Handle<String> name(String::cast(info->name()));
|
||||
Handle<String> name(String::cast(shared_info->name()));
|
||||
fni_ = new FuncNameInferrer();
|
||||
fni_->PushEnclosingName(name);
|
||||
|
||||
|
@ -746,18 +748,20 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
|||
{
|
||||
// Parse the function literal.
|
||||
Handle<String> no_name = Factory::empty_symbol();
|
||||
Scope* scope =
|
||||
NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
|
||||
Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
|
||||
if (!info->closure().is_null()) {
|
||||
scope = Scope::DeserializeScopeChain(info, scope);
|
||||
}
|
||||
LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
|
||||
scope);
|
||||
TemporaryScope temp_scope(&this->temp_scope_);
|
||||
|
||||
if (info->strict_mode()) {
|
||||
if (shared_info->strict_mode()) {
|
||||
temp_scope.EnableStrictMode();
|
||||
}
|
||||
|
||||
FunctionLiteralType type =
|
||||
info->is_expression() ? EXPRESSION : DECLARATION;
|
||||
shared_info->is_expression() ? EXPRESSION : DECLARATION;
|
||||
bool ok = true;
|
||||
result = ParseFunctionLiteral(name,
|
||||
false, // Strict mode name already checked.
|
||||
|
@ -775,7 +779,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
|||
zone_scope->DeleteOnExit();
|
||||
if (stack_overflow_) Top::StackOverflow();
|
||||
} else {
|
||||
Handle<String> inferred_name(info->inferred_name());
|
||||
Handle<String> inferred_name(shared_info->inferred_name());
|
||||
result->set_inferred_name(inferred_name);
|
||||
}
|
||||
return result;
|
||||
|
@ -5133,7 +5137,7 @@ bool ParserApi::Parse(CompilationInfo* info) {
|
|||
Handle<Script> script = info->script();
|
||||
if (info->is_lazy()) {
|
||||
Parser parser(script, true, NULL, NULL);
|
||||
result = parser.ParseLazy(info->shared_info());
|
||||
result = parser.ParseLazy(info);
|
||||
} else {
|
||||
bool allow_natives_syntax =
|
||||
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
|
||||
|
|
|
@ -426,7 +426,7 @@ class Parser {
|
|||
bool in_global_context,
|
||||
StrictModeFlag strict_mode);
|
||||
|
||||
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
|
||||
FunctionLiteral* ParseLazy(CompilationInfo* info);
|
||||
|
||||
void ReportMessageAt(Scanner::Location loc,
|
||||
const char* message,
|
||||
|
@ -441,7 +441,7 @@ class Parser {
|
|||
// construct a hashable id, so if more than 2^17 are allowed, this
|
||||
// should be checked.
|
||||
static const int kMaxNumFunctionParameters = 32766;
|
||||
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info,
|
||||
FunctionLiteral* ParseLazy(CompilationInfo* info,
|
||||
UC16CharacterStream* source,
|
||||
ZoneScope* zone_scope);
|
||||
enum Mode {
|
||||
|
|
|
@ -148,13 +148,14 @@ Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info)
|
|||
unresolved_(16),
|
||||
decls_(4) {
|
||||
ASSERT(scope_info != NULL);
|
||||
SetDefaults(FUNCTION_SCOPE, inner_scope->outer_scope(), scope_info);
|
||||
SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
|
||||
ASSERT(resolved());
|
||||
InsertAfterScope(inner_scope);
|
||||
if (scope_info->HasHeapAllocatedLocals()) {
|
||||
num_heap_slots_ = scope_info_->NumberOfContextSlots();
|
||||
}
|
||||
|
||||
AddInnerScope(inner_scope);
|
||||
|
||||
// This scope's arguments shadow (if present) is context-allocated if an inner
|
||||
// scope accesses this one's parameters. Allocate the arguments_shadow_
|
||||
// variable if necessary.
|
||||
|
@ -175,29 +176,39 @@ Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info)
|
|||
}
|
||||
|
||||
|
||||
Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
|
||||
Scope* global_scope) {
|
||||
ASSERT(!info->closure().is_null());
|
||||
// If we have a serialized scope info, reuse it.
|
||||
Scope* innermost_scope = NULL;
|
||||
Scope* scope = NULL;
|
||||
|
||||
SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
|
||||
if (scope_info != SerializedScopeInfo::Empty()) {
|
||||
JSFunction* current = *info->closure();
|
||||
do {
|
||||
current = current->context()->closure();
|
||||
SerializedScopeInfo* scope_info = current->shared()->scope_info();
|
||||
if (scope_info != SerializedScopeInfo::Empty()) {
|
||||
scope = new Scope(scope, scope_info);
|
||||
if (innermost_scope == NULL) innermost_scope = scope;
|
||||
} else {
|
||||
ASSERT(current->context()->IsGlobalContext());
|
||||
}
|
||||
} while (!current->context()->IsGlobalContext());
|
||||
}
|
||||
|
||||
global_scope->AddInnerScope(scope);
|
||||
if (innermost_scope == NULL) innermost_scope = global_scope;
|
||||
|
||||
return innermost_scope;
|
||||
}
|
||||
|
||||
|
||||
bool Scope::Analyze(CompilationInfo* info) {
|
||||
ASSERT(info->function() != NULL);
|
||||
Scope* top = info->function()->scope();
|
||||
|
||||
// If we have a serialized scope info, reuse it.
|
||||
if (!info->closure().is_null()) {
|
||||
SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
|
||||
if (scope_info != SerializedScopeInfo::Empty()) {
|
||||
Scope* scope = top;
|
||||
JSFunction* current = *info->closure();
|
||||
do {
|
||||
current = current->context()->closure();
|
||||
SerializedScopeInfo* scope_info = current->shared()->scope_info();
|
||||
if (scope_info != SerializedScopeInfo::Empty()) {
|
||||
scope = new Scope(scope, scope_info);
|
||||
} else {
|
||||
ASSERT(current->context()->IsGlobalContext());
|
||||
}
|
||||
} while (!current->context()->IsGlobalContext());
|
||||
}
|
||||
}
|
||||
|
||||
while (top->outer_scope() != NULL) top = top->outer_scope();
|
||||
top->AllocateVariables(info->calling_context());
|
||||
|
||||
|
|
|
@ -104,6 +104,9 @@ class Scope: public ZoneObject {
|
|||
// doesn't re-allocate variables repeatedly.
|
||||
static bool Analyze(CompilationInfo* info);
|
||||
|
||||
static Scope* DeserializeScopeChain(CompilationInfo* info,
|
||||
Scope* innermost_scope);
|
||||
|
||||
// The scope name is only used for printing/debugging.
|
||||
void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
|
||||
|
||||
|
@ -313,14 +316,6 @@ class Scope: public ZoneObject {
|
|||
|
||||
explicit Scope(Type type);
|
||||
|
||||
void InsertAfterScope(Scope* scope) {
|
||||
inner_scopes_.Add(scope);
|
||||
outer_scope_ = scope->outer_scope_;
|
||||
outer_scope_->inner_scopes_.RemoveElement(scope);
|
||||
outer_scope_->inner_scopes_.Add(this);
|
||||
scope->outer_scope_ = this;
|
||||
}
|
||||
|
||||
// Scope tree.
|
||||
Scope* outer_scope_; // the immediately enclosing outer scope, or NULL
|
||||
ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes
|
||||
|
@ -413,6 +408,13 @@ class Scope: public ZoneObject {
|
|||
private:
|
||||
Scope(Scope* inner_scope, SerializedScopeInfo* scope_info);
|
||||
|
||||
void AddInnerScope(Scope* inner_scope) {
|
||||
if (inner_scope != NULL) {
|
||||
inner_scopes_.Add(inner_scope);
|
||||
inner_scope->outer_scope_ = this;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDefaults(Type type,
|
||||
Scope* outer_scope,
|
||||
SerializedScopeInfo* scope_info) {
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#define MAJOR_VERSION 3
|
||||
#define MINOR_VERSION 1
|
||||
#define BUILD_NUMBER 8
|
||||
#define PATCH_LEVEL 0
|
||||
#define PATCH_LEVEL 3
|
||||
#define CANDIDATE_VERSION false
|
||||
|
||||
// Define SONAME to have the SCons build the put a specific SONAME into the
|
||||
|
|
|
@ -37,7 +37,6 @@ function hidden_int32() {
|
|||
return 1600822924; // It's a signed Int32.
|
||||
}
|
||||
|
||||
|
||||
function f() {
|
||||
var x = non_int32(); // Not a constant.
|
||||
var y = hidden_smi(); // Not a constant.
|
||||
|
@ -66,6 +65,13 @@ function f() {
|
|||
assertEquals(46512102 & 2600822924, x & y, "10rev");
|
||||
assertEquals(1600822924 & 2600822924, x & z, "11rev");
|
||||
|
||||
assertEquals((46512102 & -0x20123456) | 1, (y & -0x20123456) | 1, "12");
|
||||
assertEquals((1600822924 & -0x20123456) | 1, (z & -0x20123456) | 1, "13");
|
||||
assertEquals((2600822924 & -0x20123456) | 1, (x & -0x20123456) | 1, "14");
|
||||
assertEquals((46512102 & -0x20123456) | 1, (-0x20123456 & y) | 1, "12rev");
|
||||
assertEquals((1600822924 & -0x20123456) | 1, (-0x20123456 & z) | 1, "13rev");
|
||||
assertEquals((2600822924 & -0x20123456) | 1, (-0x20123456 & x) | 1, "14rev");
|
||||
|
||||
assertEquals(2600822924 & 2600822924, x & x, "xx");
|
||||
assertEquals(y, y & y, "yy");
|
||||
assertEquals(z, z & z, "zz");
|
||||
|
|
|
@ -17,7 +17,10 @@ method. Here are the different string encodings;
|
|||
* `'ascii'` - for 7 bit ASCII data only. This encoding method is very fast, and will
|
||||
strip the high bit if set.
|
||||
|
||||
* `'utf8'` - Unicode characters. Many web pages and other document formats use UTF-8.
|
||||
* `'utf8'` - Multi byte encoded Unicode characters. Many web pages and other document formats use UTF-8.
|
||||
|
||||
* `'ucs2'` - 2-bytes, little endian encoded Unicode characters. It can encode
|
||||
only BMP(Basic Multilingual Plane, U+0000 - U+FFFF).
|
||||
|
||||
* `'base64'` - Base64 string encoding.
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<link type="text/css" rel="stylesheet" href="sh_vim-dark.css" />
|
||||
<link rel="alternate"
|
||||
type="application/rss+xml"
|
||||
title="node blog » Feed"
|
||||
href="http://nodeblog.wordpress.com/feed/" />
|
||||
title="node blog"
|
||||
href="http://feeds.feedburner.com/nodejs/123123123"/>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>node.js</title>
|
||||
</head>
|
||||
|
@ -24,10 +24,12 @@
|
|||
<li><a href="#download">Download</a></li>
|
||||
<li><a href="https://github.com/joyent/node/raw/master/ChangeLog">ChangeLog</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="http://nodejs.org/docs/v0.4.2/api">v0.4.2 docs</a></li>
|
||||
<li><a href="http://nodejs.org/docs/v0.4.3/api">v0.4.3 docs</a></li>
|
||||
<br/>
|
||||
<li><B><a href="https://github.com/joyent/node/wiki">Wiki</a></B></li>
|
||||
<li><B><a href="http://blog.nodejs.org/">Blog</a></B></li>
|
||||
<br/>
|
||||
<li><a href="http://chat.nodejs.org/">Demo</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
<div id="content">
|
||||
|
@ -89,6 +91,12 @@ server.listen(8124, "127.0.0.1");
|
|||
Go to <a href="https://github.com/joyent/node/wiki">the Wiki</a> for lots more information.
|
||||
</p>
|
||||
|
||||
<h2 id="video">Introduction</h2>
|
||||
|
||||
<iframe title="YouTube video player" width="640" height="390"
|
||||
src="http://www.youtube.com/embed/jo_B4LTHi3I" frameborder="0"
|
||||
allowfullscreen></iframe>
|
||||
|
||||
<h2 id="download">Download</h2>
|
||||
|
||||
<p>
|
||||
|
@ -96,9 +104,9 @@ server.listen(8124, "127.0.0.1");
|
|||
</p>
|
||||
|
||||
<p>
|
||||
2011.03.02
|
||||
<a href="http://nodejs.org/dist/node-v0.4.2.tar.gz">node-v0.4.2.tar.gz</a>
|
||||
(<a href="http://nodejs.org/docs/v0.4.2/api/index.html">Documentation</a>)
|
||||
2011.03.18
|
||||
<a href="http://nodejs.org/dist/node-v0.4.3.tar.gz">node-v0.4.3.tar.gz</a>
|
||||
(<a href="http://nodejs.org/docs/v0.4.3/api/index.html">Documentation</a>)
|
||||
</p>
|
||||
|
||||
<p>Historical: <a href="http://nodejs.org/dist">versions</a>, <a href="http://nodejs.org/docs">docs</a></p>
|
||||
|
|
|
@ -77,7 +77,7 @@ function getAgent(options) {
|
|||
return agent;
|
||||
}
|
||||
exports.getAgent = getAgent;
|
||||
|
||||
exports.Agent = Agent;
|
||||
|
||||
exports.request = function(options, cb) {
|
||||
if (options.agent === undefined) {
|
||||
|
|
|
@ -548,6 +548,8 @@ Socket.prototype.setEncoding = function(encoding) {
|
|||
|
||||
|
||||
function doConnect(socket, port, host) {
|
||||
if (socket.destroyed) return;
|
||||
|
||||
timers.active(socket);
|
||||
|
||||
try {
|
||||
|
|
34
lib/tls.js
34
lib/tls.js
|
@ -168,25 +168,23 @@ CryptoStream.prototype.getCipher = function(err) {
|
|||
|
||||
|
||||
CryptoStream.prototype.end = function(d) {
|
||||
if (!this.writable) {
|
||||
throw new Error('CryptoStream is not writable');
|
||||
if (this.writable) {
|
||||
if (this.pair._done) return;
|
||||
|
||||
if (d) {
|
||||
this.write(d);
|
||||
}
|
||||
|
||||
this._pending.push(END_OF_FILE);
|
||||
this._pendingCallbacks.push(null);
|
||||
|
||||
// If this is an encrypted stream then we need to disable further 'data'
|
||||
// events.
|
||||
|
||||
this.writable = false;
|
||||
|
||||
this.pair._cycle();
|
||||
}
|
||||
|
||||
if (this.pair._done) return;
|
||||
|
||||
if (d) {
|
||||
this.write(d);
|
||||
}
|
||||
|
||||
this._pending.push(END_OF_FILE);
|
||||
this._pendingCallbacks.push(null);
|
||||
|
||||
// If this is an encrypted stream then we need to disable further 'data'
|
||||
// events.
|
||||
|
||||
this.writable = false;
|
||||
|
||||
this.pair._cycle();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ exports.open = function(path, args) {
|
|||
child = spawn(path, args, {
|
||||
env: env,
|
||||
customFds: [masterFD, masterFD, masterFD],
|
||||
setuid: true
|
||||
setsid: true
|
||||
});
|
||||
|
||||
return [stream, child];
|
||||
|
|
|
@ -1494,9 +1494,10 @@ static void CheckStatus(EV_P_ ev_timer *watcher, int revents) {
|
|||
assert(revents == EV_TIMEOUT);
|
||||
|
||||
// check memory
|
||||
size_t rss, vsize;
|
||||
if (!ev_is_active(&gc_idle) && Platform::GetMemory(&rss, &vsize) == 0) {
|
||||
if (rss > 1024*1024*128) {
|
||||
if (!ev_is_active(&gc_idle)) {
|
||||
HeapStatistics stats;
|
||||
V8::GetHeapStatistics(&stats);
|
||||
if (stats.total_heap_size() > 1024 * 1024 * 128) {
|
||||
// larger than 128 megs, just start the idle watcher
|
||||
ev_idle_start(EV_A_ &gc_idle);
|
||||
return;
|
||||
|
|
|
@ -136,6 +136,7 @@ Buffer* Buffer::New(size_t length) {
|
|||
|
||||
Local<Value> arg = Integer::NewFromUnsigned(length);
|
||||
Local<Object> b = constructor_template->GetFunction()->NewInstance(1, &arg);
|
||||
if (b.IsEmpty()) return NULL;
|
||||
|
||||
return ObjectWrap::Unwrap<Buffer>(b);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
var common = require('../common');
|
||||
var net = require('net');
|
||||
var assert = require('assert');
|
||||
|
||||
// Connect to something that we need to DNS resolve
|
||||
var c = net.createConnection(80, "google.com");
|
||||
c.destroy();
|
2
wscript
2
wscript
|
@ -885,7 +885,7 @@ def build(bld):
|
|||
, 'CPPFLAGS' : " ".join(program.env["CPPFLAGS"]).replace('"', '\\"')
|
||||
, 'LIBFLAGS' : " ".join(program.env["LIBFLAGS"]).replace('"', '\\"')
|
||||
, 'PREFIX' : safe_path(program.env["PREFIX"])
|
||||
, 'VERSION' : '0.4.2' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version.
|
||||
, 'VERSION' : '0.4.3' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version.
|
||||
}
|
||||
return x
|
||||
|
||||
|
|
Loading…
Reference in New Issue