Browse Source

Merge branch 'v0.4'

Conflicts:
	src/node_version.h
	test/simple/test-buffer.js
v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
bfa9db9dd6
  1. 4
      AUTHORS
  2. 38
      ChangeLog
  3. 1
      Makefile
  4. 40
      deps/v8/src/arm/code-stubs-arm.cc
  5. 1
      deps/v8/src/arm/code-stubs-arm.h
  6. 5
      deps/v8/src/arm/deoptimizer-arm.cc
  7. 1
      deps/v8/src/arm/lithium-codegen-arm.cc
  8. 1
      deps/v8/src/assembler.cc
  9. 3
      deps/v8/src/assembler.h
  10. 7
      deps/v8/src/deoptimizer.h
  11. 1
      deps/v8/src/heap.h
  12. 9
      deps/v8/src/hydrogen-instructions.h
  13. 37
      deps/v8/src/ia32/code-stubs-ia32.cc
  14. 1
      deps/v8/src/ia32/code-stubs-ia32.h
  15. 74
      deps/v8/src/ia32/deoptimizer-ia32.cc
  16. 40
      deps/v8/src/ia32/lithium-codegen-ia32.cc
  17. 16
      deps/v8/src/ic.cc
  18. 1
      deps/v8/src/ic.h
  19. 7
      deps/v8/src/platform-freebsd.cc
  20. 2
      deps/v8/src/version.cc
  21. 36
      deps/v8/src/x64/code-stubs-x64.cc
  22. 1
      deps/v8/src/x64/code-stubs-x64.h
  23. 5
      deps/v8/src/x64/deoptimizer-x64.cc
  24. 16
      deps/v8/src/x64/lithium-codegen-x64.cc
  25. 65
      deps/v8/test/mjsunit/compiler/regress-loadfield.js
  26. 52
      deps/v8/test/mjsunit/regress/regress-lazy-deopt-reloc.js
  27. 4
      doc/api/all.markdown
  28. 4
      doc/api/buffers.markdown
  29. 3
      doc/api/child_processes.markdown
  30. 20
      doc/api/crypto.markdown
  31. 1
      doc/api/dgram.markdown
  32. 17
      doc/api/fs.markdown
  33. 11
      doc/api/globals.markdown
  34. 4
      doc/api/http.markdown
  35. 2
      doc/api/modules.markdown
  36. 4
      doc/api/net.markdown
  37. 6
      doc/api/streams.markdown
  38. 13
      doc/api/tls.markdown
  39. BIN
      doc/favicon.ico
  40. 12
      doc/index.html
  41. BIN
      doc/joyent-logo_orange_nodeorg-01.png
  42. 2
      doc/template.html
  43. 2
      doc/v0.4_announcement.html
  44. 2
      lib/buffer.js
  45. 26
      lib/events.js
  46. 19
      lib/fs.js
  47. 16
      lib/http.js
  48. 3
      lib/https.js
  49. 40
      lib/stream.js
  50. 2
      lib/tls.js
  51. 6
      lib/util.js
  52. 37
      src/node_crypto.cc
  53. 16
      src/node_crypto.h
  54. 7
      src/node_file.cc
  55. 9
      src/node_stdio.cc
  56. 4
      test/common.js
  57. 71
      test/pummel/test-regress-GH-814.js
  58. 85
      test/pummel/test-regress-GH-814_2.js
  59. 20
      test/simple/test-assert.js
  60. 60
      test/simple/test-buffer.js
  61. 4
      test/simple/test-console.js
  62. 8
      test/simple/test-event-emitter-once.js
  63. 7
      test/simple/test-fs-read-stream.js
  64. 150
      test/simple/test-http-host-headers.js
  65. 82
      test/simple/test-stream-pipe-cleanup.js
  66. 6
      wscript

4
AUTHORS

@ -164,3 +164,7 @@ Konstantin Käfer <github@kkaefer.com>
Richard Rodger <richard@ricebridge.com>
Andreas Reich <andreas@reich.name>
Dean McNamee <dean@gmail.com>
Trevor Burnham <trevor@databraid.com>
Zachary Scott <zachary.s.scott@gmail.com>
Arnout Kazemier <info@3rd-Eden.com>

38
ChangeLog

@ -1,4 +1,40 @@
2011.03.18, Version 0.4.3 (stable)
2011.04.01, Version 0.4.5 (stable)
* Fix listener leak in stream.pipe() (Mikeal Rogers)
* Retain buffers in fs.read/write() GH-814 (Jorge Chamorro Bieling)
* TLS performance improvements
* SlowBuffer.prototype.slice bug GH-843
* process.stderr.write should return true
* Immediate pause/resume race condition GH-535 (isaacs)
* Set default host header properly GH-721 (isaacs)
* Upgrade V8 to 3.1.8.8
2011.03.26, Version 0.4.4 (stable), 25122b986a90ba0982697b7abcb0158c302a1019
* CryptoStream.end shouldn't throw if not writable GH-820
* Drop out if connection destroyed before connect() GH-819
* expose https.Agent
* Correctly setsid in tty.open GH-815
* Bug fix for failed buffer construction
* Added support for removing .once listeners (GH-806)
* Upgrade V8 to 3.1.8.5
2011.03.18, Version 0.4.3 (stable), c095ce1a1b41ca015758a713283bf1f0bd41e4c4
* Don't decrease server connection counter again if destroy() is called more
than once GH-431 (Andreas Reich, Anders Conbere)

1
Makefile

@ -70,6 +70,7 @@ website_files = \
build/doc/sh_vim-dark.css \
build/doc/logo.png \
build/doc/sponsored.png \
build/doc/favicon.ico \
build/doc/pipe.css
doc: build/default/node $(apidoc_dirs) $(website_files) $(apiassets) $(apidocs)

40
deps/v8/src/arm/code-stubs-arm.cc

@ -2856,6 +2856,9 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
case TRBinaryOpIC::HEAP_NUMBER:
GenerateHeapNumberStub(masm);
break;
case TRBinaryOpIC::ODDBALL:
GenerateOddballStub(masm);
break;
case TRBinaryOpIC::STRING:
GenerateStringStub(masm);
break;
@ -3572,10 +3575,43 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
}
void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
Label call_runtime;
if (op_ == Token::ADD) {
// Handle string addition here, because it is the only operation
// that does not do a ToNumber conversion on the operands.
GenerateAddStrings(masm);
}
// Convert oddball arguments to numbers.
Label check, done;
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r1, ip);
__ b(ne, &check);
if (Token::IsBitOp(op_)) {
__ mov(r1, Operand(Smi::FromInt(0)));
} else {
__ LoadRoot(r1, Heap::kNanValueRootIndex);
}
__ jmp(&done);
__ bind(&check);
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r0, ip);
__ b(ne, &done);
if (Token::IsBitOp(op_)) {
__ mov(r0, Operand(Smi::FromInt(0)));
} else {
__ LoadRoot(r0, Heap::kNanValueRootIndex);
}
__ bind(&done);
GenerateHeapNumberStub(masm);
}
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
Label not_numbers, call_runtime;
ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER);
GenerateFPOperation(masm, false, &not_numbers, &call_runtime);
__ bind(&not_numbers);

1
deps/v8/src/arm/code-stubs-arm.h

@ -302,6 +302,7 @@ class TypeRecordingBinaryOpStub: public CodeStub {
void GenerateSmiStub(MacroAssembler* masm);
void GenerateInt32Stub(MacroAssembler* masm);
void GenerateHeapNumberStub(MacroAssembler* masm);
void GenerateOddballStub(MacroAssembler* masm);
void GenerateStringStub(MacroAssembler* masm);
void GenerateGenericStub(MacroAssembler* masm);
void GenerateAddStrings(MacroAssembler* masm);

5
deps/v8/src/arm/deoptimizer-arm.cc

@ -44,6 +44,11 @@ int Deoptimizer::patch_size() {
}
void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
// Nothing to do. No new relocation information is written for lazy
// deoptimization on ARM.
}
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;

1
deps/v8/src/arm/lithium-codegen-arm.cc

@ -75,6 +75,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
code->set_stack_slots(StackSlotCount());
code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
PopulateDeoptimizationData(code);
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
}

1
deps/v8/src/assembler.cc

@ -139,6 +139,7 @@ const int kPCJumpTag = (1 << kExtraTagBits) - 1;
const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
const int kVariableLengthPCJumpTopTag = 1;
const int kChunkBits = 7;

3
deps/v8/src/assembler.h

@ -192,6 +192,9 @@ class RelocInfo BASE_EMBEDDED {
// The maximum size for a call instruction including pc-jump.
static const int kMaxCallSize = 6;
// The maximum pc delta that will use the short encoding.
static const int kMaxSmallPCDelta;
enum Mode {
// Please note the order is important (see IsCodeTarget, IsGCRelocMode).
CONSTRUCT_CALL, // code target that is a call to a JavaScript constructor.

7
deps/v8/src/deoptimizer.h

@ -110,6 +110,13 @@ class Deoptimizer : public Malloced {
int fp_to_sp_delta);
static Deoptimizer* Grab();
// Makes sure that there is enough room in the relocation
// information of a code object to perform lazy deoptimization
// patching. If there is not enough room a new relocation
// information object is allocated and comments are added until it
// is big enough.
static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
// Deoptimize the function now. Its current optimized code will never be run
// again and any activations of the optimized code will get deoptimized when
// execution returns.

1
deps/v8/src/heap.h

@ -163,6 +163,7 @@ namespace internal {
V(name_symbol, "name") \
V(number_symbol, "number") \
V(Number_symbol, "Number") \
V(nan_symbol, "NaN") \
V(RegExp_symbol, "RegExp") \
V(source_symbol, "source") \
V(global_symbol, "global") \

9
deps/v8/src/hydrogen-instructions.h

@ -1423,8 +1423,9 @@ class HJSArrayLength: public HUnaryOperation {
// object. It is guaranteed to be 32 bit integer, but it can be
// represented as either a smi or heap number.
set_representation(Representation::Tagged());
SetFlag(kDependsOnArrayLengths);
SetFlag(kUseGVN);
SetFlag(kDependsOnArrayLengths);
SetFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) const {
@ -1442,8 +1443,8 @@ class HFixedArrayLength: public HUnaryOperation {
public:
explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Tagged());
SetFlag(kDependsOnArrayLengths);
SetFlag(kUseGVN);
SetFlag(kDependsOnArrayLengths);
}
virtual Representation RequiredInputRepresentation(int index) const {
@ -2268,6 +2269,7 @@ class HCompareJSObjectEq: public HBinaryOperation {
: HBinaryOperation(left, right) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetFlag(kDependsOnMaps);
}
virtual bool EmitAtUses() const {
@ -2943,6 +2945,7 @@ class HLoadNamedField: public HUnaryOperation {
offset_(offset) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetFlag(kDependsOnMaps);
if (is_in_object) {
SetFlag(kDependsOnInobjectFields);
} else {
@ -3269,6 +3272,7 @@ class HStringCharCodeAt: public HBinaryOperation {
: HBinaryOperation(string, index) {
set_representation(Representation::Integer32());
SetFlag(kUseGVN);
SetFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) const {
@ -3296,6 +3300,7 @@ class HStringLength: public HUnaryOperation {
explicit HStringLength(HValue* string) : HUnaryOperation(string) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) const {

37
deps/v8/src/ia32/code-stubs-ia32.cc

@ -1342,6 +1342,9 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
case TRBinaryOpIC::HEAP_NUMBER:
GenerateHeapNumberStub(masm);
break;
case TRBinaryOpIC::ODDBALL:
GenerateOddballStub(masm);
break;
case TRBinaryOpIC::STRING:
GenerateStringStub(masm);
break;
@ -2006,9 +2009,41 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
}
void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
Label call_runtime;
if (op_ == Token::ADD) {
// Handle string addition here, because it is the only operation
// that does not do a ToNumber conversion on the operands.
GenerateAddStrings(masm);
}
// Convert odd ball arguments to numbers.
NearLabel check, done;
__ cmp(edx, Factory::undefined_value());
__ j(not_equal, &check);
if (Token::IsBitOp(op_)) {
__ xor_(edx, Operand(edx));
} else {
__ mov(edx, Immediate(Factory::nan_value()));
}
__ jmp(&done);
__ bind(&check);
__ cmp(eax, Factory::undefined_value());
__ j(not_equal, &done);
if (Token::IsBitOp(op_)) {
__ xor_(eax, Operand(eax));
} else {
__ mov(eax, Immediate(Factory::nan_value()));
}
__ bind(&done);
GenerateHeapNumberStub(masm);
}
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
Label call_runtime;
ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER);
// Floating point case.
switch (op_) {

1
deps/v8/src/ia32/code-stubs-ia32.h

@ -306,6 +306,7 @@ class TypeRecordingBinaryOpStub: public CodeStub {
void GenerateSmiStub(MacroAssembler* masm);
void GenerateInt32Stub(MacroAssembler* masm);
void GenerateHeapNumberStub(MacroAssembler* masm);
void GenerateOddballStub(MacroAssembler* masm);
void GenerateStringStub(MacroAssembler* masm);
void GenerateGenericStub(MacroAssembler* masm);
void GenerateAddStrings(MacroAssembler* masm);

74
deps/v8/src/ia32/deoptimizer-ia32.cc

@ -55,6 +55,80 @@ static void ZapCodeRange(Address start, Address end) {
}
void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
HandleScope scope;
// Compute the size of relocation information needed for the code
// patching in Deoptimizer::DeoptimizeFunction.
int min_reloc_size = 0;
Address prev_reloc_address = code->instruction_start();
Address code_start_address = code->instruction_start();
SafepointTable table(*code);
for (unsigned i = 0; i < table.length(); ++i) {
Address curr_reloc_address = code_start_address + table.GetPcOffset(i);
ASSERT_GE(curr_reloc_address, prev_reloc_address);
SafepointEntry safepoint_entry = table.GetEntry(i);
int deoptimization_index = safepoint_entry.deoptimization_index();
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
// The gap code is needed to get to the state expected at the
// bailout and we need to skip the call opcode to get to the
// address that needs reloc.
curr_reloc_address += safepoint_entry.gap_code_size() + 1;
int pc_delta = curr_reloc_address - prev_reloc_address;
// We use RUNTIME_ENTRY reloc info which has a size of 2 bytes
// if encodable with small pc delta encoding and up to 6 bytes
// otherwise.
if (pc_delta <= RelocInfo::kMaxSmallPCDelta) {
min_reloc_size += 2;
} else {
min_reloc_size += 6;
}
prev_reloc_address = curr_reloc_address;
}
}
// If the relocation information is not big enough we create a new
// relocation info object that is padded with comments to make it
// big enough for lazy doptimization.
int reloc_length = code->relocation_info()->length();
if (min_reloc_size > reloc_length) {
int comment_reloc_size = RelocInfo::kMinRelocCommentSize;
// Padding needed.
int min_padding = min_reloc_size - reloc_length;
// Number of comments needed to take up at least that much space.
int additional_comments =
(min_padding + comment_reloc_size - 1) / comment_reloc_size;
// Actual padding size.
int padding = additional_comments * comment_reloc_size;
// Allocate new relocation info and copy old relocation to the end
// of the new relocation info array because relocation info is
// written and read backwards.
Handle<ByteArray> new_reloc =
Factory::NewByteArray(reloc_length + padding, TENURED);
memcpy(new_reloc->GetDataStartAddress() + padding,
code->relocation_info()->GetDataStartAddress(),
reloc_length);
// Create a relocation writer to write the comments in the padding
// space. Use position 0 for everything to ensure short encoding.
RelocInfoWriter reloc_info_writer(
new_reloc->GetDataStartAddress() + padding, 0);
intptr_t comment_string
= reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString);
RelocInfo rinfo(0, RelocInfo::COMMENT, comment_string);
for (int i = 0; i < additional_comments; ++i) {
#ifdef DEBUG
byte* pos_before = reloc_info_writer.pos();
#endif
reloc_info_writer.Write(&rinfo);
ASSERT(RelocInfo::kMinRelocCommentSize ==
pos_before - reloc_info_writer.pos());
}
// Replace relocation information on the code object.
code->set_relocation_info(*new_reloc);
}
}
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;

40
deps/v8/src/ia32/lithium-codegen-ia32.cc

@ -31,6 +31,7 @@
#include "ia32/lithium-codegen-ia32.h"
#include "code-stubs.h"
#include "deoptimizer.h"
#include "stub-cache.h"
namespace v8 {
@ -43,20 +44,13 @@ class SafepointGenerator : public PostCallGenerator {
public:
SafepointGenerator(LCodeGen* codegen,
LPointerMap* pointers,
int deoptimization_index,
bool ensure_reloc_space = false)
int deoptimization_index)
: codegen_(codegen),
pointers_(pointers),
deoptimization_index_(deoptimization_index),
ensure_reloc_space_(ensure_reloc_space) { }
deoptimization_index_(deoptimization_index) {}
virtual ~SafepointGenerator() { }
virtual void Generate() {
// Ensure that we have enough space in the reloc info to patch
// this with calls when doing deoptimization.
if (ensure_reloc_space_) {
codegen_->EnsureRelocSpaceForDeoptimization();
}
codegen_->RecordSafepoint(pointers_, deoptimization_index_);
}
@ -64,7 +58,6 @@ class SafepointGenerator : public PostCallGenerator {
LCodeGen* codegen_;
LPointerMap* pointers_;
int deoptimization_index_;
bool ensure_reloc_space_;
};
@ -78,7 +71,6 @@ bool LCodeGen::GenerateCode() {
return GeneratePrologue() &&
GenerateBody() &&
GenerateDeferredCode() &&
GenerateRelocPadding() &&
GenerateSafepointTable();
}
@ -88,6 +80,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
code->set_stack_slots(StackSlotCount());
code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
PopulateDeoptimizationData(code);
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
}
@ -385,22 +378,6 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
}
void LCodeGen::EnsureRelocSpaceForDeoptimization() {
// Since we patch the reloc info with RUNTIME_ENTRY calls every patch
// site will take up 2 bytes + any pc-jumps.
// We are conservative and always reserver 6 bytes in case where a
// simple pc-jump is not enough.
uint32_t pc_delta =
masm()->pc_offset() - deoptimization_reloc_size.last_pc_offset;
if (is_uintn(pc_delta, 6)) {
deoptimization_reloc_size.min_size += 2;
} else {
deoptimization_reloc_size.min_size += 6;
}
deoptimization_reloc_size.last_pc_offset = masm()->pc_offset();
}
void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged) {
@ -454,7 +431,6 @@ void LCodeGen::CallCode(Handle<Code> code,
}
__ call(code, mode);
EnsureRelocSpaceForDeoptimization();
RegisterLazyDeoptimization(instr);
// Signal that we don't inline smi code before these stubs in the
@ -479,6 +455,7 @@ void LCodeGen::CallRuntime(Runtime::Function* fun,
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
__ CallRuntime(fun, argc);
RegisterLazyDeoptimization(instr);
}
@ -2299,8 +2276,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
RegisterEnvironmentForDeoptimization(env);
SafepointGenerator safepoint_generator(this,
pointers,
env->deoptimization_index(),
true);
env->deoptimization_index());
v8::internal::ParameterCount actual(eax);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
}
@ -2372,7 +2348,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
__ CallSelf();
} else {
__ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
EnsureRelocSpaceForDeoptimization();
}
// Setup deoptimization.
@ -3835,8 +3810,7 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
// builtin)
SafepointGenerator safepoint_generator(this,
pointers,
env->deoptimization_index(),
true);
env->deoptimization_index());
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ push(Immediate(Smi::FromInt(strict_mode_flag())));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);

16
deps/v8/src/ic.cc

@ -1113,6 +1113,16 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
MaybeObject* KeyedLoadIC::Load(State state,
Handle<Object> object,
Handle<Object> key) {
// Check for values that can be converted into a symbol.
// TODO(1295): Remove this code.
HandleScope scope;
if (key->IsHeapNumber() &&
isnan(HeapNumber::cast(*key)->value())) {
key = Factory::nan_symbol();
} else if (key->IsUndefined()) {
key = Factory::undefined_symbol();
}
if (key->IsSymbol()) {
Handle<String> name = Handle<String>::cast(key);
@ -2082,6 +2092,7 @@ const char* TRBinaryOpIC::GetName(TypeInfo type_info) {
case SMI: return "SMI";
case INT32: return "Int32s";
case HEAP_NUMBER: return "HeapNumbers";
case ODDBALL: return "Oddball";
case STRING: return "Strings";
case GENERIC: return "Generic";
default: return "Invalid";
@ -2096,6 +2107,7 @@ TRBinaryOpIC::State TRBinaryOpIC::ToState(TypeInfo type_info) {
case SMI:
case INT32:
case HEAP_NUMBER:
case ODDBALL:
case STRING:
return MONOMORPHIC;
case GENERIC:
@ -2143,6 +2155,10 @@ TRBinaryOpIC::TypeInfo TRBinaryOpIC::GetTypeInfo(Handle<Object> left,
return STRING;
}
// Check for oddball objects.
if (left->IsUndefined() && right->IsNumber()) return ODDBALL;
if (left->IsNumber() && right->IsUndefined()) return ODDBALL;
return GENERIC;
}

1
deps/v8/src/ic.h

@ -576,6 +576,7 @@ class TRBinaryOpIC: public IC {
SMI,
INT32,
HEAP_NUMBER,
ODDBALL,
STRING, // Only used for addition operation. At least one string operand.
GENERIC
};

7
deps/v8/src/platform-freebsd.cc

@ -526,6 +526,11 @@ class FreeBSDMutex : public Mutex {
return result;
}
virtual bool TryLock() {
int result = pthread_mutex_trylock(&mutex_);
return result == 0;
}
private:
pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms.
};
@ -604,7 +609,7 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
TickSample sample;
// We always sample the VM state.
sample.state = VMState::current_state();
sample.state = Top::current_vm_state();
// If profiling, we extract the current pc and sp.
if (active_sampler_->IsProfiling()) {

2
deps/v8/src/version.cc

@ -35,7 +35,7 @@
#define MAJOR_VERSION 3
#define MINOR_VERSION 1
#define BUILD_NUMBER 8
#define PATCH_LEVEL 3
#define PATCH_LEVEL 8
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the

36
deps/v8/src/x64/code-stubs-x64.cc

@ -1053,6 +1053,9 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
case TRBinaryOpIC::HEAP_NUMBER:
GenerateHeapNumberStub(masm);
break;
case TRBinaryOpIC::ODDBALL:
GenerateOddballStub(masm);
break;
case TRBinaryOpIC::STRING:
GenerateStringStub(masm);
break;
@ -1428,6 +1431,39 @@ void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
}
void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
Label call_runtime;
if (op_ == Token::ADD) {
// Handle string addition here, because it is the only operation
// that does not do a ToNumber conversion on the operands.
GenerateStringAddCode(masm);
}
// Convert oddball arguments to numbers.
NearLabel check, done;
__ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
__ j(not_equal, &check);
if (Token::IsBitOp(op_)) {
__ xor_(rdx, rdx);
} else {
__ LoadRoot(rdx, Heap::kNanValueRootIndex);
}
__ jmp(&done);
__ bind(&check);
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
__ j(not_equal, &done);
if (Token::IsBitOp(op_)) {
__ xor_(rax, rax);
} else {
__ LoadRoot(rax, Heap::kNanValueRootIndex);
}
__ bind(&done);
GenerateHeapNumberStub(masm);
}
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
Label gc_required, not_number;
GenerateFloatingPointCode(masm, &gc_required, &not_number);

1
deps/v8/src/x64/code-stubs-x64.h

@ -289,6 +289,7 @@ class TypeRecordingBinaryOpStub: public CodeStub {
void GenerateSmiStub(MacroAssembler* masm);
void GenerateInt32Stub(MacroAssembler* masm);
void GenerateHeapNumberStub(MacroAssembler* masm);
void GenerateOddballStub(MacroAssembler* masm);
void GenerateStringStub(MacroAssembler* masm);
void GenerateGenericStub(MacroAssembler* masm);

5
deps/v8/src/x64/deoptimizer-x64.cc

@ -101,6 +101,11 @@ class SafepointTableDeoptimiztionEntryIterator {
};
void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
// TODO(1276): Implement.
}
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;

16
deps/v8/src/x64/lithium-codegen-x64.cc

@ -43,20 +43,16 @@ class SafepointGenerator : public PostCallGenerator {
public:
SafepointGenerator(LCodeGen* codegen,
LPointerMap* pointers,
int deoptimization_index,
bool ensure_reloc_space = false)
int deoptimization_index)
: codegen_(codegen),
pointers_(pointers),
deoptimization_index_(deoptimization_index),
ensure_reloc_space_(ensure_reloc_space) { }
deoptimization_index_(deoptimization_index) { }
virtual ~SafepointGenerator() { }
virtual void Generate() {
// Ensure that we have enough space in the reloc info to patch
// this with calls when doing deoptimization.
if (ensure_reloc_space_) {
codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true);
}
codegen_->RecordSafepoint(pointers_, deoptimization_index_);
}
@ -64,7 +60,6 @@ class SafepointGenerator : public PostCallGenerator {
LCodeGen* codegen_;
LPointerMap* pointers_;
int deoptimization_index_;
bool ensure_reloc_space_;
};
@ -87,6 +82,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
code->set_stack_slots(StackSlotCount());
code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
PopulateDeoptimizationData(code);
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
}
@ -2220,8 +2216,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
RegisterEnvironmentForDeoptimization(env);
SafepointGenerator safepoint_generator(this,
pointers,
env->deoptimization_index(),
true);
env->deoptimization_index());
v8::internal::ParameterCount actual(rax);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
}
@ -3597,8 +3592,7 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
// builtin)
SafepointGenerator safepoint_generator(this,
pointers,
env->deoptimization_index(),
true);
env->deoptimization_index());
__ Push(Smi::FromInt(strict_mode_flag()));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
}

65
deps/v8/test/mjsunit/compiler/regress-loadfield.js

@ -0,0 +1,65 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Regression test for GVN on field loads.
function bar() {}
// Make sure there is a transition on adding "bar" inobject property.
var b = new bar();
b.bar = "bar";
function test(a) {
var b = new Array(10);
for (var i = 0; i < 10; i++) {
b[i] = new bar();
}
for (var i = 0; i < 10; i++) {
b[i].bar = a.foo;
}
}
// Create an object with fast backing store properties.
var a = {};
a.p1 = "";
a.p2 = "";
a.p3 = "";
a.p4 = "";
a.p5 = "";
a.p6 = "";
a.p7 = "";
a.p8 = "";
a.p9 = "";
a.p10 = "";
a.p11 = "";
a.foo = "foo";
for (var i = 0; i < 100000; i++) {
test(a);
}
test("");

52
deps/v8/test/mjsunit/regress/regress-lazy-deopt-reloc.js

@ -0,0 +1,52 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Do not generate debug code since that will space things differently
// in the generated code.
// Flags: --allow-natives-syntax --expose-gc --nodebug-code
// Regression test for issue where we did not pad the relocation
// information enough to have room for lazy deoptimization.
function kaboom() {
var a = function () {},
b = function () {},
c, d = function () { var d = []; },
e = function () { var e = {}; };
c = function () { d(); b(); };
return function (x, y) {
c();
a();
return function f() { }({});
};
}
kaboom();
%DeoptimizeFunction(kaboom);
gc();

4
doc/api/all.markdown

@ -17,15 +17,15 @@
@include fs
@include path
@include net
@include dns
@include dgram
@include dns
@include http
@include https
@include url
@include querystring
@include readline
@include repl
@include script
@include vm
@include child_processes
@include assert
@include tty

4
doc/api/buffers.markdown

@ -25,7 +25,7 @@ only BMP(Basic Multilingual Plane, U+0000 - U+FFFF).
* `'base64'` - Base64 string encoding.
* `'binary'` - A way of encoding raw binary data into strings by using only
the first 8 bits of each character. This encoding method is depreciated and
the first 8 bits of each character. This encoding method is deprecated and
should be avoided in favor of `Buffer` objects where possible. This encoding
will be removed in future versions of Node.
@ -57,8 +57,6 @@ Example: write a utf8 string into a buffer, then print it
len = buf.write('\u00bd + \u00bc = \u00be', 0);
console.log(len + " bytes: " + buf.toString('utf8', 0, len));
// 12 bytes: ½ + ¼ = ¾
### buffer.toString(encoding, start=0, end=buffer.length)

3
doc/api/child_processes.markdown

@ -130,8 +130,9 @@ Example of checking for failed exec:
var spawn = require('child_process').spawn,
child = spawn('bad_command');
child.stderr.setEncoding('utf8');
child.stderr.on('data', function (data) {
if (/^execvp\(\)/.test(data.asciiSlice(0,data.length))) {
if (/^execvp\(\)/.test(data)) {
console.log('Failed to start child process.');
}
});

20
doc/api/crypto.markdown

@ -29,6 +29,24 @@ which can be used to generate hash digests.
of OpenSSL on the platform. Examples are `'sha1'`, `'md5'`, `'sha256'`, `'sha512'`, etc.
On recent releases, `openssl list-message-digest-algorithms` will display the available digest algorithms.
Example: this program that takes the sha1 sum of a file
var filename = process.argv[2];
var crypto = require('crypto');
var fs = require('fs');
var shasum = crypto.createHash('sha1');
var s = fs.ReadStream(filename);
s.on('data', function(d) {
shasum.update(d);
});
s.on('end', function() {
var d = shasum.digest('hex');
console.log(d + ' ' + filename);
});
### hash.update(data)
Updates the hash content with the given `data`.
@ -124,7 +142,7 @@ This can be called many times with new data as it is streamed.
### verifier.verify(cert, signature, signature_format='binary')
Verifies the signed data by using the `cert` which is a string containing
the PEM encoded public key, and `signature`, which is the previously calculates
the PEM encoded certificate, and `signature`, which is the previously calculates
signature for the data, in the `signature_format` which can be `'binary'`, `'hex'` or `'base64'`.
Returns true or false depending on the validity of the signature for the data and public key.

1
doc/api/dgram.markdown

@ -124,7 +124,6 @@ Example of a UDP server listening on port 41234:
var dgram = require("dgram");
var server = dgram.createSocket("udp4");
var messageToSend = new Buffer("A message to send");
server.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " +

17
doc/api/fs.markdown

@ -82,7 +82,7 @@ Synchronous chmod(2).
### fs.stat(path, [callback])
Asynchronous stat(2). The callback gets two arguments `(err, stats)` where
`stats` is a `fs.Stats` object. It looks like this:
`stats` is a [`fs.Stats`](#fs.Stats) object. It looks like this:
{ dev: 2049,
ino: 305352,
@ -98,7 +98,7 @@ Asynchronous stat(2). The callback gets two arguments `(err, stats)` where
mtime: '2009-06-29T11:11:40Z',
ctime: '2009-06-29T11:11:40Z' }
See the `fs.Stats` section below for more information.
See the [fs.Stats](#fs.Stats) section below for more information.
### fs.lstat(path, [callback])
@ -239,8 +239,12 @@ should be written. If `position` is `null`, the data will be written at the
current position.
See pwrite(2).
The callback will be given two arguments `(err, written)` where `written`
specifies how many _bytes_ were written.
The callback will be given three arguments `(err, written, buffer)` where `written`
specifies how many _bytes_ were written into `buffer`.
Note that it is unsafe to use `fs.write` multiple times on the same file
without waiting for the callback. For this scenario,
`fs.createWriteStream` is strongly recommended.
### fs.writeSync(fd, buffer, offset, length, position)
@ -265,7 +269,7 @@ Read data from the file specified by `fd`.
`position` is an integer specifying where to begin reading from in the file.
If `position` is `null`, data will be read from the current file position.
The callback is given the two arguments, `(err, bytesRead)`.
The callback is given the three arguments, `(err, bytesRead, buffer)`.
### fs.readSync(fd, buffer, offset, length, position)
@ -302,7 +306,8 @@ returns a buffer.
### fs.writeFile(filename, data, encoding='utf8', [callback])
Asynchronously writes data to a file. `data` can be a string or a buffer.
Asynchronously writes data to a file, replacing the file if it already exists.
`data` can be a string or a buffer.
Example:

11
doc/api/globals.markdown

@ -13,11 +13,11 @@ scope; `var something` inside a Node module will be local to that module.
### process
The process object. See the 'process object' section.
The process object. See the [process object](process.html#process) section.
### require()
To require modules. See the 'Modules' section.
To require modules. See the [Modules](modules.html#modules) section.
### require.resolve()
@ -59,3 +59,10 @@ Example: running `node example.js` from `/Users/mjr`
A reference to the current module. In particular
`module.exports` is the same as the `exports` object. See `src/node.js`
for more information.
### setTimeout(cb, ms)
### clearTimeout(t)
### setInterval(cb, ms)
### clearInterval(t)
The timer functions are global variables. See the [timers](timers.html) section.

4
doc/api/http.markdown

@ -241,7 +241,7 @@ passed as the second parameter to the `'request'` event. It is a `Writable Strea
### response.writeContinue()
Sends a HTTP/1.1 100 Continue message to the client, indicating that
the request body should be sent. See the the `checkContinue` event on
the request body should be sent. See the [checkContinue](#event_checkContinue_) event on
`Server`.
### response.writeHead(statusCode, [reasonPhrase], [headers])
@ -458,7 +458,7 @@ Emitted each time a server responds to a request with an upgrade. If this event
isn't being listened for, clients receiving an upgrade header will have their
connections closed.
See the description of the `upgrade` event for `http.Server` for further details.
See the description of the [upgrade event](http.html#event_upgrade_) for `http.Server` for further details.
### Event: 'continue'

2
doc/api/modules.markdown

@ -1,7 +1,5 @@
## Modules
Node uses the CommonJS module system.
Node has a simple module loading system. In Node, files and modules are in
one-to-one correspondence. As an example, `foo.js` loads the module
`circle.js` in the same directory.

4
doc/api/net.markdown

@ -226,7 +226,7 @@ received.
#### socket.setSecure()
This function has been removed in v0.3. It used to upgrade the connection to
SSL/TLS. See the TLS for the new API.
SSL/TLS. See the [TLS section](tls.html#tLS_) for the new API.
#### socket.write(data, [encoding], [callback])
@ -319,7 +319,7 @@ See `connect()`.
Emitted when data is received. The argument `data` will be a `Buffer` or
`String`. Encoding of data is set by `socket.setEncoding()`.
(See the section on `Readable Socket` for more information.)
(See the [Readable Stream](streams.html#readable_Stream) section for more information.)
#### Event: 'end'

6
doc/api/streams.markdown

@ -170,3 +170,9 @@ Same as above but with a `buffer`.
### stream.destroy()
Closes the underlying file descriptor. Stream will not emit any more events.
### stream.destroySoon()
After the write queue is drained, close the file descriptor. `destroySoon()`
can still destroy straight away, as long as there is no data left in the queue
for writes.

13
doc/api/tls.markdown

@ -51,6 +51,19 @@ signed by one of the specified CAs. If `s.authorized === false` then the error
can be found in `s.authorizationError`.
### STARTTLS
In the v0.4 branch no function exists for starting a TLS session on an
already existing TCP connection. This is possible it just requires a bit of
work. The technique is to use `tls.createSecurePair()` which returns two
streams: an encrypted stream and a plaintext stream. The encrypted stream is then
piped to the socket, the plaintext stream is what the user interacts with thereafter.
[Here is some code that does it.](http://gist.github.com/848444)
### tls.Server
This class is a subclass of `net.Server` and has the same methods on it.

BIN
doc/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

12
doc/index.html

@ -9,6 +9,8 @@
</style>
<script type="text/javascript" src="sh_main.js"></script>
<script type="text/javascript" src="sh_javascript.min.js"></script>
<link type="image/x-icon" rel="icon" href="favicon.ico" />
<link type="image/x-icon" rel="shortcut icon" href="favicon.ico" />
<link type="text/css" rel="stylesheet" href="pipe.css" />
<link type="text/css" rel="stylesheet" href="sh_vim-dark.css" />
<link rel="alternate"
@ -24,11 +26,13 @@
<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.3/api">v0.4.3 docs</a></li>
<li><a href="http://nodejs.org/docs/v0.4.5/api">v0.4.5 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><B><a href="http://jobs.nodejs.org/">Jobs</a></B></li>
<br/>
<li><a href="http://chat.nodejs.org/">Demo</a></li>
</ol>
</div>
@ -104,9 +108,9 @@ server.listen(8124, "127.0.0.1");
</p>
<p>
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>)
2011.04.01
<a href="http://nodejs.org/dist/node-v0.4.5.tar.gz">node-v0.4.5.tar.gz</a>
(<a href="http://nodejs.org/docs/v0.4.5/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>

BIN
doc/joyent-logo_orange_nodeorg-01.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

2
doc/template.html

@ -2,6 +2,8 @@
<html>
<head>
<title>{{section}}Node.js Manual &amp; Documentation</title>
<link type="image/x-icon" rel="icon" href="/favicon.ico" />
<link type="image/x-icon" rel="shortcut icon" href="/favicon.ico" />
<link rel="stylesheet" href="assets/style.css" type="text/css" media="all" />
<link rel="stylesheet" href="assets/sh.css" type="text/css" media="all"/>
</head>

2
doc/v0.4_announcement.html

@ -7,6 +7,8 @@
margin: 0;
}
</style>
<link type="image/x-icon" rel="icon" href="favicon.ico" />
<link type="image/x-icon" rel="shortcut icon" href="favicon.ico" />
<link type="text/css" rel="stylesheet" href="pipe.css" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>node v0.4 announcement</title>

2
lib/buffer.js

@ -148,6 +148,8 @@ SlowBuffer.prototype.write = function(string, offset, encoding) {
// slice(start, end)
SlowBuffer.prototype.slice = function(start, end) {
if (end === undefined) end = this.length;
if (end > this.length) {
throw new Error('oob');
}

26
lib/events.js

@ -142,10 +142,13 @@ EventEmitter.prototype.once = function(type, listener) {
}
var self = this;
self.on(type, function g() {
function g() {
self.removeListener(type, g);
listener.apply(this, arguments);
});
};
g.listener = listener;
self.on(type, g);
return this;
};
@ -161,12 +164,23 @@ EventEmitter.prototype.removeListener = function(type, listener) {
var list = this._events[type];
if (isArray(list)) {
var i = list.indexOf(listener);
if (i < 0) return this;
list.splice(i, 1);
var position = -1;
for (var i = 0, length = list.length; i < length; i++) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener))
{
position = i;
break;
}
}
if (position < 0) return this;
list.splice(position, 1);
if (list.length == 0)
delete this._events[type];
} else if (this._events[type] === listener) {
} else if (list === listener ||
(list.listener && list.listener === listener))
{
delete this._events[type];
}

19
lib/fs.js

@ -240,7 +240,12 @@ fs.read = function(fd, buffer, offset, length, position, callback) {
};
}
binding.read(fd, buffer, offset, length, position, callback || noop);
function wrapper(err, bytesRead) {
// Retain a reference to buffer so that it can't be GC'ed too soon.
callback && callback(err, bytesRead || 0, buffer);
}
binding.read(fd, buffer, offset, length, position, wrapper);
};
fs.readSync = function(fd, buffer, offset, length, position) {
@ -285,7 +290,12 @@ fs.write = function(fd, buffer, offset, length, position, callback) {
return;
}
binding.write(fd, buffer, offset, length, position, callback || noop);
function wrapper(err, written) {
// Retain a reference to buffer so that it can't be GC'ed too soon.
callback && callback(err, written || 0, buffer);
}
binding.write(fd, buffer, offset, length, position, wrapper);
};
fs.writeSync = function(fd, buffer, offset, length, position) {
@ -867,7 +877,9 @@ ReadStream.prototype.setEncoding = function(encoding) {
ReadStream.prototype._read = function() {
var self = this;
if (!self.readable || self.paused) return;
if (!self.readable || self.paused || self.reading) return;
self.reading = true;
if (!pool || pool.length - pool.used < kMinPoolSpace) {
// discard the old pool. Can't add to the free list because
@ -893,6 +905,7 @@ ReadStream.prototype._read = function() {
}
function afterRead(err, bytesRead) {
self.reading = false;
if (err) {
self.emit('error', err);
self.readable = false;

16
lib/http.js

@ -862,9 +862,11 @@ ServerResponse.prototype.writeHeader = function() {
};
function ClientRequest(options) {
function ClientRequest(options, defaultPort) {
OutgoingMessage.call(this);
if (!defaultPort) defaultPort = 80;
var method = this.method = (options.method || 'GET').toUpperCase();
this.path = options.path || '/';
@ -879,7 +881,11 @@ function ClientRequest(options) {
}
// Host header set by default.
if (options.host && !this.getHeader('host')) {
this.setHeader("Host", options.host);
var hostHeader = options.host;
if (options.port && +options.port !== defaultPort) {
hostHeader += ':' + options.port;
}
this.setHeader("Host", hostHeader);
}
}
@ -1110,7 +1116,7 @@ exports._connectionListener = connectionListener;
function Agent(options) {
this.options = options;
this.host = options.host;
this.port = options.port || 80;
this.port = options.port || this.defaultPort;
this.queue = [];
this.sockets = [];
@ -1122,11 +1128,11 @@ exports.Agent = Agent;
Agent.defaultMaxSockets = 5;
Agent.prototype.defaultPort = 80;
Agent.prototype.appendMessage = function(options) {
var self = this;
var req = new ClientRequest(options);
var req = new ClientRequest(options, this.defaultPort);
this.queue.push(req);
req._queue = this.queue;

3
lib/https.js

@ -54,6 +54,9 @@ function Agent(options) {
inherits(Agent, http.Agent);
Agent.prototype.defaultPort = 443;
Agent.prototype._getConnection = function(host, port, cb) {
var s = tls.connect(port, host, this.options, function() {
// do other checks here?

40
lib/stream.js

@ -58,13 +58,6 @@ Stream.prototype.pipe = function(dest, options) {
source.on('end', onend);
}
dest.on('close', function() {
source.removeListener('data', ondata);
dest.removeListener('drain', ondrain);
source.removeListener('end', onend);
});
/*
* Questionable:
*/
@ -81,13 +74,38 @@ Stream.prototype.pipe = function(dest, options) {
};
}
dest.on('pause', function() {
var onpause = function() {
source.pause();
});
}
dest.on('pause', onpause);
dest.on('resume', function() {
var onresume = function() {
if (source.readable) source.resume();
});
};
dest.on('resume', onresume);
var cleanup = function () {
source.removeListener('data', ondata);
dest.removeListener('drain', ondrain);
source.removeListener('end', onend);
dest.removeListener('pause', onpause);
dest.removeListener('resume', onresume);
source.removeListener('end', cleanup);
source.removeListener('close', cleanup);
dest.removeListener('end', cleanup);
dest.removeListener('close', cleanup);
}
source.on('end', cleanup);
source.on('close', cleanup);
dest.on('end', cleanup);
dest.on('close', cleanup);
dest.emit('pipe', source);
};

2
lib/tls.js

@ -241,7 +241,7 @@ CryptoStream.prototype._push = function() {
while (this._writeState == true) {
var bytesRead = 0;
var chunkBytes = 0;
var pool = new Buffer(4096); // alloc every time?
var pool = new Buffer(16 * 4096); // alloc every time?
do {
chunkBytes = this._pusher(pool, bytesRead, pool.length - bytesRead);

6
lib/util.js

@ -118,9 +118,9 @@ exports.inspect = function(obj, showHidden, depth, colors) {
return stylize('undefined', 'undefined');
case 'string':
var simple = JSON.stringify(value).replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return stylize(simple, 'string');
case 'number':

37
src/node_crypto.cc

@ -131,8 +131,7 @@ Handle<Value> SecureContext::Init(const Arguments& args) {
SSL_CTX_set_session_cache_mode(sc->ctx_, SSL_SESS_CACHE_SERVER);
// SSL_CTX_set_session_cache_mode(sc->ctx_,SSL_SESS_CACHE_OFF);
sc->ca_store_ = X509_STORE_new();
SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_);
sc->ca_store_ = NULL;
return True();
}
@ -311,6 +310,7 @@ Handle<Value> SecureContext::SetCert(const Arguments& args) {
Handle<Value> SecureContext::AddCACert(const Arguments& args) {
bool newCAStore = false;
HandleScope scope;
SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
@ -319,6 +319,11 @@ Handle<Value> SecureContext::AddCACert(const Arguments& args) {
return ThrowException(Exception::TypeError(String::New("Bad parameter")));
}
if (!sc->ca_store_) {
sc->ca_store_ = X509_STORE_new();
newCAStore = true;
}
X509* x509 = LoadX509(args[0]);
if (!x509) return False();
@ -327,6 +332,10 @@ Handle<Value> SecureContext::AddCACert(const Arguments& args) {
X509_free(x509);
if (newCAStore) {
SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_);
}
return True();
}
@ -362,13 +371,18 @@ Handle<Value> SecureContext::AddCRL(const Arguments& args) {
}
Handle<Value> SecureContext::AddRootCerts(const Arguments& args) {
HandleScope scope;
SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
assert(sc->ca_store_ == NULL);
if (!root_cert_store) {
root_cert_store = X509_STORE_new();
for (int i = 0; root_certs[i]; i++) {
// TODO: reuse bp ?
BIO *bp = BIO_new(BIO_s_mem());
if (!BIO_write(bp, root_certs[i], strlen(root_certs[i]))) {
@ -383,11 +397,15 @@ Handle<Value> SecureContext::AddRootCerts(const Arguments& args) {
return False();
}
X509_STORE_add_cert(sc->ca_store_, x509);
X509_STORE_add_cert(root_cert_store, x509);
BIO_free(bp);
X509_free(x509);
}
}
sc->ca_store_ = root_cert_store;
SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_);
return True();
}
@ -411,19 +429,12 @@ Handle<Value> SecureContext::SetCiphers(const Arguments& args) {
Handle<Value> SecureContext::Close(const Arguments& args) {
HandleScope scope;
SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
if (sc->ctx_ != NULL) {
SSL_CTX_free(sc->ctx_);
sc->ctx_ = NULL;
sc->ca_store_ = NULL;
return True();
}
sc->FreeCTXMem();
return False();
}
#ifdef SSL_PRINT_DEBUG
# define DEBUG_PRINT(...) fprintf (stderr, __VA_ARGS__)
#else

16
src/node_crypto.h

@ -39,11 +39,14 @@
namespace node {
namespace crypto {
static X509_STORE* root_cert_store;
class SecureContext : ObjectWrap {
public:
static void Initialize(v8::Handle<v8::Object> target);
SSL_CTX *ctx_;
// TODO: ca_store_ should probably be removed, it's not used anywhere.
X509_STORE *ca_store_;
protected:
@ -62,8 +65,15 @@ class SecureContext : ObjectWrap {
ca_store_ = NULL;
}
~SecureContext() {
void FreeCTXMem() {
if (ctx_) {
if (ctx_->cert_store == root_cert_store) {
// SSL_CTX_free() will attempt to free the cert_store as well.
// Since we want our root_cert_store to stay around forever
// we just clear the field. Hopefully OpenSSL will not modify this
// struct in future versions.
ctx_->cert_store = NULL;
}
SSL_CTX_free(ctx_);
ctx_ = NULL;
ca_store_ = NULL;
@ -72,6 +82,10 @@ class SecureContext : ObjectWrap {
}
}
~SecureContext() {
FreeCTXMem();
}
private:
};

7
src/node_file.cc

@ -713,9 +713,6 @@ static Handle<Value> Write(const Arguments& args) {
Local<Value> cb = args[5];
if (cb->IsFunction()) {
// Grab a reference to buffer so it isn't GCed
Local<Object> cb_obj = cb->ToObject();
cb_obj->Set(buf_symbol, buffer_obj);
ASYNC_CALL(write, cb, fd, buf, len, pos)
} else {
@ -781,10 +778,6 @@ static Handle<Value> Read(const Arguments& args) {
cb = args[5];
if (cb->IsFunction()) {
// Grab a reference to buffer so it isn't GCed
// TODO: need test coverage
Local<Object> cb_obj = cb->ToObject();
cb_obj->Set(buf_symbol, buffer_obj);
ASYNC_CALL(read, cb, fd, buf, len, pos);
} else {

9
src/node_stdio.cc

@ -165,13 +165,12 @@ static Handle<Value> IsATTY (const Arguments& args) {
/* STDERR IS ALWAY SYNC ALWAYS UTF8 */
static Handle<Value>
WriteError (const Arguments& args)
{
static Handle<Value> WriteError (const Arguments& args) {
HandleScope scope;
if (args.Length() < 1)
if (args.Length() < 1) {
return Undefined();
}
String::Utf8Value msg(args[0]->ToString());
@ -189,7 +188,7 @@ WriteError (const Arguments& args)
written += (size_t)r;
}
return Undefined();
return True();
}

4
test/common.js

@ -60,6 +60,10 @@ process.on('exit', function() {
process,
global];
if (global.gc) {
knownGlobals.push(gc);
}
if (global.DTRACE_HTTP_SERVER_RESPONSE) {
knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE);
knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST);

71
test/pummel/test-regress-GH-814.js

@ -0,0 +1,71 @@
// Flags: --expose_gc
function newBuffer(size, value) {
var buffer = new Buffer(size);
while (size--) {
buffer[size] = value;
}
//buffer[buffer.length-2]= 0x0d;
buffer[buffer.length - 1] = 0x0a;
return buffer;
}
var common = require('../common');
var fs = require('fs');
var testFileName = require('path').join(common.tmpDir, 'GH-814_testFile.txt');
var testFileFD = fs.openSync(testFileName, 'w');
console.log(testFileName);
var kBufSize = 128 * 1024;
var PASS = true;
var neverWrittenBuffer = newBuffer(kBufSize, 0x2e); //0x2e === '.'
var bufPool = [];
var tail = require('child_process').spawn('tail', ['-f', testFileName]);
tail.stdout.on('data', tailCB);
function tailCB(data) {
PASS = data.toString().indexOf('.') < 0;
}
var timeToQuit = Date.now() + 8e3; //Test during no more than this seconds.
(function main() {
if (PASS) {
fs.write(testFileFD, newBuffer(kBufSize, 0x61), 0, kBufSize, -1, cb);
gc();
var nuBuf = new Buffer(kBufSize);
neverWrittenBuffer.copy(nuBuf);
if (bufPool.push(nuBuf) > 100) {
bufPool.length = 0;
}
}
else {
throw Error("Buffer GC'ed test -> FAIL");
}
if (Date.now() < timeToQuit) {
process.nextTick(main);
}
else {
tail.kill();
console.log("Buffer GC'ed test -> PASS (OK)");
}
})();
function cb(err, written) {
if (err) {
throw err;
}
}

85
test/pummel/test-regress-GH-814_2.js

@ -0,0 +1,85 @@
// Flags: --expose_gc
var common = require('../common');
var fs = require('fs');
var testFileName = require('path').join(common.tmpDir, 'GH-814_test.txt');
var testFD = fs.openSync(testFileName, 'w');
console.error(testFileName + '\n');
var tailProc = require('child_process').spawn('tail', ['-f', testFileName]);
tailProc.stdout.on('data', tailCB);
function tailCB(data) {
PASS = data.toString().indexOf('.') < 0;
if (PASS) {
//console.error('i');
} else {
console.error('[FAIL]\n DATA -> ');
console.error(data);
console.error('\n');
throw Error('Buffers GC test -> FAIL');
}
}
var PASS = true;
var bufPool = [];
var kBufSize = 16 * 1024 * 1024;
var neverWrittenBuffer = newBuffer(kBufSize, 0x2e); //0x2e === '.'
var timeToQuit = Date.now() + 5e3; //Test should last no more than this.
writer();
function writer() {
if (PASS) {
if (Date.now() > timeToQuit) {
setTimeout(function() {
process.kill(tailProc.pid);
console.error('\nBuffers GC test -> PASS (OK)\n');
}, 555);
} else {
fs.write(testFD, newBuffer(kBufSize, 0x61), 0, kBufSize, -1, writerCB);
gc();
gc();
gc();
gc();
gc();
gc();
var nuBuf = new Buffer(kBufSize);
neverWrittenBuffer.copy(nuBuf);
if (bufPool.push(nuBuf) > 100) {
bufPool.length = 0;
}
process.nextTick(writer);
//console.error('o');
}
}
}
function writerCB(err, written) {
//console.error('cb.');
if (err) {
throw err;
}
}
// ******************* UTILITIES
function newBuffer(size, value) {
var buffer = new Buffer(size);
while (size--) {
buffer[size] = value;
}
buffer[buffer.length - 1] = 0x0d;
buffer[buffer.length - 1] = 0x0a;
return buffer;
}

20
test/simple/test-assert.js

@ -209,3 +209,23 @@ a.throws(makeBlock(thrower, TypeError), function(err) {
return true;
}
});
// GH-207. Make sure deepEqual doesn't loop forever on circular refs
var b = {};
b.b = b;
var c = {};
c.b = c;
var gotError = false;
try {
assert.deepEqual(b, c);
} catch(e) {
gotError = true;
}
console.log('All OK');
assert.ok(gotError);

60
test/simple/test-buffer.js

@ -471,3 +471,63 @@ var b3 = b.toString('hex', 1, 5);
var b4 = b.toString('hex', 1);
assert.equal(b2, b3);
assert.equal(b2, b4);
// Test slice on SlowBuffer GH-843
var SlowBuffer = process.binding('buffer').SlowBuffer;
function buildSlowBuffer (data) {
if (Array.isArray(data)) {
var buffer = new SlowBuffer(data.length);
data.forEach(function(v,k) {
buffer[k] = v;
});
return buffer;
};
return null;
}
var x = buildSlowBuffer([0x81,0xa3,0x66,0x6f,0x6f,0xa3,0x62,0x61,0x72]);
console.log(x.inspect())
assert.equal('<SlowBuffer 81 a3 66 6f 6f a3 62 61 72>', x.inspect());
var z = x.slice(4);
console.log(z.inspect())
console.log(z.length)
assert.equal(5, z.length);
assert.equal(0x6f, z[0]);
assert.equal(0xa3, z[1]);
assert.equal(0x62, z[2]);
assert.equal(0x61, z[3]);
assert.equal(0x72, z[4]);
var z = x.slice(0);
console.log(z.inspect())
console.log(z.length)
assert.equal(z.length, x.length);
var z = x.slice(0, 4);
console.log(z.inspect())
console.log(z.length)
assert.equal(4, z.length);
assert.equal(0x81, z[0]);
assert.equal(0xa3, z[1]);
var z = x.slice(0, 9);
console.log(z.inspect())
console.log(z.length)
assert.equal(9, z.length);
var z = x.slice(1, 4);
console.log(z.inspect())
console.log(z.length)
assert.equal(3, z.length);
assert.equal(0xa3, z[0]);
var z = x.slice(2, 4);
console.log(z.inspect())
console.log(z.length)
assert.equal(2, z.length);
assert.equal(0x66, z[0]);
assert.equal(0x6f, z[1]);

4
test/simple/test-console.js

@ -31,8 +31,12 @@ global.process.stdout.write = function(string) {
console.log('foo');
console.log('foo', 'bar');
console.log('%s %s', 'foo', 'bar', 'hop');
console.log({slashes: '\\\\'})
global.process.stdout.write = stdout_write;
assert.equal('foo\n', strings.shift());
assert.equal('foo bar\n', strings.shift());
assert.equal('foo bar hop\n', strings.shift());
assert.equal("{ slashes: '\\\\\\\\' }\n", strings.shift());
assert.equal(true, process.stderr.write("hello world"));

8
test/simple/test-event-emitter-once.js

@ -35,6 +35,14 @@ e.emit('hello', 'a', 'b');
e.emit('hello', 'a', 'b');
e.emit('hello', 'a', 'b');
var remove = function() {
assert.fail(1,0, 'once->foo should not be emitted', '!');
};
e.once('foo', remove);
e.removeListener('foo', remove);
e.emit('foo');
process.addListener('exit', function() {
assert.equal(1, times_hello_emited);
});

7
test/simple/test-fs-read-stream.js

@ -42,8 +42,13 @@ file.addListener('open', function(fd) {
callbacks.open++;
assert.equal('number', typeof fd);
assert.ok(file.readable);
});
// GH-535
file.pause();
file.resume();
file.pause();
file.resume();
});
file.addListener('data', function(data) {
assert.ok(data instanceof Buffer);

150
test/simple/test-http-host-headers.js

@ -0,0 +1,150 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var http = require('http'),
https = require('https'),
fs = require('fs'),
common = require('../common'),
assert = require('assert'),
options = {
key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem')
},
httpServer = http.createServer(reqHandler),
httpsServer = https.createServer(options, reqHandler);
function reqHandler(req, res) {
console.log('Got request: ' + req.headers.host + ' ' + req.url);
assert.equal(req.headers.host, 'localhost:' + common.PORT,
'Wrong host header for req[' + req.url + ']: ' +
req.headers.host);
res.writeHead(200, {});
//process.nextTick(function() { res.end('ok'); });
res.end('ok');
}
function thrower(er) {
throw er;
}
testHttp();
function testHttp() {
console.log('testing http on port ' + common.PORT);
var counter = 0;
function cb() {
counter--;
console.log('back from http request. counter = ' + counter);
if (counter === 0) {
httpServer.close();
testHttps();
}
}
httpServer.listen(common.PORT, function(er) {
console.error('listening on ' + common.PORT);
if (er) throw er;
http.get({ method: 'GET',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower);
http.request({ method: 'GET',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower).end();
http.request({ method: 'POST',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower).end();
http.request({ method: 'PUT',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower).end();
http.request({ method: 'DELETE',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower).end();
});
}
function testHttps() {
console.log('testing https on port ' + common.PORT);
var counter = 0;
function cb() {
counter--;
console.log('back from https request. counter = ' + counter);
if (counter === 0) {
httpsServer.close();
console.log('ok');
}
}
httpsServer.listen(common.PORT, function(er) {
if (er) throw er;
https.get({ method: 'GET',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower);
https.request({ method: 'GET',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower).end();
https.request({ method: 'POST',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower).end();
https.request({ method: 'PUT',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower).end();
https.request({ method: 'DELETE',
path: '/' + (counter++),
host: 'localhost',
//agent: false,
port: common.PORT }, cb).on('error', thrower).end();
});
}

82
test/simple/test-stream-pipe-cleanup.js

@ -0,0 +1,82 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// This test asserts that Stream.prototype.pipe does not leave listeners
// hanging on the source or dest.
var stream = require('stream');
var assert = require('assert');
var util = require('util');
function Writable () {
this.writable = true;
stream.Stream.call(this);
}
util.inherits(Writable, stream.Stream);
Writable.prototype.end = function () {}
function Readable () {
this.readable = true;
stream.Stream.call(this);
}
util.inherits(Readable, stream.Stream);
var i = 0;
var limit = 100;
var w = new Writable();
console.error = function (text) {
throw new Error(text);
}
var r;
for (i = 0; i < limit; i++) {
r = new Readable()
r.pipe(w)
r.emit('end')
}
assert.equal(0, r.listeners('end').length);
for (i = 0; i < limit; i++) {
r = new Readable()
r.pipe(w)
r.emit('close')
}
assert.equal(0, r.listeners('close').length);
r = new Readable();
for (i = 0; i < limit; i++) {
w = new Writable();
r.pipe(w);
w.emit('end');
}
assert.equal(0, w.listeners('end').length);
for (i = 0; i < limit; i++) {
w = new Writable();
r.pipe(w);
w.emit('close');
}
assert.equal(0, w.listeners('close').length);

6
wscript

@ -603,7 +603,9 @@ def v8_cmd(bld, variant):
if bld.env["USE_GDBJIT"]:
cmd += ' gdbjit=on '
if sys.platform.startswith("sunos"): cmd += ' toolchain=gcc'
if sys.platform.startswith("sunos"):
cmd += ' toolchain=gcc strictaliasing=off'
return ("echo '%s' && " % cmd) + cmd
@ -885,7 +887,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.3' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version.
, 'VERSION' : '0.4.5' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version.
}
return x

Loading…
Cancel
Save