mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Backed out changeset 2c631967ab9e (bug 999651) for B2G crashes.
CLOSED TREE
This commit is contained in:
parent
68337a62cb
commit
095b86b386
@ -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;
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user