From ab97bdb71719a3488bd9dbb1236a905fd4a037c6 Mon Sep 17 00:00:00 2001 From: Eric Faust Date: Tue, 31 Jul 2012 20:05:19 -0700 Subject: [PATCH] Bug 749535 - Part 1: Implement JS_UnwrapObjectAs*Array(). (r=bhackett) --- js/src/jsfriendapi.h | 29 ++++++++++++++++ js/src/jstypedarray.cpp | 73 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index ac5f6be8a4a..a163e800656 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1093,6 +1093,35 @@ JS_IsFloat32Array(JSObject *obj, JSContext *cx); extern JS_FRIEND_API(JSBool) JS_IsFloat64Array(JSObject *obj, JSContext *cx); + +/* + * Unwrap Typed arrays all at once. Return NULL without throwing if obj cannot + * be viewed as the appropriate typed array, or the typed array object on + * success, after filling the two out parameters. + */ +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsInt8Array(JSContext *cx, JSObject *obj, uint32_t *length, int8_t **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsUint8Array(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsUint8ClampedArray(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsInt16Array(JSContext *cx, JSObject *obj, uint32_t *length, int16_t **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsUint16Array(JSContext *cx, JSObject *obj, uint32_t *length, uint16_t **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsInt32Array(JSContext *cx, JSObject *obj, uint32_t *length, int32_t **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsUint32Array(JSContext *cx, JSObject *obj, uint32_t *length, uint32_t **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsFloat32Array(JSContext *cx, JSObject *obj, uint32_t *length, float **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsFloat64Array(JSContext *cx, JSObject *obj, uint32_t *length, double **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data); +extern JS_FRIEND_API(JSObject *) +JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data); + /* * Get the type of elements in a typed array. * diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 800a1158a1a..3d2a1df3608 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -2936,6 +2936,40 @@ IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint32, uint32_t) IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float32, float) IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float64, double) +#define IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Name, ExternalType, InternalType) \ + JS_FRIEND_API(JSObject *) JS_GetObjectAs ## Name ## Array(JSContext *cx, \ + JSObject *obj, \ + uint32_t *length, \ + ExternalType **data) \ + { \ + if (obj->isWrapper()) { \ + MOZ_ASSERT(!cx->isExceptionPending()); \ + if (!(obj = UnwrapObjectChecked(cx, obj))) { \ + cx->clearPendingException(); \ + return NULL; \ + } \ + } \ + \ + Class *clasp = obj->getClass(); \ + if (clasp != &TypedArray::classes[TypedArrayTemplate::ArrayTypeID()]) \ + return NULL; \ + \ + *length = obj->getSlot(TypedArray::FIELD_LENGTH).toInt32(); \ + *data = static_cast(TypedArray::viewData(obj)); \ + \ + return obj; \ + } + +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int8, int8_t, int8_t) +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint8, uint8_t, uint8_t) +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint8Clamped, uint8_t, uint8_clamped) +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int16, int16_t, int16_t) +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint16, uint16_t, uint16_t) +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int32, int32_t, int32_t) +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint32, uint32_t, uint32_t) +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float32, float, float) +IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double) + #define IMPL_TYPED_ARRAY_PROTO_CLASS(_typedArray) \ { \ #_typedArray "Prototype", \ @@ -3558,3 +3592,42 @@ JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx) ? obj->asDataView().byteLength() : TypedArray::byteLengthValue(obj).toInt32(); } + +JS_FRIEND_API(JSObject *) +JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj, + uint32_t *length, uint8_t **data) +{ + if (obj->isWrapper()) { + if (!(obj = UnwrapObjectChecked(cx, obj))) { + cx->clearPendingException(); + return NULL; + } + } + if (!(obj->isTypedArray() || obj->isDataView())) + return NULL; + + *length = obj->isDataView() ? obj->asDataView().byteLength() + : TypedArray::byteLengthValue(obj).toInt32(); + + *data = static_cast(obj->isDataView() ? obj->asDataView().dataPointer() + : TypedArray::viewData(obj)); + return obj; +} + +JS_FRIEND_API(JSObject *) +JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data) +{ + if (obj->isWrapper()) { + if (!(obj = UnwrapObjectChecked(cx, obj))) { + cx->clearPendingException(); + return NULL; + } + } + if (!obj->isArrayBuffer()) + return NULL; + + *length = obj->asArrayBuffer().byteLength(); + *data = obj->asArrayBuffer().dataPointer(); + + return obj; +}