mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Backed out de9fff3a523, c567df2244f5, 8e3d976d5dc5, and c7499faaec23 (bug 800915) for bustage.
--HG-- extra : rebase_source : c823063bfa31d59d32b3402bd4b458b84b703cd5
This commit is contained in:
parent
be230eda17
commit
5f0fd7aeda
@ -6187,8 +6187,8 @@ nsContentUtils::CreateArrayBuffer(JSContext *aCx, const nsACString& aData,
|
||||
}
|
||||
|
||||
if (dataLen > 0) {
|
||||
NS_ASSERTION(JS_IsArrayBufferObject(*aResult), "What happened?");
|
||||
memcpy(JS_GetArrayBufferData(*aResult), aData.BeginReading(), dataLen);
|
||||
NS_ASSERTION(JS_IsArrayBufferObject(*aResult, aCx), "What happened?");
|
||||
memcpy(JS_GetArrayBufferData(*aResult, aCx), aData.BeginReading(), dataLen);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -234,12 +234,12 @@ nsDOMMultipartFile::InitInternal(JSContext* aCx,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (JS_IsArrayBufferViewObject(&obj)) {
|
||||
blobSet.AppendVoidPtr(JS_GetArrayBufferViewData(&obj),
|
||||
JS_GetArrayBufferViewByteLength(&obj));
|
||||
if (JS_IsArrayBufferViewObject(&obj, aCx)) {
|
||||
blobSet.AppendVoidPtr(JS_GetArrayBufferViewData(&obj, aCx),
|
||||
JS_GetArrayBufferViewByteLength(&obj, aCx));
|
||||
continue;
|
||||
}
|
||||
if (JS_IsArrayBufferObject(&obj)) {
|
||||
if (JS_IsArrayBufferObject(&obj, aCx)) {
|
||||
blobSet.AppendArrayBuffer(&obj, aCx);
|
||||
continue;
|
||||
}
|
||||
@ -321,6 +321,6 @@ BlobSet::AppendBlobs(const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlob)
|
||||
nsresult
|
||||
BlobSet::AppendArrayBuffer(JSObject* aBuffer, JSContext *aCx)
|
||||
{
|
||||
return AppendVoidPtr(JS_GetArrayBufferData(aBuffer),
|
||||
JS_GetArrayBufferByteLength(aBuffer));
|
||||
return AppendVoidPtr(JS_GetArrayBufferData(aBuffer, aCx),
|
||||
JS_GetArrayBufferByteLength(aBuffer, aCx));
|
||||
}
|
||||
|
@ -317,9 +317,9 @@ nsDOMDataChannel::GetSendParams(nsIVariant* aData, nsCString& aStringOut,
|
||||
nsresult rv = aData->GetAsJSVal(&realVal);
|
||||
if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal) &&
|
||||
(obj = JSVAL_TO_OBJECT(realVal)) &&
|
||||
(JS_IsArrayBufferObject(obj))) {
|
||||
int32_t len = JS_GetArrayBufferByteLength(obj);
|
||||
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(obj));
|
||||
(JS_IsArrayBufferObject(obj, aCx))) {
|
||||
int32_t len = JS_GetArrayBufferByteLength(obj, aCx);
|
||||
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(obj, aCx));
|
||||
|
||||
aStringOut.Assign(data, len);
|
||||
aIsBinary = true;
|
||||
|
@ -309,7 +309,7 @@ nsDOMFileReader::DoOnDataAvailable(nsIRequest *aRequest,
|
||||
}
|
||||
else if (mDataFormat == FILE_AS_ARRAYBUFFER) {
|
||||
uint32_t bytesRead = 0;
|
||||
aInputStream->Read((char*)JS_GetArrayBufferData(mResultArrayBuffer) + aOffset,
|
||||
aInputStream->Read((char*)JS_GetArrayBufferData(mResultArrayBuffer, NULL) + aOffset,
|
||||
aCount, &bytesRead);
|
||||
NS_ASSERTION(bytesRead == aCount, "failed to read data");
|
||||
}
|
||||
|
@ -2669,8 +2669,8 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult, uint64_t* aContentLe
|
||||
if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal)) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(realVal);
|
||||
ac.construct(cx, obj);
|
||||
if (JS_IsArrayBufferObject(obj)) {
|
||||
ArrayBuffer buf(obj);
|
||||
if (JS_IsArrayBufferObject(obj, cx)) {
|
||||
ArrayBuffer buf(cx, obj);
|
||||
return GetRequestBody(&buf, aResult, aContentLength, aContentType, aCharset);
|
||||
}
|
||||
}
|
||||
|
@ -4321,7 +4321,7 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint8_t* data = JS_GetUint8ClampedArrayData(darray);
|
||||
uint8_t* data = JS_GetUint8ClampedArrayData(darray, aCx);
|
||||
|
||||
IntRect srcRect(0, 0, mWidth, mHeight);
|
||||
IntRect destRect(aX, aY, aWidth, aHeight);
|
||||
@ -4433,7 +4433,7 @@ CanvasRenderingContext2D::PutImageData(JSContext* cx,
|
||||
return;
|
||||
}
|
||||
|
||||
dom::Uint8ClampedArray arr(imageData.GetDataObject());
|
||||
dom::Uint8ClampedArray arr(cx, imageData.GetDataObject());
|
||||
|
||||
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
|
||||
imageData.Width(), imageData.Height(),
|
||||
@ -4453,7 +4453,7 @@ CanvasRenderingContext2D::PutImageData(JSContext* cx,
|
||||
return;
|
||||
}
|
||||
|
||||
dom::Uint8ClampedArray arr(imageData.GetDataObject());
|
||||
dom::Uint8ClampedArray arr(cx, imageData.GetDataObject());
|
||||
|
||||
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
|
||||
imageData.Width(), imageData.Height(),
|
||||
|
@ -3157,8 +3157,8 @@ WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width,
|
||||
WebGLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
|
||||
|
||||
void* data = pixels->Data();
|
||||
uint32_t dataByteLen = JS_GetTypedArrayByteLength(pixels->Obj());
|
||||
int dataType = JS_GetTypedArrayType(pixels->Obj());
|
||||
uint32_t dataByteLen = JS_GetTypedArrayByteLength(pixels->Obj(), NULL);
|
||||
int dataType = JS_GetTypedArrayType(pixels->Obj(), NULL);
|
||||
|
||||
uint32_t channels = 0;
|
||||
|
||||
@ -4873,7 +4873,7 @@ WebGLContext::TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
|
||||
return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
|
||||
pixels ? pixels->Data() : 0,
|
||||
pixels ? pixels->Length() : 0,
|
||||
pixels ? (int)JS_GetTypedArrayType(pixels->Obj()) : -1,
|
||||
pixels ? (int)JS_GetTypedArrayType(pixels->Obj(), cx) : -1,
|
||||
WebGLTexelConversions::Auto, false);
|
||||
}
|
||||
|
||||
@ -4890,7 +4890,7 @@ WebGLContext::TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
|
||||
return ErrorInvalidValue("texImage2D: null ImageData");
|
||||
}
|
||||
|
||||
Uint8ClampedArray arr(pixels->GetDataObject());
|
||||
Uint8ClampedArray arr(cx, pixels->GetDataObject());
|
||||
return TexImage2D_base(target, level, internalformat, pixels->Width(),
|
||||
pixels->Height(), 4*pixels->Width(), 0,
|
||||
format, type, arr.Data(), arr.Length(), -1,
|
||||
@ -5027,7 +5027,7 @@ WebGLContext::TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
|
||||
return TexSubImage2D_base(target, level, xoffset, yoffset,
|
||||
width, height, 0, format, type,
|
||||
pixels->Data(), pixels->Length(),
|
||||
JS_GetTypedArrayType(pixels->Obj()),
|
||||
JS_GetTypedArrayType(pixels->Obj(), cx),
|
||||
WebGLTexelConversions::Auto, false);
|
||||
}
|
||||
|
||||
@ -5043,7 +5043,7 @@ WebGLContext::TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
|
||||
if (!pixels)
|
||||
return ErrorInvalidValue("texSubImage2D: pixels must not be null!");
|
||||
|
||||
Uint8ClampedArray arr(pixels->GetDataObject());
|
||||
Uint8ClampedArray arr(cx, pixels->GetDataObject());
|
||||
return TexSubImage2D_base(target, level, xoffset, yoffset,
|
||||
pixels->Width(), pixels->Height(),
|
||||
4*pixels->Width(), format, type,
|
||||
|
@ -86,7 +86,7 @@ nsDOMNotifyAudioAvailableEvent::GetFrameBuffer(JSContext* aCx, jsval* aResult)
|
||||
NS_DROP_JS_OBJECTS(this, nsDOMNotifyAudioAvailableEvent);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
memcpy(JS_GetFloat32ArrayData(mCachedArray), mFrameBuffer.get(), mFrameBufferLength * sizeof(float));
|
||||
memcpy(JS_GetFloat32ArrayData(mCachedArray, aCx), mFrameBuffer.get(), mFrameBufferLength * sizeof(float));
|
||||
|
||||
*aResult = OBJECT_TO_JSVAL(mCachedArray);
|
||||
return NS_OK;
|
||||
|
@ -156,7 +156,7 @@ nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, uint32
|
||||
JSObject* tsrc = NULL;
|
||||
|
||||
// Allow either Float32Array or plain JS Array
|
||||
if (JS_IsFloat32Array(darray)) {
|
||||
if (JS_IsFloat32Array(darray, aCx)) {
|
||||
tsrc = darray;
|
||||
} else if (JS_IsArrayObject(aCx, darray)) {
|
||||
JSObject* nobj = JS_NewFloat32ArrayFromArray(aCx, darray);
|
||||
@ -169,7 +169,7 @@ nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, uint32
|
||||
}
|
||||
tvr.setObject(tsrc);
|
||||
|
||||
uint32_t dataLength = JS_GetTypedArrayLength(tsrc);
|
||||
uint32_t dataLength = JS_GetTypedArrayLength(tsrc, aCx);
|
||||
|
||||
// Make sure that we are going to write the correct amount of data based
|
||||
// on number of channels.
|
||||
@ -180,7 +180,7 @@ nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, uint32
|
||||
// Don't write more than can be written without blocking.
|
||||
uint32_t writeLen = NS_MIN(mAudioStream->Available(), dataLength / mChannels);
|
||||
|
||||
float* frames = JS_GetFloat32ArrayData(tsrc);
|
||||
float* frames = JS_GetFloat32ArrayData(tsrc, aCx);
|
||||
// Convert the samples back to integers as we are using fixed point audio in
|
||||
// the nsAudioStream.
|
||||
// This could be optimized to avoid allocation and memcpy when
|
||||
|
@ -519,7 +519,7 @@ nsPIDOMWindow::~nsPIDOMWindow() {}
|
||||
class nsOuterWindowProxy : public js::Wrapper
|
||||
{
|
||||
public:
|
||||
nsOuterWindowProxy() : js::Wrapper(0) { setSafeToUnwrap(false); }
|
||||
nsOuterWindowProxy() : js::Wrapper(0) {}
|
||||
|
||||
virtual bool isOuterWindow() {
|
||||
return true;
|
||||
|
@ -522,11 +522,9 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
// Get the object. It might be a security wrapper, in which case we do a checked
|
||||
// unwrap.
|
||||
JSObject* origObj = JSVAL_TO_OBJECT(thisv);
|
||||
JSObject* obj = js::UnwrapObjectChecked(origObj);
|
||||
if (!obj) {
|
||||
JS_ReportError(cx, "Permission denied to access object");
|
||||
JSObject* obj = js::UnwrapObjectChecked(cx, origObj);
|
||||
if (!obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
nsISupports* native;
|
||||
if (!UnwrapDOMObjectToISupports(obj, native)) {
|
||||
|
@ -245,7 +245,7 @@ IsArrayLike(JSContext* cx, JSObject* obj)
|
||||
|
||||
// XXXbz need to detect platform objects (including listbinding
|
||||
// ones) with indexGetters here!
|
||||
return JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj);
|
||||
return JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj, cx);
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -272,7 +272,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);
|
||||
}
|
||||
|
||||
// U must be something that a T* can be assigned to (e.g. T* or an nsRefPtr<T>).
|
||||
@ -1314,11 +1314,6 @@ public:
|
||||
mImpl.construct();
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
void Construct(const T1 &t1) {
|
||||
mImpl.construct(t1);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
void Construct(const T1 &t1, const T2 &t2) {
|
||||
mImpl.construct(t1, t2);
|
||||
|
@ -2590,7 +2590,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||
else:
|
||||
declType = "NonNull<" + name + ">"
|
||||
template = (
|
||||
"%s.%s(&${val}.toObject());\n"
|
||||
"%s.%s(cx, &${val}.toObject());\n"
|
||||
"if (!%s.%s().inited()) {\n"
|
||||
"%s" # No newline here because onFailureBadType() handles that
|
||||
"}\n" %
|
||||
|
@ -19,11 +19,11 @@ namespace dom {
|
||||
* or array buffer object.
|
||||
*/
|
||||
template<typename T,
|
||||
JSObject* UnboxArray(JSObject*, uint32_t*, T**)>
|
||||
JSObject* UnboxArray(JSContext*, JSObject*, uint32_t*, T**)>
|
||||
struct TypedArray_base {
|
||||
TypedArray_base(JSObject* obj)
|
||||
TypedArray_base(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
mObj = UnboxArray(obj, &mLength, &mData);
|
||||
mObj = UnboxArray(cx, obj, &mLength, &mData);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -54,12 +54,12 @@ public:
|
||||
|
||||
|
||||
template<typename T,
|
||||
T* GetData(JSObject*),
|
||||
JSObject* UnboxArray(JSObject*, uint32_t*, T**),
|
||||
T* GetData(JSObject*, JSContext*),
|
||||
JSObject* UnboxArray(JSContext*, JSObject*, uint32_t*, T**),
|
||||
JSObject* CreateNew(JSContext*, uint32_t)>
|
||||
struct TypedArray : public TypedArray_base<T,UnboxArray> {
|
||||
TypedArray(JSObject* obj) :
|
||||
TypedArray_base<T,UnboxArray>(obj)
|
||||
TypedArray(JSContext* cx, JSObject* obj) :
|
||||
TypedArray_base<T,UnboxArray>(cx, obj)
|
||||
{}
|
||||
|
||||
static inline JSObject*
|
||||
@ -75,7 +75,7 @@ struct TypedArray : public TypedArray_base<T,UnboxArray> {
|
||||
return NULL;
|
||||
}
|
||||
if (data) {
|
||||
T* buf = static_cast<T*>(GetData(obj));
|
||||
T* buf = static_cast<T*>(GetData(obj, cx));
|
||||
memcpy(buf, data, length*sizeof(T));
|
||||
}
|
||||
return obj;
|
||||
|
@ -218,9 +218,9 @@ GetInputStreamForJSVal(const jsval& aValue, JSContext* aCx,
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(aValue)) {
|
||||
JSObject* obj = JSVAL_TO_OBJECT(aValue);
|
||||
if (JS_IsArrayBufferObject(obj)) {
|
||||
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(obj));
|
||||
uint32_t length = JS_GetArrayBufferByteLength(obj);
|
||||
if (JS_IsArrayBufferObject(obj, aCx)) {
|
||||
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(obj, aCx));
|
||||
uint32_t length = JS_GetArrayBufferByteLength(obj, aCx);
|
||||
|
||||
rv = NS_NewByteInputStream(aInputStream, data, length,
|
||||
NS_ASSIGNMENT_COPY);
|
||||
|
@ -28,7 +28,7 @@ DeserializeUint8Array(JSRawObject aObj,
|
||||
JSObject* obj = JS_NewArrayBuffer(cx, aBuffer.Length());
|
||||
if (!obj)
|
||||
return false;
|
||||
uint8_t* data = JS_GetArrayBufferData(obj);
|
||||
uint8_t* data = JS_GetArrayBufferData(obj, cx);
|
||||
if (!data)
|
||||
return false;
|
||||
memcpy(data, aBuffer.Elements(), aBuffer.Length());
|
||||
@ -187,10 +187,10 @@ TCPSocketChild::Send(const JS::Value& aData, JSContext* aCx)
|
||||
} else {
|
||||
NS_ENSURE_TRUE(aData.isObject(), NS_ERROR_FAILURE);
|
||||
JSObject* obj = &aData.toObject();
|
||||
NS_ENSURE_TRUE(JS_IsTypedArrayObject(obj), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(JS_IsUint8Array(obj), NS_ERROR_FAILURE);
|
||||
uint32_t nbytes = JS_GetTypedArrayByteLength(obj);
|
||||
uint8_t* data = JS_GetUint8ArrayData(obj);
|
||||
NS_ENSURE_TRUE(JS_IsTypedArrayObject(obj, aCx), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(JS_IsUint8Array(obj, aCx), NS_ERROR_FAILURE);
|
||||
uint32_t nbytes = JS_GetTypedArrayByteLength(obj, aCx);
|
||||
uint8_t* data = JS_GetUint8ArrayData(obj, aCx);
|
||||
if (!data) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -156,10 +156,10 @@ TCPSocketParent::SendCallback(const nsAString& aType, const JS::Value& aDataVal,
|
||||
|
||||
} else if (aDataVal.isObject()) {
|
||||
JSObject* obj = &aDataVal.toObject();
|
||||
if (JS_IsTypedArrayObject(obj)) {
|
||||
NS_ENSURE_TRUE(JS_IsUint8Array(obj), NS_ERROR_FAILURE);
|
||||
uint32_t nbytes = JS_GetTypedArrayByteLength(obj);
|
||||
uint8_t* buffer = JS_GetUint8ArrayData(obj);
|
||||
if (JS_IsTypedArrayObject(obj, aCx)) {
|
||||
NS_ENSURE_TRUE(JS_IsUint8Array(obj, aCx), NS_ERROR_FAILURE);
|
||||
uint32_t nbytes = JS_GetTypedArrayByteLength(obj, aCx);
|
||||
uint8_t* buffer = JS_GetUint8ArrayData(obj, aCx);
|
||||
if (!buffer) {
|
||||
FireInteralError(this, __LINE__);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -460,12 +460,20 @@ JSValToNPVariant(NPP npp, JSContext *cx, jsval val, NPVariant *variant)
|
||||
// element has since been adopted into a new document. We don't bother
|
||||
// transplanting the plugin objects, and just do a unwrap with security
|
||||
// checks if we encounter one of them as an argument. If the unwrap fails,
|
||||
// we run with the original wrapped object, since sometimes there are
|
||||
// legitimate cases where a security wrapper ends up here (for example,
|
||||
// Location objects, which are _always_ behind security wrappers).
|
||||
// we clear the pending exception and just run with the original wrapped object,
|
||||
// since sometimes there are legitimate cases where a security wrapper ends
|
||||
// up here (for example, Location objects, which are _always_ behind security
|
||||
// wrappers).
|
||||
//
|
||||
// NB: In addition to clearing the pending exception, we also have to temporarily
|
||||
// disable the error reporter, because SpiderMonkey calls it directly if there's
|
||||
// no JS code on the stack, which might be the case here.
|
||||
JSObject *obj = JSVAL_TO_OBJECT(val);
|
||||
obj = js::UnwrapObjectChecked(obj);
|
||||
JSErrorReporter reporter = JS_SetErrorReporter(cx, NULL);
|
||||
obj = js::UnwrapObjectChecked(cx, obj);
|
||||
JS_SetErrorReporter(cx, reporter);
|
||||
if (!obj) {
|
||||
JS_ClearPendingException(cx);
|
||||
obj = JSVAL_TO_OBJECT(val);
|
||||
}
|
||||
|
||||
@ -1126,7 +1134,7 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JSObject *obj)
|
||||
static JSObject *
|
||||
GetNPObjectWrapper(JSContext *cx, JSObject *obj, bool wrapResult = true)
|
||||
{
|
||||
while (obj && (obj = js::UnwrapObjectChecked(obj))) {
|
||||
while (obj && (obj = js::UnwrapObjectChecked(cx, obj))) {
|
||||
if (JS_GetClass(obj) == &sNPObjectJSWrapperClass) {
|
||||
if (wrapResult && !JS_WrapObject(cx, &obj)) {
|
||||
return NULL;
|
||||
|
@ -89,12 +89,12 @@ PostToRIL(JSContext *cx, unsigned argc, jsval *vp)
|
||||
data = abs.ptr();
|
||||
} else if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(v);
|
||||
if (!JS_IsTypedArrayObject(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);
|
||||
uint32_t type = JS_GetTypedArrayType(obj, cx);
|
||||
if (type != js::ArrayBufferView::TYPE_INT8 &&
|
||||
type != js::ArrayBufferView::TYPE_UINT8 &&
|
||||
type != js::ArrayBufferView::TYPE_UINT8_CLAMPED) {
|
||||
@ -102,8 +102,8 @@ PostToRIL(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
size = JS_GetTypedArrayByteLength(obj);
|
||||
data = JS_GetArrayBufferViewData(obj);
|
||||
size = JS_GetTypedArrayByteLength(obj, cx);
|
||||
data = JS_GetArrayBufferViewData(obj, cx);
|
||||
} else {
|
||||
JS_ReportError(cx,
|
||||
"Incorrect argument. Expecting a string or a typed array");
|
||||
@ -175,7 +175,7 @@ RILReceiver::DispatchRILEvent::RunTask(JSContext *aCx)
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(JS_GetArrayBufferViewData(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);
|
||||
@ -217,12 +217,12 @@ DoNetdCommand(JSContext *cx, unsigned argc, jsval *vp)
|
||||
}
|
||||
} else if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(v);
|
||||
if (!JS_IsTypedArrayObject(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);
|
||||
uint32_t type = JS_GetTypedArrayType(obj, cx);
|
||||
if (type != js::ArrayBufferView::TYPE_INT8 &&
|
||||
type != js::ArrayBufferView::TYPE_UINT8 &&
|
||||
type != js::ArrayBufferView::TYPE_UINT8_CLAMPED) {
|
||||
@ -230,13 +230,13 @@ DoNetdCommand(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
size = JS_GetTypedArrayByteLength(obj);
|
||||
size = JS_GetTypedArrayByteLength(obj, cx);
|
||||
if (!size) {
|
||||
JS_ReportError(cx, "Typed array byte length is zero");
|
||||
return false;
|
||||
}
|
||||
|
||||
data = JS_GetArrayBufferViewData(obj);
|
||||
data = JS_GetArrayBufferViewData(obj, cx);
|
||||
if (!data) {
|
||||
JS_ReportError(cx, "Array buffer view data is NULL");
|
||||
return false;
|
||||
@ -322,7 +322,7 @@ NetdReceiver::DispatchNetdEvent::RunTask(JSContext *aCx)
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(JS_GetUint8ArrayData(array), mMessage->mData, mMessage->mSize);
|
||||
memcpy(JS_GetUint8ArrayData(array, aCx), mMessage->mData, mMessage->mSize);
|
||||
jsval argv[] = { OBJECT_TO_JSVAL(array) };
|
||||
return JS_CallFunctionName(aCx, obj, "onNetdMessage", NS_ARRAY_LENGTH(argv),
|
||||
argv, argv);
|
||||
|
@ -95,8 +95,8 @@ FileReaderSync::ReadAsArrayBuffer(JSContext* aCx, JSObject* aBlob,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = blob->GetInternalStream(getter_AddRefs(stream));
|
||||
|
@ -40,8 +40,8 @@ public:
|
||||
Create(JSContext* aCx, uint32_t aWidth, uint32_t aHeight, JSObject *aData)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
MOZ_ASSERT(JS_IsTypedArrayObject(aData));
|
||||
MOZ_ASSERT(JS_IsUint8ClampedArray(aData));
|
||||
MOZ_ASSERT(JS_IsTypedArrayObject(aData, aCx));
|
||||
MOZ_ASSERT(JS_IsUint8ClampedArray(aData, aCx));
|
||||
|
||||
JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
|
||||
if (!obj) {
|
||||
|
@ -2008,7 +2008,7 @@ XMLHttpRequest::Send(JSObject* aBody, ErrorResult& aRv)
|
||||
JSContext* cx = GetJSContext();
|
||||
|
||||
jsval valToClone;
|
||||
if (JS_IsArrayBufferObject(aBody) || file::GetDOMBlobFromJSObject(aBody)) {
|
||||
if (JS_IsArrayBufferObject(aBody, cx) || file::GetDOMBlobFromJSObject(aBody)) {
|
||||
valToClone = OBJECT_TO_JSVAL(aBody);
|
||||
}
|
||||
else {
|
||||
|
@ -2116,7 +2116,7 @@ bool CanConvertTypedArrayItemTo(JSObject *baseType, JSObject *valObj, JSContext
|
||||
return true;
|
||||
}
|
||||
TypeCode elementTypeCode;
|
||||
switch (JS_GetTypedArrayType(valObj)) {
|
||||
switch (JS_GetTypedArrayType(valObj, cx)) {
|
||||
case TypedArray::TYPE_INT8:
|
||||
elementTypeCode = TYPE_int8_t;
|
||||
break;
|
||||
@ -2341,13 +2341,13 @@ ImplicitConvert(JSContext* cx,
|
||||
return TypeError(cx, "string pointer", val);
|
||||
}
|
||||
break;
|
||||
} else if (!JSVAL_IS_PRIMITIVE(val) && JS_IsArrayBufferObject(valObj)) {
|
||||
} else if (!JSVAL_IS_PRIMITIVE(val) && JS_IsArrayBufferObject(valObj, cx)) {
|
||||
// Convert ArrayBuffer to pointer without any copy.
|
||||
// Just as with C arrays, we make no effort to
|
||||
// keep the ArrayBuffer alive.
|
||||
*static_cast<void**>(buffer) = JS_GetArrayBufferData(valObj);
|
||||
*static_cast<void**>(buffer) = JS_GetArrayBufferData(valObj, cx);
|
||||
break;
|
||||
} if (!JSVAL_IS_PRIMITIVE(val) && JS_IsTypedArrayObject(valObj)) {
|
||||
} if (!JSVAL_IS_PRIMITIVE(val) && JS_IsTypedArrayObject(valObj, cx)) {
|
||||
if(!CanConvertTypedArrayItemTo(baseType, valObj, cx)) {
|
||||
return TypeError(cx, "typed array with the appropriate type", val);
|
||||
}
|
||||
@ -2355,7 +2355,7 @@ ImplicitConvert(JSContext* cx,
|
||||
// Convert TypedArray to pointer without any copy.
|
||||
// Just as with C arrays, we make no effort to
|
||||
// keep the TypedArray alive.
|
||||
*static_cast<void**>(buffer) = JS_GetArrayBufferViewData(valObj);
|
||||
*static_cast<void**>(buffer) = JS_GetArrayBufferViewData(valObj, cx);
|
||||
break;
|
||||
}
|
||||
return TypeError(cx, "pointer", val);
|
||||
@ -2444,34 +2444,34 @@ ImplicitConvert(JSContext* cx,
|
||||
memcpy(buffer, intermediate.get(), arraySize);
|
||||
|
||||
} else if (!JSVAL_IS_PRIMITIVE(val) &&
|
||||
JS_IsArrayBufferObject(valObj)) {
|
||||
JS_IsArrayBufferObject(valObj, cx)) {
|
||||
// Check that array is consistent with type, then
|
||||
// copy the array.
|
||||
uint32_t sourceLength = JS_GetArrayBufferByteLength(valObj);
|
||||
uint32_t sourceLength = JS_GetArrayBufferByteLength(valObj, cx);
|
||||
size_t elementSize = CType::GetSize(baseType);
|
||||
size_t arraySize = elementSize * targetLength;
|
||||
if (arraySize != size_t(sourceLength)) {
|
||||
JS_ReportError(cx, "ArrayType length does not match source ArrayBuffer length");
|
||||
return false;
|
||||
}
|
||||
memcpy(buffer, JS_GetArrayBufferData(valObj), sourceLength);
|
||||
memcpy(buffer, JS_GetArrayBufferData(valObj, cx), sourceLength);
|
||||
break;
|
||||
} else if (!JSVAL_IS_PRIMITIVE(val) &&
|
||||
JS_IsTypedArrayObject(valObj)) {
|
||||
JS_IsTypedArrayObject(valObj, cx)) {
|
||||
// Check that array is consistent with type, then
|
||||
// copy the array.
|
||||
if(!CanConvertTypedArrayItemTo(baseType, valObj, cx)) {
|
||||
return TypeError(cx, "typed array with the appropriate type", val);
|
||||
}
|
||||
|
||||
uint32_t sourceLength = JS_GetTypedArrayByteLength(valObj);
|
||||
uint32_t sourceLength = JS_GetTypedArrayByteLength(valObj, cx);
|
||||
size_t elementSize = CType::GetSize(baseType);
|
||||
size_t arraySize = elementSize * targetLength;
|
||||
if (arraySize != size_t(sourceLength)) {
|
||||
JS_ReportError(cx, "typed array length does not match source TypedArray length");
|
||||
return false;
|
||||
}
|
||||
memcpy(buffer, JS_GetArrayBufferViewData(valObj), sourceLength);
|
||||
memcpy(buffer, JS_GetArrayBufferViewData(valObj, cx), sourceLength);
|
||||
break;
|
||||
} else {
|
||||
// Don't implicitly convert to string. Users can implicitly convert
|
||||
|
@ -36,15 +36,15 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal)
|
||||
jsval v;
|
||||
|
||||
// Byte lengths should all agree
|
||||
CHECK(JS_IsArrayBufferObject(obj));
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(obj), size);
|
||||
CHECK(JS_IsArrayBufferObject(obj, cx));
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(obj, cx), size);
|
||||
JS_GetProperty(cx, obj, "byteLength", &v);
|
||||
CHECK_SAME(v, INT_TO_JSVAL(size));
|
||||
JS_GetProperty(cx, view, "byteLength", &v);
|
||||
CHECK_SAME(v, INT_TO_JSVAL(size));
|
||||
|
||||
// Modifying the underlying data should update the value returned through the view
|
||||
uint8_t *data = JS_GetArrayBufferData(obj);
|
||||
uint8_t *data = JS_GetArrayBufferData(obj, cx);
|
||||
CHECK(data != NULL);
|
||||
*reinterpret_cast<uint32_t*>(data) = MAGIC_VALUE_2;
|
||||
CHECK(JS_GetElement(cx, view, 0, &v));
|
||||
@ -57,7 +57,7 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal)
|
||||
CHECK(data != NULL);
|
||||
|
||||
// Check that the original ArrayBuffer is neutered
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(obj), 0);
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(obj, cx), 0);
|
||||
CHECK(JS_GetProperty(cx, obj, "byteLength", &v));
|
||||
CHECK_SAME(v, INT_TO_JSVAL(0));
|
||||
CHECK(JS_GetProperty(cx, view, "byteLength", &v));
|
||||
@ -66,21 +66,21 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal)
|
||||
CHECK_SAME(v, INT_TO_JSVAL(0));
|
||||
CHECK(JS_GetProperty(cx, view, "length", &v));
|
||||
CHECK_SAME(v, INT_TO_JSVAL(0));
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(obj), 0);
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(obj, cx), 0);
|
||||
v = JSVAL_VOID;
|
||||
JS_GetElement(cx, obj, 0, &v);
|
||||
CHECK_SAME(v, JSVAL_VOID);
|
||||
|
||||
// Transfer to a new ArrayBuffer
|
||||
js::RootedObject dst(cx, JS_NewArrayBufferWithContents(cx, contents));
|
||||
CHECK(JS_IsArrayBufferObject(dst));
|
||||
data = JS_GetArrayBufferData(obj);
|
||||
CHECK(JS_IsArrayBufferObject(dst, cx));
|
||||
data = JS_GetArrayBufferData(obj, cx);
|
||||
|
||||
js::RootedObject dstview(cx, JS_NewInt32ArrayWithBuffer(cx, dst, 0, -1));
|
||||
CHECK(dstview != NULL);
|
||||
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(dst), size);
|
||||
data = JS_GetArrayBufferData(dst);
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(dst, cx), size);
|
||||
data = JS_GetArrayBufferData(dst, cx);
|
||||
CHECK(data != NULL);
|
||||
CHECK_EQUAL(*reinterpret_cast<uint32_t*>(data), MAGIC_VALUE_2);
|
||||
CHECK(JS_GetElement(cx, dstview, 0, &v));
|
||||
|
@ -28,16 +28,16 @@ BEGIN_TEST(testTypedArrays)
|
||||
|
||||
size_t nbytes = sizeof(double) * 8;
|
||||
RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes));
|
||||
CHECK(JS_IsArrayBufferObject(buffer));
|
||||
CHECK(JS_IsArrayBufferObject(buffer, cx));
|
||||
|
||||
RootedObject proto(cx);
|
||||
JS_GetPrototype(cx, buffer, proto.address());
|
||||
CHECK(!JS_IsArrayBufferObject(proto));
|
||||
CHECK(!JS_IsArrayBufferObject(proto, cx));
|
||||
RootedObject dummy(cx, JS_GetParent(proto));
|
||||
CHECK(!JS_IsArrayBufferObject(dummy));
|
||||
CHECK(!JS_IsArrayBufferObject(dummy, cx));
|
||||
|
||||
CHECK_EQUAL(JS_GetArrayBufferByteLength(buffer), nbytes);
|
||||
memset(JS_GetArrayBufferData(buffer), 1, nbytes);
|
||||
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) &&
|
||||
@ -55,24 +55,24 @@ BEGIN_TEST(testTypedArrays)
|
||||
|
||||
template<JSObject *Create(JSContext *, uint32_t),
|
||||
typename Element,
|
||||
Element *GetData(JSObject *)>
|
||||
Element *GetData(JSObject *, JSContext *)>
|
||||
bool
|
||||
TestPlainTypedArray(JSContext *cx)
|
||||
{
|
||||
RootedObject array(cx, Create(cx, 7));
|
||||
CHECK(JS_IsTypedArrayObject(array));
|
||||
CHECK(JS_IsTypedArrayObject(array, cx));
|
||||
RootedObject proto(cx);
|
||||
JS_GetPrototype(cx, array, proto.address());
|
||||
CHECK(!JS_IsTypedArrayObject(proto));
|
||||
CHECK(!JS_IsTypedArrayObject(proto, cx));
|
||||
RootedObject dummy(cx, JS_GetParent(proto));
|
||||
CHECK(!JS_IsTypedArrayObject(dummy));
|
||||
CHECK(!JS_IsTypedArrayObject(dummy, cx));
|
||||
|
||||
CHECK_EQUAL(JS_GetTypedArrayLength(array), 7);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteOffset(array), 0);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteLength(array), sizeof(Element) * 7);
|
||||
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));
|
||||
CHECK(data = GetData(array, cx));
|
||||
*data = 13;
|
||||
jsval v;
|
||||
CHECK(JS_GetElement(cx, array, 0, &v));
|
||||
@ -84,7 +84,7 @@ TestPlainTypedArray(JSContext *cx)
|
||||
template<JSObject *CreateWithBuffer(JSContext *, JSObject *, uint32_t, int32_t),
|
||||
JSObject *CreateFromArray(JSContext *, JSObject *),
|
||||
typename Element,
|
||||
Element *GetData(JSObject *)>
|
||||
Element *GetData(JSObject *, JSContext *)>
|
||||
bool
|
||||
TestArrayFromBuffer(JSContext *cx)
|
||||
{
|
||||
@ -92,32 +92,32 @@ TestArrayFromBuffer(JSContext *cx)
|
||||
size_t nbytes = elts * sizeof(Element);
|
||||
RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes));
|
||||
uint8_t *bufdata;
|
||||
CHECK(bufdata = JS_GetArrayBufferData(buffer));
|
||||
CHECK(bufdata = JS_GetArrayBufferData(buffer, cx));
|
||||
memset(bufdata, 1, nbytes);
|
||||
|
||||
RootedObject array(cx, CreateWithBuffer(cx, buffer, 0, -1));
|
||||
CHECK_EQUAL(JS_GetTypedArrayLength(array), elts);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteOffset(array), 0);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteLength(array), nbytes);
|
||||
CHECK_EQUAL(JS_GetArrayBufferViewBuffer(array), (JSObject*) buffer);
|
||||
CHECK_EQUAL(JS_GetTypedArrayLength(array, cx), elts);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteOffset(array, cx), 0);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteLength(array, cx), nbytes);
|
||||
CHECK_EQUAL(JS_GetArrayBufferViewBuffer(array, cx), (JSObject*) buffer);
|
||||
|
||||
Element *data;
|
||||
CHECK(data = GetData(array));
|
||||
CHECK(bufdata = JS_GetArrayBufferData(buffer));
|
||||
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);
|
||||
|
||||
RootedObject shortArray(cx, CreateWithBuffer(cx, buffer, 0, elts / 2));
|
||||
CHECK_EQUAL(JS_GetTypedArrayLength(shortArray), elts / 2);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteOffset(shortArray), 0);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteLength(shortArray), nbytes / 2);
|
||||
CHECK_EQUAL(JS_GetTypedArrayLength(shortArray, cx), elts / 2);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteOffset(shortArray, cx), 0);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteLength(shortArray, cx), nbytes / 2);
|
||||
|
||||
RootedObject ofsArray(cx, CreateWithBuffer(cx, buffer, nbytes / 2, -1));
|
||||
CHECK_EQUAL(JS_GetTypedArrayLength(ofsArray), elts / 2);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteOffset(ofsArray), nbytes / 2);
|
||||
CHECK_EQUAL(JS_GetTypedArrayByteLength(ofsArray), nbytes / 2);
|
||||
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);
|
||||
|
@ -567,13 +567,13 @@ JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v)
|
||||
JS_ASSERT(v.isObject());
|
||||
RootedObject obj(w->context(), &v.toObject());
|
||||
|
||||
// If the object is a security wrapper, see if we're allowed to unwrap it.
|
||||
// If we aren't, throw.
|
||||
if (obj->isWrapper())
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
if (!obj) {
|
||||
JS_ReportError(w->context(), "Permission denied to access object");
|
||||
return false;
|
||||
// If the object is a security wrapper, try puncturing it. This may throw
|
||||
// if the access is not allowed.
|
||||
if (obj->isWrapper()) {
|
||||
JSObject *unwrapped = UnwrapObjectChecked(w->context(), obj);
|
||||
if (!unwrapped)
|
||||
return false;
|
||||
obj = unwrapped;
|
||||
}
|
||||
return w->writeTypedArray(obj);
|
||||
}
|
||||
@ -674,11 +674,9 @@ JSStructuredCloneWriter::startWrite(const Value &v)
|
||||
|
||||
// The object might be a security wrapper. See if we can clone what's
|
||||
// behind it. If we can, unwrap the object.
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
if (!obj) {
|
||||
JS_ReportError(context(), "Permission denied to access object");
|
||||
obj = UnwrapObjectChecked(context(), obj);
|
||||
if (!obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoCompartment ac(context(), obj);
|
||||
|
||||
@ -899,23 +897,23 @@ JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp
|
||||
JS_ASSERT(TypedArray::length(obj) == nelems);
|
||||
switch (tag) {
|
||||
case SCTAG_TYPED_ARRAY_INT8:
|
||||
return in.readArray((uint8_t*) JS_GetInt8ArrayData(obj), nelems);
|
||||
return in.readArray((uint8_t*) JS_GetInt8ArrayData(obj, context()), nelems);
|
||||
case SCTAG_TYPED_ARRAY_UINT8:
|
||||
return in.readArray(JS_GetUint8ArrayData(obj), nelems);
|
||||
return in.readArray(JS_GetUint8ArrayData(obj, context()), nelems);
|
||||
case SCTAG_TYPED_ARRAY_INT16:
|
||||
return in.readArray((uint16_t*) JS_GetInt16ArrayData(obj), nelems);
|
||||
return in.readArray((uint16_t*) JS_GetInt16ArrayData(obj, context()), nelems);
|
||||
case SCTAG_TYPED_ARRAY_UINT16:
|
||||
return in.readArray(JS_GetUint16ArrayData(obj), nelems);
|
||||
return in.readArray(JS_GetUint16ArrayData(obj, context()), nelems);
|
||||
case SCTAG_TYPED_ARRAY_INT32:
|
||||
return in.readArray((uint32_t*) JS_GetInt32ArrayData(obj), nelems);
|
||||
return in.readArray((uint32_t*) JS_GetInt32ArrayData(obj, context()), nelems);
|
||||
case SCTAG_TYPED_ARRAY_UINT32:
|
||||
return in.readArray(JS_GetUint32ArrayData(obj), nelems);
|
||||
return in.readArray(JS_GetUint32ArrayData(obj, context()), nelems);
|
||||
case SCTAG_TYPED_ARRAY_FLOAT32:
|
||||
return in.readArray((uint32_t*) JS_GetFloat32ArrayData(obj), nelems);
|
||||
return in.readArray((uint32_t*) JS_GetFloat32ArrayData(obj, context()), nelems);
|
||||
case SCTAG_TYPED_ARRAY_FLOAT64:
|
||||
return in.readArray((uint64_t*) JS_GetFloat64ArrayData(obj), nelems);
|
||||
return in.readArray((uint64_t*) JS_GetFloat64ArrayData(obj, context()), nelems);
|
||||
case SCTAG_TYPED_ARRAY_UINT8_CLAMPED:
|
||||
return in.readArray(JS_GetUint8ClampedArrayData(obj), nelems);
|
||||
return in.readArray(JS_GetUint8ClampedArrayData(obj, context()), nelems);
|
||||
default:
|
||||
JS_NOT_REACHED("unknown TypedArray type");
|
||||
return false;
|
||||
|
@ -1183,40 +1183,41 @@ JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
|
||||
* the various accessor JSAPI calls defined below.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsTypedArrayObject(JSObject *obj);
|
||||
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx);
|
||||
|
||||
/*
|
||||
* Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
|
||||
* return false if a security wrapper is encountered that denies the
|
||||
* unwrapping. If this test or one of the more specific tests succeeds, then it
|
||||
* is safe to call the various ArrayBufferView accessor JSAPI calls defined
|
||||
* below.
|
||||
* below. cx MUST be non-NULL and valid.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsArrayBufferViewObject(JSObject *obj);
|
||||
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
|
||||
|
||||
/*
|
||||
* Test for specific typed array types (ArrayBufferView subtypes)
|
||||
*/
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsInt8Array(JSObject *obj);
|
||||
JS_IsInt8Array(JSObject *obj, JSContext *cx);
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsUint8Array(JSObject *obj);
|
||||
JS_IsUint8Array(JSObject *obj, JSContext *cx);
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsUint8ClampedArray(JSObject *obj);
|
||||
JS_IsUint8ClampedArray(JSObject *obj, JSContext *cx);
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsInt16Array(JSObject *obj);
|
||||
JS_IsInt16Array(JSObject *obj, JSContext *cx);
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsUint16Array(JSObject *obj);
|
||||
JS_IsUint16Array(JSObject *obj, JSContext *cx);
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsInt32Array(JSObject *obj);
|
||||
JS_IsInt32Array(JSObject *obj, JSContext *cx);
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsUint32Array(JSObject *obj);
|
||||
JS_IsUint32Array(JSObject *obj, JSContext *cx);
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsFloat32Array(JSObject *obj);
|
||||
JS_IsFloat32Array(JSObject *obj, JSContext *cx);
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsFloat64Array(JSObject *obj);
|
||||
JS_IsFloat64Array(JSObject *obj, JSContext *cx);
|
||||
|
||||
|
||||
/*
|
||||
* Unwrap Typed arrays all at once. Return NULL without throwing if the object
|
||||
@ -1224,37 +1225,38 @@ JS_IsFloat64Array(JSObject *obj);
|
||||
* success, filling both outparameters.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsInt8Array(JSObject *obj, uint32_t *length, int8_t **data);
|
||||
JS_GetObjectAsInt8Array(JSContext *cx, JSObject *obj, uint32_t *length, int8_t **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsUint8Array(JSObject *obj, uint32_t *length, uint8_t **data);
|
||||
JS_GetObjectAsUint8Array(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsUint8ClampedArray(JSObject *obj, uint32_t *length, uint8_t **data);
|
||||
JS_GetObjectAsUint8ClampedArray(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsInt16Array(JSObject *obj, uint32_t *length, int16_t **data);
|
||||
JS_GetObjectAsInt16Array(JSContext *cx, JSObject *obj, uint32_t *length, int16_t **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsUint16Array(JSObject *obj, uint32_t *length, uint16_t **data);
|
||||
JS_GetObjectAsUint16Array(JSContext *cx, JSObject *obj, uint32_t *length, uint16_t **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsInt32Array(JSObject *obj, uint32_t *length, int32_t **data);
|
||||
JS_GetObjectAsInt32Array(JSContext *cx, JSObject *obj, uint32_t *length, int32_t **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsUint32Array(JSObject *obj, uint32_t *length, uint32_t **data);
|
||||
JS_GetObjectAsUint32Array(JSContext *cx, JSObject *obj, uint32_t *length, uint32_t **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsFloat32Array(JSObject *obj, uint32_t *length, float **data);
|
||||
JS_GetObjectAsFloat32Array(JSContext *cx, JSObject *obj, uint32_t *length, float **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsFloat64Array(JSObject *obj, uint32_t *length, double **data);
|
||||
JS_GetObjectAsFloat64Array(JSContext *cx, JSObject *obj, uint32_t *length, double **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data);
|
||||
JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data);
|
||||
JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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);
|
||||
JS_GetTypedArrayType(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* Check whether obj supports the JS_GetArrayBuffer* APIs. Note that this may
|
||||
@ -1263,17 +1265,18 @@ JS_GetTypedArrayType(JSObject *obj);
|
||||
* accessor JSAPI calls defined below.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsArrayBufferObject(JSObject *obj);
|
||||
JS_IsArrayBufferObject(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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);
|
||||
JS_GetArrayBufferByteLength(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* Return a pointer to an array buffer's data. The buffer is still owned by the
|
||||
@ -1282,20 +1285,22 @@ JS_GetArrayBufferByteLength(JSObject *obj);
|
||||
*
|
||||
* |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.
|
||||
* 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);
|
||||
JS_GetArrayBufferData(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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);
|
||||
JS_GetTypedArrayLength(JSObject *obj, JSContext *cx);
|
||||
|
||||
/*
|
||||
* Return the byte offset from the start of an array buffer to the start of a
|
||||
@ -1303,20 +1308,22 @@ JS_GetTypedArrayLength(JSObject *obj);
|
||||
*
|
||||
* |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.
|
||||
* 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);
|
||||
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.
|
||||
* 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);
|
||||
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
|
||||
|
||||
/*
|
||||
* Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
|
||||
@ -1324,13 +1331,13 @@ JS_GetTypedArrayByteLength(JSObject *obj);
|
||||
* unwrapping.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
JS_IsArrayBufferViewObject(JSObject *obj);
|
||||
JS_IsArrayBufferViewObject(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);
|
||||
JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx);
|
||||
|
||||
/*
|
||||
* Return a pointer to the start of the data referenced by a typed array. The
|
||||
@ -1339,34 +1346,35 @@ JS_GetArrayBufferViewByteLength(JSObject *obj);
|
||||
*
|
||||
* |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.
|
||||
* 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);
|
||||
JS_GetInt8ArrayData(JSObject *obj, JSContext *maybecx);
|
||||
extern JS_FRIEND_API(uint8_t *)
|
||||
JS_GetUint8ArrayData(JSObject *obj);
|
||||
JS_GetUint8ArrayData(JSObject *obj, JSContext *maybecx);
|
||||
extern JS_FRIEND_API(uint8_t *)
|
||||
JS_GetUint8ClampedArrayData(JSObject *obj);
|
||||
JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *maybecx);
|
||||
extern JS_FRIEND_API(int16_t *)
|
||||
JS_GetInt16ArrayData(JSObject *obj);
|
||||
JS_GetInt16ArrayData(JSObject *obj, JSContext *maybecx);
|
||||
extern JS_FRIEND_API(uint16_t *)
|
||||
JS_GetUint16ArrayData(JSObject *obj);
|
||||
JS_GetUint16ArrayData(JSObject *obj, JSContext *maybecx);
|
||||
extern JS_FRIEND_API(int32_t *)
|
||||
JS_GetInt32ArrayData(JSObject *obj);
|
||||
JS_GetInt32ArrayData(JSObject *obj, JSContext *maybecx);
|
||||
extern JS_FRIEND_API(uint32_t *)
|
||||
JS_GetUint32ArrayData(JSObject *obj);
|
||||
JS_GetUint32ArrayData(JSObject *obj, JSContext *maybecx);
|
||||
extern JS_FRIEND_API(float *)
|
||||
JS_GetFloat32ArrayData(JSObject *obj);
|
||||
JS_GetFloat32ArrayData(JSObject *obj, JSContext *maybecx);
|
||||
extern JS_FRIEND_API(double *)
|
||||
JS_GetFloat64ArrayData(JSObject *obj);
|
||||
JS_GetFloat64ArrayData(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
JS_GetArrayBufferViewData(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* Return the ArrayBuffer underlying an ArrayBufferView. If the buffer has been
|
||||
@ -1374,13 +1382,15 @@ JS_GetArrayBufferViewData(JSObject *obj);
|
||||
* object that would return true for JS_IsArrayBufferViewObject().
|
||||
*/
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
JS_GetArrayBufferViewBuffer(JSObject *obj);
|
||||
JS_GetArrayBufferViewBuffer(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* Check whether obj supports JS_GetDataView* APIs.
|
||||
* Check whether obj supports JS_GetDataView* APIs. Note that this may fail and
|
||||
* throw an exception if a security wrapper is encountered that denies the
|
||||
* operation.
|
||||
*/
|
||||
JS_FRIEND_API(JSBool)
|
||||
JS_IsDataViewObject(JSObject *obj);
|
||||
JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView);
|
||||
|
||||
/*
|
||||
* Return the byte offset of a data view into its array buffer. |obj| must be a
|
||||
@ -1388,10 +1398,11 @@ JS_IsDataViewObject(JSObject *obj);
|
||||
*
|
||||
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
|
||||
* it would pass such a test: it is a data view or a wrapper of a data view,
|
||||
* and the unwrapping will succeed.
|
||||
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
|
||||
* unable to assert when unwrapping should be disallowed.
|
||||
*/
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetDataViewByteOffset(JSObject *obj);
|
||||
JS_GetDataViewByteOffset(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* Return the byte length of a data view.
|
||||
@ -1402,7 +1413,7 @@ JS_GetDataViewByteOffset(JSObject *obj);
|
||||
* unable to assert when unwrapping should be disallowed.
|
||||
*/
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetDataViewByteLength(JSObject *obj);
|
||||
JS_GetDataViewByteLength(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* Return a pointer to the beginning of the data referenced by a DataView.
|
||||
@ -1413,7 +1424,7 @@ JS_GetDataViewByteLength(JSObject *obj);
|
||||
* unable to assert when unwrapping should be disallowed.
|
||||
*/
|
||||
JS_FRIEND_API(void *)
|
||||
JS_GetDataViewData(JSObject *obj);
|
||||
JS_GetDataViewData(JSObject *obj, JSContext *maybecx);
|
||||
|
||||
/*
|
||||
* This struct contains metadata passed from the DOM to the JS Engine for JIT
|
||||
|
@ -174,10 +174,16 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Censor the caller if we don't have full access to it.
|
||||
* Censor the caller if we can't PUNCTURE it.
|
||||
*
|
||||
* NB - This will get much much nicer with bug 800915
|
||||
*/
|
||||
JSObject &caller = vp.toObject();
|
||||
if (caller.isWrapper() && !Wrapper::wrapperHandler(&caller)->isSafeToUnwrap()) {
|
||||
JSErrorReporter reporter = JS_SetErrorReporter(cx, NULL);
|
||||
bool punctureThrew = !UnwrapObjectChecked(cx, &caller);
|
||||
JS_SetErrorReporter(cx, reporter);
|
||||
if (punctureThrew) {
|
||||
JS_ClearPendingException(cx);
|
||||
vp.setNull();
|
||||
} else if (caller.isFunction()) {
|
||||
JSFunction *callerFun = caller.toFunction();
|
||||
|
@ -1873,11 +1873,9 @@ class TypedArrayTemplate
|
||||
* compartment for a view in the target compartment referencing the
|
||||
* ArrayBuffer in that same compartment.
|
||||
*/
|
||||
JSObject *wrapped = UnwrapObjectChecked(bufobj);
|
||||
if (!wrapped) {
|
||||
JS_ReportError(cx, "Permission denied to access object");
|
||||
JSObject *wrapped = UnwrapObjectChecked(cx, bufobj);
|
||||
if (!wrapped)
|
||||
return NULL;
|
||||
}
|
||||
if (wrapped->isArrayBuffer()) {
|
||||
/*
|
||||
* And for even more fun, the new view's prototype should be
|
||||
@ -3143,10 +3141,13 @@ JSFunctionSpec _typedArray::jsfuncs[] = { \
|
||||
return TypedArrayTemplate<NativeType>::fromBuffer(cx, arrayBuffer, byteoffset, length, \
|
||||
proto); \
|
||||
} \
|
||||
JS_FRIEND_API(JSBool) JS_Is ## Name ## Array(JSObject *obj) \
|
||||
JS_FRIEND_API(JSBool) JS_Is ## Name ## Array(JSObject *obj, JSContext *cx) \
|
||||
{ \
|
||||
if (!(obj = UnwrapObjectChecked(obj))) \
|
||||
MOZ_ASSERT(!cx->isExceptionPending()); \
|
||||
if (!(obj = UnwrapObjectChecked(cx, obj))) { \
|
||||
cx->clearPendingException(); \
|
||||
return false; \
|
||||
} \
|
||||
Class *clasp = obj->getClass(); \
|
||||
return (clasp == &TypedArray::classes[TypedArrayTemplate<NativeType>::ArrayTypeID()]); \
|
||||
}
|
||||
@ -3162,12 +3163,18 @@ IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float32, float)
|
||||
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float64, double)
|
||||
|
||||
#define IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Name, ExternalType, InternalType) \
|
||||
JS_FRIEND_API(JSObject *) JS_GetObjectAs ## Name ## Array(JSObject *obj, \
|
||||
JS_FRIEND_API(JSObject *) JS_GetObjectAs ## Name ## Array(JSContext *cx, \
|
||||
JSObject *obj, \
|
||||
uint32_t *length, \
|
||||
ExternalType **data) \
|
||||
{ \
|
||||
if (!(obj = UnwrapObjectChecked(obj))) \
|
||||
return NULL; \
|
||||
if (obj->isWrapper()) { \
|
||||
MOZ_ASSERT(!cx->isExceptionPending()); \
|
||||
if (!(obj = UnwrapObjectChecked(cx, obj))) { \
|
||||
cx->clearPendingException(); \
|
||||
return NULL; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
Class *clasp = obj->getClass(); \
|
||||
if (clasp != &TypedArray::classes[TypedArrayTemplate<InternalType>::ArrayTypeID()]) \
|
||||
@ -3564,42 +3571,76 @@ js_InitTypedArrayClasses(JSContext *cx, HandleObject obj)
|
||||
|
||||
/* JS Friend API */
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
JS_IsArrayBufferObject(JSObject *obj)
|
||||
// The typed array friend API defines a number of accessor functions that want
|
||||
// to unwrap an argument, but in certain rare cases may not have a cx available
|
||||
// and so pass in NULL instead. Use UnwrapObjectChecked when possible.
|
||||
static JSObject *
|
||||
CheckedUnwrap(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
return obj ? obj->isArrayBuffer() : false;
|
||||
if (!cx)
|
||||
return UnwrapObject(obj);
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
obj = UnwrapObjectChecked(cx, obj);
|
||||
MOZ_ASSERT(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
JS_IsTypedArrayObject(JSObject *obj)
|
||||
JS_IsArrayBufferObject(JSObject *objArg, JSContext *cx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
return obj ? obj->isTypedArray() : false;
|
||||
RootedObject obj_(cx, objArg);
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
JSObject *obj = UnwrapObjectChecked(cx, obj_);
|
||||
if (!obj) {
|
||||
cx->clearPendingException();
|
||||
return false;
|
||||
}
|
||||
return obj->isArrayBuffer();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
JS_IsArrayBufferViewObject(JSObject *obj)
|
||||
JS_IsTypedArrayObject(JSObject *objArg, JSContext *cx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
return obj ? (obj->isTypedArray() || obj->isDataView()) : false;
|
||||
RootedObject obj_(cx, objArg);
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
JSObject *obj = UnwrapObjectChecked(cx, obj_);
|
||||
if (!obj) {
|
||||
cx->clearPendingException();
|
||||
return false;
|
||||
}
|
||||
return obj->isTypedArray();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
JS_IsArrayBufferViewObject(JSObject *objArg, JSContext *cx)
|
||||
{
|
||||
RootedObject obj_(cx, objArg);
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
JSObject *obj = UnwrapObjectChecked(cx, obj_);
|
||||
if (!obj) {
|
||||
cx->clearPendingException();
|
||||
return false;
|
||||
}
|
||||
return obj->isTypedArray() || obj->isDataView();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetArrayBufferByteLength(JSObject *obj)
|
||||
JS_GetArrayBufferByteLength(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
return obj ? obj->asArrayBuffer().byteLength() : 0;
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return 0;
|
||||
return obj->asArrayBuffer().byteLength();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint8_t *)
|
||||
JS_GetArrayBufferData(JSObject *obj)
|
||||
JS_GetArrayBufferData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
ArrayBufferObject &buffer = obj->asArrayBuffer();
|
||||
if (!buffer.uninlineData(NULL))
|
||||
if (!buffer.uninlineData(maybecx))
|
||||
return NULL;
|
||||
return buffer.dataPointer();
|
||||
}
|
||||
@ -3639,7 +3680,7 @@ JS_PUBLIC_API(JSBool)
|
||||
JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
|
||||
uint8_t **data)
|
||||
{
|
||||
if (!(obj = UnwrapObjectChecked(obj)))
|
||||
if (!(obj = UnwrapObjectChecked(cx, obj)))
|
||||
return false;
|
||||
|
||||
if (!obj->isArrayBuffer()) {
|
||||
@ -3654,9 +3695,9 @@ JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetTypedArrayLength(JSObject *obj)
|
||||
JS_GetTypedArrayLength(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return 0;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3664,9 +3705,9 @@ JS_GetTypedArrayLength(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetTypedArrayByteOffset(JSObject *obj)
|
||||
JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return 0;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3674,9 +3715,9 @@ JS_GetTypedArrayByteOffset(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetTypedArrayByteLength(JSObject *obj)
|
||||
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return 0;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3684,9 +3725,9 @@ JS_GetTypedArrayByteLength(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSArrayBufferViewType)
|
||||
JS_GetTypedArrayType(JSObject *obj)
|
||||
JS_GetTypedArrayType(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return ArrayBufferView::TYPE_MAX;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3694,9 +3735,9 @@ JS_GetTypedArrayType(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(int8_t *)
|
||||
JS_GetInt8ArrayData(JSObject *obj)
|
||||
JS_GetInt8ArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3705,9 +3746,9 @@ JS_GetInt8ArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint8_t *)
|
||||
JS_GetUint8ArrayData(JSObject *obj)
|
||||
JS_GetUint8ArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3716,9 +3757,9 @@ JS_GetUint8ArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint8_t *)
|
||||
JS_GetUint8ClampedArrayData(JSObject *obj)
|
||||
JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3727,9 +3768,9 @@ JS_GetUint8ClampedArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(int16_t *)
|
||||
JS_GetInt16ArrayData(JSObject *obj)
|
||||
JS_GetInt16ArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3738,9 +3779,9 @@ JS_GetInt16ArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint16_t *)
|
||||
JS_GetUint16ArrayData(JSObject *obj)
|
||||
JS_GetUint16ArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3749,9 +3790,9 @@ JS_GetUint16ArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(int32_t *)
|
||||
JS_GetInt32ArrayData(JSObject *obj)
|
||||
JS_GetInt32ArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3760,9 +3801,9 @@ JS_GetInt32ArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t *)
|
||||
JS_GetUint32ArrayData(JSObject *obj)
|
||||
JS_GetUint32ArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3771,9 +3812,9 @@ JS_GetUint32ArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(float *)
|
||||
JS_GetFloat32ArrayData(JSObject *obj)
|
||||
JS_GetFloat32ArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3782,9 +3823,9 @@ JS_GetFloat32ArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(double *)
|
||||
JS_GetFloat64ArrayData(JSObject *obj)
|
||||
JS_GetFloat64ArrayData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray());
|
||||
@ -3793,25 +3834,29 @@ JS_GetFloat64ArrayData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
JS_IsDataViewObject(JSObject *obj)
|
||||
JS_IsDataViewObject(JSContext *cx, JSObject *objArg, JSBool *isDataView)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
return obj ? obj->isDataView() : false;
|
||||
RootedObject obj_(cx, objArg);
|
||||
JSObject *obj = CheckedUnwrap(cx, obj_);
|
||||
if (!obj)
|
||||
return false;
|
||||
*isDataView = obj->isDataView();
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetDataViewByteOffset(JSObject *obj)
|
||||
JS_GetDataViewByteOffset(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return 0;
|
||||
return obj->asDataView().byteOffset();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void *)
|
||||
JS_GetDataViewData(JSObject *obj)
|
||||
JS_GetDataViewData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isDataView());
|
||||
@ -3819,9 +3864,9 @@ JS_GetDataViewData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetDataViewByteLength(JSObject *obj)
|
||||
JS_GetDataViewByteLength(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return 0;
|
||||
JS_ASSERT(obj->isDataView());
|
||||
@ -3829,9 +3874,9 @@ JS_GetDataViewByteLength(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void *)
|
||||
JS_GetArrayBufferViewData(JSObject *obj)
|
||||
JS_GetArrayBufferViewData(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray() || obj->isDataView());
|
||||
@ -3839,9 +3884,9 @@ JS_GetArrayBufferViewData(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
JS_GetArrayBufferViewBuffer(JSObject *obj)
|
||||
JS_GetArrayBufferViewBuffer(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isTypedArray() || obj->isDataView());
|
||||
@ -3849,9 +3894,9 @@ JS_GetArrayBufferViewBuffer(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
JS_GetArrayBufferViewByteLength(JSObject *obj)
|
||||
JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *maybecx)
|
||||
{
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
obj = CheckedUnwrap(maybecx, obj);
|
||||
if (!obj)
|
||||
return 0;
|
||||
JS_ASSERT(obj->isTypedArray() || obj->isDataView());
|
||||
@ -3861,10 +3906,15 @@ JS_GetArrayBufferViewByteLength(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data)
|
||||
JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj,
|
||||
uint32_t *length, uint8_t **data)
|
||||
{
|
||||
if (!(obj = UnwrapObjectChecked(obj)))
|
||||
return NULL;
|
||||
if (obj->isWrapper()) {
|
||||
if (!(obj = UnwrapObjectChecked(cx, obj))) {
|
||||
cx->clearPendingException();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!(obj->isTypedArray() || obj->isDataView()))
|
||||
return NULL;
|
||||
|
||||
@ -3877,10 +3927,14 @@ JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data)
|
||||
JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data)
|
||||
{
|
||||
if (!(obj = UnwrapObjectChecked(obj)))
|
||||
return NULL;
|
||||
if (obj->isWrapper()) {
|
||||
if (!(obj = UnwrapObjectChecked(cx, obj))) {
|
||||
cx->clearPendingException();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!obj->isArrayBuffer())
|
||||
return NULL;
|
||||
|
||||
|
@ -109,18 +109,19 @@ js::UnwrapObject(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::UnwrapObjectChecked(RawObject obj)
|
||||
js::UnwrapObjectChecked(JSContext *cx, RawObject objArg)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
while (true) {
|
||||
JSObject *wrapper = obj;
|
||||
obj = UnwrapOneChecked(obj);
|
||||
obj = UnwrapOneChecked(cx, obj);
|
||||
if (!obj || obj == wrapper)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::UnwrapOneChecked(RawObject obj)
|
||||
js::UnwrapOneChecked(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
// Checked unwraps should never unwrap outer windows.
|
||||
if (!obj->isWrapper() ||
|
||||
@ -130,7 +131,13 @@ js::UnwrapOneChecked(RawObject obj)
|
||||
}
|
||||
|
||||
Wrapper *handler = Wrapper::wrapperHandler(obj);
|
||||
return handler->isSafeToUnwrap() ? Wrapper::wrappedObject(obj) : NULL;
|
||||
bool rvOnFailure;
|
||||
if (!handler->enter(cx, obj, JSID_VOID, Wrapper::PUNCTURE, &rvOnFailure))
|
||||
return rvOnFailure ? (JSObject*) obj : NULL;
|
||||
JSObject *ret = Wrapper::wrappedObject(obj);
|
||||
JS_ASSERT(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -153,7 +160,6 @@ js::IsCrossCompartmentWrapper(RawObject wrapper)
|
||||
|
||||
Wrapper::Wrapper(unsigned flags, bool hasPrototype) : DirectProxyHandler(&sWrapperFamily)
|
||||
, mFlags(flags)
|
||||
, mSafeToUnwrap(true)
|
||||
{
|
||||
setHasPrototype(hasPrototype);
|
||||
}
|
||||
@ -215,22 +221,25 @@ Wrapper::enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props)
|
||||
}
|
||||
|
||||
/*
|
||||
* Ordinarily, the convert trap would require unwrapping. However, the default
|
||||
* Ordinarily, the convert trap would require a PUNCTURE. However, the default
|
||||
* implementation of convert, JS_ConvertStub, obtains a default value by calling
|
||||
* the toString/valueOf method on the wrapper, if any. Throwing if we can't unwrap
|
||||
* in this case would be overly conservative. To make matters worse, XPConnect sometimes
|
||||
* the toString/valueOf method on the wrapper, if any. Doing a PUNCTURE in this
|
||||
* case would be overly conservative. To make matters worse, XPConnect sometimes
|
||||
* installs a custom convert trap that obtains a default value by calling the
|
||||
* toString method on the wrapper. Doing a puncture in this case would be overly
|
||||
* conservative as well. We deal with these anomalies by falling back to the DefaultValue
|
||||
* algorithm whenever unwrapping is forbidden.
|
||||
* conservative as well. We deal with these anomalies by clearing the pending
|
||||
* exception and falling back to the DefaultValue algorithm whenever the
|
||||
* PUNCTURE fails.
|
||||
*/
|
||||
bool
|
||||
Wrapper::defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint, Value *vp)
|
||||
{
|
||||
RootedObject wrapper(cx, wrapper_);
|
||||
|
||||
if (!wrapperHandler(wrapper)->isSafeToUnwrap()) {
|
||||
bool status;
|
||||
if (!enter(cx, wrapper_, JSID_VOID, PUNCTURE, &status)) {
|
||||
RootedValue v(cx);
|
||||
JS_ClearPendingException(cx);
|
||||
if (!DefaultValue(cx, wrapper, hint, &v))
|
||||
return false;
|
||||
*vp = v;
|
||||
@ -787,9 +796,7 @@ CrossCompartmentWrapper CrossCompartmentWrapper::singleton(0u);
|
||||
template <class Base>
|
||||
SecurityWrapper<Base>::SecurityWrapper(unsigned flags)
|
||||
: Base(flags)
|
||||
{
|
||||
Base::setSafeToUnwrap(false);
|
||||
}
|
||||
{}
|
||||
|
||||
template <class Base>
|
||||
bool
|
||||
|
@ -29,13 +29,13 @@ class DummyFrameGuard;
|
||||
class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
|
||||
{
|
||||
unsigned mFlags;
|
||||
bool mSafeToUnwrap;
|
||||
|
||||
public:
|
||||
enum Action {
|
||||
GET,
|
||||
SET,
|
||||
CALL
|
||||
CALL,
|
||||
PUNCTURE
|
||||
};
|
||||
|
||||
enum Flags {
|
||||
@ -43,15 +43,6 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
|
||||
LAST_USED_FLAG = CROSS_COMPARTMENT
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrappers can explicitly specify that they are unsafe to unwrap from a
|
||||
* security perspective (as is the case for SecurityWrappers). If a wrapper
|
||||
* is not safe to unwrap, operations requiring full access to the underlying
|
||||
* object (via UnwrapObjectChecked) will throw. Otherwise, they will succeed.
|
||||
*/
|
||||
void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; };
|
||||
bool isSafeToUnwrap() { return mSafeToUnwrap; };
|
||||
|
||||
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
|
||||
JSObject *parent, Wrapper *handler);
|
||||
|
||||
@ -71,7 +62,24 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
|
||||
* on the underlying object's |id| property. In the case when |act| is CALL,
|
||||
* |id| is generally JSID_VOID.
|
||||
*
|
||||
* The |act| parameter to enter() specifies the action being performed.
|
||||
* The |act| parameter to enter() specifies the action being performed. GET,
|
||||
* SET, and CALL are self-explanatory, but PUNCTURE requires more
|
||||
* explanation:
|
||||
*
|
||||
* GET and SET allow for a very fine-grained security membrane, through
|
||||
* which access can be granted or denied on a per-property, per-object, and
|
||||
* per-action basis. Sometimes though, we just want to asks if we can access
|
||||
* _everything_ behind the wrapper barrier. For example, when the structured
|
||||
* clone algorithm runs up against a cross-compartment wrapper, it needs to
|
||||
* know whether it can enter the compartment and keep cloning, or whether it
|
||||
* should throw. This is the role of PUNCTURE.
|
||||
*
|
||||
* PUNCTURE allows the policy to specify whether the wrapper barrier may
|
||||
* be lifted - that is to say, whether the caller is allowed to access
|
||||
* anything that the wrapped object could access. This is a very powerful
|
||||
* permission, and thus should generally be denied for security wrappers
|
||||
* except under very special circumstances. When |act| is PUNCTURE, |id|
|
||||
* should be JSID_VOID.
|
||||
*/
|
||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
|
||||
bool *bp);
|
||||
@ -255,12 +263,12 @@ UnwrapObject(JSObject *obj, bool stopAtOuter = true, unsigned *flagsp = NULL);
|
||||
// code should never be unwrapping outer window wrappers, we always stop at
|
||||
// outer windows.
|
||||
JS_FRIEND_API(JSObject *)
|
||||
UnwrapObjectChecked(RawObject obj);
|
||||
UnwrapObjectChecked(JSContext *cx, RawObject obj);
|
||||
|
||||
// Unwrap only the outermost security wrapper, with the same semantics as
|
||||
// above. This is the checked version of Wrapper::wrappedObject.
|
||||
JS_FRIEND_API(JSObject *)
|
||||
UnwrapOneChecked(RawObject obj);
|
||||
UnwrapOneChecked(JSContext *cx, HandleObject obj);
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
IsCrossCompartmentWrapper(RawObject obj);
|
||||
|
@ -1819,11 +1819,9 @@ Debugger::unwrapDebuggeeArgument(JSContext *cx, const Value &v)
|
||||
}
|
||||
|
||||
/* If we have a cross-compartment wrapper, dereference as far as is secure. */
|
||||
obj = UnwrapObjectChecked(obj);
|
||||
if (!obj) {
|
||||
JS_ReportError(cx, "Permission denied to access object");
|
||||
obj = UnwrapObjectChecked(cx, obj);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If that produced an outer window, innerize it. */
|
||||
obj = GetInnerObject(cx, obj);
|
||||
@ -4467,8 +4465,18 @@ static JSBool
|
||||
DebuggerObject_unwrap(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "unwrap", args, dbg, referent);
|
||||
JSObject *unwrapped = UnwrapOneChecked(referent);
|
||||
JSObject *unwrapped = UnwrapOneChecked(cx, referent);
|
||||
if (!unwrapped) {
|
||||
// If we were terminated, then pass that along.
|
||||
if (!cx->isExceptionPending())
|
||||
return false;
|
||||
|
||||
// If the unwrap operation threw an exception, assume it's a
|
||||
// security exception, and return null. It seems like the wrappers
|
||||
// in use in Firefox just call JS_ReportError, so we have no way to
|
||||
// distinguish genuine should-not-unwrap errors from other kinds of
|
||||
// errors.
|
||||
cx->clearPendingException();
|
||||
vp->setNull();
|
||||
return true;
|
||||
}
|
||||
|
@ -2711,7 +2711,7 @@ nsXPCComponents_Utils::LookupMethod(const JS::Value& object,
|
||||
// we don't have full access to the other compartment, in which case we throw.
|
||||
// Otherwise, enter the compartment.
|
||||
if (js::IsCrossCompartmentWrapper(obj)) {
|
||||
obj = js::UnwrapOneChecked(obj);
|
||||
obj = js::UnwrapOneChecked(cx, obj);
|
||||
if (!obj)
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
@ -3863,7 +3863,7 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
|
||||
{
|
||||
JS_AbortIfWrongThread(JS_GetRuntime(cx));
|
||||
|
||||
sandbox = js::UnwrapObjectChecked(sandbox);
|
||||
sandbox = js::UnwrapObjectChecked(cx, sandbox);
|
||||
if (!sandbox || js::GetObjectJSClass(sandbox) != &SandboxClass) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -1483,7 +1483,8 @@ failure:
|
||||
// of the output does not exceed UINT32_MAX bytes. Allocate
|
||||
// the memory and copy the elements by memcpy.
|
||||
static JSBool
|
||||
CheckTargetAndPopulate(const nsXPTType& type,
|
||||
CheckTargetAndPopulate(JSContext *cx,
|
||||
const nsXPTType& type,
|
||||
uint8_t requiredType,
|
||||
size_t typeSize,
|
||||
uint32_t count,
|
||||
@ -1514,7 +1515,7 @@ CheckTargetAndPopulate(const nsXPTType& type,
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(*output, JS_GetArrayBufferViewData(tArr), byteSize);
|
||||
memcpy(*output, JS_GetArrayBufferViewData(tArr, cx), byteSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1528,7 +1529,8 @@ CheckTargetAndPopulate(const nsXPTType& type,
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCConvert::JSTypedArray2Native(void** d,
|
||||
XPCConvert::JSTypedArray2Native(JSContext* cx,
|
||||
void** d,
|
||||
JSObject* jsArray,
|
||||
uint32_t count,
|
||||
const nsXPTType& type,
|
||||
@ -1536,11 +1538,11 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
{
|
||||
NS_ABORT_IF_FALSE(jsArray, "bad param");
|
||||
NS_ABORT_IF_FALSE(d, "bad param");
|
||||
NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(jsArray), "not a typed array");
|
||||
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;
|
||||
@ -1550,9 +1552,9 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
|
||||
void* output = nullptr;
|
||||
|
||||
switch (JS_GetTypedArrayType(jsArray)) {
|
||||
switch (JS_GetTypedArrayType(jsArray, cx)) {
|
||||
case js::ArrayBufferView::TYPE_INT8:
|
||||
if (!CheckTargetAndPopulate(nsXPTType::T_I8, type,
|
||||
if (!CheckTargetAndPopulate(cx, nsXPTType::T_I8, type,
|
||||
sizeof(int8_t), count,
|
||||
jsArray, &output, pErr)) {
|
||||
return false;
|
||||
@ -1561,7 +1563,7 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
|
||||
case js::ArrayBufferView::TYPE_UINT8:
|
||||
case js::ArrayBufferView::TYPE_UINT8_CLAMPED:
|
||||
if (!CheckTargetAndPopulate(nsXPTType::T_U8, type,
|
||||
if (!CheckTargetAndPopulate(cx, nsXPTType::T_U8, type,
|
||||
sizeof(uint8_t), count,
|
||||
jsArray, &output, pErr)) {
|
||||
return false;
|
||||
@ -1569,7 +1571,7 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
break;
|
||||
|
||||
case js::ArrayBufferView::TYPE_INT16:
|
||||
if (!CheckTargetAndPopulate(nsXPTType::T_I16, type,
|
||||
if (!CheckTargetAndPopulate(cx, nsXPTType::T_I16, type,
|
||||
sizeof(int16_t), count,
|
||||
jsArray, &output, pErr)) {
|
||||
return false;
|
||||
@ -1577,7 +1579,7 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
break;
|
||||
|
||||
case js::ArrayBufferView::TYPE_UINT16:
|
||||
if (!CheckTargetAndPopulate(nsXPTType::T_U16, type,
|
||||
if (!CheckTargetAndPopulate(cx, nsXPTType::T_U16, type,
|
||||
sizeof(uint16_t), count,
|
||||
jsArray, &output, pErr)) {
|
||||
return false;
|
||||
@ -1585,7 +1587,7 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
break;
|
||||
|
||||
case js::ArrayBufferView::TYPE_INT32:
|
||||
if (!CheckTargetAndPopulate(nsXPTType::T_I32, type,
|
||||
if (!CheckTargetAndPopulate(cx, nsXPTType::T_I32, type,
|
||||
sizeof(int32_t), count,
|
||||
jsArray, &output, pErr)) {
|
||||
return false;
|
||||
@ -1593,7 +1595,7 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
break;
|
||||
|
||||
case js::ArrayBufferView::TYPE_UINT32:
|
||||
if (!CheckTargetAndPopulate(nsXPTType::T_U32, type,
|
||||
if (!CheckTargetAndPopulate(cx, nsXPTType::T_U32, type,
|
||||
sizeof(uint32_t), count,
|
||||
jsArray, &output, pErr)) {
|
||||
return false;
|
||||
@ -1601,7 +1603,7 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
break;
|
||||
|
||||
case js::ArrayBufferView::TYPE_FLOAT32:
|
||||
if (!CheckTargetAndPopulate(nsXPTType::T_FLOAT, type,
|
||||
if (!CheckTargetAndPopulate(cx, nsXPTType::T_FLOAT, type,
|
||||
sizeof(float), count,
|
||||
jsArray, &output, pErr)) {
|
||||
return false;
|
||||
@ -1609,7 +1611,7 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
break;
|
||||
|
||||
case js::ArrayBufferView::TYPE_FLOAT64:
|
||||
if (!CheckTargetAndPopulate(nsXPTType::T_DOUBLE, type,
|
||||
if (!CheckTargetAndPopulate(cx, nsXPTType::T_DOUBLE, type,
|
||||
sizeof(double), count,
|
||||
jsArray, &output, pErr)) {
|
||||
return false;
|
||||
@ -1663,8 +1665,8 @@ XPCConvert::JSArray2Native(JSContext* cx, void** d, JS::Value s,
|
||||
JSObject* jsarray = &s.toObject();
|
||||
|
||||
// If this is a typed array, then try a fast conversion with memcpy.
|
||||
if (JS_IsTypedArrayObject(jsarray)) {
|
||||
return JSTypedArray2Native(d, jsarray, count, type, pErr);
|
||||
if (JS_IsTypedArrayObject(jsarray, cx)) {
|
||||
return JSTypedArray2Native(cx, d, jsarray, count, type, pErr);
|
||||
}
|
||||
|
||||
if (!JS_IsArrayObject(cx, jsarray)) {
|
||||
|
@ -3368,7 +3368,8 @@ public:
|
||||
uint32_t count, const nsXPTType& type,
|
||||
const nsID* iid, nsresult* pErr);
|
||||
|
||||
static JSBool JSTypedArray2Native(void** d,
|
||||
static JSBool JSTypedArray2Native(JSContext* cx,
|
||||
void** d,
|
||||
JSObject* jsarray,
|
||||
uint32_t count,
|
||||
const nsXPTType& type,
|
||||
|
@ -231,6 +231,11 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapper, jsid
|
||||
|
||||
JSObject *obj = Wrapper::wrappedObject(wrapper);
|
||||
|
||||
// PUNCTURE Is always denied for cross-origin access.
|
||||
if (act == Wrapper::PUNCTURE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *name;
|
||||
js::Class *clasp = js::GetObjectClass(obj);
|
||||
NS_ASSERTION(Jsvalify(clasp) != &XrayUtils::HolderClass, "shouldn't have a holder here");
|
||||
@ -340,6 +345,9 @@ ExposedPropertiesOnly::check(JSContext *cx, JSObject *wrapper, jsid id, Wrapper:
|
||||
if (act == Wrapper::CALL)
|
||||
return true;
|
||||
|
||||
if (act == Wrapper::PUNCTURE)
|
||||
return false;
|
||||
|
||||
jsid exposedPropsId = GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS);
|
||||
|
||||
// We need to enter the wrappee's compartment to look at __exposedProps__,
|
||||
@ -354,7 +362,7 @@ ExposedPropertiesOnly::check(JSContext *cx, JSObject *wrapper, jsid id, Wrapper:
|
||||
|
||||
// Always permit access to "length" and indexed properties of arrays.
|
||||
if ((JS_IsArrayObject(cx, wrappedObject) ||
|
||||
JS_IsTypedArrayObject(wrappedObject)) &&
|
||||
JS_IsTypedArrayObject(wrappedObject, cx)) &&
|
||||
((JSID_IS_INT(id) && JSID_TO_INT(id) >= 0) ||
|
||||
(JSID_IS_STRING(id) && JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), "length")))) {
|
||||
return true; // Allow
|
||||
|
@ -96,7 +96,9 @@ struct LocationPolicy : public Policy {
|
||||
// We should only be dealing with Location objects here.
|
||||
MOZ_ASSERT(WrapperFactory::IsLocationObject(js::UnwrapObject(wrapper)));
|
||||
|
||||
if ((AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, act) ||
|
||||
// Location object security is complicated enough. Don't allow punctures.
|
||||
if (act != js::Wrapper::PUNCTURE &&
|
||||
(AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, act) ||
|
||||
AccessCheck::isLocationObjectSameOrigin(cx, wrapper))) {
|
||||
return true;
|
||||
}
|
||||
|
@ -133,13 +133,20 @@ FilteringWrapper<Base, Policy>::enter(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
|
||||
#define SOW FilteringWrapper<CrossCompartmentSecurityWrapper, OnlyIfSubjectIsSystem>
|
||||
#define SCSOW FilteringWrapper<SameCompartmentSecurityWrapper, OnlyIfSubjectIsSystem>
|
||||
#define XOW FilteringWrapper<SecurityXrayXPCWN, CrossOriginAccessiblePropertiesOnly>
|
||||
#define DXOW FilteringWrapper<SecurityXrayDOM, CrossOriginAccessiblePropertiesOnly>
|
||||
#define NNXOW FilteringWrapper<CrossCompartmentSecurityWrapper, CrossOriginAccessiblePropertiesOnly>
|
||||
#define LW FilteringWrapper<SCSecurityXrayXPCWN, LocationPolicy>
|
||||
#define XLW FilteringWrapper<SecurityXrayXPCWN, LocationPolicy>
|
||||
#define CW FilteringWrapper<SameCompartmentSecurityWrapper, ComponentsObjectPolicy>
|
||||
#define XCW FilteringWrapper<CrossCompartmentSecurityWrapper, ComponentsObjectPolicy>
|
||||
#define XOW FilteringWrapper<XrayWrapper<CrossCompartmentSecurityWrapper>, \
|
||||
CrossOriginAccessiblePropertiesOnly>
|
||||
#define DXOW FilteringWrapper<XrayDOM, \
|
||||
CrossOriginAccessiblePropertiesOnly>
|
||||
#define NNXOW FilteringWrapper<CrossCompartmentSecurityWrapper, \
|
||||
CrossOriginAccessiblePropertiesOnly>
|
||||
#define LW FilteringWrapper<XrayWrapper<SameCompartmentSecurityWrapper>, \
|
||||
LocationPolicy>
|
||||
#define XLW FilteringWrapper<XrayWrapper<CrossCompartmentSecurityWrapper>, \
|
||||
LocationPolicy>
|
||||
#define CW FilteringWrapper<SameCompartmentSecurityWrapper, \
|
||||
ComponentsObjectPolicy>
|
||||
#define XCW FilteringWrapper<CrossCompartmentSecurityWrapper, \
|
||||
ComponentsObjectPolicy>
|
||||
template<> SOW SOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
|
||||
WrapperFactory::SOW_FLAG);
|
||||
template<> SCSOW SCSOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
|
||||
|
@ -291,31 +291,6 @@ GetWrappedNative(JSContext *cx, JSObject *obj)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
DEBUG_CheckUnwrapSafety(JSObject *obj, js::Wrapper *handler,
|
||||
JSCompartment *origin, JSCompartment *target)
|
||||
{
|
||||
typedef FilteringWrapper<CrossCompartmentSecurityWrapper, OnlyIfSubjectIsSystem> XSOW;
|
||||
|
||||
if (AccessCheck::isChrome(target) || xpc::IsUniversalXPConnectEnabled(target)) {
|
||||
// If the caller is chrome (or effectively so), unwrap should always be allowed.
|
||||
MOZ_ASSERT(handler->isSafeToUnwrap());
|
||||
} else if (WrapperFactory::IsLocationObject(obj) ||
|
||||
WrapperFactory::IsComponentsObject(obj) ||
|
||||
handler == &XSOW::singleton)
|
||||
{
|
||||
// This is an object that is restricted regardless of origin.
|
||||
MOZ_ASSERT(!handler->isSafeToUnwrap());
|
||||
} else {
|
||||
// Otherwise, it should depend on whether the target subsumes the origin.
|
||||
MOZ_ASSERT(handler->isSafeToUnwrap() == AccessCheck::subsumes(target, origin));
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DEBUG_CheckUnwrapSafety(obj, handler, origin, target) {}
|
||||
#endif
|
||||
|
||||
JSObject *
|
||||
WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
|
||||
JSObject *wrappedProto, JSObject *parent,
|
||||
@ -348,9 +323,10 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
|
||||
// Native objects must be wrapped into an X-ray wrapper.
|
||||
XrayType type = GetXrayType(obj);
|
||||
if (type == XrayForDOMObject) {
|
||||
wrapper = &PermissiveXrayDOM::singleton;
|
||||
wrapper = &XrayDOM::singleton;
|
||||
} else if (type == XrayForWrappedNative) {
|
||||
wrapper = &PermissiveXrayXPCWN::singleton;
|
||||
typedef XrayWrapper<CrossCompartmentWrapper> Xray;
|
||||
wrapper = &Xray::singleton;
|
||||
} else {
|
||||
wrapper = &CrossCompartmentWrapper::singleton;
|
||||
}
|
||||
@ -371,12 +347,13 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
|
||||
if (targetdata &&
|
||||
(wn = GetWrappedNative(cx, obj)) &&
|
||||
wn->HasProto() && wn->GetProto()->ClassIsDOMObject()) {
|
||||
typedef XrayWrapper<CrossCompartmentSecurityWrapper> Xray;
|
||||
if (IsLocationObject(obj))
|
||||
wrapper = &FilteringWrapper<SecurityXrayXPCWN, LocationPolicy>::singleton;
|
||||
wrapper = &FilteringWrapper<Xray, LocationPolicy>::singleton;
|
||||
else
|
||||
wrapper = &FilteringWrapper<SecurityXrayXPCWN, CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
wrapper = &FilteringWrapper<Xray, CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
} else if (mozilla::dom::UseDOMXray(obj)) {
|
||||
wrapper = &FilteringWrapper<SecurityXrayDOM, CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
wrapper = &FilteringWrapper<XrayDOM, CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
} else if (IsComponentsObject(obj)) {
|
||||
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
|
||||
ComponentsObjectPolicy>::singleton;
|
||||
@ -431,7 +408,8 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
|
||||
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
|
||||
OnlyIfSubjectIsSystem>::singleton;
|
||||
} else if (IsLocationObject(obj)) {
|
||||
wrapper = &FilteringWrapper<SecurityXrayXPCWN, LocationPolicy>::singleton;
|
||||
typedef XrayWrapper<CrossCompartmentSecurityWrapper> Xray;
|
||||
wrapper = &FilteringWrapper<Xray, LocationPolicy>::singleton;
|
||||
} else if (IsComponentsObject(obj)) {
|
||||
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
|
||||
ComponentsObjectPolicy>::singleton;
|
||||
@ -439,9 +417,10 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
|
||||
(type = GetXrayType(obj)) == NotXray) {
|
||||
wrapper = &CrossCompartmentWrapper::singleton;
|
||||
} else if (type == XrayForDOMObject) {
|
||||
wrapper = &PermissiveXrayDOM::singleton;
|
||||
wrapper = &XrayDOM::singleton;
|
||||
} else {
|
||||
wrapper = &PermissiveXrayXPCWN::singleton;
|
||||
typedef XrayWrapper<CrossCompartmentWrapper> Xray;
|
||||
wrapper = &Xray::singleton;
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(!AccessCheck::needsSystemOnlyWrapper(obj),
|
||||
@ -454,22 +433,22 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
|
||||
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
|
||||
CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
} else if (type == XrayForDOMObject) {
|
||||
wrapper = &FilteringWrapper<SecurityXrayDOM,
|
||||
wrapper = &FilteringWrapper<XrayDOM,
|
||||
CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
} else {
|
||||
typedef XrayWrapper<CrossCompartmentSecurityWrapper> Xray;
|
||||
|
||||
// Location objects can become same origin after navigation, so we might
|
||||
// have to grant transparent access later on.
|
||||
if (IsLocationObject(obj)) {
|
||||
wrapper = &FilteringWrapper<SecurityXrayXPCWN, LocationPolicy>::singleton;
|
||||
wrapper = &FilteringWrapper<Xray, LocationPolicy>::singleton;
|
||||
} else {
|
||||
wrapper = &FilteringWrapper<SecurityXrayXPCWN,
|
||||
CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
wrapper = &FilteringWrapper<Xray,
|
||||
CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_CheckUnwrapSafety(obj, wrapper, origin, target);
|
||||
|
||||
if (existing && proxyProto == wrappedProto)
|
||||
return Wrapper::Renew(cx, existing, obj, wrapper);
|
||||
|
||||
@ -492,11 +471,11 @@ WrapperFactory::WrapForSameCompartment(JSContext *cx, JSObject *obj)
|
||||
MOZ_ASSERT(wn, "Trying to wrap a dead WN!");
|
||||
|
||||
// The WN knows what to do.
|
||||
JSObject *wrapper = wn->GetSameCompartmentSecurityWrapper(cx);
|
||||
MOZ_ASSERT_IF(wrapper != obj, !Wrapper::wrapperHandler(wrapper)->isSafeToUnwrap());
|
||||
return wrapper;
|
||||
return wn->GetSameCompartmentSecurityWrapper(cx);
|
||||
}
|
||||
|
||||
typedef FilteringWrapper<XrayWrapper<SameCompartmentSecurityWrapper>, LocationPolicy> LW;
|
||||
|
||||
bool
|
||||
WrapperFactory::IsLocationObject(JSObject *obj)
|
||||
{
|
||||
@ -510,8 +489,7 @@ WrapperFactory::WrapLocationObject(JSContext *cx, JSObject *obj)
|
||||
JSObject *proto;
|
||||
if (!js::GetObjectProto(cx, obj, &proto))
|
||||
return nullptr;
|
||||
return Wrapper::New(cx, obj, proto, js::GetObjectParent(obj),
|
||||
&FilteringWrapper<SCSecurityXrayXPCWN, LocationPolicy>::singleton);
|
||||
return Wrapper::New(cx, obj, proto, js::GetObjectParent(obj), &LW::singleton);
|
||||
}
|
||||
|
||||
// Call WaiveXrayAndWrap when you have a JS object that you don't want to be
|
||||
@ -586,9 +564,9 @@ WrapperFactory::WrapForSameCompartmentXray(JSContext *cx, JSObject *obj)
|
||||
// Select the appropriate proxy handler.
|
||||
Wrapper *wrapper = NULL;
|
||||
if (type == XrayForWrappedNative)
|
||||
wrapper = &SCPermissiveXrayXPCWN::singleton;
|
||||
wrapper = &XrayWrapper<Wrapper>::singleton;
|
||||
else if (type == XrayForDOMObject)
|
||||
wrapper = &SCPermissiveXrayDOM::singleton;
|
||||
wrapper = &XrayWrapper<Wrapper, DOMXrayTraits>::singleton;
|
||||
else
|
||||
MOZ_NOT_REACHED("Bad Xray type");
|
||||
|
||||
|
@ -1702,26 +1702,37 @@ XrayWrapper<Base, Traits>::construct(JSContext *cx, JSObject *wrapper, unsigned
|
||||
return Traits::construct(cx, wrapper, argc, argv, rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Permissive / Security variants should be used depending on whether the
|
||||
* compartment of the wrapper is guranteed to subsume the compartment of the
|
||||
* wrapped object (i.e. - whether it is safe from a security perspective to
|
||||
* unwrap the wrapper).
|
||||
*/
|
||||
|
||||
template<>
|
||||
PermissiveXrayXPCWN PermissiveXrayXPCWN::singleton(0);
|
||||
template<>
|
||||
SecurityXrayXPCWN SecurityXrayXPCWN::singleton(0);
|
||||
template<>
|
||||
PermissiveXrayDOM PermissiveXrayDOM::singleton(0);
|
||||
template<>
|
||||
SecurityXrayDOM SecurityXrayDOM::singleton(0);
|
||||
template<>
|
||||
SCPermissiveXrayXPCWN SCPermissiveXrayXPCWN::singleton(0);
|
||||
template<>
|
||||
SCSecurityXrayXPCWN SCSecurityXrayXPCWN::singleton(0);
|
||||
template<>
|
||||
SCPermissiveXrayDOM SCPermissiveXrayDOM::singleton(0);
|
||||
#define XRAY XrayWrapper<CrossCompartmentSecurityWrapper, XPCWrappedNativeXrayTraits >
|
||||
template <> XRAY XRAY::singleton(0);
|
||||
template class XRAY;
|
||||
#undef XRAY
|
||||
|
||||
#define XRAY XrayWrapper<SameCompartmentSecurityWrapper, XPCWrappedNativeXrayTraits >
|
||||
template <> XRAY XRAY::singleton(0);
|
||||
template class XRAY;
|
||||
#undef XRAY
|
||||
|
||||
#define XRAY XrayWrapper<CrossCompartmentWrapper, XPCWrappedNativeXrayTraits >
|
||||
template <> XRAY XRAY::singleton(0);
|
||||
template class XRAY;
|
||||
#undef XRAY
|
||||
|
||||
#define XRAY XrayWrapper<CrossCompartmentWrapper, DOMXrayTraits >
|
||||
template <> XRAY XRAY::singleton(0);
|
||||
template class XRAY;
|
||||
#undef XRAY
|
||||
|
||||
/* Same-compartment non-filtering versions. */
|
||||
|
||||
#define XRAY XrayWrapper<Wrapper, XPCWrappedNativeXrayTraits >
|
||||
template <> XRAY XRAY::singleton(0);
|
||||
template class XRAY;
|
||||
#undef XRAY
|
||||
|
||||
#define XRAY XrayWrapper<Wrapper, DOMXrayTraits >
|
||||
template <> XRAY XRAY::singleton(0);
|
||||
template class XRAY;
|
||||
#undef XRAY
|
||||
|
||||
}
|
||||
|
@ -93,13 +93,7 @@ class XrayWrapper : public Base {
|
||||
JS::AutoIdVector &props);
|
||||
};
|
||||
|
||||
typedef XrayWrapper<js::CrossCompartmentWrapper, XPCWrappedNativeXrayTraits > PermissiveXrayXPCWN;
|
||||
typedef XrayWrapper<js::CrossCompartmentSecurityWrapper, XPCWrappedNativeXrayTraits > SecurityXrayXPCWN;
|
||||
typedef XrayWrapper<js::CrossCompartmentWrapper, DOMXrayTraits > PermissiveXrayDOM;
|
||||
typedef XrayWrapper<js::CrossCompartmentSecurityWrapper, DOMXrayTraits > SecurityXrayDOM;
|
||||
typedef XrayWrapper<js::SameCompartmentSecurityWrapper, XPCWrappedNativeXrayTraits > SCSecurityXrayXPCWN;
|
||||
typedef XrayWrapper<js::Wrapper, XPCWrappedNativeXrayTraits > SCPermissiveXrayXPCWN;
|
||||
typedef XrayWrapper<js::Wrapper, DOMXrayTraits > SCPermissiveXrayDOM;
|
||||
typedef XrayWrapper<js::CrossCompartmentWrapper, DOMXrayTraits > XrayDOM;
|
||||
|
||||
class SandboxProxyHandler : public js::Wrapper {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user