diff --git a/lib/buffer.js b/lib/buffer.js index ed159158415..7fd297559bd 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -295,6 +295,29 @@ Buffer.prototype.compare = function compare(b) { }; +Buffer.prototype.fill = function fill(val, start, end) { + start = start >> 0; + end = (end === undefined) ? this.length : end >> 0; + + if (start < 0 || end > this.length) + throw new RangeError('out of range index'); + if (end <= start) + return this; + + if (typeof val !== 'string') { + val = val >>> 0; + } else if (val.length === 1) { + var code = val.charCodeAt(0); + if (code < 256) + val = code; + } + + internal.fill(this, val, start, end); + + return this; +}; + + // XXX remove in v0.13 Buffer.prototype.get = util.deprecate(function get(offset) { offset = ~~offset; diff --git a/src/env.h b/src/env.h index 7fe132ce69b..015dcd26e83 100644 --- a/src/env.h +++ b/src/env.h @@ -72,7 +72,6 @@ namespace node { V(buffer_string, "buffer") \ V(bytes_string, "bytes") \ V(bytes_parsed_string, "bytesParsed") \ - V(byte_length_string, "byteLength") \ V(callback_string, "callback") \ V(change_string, "change") \ V(close_string, "close") \ diff --git a/src/node_buffer.cc b/src/node_buffer.cc index dada1002baf..8be551d9b0e 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -338,37 +338,31 @@ void Copy(const FunctionCallbackInfo &args) { } -// buffer.fill(value[, start][, end]); void Fill(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args.GetIsolate()); - HandleScope scope(env->isolate()); + ARGS_THIS(args[0].As()) - ARGS_THIS(args.This()) - SLICE_START_END(args[1], args[2], obj_length) - args.GetReturnValue().Set(args.This()); + size_t start = args[2]->Uint32Value(); + size_t end = args[3]->Uint32Value(); + size_t length = end - start; + CHECK(length + start <= obj_length); - if (args[0]->IsNumber()) { - int value = args[0]->Uint32Value() & 255; + if (args[1]->IsNumber()) { + int value = args[1]->Uint32Value() & 255; memset(obj_data + start, value, length); return; } - node::Utf8Value at(args[0]); - size_t at_length = at.length(); + node::Utf8Value str(args[1]); + size_t str_length = str.length(); + size_t in_there = str_length; + char* ptr = obj_data + start + str_length; - // optimize single ascii character case - if (at_length == 1) { - int value = static_cast((*at)[0]); - memset(obj_data + start, value, length); + if (str_length == 0) return; - } - size_t in_there = at_length; - char* ptr = obj_data + start + at_length; + memcpy(obj_data + start, *str, MIN(str_length, length)); - memcpy(obj_data + start, *at, MIN(at_length, length)); - - if (at_length >= length) + if (str_length >= length) return; while (in_there < length - in_there) { @@ -660,7 +654,6 @@ void SetupBufferJS(const FunctionCallbackInfo& args) { NODE_SET_METHOD(proto, "writeFloatLE", WriteFloatLE); NODE_SET_METHOD(proto, "copy", Copy); - NODE_SET_METHOD(proto, "fill", Fill); // for backwards compatibility proto->Set(env->offset_string(), @@ -670,16 +663,11 @@ void SetupBufferJS(const FunctionCallbackInfo& args) { assert(args[1]->IsObject()); Local internal = args[1].As(); + ASSERT(internal->IsObject()); - Local byte_length = FunctionTemplate::New( - env->isolate(), ByteLength)->GetFunction(); - byte_length->SetName(env->byte_length_string()); - internal->Set(env->byte_length_string(), byte_length); - - Local compare = FunctionTemplate::New( - env->isolate(), Compare)->GetFunction(); - compare->SetName(env->compare_string()); - internal->Set(env->compare_string(), compare); + NODE_SET_METHOD(internal, "byteLength", ByteLength); + NODE_SET_METHOD(internal, "compare", Compare); + NODE_SET_METHOD(internal, "fill", Fill); } diff --git a/test/simple/test-buffer.js b/test/simple/test-buffer.js index 70cc5908af4..4219a15be54 100644 --- a/test/simple/test-buffer.js +++ b/test/simple/test-buffer.js @@ -49,6 +49,56 @@ var c = new Buffer(512); console.log('c.length == %d', c.length); assert.strictEqual(512, c.length); +// First check Buffer#fill() works as expected. + +assert.throws(function() { + Buffer(8).fill('a', -1); +}); + +assert.throws(function() { + Buffer(8).fill('a', 0, 9); +}); + +// Make sure this doesn't hang indefinitely. +Buffer(8).fill(''); + +var buf = new Buffer(64); +buf.fill(10); +for (var i = 0; i < buf.length; i++) + assert.equal(buf[i], 10); + +buf.fill(11, 0, buf.length >> 1); +for (var i = 0; i < buf.length >> 1; i++) + assert.equal(buf[i], 11); +for (var i = (buf.length >> 1) + 1; i < buf.length; i++) + assert.equal(buf[i], 10); + +buf.fill('h'); +for (var i = 0; i < buf.length; i++) + assert.equal('h'.charCodeAt(0), buf[i]); + +buf.fill(0); +for (var i = 0; i < buf.length; i++) + assert.equal(0, buf[i]); + +buf.fill(null); +for (var i = 0; i < buf.length; i++) + assert.equal(0, buf[i]); + +buf.fill(1, 16, 32); +for (var i = 0; i < 16; i++) + assert.equal(0, buf[i]); +for (; i < 32; i++) + assert.equal(1, buf[i]); +for (; i < buf.length; i++) + assert.equal(0, buf[i]); + +var buf = new Buffer(10); +buf.fill('abc'); +assert.equal(buf.toString(), 'abcabcabca'); +buf.fill('է'); +assert.equal(buf.toString(), 'էէէէէ'); + // copy 512 bytes, from 0 to 512. b.fill(++cntr); c.fill(++cntr); @@ -642,28 +692,6 @@ assert.equal(0x6f, z[1]); assert.equal(0, Buffer('hello').slice(0, 0).length); -b = new Buffer(50); -b.fill('h'); -for (var i = 0; i < b.length; i++) { - assert.equal('h'.charCodeAt(0), b[i]); -} - -b.fill(0); -for (var i = 0; i < b.length; i++) { - assert.equal(0, b[i]); -} - -b.fill(1, 16, 32); -for (var i = 0; i < 16; i++) assert.equal(0, b[i]); -for (; i < 32; i++) assert.equal(1, b[i]); -for (; i < b.length; i++) assert.equal(0, b[i]); - -var buf = new Buffer(10); -buf.fill('abc'); -assert.equal(buf.toString(), 'abcabcabca'); -buf.fill('է'); -assert.equal(buf.toString(), 'էէէէէ'); - ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach(function(encoding) { var b = new Buffer(10); b.write('あいうえお', encoding);