diff --git a/lib/smalloc.js b/lib/smalloc.js index b6eb21fbc3298e..9ebbaf402d17df 100644 --- a/lib/smalloc.js +++ b/lib/smalloc.js @@ -5,9 +5,9 @@ const kMaxLength = smalloc.kMaxLength; const util = require('util'); exports.alloc = alloc; -exports.copyOnto = smalloc.copyOnto; +exports.copyOnto = copyOnto; exports.dispose = dispose; -exports.hasExternalData = smalloc.hasExternalData; +exports.hasExternalData = hasExternalData; // don't allow kMaxLength to accidentally be overwritten. it's a lot less // apparent when a primitive is accidentally changed. @@ -50,13 +50,21 @@ function alloc(n, obj, type) { throw new TypeError('obj must be an Object'); } + if (Array.isArray(obj)) + throw new TypeError('obj cannot be an array'); + if (obj instanceof Buffer) + throw new TypeError('obj cannot be a Buffer'); + if (smalloc.isTypedArray(obj)) + throw new TypeError('obj cannot be a typed array'); + if (smalloc.hasExternalData(obj)) + throw new TypeError('object already has external array data'); + // 1 == v8::kExternalUint8Array, 9 == v8::kExternalUint8ClampedArray if (type < 1 || type > 9) throw new TypeError('unknown external array type: ' + type); - if (Array.isArray(obj)) - throw new TypeError('Arrays are not supported'); if (n > kMaxLength) - throw new RangeError('n > kMaxLength'); + throw new RangeError('Attempt to allocate array larger than maximum ' + + 'size: 0x' + kMaxLength.toString(16) + ' elements'); return smalloc.alloc(obj, n, type); } @@ -70,7 +78,29 @@ function dispose(obj) { if (smalloc.isTypedArray(obj)) throw new TypeError('obj cannot be a typed array'); if (!smalloc.hasExternalData(obj)) - throw new Error('obj has no external array data'); + throw new TypeError('obj has no external array data'); smalloc.dispose(obj); } + + +function copyOnto(source, sourceStart, dest, destStart, copyLength) { + if (util.isPrimitive(source)) + throw new TypeError('source must be an Object'); + if (util.isPrimitive(dest)) + throw new TypeError('dest must be an Object'); + if (!smalloc.hasExternalData(source)) + throw new TypeError('source has no external array data'); + if (!smalloc.hasExternalData(dest)) + throw new TypeError('dest has no external array data'); + + return smalloc.copyOnto(source, sourceStart, dest, destStart, copyLength); +} + + +function hasExternalData(obj) { + if (util.isPrimitive(obj)) + return false; + + return smalloc.hasExternalData(obj); +} diff --git a/src/smalloc.cc b/src/smalloc.cc index 89461959dd8912..834b93a7473dd1 100644 --- a/src/smalloc.cc +++ b/src/smalloc.cc @@ -152,18 +152,14 @@ size_t ExternalArraySize(enum ExternalArrayType type) { void CopyOnto(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (!args[0]->IsObject()) - return env->ThrowTypeError("source must be an object"); - if (!args[2]->IsObject()) - return env->ThrowTypeError("dest must be an object"); + ASSERT(args[0]->IsObject()); + ASSERT(args[2]->IsObject()); Local source = args[0].As(); Local dest = args[2].As(); - if (!source->HasIndexedPropertiesInExternalArrayData()) - return env->ThrowError("source has no external array data"); - if (!dest->HasIndexedPropertiesInExternalArrayData()) - return env->ThrowError("dest has no external array data"); + ASSERT(source->HasIndexedPropertiesInExternalArrayData()); + ASSERT(dest->HasIndexedPropertiesInExternalArrayData()); size_t source_start = args[1]->Uint32Value(); size_t dest_start = args[3]->Uint32Value(); @@ -266,11 +262,11 @@ void SliceOnto(const FunctionCallbackInfo& args) { void Alloc(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); + ASSERT(args[0]->IsObject()); + Local obj = args[0].As(); - // can't perform this check in JS - if (obj->HasIndexedPropertiesInExternalArrayData()) - return env->ThrowTypeError("object already has external array data"); + ASSERT(!obj->HasIndexedPropertiesInExternalArrayData()); size_t length = args[1]->Uint32Value(); enum ExternalArrayType array_type; @@ -410,8 +406,8 @@ void Alloc(Environment* env, void HasExternalData(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - args.GetReturnValue().Set(args[0]->IsObject() && - HasExternalData(env, args[0].As())); + ASSERT(args[0]->IsObject()); + args.GetReturnValue().Set(HasExternalData(env, args[0].As())); }