Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 3095) |
+++ src/runtime.cc (working copy) |
@@ -156,7 +156,7 @@ |
// Deep copy local elements. |
// Pixel elements cannot be created using an object literal. |
- ASSERT(!copy->HasPixelElements()); |
+ ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements()); |
switch (copy->GetElementsKind()) { |
case JSObject::FAST_ELEMENTS: { |
FixedArray* elements = FixedArray::cast(copy->elements()); |
@@ -2580,6 +2580,18 @@ |
return GetElementOrCharAt(object, index); |
} |
+ // If the target object is a JSObject and has an ExternalArray as |
+ // its elements, we need to check for negative indices and report |
+ // exceptions. Indices larger than the array's length will be caught |
+ // elsewhere. |
+ if (key->IsSmi() && Smi::cast(*key)->value() < 0) { |
+ if (object->IsJSObject() && |
+ JSObject::cast(*object)->HasExternalArrayElements()) { |
+ uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value()); |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ } |
+ |
// Convert the key to a string - possibly by calling back into JavaScript. |
Handle<String> name; |
if (key->IsString()) { |
@@ -2714,6 +2726,18 @@ |
return *value; |
} |
+ // If the target object is a JSObject and has an ExternalArray as |
+ // its elements, we need to check for negative indices and report |
+ // exceptions. Indices larger than the array's length will be caught |
+ // elsewhere. |
+ if (key->IsSmi() && Smi::cast(*key)->value() < 0) { |
+ if (object->IsJSObject() && |
+ JSObject::cast(*object)->HasExternalArrayElements()) { |
+ uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value()); |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ } |
+ |
if (key->IsString()) { |
Handle<Object> result; |
if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
@@ -5273,6 +5297,47 @@ |
}; |
+template<class ExternalArrayClass, class ElementType> |
+static uint32_t IterateExternalArrayElements(Handle<JSObject> receiver, |
+ bool elements_are_ints, |
+ bool elements_are_guaranteed_smis, |
+ uint32_t range, |
+ ArrayConcatVisitor* visitor) { |
+ Handle<ExternalArrayClass> array( |
+ ExternalArrayClass::cast(receiver->elements())); |
+ uint32_t len = Min(static_cast<uint32_t>(array->length()), range); |
+ |
+ if (visitor != NULL) { |
+ if (elements_are_ints) { |
+ if (elements_are_guaranteed_smis) { |
+ for (uint32_t j = 0; j < len; j++) { |
+ Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j)))); |
+ visitor->visit(j, e); |
+ } |
+ } else { |
+ for (uint32_t j = 0; j < len; j++) { |
+ int64_t val = static_cast<int64_t>(array->get(j)); |
+ if (Smi::IsValid(static_cast<intptr_t>(val))) { |
+ Handle<Smi> e(Smi::FromInt(static_cast<int>(val))); |
+ visitor->visit(j, e); |
+ } else { |
+ Handle<Object> e( |
+ Heap::AllocateHeapNumber(static_cast<ElementType>(val))); |
+ visitor->visit(j, e); |
+ } |
+ } |
+ } |
+ } else { |
+ for (uint32_t j = 0; j < len; j++) { |
+ Handle<Object> e(Heap::AllocateHeapNumber(array->get(j))); |
+ visitor->visit(j, e); |
+ } |
+ } |
+ } |
+ |
+ return len; |
+} |
+ |
/** |
* A helper function that visits elements of a JSObject. Only elements |
* whose index between 0 and range (exclusive) are visited. |
@@ -5322,6 +5387,48 @@ |
} |
break; |
} |
+ case JSObject::EXTERNAL_BYTE_ELEMENTS: { |
+ num_of_elements = |
+ IterateExternalArrayElements<ExternalByteArray, int8_t>( |
+ receiver, true, true, range, visitor); |
+ break; |
+ } |
+ case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
+ num_of_elements = |
+ IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>( |
+ receiver, true, true, range, visitor); |
+ break; |
+ } |
+ case JSObject::EXTERNAL_SHORT_ELEMENTS: { |
+ num_of_elements = |
+ IterateExternalArrayElements<ExternalShortArray, int16_t>( |
+ receiver, true, true, range, visitor); |
+ break; |
+ } |
+ case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { |
+ num_of_elements = |
+ IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>( |
+ receiver, true, true, range, visitor); |
+ break; |
+ } |
+ case JSObject::EXTERNAL_INT_ELEMENTS: { |
+ num_of_elements = |
+ IterateExternalArrayElements<ExternalIntArray, int32_t>( |
+ receiver, true, false, range, visitor); |
+ break; |
+ } |
+ case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
+ num_of_elements = |
+ IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>( |
+ receiver, true, false, range, visitor); |
+ break; |
+ } |
+ case JSObject::EXTERNAL_FLOAT_ELEMENTS: { |
+ num_of_elements = |
+ IterateExternalArrayElements<ExternalFloatArray, float>( |
+ receiver, false, false, range, visitor); |
+ break; |
+ } |
case JSObject::DICTIONARY_ELEMENTS: { |
Handle<NumberDictionary> dict(receiver->element_dictionary()); |
uint32_t capacity = dict->Capacity(); |