Backed out changeset 2c631967ab9e (bug 999651) for B2G crashes.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2014-05-27 14:08:30 -04:00
parent 68337a62cb
commit 095b86b386
41 changed files with 211 additions and 629 deletions

View File

@ -143,8 +143,6 @@ already_AddRefed<nsIDocument>
DOMParser::ParseFromBuffer(const Uint8Array& aBuf, uint32_t aBufLen,
SupportedType aType, ErrorResult& rv)
{
aBuf.ComputeLengthAndData();
if (aBufLen > aBuf.Length()) {
rv.Throw(NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY);
return nullptr;

View File

@ -1212,10 +1212,7 @@ WebSocket::Send(const ArrayBuffer& aData,
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
aData.ComputeLengthAndData();
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
MOZ_ASSERT(sizeof(*aData.Data()) == 1);
uint32_t len = aData.Length();
char* data = reinterpret_cast<char*>(aData.Data());
@ -1229,10 +1226,7 @@ WebSocket::Send(const ArrayBufferView& aData,
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
aData.ComputeLengthAndData();
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
MOZ_ASSERT(sizeof(*aData.Data()) == 1);
uint32_t len = aData.Length();
char* data = reinterpret_cast<char*>(aData.Data());

View File

@ -303,10 +303,7 @@ nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
aData.ComputeLengthAndData();
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
MOZ_ASSERT(sizeof(*aData.Data()) == 1);
uint32_t len = aData.Length();
char* data = reinterpret_cast<char*>(aData.Data());
@ -319,10 +316,7 @@ nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
aData.ComputeLengthAndData();
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
MOZ_ASSERT(sizeof(*aData.Data()) == 1);
uint32_t len = aData.Length();
char* data = reinterpret_cast<char*>(aData.Data());

View File

@ -2529,7 +2529,6 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult, uint64_t* aContentLe
JS::Rooted<JSObject*> obj(cx, realVal.toObjectOrNull());
if (JS_IsArrayBufferObject(obj)) {
ArrayBuffer buf(obj);
buf.ComputeLengthAndData();
return GetRequestBody(buf.Data(), buf.Length(), aResult,
aContentLength, aContentType, aCharset);
}
@ -2573,16 +2572,14 @@ nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
switch (body.GetType()) {
case nsXMLHttpRequest::RequestBody::ArrayBuffer:
{
const ArrayBuffer* buffer = value.mArrayBuffer;
buffer->ComputeLengthAndData();
return ::GetRequestBody(buffer->Data(), buffer->Length(), aResult,
return ::GetRequestBody(value.mArrayBuffer->Data(),
value.mArrayBuffer->Length(), aResult,
aContentLength, aContentType, aCharset);
}
case nsXMLHttpRequest::RequestBody::ArrayBufferView:
{
const ArrayBufferView* view = value.mArrayBufferView;
view->ComputeLengthAndData();
return ::GetRequestBody(view->Data(), view->Length(), aResult,
return ::GetRequestBody(value.mArrayBufferView->Data(),
value.mArrayBufferView->Length(), aResult,
aContentLength, aContentType, aCharset);
}
case nsXMLHttpRequest::RequestBody::Blob:

View File

@ -4010,7 +4010,7 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
imageData.Width(), imageData.Height(),
&arr, false, 0, 0, 0, 0);
arr.Data(), arr.Length(), false, 0, 0, 0, 0);
}
void
@ -4024,7 +4024,7 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
imageData.Width(), imageData.Height(),
&arr, true,
arr.Data(), arr.Length(), true,
JS_DoubleToInt32(dirtyX),
JS_DoubleToInt32(dirtyY),
JS_DoubleToInt32(dirtyWidth),
@ -4036,7 +4036,7 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
nsresult
CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
dom::Uint8ClampedArray* aArray,
unsigned char *aData, uint32_t aDataLen,
bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
int32_t dirtyWidth, int32_t dirtyHeight)
{
@ -4089,12 +4089,8 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
return NS_OK;
}
aArray->ComputeLengthAndData();
uint32_t dataLen = aArray->Length();
uint32_t len = w * h * 4;
if (dataLen != len) {
if (aDataLen != len) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
@ -4105,7 +4101,7 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
return NS_ERROR_FAILURE;
}
uint8_t *src = aArray->Data();
uint8_t *src = aData;
uint8_t *dst = imgsurf->Data();
for (uint32_t j = 0; j < h; j++) {

View File

@ -551,7 +551,7 @@ protected:
JSObject** aRetval);
nsresult PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
dom::Uint8ClampedArray* aArray,
unsigned char *aData, uint32_t aDataLen,
bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
int32_t dirtyWidth, int32_t dirtyHeight);

View File

@ -70,8 +70,6 @@ ImageData::Constructor(const GlobalObject& aGlobal,
const Optional<uint32_t>& aHeight,
ErrorResult& aRv)
{
aData.ComputeLengthAndData();
uint32_t length = aData.Length();
if (length == 0 || length % 4) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);

View File

@ -511,7 +511,6 @@ public:
void Uniform1iv(WebGLUniformLocation* location,
const dom::Int32Array& arr) {
arr.ComputeLengthAndData();
Uniform1iv_base(location, arr.Length(), arr.Data());
}
void Uniform1iv(WebGLUniformLocation* location,
@ -523,7 +522,6 @@ public:
void Uniform2iv(WebGLUniformLocation* location,
const dom::Int32Array& arr) {
arr.ComputeLengthAndData();
Uniform2iv_base(location, arr.Length(), arr.Data());
}
void Uniform2iv(WebGLUniformLocation* location,
@ -535,7 +533,6 @@ public:
void Uniform3iv(WebGLUniformLocation* location,
const dom::Int32Array& arr) {
arr.ComputeLengthAndData();
Uniform3iv_base(location, arr.Length(), arr.Data());
}
void Uniform3iv(WebGLUniformLocation* location,
@ -547,7 +544,6 @@ public:
void Uniform4iv(WebGLUniformLocation* location,
const dom::Int32Array& arr) {
arr.ComputeLengthAndData();
Uniform4iv_base(location, arr.Length(), arr.Data());
}
void Uniform4iv(WebGLUniformLocation* location,
@ -559,7 +555,6 @@ public:
void Uniform1fv(WebGLUniformLocation* location,
const dom::Float32Array& arr) {
arr.ComputeLengthAndData();
Uniform1fv_base(location, arr.Length(), arr.Data());
}
void Uniform1fv(WebGLUniformLocation* location,
@ -571,7 +566,6 @@ public:
void Uniform2fv(WebGLUniformLocation* location,
const dom::Float32Array& arr) {
arr.ComputeLengthAndData();
Uniform2fv_base(location, arr.Length(), arr.Data());
}
void Uniform2fv(WebGLUniformLocation* location,
@ -583,7 +577,6 @@ public:
void Uniform3fv(WebGLUniformLocation* location,
const dom::Float32Array& arr) {
arr.ComputeLengthAndData();
Uniform3fv_base(location, arr.Length(), arr.Data());
}
void Uniform3fv(WebGLUniformLocation* location,
@ -595,7 +588,6 @@ public:
void Uniform4fv(WebGLUniformLocation* location,
const dom::Float32Array& arr) {
arr.ComputeLengthAndData();
Uniform4fv_base(location, arr.Length(), arr.Data());
}
void Uniform4fv(WebGLUniformLocation* location,
@ -608,7 +600,6 @@ public:
void UniformMatrix2fv(WebGLUniformLocation* location,
WebGLboolean transpose,
const dom::Float32Array &value) {
value.ComputeLengthAndData();
UniformMatrix2fv_base(location, transpose, value.Length(), value.Data());
}
void UniformMatrix2fv(WebGLUniformLocation* location,
@ -624,7 +615,6 @@ public:
void UniformMatrix3fv(WebGLUniformLocation* location,
WebGLboolean transpose,
const dom::Float32Array &value) {
value.ComputeLengthAndData();
UniformMatrix3fv_base(location, transpose, value.Length(), value.Data());
}
void UniformMatrix3fv(WebGLUniformLocation* location,
@ -640,7 +630,6 @@ public:
void UniformMatrix4fv(WebGLUniformLocation* location,
WebGLboolean transpose,
const dom::Float32Array &value) {
value.ComputeLengthAndData();
UniformMatrix4fv_base(location, transpose, value.Length(), value.Data());
}
void UniformMatrix4fv(WebGLUniformLocation* location,
@ -764,7 +753,6 @@ public:
GLfloat x2, GLfloat x3);
void VertexAttrib1fv(GLuint idx, const dom::Float32Array &arr) {
arr.ComputeLengthAndData();
VertexAttrib1fv_base(idx, arr.Length(), arr.Data());
}
void VertexAttrib1fv(GLuint idx, const dom::Sequence<GLfloat>& arr) {
@ -772,7 +760,6 @@ public:
}
void VertexAttrib2fv(GLuint idx, const dom::Float32Array &arr) {
arr.ComputeLengthAndData();
VertexAttrib2fv_base(idx, arr.Length(), arr.Data());
}
void VertexAttrib2fv(GLuint idx, const dom::Sequence<GLfloat>& arr) {
@ -780,7 +767,6 @@ public:
}
void VertexAttrib3fv(GLuint idx, const dom::Float32Array &arr) {
arr.ComputeLengthAndData();
VertexAttrib3fv_base(idx, arr.Length(), arr.Data());
}
void VertexAttrib3fv(GLuint idx, const dom::Sequence<GLfloat>& arr) {
@ -788,7 +774,6 @@ public:
}
void VertexAttrib4fv(GLuint idx, const dom::Float32Array &arr) {
arr.ComputeLengthAndData();
VertexAttrib4fv_base(idx, arr.Length(), arr.Data());
}
void VertexAttrib4fv(GLuint idx, const dom::Sequence<GLfloat>& arr) {

View File

@ -203,10 +203,8 @@ WebGLContext::BufferData(GLenum target,
}
const ArrayBuffer& data = maybeData.Value();
data.ComputeLengthAndData();
// Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
// is like intptr_t.
// careful: data.Length() could conceivably be any size_t, but GLsizeiptr is like intptr_t.
if (!CheckedInt<GLsizeiptr>(data.Length()).isValid())
return ErrorOutOfMemory("bufferData: bad size");
@ -255,10 +253,7 @@ WebGLContext::BufferData(GLenum target, const ArrayBufferView& data,
if (!boundBuffer)
return ErrorInvalidOperation("bufferData: no buffer bound!");
data.ComputeLengthAndData();
// Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
// is like intptr_t.
// careful: data.Length() could conceivably be any size_t, but GLsizeiptr is like intptr_t.
if (!CheckedInt<GLsizeiptr>(data.Length()).isValid())
return ErrorOutOfMemory("bufferData: bad size");
@ -295,6 +290,8 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
return;
}
const ArrayBuffer& data = maybeData.Value();
if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset");
@ -303,9 +300,6 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
if (!boundBuffer)
return ErrorInvalidOperation("bufferData: no buffer bound!");
const ArrayBuffer& data = maybeData.Value();
data.ComputeLengthAndData();
CheckedInt<WebGLsizeiptr> checked_neededByteLength = CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
if (!checked_neededByteLength.isValid())
return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length");
@ -342,8 +336,6 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
if (!boundBuffer)
return ErrorInvalidOperation("bufferSubData: no buffer bound!");
data.ComputeLengthAndData();
CheckedInt<WebGLsizeiptr> checked_neededByteLength = CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
if (!checked_neededByteLength.isValid())
return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length");

View File

@ -2126,8 +2126,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
if (!isReadTypeValid)
return ErrorInvalidEnum("readPixels: Bad type", type);
const ArrayBufferView& pixbuf = pixels.Value();
int dataType = JS_GetArrayBufferViewType(pixbuf.Obj());
int dataType = JS_GetArrayBufferViewType(pixels.Value().Obj());
// Check the pixels param type
if (dataType != requiredDataType)
@ -2145,15 +2144,11 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("readPixels: integer overflow computing the needed buffer size");
// Compute length and data. Don't reenter after this point, lest the
// precomputed go out of sync with the instant length/data.
pixbuf.ComputeLengthAndData();
uint32_t dataByteLen = pixbuf.Length();
uint32_t dataByteLen = JS_GetTypedArrayByteLength(pixels.Value().Obj());
if (checked_neededByteLength.value() > dataByteLen)
return ErrorInvalidOperation("readPixels: buffer too small");
void* data = pixbuf.Data();
void* data = pixels.Value().Data();
if (!data) {
ErrorOutOfMemory("readPixels: buffer storage is null. Did we run out of memory?");
return rv.Throw(NS_ERROR_OUT_OF_MEMORY);
@ -3266,8 +3261,6 @@ WebGLContext::CompressedTexImage2D(GLenum target, GLint level, GLenum internalfo
return;
}
view.ComputeLengthAndData();
uint32_t byteLength = view.Length();
if (!ValidateCompTexImageDataSize(target, internalformat, width, height, byteLength, func)) {
return;
@ -3311,8 +3304,6 @@ WebGLContext::CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
MOZ_ASSERT(tex);
WebGLTexture::ImageInfo& levelInfo = tex->ImageInfoAt(target, level);
view.ComputeLengthAndData();
uint32_t byteLength = view.Length();
if (!ValidateCompTexImageDataSize(target, format, width, height, byteLength, func))
return;
@ -3679,24 +3670,10 @@ WebGLContext::TexImage2D(GLenum target, GLint level,
if (IsContextLost())
return;
void* data;
uint32_t length;
int jsArrayType;
if (pixels.IsNull()) {
data = nullptr;
length = 0;
jsArrayType = -1;
} else {
const ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
data = view.Data();
length = view.Length();
jsArrayType = int(JS_GetArrayBufferViewType(view.Obj()));
}
return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
data, length, jsArrayType,
pixels.IsNull() ? 0 : pixels.Value().Data(),
pixels.IsNull() ? 0 : pixels.Value().Length(),
pixels.IsNull() ? -1 : (int)JS_GetArrayBufferViewType(pixels.Value().Obj()),
WebGLTexelFormat::Auto, false);
}
@ -3714,8 +3691,6 @@ WebGLContext::TexImage2D(GLenum target, GLint level,
}
Uint8ClampedArray arr(pixels->GetDataObject());
arr.ComputeLengthAndData();
return TexImage2D_base(target, level, internalformat, pixels->Width(),
pixels->Height(), 4*pixels->Width(), 0,
format, type, arr.Data(), arr.Length(), -1,
@ -3824,13 +3799,10 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
if (pixels.IsNull())
return ErrorInvalidValue("texSubImage2D: pixels must not be null!");
const ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
return TexSubImage2D_base(target, level, xoffset, yoffset,
width, height, 0, format, type,
view.Data(), view.Length(),
JS_GetArrayBufferViewType(view.Obj()),
pixels.Value().Data(), pixels.Value().Length(),
JS_GetArrayBufferViewType(pixels.Value().Obj()),
WebGLTexelFormat::Auto, false);
}
@ -3847,8 +3819,6 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
return ErrorInvalidValue("texSubImage2D: pixels must not be null!");
Uint8ClampedArray arr(pixels->GetDataObject());
arr.ComputeLengthAndData();
return TexSubImage2D_base(target, level, xoffset, yoffset,
pixels->Width(), pixels->Height(),
4*pixels->Width(), format, type,

View File

@ -250,16 +250,12 @@ SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
void
SourceBuffer::AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv)
{
aData.ComputeLengthAndData();
AppendData(aData.Data(), aData.Length(), aRv);
}
void
SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv)
{
aData.ComputeLengthAndData();
AppendData(aData.Data(), aData.Length(), aRv);
}

View File

@ -171,8 +171,6 @@ AnalyserNode::GetFloatFrequencyData(const Float32Array& aArray)
return;
}
aArray.ComputeLengthAndData();
float* buffer = aArray.Data();
size_t length = std::min(size_t(aArray.Length()), mOutputBuffer.Length());
@ -191,8 +189,6 @@ AnalyserNode::GetByteFrequencyData(const Uint8Array& aArray)
const double rangeScaleFactor = 1.0 / (mMaxDecibels - mMinDecibels);
aArray.ComputeLengthAndData();
unsigned char* buffer = aArray.Data();
size_t length = std::min(size_t(aArray.Length()), mOutputBuffer.Length());
@ -208,8 +204,6 @@ AnalyserNode::GetByteFrequencyData(const Uint8Array& aArray)
void
AnalyserNode::GetFloatTimeDomainData(const Float32Array& aArray)
{
aArray.ComputeLengthAndData();
float* buffer = aArray.Data();
size_t length = std::min(size_t(aArray.Length()), mBuffer.Length());
@ -221,8 +215,6 @@ AnalyserNode::GetFloatTimeDomainData(const Float32Array& aArray)
void
AnalyserNode::GetByteTimeDomainData(const Uint8Array& aArray)
{
aArray.ComputeLengthAndData();
unsigned char* buffer = aArray.Data();
size_t length = std::min(size_t(aArray.Length()), mBuffer.Length());

View File

@ -130,8 +130,6 @@ void
AudioBuffer::CopyFromChannel(const Float32Array& aDestination, uint32_t aChannelNumber,
uint32_t aStartInChannel, ErrorResult& aRv)
{
aDestination.ComputeLengthAndData();
uint32_t length = aDestination.Length();
CheckedInt<uint32_t> end = aStartInChannel;
end += length;
@ -158,8 +156,6 @@ AudioBuffer::CopyToChannel(JSContext* aJSContext, const Float32Array& aSource,
uint32_t aChannelNumber, uint32_t aStartInChannel,
ErrorResult& aRv)
{
aSource.ComputeLengthAndData();
uint32_t length = aSource.Length();
CheckedInt<uint32_t> end = aStartInChannel;
end += length;

View File

@ -400,9 +400,6 @@ AudioContext::CreatePeriodicWave(const Float32Array& aRealData,
const Float32Array& aImagData,
ErrorResult& aRv)
{
aRealData.ComputeLengthAndData();
aImagData.ComputeLengthAndData();
if (aRealData.Length() != aImagData.Length() ||
aRealData.Length() == 0 ||
aRealData.Length() > 4096) {
@ -437,8 +434,6 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer,
JSContext* cx = jsapi.cx();
JSAutoCompartment ac(cx, aBuffer.Obj());
aBuffer.ComputeLengthAndData();
// Neuter the array buffer
size_t length = aBuffer.Length();
JS::RootedObject obj(cx, aBuffer.Obj());

View File

@ -55,7 +55,6 @@ public:
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
aValues.ComputeLengthAndData();
AudioParamTimeline::SetValueCurveAtTime(aValues.Data(), aValues.Length(),
DOMTimeToStreamTime(aStartTime), aDuration, aRv);
mCallback(mNode);

View File

@ -308,10 +308,6 @@ BiquadFilterNode::GetFrequencyResponse(const Float32Array& aFrequencyHz,
const Float32Array& aMagResponse,
const Float32Array& aPhaseResponse)
{
aFrequencyHz.ComputeLengthAndData();
aMagResponse.ComputeLengthAndData();
aPhaseResponse.ComputeLengthAndData();
uint32_t length = std::min(std::min(aFrequencyHz.Length(), aMagResponse.Length()),
aPhaseResponse.Length());
if (!length) {

View File

@ -313,14 +313,10 @@ WaveShaperNode::SetCurve(const Nullable<Float32Array>& aCurve)
{
nsTArray<float> curve;
if (!aCurve.IsNull()) {
const Float32Array& floats = aCurve.Value();
mCurve = aCurve.Value().Obj();
mCurve = floats.Obj();
floats.ComputeLengthAndData();
curve.SetLength(floats.Length());
PodCopy(curve.Elements(), floats.Data(), floats.Length());
curve.SetLength(aCurve.Value().Length());
PodCopy(curve.Elements(), aCurve.Value().Data(), aCurve.Value().Length());
} else {
mCurve = nullptr;
}

View File

@ -79,7 +79,6 @@ Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
return nullptr;
}
aArray.ComputeLengthAndData();
uint32_t dataLen = aArray.Length();
if (dataLen == 0) {
NS_WARNING("ArrayBufferView length is 0, cannot continue");

View File

@ -1243,10 +1243,8 @@ Navigator::SendBeacon(const nsAString& aUrl,
return false;
}
ArrayBufferView& view = aData.Value().GetAsArrayBufferView();
view.ComputeLengthAndData();
rv = strStream->SetData(reinterpret_cast<char*>(view.Data()),
view.Length());
rv = strStream->SetData(reinterpret_cast<char*>(aData.Value().GetAsArrayBufferView().Data()),
aData.Value().GetAsArrayBufferView().Length());
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_FAILURE);

View File

@ -26,7 +26,7 @@ struct TypedArrayObjectStorage : AllTypedArraysBase {
protected:
JSObject* mObj;
TypedArrayObjectStorage(JSObject *obj) : mObj(obj)
TypedArrayObjectStorage()
{
}
@ -55,43 +55,32 @@ private:
* or array buffer object.
*/
template<typename T,
JSObject* UnwrapArray(JSObject*),
void GetLengthAndData(JSObject*, uint32_t*, T**)>
JSObject* UnboxArray(JSObject*, uint32_t*, T**)>
struct TypedArray_base : public TypedArrayObjectStorage {
typedef T element_type;
TypedArray_base(JSObject* obj)
: TypedArrayObjectStorage(obj),
mData(nullptr),
mLength(0),
mComputed(false)
{
MOZ_ASSERT(obj != nullptr);
DoInit(obj);
}
TypedArray_base()
: TypedArrayObjectStorage(nullptr),
mData(nullptr),
mLength(0),
mComputed(false)
{
mObj = nullptr;
}
explicit TypedArray_base(TypedArray_base&& aOther)
: TypedArrayObjectStorage(Move(aOther)),
mData(aOther.mData),
mLength(aOther.mLength),
mComputed(aOther.mComputed)
mLength(aOther.mLength)
{
aOther.mData = nullptr;
aOther.mLength = 0;
aOther.mComputed = false;
}
private:
mutable T* mData;
mutable uint32_t mLength;
mutable bool mComputed;
T* mData;
uint32_t mLength;
public:
inline bool Init(JSObject* obj)
@ -106,12 +95,12 @@ public:
}
inline T *Data() const {
MOZ_ASSERT(mComputed);
MOZ_ASSERT(inited());
return mData;
}
inline uint32_t Length() const {
MOZ_ASSERT(mComputed);
MOZ_ASSERT(inited());
return mLength;
}
@ -126,26 +115,10 @@ public:
JS::MutableHandle<JSObject*>::fromMarkedLocation(&mObj));
}
inline void ComputeLengthAndData() const
{
MOZ_ASSERT(inited());
MOZ_ASSERT(!mComputed);
GetLengthAndData(mObj, &mLength, &mData);
mComputed = true;
}
protected:
inline void DoInit(JSObject* obj)
{
mObj = UnwrapArray(obj);
}
inline void ComputeData() const {
MOZ_ASSERT(inited());
if (!mComputed) {
GetLengthAndData(mObj, &mLength, &mData);
mComputed = true;
}
mObj = UnboxArray(obj, &mLength, &mData);
}
private:
@ -154,25 +127,20 @@ private:
template<typename T,
JSObject* UnwrapArray(JSObject*),
T* GetData(JSObject*),
void GetLengthAndData(JSObject*, uint32_t*, T**),
JSObject* UnboxArray(JSObject*, uint32_t*, T**),
JSObject* CreateNew(JSContext*, uint32_t)>
struct TypedArray : public TypedArray_base<T, UnwrapArray, GetLengthAndData> {
private:
typedef TypedArray_base<T, UnwrapArray, GetLengthAndData> Base;
public:
TypedArray(JSObject* obj)
: Base(obj)
struct TypedArray : public TypedArray_base<T,UnboxArray> {
TypedArray(JSObject* obj) :
TypedArray_base<T,UnboxArray>(obj)
{}
TypedArray()
: Base()
TypedArray() :
TypedArray_base<T,UnboxArray>()
{}
explicit TypedArray(TypedArray&& aOther)
: Base(Move(aOther))
: TypedArray_base<T,UnboxArray>(Move(aOther))
{
}
@ -210,37 +178,37 @@ private:
TypedArray(const TypedArray&) MOZ_DELETE;
};
typedef TypedArray<int8_t, js::UnwrapInt8Array, JS_GetInt8ArrayData,
js::GetInt8ArrayLengthAndData, JS_NewInt8Array>
typedef TypedArray<int8_t, JS_GetInt8ArrayData, JS_GetObjectAsInt8Array,
JS_NewInt8Array>
Int8Array;
typedef TypedArray<uint8_t, js::UnwrapUint8Array, JS_GetUint8ArrayData,
js::GetUint8ArrayLengthAndData, JS_NewUint8Array>
typedef TypedArray<uint8_t, JS_GetUint8ArrayData,
JS_GetObjectAsUint8Array, JS_NewUint8Array>
Uint8Array;
typedef TypedArray<uint8_t, js::UnwrapUint8ClampedArray, JS_GetUint8ClampedArrayData,
js::GetUint8ClampedArrayLengthAndData, JS_NewUint8ClampedArray>
typedef TypedArray<uint8_t, JS_GetUint8ClampedArrayData,
JS_GetObjectAsUint8ClampedArray, JS_NewUint8ClampedArray>
Uint8ClampedArray;
typedef TypedArray<int16_t, js::UnwrapInt16Array, JS_GetInt16ArrayData,
js::GetInt16ArrayLengthAndData, JS_NewInt16Array>
typedef TypedArray<int16_t, JS_GetInt16ArrayData,
JS_GetObjectAsInt16Array, JS_NewInt16Array>
Int16Array;
typedef TypedArray<uint16_t, js::UnwrapUint16Array, JS_GetUint16ArrayData,
js::GetUint16ArrayLengthAndData, JS_NewUint16Array>
typedef TypedArray<uint16_t, JS_GetUint16ArrayData,
JS_GetObjectAsUint16Array, JS_NewUint16Array>
Uint16Array;
typedef TypedArray<int32_t, js::UnwrapInt32Array, JS_GetInt32ArrayData,
js::GetInt32ArrayLengthAndData, JS_NewInt32Array>
typedef TypedArray<int32_t, JS_GetInt32ArrayData,
JS_GetObjectAsInt32Array, JS_NewInt32Array>
Int32Array;
typedef TypedArray<uint32_t, js::UnwrapUint32Array, JS_GetUint32ArrayData,
js::GetUint32ArrayLengthAndData, JS_NewUint32Array>
typedef TypedArray<uint32_t, JS_GetUint32ArrayData,
JS_GetObjectAsUint32Array, JS_NewUint32Array>
Uint32Array;
typedef TypedArray<float, js::UnwrapFloat32Array, JS_GetFloat32ArrayData,
js::GetFloat32ArrayLengthAndData, JS_NewFloat32Array>
typedef TypedArray<float, JS_GetFloat32ArrayData,
JS_GetObjectAsFloat32Array, JS_NewFloat32Array>
Float32Array;
typedef TypedArray<double, js::UnwrapFloat64Array, JS_GetFloat64ArrayData,
js::GetFloat64ArrayLengthAndData, JS_NewFloat64Array>
typedef TypedArray<double, JS_GetFloat64ArrayData,
JS_GetObjectAsFloat64Array, JS_NewFloat64Array>
Float64Array;
typedef TypedArray_base<uint8_t, js::UnwrapArrayBufferView, js::GetArrayBufferViewLengthAndData>
typedef TypedArray_base<uint8_t, JS_GetObjectAsArrayBufferView>
ArrayBufferView;
typedef TypedArray<uint8_t, js::UnwrapArrayBuffer, JS_GetArrayBufferData,
js::GetArrayBufferLengthAndData, JS_NewArrayBuffer>
typedef TypedArray<uint8_t, JS_GetArrayBufferData,
JS_GetObjectAsArrayBuffer, JS_NewArrayBuffer>
ArrayBuffer;
// A class for converting an nsTArray to a TypedArray

View File

@ -26,14 +26,12 @@ CryptoBuffer::Assign(const SECItem* aItem)
uint8_t*
CryptoBuffer::Assign(const ArrayBuffer& aData)
{
aData.ComputeLengthAndData();
return Assign(aData.Data(), aData.Length());
}
uint8_t*
CryptoBuffer::Assign(const ArrayBufferView& aData)
{
aData.ComputeLengthAndData();
return Assign(aData.Data(), aData.Length());
}

View File

@ -28,12 +28,10 @@ public:
uint8_t* Assign(const OwningArrayBufferViewOrArrayBuffer& aData);
template<typename T,
JSObject* UnwrapArray(JSObject*),
void GetLengthAndData(JSObject*, uint32_t*, T**)>
uint8_t* Assign(const TypedArray_base<T, UnwrapArray, GetLengthAndData>& aArray)
JSObject* UnboxArray(JSObject*, uint32_t*, T**)>
uint8_t* Assign(const TypedArray_base<T, UnboxArray>& aData)
{
aArray.ComputeLengthAndData();
return Assign(aArray.Data(), aArray.Length());
return Assign(aData.Data(), aData.Length());
}

View File

@ -107,7 +107,6 @@ public:
const TextDecodeOptions& aOptions,
nsAString& aOutDecodedString,
ErrorResult& aRv) {
aView.ComputeLengthAndData();
Decode(reinterpret_cast<char*>(aView.Data()), aView.Length(),
aOptions.mStream, aOutDecodedString, aRv);
}

View File

@ -756,7 +756,6 @@ already_AddRefed<nsIInputStream>
LockedFile::GetInputStream(const ArrayBuffer& aValue, uint64_t* aInputLength,
ErrorResult& aRv)
{
aValue.ComputeLengthAndData();
const char* data = reinterpret_cast<const char*>(aValue.Data());
uint32_t length = aValue.Length();

View File

@ -112,11 +112,9 @@ Directory::CreateFile(const nsAString& aPath, const CreateFileOptions& aOptions)
str.Length());
} else if (data.IsArrayBuffer()) {
ArrayBuffer& buffer = data.GetAsArrayBuffer();
buffer.ComputeLengthAndData();
arrayData.AppendElements(buffer.Data(), buffer.Length());
} else if (data.IsArrayBufferView()){
ArrayBufferView& view = data.GetAsArrayBufferView();
view.ComputeLengthAndData();
arrayData.AppendElements(view.Data(), view.Length());
} else {
blobData = data.GetAsBlob();

View File

@ -58,7 +58,6 @@ static bool GetX4Lane(JSContext *cx, unsigned argc, Value *vp) {
return false;
}
MOZ_ASSERT(!typedObj.owner().isNeutered());
Elem *data = reinterpret_cast<Elem *>(typedObj.typedMem());
Type32x4::setReturn(args, data[lane]);
return true;
@ -101,7 +100,6 @@ static bool SignMask(JSContext *cx, unsigned argc, Value *vp) {
return false;
}
MOZ_ASSERT(!typedObj.owner().isNeutered());
Elem *data = reinterpret_cast<Elem *>(typedObj.typedMem());
int32_t mx = data[0] < 0.0 ? 1 : 0;
int32_t my = data[1] < 0.0 ? 1 : 0;
@ -276,7 +274,6 @@ X4TypeDescr::call(JSContext *cx, unsigned argc, Value *vp)
if (!result)
return false;
MOZ_ASSERT(!result->owner().isNeutered());
switch (descr->type()) {
#define STORE_LANES(_constant, _type, _name) \
case _constant: \
@ -409,9 +406,7 @@ template<typename Elem>
static Elem
TypedObjectMemory(HandleValue v)
{
TypedObject &obj = v.toObject().as<TypedObject>();
MOZ_ASSERT(!obj.owner().isNeutered());
return reinterpret_cast<Elem>(obj.typedMem());
return reinterpret_cast<Elem>(v.toObject().as<TypedObject>().typedMem());
}
template<typename V>
@ -426,7 +421,6 @@ js::Create(JSContext *cx, typename V::Elem *data)
if (!result)
return nullptr;
MOZ_ASSERT(!result->owner().isNeutered());
Elem *resultMem = reinterpret_cast<Elem *>(result->typedMem());
memcpy(resultMem, data, sizeof(Elem) * V::lanes);
return result;

View File

@ -2480,7 +2480,7 @@ TypedObject::constructUnsized(JSContext *cx, unsigned int argc, Value *vp)
Rooted<ArrayBufferObject*> buffer(cx);
buffer = &args[0].toObject().as<ArrayBufferObject>();
if (callee->opaque()) {
if (callee->opaque() || buffer->isNeutered()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage,
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
return false;
@ -2533,12 +2533,6 @@ TypedObject::constructUnsized(JSContext *cx, unsigned int argc, Value *vp)
length = maximumLength;
}
if (buffer->isNeutered()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage,
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
return false;
}
Rooted<TypedObject*> obj(cx);
obj = TypedObject::createUnattached(cx, callee, length);
if (!obj)

View File

@ -58,9 +58,8 @@
function TypedObjectGet(descr, typedObj, offset) {
assert(IsObject(descr) && ObjectIsTypeDescr(descr),
"get() called with bad type descr");
if (!TypedObjectIsAttached(typedObj))
ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
assert(TypedObjectIsAttached(typedObj),
"get() called with unattached typedObj");
switch (DESCR_KIND(descr)) {
case JS_TYPEREPR_SCALAR_KIND:
@ -187,8 +186,7 @@ function TypedObjectGetX4(descr, typedObj, offset) {
// it to `descr` as needed. This is the most general entry point
// and works for any type.
function TypedObjectSet(descr, typedObj, offset, fromValue) {
if (!TypedObjectIsAttached(typedObj))
ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
assert(TypedObjectIsAttached(typedObj), "set() called with unattached typedObj");
// Fast path: `fromValue` is a typed object with same type
// representation as the destination. In that case, we can just do a

View File

@ -327,25 +327,24 @@ ValidateConstant(JSContext *cx, AsmJSModule::Global &global, HandleValue globalV
static bool
LinkModuleToHeap(JSContext *cx, AsmJSModule &module, Handle<ArrayBufferObject*> heap)
{
uint32_t heapLength = heap->byteLength();
if (!IsValidAsmJSHeapLength(heapLength)) {
if (!IsValidAsmJSHeapLength(heap->byteLength())) {
ScopedJSFreePtr<char> msg(
JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next "
"valid length is 0x%x",
heapLength,
RoundUpToNextValidAsmJSHeapLength(heapLength)));
heap->byteLength(),
RoundUpToNextValidAsmJSHeapLength(heap->byteLength())));
return LinkFail(cx, msg.get());
}
// This check is sufficient without considering the size of the loaded datum because heap
// loads and stores start on an aligned boundary and the heap byteLength has larger alignment.
JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX);
if (heapLength < module.minHeapLength()) {
if (heap->byteLength() < module.minHeapLength()) {
ScopedJSFreePtr<char> msg(
JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the"
"largest constant heap access offset rounded up to the next valid "
"heap size).",
heapLength,
heap->byteLength(),
module.minHeapLength()));
return LinkFail(cx, msg.get());
}
@ -461,6 +460,15 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
// the arguments.
const AsmJSModule::ExportedFunction &func = FunctionToExportedFunction(callee, module);
// An asm.js module is specialized to its heap's base address and length
// which is normally immutable except for the neuter operation that occurs
// when an ArrayBuffer is transfered. Throw an internal error if we try to
// run with a neutered heap.
if (module.maybeHeapBufferObject() && module.maybeHeapBufferObject()->isNeutered()) {
js_ReportOverRecursed(cx);
return false;
}
// The calling convention for an external call into asm.js is to pass an
// array of 8-byte values where each value contains either a coerced int32
// (in the low word) or double value, with the coercions specified by the
@ -492,15 +500,6 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
}
}
// An asm.js module is specialized to its heap's base address and length
// which is normally immutable except for the neuter operation that occurs
// when an ArrayBuffer is transfered. Throw an internal error if we're
// about to run with a neutered heap.
if (module.maybeHeapBufferObject() && module.maybeHeapBufferObject()->isNeutered()) {
js_ReportOverRecursed(cx);
return false;
}
{
// Push an AsmJSActivation to describe the asm.js frames we're about to
// push when running this module. Additionally, push a JitActivation so

View File

@ -35,7 +35,6 @@ using namespace js::jit;
using mozilla::DebugOnly;
using mozilla::Maybe;
using mozilla::SafeCast;
class jit::BaselineFrameInspector
{
@ -7081,13 +7080,9 @@ IonBuilder::getElemTryTypedStatic(bool *emitted, MDefinition *obj, MDefinition *
return true;
TypedArrayObject *tarr = &tarrObj->as<TypedArrayObject>();
types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr);
if (tarrType->unknownProperties())
return true;
ArrayBufferView::ViewType viewType = (ArrayBufferView::ViewType) tarr->type();
// LoadTypedArrayElementStatic currently treats uint32 arrays as int32.
ArrayBufferView::ViewType viewType = (ArrayBufferView::ViewType) tarr->type();
if (viewType == ArrayBufferView::TYPE_UINT32)
return true;
@ -7096,7 +7091,6 @@ IonBuilder::getElemTryTypedStatic(bool *emitted, MDefinition *obj, MDefinition *
return true;
// Emit LoadTypedArrayElementStatic.
tarrType->watchStateChangeForTypedArrayData(constraints());
obj->setImplicitlyUsedUnchecked();
index->setImplicitlyUsedUnchecked();
@ -7439,14 +7433,21 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
return pushTypeBarrier(load, types, barrier);
}
void
IonBuilder::addTypedArrayLengthAndData(MDefinition *obj,
BoundsChecking checking,
MDefinition **index,
MInstruction **length, MInstruction **elements)
MInstruction *
IonBuilder::getTypedArrayLength(MDefinition *obj)
{
MOZ_ASSERT((index != nullptr) == (elements != nullptr));
if (obj->isConstant() && obj->toConstant()->value().isObject()) {
TypedArrayObject *tarr = &obj->toConstant()->value().toObject().as<TypedArrayObject>();
int32_t length = (int32_t) tarr->length();
obj->setImplicitlyUsedUnchecked();
return MConstant::New(alloc(), Int32Value(length));
}
return MTypedArrayLength::New(alloc(), obj);
}
MInstruction *
IonBuilder::getTypedArrayElements(MDefinition *obj)
{
if (obj->isConstant() && obj->toConstant()->value().isObject()) {
TypedArrayObject *tarr = &obj->toConstant()->value().toObject().as<TypedArrayObject>();
void *data = tarr->viewData();
@ -7462,36 +7463,14 @@ IonBuilder::addTypedArrayLengthAndData(MDefinition *obj,
// (ArrayBufferObject::changeContents).
types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr);
if (!tarrType->unknownProperties()) {
tarrType->watchStateChangeForTypedArrayData(constraints());
tarrType->watchStateChangeForTypedArrayBuffer(constraints());
obj->setImplicitlyUsedUnchecked();
int32_t len = SafeCast<int32_t>(tarr->length());
*length = MConstant::New(alloc(), Int32Value(len));
current->add(*length);
if (index) {
if (checking == DoBoundsCheck)
*index = addBoundsCheck(*index, *length);
*elements = MConstantElements::New(alloc(), data);
current->add(*elements);
}
return;
return MConstantElements::New(alloc(), data);
}
}
}
*length = MTypedArrayLength::New(alloc(), obj);
current->add(*length);
if (index) {
if (checking == DoBoundsCheck)
*index = addBoundsCheck(*index, *length);
*elements = MTypedArrayElements::New(alloc(), obj);
current->add(*elements);
}
return MTypedArrayElements::New(alloc(), obj);
}
MDefinition *
@ -7583,10 +7562,16 @@ IonBuilder::jsop_getelem_typed(MDefinition *obj, MDefinition *index,
// uint32 reads that may produce either doubles or integers.
MIRType knownType = MIRTypeForTypedArrayRead(arrayType, allowDouble);
// Get length, bounds-check, then get elements, and add all instructions.
MInstruction *length;
MInstruction *elements;
addTypedArrayLengthAndData(obj, DoBoundsCheck, &index, &length, &elements);
// Get the length.
MInstruction *length = getTypedArrayLength(obj);
current->add(length);
// Bounds check.
index = addBoundsCheck(index, length);
// Get the elements vector.
MInstruction *elements = getTypedArrayElements(obj);
current->add(elements);
// Load the element.
MLoadTypedArrayElement *load = MLoadTypedArrayElement::New(alloc(), elements, index, arrayType);
@ -7785,18 +7770,13 @@ IonBuilder::setElemTryTypedStatic(bool *emitted, MDefinition *object,
return true;
#endif
types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr);
if (tarrType->unknownProperties())
return true;
ArrayBufferView::ViewType viewType = (ArrayBufferView::ViewType) tarr->type();
MDefinition *ptr = convertShiftToMaskForStaticTypedArray(index, viewType);
if (!ptr)
return true;
// Emit StoreTypedArrayElementStatic.
tarrType->watchStateChangeForTypedArrayData(constraints());
object->setImplicitlyUsedUnchecked();
index->setImplicitlyUsedUnchecked();
@ -8064,13 +8044,18 @@ IonBuilder::jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
current->add(idInt32);
id = idInt32;
// Get length, bounds-check, then get elements, and add all instructions.
MInstruction *length;
MInstruction *elements;
BoundsChecking checking = (!expectOOB && safety == SetElem_Normal)
? DoBoundsCheck
: SkipBoundsCheck;
addTypedArrayLengthAndData(obj, checking, &id, &length, &elements);
// Get the length.
MInstruction *length = getTypedArrayLength(obj);
current->add(length);
if (!expectOOB && safety == SetElem_Normal) {
// Bounds check.
id = addBoundsCheck(id, length);
}
// Get the elements vector.
MInstruction *elements = getTypedArrayElements(obj);
current->add(elements);
// Clamp value to [0, 255] for Uint8ClampedArray.
MDefinition *toWrite = value;
@ -8171,7 +8156,8 @@ IonBuilder::jsop_length_fastPath()
if (objTypes && objTypes->getTypedArrayType() != ScalarTypeDescr::TYPE_MAX) {
current->pop();
MInstruction *length = addTypedArrayLength(obj);
MInstruction *length = getTypedArrayLength(obj);
current->add(length);
current->push(length);
return true;
}

View File

@ -542,27 +542,9 @@ class IonBuilder : public MIRGenerator
TypeDescrSet elemTypeReprs,
int32_t elemSize);
enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
// Add instructions to compute a typed array's length and data. Also
// optionally convert |*index| into a bounds-checked definition, if
// requested.
//
// If you only need the array's length, use addTypedArrayLength below.
void addTypedArrayLengthAndData(MDefinition *obj,
BoundsChecking checking,
MDefinition **index,
MInstruction **length, MInstruction **elements);
// Add an instruction to compute a typed array's length to the current
// block. If you also need the typed array's data, use the above method
// instead.
MInstruction *addTypedArrayLength(MDefinition *obj) {
MInstruction *length;
addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
return length;
}
// Typed array helpers.
MInstruction *getTypedArrayLength(MDefinition *obj);
MInstruction *getTypedArrayElements(MDefinition *obj);
MDefinition *getCallee();

View File

@ -248,22 +248,18 @@ class AliasSet {
FrameArgument = 1 << 6, // An argument kept on the stack frame
AsmJSGlobalVar = 1 << 7, // An asm.js global var
AsmJSHeap = 1 << 8, // An asm.js heap load
TypedArrayLength = 1 << 9,// A typed array's length
Last = TypedArrayLength,
Last = AsmJSHeap,
Any = Last | (Last - 1),
NumCategories = 10,
NumCategories = 9,
// Indicates load or store.
Store_ = 1 << 31
};
static_assert((1 << NumCategories) - 1 == Any,
"NumCategories must include all flags present in Any");
explicit AliasSet(uint32_t flags)
: flags_(flags)
{
JS_STATIC_ASSERT((1 << NumCategories) - 1 == Any);
}
public:
@ -5894,7 +5890,9 @@ class MTypedArrayLength
return congruentIfOperandsEqual(ins);
}
AliasSet getAliasSet() const {
return AliasSet::Load(AliasSet::TypedArrayLength);
// The typed array |length| property is immutable, so there is no
// implicit dependency.
return AliasSet::None();
}
void computeRange(TempAllocator &alloc);

View File

@ -241,11 +241,11 @@ MSG_DEF(JSMSG_UNUSED187, 187, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
MSG_DEF(JSMSG_UNUSED189, 189, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED190, 190, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_BAD_INDEX, 191, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
MSG_DEF(JSMSG_UNUSED191, 191, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED192, 192, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop")
MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED,194, 0, JSEXN_TYPEERR, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead")
MSG_DEF(JSMSG_TYPE_ERR_BAD_ARGS, 195, 0, JSEXN_TYPEERR, "invalid arguments")
MSG_DEF(JSMSG_UNUSED195, 195, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED196, 196, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_INTERNAL_INTL_ERROR, 197, 0, JSEXN_ERR, "internal error while computing Intl data")
MSG_DEF(JSMSG_DEFAULT_LOCALE_ERROR, 198, 0, JSEXN_ERR, "internal error getting the default locale")

View File

@ -7,7 +7,6 @@
#ifndef jsfriendapi_h
#define jsfriendapi_h
#include "mozilla/Casting.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/TypedEnum.h"
@ -1296,93 +1295,6 @@ JS_IsFloat32Array(JSObject *obj);
extern JS_FRIEND_API(bool)
JS_IsFloat64Array(JSObject *obj);
/*
* Test for specific typed array types (ArrayBufferView subtypes) and return
* the unwrapped object if so, else nullptr. Never throws.
*/
namespace js {
extern JS_FRIEND_API(JSObject *)
UnwrapInt8Array(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapUint8Array(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapUint8ClampedArray(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapInt16Array(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapUint16Array(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapInt32Array(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapUint32Array(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapFloat32Array(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapFloat64Array(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapArrayBuffer(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
UnwrapArrayBufferView(JSObject *obj);
namespace detail {
extern JS_FRIEND_DATA(const Class* const) Int8ArrayClassPtr;
extern JS_FRIEND_DATA(const Class* const) Uint8ArrayClassPtr;
extern JS_FRIEND_DATA(const Class* const) Uint8ClampedArrayClassPtr;
extern JS_FRIEND_DATA(const Class* const) Int16ArrayClassPtr;
extern JS_FRIEND_DATA(const Class* const) Uint16ArrayClassPtr;
extern JS_FRIEND_DATA(const Class* const) Int32ArrayClassPtr;
extern JS_FRIEND_DATA(const Class* const) Uint32ArrayClassPtr;
extern JS_FRIEND_DATA(const Class* const) Float32ArrayClassPtr;
extern JS_FRIEND_DATA(const Class* const) Float64ArrayClassPtr;
const size_t TypedArrayLengthSlot = 4;
} // namespace detail
/*
* Test for specific typed array types (ArrayBufferView subtypes) and return
* the unwrapped object if so, else nullptr. Never throws.
*/
#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
inline void \
Get ## Type ## ArrayLengthAndData(JSObject *obj, uint32_t *length, type **data) \
{ \
JS_ASSERT(GetObjectClass(obj) == detail::Type ## ArrayClassPtr); \
const JS::Value &slot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
*length = mozilla::SafeCast<uint32_t>(slot.toInt32()); \
*data = static_cast<type*>(GetObjectPrivate(obj)); \
}
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32, int32_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
#undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR
// This one isn't inlined because it's rather tricky (by dint of having to deal
// with a dozen-plus classes and varying slot layouts.
extern JS_FRIEND_API(void)
GetArrayBufferViewLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data);
// This one isn't inlined because there are a bunch of different ArrayBuffer
// classes that would have to be individually handled here.
extern JS_FRIEND_API(void)
GetArrayBufferLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data);
} // namespace js
/*
* Unwrap Typed arrays all at once. Return nullptr without throwing if the
* object cannot be viewed as the correct typed array, or the typed array

View File

@ -1596,26 +1596,23 @@ class ConstraintDataFreezeObjectForNewScriptTemplate
}
};
// Constraint which triggers recompilation when a typed array's data becomes
// invalid.
class ConstraintDataFreezeObjectForTypedArrayData
// Constraint which triggers recompilation when the underlying data pointer for
// a typed array changes.
class ConstraintDataFreezeObjectForTypedArrayBuffer
{
void *viewData;
uint32_t length;
public:
explicit ConstraintDataFreezeObjectForTypedArrayData(TypedArrayObject &tarray)
: viewData(tarray.viewData()),
length(tarray.length())
explicit ConstraintDataFreezeObjectForTypedArrayBuffer(void *viewData)
: viewData(viewData)
{}
const char *kind() { return "freezeObjectForTypedArrayData"; }
const char *kind() { return "freezeObjectForTypedArrayBuffer"; }
bool invalidateOnNewType(Type type) { return false; }
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
bool invalidateOnNewObjectState(TypeObject *object) {
TypedArrayObject &tarray = object->singleton()->as<TypedArrayObject>();
return tarray.viewData() != viewData || tarray.length() != length;
return object->singleton()->as<TypedArrayObject>().viewData() != viewData;
}
bool constraintHolds(JSContext *cx,
@ -1655,15 +1652,15 @@ TypeObjectKey::watchStateChangeForNewScriptTemplate(CompilerConstraintList *cons
}
void
TypeObjectKey::watchStateChangeForTypedArrayData(CompilerConstraintList *constraints)
TypeObjectKey::watchStateChangeForTypedArrayBuffer(CompilerConstraintList *constraints)
{
TypedArrayObject &tarray = asSingleObject()->as<TypedArrayObject>();
void *viewData = asSingleObject()->as<TypedArrayObject>().viewData();
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
LifoAlloc *alloc = constraints->alloc();
typedef CompilerConstraintInstance<ConstraintDataFreezeObjectForTypedArrayData> T;
typedef CompilerConstraintInstance<ConstraintDataFreezeObjectForTypedArrayBuffer> T;
constraints->add(alloc->new_<T>(alloc, objectProperty,
ConstraintDataFreezeObjectForTypedArrayData(tarray)));
ConstraintDataFreezeObjectForTypedArrayBuffer(viewData)));
}
static void

View File

@ -1423,7 +1423,7 @@ struct TypeObjectKey
bool hasFlags(CompilerConstraintList *constraints, TypeObjectFlags flags);
void watchStateChangeForInlinedCall(CompilerConstraintList *constraints);
void watchStateChangeForNewScriptTemplate(CompilerConstraintList *constraints);
void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints);
void watchStateChangeForTypedArrayBuffer(CompilerConstraintList *constraints);
HeapTypeSetKey property(jsid id);
void ensureTrackedProperty(JSContext *cx, jsid id);

View File

@ -675,21 +675,18 @@ JSObject *
ArrayBufferObject::createSlice(JSContext *cx, Handle<ArrayBufferObject*> arrayBuffer,
uint32_t begin, uint32_t end)
{
uint32_t bufLength = arrayBuffer->byteLength();
if (begin > bufLength || end > bufLength || begin > end) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPE_ERR_BAD_ARGS);
return nullptr;
}
JS_ASSERT(begin <= arrayBuffer->byteLength());
JS_ASSERT(end <= arrayBuffer->byteLength());
JS_ASSERT(begin <= end);
uint32_t length = end - begin;
if (!arrayBuffer->hasData())
return create(cx, 0);
ArrayBufferObject *slice = create(cx, length);
JSObject *slice = create(cx, length);
if (!slice)
return nullptr;
memcpy(slice->dataPointer(), arrayBuffer->dataPointer() + begin, length);
memcpy(slice->as<ArrayBufferObject>().dataPointer(), arrayBuffer->dataPointer() + begin, length);
return slice;
}
@ -988,14 +985,6 @@ JS_IsArrayBufferViewObject(JSObject *obj)
return obj ? obj->is<ArrayBufferViewObject>() : false;
}
JS_FRIEND_API(JSObject *)
js::UnwrapArrayBufferView(JSObject *obj)
{
if (JSObject *unwrapped = CheckedUnwrap(obj))
return unwrapped->is<ArrayBufferViewObject>() ? unwrapped : nullptr;
return nullptr;
}
JS_FRIEND_API(uint32_t)
JS_GetArrayBufferByteLength(JSObject *obj)
{
@ -1100,14 +1089,6 @@ JS_IsArrayBufferObject(JSObject *obj)
return obj ? obj->is<ArrayBufferObject>() : false;
}
JS_FRIEND_API(JSObject *)
js::UnwrapArrayBuffer(JSObject *obj)
{
if (JSObject *unwrapped = CheckedUnwrap(obj))
return unwrapped->is<ArrayBufferObject>() ? unwrapped : nullptr;
return nullptr;
}
JS_PUBLIC_API(void *)
JS_StealArrayBufferContents(JSContext *cx, HandleObject objArg)
{
@ -1204,20 +1185,6 @@ JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data)
return obj;
}
JS_FRIEND_API(void)
js::GetArrayBufferViewLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data)
{
MOZ_ASSERT(obj->is<ArrayBufferViewObject>());
*length = obj->is<DataViewObject>()
? obj->as<DataViewObject>().byteLength()
: obj->as<TypedArrayObject>().byteLength();
*data = static_cast<uint8_t*>(obj->is<DataViewObject>()
? obj->as<DataViewObject>().dataPointer()
: obj->as<TypedArrayObject>().viewData());
}
JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data)
{
@ -1231,11 +1198,3 @@ JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data)
return obj;
}
JS_FRIEND_API(void)
js::GetArrayBufferLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data)
{
MOZ_ASSERT(IsArrayBuffer(obj));
*length = AsArrayBuffer(obj).byteLength();
*data = AsArrayBuffer(obj).dataPointer();
}

View File

@ -556,25 +556,20 @@ class TypedArrayObjectTemplate : public TypedArrayObject
uint32_t srcEnd;
uint32_t dest;
uint32_t originalLength = tarray->length();
if (!ToClampedIndex(cx, args[0], originalLength, &srcBegin) ||
!ToClampedIndex(cx, args[1], originalLength, &srcEnd) ||
!ToClampedIndex(cx, args[2], originalLength, &dest))
uint32_t length = tarray->length();
if (!ToClampedIndex(cx, args[0], length, &srcBegin) ||
!ToClampedIndex(cx, args[1], length, &srcEnd) ||
!ToClampedIndex(cx, args[2], length, &dest) ||
srcBegin > srcEnd)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
if (srcBegin > srcEnd) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
return false;
}
uint32_t lengthDuringMove = tarray->length(); // beware ToClampedIndex
uint32_t nelts = srcEnd - srcBegin;
MOZ_ASSERT(dest <= INT32_MAX, "size limited to 2**31");
MOZ_ASSERT(nelts <= INT32_MAX, "size limited to 2**31");
if (dest + nelts > lengthDuringMove || srcEnd > lengthDuringMove) {
JS_ASSERT(dest + nelts >= dest);
if (dest + nelts > length) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
@ -654,7 +649,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject
if (!GetLengthProperty(cx, arg0, &len))
return false;
if (uint32_t(offset) > tarray->length() || len > tarray->length() - offset) {
// avoid overflow; we know that offset <= length
if (len > tarray->length() - offset) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
@ -831,9 +827,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
static const NativeType
getIndex(JSObject *obj, uint32_t index)
{
TypedArrayObject &tarray = obj->as<TypedArrayObject>();
MOZ_ASSERT(index < tarray.length());
return static_cast<const NativeType*>(tarray.viewData())[index];
return *(static_cast<const NativeType*>(obj->as<TypedArrayObject>().viewData()) + index);
}
static void
@ -850,10 +844,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject
{
Rooted<TypedArrayObject*> tarray(cx, &tarrayArg->as<TypedArrayObject>());
if (begin > tarray->length() || end > tarray->length() || begin > end) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
return nullptr;
}
JS_ASSERT(begin <= tarray->length());
JS_ASSERT(end <= tarray->length());
if (!ensureHasBuffer(cx, tarray))
return nullptr;
@ -861,6 +853,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
Rooted<ArrayBufferObject *> bufobj(cx, tarray->buffer());
JS_ASSERT(bufobj);
JS_ASSERT(begin <= end);
uint32_t length = end - begin;
JS_ASSERT(begin < UINT32_MAX / sizeof(NativeType));
@ -1084,54 +1077,53 @@ class TypedArrayObjectTemplate : public TypedArrayObject
return false;
js_memcpy(srcbuf, tarray->viewData(), byteLength);
uint32_t len = tarray->length();
switch (tarray->type()) {
case ScalarTypeDescr::TYPE_INT8: {
int8_t *src = (int8_t*) srcbuf;
for (unsigned i = 0; i < len; ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case ScalarTypeDescr::TYPE_UINT8:
case ScalarTypeDescr::TYPE_UINT8_CLAMPED: {
uint8_t *src = (uint8_t*) srcbuf;
for (unsigned i = 0; i < len; ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case ScalarTypeDescr::TYPE_INT16: {
int16_t *src = (int16_t*) srcbuf;
for (unsigned i = 0; i < len; ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case ScalarTypeDescr::TYPE_UINT16: {
uint16_t *src = (uint16_t*) srcbuf;
for (unsigned i = 0; i < len; ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case ScalarTypeDescr::TYPE_INT32: {
int32_t *src = (int32_t*) srcbuf;
for (unsigned i = 0; i < len; ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case ScalarTypeDescr::TYPE_UINT32: {
uint32_t *src = (uint32_t*) srcbuf;
for (unsigned i = 0; i < len; ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case ScalarTypeDescr::TYPE_FLOAT32: {
float *src = (float*) srcbuf;
for (unsigned i = 0; i < len; ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case ScalarTypeDescr::TYPE_FLOAT64: {
double *src = (double*) srcbuf;
for (unsigned i = 0; i < len; ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
@ -1321,13 +1313,6 @@ DataViewObject::create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength,
RootedObject proto(cx, protoArg);
RootedObject obj(cx);
// This is overflow-safe: 2 * INT32_MAX is still a valid uint32_t.
if (byteOffset + byteLength > arrayBuffer->byteLength()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE, "1");
return nullptr;
}
NewObjectKind newKind = DataViewNewObjectKind(cx, byteLength, proto);
obj = NewBuiltinClassInstance(cx, &class_, newKind);
if (!obj)
@ -1454,17 +1439,21 @@ DataViewObject::class_constructor(JSContext *cx, unsigned argc, Value *vp)
return construct(cx, bufobj, args, NullPtr());
}
template <typename NativeType>
/* static */ uint8_t *
DataViewObject::getDataPointer(JSContext *cx, Handle<DataViewObject*> obj, uint32_t offset)
/* static */ bool
DataViewObject::getDataPointer(JSContext *cx, Handle<DataViewObject*> obj,
CallArgs args, size_t typeSize, uint8_t **data)
{
const size_t TypeSize = sizeof(NativeType);
if (offset > UINT32_MAX - TypeSize || offset + TypeSize > obj->byteLength()) {
uint32_t offset;
JS_ASSERT(args.length() > 0);
if (!ToUint32(cx, args[0], &offset))
return false;
if (offset > UINT32_MAX - typeSize || offset + typeSize > obj->byteLength()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE, "1");
return nullptr;
return false;
}
return static_cast<uint8_t*>(obj->dataPointer()) + offset;
*data = static_cast<uint8_t*>(obj->dataPointer()) + offset;
return true;
}
static inline bool
@ -1552,16 +1541,11 @@ DataViewObject::read(JSContext *cx, Handle<DataViewObject*> obj,
return false;
}
uint32_t offset;
if (!ToUint32(cx, args[0], &offset))
uint8_t *data;
if (!getDataPointer(cx, obj, args, sizeof(NativeType), &data))
return false;
bool fromLittleEndian = args.length() >= 2 && ToBoolean(args[1]);
uint8_t *data = DataViewObject::getDataPointer<NativeType>(cx, obj, offset);
if (!data)
return false;
DataViewIO<NativeType>::fromBuffer(val, data, needToSwapBytes(fromLittleEndian));
return true;
}
@ -1609,8 +1593,8 @@ DataViewObject::write(JSContext *cx, Handle<DataViewObject*> obj,
return false;
}
uint32_t offset;
if (!ToUint32(cx, args[0], &offset))
uint8_t *data;
if (!getDataPointer(cx, obj, args, sizeof(NativeType), &data))
return false;
NativeType value;
@ -1618,11 +1602,6 @@ DataViewObject::write(JSContext *cx, Handle<DataViewObject*> obj,
return false;
bool toLittleEndian = args.length() >= 3 && ToBoolean(args[2]);
uint8_t *data = DataViewObject::getDataPointer<NativeType>(cx, obj, offset);
if (!data)
return false;
DataViewIO<NativeType>::toBuffer(data, &value, needToSwapBytes(toLittleEndian));
return true;
}
@ -1960,6 +1939,8 @@ DataViewObject::fun_setFloat64(JSContext *cx, unsigned argc, Value *vp)
Value
TypedArrayObject::getElement(uint32_t index)
{
JS_ASSERT(index < length());
switch (type()) {
case ScalarTypeDescr::TYPE_INT8:
return TypedArrayObjectTemplate<int8_t>::getIndexValue(this, index);
@ -2081,19 +2062,7 @@ const JSFunctionSpec _typedArray##Object::jsfuncs[] = {
return false; \
const Class *clasp = obj->getClass(); \
return clasp == &TypedArrayObject::classes[TypedArrayObjectTemplate<NativeType>::ArrayTypeID()]; \
} \
JS_FRIEND_API(JSObject *) js::Unwrap ## Name ## Array(JSObject *obj) \
{ \
obj = CheckedUnwrap(obj); \
if (!obj) \
return nullptr; \
const Class *clasp = obj->getClass(); \
if (clasp == &TypedArrayObject::classes[TypedArrayObjectTemplate<NativeType>::ArrayTypeID()]) \
return obj; \
return nullptr; \
} \
JS_FRIEND_DATA(const js::Class* const) js::detail::Name ## ArrayClassPtr = \
&js::TypedArrayObject::classes[TypedArrayObjectTemplate<NativeType>::ArrayTypeID()];
}
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int8, int8_t)
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint8, uint8_t)

View File

@ -36,9 +36,6 @@ class TypedArrayObject : public ArrayBufferViewObject
static const size_t RESERVED_SLOTS = JS_TYPEDOBJ_SLOTS;
static const size_t DATA_SLOT = JS_TYPEDOBJ_SLOT_DATA;
static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT,
"bad inlined constant in jsfriendapi.h");
public:
static const Class classes[ScalarTypeDescr::TYPE_MAX];
static const Class protoClasses[ScalarTypeDescr::TYPE_MAX];
@ -99,7 +96,6 @@ class TypedArrayObject : public ArrayBufferViewObject
return getFixedSlot(TYPE_SLOT).toInt32();
}
void *viewData() const {
// Keep synced with js::Get<Type>ArrayLengthAndData in jsfriendapi.h!
return static_cast<void*>(getPrivate(DATA_SLOT));
}
@ -227,10 +223,6 @@ class DataViewObject : public ArrayBufferViewObject
return v.isObject() && v.toObject().hasClass(&class_);
}
template <typename NativeType>
static uint8_t *
getDataPointer(JSContext *cx, Handle<DataViewObject*> obj, uint32_t offset);
template<Value ValueGetter(DataViewObject *view)>
static bool
getterImpl(JSContext *cx, CallArgs args);
@ -337,6 +329,8 @@ class DataViewObject : public ArrayBufferViewObject
static bool initClass(JSContext *cx);
static void neuter(JSObject *view);
static bool getDataPointer(JSContext *cx, Handle<DataViewObject*> obj,
CallArgs args, size_t typeSize, uint8_t **data);
template<typename NativeType>
static bool read(JSContext *cx, Handle<DataViewObject*> obj,
CallArgs &args, NativeType *val, const char *method);

View File

@ -81,17 +81,6 @@ ArrayBufferInputStream::ReadSegments(nsWriteSegmentFun writer, void *closure,
}
uint32_t remaining = mBufferLength - mPos;
if (!mArrayBuffer.empty()) {
JSObject* buf = &mArrayBuffer.ref().get().toObject();
uint32_t byteLength = JS_GetArrayBufferByteLength(buf);
if (byteLength == 0 && remaining != 0) {
mClosed = true;
return NS_BASE_STREAM_CLOSED;
}
} else {
MOZ_ASSERT(remaining == 0, "stream inited incorrectly");
}
if (!remaining) {
*result = 0;
return NS_OK;

View File

@ -18,27 +18,18 @@
* @See nsIBinaryInputStream
* @See nsIBinaryOutputStream
*/
#include <algorithm>
#include <string.h>
#include "nsBinaryStream.h"
#include "mozilla/Endian.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Scoped.h"
#include "nsCRT.h"
#include "nsString.h"
#include "nsISerializable.h"
#include "nsIClassInfo.h"
#include "nsComponentManagerUtils.h"
#include "nsIURI.h" // for NS_IURI_IID
#include "mozilla/Endian.h"
#include "jsfriendapi.h"
using mozilla::PodCopy;
using mozilla::ScopedDeleteArray;
NS_IMPL_ISUPPORTS(nsBinaryOutputStream,
nsIObjectOutputStream,
nsIBinaryOutputStream,
@ -831,50 +822,19 @@ nsBinaryInputStream::ReadArrayBuffer(uint32_t aLength,
return NS_ERROR_FAILURE;
}
JS::RootedObject buffer(aCx, &aBuffer.toObject());
if (!JS_IsArrayBufferObject(buffer)) {
if (!JS_IsArrayBufferObject(buffer) ||
JS_GetArrayBufferByteLength(buffer) < aLength) {
return NS_ERROR_FAILURE;
}
uint32_t bufferLength = JS_GetArrayBufferByteLength(buffer);
if (bufferLength < aLength) {
return NS_ERROR_FAILURE;
}
char* data = reinterpret_cast<char*>(JS_GetStableArrayBufferData(aCx, buffer));
uint8_t* data = JS_GetStableArrayBufferData(aCx, buffer);
if (!data) {
return NS_ERROR_FAILURE;
}
uint32_t bufSize = std::min<uint32_t>(aLength, 4096);
ScopedDeleteArray<char> buf(new char[bufSize]);
uint32_t remaining = aLength;
*rLength = 0;
do {
// Read data into temporary buffer.
uint32_t bytesRead;
uint32_t amount = std::min(remaining, bufSize);
nsresult rv = Read(buf, amount, &bytesRead);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(bytesRead <= amount);
if (bytesRead == 0) {
break;
}
// Copy data into actual buffer.
if (bufferLength != JS_GetArrayBufferByteLength(buffer)) {
return NS_ERROR_FAILURE;
}
*rLength += bytesRead;
PodCopy(data, buf.get(), bytesRead);
remaining -= bytesRead;
data += bytesRead;
} while (remaining > 0);
nsresult rv = Read(reinterpret_cast<char*>(data), aLength, rLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}