diff --git a/src/v8_typed_array.cc b/src/v8_typed_array.cc index 8885f412ff..6c2303221a 100644 --- a/src/v8_typed_array.cc +++ b/src/v8_typed_array.cc @@ -71,6 +71,13 @@ class ArrayBuffer { v8::Local instance = ft_cache->InstanceTemplate(); instance->SetInternalFieldCount(1); // Buffer. + v8::Local default_signature = v8::Signature::New(ft_cache); + + instance->Set(v8::String::New("slice"), + v8::FunctionTemplate::New(&ArrayBuffer::slice, + v8::Handle(), + default_signature)); + return ft_cache; } @@ -139,6 +146,42 @@ class ArrayBuffer { return args.This(); } + + static v8::Handle slice(const v8::Arguments& args) { + if (args.Length() < 1) + return ThrowError("Wrong number of arguments."); + + unsigned int length = + args.This()->Get(v8::String::New("byteLength"))->Uint32Value(); + int begin = args[0]->Int32Value(); + int end = length; + if (args.Length() > 1) + end = args[1]->Int32Value(); + + if (begin < 0) begin = length + begin; + if (begin < 0) begin = 0; + if (static_cast(begin) > length) begin = length; + + if (end < 0) end = length + end; + if (end < 0) end = 0; + if (static_cast(end) > length) end = length; + + if (begin > end) begin = end; + + unsigned int slice_length = end - begin; + v8::Local argv[] = { + v8::Integer::New(slice_length)}; + v8::Local buffer = ArrayBuffer::GetTemplate()-> + GetFunction()->NewInstance(1, argv); + + if (buffer.IsEmpty()) return v8::Undefined(); // constructor failed + + void* src = args.This()->GetPointerFromInternalField(0); + void* dest = buffer->GetPointerFromInternalField(0); + memcpy(dest, static_cast(src) + begin, slice_length); + + return buffer; + } }; static bool checkAlignment(size_t val, unsigned int bytes) { diff --git a/test/simple/test-arraybuffer-slice.js b/test/simple/test-arraybuffer-slice.js new file mode 100644 index 0000000000..7703cf73f9 --- /dev/null +++ b/test/simple/test-arraybuffer-slice.js @@ -0,0 +1,89 @@ +// 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. + +/* + * Tests to verify slice functionality of ArrayBuffer. + * (http://www.khronos.org/registry/typedarray/specs/latest/#5) + */ + +var common = require('../common'); +var assert = require('assert'); + +var buffer = new ArrayBuffer(8); +var sub; +var i; + +for (var i = 0; i < 8; i++) { + buffer[i] = i; +} + +// slice a copy of buffer +sub = buffer.slice(2, 6); + +// make sure it copied correctly +assert.ok(sub instanceof ArrayBuffer); +assert.equal(sub.byteLength, 4); + +for (i = 0; i < 4; i++) { + assert.equal(sub[i], i+2); +} + +// modifications to the new slice shouldn't affect the original +sub[0] = 999; + +for (i = 0; i < 8; i++) { + assert.equal(buffer[i], i); +} + +// test optional end param +sub = buffer.slice(5); + +assert.ok(sub instanceof ArrayBuffer); +assert.equal(sub.byteLength, 3); +for (i = 0; i < 3; i++) { + assert.equal(sub[i], i+5); +} + +// test clamping +sub = buffer.slice(-3, -1); + +assert.ok(sub instanceof ArrayBuffer); +assert.equal(sub.byteLength, 2); +for (i = 0; i < 2; i++) { + assert.equal(sub[i], i+5); +} + +// test invalid clamping range +sub = buffer.slice(-1, -3); + +assert.ok(sub instanceof ArrayBuffer); +assert.equal(sub.byteLength, 0); + +// test wrong number of arguments +var gotError = false; + +try { + sub = buffer.slice(); +} catch (e) { + gotError = true; +} + +assert.ok(gotError); \ No newline at end of file