Merge remote-tracking branch 'upstream/v0.10'
authorTimothy J Fontaine <tjfontaine@gmail.com>
Mon, 2 Dec 2013 03:43:34 +0000 (19:43 -0800)
committerTimothy J Fontaine <tjfontaine@gmail.com>
Mon, 2 Dec 2013 03:43:34 +0000 (19:43 -0800)
Conflicts:
src/stream_wrap.cc

1  2 
common.gypi
doc/api/http.markdown
doc/api/net.markdown
node.gyp
src/stream_wrap.cc

diff --cc common.gypi
            ['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': {
@@@ -463,12 -434,10 +474,15 @@@ Options
   - `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.
Simple merge
diff --cc node.gyp
+++ b/node.gyp
              'PLATFORM="sunos"',
            ],
          }],
 -              '-Wl,--whole-archive <(PRODUCT_DIR)/obj.target/deps/v8/tools/gyp/libv8_base.a -Wl,--no-whole-archive',
+         [
+           'OS=="linux"', {
+             'ldflags': [
++              '-Wl,--whole-archive <(PRODUCT_DIR)/obj.target/deps/v8/tools/gyp/libv8_base.<(target_arch).a -Wl,--no-whole-archive',
+             ],
+         }],
        ],
        'msvs_settings': {
          'VCLinkerTool': {
@@@ -298,116 -412,24 +298,116 @@@ void StreamWrap::WriteStringImpl(const 
    }
  
    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);
  }