Bug 1176214 - Part 11: Changes to DOM, except for WebGL. r=bz, r=clb

This commit is contained in:
Lars T Hansen 2015-11-25 19:04:50 +01:00
parent fe75937491
commit 24ab5fa8d9
19 changed files with 189 additions and 183 deletions

View File

@ -62,6 +62,12 @@ Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
JS::Rooted<JSObject*> view(aCx, aArray.Obj());
if (JS_IsTypedArrayObject(view) && JS_GetTypedArraySharedness(view)) {
// Throw if the object is mapping shared memory (must opt in).
aRv.ThrowTypeError<MSG_TYPEDARRAY_IS_SHARED>(NS_LITERAL_STRING("Argument of Crypto.getRandomValues"));
return;
}
// Throw if the wrong type of ArrayBufferView is passed in
// (Part of the Web Crypto API spec)
switch (JS_GetArrayBufferViewType(view)) {

View File

@ -6150,7 +6150,9 @@ nsContentUtils::CreateArrayBuffer(JSContext *aCx, const nsACString& aData,
if (dataLen > 0) {
NS_ASSERTION(JS_IsArrayBufferObject(*aResult), "What happened?");
JS::AutoCheckCannotGC nogc;
memcpy(JS_GetArrayBufferData(*aResult, nogc), aData.BeginReading(), dataLen);
bool isShared;
memcpy(JS_GetArrayBufferData(*aResult, &isShared, nogc), aData.BeginReading(), dataLen);
MOZ_ASSERT(!isShared);
}
return NS_OK;

View File

@ -91,3 +91,4 @@ MSG_DEF(MSG_PROMISE_ARG_NOT_ITERABLE, 1, JSEXN_TYPEERR, "{0} is not iterable")
MSG_DEF(MSG_IS_NOT_PROMISE, 1, JSEXN_TYPEERR, "{0} is not a Promise")
MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")

View File

@ -64,13 +64,14 @@ private:
*/
template<typename T,
JSObject* UnwrapArray(JSObject*),
void GetLengthAndData(JSObject*, uint32_t*, T**)>
void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*, T**)>
struct TypedArray_base : public TypedArrayObjectStorage {
typedef T element_type;
TypedArray_base()
: mData(nullptr),
mLength(0),
mShared(false),
mComputed(false)
{
}
@ -79,16 +80,19 @@ struct TypedArray_base : public TypedArrayObjectStorage {
: TypedArrayObjectStorage(Move(aOther)),
mData(aOther.mData),
mLength(aOther.mLength),
mShared(aOther.mShared),
mComputed(aOther.mComputed)
{
aOther.mData = nullptr;
aOther.mLength = 0;
aOther.mShared = false;
aOther.mComputed = false;
}
private:
mutable T* mData;
mutable uint32_t mLength;
mutable bool mShared;
mutable bool mComputed;
public:
@ -103,12 +107,73 @@ public:
return !!mTypedObj;
}
// About shared memory:
//
// Any DOM TypedArray as well as any DOM ArrayBufferView that does
// not represent a JS DataView can map the memory of either a JS
// ArrayBuffer or a JS SharedArrayBuffer. (DataView cannot view
// shared memory.) If the TypedArray maps a SharedArrayBuffer the
// Length() and Data() accessors on the DOM view will return zero
// and nullptr; to get the actual length and data, call the
// LengthAllowShared() and DataAllowShared() accessors instead.
//
// Two methods are available for determining if a DOM view maps
// shared memory. The IsShared() method is cheap and can be called
// if the view has been computed; the JS_GetTypedArraySharedness()
// method is slightly more expensive and can be called on the Obj()
// value if the view may not have been computed and if the value is
// known to represent a JS TypedArray.
//
// (Just use JS_IsSharedArrayBuffer() to test if any object is of
// that type.)
//
// Code that elects to allow views that map shared memory to be used
// -- ie, code that "opts in to shared memory" -- should generally
// not access the raw data buffer with standard C++ mechanisms as
// that creates the possibility of C++ data races, which is
// undefined behavior. The JS engine will eventually export (bug
// 1225033) a suite of methods that avoid undefined behavior.
//
// Callers of Obj() that do not opt in to shared memory can produce
// better diagnostics by checking whether the JSObject in fact maps
// shared memory and throwing an error if it does. However, it is
// safe to use the value of Obj() without such checks.
//
// The DOM TypedArray abstraction prevents the underlying buffer object
// from being accessed directly, but JS_GetArrayBufferViewBuffer(Obj())
// will obtain the buffer object. Code that calls that function must
// not assume the returned buffer is an ArrayBuffer. That is guarded
// against by an out parameter on that call that communicates the
// sharedness of the buffer.
//
// Finally, note that the buffer memory of a SharedArrayBuffer is
// not detachable.
inline bool IsShared() const {
MOZ_ASSERT(mComputed);
return mShared;
}
inline T *Data() const {
MOZ_ASSERT(mComputed);
if (mShared)
return nullptr;
return mData;
}
inline T *DataAllowShared() const {
MOZ_ASSERT(mComputed);
return mData;
}
inline uint32_t Length() const {
MOZ_ASSERT(mComputed);
if (mShared)
return 0;
return mLength;
}
inline uint32_t LengthAllowShared() const {
MOZ_ASSERT(mComputed);
return mLength;
}
@ -128,7 +193,7 @@ public:
{
MOZ_ASSERT(inited());
MOZ_ASSERT(!mComputed);
GetLengthAndData(mTypedObj, &mLength, &mData);
GetLengthAndDataAndSharedness(mTypedObj, &mLength, &mShared, &mData);
mComputed = true;
}
@ -138,12 +203,14 @@ private:
template<typename T,
JSObject* UnwrapArray(JSObject*),
T* GetData(JSObject*, const JS::AutoCheckCannotGC&),
void GetLengthAndData(JSObject*, uint32_t*, T**),
T* GetData(JSObject*, bool* isShared, const JS::AutoCheckCannotGC&),
void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*, T**),
JSObject* CreateNew(JSContext*, uint32_t)>
struct TypedArray : public TypedArray_base<T, UnwrapArray, GetLengthAndData> {
struct TypedArray
: public TypedArray_base<T, UnwrapArray, GetLengthAndDataAndSharedness>
{
private:
typedef TypedArray_base<T, UnwrapArray, GetLengthAndData> Base;
typedef TypedArray_base<T, UnwrapArray, GetLengthAndDataAndSharedness> Base;
public:
TypedArray()
@ -181,7 +248,11 @@ private:
}
if (data) {
JS::AutoCheckCannotGC nogc;
T* buf = static_cast<T*>(GetData(obj, nogc));
bool isShared;
T* buf = static_cast<T*>(GetData(obj, &isShared, nogc));
// Data will not be shared, until a construction protocol exists
// for constructing shared data.
MOZ_ASSERT(!isShared);
memcpy(buf, data, length*sizeof(T));
}
return obj;
@ -191,12 +262,15 @@ private:
};
template<JSObject* UnwrapArray(JSObject*),
void GetLengthAndData(JSObject*, uint32_t*, uint8_t**),
void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*,
uint8_t**),
js::Scalar::Type GetViewType(JSObject*)>
struct ArrayBufferView_base : public TypedArray_base<uint8_t, UnwrapArray,
GetLengthAndData> {
struct ArrayBufferView_base
: public TypedArray_base<uint8_t, UnwrapArray, GetLengthAndDataAndSharedness>
{
private:
typedef TypedArray_base<uint8_t, UnwrapArray, GetLengthAndData> Base;
typedef TypedArray_base<uint8_t, UnwrapArray, GetLengthAndDataAndSharedness>
Base;
public:
ArrayBufferView_base()
@ -267,37 +341,6 @@ typedef TypedArray<uint8_t, js::UnwrapArrayBuffer, JS_GetArrayBufferData,
js::GetArrayBufferLengthAndData, JS_NewArrayBuffer>
ArrayBuffer;
typedef TypedArray<int8_t, js::UnwrapSharedInt8Array, JS_GetSharedInt8ArrayData,
js::GetSharedInt8ArrayLengthAndData, JS_NewSharedInt8Array>
SharedInt8Array;
typedef TypedArray<uint8_t, js::UnwrapSharedUint8Array, JS_GetSharedUint8ArrayData,
js::GetSharedUint8ArrayLengthAndData, JS_NewSharedUint8Array>
SharedUint8Array;
typedef TypedArray<uint8_t, js::UnwrapSharedUint8ClampedArray, JS_GetSharedUint8ClampedArrayData,
js::GetSharedUint8ClampedArrayLengthAndData, JS_NewSharedUint8ClampedArray>
SharedUint8ClampedArray;
typedef TypedArray<int16_t, js::UnwrapSharedInt16Array, JS_GetSharedInt16ArrayData,
js::GetSharedInt16ArrayLengthAndData, JS_NewSharedInt16Array>
SharedInt16Array;
typedef TypedArray<uint16_t, js::UnwrapSharedUint16Array, JS_GetSharedUint16ArrayData,
js::GetSharedUint16ArrayLengthAndData, JS_NewSharedUint16Array>
SharedUint16Array;
typedef TypedArray<int32_t, js::UnwrapSharedInt32Array, JS_GetSharedInt32ArrayData,
js::GetSharedInt32ArrayLengthAndData, JS_NewSharedInt32Array>
SharedInt32Array;
typedef TypedArray<uint32_t, js::UnwrapSharedUint32Array, JS_GetSharedUint32ArrayData,
js::GetSharedUint32ArrayLengthAndData, JS_NewSharedUint32Array>
SharedUint32Array;
typedef TypedArray<float, js::UnwrapSharedFloat32Array, JS_GetSharedFloat32ArrayData,
js::GetSharedFloat32ArrayLengthAndData, JS_NewSharedFloat32Array>
SharedFloat32Array;
typedef TypedArray<double, js::UnwrapSharedFloat64Array, JS_GetSharedFloat64ArrayData,
js::GetSharedFloat64ArrayLengthAndData, JS_NewSharedFloat64Array>
SharedFloat64Array;
typedef ArrayBufferView_base<js::UnwrapSharedArrayBufferView,
js::GetSharedArrayBufferViewLengthAndData,
JS_GetSharedArrayBufferViewType>
SharedArrayBufferView;
typedef TypedArray<uint8_t, js::UnwrapSharedArrayBuffer, JS_GetSharedArrayBufferData,
js::GetSharedArrayBufferLengthAndData, JS_NewSharedArrayBuffer>
SharedArrayBuffer;

View File

@ -1834,15 +1834,9 @@ class IDLType(IDLObject):
def isSharedArrayBuffer(self):
return False
def isSharedArrayBufferView(self):
return False
def isTypedArray(self):
return False
def isSharedTypedArray(self):
return False
def isCallbackInterface(self):
return False
@ -1863,9 +1857,7 @@ class IDLType(IDLObject):
return self.isInterface() and (self.isArrayBuffer() or
self.isArrayBufferView() or
self.isSharedArrayBuffer() or
self.isSharedArrayBufferView() or
self.isTypedArray() or
self.isSharedTypedArray())
self.isTypedArray())
def isDictionary(self):
return False
@ -2052,15 +2044,9 @@ class IDLNullableType(IDLType):
def isSharedArrayBuffer(self):
return self.inner.isSharedArrayBuffer()
def isSharedArrayBufferView(self):
return self.inner.isSharedArrayBufferView()
def isTypedArray(self):
return self.inner.isTypedArray()
def isSharedTypedArray(self):
return self.inner.isSharedTypedArray()
def isDictionary(self):
return self.inner.isDictionary()
@ -2567,15 +2553,9 @@ class IDLTypedefType(IDLType):
def isSharedArrayBuffer(self):
return self.inner.isSharedArrayBuffer()
def isSharedArrayBufferView(self):
return self.inner.isSharedArrayBufferView()
def isTypedArray(self):
return self.inner.isTypedArray()
def isSharedTypedArray(self):
return self.inner.isSharedTypedArray()
def isInterface(self):
return self.inner.isInterface()
@ -2845,7 +2825,6 @@ class IDLBuiltinType(IDLType):
'ArrayBuffer',
'ArrayBufferView',
'SharedArrayBuffer',
'SharedArrayBufferView',
'Int8Array',
'Uint8Array',
'Uint8ClampedArray',
@ -2854,16 +2833,7 @@ class IDLBuiltinType(IDLType):
'Int32Array',
'Uint32Array',
'Float32Array',
'Float64Array',
'SharedInt8Array',
'SharedUint8Array',
'SharedUint8ClampedArray',
'SharedInt16Array',
'SharedUint16Array',
'SharedInt32Array',
'SharedUint32Array',
'SharedFloat32Array',
'SharedFloat64Array'
'Float64Array'
)
TagLookup = {
@ -2890,7 +2860,6 @@ class IDLBuiltinType(IDLType):
Types.ArrayBuffer: IDLType.Tags.interface,
Types.ArrayBufferView: IDLType.Tags.interface,
Types.SharedArrayBuffer: IDLType.Tags.interface,
Types.SharedArrayBufferView: IDLType.Tags.interface,
Types.Int8Array: IDLType.Tags.interface,
Types.Uint8Array: IDLType.Tags.interface,
Types.Uint8ClampedArray: IDLType.Tags.interface,
@ -2899,16 +2868,7 @@ class IDLBuiltinType(IDLType):
Types.Int32Array: IDLType.Tags.interface,
Types.Uint32Array: IDLType.Tags.interface,
Types.Float32Array: IDLType.Tags.interface,
Types.Float64Array: IDLType.Tags.interface,
Types.SharedInt8Array: IDLType.Tags.interface,
Types.SharedUint8Array: IDLType.Tags.interface,
Types.SharedUint8ClampedArray: IDLType.Tags.interface,
Types.SharedInt16Array: IDLType.Tags.interface,
Types.SharedUint16Array: IDLType.Tags.interface,
Types.SharedInt32Array: IDLType.Tags.interface,
Types.SharedUint32Array: IDLType.Tags.interface,
Types.SharedFloat32Array: IDLType.Tags.interface,
Types.SharedFloat64Array: IDLType.Tags.interface
Types.Float64Array: IDLType.Tags.interface
}
def __init__(self, location, name, type):
@ -2951,17 +2911,10 @@ class IDLBuiltinType(IDLType):
def isSharedArrayBuffer(self):
return self._typeTag == IDLBuiltinType.Types.SharedArrayBuffer
def isSharedArrayBufferView(self):
return self._typeTag == IDLBuiltinType.Types.SharedArrayBufferView
def isTypedArray(self):
return (self._typeTag >= IDLBuiltinType.Types.Int8Array and
self._typeTag <= IDLBuiltinType.Types.Float64Array)
def isSharedTypedArray(self):
return (self._typeTag >= IDLBuiltinType.Types.SharedInt8Array and
self._typeTag <= IDLBuiltinType.Types.SharedFloat64Array)
def isInterface(self):
# TypedArray things are interface types per the TypedArray spec,
# but we handle them as builtins because SpiderMonkey implements
@ -2969,9 +2922,7 @@ class IDLBuiltinType(IDLType):
return (self.isArrayBuffer() or
self.isArrayBufferView() or
self.isSharedArrayBuffer() or
self.isSharedArrayBufferView() or
self.isTypedArray() or
self.isSharedTypedArray())
self.isTypedArray())
def isNonCallbackInterface(self):
# All the interfaces we can be are non-callback
@ -3049,15 +3000,11 @@ class IDLBuiltinType(IDLType):
# that's not an ArrayBufferView or typed array.
(self.isArrayBufferView() and not other.isArrayBufferView() and
not other.isTypedArray()) or
(self.isSharedArrayBufferView() and not other.isSharedArrayBufferView() and
not other.isSharedTypedArray()) or
# Typed arrays are distinguishable from everything
# except ArrayBufferView and the same type of typed
# array
(self.isTypedArray() and not other.isArrayBufferView() and not
(other.isTypedArray() and other.name == self.name)) or
(self.isSharedTypedArray() and not other.isSharedArrayBufferView() and not
(other.isSharedTypedArray() and other.name == self.name)))))
(other.isTypedArray() and other.name == self.name)))))
def _getDependentObjects(self):
return set()
@ -3132,9 +3079,6 @@ BuiltinTypes = {
IDLBuiltinType.Types.SharedArrayBuffer:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBuffer",
IDLBuiltinType.Types.SharedArrayBuffer),
IDLBuiltinType.Types.SharedArrayBufferView:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBufferView",
IDLBuiltinType.Types.SharedArrayBufferView),
IDLBuiltinType.Types.Int8Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array",
IDLBuiltinType.Types.Int8Array),
@ -3161,34 +3105,7 @@ BuiltinTypes = {
IDLBuiltinType.Types.Float32Array),
IDLBuiltinType.Types.Float64Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array",
IDLBuiltinType.Types.Float64Array),
IDLBuiltinType.Types.SharedInt8Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedInt8Array",
IDLBuiltinType.Types.SharedInt8Array),
IDLBuiltinType.Types.SharedUint8Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedUint8Array",
IDLBuiltinType.Types.SharedUint8Array),
IDLBuiltinType.Types.SharedUint8ClampedArray:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedUint8ClampedArray",
IDLBuiltinType.Types.SharedUint8ClampedArray),
IDLBuiltinType.Types.SharedInt16Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedInt16Array",
IDLBuiltinType.Types.SharedInt16Array),
IDLBuiltinType.Types.SharedUint16Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedUint16Array",
IDLBuiltinType.Types.SharedUint16Array),
IDLBuiltinType.Types.SharedInt32Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedInt32Array",
IDLBuiltinType.Types.SharedInt32Array),
IDLBuiltinType.Types.SharedUint32Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedUint32Array",
IDLBuiltinType.Types.SharedUint32Array),
IDLBuiltinType.Types.SharedFloat32Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedFloat32Array",
IDLBuiltinType.Types.SharedFloat32Array),
IDLBuiltinType.Types.SharedFloat64Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedFloat64Array",
IDLBuiltinType.Types.SharedFloat64Array)
IDLBuiltinType.Types.Float64Array)
}
@ -6531,7 +6448,7 @@ class Parser(Tokenizer):
assert isinstance(scope, IDLScope)
# xrange omits the last value.
for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.SharedFloat64Array + 1):
for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
builtin = BuiltinTypes[x]
name = builtin.name
typedef = IDLTypedef(BuiltinLocation("<builtin type>"), scope, builtin, name)
@ -6634,7 +6551,6 @@ class Parser(Tokenizer):
_builtins = """
typedef unsigned long long DOMTimeStamp;
typedef (ArrayBufferView or ArrayBuffer) BufferSource;
typedef (SharedArrayBufferView or SharedArrayBuffer) SharedBufferSource;
"""

View File

@ -161,8 +161,8 @@ def WebIDLTest(parser, harness):
"MozMap<object>", "MozMap<Dict>", "MozMap<long>",
"long[]", "short[]", "Date", "Date?", "any",
"Promise<any>", "Promise<any>?",
"USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer", "SharedArrayBufferView",
"Uint8Array", "SharedUint8Array", "Uint16Array", "SharedUint16Array" ]
"USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
"Uint8Array", "Uint16Array" ]
# When we can parse Date and RegExp, we need to add them here.
# Try to categorize things a bit to keep list lengths down
@ -179,7 +179,7 @@ def WebIDLTest(parser, harness):
nonObjects = primitives + strings
objects = allBut(argTypes, nonObjects )
bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"]
sharedBufferSourceTypes = ["SharedArrayBuffer", "SharedArrayBufferView", "SharedUint8Array", "SharedUint16Array"]
sharedBufferSourceTypes = ["SharedArrayBuffer"]
interfaces = [ "Interface", "Interface?", "AncestorInterface",
"UnrelatedInterface", "ImplementedInterface" ] + bufferSourceTypes + sharedBufferSourceTypes
nullables = ["long?", "short?", "boolean?", "Interface?",
@ -247,9 +247,6 @@ def WebIDLTest(parser, harness):
setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"]))
setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"]))
setDistinguishable("SharedArrayBuffer", allBut(argTypes, ["SharedArrayBuffer", "object"]))
setDistinguishable("SharedArrayBufferView", allBut(argTypes, ["SharedArrayBufferView", "SharedUint8Array", "SharedUint16Array", "object"]))
setDistinguishable("SharedUint8Array", allBut(argTypes, ["SharedArrayBufferView", "SharedUint8Array", "object"]))
setDistinguishable("SharedUint16Array", allBut(argTypes, ["SharedArrayBufferView", "SharedUint16Array", "object"]))
def areDistinguishable(type1, type2):
return data[type1].get(type2, False)

View File

@ -5208,7 +5208,9 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
}
JS::AutoCheckCannotGC nogc;
uint8_t* data = JS_GetUint8ClampedArrayData(darray, nogc);
bool isShared;
uint8_t* data = JS_GetUint8ClampedArrayData(darray, &isShared, nogc);
MOZ_ASSERT(!isShared); // Should not happen, data was created above
if (!readback) {
src = data;
srcStride = aWidth * 4;

View File

@ -89,6 +89,11 @@ ImageData::Constructor(const GlobalObject& aGlobal,
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return nullptr;
}
if (JS_GetTypedArraySharedness(aData.Obj())) {
// Throw if the object is mapping shared memory (must opt in).
aRv.ThrowTypeError<MSG_TYPEDARRAY_IS_SHARED>(NS_LITERAL_STRING("Argument of ImageData constructor"));
return nullptr;
}
RefPtr<ImageData> imageData = new ImageData(aWidth, height, *aData.Obj());
return imageData.forget();
}

View File

@ -30,8 +30,9 @@ public:
template<typename T,
JSObject* UnwrapArray(JSObject*),
void GetLengthAndData(JSObject*, uint32_t*, T**)>
uint8_t* Assign(const TypedArray_base<T, UnwrapArray, GetLengthAndData>& aArray)
void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*, T**)>
uint8_t* Assign(const TypedArray_base<T, UnwrapArray,
GetLengthAndDataAndSharedness>& aArray)
{
aArray.ComputeLengthAndData();
return Assign(aArray.Data(), aArray.Length());

View File

@ -321,7 +321,9 @@ FMRadio::GetRdsgroup(JSContext* cx, JS::MutableHandle<JSObject*> retval)
JSObject *rdsgroup = Uint16Array::Create(cx, this, 4);
JS::AutoCheckCannotGC nogc;
uint16_t *data = JS_GetUint16ArrayData(rdsgroup, nogc);
bool isShared = false;
uint16_t *data = JS_GetUint16ArrayData(rdsgroup, &isShared, nogc);
MOZ_ASSERT(!isShared); // Because created above.
data[3] = group & 0xFFFF;
group >>= 16;
data[2] = group & 0xFFFF;

View File

@ -119,7 +119,9 @@ AudioBuffer::RestoreJSChannelData(JSContext* aJSContext)
// AudioBuffer, to be returned by the next call to getChannelData."
const float* data = mSharedChannels->GetData(i);
JS::AutoCheckCannotGC nogc;
mozilla::PodCopy(JS_GetFloat32ArrayData(array, nogc), data, mLength);
bool isShared;
mozilla::PodCopy(JS_GetFloat32ArrayData(array, &isShared, nogc), data, mLength);
MOZ_ASSERT(!isShared); // Was created as unshared above
}
mJSChannels[i] = array;
}
@ -154,7 +156,11 @@ AudioBuffer::CopyFromChannel(const Float32Array& aDestination, uint32_t aChannel
return;
}
sourceData = JS_GetFloat32ArrayData(channelArray, nogc);
bool isShared = false;
sourceData = JS_GetFloat32ArrayData(channelArray, &isShared, nogc);
// The sourceData arrays should all have originated in
// RestoreJSChannelData, where they are created unshared.
MOZ_ASSERT(!isShared);
} else if (mSharedChannels) {
sourceData = mSharedChannels->GetData(aChannelNumber);
}
@ -195,8 +201,12 @@ AudioBuffer::CopyToChannel(JSContext* aJSContext, const Float32Array& aSource,
return;
}
PodMove(JS_GetFloat32ArrayData(channelArray, nogc) + aStartInChannel,
aSource.Data(), length);
bool isShared = false;
float* channelData = JS_GetFloat32ArrayData(channelArray, &isShared, nogc);
// The channelData arrays should all have originated in
// RestoreJSChannelData, where they are created unshared.
MOZ_ASSERT(!isShared);
PodMove(channelData + aStartInChannel, aSource.Data(), length);
}
void
@ -242,8 +252,14 @@ AudioBuffer::StealJSArrayDataIntoSharedChannels(JSContext* aJSContext)
new ThreadSharedFloatArrayBufferList(mJSChannels.Length());
for (uint32_t i = 0; i < mJSChannels.Length(); ++i) {
JS::Rooted<JSObject*> arrayBufferView(aJSContext, mJSChannels[i]);
bool isSharedMemory;
JS::Rooted<JSObject*> arrayBuffer(aJSContext,
JS_GetArrayBufferViewBuffer(aJSContext, arrayBufferView));
JS_GetArrayBufferViewBuffer(aJSContext,
arrayBufferView,
&isSharedMemory));
// The channel data arrays should all have originated in
// RestoreJSChannelData, where they are created unshared.
MOZ_ASSERT(!isSharedMemory);
auto stolenData = arrayBuffer
? static_cast<float*>(JS_StealArrayBufferContents(aJSContext,
arrayBuffer))

View File

@ -572,6 +572,12 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer,
aBuffer.ComputeLengthAndData();
if (aBuffer.IsShared()) {
// Throw if the object is mapping shared memory (must opt in).
aRv.ThrowTypeError<MSG_TYPEDARRAY_IS_SHARED>(NS_LITERAL_STRING("Argument of AudioContext.decodeAudioData"));
return nullptr;
}
// Neuter the array buffer
size_t length = aBuffer.Length();
JS::RootedObject obj(cx, aBuffer.Obj());

View File

@ -327,6 +327,11 @@ WaveShaperNode::SetCurve(const Nullable<Float32Array>& aCurve, ErrorResult& aRv)
const Float32Array& floats = aCurve.Value();
floats.ComputeLengthAndData();
if (floats.IsShared()) {
// Throw if the object is mapping shared memory (must opt in).
aRv.ThrowTypeError<MSG_TYPEDARRAY_IS_SHARED>(NS_LITERAL_STRING("Argument of WaveShaperNode.setCurve"));
return;
}
uint32_t argLength = floats.Length();
if (argLength < 2) {

View File

@ -275,7 +275,13 @@ nsSpeechTask::SendAudio(JS::Handle<JS::Value> aData, JS::Handle<JS::Value> aLand
RefPtr<mozilla::SharedBuffer> samples;
{
JS::AutoCheckCannotGC nogc;
samples = makeSamples(JS_GetInt16ArrayData(tsrc, nogc), dataLen);
bool isShared;
int16_t* data = JS_GetInt16ArrayData(tsrc, &isShared, nogc);
if (isShared) {
// Must opt in to using shared data.
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
}
samples = makeSamples(data, dataLen);
}
SendAudioImpl(samples, dataLen);

View File

@ -163,7 +163,11 @@ MozNDEFRecord::GetAsURI(nsAString& aRetVal)
}
JS::AutoCheckCannotGC nogc;
uint8_t* typeData = JS_GetUint8ArrayData(mType, nogc);
bool isShared = false;
uint8_t* typeData = JS_GetUint8ArrayData(mType, &isShared, nogc);
if (isShared) {
return; // Must opt in to shared memory
}
const char* uVal = RTDValues::strings[static_cast<uint32_t>(RTD::U)].value;
if (typeData[0] != uVal[0]) {
return;
@ -171,7 +175,10 @@ MozNDEFRecord::GetAsURI(nsAString& aRetVal)
uint32_t payloadLen;
uint8_t* payloadData;
js::GetUint8ArrayLengthAndData(mPayload, &payloadLen, &payloadData);
js::GetUint8ArrayLengthAndData(mPayload, &payloadLen, &isShared, &payloadData);
if (isShared) {
return; // Must opt in to shared memory
}
uint8_t id = payloadData[0];
if (id >= static_cast<uint8_t>(WellKnownURIPrefix::EndGuard_)) {
return;
@ -188,16 +195,26 @@ MozNDEFRecord::WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWr
{
uint8_t* dummy;
uint32_t typeLen = 0, idLen = 0, payloadLen = 0;
bool isShared;
if (mType) {
js::GetUint8ArrayLengthAndData(mType, &typeLen, &dummy);
js::GetUint8ArrayLengthAndData(mType, &typeLen, &isShared, &dummy);
if (isShared) {
return false; // Must opt in to shared memory
}
}
if (mId) {
js::GetUint8ArrayLengthAndData(mId, &idLen, &dummy);
js::GetUint8ArrayLengthAndData(mId, &idLen, &isShared, &dummy);
if (isShared) {
return false; // Must opt in to shared memory
}
}
if (mPayload) {
js::GetUint8ArrayLengthAndData(mPayload, &payloadLen, &dummy);
js::GetUint8ArrayLengthAndData(mPayload, &payloadLen, &isShared, &dummy);
if (isShared) {
return false; // Must opt in to shared memory
}
}
return JS_WriteUint32Pair(aWriter, static_cast<uint32_t>(mTnf), typeLen) &&
@ -322,7 +339,9 @@ MozNDEFRecord::InitPayload(JSContext* aCx, const nsAString& aUri)
mPayload = Uint8Array::Create(aCx, this, uri.Length() + 1);
JS::AutoCheckCannotGC nogc;
uint8_t* data = JS_GetUint8ArrayData(mPayload, nogc);
bool isShared = false;
uint8_t* data = JS_GetUint8ArrayData(mPayload, &isShared, nogc);
MOZ_ASSERT(!isShared); // Created as unshared above
data[0] = id;
memcpy(&data[1], reinterpret_cast<const uint8_t*>(uri.Data()), uri.Length());
IncSizeForPayload(uri.Length() + 1);

View File

@ -79,15 +79,6 @@ var ecmaGlobals =
"RegExp",
"Set",
{name: "SharedArrayBuffer", nightly: true},
{name: "SharedInt8Array", nightly: true},
{name: "SharedUint8Array", nightly: true},
{name: "SharedUint8ClampedArray", nightly: true},
{name: "SharedInt16Array", nightly: true},
{name: "SharedUint16Array", nightly: true},
{name: "SharedInt32Array", nightly: true},
{name: "SharedUint32Array", nightly: true},
{name: "SharedFloat32Array", nightly: true},
{name: "SharedFloat64Array", nightly: true},
{name: "SIMD", nightly: true},
{name: "Atomics", nightly: true},
"StopIteration",

View File

@ -2245,6 +2245,12 @@ XMLHttpRequest::Send(const ArrayBuffer& aBody, ErrorResult& aRv)
void
XMLHttpRequest::Send(const ArrayBufferView& aBody, ErrorResult& aRv)
{
if (JS_IsTypedArrayObject(aBody.Obj()) &&
JS_GetTypedArraySharedness(aBody.Obj())) {
// Throw if the object is mapping shared memory (must opt in).
aRv.ThrowTypeError<MSG_TYPEDARRAY_IS_SHARED>(NS_LITERAL_STRING("Argument of XMLHttpRequest.send"));
return;
}
JS::Rooted<JSObject*> obj(mWorkerPrivate->GetJSContext(), aBody.Obj());
return Send(obj, aRv);
}

View File

@ -54,15 +54,6 @@ var ecmaGlobals =
"RegExp",
"Set",
{name: "SharedArrayBuffer", nightly: true},
{name: "SharedInt8Array", nightly: true},
{name: "SharedUint8Array", nightly: true},
{name: "SharedUint8ClampedArray", nightly: true},
{name: "SharedInt16Array", nightly: true},
{name: "SharedUint16Array", nightly: true},
{name: "SharedInt32Array", nightly: true},
{name: "SharedUint32Array", nightly: true},
{name: "SharedFloat32Array", nightly: true},
{name: "SharedFloat64Array", nightly: true},
{name: "SIMD", nightly: true},
{name: "Atomics", nightly: true},
"StopIteration",

View File

@ -54,15 +54,6 @@ var ecmaGlobals =
"RegExp",
"Set",
{name: "SharedArrayBuffer", nightly: true},
{name: "SharedInt8Array", nightly: true},
{name: "SharedUint8Array", nightly: true},
{name: "SharedUint8ClampedArray", nightly: true},
{name: "SharedInt16Array", nightly: true},
{name: "SharedUint16Array", nightly: true},
{name: "SharedInt32Array", nightly: true},
{name: "SharedUint32Array", nightly: true},
{name: "SharedFloat32Array", nightly: true},
{name: "SharedFloat64Array", nightly: true},
{name: "SIMD", nightly: true},
{name: "Atomics", nightly: true},
"StopIteration",