Bug 1165053 - Part 1: Handle when ArrayBuffer species constructor returns wrapped ArrayBuffer. r=jwalden

This commit is contained in:
Tooru Fujisawa 2016-01-14 15:11:26 +09:00
parent 6e95072f22
commit f28ae392ef
2 changed files with 70 additions and 20 deletions

View File

@ -1308,7 +1308,7 @@ function TypedArrayStaticOf(/*...items*/) {
return newObj; return newObj;
} }
// ES 2016 draft Dec 10, 2015 24.1.4.3. // ES 2016 draft Mar 25, 2016 24.1.4.3.
function ArrayBufferSlice(start, end) { function ArrayBufferSlice(start, end) {
// Step 1. // Step 1.
var O = this; var O = this;
@ -1351,33 +1351,47 @@ function ArrayBufferSlice(start, end) {
// Step 12. // Step 12.
var new_ = new ctor(newLen); var new_ = new ctor(newLen);
// Step 13. var isWrapped = false;
if (!IsArrayBuffer(new_)) if (IsArrayBuffer(new_)) {
ThrowTypeError(JSMSG_NON_ARRAY_BUFFER_RETURNED); // Step 14.
if (IsDetachedBuffer(new_))
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
} else {
// Step 13.
if (!IsWrappedArrayBuffer(new_))
ThrowTypeError(JSMSG_NON_ARRAY_BUFFER_RETURNED);
// Step 14. isWrapped = true;
if (IsDetachedBuffer(new_))
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); // Step 14.
if (callFunction(CallArrayBufferMethodIfWrapped, new_, "IsDetachedBufferThis"))
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
}
// Step 15. // Step 15.
if (new_ == O) if (new_ === O)
ThrowTypeError(JSMSG_SAME_ARRAY_BUFFER_RETURNED); ThrowTypeError(JSMSG_SAME_ARRAY_BUFFER_RETURNED);
// Step 16. // Step 16.
if (ArrayBufferByteLength(new_) < newLen) var actualLen = PossiblyWrappedArrayBufferByteLength(new_);
ThrowTypeError(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, newLen, ArrayBufferByteLength(new_)); if (actualLen < newLen)
ThrowTypeError(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, newLen, actualLen);
// Step 18. // Step 18.
if (IsDetachedBuffer(O)) if (IsDetachedBuffer(O))
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
// Steps 19-21. // Steps 19-21.
ArrayBufferCopyData(new_, O, first | 0, newLen | 0); ArrayBufferCopyData(new_, O, first | 0, newLen | 0, isWrapped);
// Step 22. // Step 22.
return new_; return new_;
} }
function IsDetachedBufferThis() {
return IsDetachedBuffer(this);
}
function ArrayBufferStaticSlice(buf, start, end) { function ArrayBufferStaticSlice(buf, start, end) {
if (arguments.length < 1) if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'ArrayBuffer.slice'); ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'ArrayBuffer.slice');

View File

@ -41,6 +41,7 @@
#include "vm/Interpreter.h" #include "vm/Interpreter.h"
#include "vm/String.h" #include "vm/String.h"
#include "vm/TypedArrayCommon.h" #include "vm/TypedArrayCommon.h"
#include "vm/WrapperObject.h"
#include "jsfuninlines.h" #include "jsfuninlines.h"
#include "jsobjinlines.h" #include "jsobjinlines.h"
@ -868,6 +869,33 @@ intrinsic_GeneratorSetClosed(JSContext* cx, unsigned argc, Value* vp)
return true; return true;
} }
static bool
intrinsic_IsWrappedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
if (!args[0].isObject()) {
args.rval().setBoolean(false);
return true;
}
JSObject* obj = &args[0].toObject();
if (!obj->is<WrapperObject>()) {
args.rval().setBoolean(false);
return true;
}
JSObject* unwrapped = CheckedUnwrap(obj);
if (!unwrapped) {
JS_ReportError(cx, "Permission denied to access object");
return false;
}
args.rval().setBoolean(unwrapped->is<ArrayBufferObject>());
return true;
}
static bool static bool
intrinsic_ArrayBufferByteLength(JSContext* cx, unsigned argc, Value* vp) intrinsic_ArrayBufferByteLength(JSContext* cx, unsigned argc, Value* vp)
{ {
@ -902,15 +930,22 @@ static bool
intrinsic_ArrayBufferCopyData(JSContext* cx, unsigned argc, Value* vp) intrinsic_ArrayBufferCopyData(JSContext* cx, unsigned argc, Value* vp)
{ {
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 4); MOZ_ASSERT(args.length() == 5);
MOZ_ASSERT(args[0].isObject());
MOZ_ASSERT(args[0].toObject().is<ArrayBufferObject>());
MOZ_ASSERT(args[1].isObject());
MOZ_ASSERT(args[1].toObject().is<ArrayBufferObject>());
MOZ_ASSERT(args[2].isInt32());
MOZ_ASSERT(args[3].isInt32());
Rooted<ArrayBufferObject*> toBuffer(cx, &args[0].toObject().as<ArrayBufferObject>()); bool isWrapped = args[4].toBoolean();
Rooted<ArrayBufferObject*> toBuffer(cx);
if (!isWrapped) {
toBuffer = &args[0].toObject().as<ArrayBufferObject>();
} else {
JSObject* wrapped = &args[0].toObject();
MOZ_ASSERT(wrapped->is<WrapperObject>());
RootedObject toBufferObj(cx, CheckedUnwrap(wrapped));
if (!toBufferObj) {
JS_ReportError(cx, "Permission denied to access object");
return false;
}
toBuffer = toBufferObj.as<ArrayBufferObject>();
}
Rooted<ArrayBufferObject*> fromBuffer(cx, &args[1].toObject().as<ArrayBufferObject>()); Rooted<ArrayBufferObject*> fromBuffer(cx, &args[1].toObject().as<ArrayBufferObject>());
uint32_t fromIndex = uint32_t(args[2].toInt32()); uint32_t fromIndex = uint32_t(args[2].toInt32());
uint32_t count = uint32_t(args[3].toInt32()); uint32_t count = uint32_t(args[3].toInt32());
@ -2167,12 +2202,13 @@ static const JSFunctionSpec intrinsic_functions[] = {
intrinsic_IsInstanceOfBuiltin<ArrayBufferObject>, 1,0), intrinsic_IsInstanceOfBuiltin<ArrayBufferObject>, 1,0),
JS_FN("IsSharedArrayBuffer", JS_FN("IsSharedArrayBuffer",
intrinsic_IsInstanceOfBuiltin<SharedArrayBufferObject>, 1,0), intrinsic_IsInstanceOfBuiltin<SharedArrayBufferObject>, 1,0),
JS_FN("IsWrappedArrayBuffer", intrinsic_IsWrappedArrayBuffer, 1,0),
JS_INLINABLE_FN("ArrayBufferByteLength", intrinsic_ArrayBufferByteLength, 1,0, JS_INLINABLE_FN("ArrayBufferByteLength", intrinsic_ArrayBufferByteLength, 1,0,
IntrinsicArrayBufferByteLength), IntrinsicArrayBufferByteLength),
JS_INLINABLE_FN("PossiblyWrappedArrayBufferByteLength", intrinsic_PossiblyWrappedArrayBufferByteLength, 1,0, JS_INLINABLE_FN("PossiblyWrappedArrayBufferByteLength", intrinsic_PossiblyWrappedArrayBufferByteLength, 1,0,
IntrinsicPossiblyWrappedArrayBufferByteLength), IntrinsicPossiblyWrappedArrayBufferByteLength),
JS_FN("ArrayBufferCopyData", intrinsic_ArrayBufferCopyData, 4,0), JS_FN("ArrayBufferCopyData", intrinsic_ArrayBufferCopyData, 5,0),
JS_FN("IsUint8TypedArray", intrinsic_IsUint8TypedArray, 1,0), JS_FN("IsUint8TypedArray", intrinsic_IsUint8TypedArray, 1,0),
JS_FN("IsInt8TypedArray", intrinsic_IsInt8TypedArray, 1,0), JS_FN("IsInt8TypedArray", intrinsic_IsInt8TypedArray, 1,0),