Bug 711843 - Update JSAPI for typed arrays, remove uses of jstypedarray.h outside the engine [r=Waldo,bz,Ms2ger,bholley,bjacob,philikon,evilpie,bent,yourmama] [a=mfinkle thanks to gkw]

This commit is contained in:
Tom Schuster 2012-01-14 09:43:00 -08:00
parent 748a97a1ee
commit 0fe26d128c
40 changed files with 1081 additions and 612 deletions

View File

@ -59,7 +59,7 @@ class nsString;
* http://dev.w3.org/html5/websockets/
*
*/
[scriptable, uuid(f463b9b5-1408-4057-9224-e4f5bc33f17b)]
[scriptable, uuid(e59c8c65-df29-485c-a00b-8fac3dc1573a)]
interface nsIWebSocket : nsISupports
{
readonly attribute DOMString url;
@ -93,7 +93,7 @@ interface nsIWebSocket : nsISupports
* @return if the connection is still established and the data was queued or
* sent successfully.
*/
void send(in nsIVariant data);
[implicit_jscontext] void send(in nsIVariant data);
/**
* Closes the Web Socket connection or connection attempt, if any.

View File

@ -111,7 +111,7 @@ interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
* you're aware of all the security implications. And then think twice about
* it.
*/
[scriptable, uuid(88ffc45a-22e2-44f4-9a6e-f4586fbde376)]
[scriptable, uuid(8681ffbc-4755-45de-9fc1-b63e6930e76a)]
interface nsIXMLHttpRequest : nsISupports
{
/**
@ -260,7 +260,7 @@ interface nsIXMLHttpRequest : nsISupports
* Type header via the setRequestHeader method before
* calling send.
*/
void send([optional] in nsIVariant body);
[implicit_jscontext] void send([optional] in nsIVariant body);
/**
* A variant of the send() method used to send binary data.
@ -269,7 +269,7 @@ interface nsIXMLHttpRequest : nsISupports
* converted to a single-byte string by truncation (i.e., the
* high-order byte of each character will be discarded).
*/
void sendAsBinary(in DOMString body);
[implicit_jscontext] void sendAsBinary(in DOMString body);
/**
* Sets a HTTP request header for HTTP requests. You must call open

View File

@ -45,7 +45,7 @@
#include "jsapi.h"
#include "jsdbgapi.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "nsJSUtils.h"
#include "nsCOMPtr.h"
@ -5872,15 +5872,14 @@ nsContentUtils::CreateArrayBuffer(JSContext *aCx, const nsACString& aData,
}
PRInt32 dataLen = aData.Length();
*aResult = js_CreateArrayBuffer(aCx, dataLen);
*aResult = JS_NewArrayBuffer(aCx, dataLen);
if (!*aResult) {
return NS_ERROR_FAILURE;
}
if (dataLen > 0) {
JSObject *abuf = js::ArrayBuffer::getArrayBuffer(*aResult);
NS_ASSERTION(abuf, "What happened?");
memcpy(JS_GetArrayBufferData(abuf), aData.BeginReading(), dataLen);
NS_ASSERTION(JS_IsArrayBufferObject(*aResult, aCx), "What happened?");
memcpy(JS_GetArrayBufferData(*aResult, aCx), aData.BeginReading(), dataLen);
}
return NS_OK;

View File

@ -36,7 +36,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsDOMBlobBuilder.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "nsAutoPtr.h"
#include "nsDOMClassInfoID.h"
#include "nsIMultiplexInputStream.h"
@ -249,11 +249,8 @@ nsDOMMultipartFile::InitInternal(JSContext* aCx,
} else {
blobSet.AppendBlob(blob);
}
} else if (js_IsArrayBuffer(&obj)) {
JSObject* buffer = js::ArrayBuffer::getArrayBuffer(&obj);
if (!buffer)
return NS_ERROR_DOM_INVALID_STATE_ERR;
blobSet.AppendArrayBuffer(buffer);
} else if (JS_IsArrayBufferObject(&obj, aCx)) {
blobSet.AppendArrayBuffer(&obj, aCx);
} else {
// neither arraybuffer nor blob
return NS_ERROR_DOM_INVALID_STATE_ERR;
@ -331,9 +328,10 @@ BlobSet::AppendBlobs(const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlob)
}
nsresult
BlobSet::AppendArrayBuffer(JSObject* aBuffer)
BlobSet::AppendArrayBuffer(JSObject* aBuffer, JSContext *aCx)
{
return AppendVoidPtr(JS_GetArrayBufferData(aBuffer), JS_GetArrayBufferByteLength(aBuffer));
return AppendVoidPtr(JS_GetArrayBufferData(aBuffer, aCx),
JS_GetArrayBufferByteLength(aBuffer, aCx));
}
DOMCI_DATA(MozBlobBuilder, nsDOMBlobBuilder)
@ -436,10 +434,8 @@ nsDOMBlobBuilder::Append(const jsval& aData,
}
// Is it an array buffer?
if (js_IsArrayBuffer(obj)) {
JSObject* buffer = js::ArrayBuffer::getArrayBuffer(obj);
if (buffer)
return mBlobSet.AppendArrayBuffer(buffer);
if (JS_IsArrayBufferObject(obj, aCx)) {
return mBlobSet.AppendArrayBuffer(obj, aCx);
}
}

View File

@ -113,7 +113,7 @@ public:
nsresult AppendVoidPtr(const void* aData, PRUint32 aLength);
nsresult AppendString(JSString* aString, bool nativeEOL, JSContext* aCx);
nsresult AppendBlob(nsIDOMBlob* aBlob);
nsresult AppendArrayBuffer(JSObject* aBuffer);
nsresult AppendArrayBuffer(JSObject* aBuffer, JSContext *aCx);
nsresult AppendBlobs(const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlob);
nsTArray<nsCOMPtr<nsIDOMBlob> >& GetBlobs() { Flush(); return mBlobs; }

View File

@ -81,7 +81,7 @@
#include "nsDOMJSUtils.h"
#include "nsDOMEventTargetHelper.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
using namespace mozilla;
@ -359,11 +359,9 @@ nsDOMFileReader::DoOnDataAvailable(nsIRequest *aRequest,
NS_ASSERTION(bytesRead == aCount, "failed to read data");
}
else if (mDataFormat == FILE_AS_ARRAYBUFFER) {
JSObject* abuf = js::ArrayBuffer::getArrayBuffer(mResultArrayBuffer);
NS_ASSERTION(abuf, "What happened?");
PRUint32 bytesRead = 0;
aInputStream->Read((char*)JS_GetArrayBufferData(abuf) + aOffset, aCount, &bytesRead);
aInputStream->Read((char*)JS_GetArrayBufferData(mResultArrayBuffer, NULL) + aOffset,
aCount, &bytesRead);
NS_ASSERTION(bytesRead == aCount, "failed to read data");
}
else {
@ -470,7 +468,7 @@ nsDOMFileReader::ReadFileContent(JSContext* aCx,
if (mDataFormat == FILE_AS_ARRAYBUFFER) {
RootResultArrayBuffer();
mResultArrayBuffer = js_CreateArrayBuffer(aCx, mTotal);
mResultArrayBuffer = JS_NewArrayBuffer(aCx, mTotal);
if (!mResultArrayBuffer) {
NS_WARNING("Failed to create JS array buffer");
return NS_ERROR_FAILURE;

View File

@ -79,7 +79,7 @@
#include "xpcpublic.h"
#include "nsContentPolicyUtils.h"
#include "nsContentErrors.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "prmem.h"
#include "nsDOMFile.h"
#include "nsWrapperCacheInlines.h"
@ -1301,7 +1301,7 @@ ContainsUnpairedSurrogates(const nsAString& aData)
}
NS_IMETHODIMP
nsWebSocket::Send(nsIVariant *aData)
nsWebSocket::Send(nsIVariant *aData, JSContext *aCx)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
@ -1313,7 +1313,7 @@ nsWebSocket::Send(nsIVariant *aData)
nsCOMPtr<nsIInputStream> msgStream;
bool isBinary;
PRUint32 msgLen;
nsresult rv = GetSendParams(aData, msgString, msgStream, isBinary, msgLen);
nsresult rv = GetSendParams(aData, msgString, msgStream, isBinary, msgLen, aCx);
NS_ENSURE_SUCCESS(rv, rv);
// Always increment outgoing buffer len, even if closed
@ -1346,7 +1346,8 @@ nsWebSocket::Send(nsIVariant *aData)
nsresult
nsWebSocket::GetSendParams(nsIVariant *aData, nsCString &aStringOut,
nsCOMPtr<nsIInputStream> &aStreamOut,
bool &aIsBinary, PRUint32 &aOutgoingLength)
bool &aIsBinary, PRUint32 &aOutgoingLength,
JSContext *aCx)
{
// Get type of data (arraybuffer, blob, or string)
PRUint16 dataType;
@ -1368,9 +1369,9 @@ nsWebSocket::GetSendParams(nsIVariant *aData, nsCString &aStringOut,
nsresult rv = aData->GetAsJSVal(&realVal);
if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal) &&
(obj = JSVAL_TO_OBJECT(realVal)) &&
(js_IsArrayBuffer(obj))) {
PRInt32 len = JS_GetArrayBufferByteLength(obj);
char* data = (char*)JS_GetArrayBufferData(obj);
(JS_IsArrayBufferObject(obj, aCx))) {
PRInt32 len = JS_GetArrayBufferByteLength(obj, aCx);
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(obj, aCx));
aStringOut.Assign(data, len);
aIsBinary = true;

View File

@ -136,7 +136,8 @@ protected:
// Get msg info out of JS variable being sent (string, arraybuffer, blob)
nsresult GetSendParams(nsIVariant *aData, nsCString &aStringOut,
nsCOMPtr<nsIInputStream> &aStreamOut,
bool &aIsBinary, PRUint32 &aOutgoingLength);
bool &aIsBinary, PRUint32 &aOutgoingLength,
JSContext *aCx);
nsresult DoOnMessageAvailable(const nsACString & aMsg, bool isBinary);
nsresult CreateAndDispatchSimpleEvent(const nsString& aName);

View File

@ -99,11 +99,11 @@
#include "nsChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsAsyncRedirectVerifyHelper.h"
#include "jstypedarray.h"
#include "nsStringBuffer.h"
#include "nsDOMFile.h"
#include "nsIFileChannel.h"
#include "mozilla/Telemetry.h"
#include "jsfriendapi.h"
#include "sampler.h"
#include "mozilla/dom/bindings/XMLHttpRequestBinding.h"
#include "nsIDOMFormData.h"
@ -2511,15 +2511,15 @@ nsXMLHttpRequest::ChangeStateToDone()
}
NS_IMETHODIMP
nsXMLHttpRequest::SendAsBinary(const nsAString &aBody)
nsXMLHttpRequest::SendAsBinary(const nsAString &aBody, JSContext *aCx)
{
nsresult rv = NS_OK;
SendAsBinary(aBody, rv);
SendAsBinary(aCx, aBody, rv);
return rv;
}
void
nsXMLHttpRequest::SendAsBinary(const nsAString &aBody, nsresult& aRv)
nsXMLHttpRequest::SendAsBinary(JSContext *aCx, const nsAString &aBody, nsresult& aRv)
{
char *data = static_cast<char*>(NS_Alloc(aBody.Length() + 1));
if (!data) {
@ -2556,7 +2556,7 @@ nsXMLHttpRequest::SendAsBinary(const nsAString &aBody, nsresult& aRv)
return;
}
aRv = Send(variant);
aRv = Send(variant, aCx);
}
static nsresult
@ -2627,15 +2627,15 @@ GetRequestBody(nsIXHRSendable* aSendable, nsIInputStream** aResult,
}
static nsresult
GetRequestBody(JSObject* aArrayBuffer, nsIInputStream** aResult,
GetRequestBody(JSObject* aArrayBuffer, JSContext *aCx, nsIInputStream** aResult,
nsACString& aContentType, nsACString& aCharset)
{
NS_ASSERTION(js_IsArrayBuffer(aArrayBuffer), "Not an ArrayBuffer!");
NS_ASSERTION(JS_IsArrayBufferObject(aArrayBuffer, aCx), "Not an ArrayBuffer!");
aContentType.SetIsVoid(true);
aCharset.Truncate();
PRInt32 length = JS_GetArrayBufferByteLength(aArrayBuffer);
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(aArrayBuffer));
PRInt32 length = JS_GetArrayBufferByteLength(aArrayBuffer, aCx);
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(aArrayBuffer, aCx));
nsCOMPtr<nsIInputStream> stream;
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, length,
@ -2648,7 +2648,7 @@ GetRequestBody(JSObject* aArrayBuffer, nsIInputStream** aResult,
}
static nsresult
GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult,
GetRequestBody(nsIVariant* aBody, JSContext *aCx, nsIInputStream** aResult,
nsACString& aContentType, nsACString& aCharset)
{
*aResult = nsnull;
@ -2699,8 +2699,8 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult,
nsresult rv = aBody->GetAsJSVal(&realVal);
if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal) &&
(obj = JSVAL_TO_OBJECT(realVal)) &&
(js_IsArrayBuffer(obj))) {
return GetRequestBody(obj, aResult, aContentType, aCharset);
(JS_IsArrayBufferObject(obj, aCx))) {
return GetRequestBody(obj, aCx, aResult, aContentType, aCharset);
}
}
else if (dataType == nsIDataType::VTYPE_VOID ||
@ -2725,13 +2725,13 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult,
/* static */
nsresult
nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant, JSContext *aCx,
const Nullable<RequestBody>& aBody,
nsIInputStream** aResult,
nsACString& aContentType, nsACString& aCharset)
{
if (aVariant) {
return ::GetRequestBody(aVariant, aResult, aContentType, aCharset);
return ::GetRequestBody(aVariant, aCx, aResult, aContentType, aCharset);
}
const RequestBody& body = aBody.Value();
@ -2739,7 +2739,7 @@ nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
switch (body.GetType()) {
case nsXMLHttpRequest::RequestBody::ArrayBuffer:
{
return ::GetRequestBody(value.mArrayBuffer, aResult, aContentType, aCharset);
return ::GetRequestBody(value.mArrayBuffer, aCx, aResult, aContentType, aCharset);
}
case nsXMLHttpRequest::RequestBody::Blob:
{
@ -2782,13 +2782,13 @@ nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
/* void send (in nsIVariant aBody); */
NS_IMETHODIMP
nsXMLHttpRequest::Send(nsIVariant *aBody)
nsXMLHttpRequest::Send(nsIVariant *aBody, JSContext *aCx)
{
return Send(aBody, Nullable<RequestBody>());
return Send(aCx, aBody, Nullable<RequestBody>());
}
nsresult
nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
nsXMLHttpRequest::Send(JSContext *aCx, nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
{
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
@ -2912,7 +2912,7 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
nsCAutoString defaultContentType;
nsCOMPtr<nsIInputStream> postDataStream;
rv = GetRequestBody(aVariant, aBody, getter_AddRefs(postDataStream),
rv = GetRequestBody(aVariant, aCx, aBody, getter_AddRefs(postDataStream),
defaultContentType, charset);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -370,61 +370,62 @@ private:
};
static nsresult GetRequestBody(nsIVariant* aVariant,
JSContext* aCx,
const Nullable<RequestBody>& aBody,
nsIInputStream** aResult,
nsACString& aContentType,
nsACString& aCharset);
nsresult Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody);
nsresult Send(const Nullable<RequestBody>& aBody)
nsresult Send(JSContext *aCx, nsIVariant* aVariant, const Nullable<RequestBody>& aBody);
nsresult Send(JSContext *aCx, const Nullable<RequestBody>& aBody)
{
return Send(nsnull, aBody);
return Send(aCx, nsnull, aBody);
}
nsresult Send(const RequestBody& aBody)
nsresult Send(JSContext *aCx, const RequestBody& aBody)
{
return Send(Nullable<RequestBody>(aBody));
return Send(aCx, Nullable<RequestBody>(aBody));
}
public:
void Send(nsresult& aRv)
void Send(JSContext *aCx, nsresult& aRv)
{
aRv = Send(Nullable<RequestBody>());
aRv = Send(aCx, Nullable<RequestBody>());
}
void Send(JSObject* aArrayBuffer, nsresult& aRv)
void Send(JSContext *aCx, JSObject* aArrayBuffer, nsresult& aRv)
{
NS_ASSERTION(aArrayBuffer, "Null should go to string version");
aRv = Send(RequestBody(aArrayBuffer));
aRv = Send(aCx, RequestBody(aArrayBuffer));
}
void Send(nsIDOMBlob* aBlob, nsresult& aRv)
void Send(JSContext *aCx, nsIDOMBlob* aBlob, nsresult& aRv)
{
NS_ASSERTION(aBlob, "Null should go to string version");
aRv = Send(RequestBody(aBlob));
aRv = Send(aCx, RequestBody(aBlob));
}
void Send(nsIDocument* aDoc, nsresult& aRv)
void Send(JSContext *aCx, nsIDocument* aDoc, nsresult& aRv)
{
NS_ASSERTION(aDoc, "Null should go to string version");
aRv = Send(RequestBody(aDoc));
aRv = Send(aCx, RequestBody(aDoc));
}
void Send(const nsAString& aString, nsresult& aRv)
void Send(JSContext *aCx, const nsAString& aString, nsresult& aRv)
{
if (DOMStringIsNull(aString)) {
Send(aRv);
Send(aCx, aRv);
}
else {
aRv = Send(RequestBody(aString));
aRv = Send(aCx, RequestBody(aString));
}
}
void Send(nsIDOMFormData* aFormData, nsresult& aRv)
void Send(JSContext *aCx, nsIDOMFormData* aFormData, nsresult& aRv)
{
NS_ASSERTION(aFormData, "Null should go to string version");
aRv = Send(RequestBody(aFormData));
aRv = Send(aCx, RequestBody(aFormData));
}
void Send(nsIInputStream* aStream, nsresult& aRv)
void Send(JSContext *aCx, nsIInputStream* aStream, nsresult& aRv)
{
NS_ASSERTION(aStream, "Null should go to string version");
aRv = Send(RequestBody(aStream));
aRv = Send(aCx, RequestBody(aStream));
}
void SendAsBinary(const nsAString& aBody, nsresult& aRv);
void SendAsBinary(JSContext *aCx, const nsAString& aBody, nsresult& aRv);
void Abort();
@ -475,7 +476,7 @@ public:
}
// We need a GetInterface callable from JS for chrome JS
JS::Value GetInterface(JSContext*aCx, nsIJSIID* aIID, nsresult& aRv);
JS::Value GetInterface(JSContext* aCx, nsIJSIID* aIID, nsresult& aRv);
// This creates a trusted readystatechange event, which is not cancelable and
// doesn't bubble.

View File

@ -79,7 +79,7 @@ nsresult TestGetURL(const nsCString& aURL)
rv = xhr->Open(getString, aURL, false, empty, empty);
TEST_ENSURE_SUCCESS(rv, "OpenRequest failed!");
rv = xhr->Send(nsnull);
rv = xhr->Send(nsnull, nsnull);
TEST_ENSURE_SUCCESS(rv, "Send failed!");
nsAutoString response;

View File

@ -95,7 +95,7 @@ nsresult TestNativeXMLHttpRequest()
rv = xhr->Open(getString, testURL, false, empty, empty);
TEST_ENSURE_SUCCESS(rv, "Open failed!");
rv = xhr->Send(nsnull);
rv = xhr->Send(nsnull, nsnull);
TEST_ENSURE_SUCCESS(rv, "Send failed!");
nsAutoString response;

View File

@ -45,6 +45,7 @@
#include "CustomQS_Canvas.h"
#include "jsapi.h"
#include "jsfriendapi.h"
typedef NS_STDCALL_FUNCPROTO(nsresult, CanvasStyleSetterType, nsIDOMCanvasRenderingContext2D,
SetStrokeStyle_multi, (const nsAString &, nsISupports *));
@ -173,8 +174,7 @@ CreateImageData(JSContext* cx, JSObject* obj, uint32_t w, uint32_t h, jsval* vp)
}
// Create the fast typed array; it's initialized to 0 by default.
JSObject* darray =
js_CreateTypedArray(cx, js::TypedArray::TYPE_UINT8_CLAMPED, len.value());
JSObject* darray = JS_NewUint8ClampedArray(cx, len.value());
JS::AutoObjectRooter rd(cx, darray);
if (!darray) {
return false;
@ -305,26 +305,30 @@ nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, unsigned argc, jsval
JS::AutoValueRooter tsrc_tvr(cx);
JSObject *tsrc = NULL;
if (js::GetObjectClass(darray.get()) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8] ||
js::GetObjectClass(darray.get()) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8_CLAMPED])
JSObject * tsrc = NULL;
if (JS_IsInt8Array(darray.get(), cx) ||
JS_IsUint8Array(darray.get(), cx) ||
JS_IsUint8ClampedArray(darray.get(), cx))
{
tsrc = darray.get();
} else if (JS_IsArrayObject(cx, darray.get()) || js_IsTypedArray(darray.get())) {
} else if (JS_IsTypedArrayObject(darray.get(), cx) || JS_IsArrayObject(cx, darray.get())) {
// ugh, this isn't a uint8 typed array, someone made their own object; convert it to a typed array
JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_UINT8, darray.get());
JSObject *nobj = JS_NewUint8ClampedArrayFromArray(cx, darray.get());
if (!nobj)
return JS_FALSE;
*tsrc_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj);
tsrc = js::TypedArray::getTypedArray(nobj);
tsrc = nobj;
} else {
// yeah, no.
return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
}
// make the call
rv = self->PutImageData_explicit(x, y, w, h, static_cast<PRUint8*>(JS_GetTypedArrayData(tsrc)), JS_GetTypedArrayByteLength(tsrc), hasDirtyRect, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
MOZ_ASSERT(JS_IsTypedArrayObject(tsrc, cx));
PRUint8* data = reinterpret_cast<PRUint8*>(JS_GetArrayBufferViewData(tsrc, cx));
uint32_t byteLength = JS_GetTypedArrayByteLength(tsrc, cx);
rv = self->PutImageData_explicit(x, y, w, h, data, byteLength, hasDirtyRect, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
if (NS_FAILED(rv))
return xpc_qsThrowMethodFailed(cx, rv, vp);

View File

@ -41,7 +41,7 @@
*/
#include "jsapi.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "CustomQS_Canvas.h"
#define GET_INT32_ARG(var, index) \
@ -84,10 +84,10 @@ public:
{}
nsresult DoCallForImageData(WebGLsizei width, WebGLsizei height,
JSObject* pixels)
JSObject* pixels, JSContext *cx)
{
return self->TexImage2D_imageData(target, level, internalformat, width,
height, 0, format, type, pixels);
height, 0, format, type, pixels, cx);
}
nsresult DoCallForElement(mozilla::dom::Element* elt)
{
@ -126,11 +126,11 @@ public:
{}
nsresult DoCallForImageData(WebGLsizei width, WebGLsizei height,
JSObject* pixels)
JSObject* pixels, JSContext *cx)
{
return self->TexSubImage2D_imageData(target, level, xoffset, yoffset,
width, height, format, type,
pixels);
pixels, cx);
}
nsresult DoCallForElement(mozilla::dom::Element* elt)
{
@ -160,11 +160,11 @@ TexImage2DImageDataOrElement(JSContext* cx, T& self, JS::Value* object)
if (!GetImageData(cx, *object, &int_width, &int_height, &obj_data)) {
return false;
}
if (!js_IsTypedArray(obj_data.get())) {
if (!JS_IsTypedArrayObject(obj_data.get(), cx)) {
return xpc_qsThrow(cx, NS_ERROR_FAILURE);
}
nsresult rv = self.DoCallForImageData(int_width, int_height, obj_data.get());
nsresult rv = self.DoCallForImageData(int_width, int_height, obj_data.get(), cx);
return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv);
}
@ -225,11 +225,11 @@ nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, unsigned argc, jsval *vp)
if (argv8 == nsnull) {
rv = self->TexImage2D_array(argv0, argv1, argv2, argv3,
argv4, argv5, argv6, argv7,
nsnull);
} else if (js_IsTypedArray(argv8)) {
nsnull, cx);
} else if (JS_IsTypedArrayObject(argv8, cx)) {
rv = self->TexImage2D_array(argv0, argv1, argv2, argv3,
argv4, argv5, argv6, argv7,
js::TypedArray::getTypedArray(argv8));
argv8, cx);
} else {
xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
return JS_FALSE;
@ -297,10 +297,10 @@ nsIDOMWebGLRenderingContext_TexSubImage2D(JSContext *cx, unsigned argc, jsval *v
JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]);
// try to grab a js::TypedArray
if (js_IsTypedArray(argv8)) {
if (JS_IsTypedArrayObject(argv8, cx)) {
rv = self->TexSubImage2D_array(argv0, argv1, argv2, argv3,
argv4, argv5, argv6, argv7,
js::TypedArray::getTypedArray(argv8));
argv8, cx);
} else {
xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
return JS_FALSE;

View File

@ -691,11 +691,11 @@ protected:
}
nsresult BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage);
nsresult BufferData_buf(WebGLenum target, JSObject* data, WebGLenum usage);
nsresult BufferData_array(WebGLenum target, JSObject* data, WebGLenum usage);
nsresult BufferData_buf(WebGLenum target, JSObject* data, WebGLenum usage, JSContext *cx);
nsresult BufferData_array(WebGLenum target, JSObject* data, WebGLenum usage, JSContext *cx);
nsresult BufferSubData_buf(WebGLenum target, PRInt32 offset, JSObject* data);
nsresult BufferSubData_array(WebGLenum target, PRInt32 offset, JSObject* data);
nsresult BufferSubData_buf(WebGLenum target, PRInt32 offset, JSObject* data, JSContext *cx);
nsresult BufferSubData_array(WebGLenum target, PRInt32 offset, JSObject* data, JSContext *cx);
nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;

View File

@ -54,7 +54,7 @@
#include "CanvasUtils.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "WebGLTexelConversions.h"
#include "WebGLValidateStrings.h"
@ -455,12 +455,12 @@ WebGLContext::BufferData(PRInt32 target, const JS::Value& data, PRInt32 usage,
if (data.isObject()) {
JSObject& dataObj = data.toObject();
if (js_IsArrayBuffer(&dataObj)) {
return BufferData_buf(target, &dataObj, usage);
if (JS_IsArrayBufferObject(&dataObj, cx)) {
return BufferData_buf(target, &dataObj, usage, cx);
}
if (js_IsTypedArray(&dataObj)) {
return BufferData_array(target, &dataObj, usage);
if (JS_IsTypedArrayObject(&dataObj, cx)) {
return BufferData_array(target, &dataObj, usage, cx);
}
return ErrorInvalidValue("bufferData: object passed that is not an "
@ -516,11 +516,14 @@ WebGLContext::BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage
}
nsresult
WebGLContext::BufferData_buf(WebGLenum target, JSObject *wb, WebGLenum usage)
WebGLContext::BufferData_buf(WebGLenum target, JSObject *wb, WebGLenum usage, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
if (!JS_IsArrayBufferObject(wb, cx))
return ErrorInvalidOperation("BufferData: incorrect type");
WebGLBuffer *boundBuffer = NULL;
if (target == LOCAL_GL_ARRAY_BUFFER) {
@ -540,24 +543,24 @@ WebGLContext::BufferData_buf(WebGLenum target, JSObject *wb, WebGLenum usage)
MakeContextCurrent();
GLenum error = CheckedBufferData(target,
JS_GetArrayBufferByteLength(wb),
JS_GetArrayBufferData(wb),
JS_GetArrayBufferByteLength(wb, cx),
JS_GetArrayBufferData(wb, cx),
usage);
if (error) {
LogMessageIfVerbose("bufferData generated error %s", ErrorName(error));
return NS_OK;
}
boundBuffer->SetByteLength(JS_GetArrayBufferByteLength(wb));
boundBuffer->SetByteLength(JS_GetArrayBufferByteLength(wb, cx));
boundBuffer->InvalidateCachedMaxElements();
if (!boundBuffer->CopyDataIfElementArray(JS_GetArrayBufferData(wb)))
if (!boundBuffer->CopyDataIfElementArray(JS_GetArrayBufferData(wb, cx)))
return ErrorOutOfMemory("bufferData: out of memory");
return NS_OK;
}
nsresult
WebGLContext::BufferData_array(WebGLenum target, JSObject *wa, WebGLenum usage)
WebGLContext::BufferData_array(WebGLenum target, JSObject *wa, WebGLenum usage, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
@ -580,25 +583,27 @@ WebGLContext::BufferData_array(WebGLenum target, JSObject *wa, WebGLenum usage)
MakeContextCurrent();
GLenum error = CheckedBufferData(target,
JS_GetTypedArrayByteLength(wa),
JS_GetTypedArrayData(wa),
usage);
if (!JS_IsTypedArrayObject(wa, cx))
return ErrorInvalidOperation("BufferData: incorrect type");
uint32_t byteLength = JS_GetTypedArrayByteLength(wa, cx);
void *data = JS_GetArrayBufferViewData(wa, cx);
GLenum error = CheckedBufferData(target, byteLength, data, usage);
if (error) {
LogMessageIfVerbose("bufferData generated error %s", ErrorName(error));
return NS_OK;
}
boundBuffer->SetByteLength(JS_GetTypedArrayByteLength(wa));
boundBuffer->SetByteLength(byteLength);
boundBuffer->InvalidateCachedMaxElements();
if (!boundBuffer->CopyDataIfElementArray(JS_GetTypedArrayData(wa)))
if (!boundBuffer->CopyDataIfElementArray(data))
return ErrorOutOfMemory("bufferData: out of memory");
return NS_OK;
}
NS_IMETHODIMP
WebGLContext::BufferSubData(PRInt32 target, PRInt32 offset, const JS::Value& data)
WebGLContext::BufferSubData(PRInt32 target, PRInt32 offset, const JS::Value& data, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
@ -613,23 +618,26 @@ WebGLContext::BufferSubData(PRInt32 target, PRInt32 offset, const JS::Value& dat
}
JSObject& dataObj = data.toObject();
if (js_IsArrayBuffer(&dataObj)) {
return BufferSubData_buf(target, offset, &dataObj);
if (JS_IsArrayBufferObject(&dataObj, cx)) {
return BufferSubData_buf(target, offset, &dataObj, cx);
}
if (js_IsTypedArray(&dataObj)) {
return BufferSubData_array(target, offset, &dataObj);
if (JS_IsTypedArrayObject(&dataObj, cx)) {
return BufferSubData_array(target, offset, &dataObj, cx);
}
return NS_ERROR_FAILURE;
}
nsresult
WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, JSObject *wb)
WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, JSObject *wb, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
if (!JS_IsArrayBufferObject(wb, cx))
return ErrorInvalidOperation("BufferSubData: incorrect type");
WebGLBuffer *boundBuffer = NULL;
if (target == LOCAL_GL_ARRAY_BUFFER) {
@ -646,30 +654,33 @@ WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, JSObject *
if (!boundBuffer)
return ErrorInvalidOperation("BufferData: no buffer bound!");
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetArrayBufferByteLength(wb);
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetArrayBufferByteLength(wb, cx);
if (!checked_neededByteLength.valid())
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
return ErrorInvalidOperation("BufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
byteOffset, JS_GetArrayBufferByteLength(wb), boundBuffer->ByteLength());
byteOffset, JS_GetArrayBufferByteLength(wb, cx), boundBuffer->ByteLength());
MakeContextCurrent();
boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetArrayBufferByteLength(wb), JS_GetArrayBufferData(wb));
boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetArrayBufferByteLength(wb, cx), JS_GetArrayBufferData(wb, cx));
boundBuffer->InvalidateCachedMaxElements();
gl->fBufferSubData(target, byteOffset, JS_GetArrayBufferByteLength(wb), JS_GetArrayBufferData(wb));
gl->fBufferSubData(target, byteOffset, JS_GetArrayBufferByteLength(wb, cx), JS_GetArrayBufferData(wb, cx));
return NS_OK;
}
nsresult
WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, JSObject *wa)
WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, JSObject *wa, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
if (!JS_IsTypedArrayObject(wa, cx))
return ErrorInvalidOperation("BufferSubData: incorrect type");
WebGLBuffer *boundBuffer = NULL;
if (target == LOCAL_GL_ARRAY_BUFFER) {
@ -686,20 +697,20 @@ WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, JSObj
if (!boundBuffer)
return ErrorInvalidOperation("BufferData: no buffer bound!");
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetTypedArrayByteLength(wa);
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetTypedArrayByteLength(wa, cx);
if (!checked_neededByteLength.valid())
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
return ErrorInvalidOperation("BufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
byteOffset, JS_GetTypedArrayByteLength(wa), boundBuffer->ByteLength());
byteOffset, JS_GetTypedArrayByteLength(wa, cx), boundBuffer->ByteLength());
MakeContextCurrent();
boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetTypedArrayByteLength(wa), JS_GetTypedArrayData(wa));
boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetTypedArrayByteLength(wa, cx), JS_GetArrayBufferViewData(wa, cx));
boundBuffer->InvalidateCachedMaxElements();
gl->fBufferSubData(target, byteOffset, JS_GetTypedArrayByteLength(wa), JS_GetTypedArrayData(wa));
gl->fBufferSubData(target, byteOffset, JS_GetTypedArrayByteLength(wa, cx), JS_GetArrayBufferViewData(wa, cx));
return NS_OK;
}
@ -3381,9 +3392,13 @@ GL_SAME_METHOD_2(PolygonOffset, PolygonOffset, WebGLfloat, WebGLfloat)
NS_IMETHODIMP
WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height,
WebGLenum format, WebGLenum type, const JS::Value& pixelsVal)
WebGLenum format, WebGLenum type, const JS::Value& pixelsVal, JSContext *cx)
{
if (!pixelsVal.isObject() || !js_IsTypedArray(&pixelsVal.toObject())) {
if (!pixelsVal.isObject()) {
return NS_ERROR_FAILURE;
}
if (!JS_IsTypedArrayObject(&pixelsVal.toObject(), cx)) {
return NS_ERROR_FAILURE;
}
@ -3405,9 +3420,9 @@ WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei he
WebGLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
WebGLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
void* data = JS_GetTypedArrayData(&pixels);
PRUint32 dataByteLen = JS_GetTypedArrayByteLength(&pixels);
int dataType = JS_GetTypedArrayType(&pixels);
void* data = JS_GetArrayBufferViewData(&pixels, cx);
PRUint32 dataByteLen = JS_GetTypedArrayByteLength(&pixels, cx);
int dataType = JS_GetTypedArrayType(&pixels, cx);
PRUint32 channels = 0;
@ -3433,13 +3448,13 @@ WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei he
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
bytesPerPixel = 1 * channels;
requiredDataType = js::TypedArray::TYPE_UINT8;
requiredDataType = js::ArrayBufferView::TYPE_UINT8;
break;
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
bytesPerPixel = 2;
requiredDataType = js::TypedArray::TYPE_UINT16;
requiredDataType = js::ArrayBufferView::TYPE_UINT16;
break;
default:
return ErrorInvalidEnum("readPixels: Bad type");
@ -4105,7 +4120,8 @@ WebGLContext::DOMElementToImageSurface(Element* imageOrCanvas,
return NS_OK;
}
template<size_t type>
template<JSBool TypedArrayTest(JSObject* obj, JSContext* cx),
JSObject* TypedArrayCopy(JSContext* cx, JSObject* src)>
static JSObject*
GetTypedArray(JSContext* aCx, const JS::Value& aValue)
{
@ -4115,12 +4131,12 @@ GetTypedArray(JSContext* aCx, const JS::Value& aValue)
JSObject& value = aValue.toObject();
if (js::GetObjectClass(&value) == &js::TypedArray::fastClasses[type]) {
if (TypedArrayTest(&value, aCx)) {
return &value;
}
if (JS_IsArrayObject(aCx, &value)) {
return js_CreateTypedArrayWithArray(aCx, type, &value);
return TypedArrayCopy(aCx, &value);
}
return NULL;
@ -4129,7 +4145,7 @@ GetTypedArray(JSContext* aCx, const JS::Value& aValue)
static JSObject*
GetFloat32Array(JSContext* aCx, const JS::Value& aValue)
{
return GetTypedArray<js::TypedArray::TYPE_FLOAT32>(aCx, aValue);
return GetTypedArray<JS_IsFloat32Array, JS_NewFloat32ArrayFromArray>(aCx, aValue);
}
#define OBTAIN_UNIFORM_LOCATION(info) \
@ -4153,7 +4169,7 @@ NS_IMETHODIMP
WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue, \
JSContext* aCx) \
{ \
JSObject* wa = GetTypedArray<js::TypedArray::arrayType>(aCx, aValue); \
JSObject* wa = GetTypedArray<JS_Is ## arrayType ## Array, JS_New ## arrayType ## ArrayFromArray>(aCx, aValue); \
if (!wa) { \
return NS_ERROR_FAILURE; \
} \
@ -4164,9 +4180,6 @@ WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue,
\
nsIWebGLUniformLocation* ploc = aLocation; \
OBTAIN_UNIFORM_LOCATION(#name ": location") \
if (JS_GetTypedArrayType(wa) != js::TypedArray::arrayType) { \
return ErrorInvalidOperation(#name ": array must be " #arrayType); \
} \
int elementSize = location_object->ElementSize(); \
if (cnt != elementSize) { \
return ErrorInvalidOperation( \
@ -4175,7 +4188,7 @@ WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue,
cnt, \
elementSize); \
} \
PRUint32 arrayLength = JS_GetTypedArrayLength(wa); \
PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx); \
const WebGLUniformInfo& info = location_object->Info(); \
PRUint32 expectedArrayLength = cnt * info.arraySize; \
if (arrayLength < expectedArrayLength || \
@ -4200,7 +4213,7 @@ WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue,
\
MakeContextCurrent(); \
gl->f##name(location, info.arraySize, \
static_cast<ptrType*>(JS_GetTypedArrayData(wa))); \
static_cast<ptrType*>(JS_GetArrayBufferViewData(wa, aCx))); \
return NS_OK; \
}
@ -4220,7 +4233,7 @@ WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,
\
nsIWebGLUniformLocation* ploc = aLocation; \
OBTAIN_UNIFORM_LOCATION(#name ": location") \
if (JS_GetTypedArrayType(wa) != js::TypedArray::TYPE_FLOAT32) { \
if (!wa || !JS_IsFloat32Array(wa, aCx)) { \
return ErrorInvalidValue(#name ": array must be of Float32 type"); \
} \
int elementSize = location_object->ElementSize(); \
@ -4231,7 +4244,7 @@ WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,
dim*dim, \
elementSize); \
} \
PRUint32 arrayLength = JS_GetTypedArrayLength(wa); \
PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx); \
const WebGLUniformInfo& info = location_object->Info(); \
PRUint32 expectedArrayLength = dim * dim * info.arraySize; \
if (arrayLength < expectedArrayLength || \
@ -4260,7 +4273,7 @@ WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,
\
MakeContextCurrent(); \
gl->f##name(location, info.arraySize, false, \
static_cast<WebGLfloat*>(JS_GetTypedArrayData(wa))); \
static_cast<WebGLfloat*>(JS_GetArrayBufferViewData(wa, aCx))); \
return NS_OK; \
}
@ -4306,15 +4319,15 @@ SIMPLE_METHOD_UNIFORM_2(Uniform2f, Uniform2f, WebGLfloat, WebGLfloat)
SIMPLE_METHOD_UNIFORM_3(Uniform3f, Uniform3f, WebGLfloat, WebGLfloat, WebGLfloat)
SIMPLE_METHOD_UNIFORM_4(Uniform4f, Uniform4f, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1iv, 1, TYPE_INT32, WebGLint)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2iv, 2, TYPE_INT32, WebGLint)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3iv, 3, TYPE_INT32, WebGLint)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4iv, 4, TYPE_INT32, WebGLint)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1iv, 1, Int32, WebGLint)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2iv, 2, Int32, WebGLint)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3iv, 3, Int32, WebGLint)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4iv, 4, Int32, WebGLint)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1fv, 1, TYPE_FLOAT32, WebGLfloat)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2fv, 2, TYPE_FLOAT32, WebGLfloat)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3fv, 3, TYPE_FLOAT32, WebGLfloat)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4fv, 4, TYPE_FLOAT32, WebGLfloat)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1fv, 1, Float32, WebGLfloat)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2fv, 2, Float32, WebGLfloat)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3fv, 3, Float32, WebGLfloat)
SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4fv, 4, Float32, WebGLfloat)
SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix2fv, 2)
SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix3fv, 3)
@ -4409,7 +4422,7 @@ WebGLContext::VertexAttrib4f(PRUint32 index, WebGLfloat x0, WebGLfloat x1,
return NS_OK;
}
#define SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, arrayType, ptrType) \
#define SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, ptrType) \
NS_IMETHODIMP \
WebGLContext::name(WebGLuint idx, const JS::Value& aValue, JSContext* aCx) \
{ \
@ -4421,16 +4434,13 @@ WebGLContext::name(WebGLuint idx, const JS::Value& aValue, JSContext* aCx)
if (!IsContextStable()) { \
return NS_OK; \
} \
if (JS_GetTypedArrayType(wa) != js::TypedArray::arrayType) { \
return ErrorInvalidOperation(#name ": array must be " #arrayType); \
} \
if (JS_GetTypedArrayLength(wa) < cnt) { \
if (JS_GetTypedArrayLength(wa, aCx) < cnt) { \
return ErrorInvalidOperation(#name ": array must be >= %d elements", \
cnt); \
} \
\
MakeContextCurrent(); \
ptrType *ptr = static_cast<ptrType*>(JS_GetTypedArrayData(wa)); \
ptrType *ptr = static_cast<ptrType*>(JS_GetFloat32ArrayData(wa, aCx)); \
if (idx) { \
gl->f##name(idx, ptr); \
} else { \
@ -4444,10 +4454,10 @@ WebGLContext::name(WebGLuint idx, const JS::Value& aValue, JSContext* aCx)
return NS_OK; \
}
SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, TYPE_FLOAT32, WebGLfloat)
SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, TYPE_FLOAT32, WebGLfloat)
SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, TYPE_FLOAT32, WebGLfloat)
SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, TYPE_FLOAT32, WebGLfloat)
SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, WebGLfloat)
SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, WebGLfloat)
SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, WebGLfloat)
SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, WebGLfloat)
NS_IMETHODIMP
WebGLContext::UseProgram(nsIWebGLProgram *pobj)
@ -4733,9 +4743,9 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
NS_IMETHODIMP
WebGLContext::CompressedTexImage2D(WebGLenum target, WebGLint level, WebGLenum internalformat,
WebGLsizei width, WebGLsizei height, WebGLint border,
const JS::Value& pixels)
const JS::Value& pixels, JSContext *cx)
{
if (!pixels.isObject() || !js_IsTypedArray(&pixels.toObject())) {
if (!pixels.isObject() || !JS_IsTypedArrayObject(&pixels.toObject(), cx)) {
return NS_ERROR_FAILURE;
}
@ -4753,9 +4763,9 @@ WebGLContext::CompressedTexImage2D(WebGLenum target, WebGLint level, WebGLenum i
NS_IMETHODIMP
WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint xoffset,
WebGLint yoffset, WebGLsizei width, WebGLsizei height,
WebGLenum format, const JS::Value& pixels)
WebGLenum format, const JS::Value& pixels, JSContext *cx)
{
if (!pixels.isObject() || !js_IsTypedArray(&pixels.toObject())) {
if (!pixels.isObject() || !JS_IsTypedArrayObject(&pixels.toObject(), cx)) {
return NS_ERROR_FAILURE;
}
@ -5225,30 +5235,35 @@ NS_IMETHODIMP
WebGLContext::TexImage2D_array(WebGLenum target, WebGLint level, WebGLenum internalformat,
WebGLsizei width, WebGLsizei height, WebGLint border,
WebGLenum format, WebGLenum type,
JSObject *pixels)
JSObject *pixels, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
if (pixels && !JS_IsTypedArrayObject(pixels, cx))
return ErrorInvalidValue("TexSubImage2D: pixels are wrong type!");
return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
pixels ? JS_GetTypedArrayData(pixels) : 0,
pixels ? JS_GetTypedArrayByteLength(pixels) : 0,
pixels ? (int)JS_GetTypedArrayType(pixels) : -1,
pixels ? JS_GetArrayBufferViewData(pixels, cx) : 0,
pixels ? JS_GetArrayBufferViewByteLength(pixels, cx) : 0,
pixels ? (int)JS_GetTypedArrayType(pixels, cx) : -1,
WebGLTexelFormat::Auto, false);
}
NS_IMETHODIMP
WebGLContext::TexImage2D_imageData(WebGLenum target, WebGLint level, WebGLenum internalformat,
WebGLsizei width, WebGLsizei height, WebGLint border,
WebGLenum format, WebGLenum type,
JSObject *pixels)
WebGLsizei width, WebGLsizei height, WebGLint border,
WebGLenum format, WebGLenum type,
JSObject *pixels, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
return TexImage2D_base(target, level, internalformat, width, height, 4*width, border, format, type,
pixels ? JS_GetTypedArrayData(pixels) : 0,
pixels ? JS_GetTypedArrayByteLength(pixels) : 0,
pixels ? JS_GetArrayBufferViewData(pixels, cx) : 0,
pixels ? JS_GetArrayBufferViewByteLength(pixels, cx) : 0,
-1,
WebGLTexelFormat::RGBA8, false);
}
@ -5406,7 +5421,7 @@ WebGLContext::TexSubImage2D_array(WebGLenum target, WebGLint level,
WebGLint xoffset, WebGLint yoffset,
WebGLsizei width, WebGLsizei height,
WebGLenum format, WebGLenum type,
JSObject *pixels)
JSObject *pixels, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
@ -5414,10 +5429,12 @@ WebGLContext::TexSubImage2D_array(WebGLenum target, WebGLint level,
if (!pixels)
return ErrorInvalidValue("TexSubImage2D: pixels must not be null!");
NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
return TexSubImage2D_base(target, level, xoffset, yoffset,
width, height, 0, format, type,
JS_GetTypedArrayData(pixels), JS_GetTypedArrayByteLength(pixels),
JS_GetTypedArrayType(pixels),
JS_GetArrayBufferViewData(pixels, cx), JS_GetArrayBufferViewByteLength(pixels, cx),
JS_GetTypedArrayType(pixels, cx),
WebGLTexelFormat::Auto, false);
}
@ -5426,7 +5443,7 @@ WebGLContext::TexSubImage2D_imageData(WebGLenum target, WebGLint level,
WebGLint xoffset, WebGLint yoffset,
WebGLsizei width, WebGLsizei height,
WebGLenum format, WebGLenum type,
JSObject *pixels)
JSObject *pixels, JSContext *cx)
{
if (!IsContextStable())
return NS_OK;
@ -5434,9 +5451,11 @@ WebGLContext::TexSubImage2D_imageData(WebGLenum target, WebGLint level,
if (!pixels)
return ErrorInvalidValue("TexSubImage2D: pixels must not be null!");
NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
return TexSubImage2D_base(target, level, xoffset, yoffset,
width, height, 4*width, format, type,
JS_GetTypedArrayData(pixels), JS_GetTypedArrayByteLength(pixels),
JS_GetArrayBufferViewData(pixels, cx), JS_GetArrayBufferViewByteLength(pixels, cx),
-1,
WebGLTexelFormat::RGBA8, false);
}

View File

@ -43,7 +43,7 @@
#include "CheckedInt.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#if defined(USE_ANGLE)
#include "angle/ShaderLang.h"
@ -406,10 +406,10 @@ bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, in
(IsExtensionEnabled(WebGL_OES_texture_float) && type == LOCAL_GL_FLOAT))
{
if (jsArrayType != -1) {
if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::TypedArray::TYPE_UINT8) ||
(type == LOCAL_GL_FLOAT && jsArrayType != js::TypedArray::TYPE_FLOAT32))
if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::ArrayBufferView::TYPE_UINT8) ||
(type == LOCAL_GL_FLOAT && jsArrayType != js::ArrayBufferView::TYPE_FLOAT32))
{
ErrorInvalidOperation("%s: invalid typed array type for given format", info);
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
return false;
}
}
@ -440,8 +440,8 @@ bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, in
switch (type) {
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
if (jsArrayType != -1 && jsArrayType != js::TypedArray::TYPE_UINT16) {
ErrorInvalidOperation("%s: invalid typed array type for given format", info);
if (jsArrayType != -1 && jsArrayType != js::ArrayBufferView::TYPE_UINT16) {
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
return false;
}
@ -453,8 +453,8 @@ bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, in
return false;
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
if (jsArrayType != -1 && jsArrayType != js::TypedArray::TYPE_UINT16) {
ErrorInvalidOperation("%s: invalid typed array type for given format", info);
if (jsArrayType != -1 && jsArrayType != js::ArrayBufferView::TYPE_UINT16) {
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
return false;
}

View File

@ -113,7 +113,7 @@
#include <algorithm>
#include "jsapi.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/ContentParent.h"
@ -3935,13 +3935,12 @@ nsCanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
return NS_ERROR_DOM_SYNTAX_ERR;
}
JSObject* darray =
js_CreateTypedArray(aCx, js::TypedArray::TYPE_UINT8_CLAMPED, len.value());
JSObject* darray = JS_NewUint8ClampedArray(aCx, len.value());
if (!darray) {
return NS_ERROR_OUT_OF_MEMORY;
}
uint8_t* data = static_cast<uint8_t*>(JS_GetTypedArrayData(darray));
uint8_t* data = JS_GetUint8ClampedArrayData(darray, aCx);
/* Copy the surface contents to the buffer */
nsRefPtr<gfxImageSurface> tmpsurf =

View File

@ -109,7 +109,7 @@
#include <algorithm>
#include "jsapi.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/ContentParent.h"
@ -4103,8 +4103,7 @@ nsCanvasRenderingContext2DAzure::GetImageDataArray(JSContext* aCx,
return NS_ERROR_DOM_SYNTAX_ERR;
}
JSObject* darray =
js_CreateTypedArray(aCx, js::TypedArray::TYPE_UINT8_CLAMPED, len.value());
JSObject* darray = JS_NewUint8ClampedArray(aCx, len.value());
if (!darray) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -4114,7 +4113,7 @@ nsCanvasRenderingContext2DAzure::GetImageDataArray(JSContext* aCx,
return NS_OK;
}
uint8_t* data = static_cast<uint8_t*>(JS_GetTypedArrayData(darray));
uint8_t* data = JS_GetUint8ClampedArrayData(darray, aCx);
IntRect srcRect(0, 0, mWidth, mHeight);
IntRect destRect(aX, aY, aWidth, aHeight);

View File

@ -40,7 +40,7 @@
#include "nsDOMNotifyAudioAvailableEvent.h"
#include "nsDOMClassInfoID.h" // DOMCI_DATA, NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO
#include "nsContentUtils.h" // NS_DROP_JS_OBJECTS
#include "jstypedarray.h"
#include "jsfriendapi.h"
nsDOMNotifyAudioAvailableEvent::nsDOMNotifyAudioAvailableEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
@ -113,15 +113,12 @@ nsDOMNotifyAudioAvailableEvent::GetFrameBuffer(JSContext* aCx, jsval* aResult)
// Cache this array so we don't recreate on next call.
NS_HOLD_JS_OBJECTS(this, nsDOMNotifyAudioAvailableEvent);
mCachedArray = js_CreateTypedArray(aCx, js::TypedArray::TYPE_FLOAT32, mFrameBufferLength);
mCachedArray = JS_NewFloat32Array(aCx, mFrameBufferLength);
if (!mCachedArray) {
NS_DROP_JS_OBJECTS(this, nsDOMNotifyAudioAvailableEvent);
NS_ERROR("Failed to get audio signal!");
return NS_ERROR_FAILURE;
}
JSObject *tdest = js::TypedArray::getTypedArray(mCachedArray);
memcpy(JS_GetTypedArrayData(tdest), mFrameBuffer.get(), mFrameBufferLength * sizeof(float));
memcpy(JS_GetFloat32ArrayData(mCachedArray, aCx), mFrameBuffer.get(), mFrameBufferLength * sizeof(float));
*aResult = OBJECT_TO_JSVAL(mCachedArray);
return NS_OK;

View File

@ -57,7 +57,6 @@
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "jstypedarray.h"
#include "nsJSUtils.h"
#include "nsITimer.h"
@ -184,36 +183,35 @@ nsHTMLAudioElement::MozSetup(PRUint32 aChannels, PRUint32 aRate)
}
NS_IMETHODIMP
nsHTMLAudioElement::MozWriteAudio(const jsval &aData, JSContext *aCx, PRUint32 *aRetVal)
nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, PRUint32* aRetVal)
{
if (!mAudioStream) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
if (JSVAL_IS_PRIMITIVE(aData)) {
if (!aData.isObject()) {
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
}
JSObject *darray = JSVAL_TO_OBJECT(aData);
JS::AutoValueRooter tsrc_tvr(aCx);
JSObject *tsrc = NULL;
JSObject* darray = &aData.toObject();
JS::AutoObjectRooter tvr(aCx);
JSObject* tsrc = NULL;
// Allow either Float32Array or plain JS Array
if (js::GetObjectClass(darray) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_FLOAT32])
{
tsrc = js::TypedArray::getTypedArray(darray);
if (JS_IsFloat32Array(darray, aCx)) {
tsrc = darray;
} else if (JS_IsArrayObject(aCx, darray)) {
JSObject *nobj = js_CreateTypedArrayWithArray(aCx, js::TypedArray::TYPE_FLOAT32, darray);
JSObject* nobj = JS_NewFloat32ArrayFromArray(aCx, darray);
if (!nobj) {
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
}
*tsrc_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj);
tsrc = js::TypedArray::getTypedArray(nobj);
tsrc = nobj;
} else {
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
}
tvr.setObject(tsrc);
PRUint32 dataLength = JS_GetTypedArrayLength(tsrc);
PRUint32 dataLength = JS_GetTypedArrayLength(tsrc, aCx);
// Make sure that we are going to write the correct amount of data based
// on number of channels.
@ -224,7 +222,7 @@ nsHTMLAudioElement::MozWriteAudio(const jsval &aData, JSContext *aCx, PRUint32 *
// Don't write more than can be written without blocking.
PRUint32 writeLen = NS_MIN(mAudioStream->Available(), dataLength / mChannels);
nsresult rv = mAudioStream->Write(JS_GetTypedArrayData(tsrc), writeLen);
nsresult rv = mAudioStream->Write(JS_GetFloat32ArrayData(tsrc, aCx), writeLen);
if (NS_FAILED(rv)) {
return rv;
}

View File

@ -226,7 +226,7 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
rv = target->AddEventListener(NS_LITERAL_STRING("error"), this, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = req->Send(nsnull);
rv = req->Send(nsnull, context->GetNativeContext());
NS_ENSURE_SUCCESS(rv, rv);
mTemplateBuilder = aBuilder;

View File

@ -55,7 +55,7 @@ DOMInterfaces = {
},
'implicitJSContext': {
'all': [
'response', 'getInterface'
'response', 'getInterface', 'send', 'sendAsBinary'
],
'setterOnly': [
'onreadystatechange'

View File

@ -324,7 +324,7 @@ class CGHeaders(CGWrapper):
for t in types:
if t.unroll().isInterface():
if t.unroll().isArrayBuffer():
bindingHeaders.add("jstypedarray.h")
bindingHeaders.add("jsfriendapi.h")
else:
typeDesc = d.getDescriptor(t.unroll().inner.identifier.name)
if typeDesc is not None:
@ -1189,7 +1189,7 @@ def getArgumentConversionTemplate(type, descriptor):
if type.isArrayBuffer():
template = (
" JSObject* ${name};\n"
" if (${argVal}.isObject() && JS_IsArrayBufferObject(&${argVal}.toObject())) {\n"
" if (${argVal}.isObject() && JS_IsArrayBufferObject(&${argVal}.toObject(), cx)) {\n"
" ${name} = &${argVal}.toObject();\n"
" }")
if type.nullable():
@ -1900,7 +1900,7 @@ class CGMethodCall(CGThing):
# other things.
# XXXbz Do we need to worry about security
# wrappers around the array buffer?
pickFirstSignature("%s.isObject() && JS_IsArrayBufferObject(&%s.toObject())" %
pickFirstSignature("%s.isObject() && JS_IsArrayBufferObject(&%s.toObject(), cx)" %
(distinguishingArg, distinguishingArg),
lambda s: (s[1][distinguishingIndex].type.isArrayBuffer() or
s[1][distinguishingIndex].type.isObject()))

View File

@ -10,7 +10,7 @@
#include "mozilla/dom/bindings/DOMJSClass.h"
#include "jsapi.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "XPCQuickStubs.h"
#include "XPCWrapper.h"
@ -169,7 +169,7 @@ IsPlatformObject(JSContext* cx, JSObject* obj)
clasp = js::GetObjectJSClass(obj);
}
return IS_WRAPPER_CLASS(js::Valueify(clasp)) || IsDOMClass(clasp) ||
JS_IsArrayBufferObject(obj);
JS_IsArrayBufferObject(obj, cx);
}
template <class T>

View File

@ -177,7 +177,7 @@ interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension
const WebGLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
};
[scriptable, builtinclass, uuid(dcba5412-42b4-4897-b2f4-56a5cae7ef2d)]
[scriptable, builtinclass, uuid(ba7635d7-98af-41ac-8bf9-9f08cf441958)]
interface nsIDOMWebGLRenderingContext : nsISupports
{
//
@ -624,7 +624,7 @@ interface nsIDOMWebGLRenderingContext : nsISupports
// Modified: void glBufferData(WebGLenum target, long size, const void* data, WebGLenum usage);
[implicit_jscontext] void bufferData(in long target, in jsval data, in long usage);
void bufferSubData(in long target, in long offset, in jsval data);
[implicit_jscontext] void bufferSubData(in long target, in long offset, in jsval data);
WebGLenum checkFramebufferStatus(in WebGLenum target);
void clear(in WebGLbitfield mask);
@ -634,11 +634,11 @@ interface nsIDOMWebGLRenderingContext : nsISupports
void colorMask(in WebGLboolean red, in WebGLboolean green, in WebGLboolean blue, in WebGLboolean alpha);
void compileShader([optional] in nsIWebGLShader shader);
void compressedTexImage2D(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
[implicit_jscontext] void compressedTexImage2D(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
in WebGLsizei width, in WebGLsizei height, in WebGLint border,
in jsval pixels);
void compressedTexSubImage2D(in WebGLenum target, in WebGLint level, in WebGLint xoffset,
[implicit_jscontext] void compressedTexSubImage2D(in WebGLenum target, in WebGLint level, in WebGLint xoffset,
in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height,
in WebGLenum format, in jsval pixels);
@ -749,7 +749,7 @@ interface nsIDOMWebGLRenderingContext : nsISupports
void pixelStorei(in WebGLenum pname, in WebGLint param);
void polygonOffset(in WebGLfloat factor, in WebGLfloat units);
void readPixels(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height,
[implicit_jscontext] void readPixels(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height,
in WebGLenum format, in WebGLenum type, in jsval pixels);
//void glReleaseShaderCompiler();
@ -769,10 +769,10 @@ interface nsIDOMWebGLRenderingContext : nsISupports
void stencilOpSeparate(in WebGLenum face, in WebGLenum fail, in WebGLenum zfail, in WebGLenum zpass);
void texImage2D([optional] in long dummy);
[noscript] void texImage2D_array(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
[noscript,implicit_jscontext] void texImage2D_array(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
in WebGLsizei width, in WebGLsizei height,
in WebGLint border, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
[noscript] void texImage2D_imageData(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
[noscript,implicit_jscontext] void texImage2D_imageData(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
in WebGLsizei width, in WebGLsizei height,
in WebGLint border, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
@ -781,10 +781,10 @@ interface nsIDOMWebGLRenderingContext : nsISupports
in WebGLenum format, in WebGLenum type, in Element element);
void texSubImage2D([optional] in long dummy);
[noscript] void texSubImage2D_array(in WebGLenum target, in WebGLint level,
[noscript,implicit_jscontext] void texSubImage2D_array(in WebGLenum target, in WebGLint level,
in WebGLint xoffset, in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height,
in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
[noscript] void texSubImage2D_imageData(in WebGLenum target, in WebGLint level,
[noscript,implicit_jscontext] void texSubImage2D_imageData(in WebGLenum target, in WebGLint level,
in WebGLint xoffset, in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height,
in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
// HTMLImageElement, HTMLCanvasElement, HTMLVideoElement

View File

@ -46,7 +46,7 @@
#include "nsIWorkerHolder.h"
#include "nsIXPConnect.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "mozilla/dom/workers/Workers.h"
#include "mozilla/ipc/Ril.h"
#include "nsContentUtils.h"
@ -100,21 +100,21 @@ PostToRIL(JSContext *cx, unsigned argc, jsval *vp)
data = abs.ptr();
} else if (!JSVAL_IS_PRIMITIVE(v)) {
JSObject *obj = JSVAL_TO_OBJECT(v);
if (!js_IsTypedArray(obj)) {
if (!JS_IsTypedArrayObject(obj, cx)) {
JS_ReportError(cx, "Object passed in wasn't a typed array");
return false;
}
uint32_t type = JS_GetTypedArrayType(obj);
if (type != js::TypedArray::TYPE_INT8 &&
type != js::TypedArray::TYPE_UINT8 &&
type != js::TypedArray::TYPE_UINT8_CLAMPED) {
uint32_t type = JS_GetTypedArrayType(obj, cx);
if (type != js::ArrayBufferView::TYPE_INT8 &&
type != js::ArrayBufferView::TYPE_UINT8 &&
type != js::ArrayBufferView::TYPE_UINT8_CLAMPED) {
JS_ReportError(cx, "Typed array data is not octets");
return false;
}
size = JS_GetTypedArrayByteLength(obj);
data = JS_GetTypedArrayData(obj);
size = JS_GetTypedArrayByteLength(obj, cx);
data = JS_GetArrayBufferViewData(obj, cx);
} else {
JS_ReportError(cx,
"Incorrect argument. Expecting a string or a typed array");
@ -181,13 +181,12 @@ RILReceiver::DispatchRILEvent::RunTask(JSContext *aCx)
{
JSObject *obj = JS_GetGlobalObject(aCx);
JSObject *array =
js_CreateTypedArray(aCx, js::TypedArray::TYPE_UINT8, mMessage->mSize);
JSObject *array = JS_NewUint8Array(aCx, mMessage->mSize);
if (!array) {
return false;
}
memcpy(JS_GetTypedArrayData(array), mMessage->mData, mMessage->mSize);
memcpy(JS_GetArrayBufferViewData(array, aCx), mMessage->mData, mMessage->mSize);
jsval argv[] = { OBJECT_TO_JSVAL(array) };
return JS_CallFunctionName(aCx, obj, "onRILMessage", NS_ARRAY_LENGTH(argv),
argv, argv);

View File

@ -44,7 +44,6 @@
#include "jsapi.h"
#include "jsatom.h"
#include "jsfriendapi.h"
#include "jstypedarray.h"
#include "nsJSUtils.h"
#include "Exceptions.h"
@ -58,7 +57,6 @@
USING_WORKERS_NAMESPACE
using mozilla::dom::workers::exceptions::ThrowFileExceptionForCode;
using js::ArrayBuffer;
namespace {
@ -194,13 +192,13 @@ private:
return false;
}
JSObject* jsArrayBuffer = js_CreateArrayBuffer(aCx, blobSize);
JSObject* jsArrayBuffer = JS_NewArrayBuffer(aCx, blobSize);
if (!jsArrayBuffer) {
return false;
}
uint32_t bufferLength = JS_GetArrayBufferByteLength(jsArrayBuffer);
uint8_t* arrayBuffer = JS_GetArrayBufferData(jsArrayBuffer);
uint32_t bufferLength = JS_GetArrayBufferByteLength(jsArrayBuffer, aCx);
uint8_t* arrayBuffer = JS_GetArrayBufferData(jsArrayBuffer, aCx);
rv = fileReader->ReadAsArrayBuffer(blob, bufferLength, arrayBuffer);
if (!EnsureSucceededOrThrow(aCx, rv)) {

View File

@ -13,7 +13,7 @@
#include "nsIXMLHttpRequest.h"
#include "nsIXPConnect.h"
#include "jstypedarray.h"
#include "jsfriendapi.h"
#include "nsContentUtils.h"
#include "nsJSUtils.h"
#include "nsThreadUtils.h"
@ -1158,12 +1158,12 @@ public:
MainThreadRun()
{
nsCOMPtr<nsIVariant> variant;
RuntimeService::AutoSafeJSContext cx;
if (mBody.data()) {
nsIXPConnect* xpc = nsContentUtils::XPConnect();
NS_ASSERTION(xpc, "This should never be null!");
RuntimeService::AutoSafeJSContext cx;
int error = 0;
JSStructuredCloneCallbacks* callbacks =
@ -1216,7 +1216,7 @@ public:
mProxy->mInnerChannelId++;
nsresult rv = mProxy->mXHR->Send(variant);
nsresult rv = mProxy->mXHR->Send(variant, cx);
if (NS_SUCCEEDED(rv)) {
mProxy->mOutstandingSendCount++;
@ -1987,7 +1987,7 @@ XMLHttpRequest::Send(JSObject* aBody, nsresult& aRv)
JSContext* cx = GetJSContext();
jsval valToClone;
if (js_IsArrayBuffer(aBody) || file::GetDOMBlobFromJSObject(aBody)) {
if (JS_IsArrayBufferObject(aBody, cx) || file::GetDOMBlobFromJSObject(aBody)) {
valToClone = OBJECT_TO_JSVAL(aBody);
}
else {

View File

@ -205,7 +205,6 @@ INSTALLED_HEADERS = \
jsproto.tbl \
jsprvtd.h \
jspubtd.h \
jstypedarray.h \
jstypes.h \
jsutil.h \
jsversion.h \

View File

@ -89,6 +89,7 @@ CPPSRCS = \
testSetProperty.cpp \
testStringBuffer.cpp \
testTrap.cpp \
testTypedArrays.cpp \
testUTF8.cpp \
testValueABI.cpp \
testVersion.cpp \

View File

@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*/
#include "tests.h"
#include "jsfriendapi.h"
using namespace js;
BEGIN_TEST(testTypedArrays)
{
bool ok = true;
ok = ok &&
TestPlainTypedArray<JS_NewInt8Array, int8_t, JS_GetInt8ArrayData>(cx) &&
TestPlainTypedArray<JS_NewUint8Array, uint8_t, JS_GetUint8ArrayData>(cx) &&
TestPlainTypedArray<JS_NewUint8ClampedArray, uint8_t, JS_GetUint8ClampedArrayData>(cx) &&
TestPlainTypedArray<JS_NewInt16Array, int16_t, JS_GetInt16ArrayData>(cx) &&
TestPlainTypedArray<JS_NewUint16Array, uint16_t, JS_GetUint16ArrayData>(cx) &&
TestPlainTypedArray<JS_NewInt32Array, int32_t, JS_GetInt32ArrayData>(cx) &&
TestPlainTypedArray<JS_NewUint32Array, uint32_t, JS_GetUint32ArrayData>(cx) &&
TestPlainTypedArray<JS_NewFloat32Array, float, JS_GetFloat32ArrayData>(cx) &&
TestPlainTypedArray<JS_NewFloat64Array, double, JS_GetFloat64ArrayData>(cx);
size_t nbytes = sizeof(double) * 8;
JSObject *buffer = JS_NewArrayBuffer(cx, nbytes);
CHECK(JS_IsArrayBufferObject(buffer, cx));
JSObject *proto = JS_GetPrototype(buffer);
CHECK(!JS_IsArrayBufferObject(proto, cx));
JSObject *dummy = JS_GetParent(proto);
CHECK(!JS_IsArrayBufferObject(dummy, cx));
CHECK_EQUAL(JS_GetArrayBufferByteLength(buffer, cx), nbytes);
memset(JS_GetArrayBufferData(buffer, cx), 1, nbytes);
ok = ok &&
TestArrayFromBuffer<JS_NewInt8ArrayWithBuffer, JS_NewInt8ArrayFromArray, int8_t, JS_GetInt8ArrayData>(cx) &&
TestArrayFromBuffer<JS_NewUint8ArrayWithBuffer, JS_NewUint8ArrayFromArray, uint8_t, JS_GetUint8ArrayData>(cx) &&
TestArrayFromBuffer<JS_NewUint8ClampedArrayWithBuffer, JS_NewUint8ClampedArrayFromArray, uint8_t, JS_GetUint8ClampedArrayData>(cx) &&
TestArrayFromBuffer<JS_NewInt16ArrayWithBuffer, JS_NewInt16ArrayFromArray, int16_t, JS_GetInt16ArrayData>(cx) &&
TestArrayFromBuffer<JS_NewUint16ArrayWithBuffer, JS_NewUint16ArrayFromArray, uint16_t, JS_GetUint16ArrayData>(cx) &&
TestArrayFromBuffer<JS_NewInt32ArrayWithBuffer, JS_NewInt32ArrayFromArray, int32_t, JS_GetInt32ArrayData>(cx) &&
TestArrayFromBuffer<JS_NewUint32ArrayWithBuffer, JS_NewUint32ArrayFromArray, uint32_t, JS_GetUint32ArrayData>(cx) &&
TestArrayFromBuffer<JS_NewFloat32ArrayWithBuffer, JS_NewFloat32ArrayFromArray, float, JS_GetFloat32ArrayData>(cx) &&
TestArrayFromBuffer<JS_NewFloat64ArrayWithBuffer, JS_NewFloat64ArrayFromArray, double, JS_GetFloat64ArrayData>(cx);
return ok;
}
template<JSObject *Create(JSContext *, uint32_t),
typename Element,
Element *GetData(JSObject *, JSContext *)>
bool
TestPlainTypedArray(JSContext *cx)
{
JSObject *array = Create(cx, 7);
CHECK(JS_IsTypedArrayObject(array, cx));
JSObject *proto = JS_GetPrototype(array);
CHECK(!JS_IsTypedArrayObject(proto, cx));
JSObject *dummy = JS_GetParent(proto);
CHECK(!JS_IsTypedArrayObject(dummy, cx));
CHECK_EQUAL(JS_GetTypedArrayLength(array, cx), 7);
CHECK_EQUAL(JS_GetTypedArrayByteOffset(array, cx), 0);
CHECK_EQUAL(JS_GetTypedArrayByteLength(array, cx), sizeof(Element) * 7);
Element *data;
CHECK(data = GetData(array, cx));
*data = 13;
jsval v;
CHECK(JS_GetElement(cx, array, 0, &v));
CHECK_SAME(v, INT_TO_JSVAL(13));
return true;
}
template<JSObject *CreateWithBuffer(JSContext *, JSObject *, uint32_t, int32_t),
JSObject *CreateFromArray(JSContext *, JSObject *),
typename Element,
Element *GetData(JSObject *, JSContext *)>
bool
TestArrayFromBuffer(JSContext *cx)
{
size_t elts = 8;
size_t nbytes = elts * sizeof(Element);
JSObject *buffer = JS_NewArrayBuffer(cx, nbytes);
uint8_t *bufdata;
CHECK(bufdata = JS_GetArrayBufferData(buffer, cx));
memset(bufdata, 1, nbytes);
JSObject *array = CreateWithBuffer(cx, buffer, 0, -1);
CHECK_EQUAL(JS_GetTypedArrayLength(array, cx), elts);
CHECK_EQUAL(JS_GetTypedArrayByteOffset(array, cx), 0);
CHECK_EQUAL(JS_GetTypedArrayByteLength(array, cx), nbytes);
Element *data;
CHECK(data = GetData(array, cx));
CHECK(bufdata = JS_GetArrayBufferData(buffer, cx));
CHECK_EQUAL((void*) data, (void*) bufdata);
CHECK_EQUAL(*bufdata, 1);
CHECK_EQUAL(*reinterpret_cast<uint8_t*>(data), 1);
JSObject *shortArray = CreateWithBuffer(cx, buffer, 0, elts / 2);
CHECK_EQUAL(JS_GetTypedArrayLength(shortArray, cx), elts / 2);
CHECK_EQUAL(JS_GetTypedArrayByteOffset(shortArray, cx), 0);
CHECK_EQUAL(JS_GetTypedArrayByteLength(shortArray, cx), nbytes / 2);
JSObject *ofsArray = CreateWithBuffer(cx, buffer, nbytes / 2, -1);
CHECK_EQUAL(JS_GetTypedArrayLength(ofsArray, cx), elts / 2);
CHECK_EQUAL(JS_GetTypedArrayByteOffset(ofsArray, cx), nbytes / 2);
CHECK_EQUAL(JS_GetTypedArrayByteLength(ofsArray, cx), nbytes / 2);
// Make sure all 3 views reflect the same buffer at the expected locations
jsval v = INT_TO_JSVAL(39);
JS_SetElement(cx, array, 0, &v);
jsval v2;
CHECK(JS_GetElement(cx, array, 0, &v2));
CHECK_SAME(v, v2);
CHECK(JS_GetElement(cx, shortArray, 0, &v2));
CHECK_SAME(v, v2);
CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast<Element*>(data)[0]));
v = INT_TO_JSVAL(40);
JS_SetElement(cx, array, elts / 2, &v);
CHECK(JS_GetElement(cx, array, elts / 2, &v2));
CHECK_SAME(v, v2);
CHECK(JS_GetElement(cx, ofsArray, 0, &v2));
CHECK_SAME(v, v2);
CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast<Element*>(data)[elts / 2]));
v = INT_TO_JSVAL(41);
JS_SetElement(cx, array, elts - 1, &v);
CHECK(JS_GetElement(cx, array, elts - 1, &v2));
CHECK_SAME(v, v2);
CHECK(JS_GetElement(cx, ofsArray, elts / 2 - 1, &v2));
CHECK_SAME(v, v2);
CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast<Element*>(data)[elts - 1]));
JSObject *copy = CreateFromArray(cx, array);
CHECK(JS_GetElement(cx, array, 0, &v));
CHECK(JS_GetElement(cx, copy, 0, &v2));
CHECK_SAME(v, v2);
/* The copy should not see changes in the original */
v2 = INT_TO_JSVAL(42);
JS_SetElement(cx, array, 0, &v2);
CHECK(JS_GetElement(cx, copy, 0, &v2));
CHECK_SAME(v2, v); /* v is still the original value from 'array' */
return true;
}
END_TEST(testTypedArrays)

View File

@ -96,12 +96,29 @@ enum StructuredDataType {
SCTAG_NUMBER_OBJECT,
SCTAG_BACK_REFERENCE_OBJECT,
SCTAG_TYPED_ARRAY_MIN = 0xFFFF0100,
SCTAG_TYPED_ARRAY_INT8 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_INT8,
SCTAG_TYPED_ARRAY_UINT8 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_UINT8,
SCTAG_TYPED_ARRAY_INT16 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_INT16,
SCTAG_TYPED_ARRAY_UINT16 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_UINT16,
SCTAG_TYPED_ARRAY_INT32 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_INT32,
SCTAG_TYPED_ARRAY_UINT32 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_UINT32,
SCTAG_TYPED_ARRAY_FLOAT32 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_FLOAT32,
SCTAG_TYPED_ARRAY_FLOAT64 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_FLOAT64,
SCTAG_TYPED_ARRAY_UINT8_CLAMPED = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_UINT8_CLAMPED,
SCTAG_TYPED_ARRAY_MAX = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_MAX - 1,
SCTAG_END_OF_BUILTIN_TYPES
};
static StructuredDataType
ArrayTypeToTag(uint32_t type)
{
JS_ASSERT(type < TypedArray::TYPE_MAX);
return static_cast<StructuredDataType>(uint32_t(SCTAG_TYPED_ARRAY_MIN) + type);
}
JS_STATIC_ASSERT(SCTAG_END_OF_BUILTIN_TYPES <= JS_SCTAG_USER_MIN);
JS_STATIC_ASSERT(JS_SCTAG_USER_MIN <= JS_SCTAG_USER_MAX);
JS_STATIC_ASSERT(TypedArray::TYPE_INT8 == 0);
static uint8_t
SwapBytes(uint8_t u)
@ -407,36 +424,6 @@ JSStructuredCloneWriter::checkStack()
#endif
}
static inline uint32_t
ArrayTypeToTag(uint32_t type)
{
/*
* As long as these are all true, we can just add. Note that for backward
* compatibility, the tags cannot change. So if the ArrayType type codes
* change, this function and TagToArrayType will have to do more work.
*/
JS_STATIC_ASSERT(TypedArray::TYPE_INT8 == 0);
JS_STATIC_ASSERT(TypedArray::TYPE_UINT8 == 1);
JS_STATIC_ASSERT(TypedArray::TYPE_INT16 == 2);
JS_STATIC_ASSERT(TypedArray::TYPE_UINT16 == 3);
JS_STATIC_ASSERT(TypedArray::TYPE_INT32 == 4);
JS_STATIC_ASSERT(TypedArray::TYPE_UINT32 == 5);
JS_STATIC_ASSERT(TypedArray::TYPE_FLOAT32 == 6);
JS_STATIC_ASSERT(TypedArray::TYPE_FLOAT64 == 7);
JS_STATIC_ASSERT(TypedArray::TYPE_UINT8_CLAMPED == 8);
JS_STATIC_ASSERT(TypedArray::TYPE_MAX == TypedArray::TYPE_UINT8_CLAMPED + 1);
JS_ASSERT(type < TypedArray::TYPE_MAX);
return SCTAG_TYPED_ARRAY_MIN + type;
}
static inline uint32_t
TagToArrayType(uint32_t tag)
{
JS_ASSERT(SCTAG_TYPED_ARRAY_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_MAX);
return tag - SCTAG_TYPED_ARRAY_MIN;
}
bool
JSStructuredCloneWriter::writeTypedArray(JSObject *obj)
{
@ -539,7 +526,7 @@ class AutoEnterCompartmentAndPushPrincipal : public JSAutoEnterCompartment
bool
JSStructuredCloneWriter::startWrite(const js::Value &v)
JSStructuredCloneWriter::startWrite(const Value &v)
{
assertSameCompartment(context(), v);
@ -577,9 +564,9 @@ JSStructuredCloneWriter::startWrite(const js::Value &v)
return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(d);
} else if (obj->isObject() || obj->isArray()) {
return startObject(obj);
} else if (js_IsTypedArray(obj)) {
} else if (obj->isTypedArray()) {
return writeTypedArray(obj);
} else if (js_IsArrayBuffer(obj)) {
} else if (obj->isArrayBuffer()) {
return writeArrayBuffer(obj);
} else if (obj->isBoolean()) {
return out.writePair(SCTAG_BOOLEAN_OBJECT, obj->asBoolean().unbox());
@ -705,29 +692,66 @@ JSStructuredCloneReader::readString(uint32_t nchars)
bool
JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp)
{
uint32_t atype = TagToArrayType(tag);
JSObject *obj = js_CreateTypedArray(context(), atype, nelems);
JSObject *obj = NULL;
switch (tag) {
case SCTAG_TYPED_ARRAY_INT8:
obj = JS_NewInt8Array(context(), nelems);
break;
case SCTAG_TYPED_ARRAY_UINT8:
obj = JS_NewUint8Array(context(), nelems);
break;
case SCTAG_TYPED_ARRAY_INT16:
obj = JS_NewInt16Array(context(), nelems);
break;
case SCTAG_TYPED_ARRAY_UINT16:
obj = JS_NewUint16Array(context(), nelems);
break;
case SCTAG_TYPED_ARRAY_INT32:
obj = JS_NewInt32Array(context(), nelems);
break;
case SCTAG_TYPED_ARRAY_UINT32:
obj = JS_NewUint32Array(context(), nelems);
break;
case SCTAG_TYPED_ARRAY_FLOAT32:
obj = JS_NewFloat32Array(context(), nelems);
break;
case SCTAG_TYPED_ARRAY_FLOAT64:
obj = JS_NewFloat64Array(context(), nelems);
break;
case SCTAG_TYPED_ARRAY_UINT8_CLAMPED:
obj = JS_NewUint8ClampedArray(context(), nelems);
break;
default:
JS_NOT_REACHED("unknown TypedArray type");
return false;
}
if (!obj)
return false;
vp->setObject(*obj);
JSObject *arr = TypedArray::getTypedArray(obj);
JS_ASSERT(TypedArray::getLength(arr) == nelems);
JS_ASSERT(TypedArray::getType(arr) == atype);
switch (atype) {
case TypedArray::TYPE_INT8:
case TypedArray::TYPE_UINT8:
case TypedArray::TYPE_UINT8_CLAMPED:
return in.readArray((uint8_t *) TypedArray::getDataOffset(arr), nelems);
case TypedArray::TYPE_INT16:
case TypedArray::TYPE_UINT16:
return in.readArray((uint16_t *) TypedArray::getDataOffset(arr), nelems);
case TypedArray::TYPE_INT32:
case TypedArray::TYPE_UINT32:
case TypedArray::TYPE_FLOAT32:
return in.readArray((uint32_t *) TypedArray::getDataOffset(arr), nelems);
case TypedArray::TYPE_FLOAT64:
return in.readArray((uint64_t *) TypedArray::getDataOffset(arr), nelems);
switch (tag) {
case SCTAG_TYPED_ARRAY_INT8:
return in.readArray((uint8_t *) JS_GetInt8ArrayData(arr, context()), nelems);
case SCTAG_TYPED_ARRAY_UINT8:
return in.readArray((uint8_t *) JS_GetUint8ArrayData(arr, context()), nelems);
case SCTAG_TYPED_ARRAY_INT16:
return in.readArray((uint16_t *) JS_GetInt16ArrayData(arr, context()), nelems);
case SCTAG_TYPED_ARRAY_UINT16:
return in.readArray((uint16_t *) JS_GetUint16ArrayData(arr, context()), nelems);
case SCTAG_TYPED_ARRAY_INT32:
return in.readArray((uint32_t *) JS_GetInt32ArrayData(arr, context()), nelems);
case SCTAG_TYPED_ARRAY_UINT32:
return in.readArray((uint32_t *) JS_GetUint32ArrayData(arr, context()), nelems);
case SCTAG_TYPED_ARRAY_FLOAT32:
return in.readArray((uint32_t *) JS_GetFloat32ArrayData(arr, context()), nelems);
case SCTAG_TYPED_ARRAY_FLOAT64:
return in.readArray((uint64_t *) JS_GetFloat64ArrayData(arr, context()), nelems);
case SCTAG_TYPED_ARRAY_UINT8_CLAMPED:
return in.readArray((uint8_t *) JS_GetUint8ClampedArrayData(arr, context()), nelems);
default:
JS_NOT_REACHED("unknown TypedArray type");
return false;
@ -737,7 +761,7 @@ JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp
bool
JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes, Value *vp)
{
JSObject *obj = js_CreateArrayBuffer(context(), nbytes);
JSObject *obj = ArrayBuffer::create(context(), nbytes);
if (!obj)
return false;
vp->setObject(*obj);

View File

@ -828,4 +828,282 @@ js_GetErrorMessage(void *userRef, const char *locale, const unsigned errorNumber
extern JS_FRIEND_API(uint64_t)
js_GetSCOffset(JSStructuredCloneWriter* writer);
/* Typed Array functions, implemented in jstypedarray.cpp */
#ifdef __cplusplus
namespace js {
namespace ArrayBufferView {
enum ViewType {
TYPE_INT8 = 0,
TYPE_UINT8,
TYPE_INT16,
TYPE_UINT16,
TYPE_INT32,
TYPE_UINT32,
TYPE_FLOAT32,
TYPE_FLOAT64,
/*
* Special type that is a uint8_t, but assignments are clamped to [0, 256).
* Treat the raw data type as a uint8_t.
*/
TYPE_UINT8_CLAMPED,
TYPE_MAX
};
} /* namespace ArrayBufferView */
} /* namespace js */
typedef js::ArrayBufferView::ViewType JSArrayBufferViewType;
#else
typedef uint32_t JSArrayBufferViewType;
#endif /* __cplusplus */
/*
* Create a new typed array with nelements elements.
*/
extern JS_FRIEND_API(JSObject *)
JS_NewInt8Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ClampedArray(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewInt16Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewUint16Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewInt32Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewUint32Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat32Array(JSContext *cx, uint32_t nelements);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat64Array(JSContext *cx, uint32_t nelements);
/*
* Create a new typed array and copy in values from the given object. The
* object is used as if it were an array; that is, the new array (if
* successfully created) will have length given by array.length, and its
* elements will be those specified by array[0], array[1], and so on, after
* conversion to the typed array element type.
*/
extern JS_FRIEND_API(JSObject *)
JS_NewInt8ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ClampedArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewInt16ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewUint16ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewInt32ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewUint32ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat32ArrayFromArray(JSContext *cx, JSObject *array);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat64ArrayFromArray(JSContext *cx, JSObject *array);
/*
* Create a new typed array using the given ArrayBuffer for storage. byteOffset
* must not exceed (signed) INT32_MAX. The length value is optional; if -1 is
* passed, enough elements to use up the remainder of the byte array is used as
* the default value.
*/
extern JS_FRIEND_API(JSObject *)
JS_NewInt8ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewUint8ClampedArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewInt16ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewUint16ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewInt32ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewUint32ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat32ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
extern JS_FRIEND_API(JSObject *)
JS_NewFloat64ArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer,
uint32_t byteOffset, int32_t length);
/*
* Create a new ArrayBuffer with the given byte length.
*/
extern JS_FRIEND_API(JSObject *)
JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
/*
* Check whether obj supports JS_GetTypedArray* APIs. Note that this may return
* false if a security wrapper is encountered that denies the unwrapping. If
* this test or one of the JS_Is*Array tests succeeds, then it is safe to call
* the various accessor JSAPI calls defined below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx);
/*
* Test for specific typed array types (ArrayBufferView subtypes)
*/
extern JS_FRIEND_API(JSBool)
JS_IsInt8Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsUint8Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsUint8ClampedArray(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsInt16Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsUint16Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsInt32Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsUint32Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsFloat32Array(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_IsFloat64Array(JSObject *obj, JSContext *cx);
/*
* Get the type of elements in a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(JSArrayBufferViewType)
JS_GetTypedArrayType(JSObject *obj, JSContext *cx);
/*
* Check whether obj supports the JS_GetArrayBuffer* APIs. Note that this may
* return false if a security wrapper is encountered that denies the
* unwrapping. If this test succeeds, then it is safe to call the various
* accessor JSAPI calls defined below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferObject(JSObject *obj, JSContext *cx);
/*
* Return the available byte length of an array buffer.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferByteLength(JSObject *obj, JSContext *cx);
/*
* Return a pointer to an array buffer's data. The buffer is still owned by the
* array buffer object, and should not be modified on another thread.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint8_t *)
JS_GetArrayBufferData(JSObject *obj, JSContext *cx);
/*
* Return the number of elements in a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayLength(JSObject *obj, JSContext *cx);
/*
* Return the byte offset from the start of an array buffer to the start of a
* typed array view.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx);
/*
* Return the byte length of a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
/*
* More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
*/
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx);
/*
* Return a pointer to the start of the data referenced by a typed array. The
* data is still owned by the typed array, and should not be modified on
* another thread.
*
* |obj| must have passed a JS_Is*Array test, or somehow be known that it would
* pass such a test: it is a typed array or a wrapper of a typed array, and the
* unwrapping will succeed. If cx is NULL, then DEBUG builds may be unable to
* assert when unwrapping should be disallowed.
*/
extern JS_FRIEND_API(int8_t *)
JS_GetInt8ArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(uint8_t *)
JS_GetUint8ArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(uint8_t *)
JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(int16_t *)
JS_GetInt16ArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(uint16_t *)
JS_GetUint16ArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(int32_t *)
JS_GetInt32ArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(uint32_t *)
JS_GetUint32ArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(float *)
JS_GetFloat32ArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(double *)
JS_GetFloat64ArrayData(JSObject *obj, JSContext *cx);
/*
* Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
* versions when possible.
*/
extern JS_FRIEND_API(void *)
JS_GetArrayBufferViewData(JSObject *obj, JSContext *cx);
#endif /* jsfriendapi_h___ */

View File

@ -232,7 +232,7 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp
}
}
if (js_IsTypedArray(obj)) {
if (obj->isTypedArray()) {
JSObject *tarray = TypedArray::getTypedArray(obj);
*vp = Int32Value(TypedArray::getLength(tarray));
return true;

View File

@ -138,13 +138,13 @@ ToClampedIndex(JSContext *cx, const Value &v, int32_t length, int32_t *out)
/**
* Walks up the prototype chain to find the actual ArrayBuffer data.
* This MAY return NULL. Callers should always use js_IsArrayBuffer()
* This MAY return NULL. Callers should always use isArrayBuffer()
* first.
*/
JSObject *
ArrayBuffer::getArrayBuffer(JSObject *obj)
{
while (obj && !js_IsArrayBuffer(obj))
while (obj && !obj->isArrayBuffer())
obj = obj->getProto();
return obj;
}
@ -726,7 +726,7 @@ ArrayBuffer::obj_typeOf(JSContext *cx, JSObject *obj)
JSObject *
TypedArray::getTypedArray(JSObject *obj)
{
while (!js_IsTypedArray(obj))
while (!obj->isTypedArray())
obj = obj->getProto();
return obj;
}
@ -751,7 +751,7 @@ class TypedArrayGetter {
public:
static inline bool get(JSContext *cx, JSObject *obj, jsid id, Value *vp) {
do {
if (js_IsTypedArray(obj)) {
if (obj->isTypedArray()) {
JSObject *tarray = TypedArray::getTypedArray(obj);
if (tarray)
*vp = Get(tarray);
@ -995,10 +995,20 @@ template<> inline const bool ElementTypeMayBeDouble<double>() { return true; }
template<typename NativeType> class TypedArrayTemplate;
template<typename ElementType>
static inline JSObject *
NewArray(JSContext *cx, uint32_t nelements);
template<typename NativeType>
class TypedArrayTemplate
: public TypedArray
{
template<typename ElementType>
friend JSObject *NewTypedArrayFromArray(JSContext *cx, JSObject *other);
template<typename ElementType>
friend JSObject *NewArray(JSContext *cx, uint32_t nelements);
public:
typedef NativeType ThisType;
typedef TypedArrayTemplate<NativeType> ThisTypeArray;
@ -1391,7 +1401,7 @@ class TypedArrayTemplate
obj->setSlot(FIELD_BYTEOFFSET, Int32Value(byteOffset));
obj->setSlot(FIELD_BYTELENGTH, Int32Value(len * sizeof(NativeType)));
DebugOnly<uint32_t> bufferByteLength = getBuffer(obj)->arrayBufferByteLength();
DebugOnly<uint32_t> bufferByteLength = bufobj->arrayBufferByteLength();
JS_ASSERT(bufferByteLength - getByteOffset(obj) >= getByteLength(obj));
JS_ASSERT(getByteOffset(obj) <= bufferByteLength);
JS_ASSERT(getBuffer(obj)->arrayBufferDataOffset() <= getDataOffset(obj));
@ -1454,7 +1464,7 @@ class TypedArrayTemplate
JSObject *dataObj = &argv[0].toObject();
/* (typedArray) */
if (js_IsTypedArray(dataObj)) {
if (dataObj->isTypedArray()) {
JSObject *otherTypedArray = getTypedArray(dataObj);
JS_ASSERT(otherTypedArray);
@ -1576,7 +1586,7 @@ class TypedArrayTemplate
}
JSObject *arg0 = args[0].toObjectOrNull();
if (js_IsTypedArray(arg0)) {
if (arg0->isTypedArray()) {
JSObject *src = TypedArray::getTypedArray(arg0);
if (!src ||
getLength(src) > getLength(tarray) - offset)
@ -1610,56 +1620,45 @@ class TypedArrayTemplate
public:
static JSObject *
createTypedArrayWithOffsetLength(JSContext *cx, JSObject *other,
int32_t byteOffsetInt, int32_t lengthInt)
createTypedArrayWithBuffer(JSContext *cx, JSObject *buffer,
int32_t byteOffsetInt, int32_t lengthInt)
{
JS_ASSERT(!js_IsTypedArray(other));
uint32_t boffset = (byteOffsetInt == -1) ? 0 : uint32_t(byteOffsetInt);
/* Handle creation from an ArrayBuffer not ArrayBuffer.prototype. */
if (other->isArrayBuffer()) {
uint32_t boffset = (byteOffsetInt < 0) ? 0 : uint32_t(byteOffsetInt);
if (boffset > other->arrayBufferByteLength() || boffset % sizeof(NativeType) != 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // invalid byteOffset
}
uint32_t len;
if (lengthInt < 0) {
len = (other->arrayBufferByteLength() - boffset) / sizeof(NativeType);
if (len * sizeof(NativeType) != (other->arrayBufferByteLength() - boffset)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // given byte array doesn't map exactly to sizeof(NativeType)*N
}
} else {
len = (uint32_t) lengthInt;
}
// Go slowly and check for overflow.
uint32_t arrayByteLength = len*sizeof(NativeType);
if (uint32_t(len) >= INT32_MAX / sizeof(NativeType) ||
uint32_t(boffset) >= INT32_MAX - arrayByteLength)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // overflow occurred along the way when calculating boffset+len*sizeof(NativeType)
}
if (arrayByteLength + boffset > other->arrayBufferByteLength()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // boffset+len is too big for the arraybuffer
}
return createTypedArray(cx, other, boffset, len);
if (boffset > buffer->arrayBufferByteLength() || boffset % sizeof(NativeType) != 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // invalid byteOffset
}
/*
* Otherwise create a new typed array and copy len properties from the
* object.
*/
uint32_t len;
if (lengthInt == -1) {
len = (buffer->arrayBufferByteLength() - boffset) / sizeof(NativeType);
if (len * sizeof(NativeType) != buffer->arrayBufferByteLength() - boffset) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // given byte array doesn't map exactly to sizeof(NativeType) * N
}
} else {
len = uint32_t(lengthInt);
}
// Go slowly and check for overflow.
uint32_t arrayByteLength = len * sizeof(NativeType);
if (len >= INT32_MAX / sizeof(NativeType) || boffset >= INT32_MAX - arrayByteLength) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // overflow when calculating boffset + len * sizeof(NativeType)
}
if (arrayByteLength + boffset > buffer->arrayBufferByteLength()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // boffset + len is too big for the arraybuffer
}
return createTypedArray(cx, buffer, boffset, len);
}
static JSObject *
createTypedArrayFromArray(JSContext *cx, JSObject *other)
{
uint32_t len;
if (!js_GetLengthProperty(cx, other, &len))
return NULL;
@ -1674,6 +1673,27 @@ class TypedArrayTemplate
return obj;
}
/*
* Note: the offset and length arguments are ignored if an array is passed in.
*/
static JSObject *
createTypedArrayWithOffsetLength(JSContext *cx, JSObject *other,
int32_t byteOffsetInt, int32_t lengthInt)
{
JS_ASSERT(!other->isTypedArray());
if (other->isArrayBuffer()) {
/* Handle creation from an ArrayBuffer not ArrayBuffer.prototype. */
return createTypedArrayWithBuffer(cx, other, byteOffsetInt, lengthInt);
}
/*
* Otherwise create a new typed array and copy len properties from
* the object.
*/
return createTypedArrayFromArray(cx, other);
}
static const NativeType
getIndex(JSObject *obj, uint32_t index)
{
@ -2203,6 +2223,62 @@ JSFunctionSpec _typedArray::jsfuncs[] = { \
JS_FS_END \
}
template<typename ElementType>
static inline JSObject *
NewArray(JSContext *cx, uint32_t nelements)
{
JSObject *buffer = TypedArrayTemplate<ElementType>::createBufferWithSizeAndCount(cx, nelements);
if (!buffer)
return NULL;
return TypedArrayTemplate<ElementType>::createTypedArray(cx, buffer, 0, nelements);
}
template<typename ElementType>
static inline JSObject *
NewArrayWithBuffer(JSContext *cx, JSObject *arrayBuffer, int32_t byteoffset, int32_t intLength)
{
if (!arrayBuffer->isArrayBuffer()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
return NULL; // must be arrayBuffer
}
return TypedArrayTemplate<ElementType>::createTypedArrayWithBuffer(cx, arrayBuffer,
byteoffset, intLength);
}
#define IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Name,NativeType) \
JS_FRIEND_API(JSObject *) JS_New ## Name ## Array(JSContext *cx, uint32_t nelements) \
{ \
MOZ_ASSERT(nelements <= INT32_MAX); \
return NewArray<NativeType>(cx, nelements); \
} \
JS_FRIEND_API(JSObject *) JS_New ## Name ## ArrayFromArray(JSContext *cx, JSObject *other) \
{ \
return TypedArrayTemplate<NativeType>::createTypedArrayFromArray(cx, other); \
} \
JS_FRIEND_API(JSObject *) JS_New ## Name ## ArrayWithBuffer(JSContext *cx, \
JSObject *arrayBuffer, uint32_t byteoffset, int32_t length) \
{ \
MOZ_ASSERT(byteoffset <= INT32_MAX); \
return NewArrayWithBuffer<NativeType>(cx, arrayBuffer, byteoffset, length); \
} \
JS_FRIEND_API(JSBool) JS_Is ## Name ## Array(JSObject *obj, JSContext *cx) \
{ \
obj = UnwrapObject(obj); \
Class *clasp = obj->getClass(); \
return (clasp == &TypedArray::fastClasses[TypedArrayTemplate<NativeType>::ArrayTypeID()]); \
}
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int8, int8_t)
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint8, uint8_t)
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint8Clamped, uint8_clamped)
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int16, int16_t)
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint16, uint16_t)
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int32, int32_t)
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_SLOW_CLASS(_typedArray) \
{ \
#_typedArray, \
@ -2409,199 +2485,190 @@ js_InitTypedArrayClasses(JSContext *cx, JSObject *obj)
return InitArrayBufferClass(cx, global);
}
JS_FRIEND_API(JSBool)
js_IsArrayBuffer(JSObject *obj)
{
JS_ASSERT(obj);
obj = UnwrapObject(obj);
return obj->isArrayBuffer();
}
JS_FRIEND_API(JSBool)
JS_IsArrayBufferObject(JSObject *obj)
{
return js_IsArrayBuffer(obj);
}
namespace js {
bool
IsFastTypedArrayClass(const Class *clasp)
js::IsFastTypedArrayClass(const Class *clasp)
{
return &TypedArray::fastClasses[0] <= clasp &&
clasp < &TypedArray::fastClasses[TypedArray::TYPE_MAX];
}
bool
static inline bool
IsSlowTypedArrayClass(const Class *clasp)
{
return &TypedArray::slowClasses[0] <= clasp &&
clasp < &TypedArray::slowClasses[TypedArray::TYPE_MAX];
}
bool IsFastOrSlowTypedArray(JSObject *obj)
bool
js::IsFastOrSlowTypedArray(JSObject *obj)
{
Class *clasp = obj->getClass();
return IsFastTypedArrayClass(clasp) || IsSlowTypedArrayClass(clasp);
}
} // namespace js
/* JS Friend API */
uint32_t
JS_GetArrayBufferByteLength(JSObject *obj)
JS_FRIEND_API(JSBool)
JS_IsArrayBufferObject(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
return obj->isArrayBuffer();
}
JS_FRIEND_API(JSBool)
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
return obj->isTypedArray();
}
JS_FRIEND_API(uint32_t)
JS_GetArrayBufferByteLength(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isArrayBuffer());
return obj->arrayBufferByteLength();
}
uint8_t *
JS_GetArrayBufferData(JSObject *obj)
JS_FRIEND_API(uint8_t *)
JS_GetArrayBufferData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isArrayBuffer());
return obj->arrayBufferDataOffset();
}
JS_FRIEND_API(JSBool)
js_IsTypedArray(JSObject *obj)
{
JS_ASSERT(obj);
obj = UnwrapObject(obj);
Class *clasp = obj->getClass();
return IsFastTypedArrayClass(clasp);
}
JS_FRIEND_API(JSObject *)
js_CreateArrayBuffer(JSContext *cx, uint32_t nbytes)
JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes)
{
return ArrayBuffer::create(cx, nbytes);
}
JS_FRIEND_API(JSObject *)
JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes)
{
return js_CreateArrayBuffer(cx, nbytes);
}
static inline JSObject *
TypedArrayConstruct(JSContext *cx, int atype, unsigned argc, Value *argv)
{
switch (atype) {
case TypedArray::TYPE_INT8:
return Int8Array::create(cx, argc, argv);
case TypedArray::TYPE_UINT8:
return Uint8Array::create(cx, argc, argv);
case TypedArray::TYPE_INT16:
return Int16Array::create(cx, argc, argv);
case TypedArray::TYPE_UINT16:
return Uint16Array::create(cx, argc, argv);
case TypedArray::TYPE_INT32:
return Int32Array::create(cx, argc, argv);
case TypedArray::TYPE_UINT32:
return Uint32Array::create(cx, argc, argv);
case TypedArray::TYPE_FLOAT32:
return Float32Array::create(cx, argc, argv);
case TypedArray::TYPE_FLOAT64:
return Float64Array::create(cx, argc, argv);
case TypedArray::TYPE_UINT8_CLAMPED:
return Uint8ClampedArray::create(cx, argc, argv);
default:
JS_NOT_REACHED("shouldn't have gotten here");
return NULL;
}
}
JS_FRIEND_API(JSObject *)
js_CreateTypedArray(JSContext *cx, int atype, uint32_t nelements)
{
JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
Value nelems = Int32Value(nelements);
return TypedArrayConstruct(cx, atype, 1, &nelems);
}
JS_FRIEND_API(JSObject *)
js_CreateTypedArrayWithArray(JSContext *cx, int atype, JSObject *arrayArg)
{
JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
Value arrval = ObjectValue(*arrayArg);
return TypedArrayConstruct(cx, atype, 1, &arrval);
}
JS_FRIEND_API(JSObject *)
js_CreateTypedArrayWithBuffer(JSContext *cx, int atype, JSObject *bufArg,
int byteoffset, int length)
{
JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
JS_ASSERT(bufArg && js_IsArrayBuffer(bufArg));
JS_ASSERT_IF(byteoffset < 0, length < 0);
Value vals[4];
int argc = 1;
vals[0].setObject(*bufArg);
if (byteoffset >= 0) {
vals[argc].setInt32(byteoffset);
argc++;
}
if (length >= 0) {
vals[argc].setInt32(length);
argc++;
}
AutoArrayRooter tvr(cx, ArrayLength(vals), vals);
return TypedArrayConstruct(cx, atype, argc, &vals[0]);
}
uint32_t
JS_GetTypedArrayLength(JSObject *obj)
JS_FRIEND_API(uint32_t)
JS_GetTypedArrayLength(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
return obj->getSlot(TypedArray::FIELD_LENGTH).toInt32();
}
uint32_t
JS_GetTypedArrayByteOffset(JSObject *obj)
JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
return obj->getSlot(TypedArray::FIELD_BYTEOFFSET).toInt32();
}
uint32_t
JS_GetTypedArrayByteLength(JSObject *obj)
JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
return obj->getSlot(TypedArray::FIELD_BYTELENGTH).toInt32();
}
uint32_t
JS_GetTypedArrayType(JSObject *obj)
JS_FRIEND_API(JSArrayBufferViewType)
JS_GetTypedArrayType(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
return obj->getSlot(TypedArray::FIELD_TYPE).toInt32();
return static_cast<JSArrayBufferViewType>(obj->getSlot(TypedArray::FIELD_TYPE).toInt32());
}
void *
JS_GetTypedArrayData(JSObject *obj)
JS_FRIEND_API(int8_t *)
JS_GetInt8ArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_INT8);
return static_cast<int8_t *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(uint8_t *)
JS_GetUint8ArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_UINT8);
return static_cast<uint8_t *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(uint8_t *)
JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_UINT8_CLAMPED);
return static_cast<uint8_t *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(int16_t *)
JS_GetInt16ArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_INT16);
return static_cast<int16_t *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(uint16_t *)
JS_GetUint16ArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_UINT16);
return static_cast<uint16_t *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(int32_t *)
JS_GetInt32ArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_INT32);
return static_cast<int32_t *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(uint32_t *)
JS_GetUint32ArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_UINT32);
return static_cast<uint32_t *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(float *)
JS_GetFloat32ArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_FLOAT32);
return static_cast<float *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(double *)
JS_GetFloat64ArrayData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_FLOAT64);
return static_cast<double *>(TypedArray::getDataOffset(obj));
}
JS_FRIEND_API(void *)
JS_GetArrayBufferViewData(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
return TypedArray::getDataOffset(obj);
}
JS_FRIEND_API(uint32_t)
JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx)
{
obj = UnwrapObject(obj);
JS_ASSERT(obj->isTypedArray());
return obj->getSlot(TypedArray::FIELD_BYTELENGTH).toInt32();
}

View File

@ -57,7 +57,7 @@ namespace js {
* TypedArray subclass, or can be created implicitly by constructing a
* TypedArray with a size.
*/
struct JS_FRIEND_API(ArrayBuffer) {
struct ArrayBuffer {
static Class slowClass;
static JSPropertySpec jsprops[];
static JSFunctionSpec jsfuncs[];
@ -177,7 +177,7 @@ struct JS_FRIEND_API(ArrayBuffer) {
* the subclasses.
*/
struct JS_FRIEND_API(TypedArray) {
struct TypedArray {
enum {
TYPE_INT8 = 0,
TYPE_UINT8,
@ -283,79 +283,15 @@ struct JS_FRIEND_API(TypedArray) {
static int dataOffset();
};
extern bool
IsFastTypedArrayClass(const Class *clasp);
extern bool
IsSlowTypedArrayClass(const Class *clasp);
extern bool
bool
IsFastOrSlowTypedArray(JSObject *obj);
bool
IsFastOrSlowTypedArrayClass(const Class *clasp);
bool
IsFastTypedArrayClass(const Class *clasp);
} // namespace js
/* Friend API methods */
JS_FRIEND_API(JSBool)
js_IsTypedArray(JSObject *obj);
JS_FRIEND_API(JSBool)
js_IsArrayBuffer(JSObject *obj);
JS_FRIEND_API(JSObject *)
js_CreateArrayBuffer(JSContext *cx, uint32_t nbytes);
/*
* Create a new typed array of type atype (one of the TypedArray
* enumerant values above), with nelements elements.
*/
JS_FRIEND_API(JSObject *)
js_CreateTypedArray(JSContext *cx, int atype, uint32_t nelements);
/*
* Create a new typed array of type atype (one of the TypedArray
* enumerant values above), and copy in values from the given JSObject,
* which must either be a typed array or an array-like object.
*/
JS_FRIEND_API(JSObject *)
js_CreateTypedArrayWithArray(JSContext *cx, int atype, JSObject *arrayArg);
/*
* Create a new typed array of type atype (one of the TypedArray
* enumerant values above), using a given ArrayBuffer for storage.
* The byteoffset and length values are optional; if -1 is passed, an
* offset of 0 and enough elements to use up the remainder of the byte
* array are used as the default values.
*/
JS_FRIEND_API(JSObject *)
js_CreateTypedArrayWithBuffer(JSContext *cx, int atype, JSObject *bufArg,
int byteoffset, int length);
JS_FRIEND_API(JSBool)
JS_IsArrayBufferObject(JSObject *obj);
JS_FRIEND_API(JSObject *)
JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
JS_FRIEND_API(uint32_t)
JS_GetArrayBufferByteLength(JSObject *obj);
JS_FRIEND_API(uint8_t *)
JS_GetArrayBufferData(JSObject *obj);
JS_FRIEND_API(uint32_t)
JS_GetTypedArrayLength(JSObject *obj);
JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteOffset(JSObject *obj);
JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteLength(JSObject *obj);
JS_FRIEND_API(uint32_t)
JS_GetTypedArrayType(JSObject *obj);
JS_FRIEND_API(void *)
JS_GetTypedArrayData(JSObject *obj);
#endif /* jstypedarray_h */

View File

@ -2398,7 +2398,7 @@ GetElementIC::update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *
* Since we can use type information to generate inline paths for typed
* arrays, just don't generate these ICs with inference enabled.
*/
if (!f.cx->typeInferenceEnabled() && js_IsTypedArray(obj))
if (!f.cx->typeInferenceEnabled() && obj->isTypedArray())
return attachTypedArray(f, obj, v, id, vp);
#endif
@ -2720,7 +2720,7 @@ SetElementIC::update(VMFrame &f, const Value &objval, const Value &idval)
#if defined JS_METHODJIT_TYPED_ARRAY
/* Not attaching typed array stubs with linear scan allocator, see GetElementIC. */
if (!f.cx->typeInferenceEnabled() && js_IsTypedArray(obj))
if (!f.cx->typeInferenceEnabled() && obj->isTypedArray())
return attachTypedArray(f, obj, key);
#endif

View File

@ -921,10 +921,10 @@ FileAsTypedArray(JSContext *cx, const char *pathname)
if (fseek(file, 0, SEEK_SET) != 0) {
JS_ReportError(cx, "can't seek start of %s", pathname);
} else {
obj = js_CreateTypedArray(cx, TypedArray::TYPE_UINT8, len);
obj = JS_NewUint8Array(cx, len);
if (!obj)
return NULL;
char *buf = (char *) TypedArray::getDataOffset(TypedArray::getTypedArray(obj));
char *buf = (char *) TypedArray::getDataOffset(obj);
size_t cc = fread(buf, 1, len, file);
if (cc != len) {
JS_ReportError(cx, "can't read %s: %s", pathname,
@ -3395,16 +3395,15 @@ Serialize(JSContext *cx, unsigned argc, jsval *vp)
if (!JS_WriteStructuredClone(cx, v, &datap, &nbytes, NULL, NULL))
return false;
JSObject *arrayobj = js_CreateTypedArray(cx, TypedArray::TYPE_UINT8, nbytes);
if (!arrayobj) {
JSObject *array = JS_NewUint8Array(cx, nbytes);
if (!array) {
JS_free(cx, datap);
return false;
}
JSObject *array = TypedArray::getTypedArray(arrayobj);
JS_ASSERT((uintptr_t(TypedArray::getDataOffset(array)) & 7) == 0);
js_memcpy(TypedArray::getDataOffset(array), datap, nbytes);
JS_free(cx, datap);
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(arrayobj));
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(array));
return true;
}
@ -3413,7 +3412,7 @@ Deserialize(JSContext *cx, unsigned argc, jsval *vp)
{
jsval v = argc > 0 ? JS_ARGV(cx, vp)[0] : JSVAL_VOID;
JSObject *obj;
if (JSVAL_IS_PRIMITIVE(v) || !js_IsTypedArray((obj = JSVAL_TO_OBJECT(v)))) {
if (JSVAL_IS_PRIMITIVE(v) || !(obj = JSVAL_TO_OBJECT(v))->isTypedArray()) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
return false;
}

View File

@ -59,7 +59,6 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "jstypedarray.h"
#include "mozilla/dom/bindings/Utils.h"
@ -1606,7 +1605,8 @@ failure:
// of the output does not exceed PR_UINT32_MAX bytes. Allocate
// the memory and copy the elements by memcpy.
static JSBool
CheckTargetAndPopulate(const nsXPTType& type,
CheckTargetAndPopulate(JSContext *cx,
const nsXPTType& type,
PRUint8 requiredType,
size_t typeSize,
uint32_t count,
@ -1637,7 +1637,7 @@ CheckTargetAndPopulate(const nsXPTType& type,
return false;
}
memcpy(*output, JS_GetTypedArrayData(tArr), byteSize);
memcpy(*output, JS_GetArrayBufferViewData(tArr, cx), byteSize);
return true;
}
@ -1660,11 +1660,12 @@ XPCConvert::JSTypedArray2Native(XPCCallContext& ccx,
{
NS_ABORT_IF_FALSE(jsArray, "bad param");
NS_ABORT_IF_FALSE(d, "bad param");
NS_ABORT_IF_FALSE(js_IsTypedArray(jsArray), "not a typed array");
JSContext* cx = ccx.GetJSContext();
NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(jsArray, cx), "not a typed array");
// Check the actual length of the input array against the
// given size_is.
uint32_t len = JS_GetTypedArrayLength(jsArray);
uint32_t len = JS_GetTypedArrayLength(jsArray, cx);
if (len < count) {
if (pErr)
*pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
@ -1674,66 +1675,66 @@ XPCConvert::JSTypedArray2Native(XPCCallContext& ccx,
void* output = nsnull;
switch (JS_GetTypedArrayType(jsArray)) {
case js::TypedArray::TYPE_INT8:
if (!CheckTargetAndPopulate(nsXPTType::T_I8, type,
switch (JS_GetTypedArrayType(jsArray, cx)) {
case js::ArrayBufferView::TYPE_INT8:
if (!CheckTargetAndPopulate(cx, nsXPTType::T_I8, type,
sizeof(int8_t), count,
jsArray, &output, pErr)) {
return false;
}
break;
case js::TypedArray::TYPE_UINT8:
case js::TypedArray::TYPE_UINT8_CLAMPED:
if (!CheckTargetAndPopulate(nsXPTType::T_U8, type,
case js::ArrayBufferView::TYPE_UINT8:
case js::ArrayBufferView::TYPE_UINT8_CLAMPED:
if (!CheckTargetAndPopulate(cx, nsXPTType::T_U8, type,
sizeof(uint8_t), count,
jsArray, &output, pErr)) {
return false;
}
break;
case js::TypedArray::TYPE_INT16:
if (!CheckTargetAndPopulate(nsXPTType::T_I16, type,
case js::ArrayBufferView::TYPE_INT16:
if (!CheckTargetAndPopulate(cx, nsXPTType::T_I16, type,
sizeof(int16_t), count,
jsArray, &output, pErr)) {
return false;
}
break;
case js::TypedArray::TYPE_UINT16:
if (!CheckTargetAndPopulate(nsXPTType::T_U16, type,
case js::ArrayBufferView::TYPE_UINT16:
if (!CheckTargetAndPopulate(cx, nsXPTType::T_U16, type,
sizeof(uint16_t), count,
jsArray, &output, pErr)) {
return false;
}
break;
case js::TypedArray::TYPE_INT32:
if (!CheckTargetAndPopulate(nsXPTType::T_I32, type,
case js::ArrayBufferView::TYPE_INT32:
if (!CheckTargetAndPopulate(cx, nsXPTType::T_I32, type,
sizeof(int32_t), count,
jsArray, &output, pErr)) {
return false;
}
break;
case js::TypedArray::TYPE_UINT32:
if (!CheckTargetAndPopulate(nsXPTType::T_U32, type,
case js::ArrayBufferView::TYPE_UINT32:
if (!CheckTargetAndPopulate(cx, nsXPTType::T_U32, type,
sizeof(uint32_t), count,
jsArray, &output, pErr)) {
return false;
}
break;
case js::TypedArray::TYPE_FLOAT32:
if (!CheckTargetAndPopulate(nsXPTType::T_FLOAT, type,
case js::ArrayBufferView::TYPE_FLOAT32:
if (!CheckTargetAndPopulate(cx, nsXPTType::T_FLOAT, type,
sizeof(float), count,
jsArray, &output, pErr)) {
return false;
}
break;
case js::TypedArray::TYPE_FLOAT64:
if (!CheckTargetAndPopulate(nsXPTType::T_DOUBLE, type,
case js::ArrayBufferView::TYPE_FLOAT64:
if (!CheckTargetAndPopulate(cx, nsXPTType::T_DOUBLE, type,
sizeof(double), count,
jsArray, &output, pErr)) {
return false;
@ -1798,8 +1799,8 @@ XPCConvert::JSArray2Native(XPCCallContext& ccx, void** d, jsval s,
jsarray = JSVAL_TO_OBJECT(s);
// If this is a typed array, then do a fast conversion with memcpy.
if (js_IsTypedArray(jsarray)) {
// If this is a typed array, then try a fast conversion with memcpy.
if (JS_IsTypedArrayObject(jsarray, cx)) {
return JSTypedArray2Native(ccx, d, jsarray, count, type, pErr);
}