Merge branch 'v0.4'
Conflicts: src/node_version.h test/simple/test-buffer.js
This commit is contained in:
commit
bfa9db9dd6
4
AUTHORS
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
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
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
vendored
40
deps/v8/src/arm/code-stubs-arm.cc
vendored
@ -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, ¬_numbers, &call_runtime);
|
||||
|
||||
__ bind(¬_numbers);
|
||||
|
1
deps/v8/src/arm/code-stubs-arm.h
vendored
1
deps/v8/src/arm/code-stubs-arm.h
vendored
@ -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
vendored
5
deps/v8/src/arm/deoptimizer-arm.cc
vendored
@ -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
vendored
1
deps/v8/src/arm/lithium-codegen-arm.cc
vendored
@ -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
vendored
1
deps/v8/src/assembler.cc
vendored
@ -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
vendored
3
deps/v8/src/assembler.h
vendored
@ -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
vendored
7
deps/v8/src/deoptimizer.h
vendored
@ -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
vendored
1
deps/v8/src/heap.h
vendored
@ -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
vendored
9
deps/v8/src/hydrogen-instructions.h
vendored
@ -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
vendored
37
deps/v8/src/ia32/code-stubs-ia32.cc
vendored
@ -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
vendored
1
deps/v8/src/ia32/code-stubs-ia32.h
vendored
@ -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
vendored
74
deps/v8/src/ia32/deoptimizer-ia32.cc
vendored
@ -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
vendored
40
deps/v8/src/ia32/lithium-codegen-ia32.cc
vendored
@ -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
vendored
16
deps/v8/src/ic.cc
vendored
@ -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
vendored
1
deps/v8/src/ic.h
vendored
@ -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
vendored
7
deps/v8/src/platform-freebsd.cc
vendored
@ -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
vendored
2
deps/v8/src/version.cc
vendored
@ -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
vendored
36
deps/v8/src/x64/code-stubs-x64.cc
vendored
@ -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, ¬_number);
|
||||
|
1
deps/v8/src/x64/code-stubs-x64.h
vendored
1
deps/v8/src/x64/code-stubs-x64.h
vendored
@ -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
vendored
5
deps/v8/src/x64/deoptimizer-x64.cc
vendored
@ -101,6 +101,11 @@ class SafepointTableDeoptimiztionEntryIterator {
|
||||
};
|
||||
|
||||
|
||||
void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
|
||||
// TODO(1276): Implement.
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
|
||||
AssertNoAllocation no_allocation;
|
||||
|
||||
|
18
deps/v8/src/x64/lithium-codegen-x64.cc
vendored
18
deps/v8/src/x64/lithium-codegen-x64.cc
vendored
@ -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_->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
vendored
Normal file
65
deps/v8/test/mjsunit/compiler/regress-loadfield.js
vendored
Normal file
@ -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
vendored
Normal file
52
deps/v8/test/mjsunit/regress/regress-lazy-deopt-reloc.js
vendored
Normal file
@ -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();
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -71,7 +71,7 @@ if set true, will cause the subprocess to be run in a new session.
|
||||
|
||||
Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the exit code:
|
||||
|
||||
var util = require('util'),
|
||||
var util = require('util'),
|
||||
spawn = require('child_process').spawn,
|
||||
ls = spawn('ls', ['-lh', '/usr']);
|
||||
|
||||
@ -90,7 +90,7 @@ Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the exit cod
|
||||
|
||||
Example: A very elaborate way to run 'ps ax | grep ssh'
|
||||
|
||||
var util = require('util'),
|
||||
var util = require('util'),
|
||||
spawn = require('child_process').spawn,
|
||||
ps = spawn('ps', ['ax']),
|
||||
grep = spawn('grep', ['ssh']);
|
||||
@ -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.');
|
||||
}
|
||||
});
|
||||
@ -144,8 +145,8 @@ See also: `child_process.exec()`
|
||||
High-level way to execute a command as a child process, buffer the
|
||||
output, and return it all in a callback.
|
||||
|
||||
var util = require('util'),
|
||||
exec = require('child_process').exec,
|
||||
var util = require('util'),
|
||||
exec = require('child_process').exec,
|
||||
child;
|
||||
|
||||
child = exec('cat *.js bad_file | wc -l',
|
||||
|
@ -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.
|
||||
|
@ -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 " +
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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'
|
||||
|
||||
@ -485,7 +485,7 @@ A queue of requests waiting to be sent to sockets.
|
||||
## http.ClientRequest
|
||||
|
||||
This object is created internally and returned from `http.request()`. It
|
||||
represents an _in-progress_ request whose header has already been queued. The
|
||||
represents an _in-progress_ request whose header has already been queued. The
|
||||
header is still mutable using the `setHeader(name, value)`, `getHeader(name)`,
|
||||
`removeHeader(name)` API. The actual header will be sent along with the first
|
||||
data chunk or when closing the connection.
|
||||
|
@ -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.
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
Normal file
BIN
doc/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -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
Normal file
BIN
doc/joyent-logo_orange_nodeorg-01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
@ -2,6 +2,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>{{section}}Node.js Manual & 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>
|
||||
|
@ -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>
|
||||
|
@ -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');
|
||||
}
|
||||
|
@ -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
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
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;
|
||||
|
||||
|
@ -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?
|
||||
|
@ -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:
|
||||
*/
|
||||
@ -80,14 +73,39 @@ Stream.prototype.pipe = function(dest, options) {
|
||||
source.emit('resume');
|
||||
};
|
||||
}
|
||||
|
||||
dest.on('pause', function() {
|
||||
|
||||
var onpause = function() {
|
||||
source.pause();
|
||||
});
|
||||
}
|
||||
|
||||
dest.on('resume', function() {
|
||||
dest.on('pause', onpause);
|
||||
|
||||
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);
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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':
|
||||
|
@ -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,33 +371,42 @@ Handle<Value> SecureContext::AddCRL(const Arguments& args) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
Handle<Value> SecureContext::AddRootCerts(const Arguments& args) {
|
||||
HandleScope scope;
|
||||
|
||||
SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
|
||||
|
||||
for (int i = 0; root_certs[i]; i++) {
|
||||
// TODO: reuse bp ?
|
||||
BIO *bp = BIO_new(BIO_s_mem());
|
||||
assert(sc->ca_store_ == NULL);
|
||||
|
||||
if (!root_cert_store) {
|
||||
root_cert_store = X509_STORE_new();
|
||||
|
||||
for (int i = 0; root_certs[i]; i++) {
|
||||
BIO *bp = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!BIO_write(bp, root_certs[i], strlen(root_certs[i]))) {
|
||||
BIO_free(bp);
|
||||
return False();
|
||||
}
|
||||
|
||||
X509 *x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);
|
||||
|
||||
if (x509 == NULL) {
|
||||
BIO_free(bp);
|
||||
return False();
|
||||
}
|
||||
|
||||
X509_STORE_add_cert(root_cert_store, x509);
|
||||
|
||||
if (!BIO_write(bp, root_certs[i], strlen(root_certs[i]))) {
|
||||
BIO_free(bp);
|
||||
return False();
|
||||
X509_free(x509);
|
||||
}
|
||||
|
||||
X509 *x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);
|
||||
|
||||
if (x509 == NULL) {
|
||||
BIO_free(bp);
|
||||
return False();
|
||||
}
|
||||
|
||||
X509_STORE_add_cert(sc->ca_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
|
||||
|
@ -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:
|
||||
};
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
Normal file
71
test/pummel/test-regress-GH-814.js
Normal file
@ -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
Normal file
85
test/pummel/test-regress-GH-814_2.js
Normal file
@ -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;
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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"));
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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
Normal file
150
test/simple/test-http-host-headers.js
Normal file
@ -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
Normal file
82
test/simple/test-stream-pipe-cleanup.js
Normal file
@ -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
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…
x
Reference in New Issue
Block a user