['target_arch=="x64"', {
'msvs_configuration_platform': 'x64',
}],
- ['node_unsafe_optimizations==1', {
- 'cflags': [ '-O3', '-ffunction-sections', '-fdata-sections' ],
- 'ldflags': [ '-Wl,--gc-sections' ],
- }, {
- 'cflags': [ '-O2', '-fno-strict-aliasing' ],
- 'cflags!': [ '-O3', '-fstrict-aliasing' ],
- 'conditions': [
- # Required by the dtrace post-processor. Unfortunately,
- # some gcc/binutils combos generate bad code when
- # -ffunction-sections is enabled. Let's hope for the best.
- ['OS=="solaris"', {
- 'cflags': [ '-ffunction-sections', '-fdata-sections' ],
- }, {
- 'cflags!': [ '-ffunction-sections', '-fdata-sections' ],
- }],
- ['clang == 0 and gcc_version >= 40', {
- 'cflags': [ '-fno-tree-vrp' ],
- }],
- ['clang == 0 and gcc_version <= 44', {
- 'cflags': [ '-fno-tree-sink' ],
- }],
- ],
- }],
['OS=="solaris"', {
- 'cflags': [ '-fno-omit-frame-pointer' ],
# pull in V8's postmortem metadata
'ldflags': [ '-Wl,-z,allextract' ]
+ }, {
+ # Doesn't work with the Solaris linker.
+ 'ldflags': [ '-Wl,--gc-sections' ],
+ }],
+ ['clang == 0 and gcc_version >= 40', {
+ 'cflags': [ '-fno-tree-vrp' ], # Work around compiler bug.
+ }],
+ ['clang == 0 and gcc_version <= 44', {
+ 'cflags': [ '-fno-tree-sink' ], # Work around compiler bug.
}],
+ ['OS!="mac" and OS!="win"', {
+ 'cflags': [ '-fno-omit-frame-pointer' ],
+ }],
],
'msvs_settings': {
'VCCLCompilerTool': {
- `Agent` object: explicitly use the passed in `Agent`.
- `false`: opts out of connection pooling with an Agent, defaults request to
`Connection: close`.
+- `keepAlive`: {Boolean} Keep sockets around in a pool to be used
+ by other requests in the future. Default = `false`
+- `keepAliveMsecs`: {Integer} When using HTTP KeepAlive, how often to
+ send TCP KeepAlive packets over sockets being kept alive. Default =
+ `1000`. Only relevant if `keepAlive` is set to `true`.
+ The optional `callback` parameter will be added as a one time listener for
+ the ['response'][] event.
+
`http.request()` returns an instance of the [http.ClientRequest][]
class. The `ClientRequest` instance is a writable stream. If one needs to
upload a file with a POST request, then write to the `ClientRequest` object.
}
req_wrap->Dispatched();
- req_wrap->object_->Set(bytes_sym, Integer::NewFromUnsigned(data_size));
-
- wrap->UpdateWriteQueueSize();
+ req_wrap->object()->Set(env->bytes_string(),
- Number::New(node_isolate, data_size));
++ Integer::NewFromUnsigned(data_size, node_isolate));
- if (r) {
- SetErrno(uv_last_error(uv_default_loop()));
+ if (err) {
req_wrap->~WriteWrap();
delete[] storage;
- return scope.Close(v8::Null());
- } else {
- if (wrap->stream_->type == UV_TCP) {
- NODE_COUNT_NET_BYTES_SENT(buf.len);
- } else if (wrap->stream_->type == UV_NAMED_PIPE) {
- NODE_COUNT_PIPE_BYTES_SENT(buf.len);
+ }
+
+ args.GetReturnValue().Set(err);
+}
+
+
+void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
+ HandleScope handle_scope(args.GetIsolate());
+ Environment* env = Environment::GetCurrent(args.GetIsolate());
+
+ StreamWrap* wrap = Unwrap<StreamWrap>(args.This());
+
+ assert(args[0]->IsObject());
+ assert(args[1]->IsArray());
+
+ Local<Object> req_wrap_obj = args[0].As<Object>();
+ Local<Array> chunks = args[1].As<Array>();
+ size_t count = chunks->Length() >> 1;
+
+ uv_buf_t bufs_[16];
+ uv_buf_t* bufs = bufs_;
+
+ // Determine storage size first
+ size_t storage_size = 0;
+ for (size_t i = 0; i < count; i++) {
+ Handle<Value> chunk = chunks->Get(i * 2);
+
+ if (Buffer::HasInstance(chunk))
+ continue;
+ // Buffer chunk, no additional storage required
+
+ // String chunk
+ Handle<String> string = chunk->ToString();
+ enum encoding encoding = ParseEncoding(chunks->Get(i * 2 + 1));
+ size_t chunk_size;
+ if (encoding == UTF8 && string->Length() > 65535)
+ chunk_size = StringBytes::Size(string, encoding);
+ else
+ chunk_size = StringBytes::StorageSize(string, encoding);
+
+ storage_size += chunk_size + 15;
+ }
+
+ if (storage_size > INT_MAX) {
+ args.GetReturnValue().Set(UV_ENOBUFS);
+ return;
+ }
+
+ if (ARRAY_SIZE(bufs_) < count)
+ bufs = new uv_buf_t[count];
+
+ storage_size += sizeof(WriteWrap);
+ char* storage = new char[storage_size];
+ WriteWrap* req_wrap =
+ new(storage) WriteWrap(env, req_wrap_obj, wrap);
+
+ uint32_t bytes = 0;
+ size_t offset = sizeof(WriteWrap);
+ for (size_t i = 0; i < count; i++) {
+ Handle<Value> chunk = chunks->Get(i * 2);
+
+ // Write buffer
+ if (Buffer::HasInstance(chunk)) {
+ bufs[i].base = Buffer::Data(chunk);
+ bufs[i].len = Buffer::Length(chunk);
+ bytes += bufs[i].len;
+ continue;
}
- return scope.Close(req_wrap->object_);
+ // Write string
+ offset = ROUND_UP(offset, 16);
+ assert(offset < storage_size);
+ char* str_storage = storage + offset;
+ size_t str_size = storage_size - offset;
+
+ Handle<String> string = chunk->ToString();
+ enum encoding encoding = ParseEncoding(chunks->Get(i * 2 + 1));
+ str_size = StringBytes::Write(str_storage, str_size, string, encoding);
+ bufs[i].base = str_storage;
+ bufs[i].len = str_size;
+ offset += str_size;
+ bytes += str_size;
}
+
+ int err = wrap->callbacks()->DoWrite(req_wrap,
+ bufs,
+ count,
+ NULL,
+ StreamWrap::AfterWrite);
+
+ // Deallocate space
+ if (bufs != bufs_)
+ delete[] bufs;
+
+ req_wrap->Dispatched();
+ req_wrap->object()->Set(env->bytes_string(),
+ Number::New(node_isolate, bytes));
+
+ if (err) {
+ req_wrap->~WriteWrap();
+ delete[] storage;
+ }
+
+ args.GetReturnValue().Set(err);
}