diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 3a29e928a69..abc904a51bc 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1741,7 +1741,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj) } #define CLASP(name) (&name##Class) -#define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type]) +#define TYPED_ARRAY_CLASP(type) (&TypedArray::classes[TypedArray::type]) #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name) diff --git a/js/src/jsclone.cpp b/js/src/jsclone.cpp index 5092127567b..634fa7eb5d6 100644 --- a/js/src/jsclone.cpp +++ b/js/src/jsclone.cpp @@ -434,9 +434,8 @@ JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v) } bool -JSStructuredCloneWriter::writeTypedArray(JSObject *obj) +JSStructuredCloneWriter::writeTypedArray(JSObject *arr) { - JSObject *arr = TypedArray::getTypedArray(obj); if (!out.writePair(ArrayTypeToTag(TypedArray::getType(arr)), TypedArray::getLength(arr))) return false; @@ -750,27 +749,26 @@ JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp return false; vp->setObject(*obj); - JSObject *arr = TypedArray::getTypedArray(obj); - JS_ASSERT(TypedArray::getLength(arr) == nelems); + JS_ASSERT(TypedArray::getLength(obj) == nelems); switch (tag) { case SCTAG_TYPED_ARRAY_INT8: - return in.readArray((uint8_t *) JS_GetInt8ArrayData(arr, context()), nelems); + return in.readArray((uint8_t*) JS_GetInt8ArrayData(obj, context()), nelems); case SCTAG_TYPED_ARRAY_UINT8: - return in.readArray((uint8_t *) JS_GetUint8ArrayData(arr, context()), nelems); + return in.readArray(JS_GetUint8ArrayData(obj, context()), nelems); case SCTAG_TYPED_ARRAY_INT16: - return in.readArray((uint16_t *) JS_GetInt16ArrayData(arr, context()), nelems); + return in.readArray((uint16_t*) JS_GetInt16ArrayData(obj, context()), nelems); case SCTAG_TYPED_ARRAY_UINT16: - return in.readArray((uint16_t *) JS_GetUint16ArrayData(arr, context()), nelems); + return in.readArray(JS_GetUint16ArrayData(obj, context()), nelems); case SCTAG_TYPED_ARRAY_INT32: - return in.readArray((uint32_t *) JS_GetInt32ArrayData(arr, context()), nelems); + return in.readArray((uint32_t*) JS_GetInt32ArrayData(obj, context()), nelems); case SCTAG_TYPED_ARRAY_UINT32: - return in.readArray((uint32_t *) JS_GetUint32ArrayData(arr, context()), nelems); + return in.readArray(JS_GetUint32ArrayData(obj, context()), nelems); case SCTAG_TYPED_ARRAY_FLOAT32: - return in.readArray((uint32_t *) JS_GetFloat32ArrayData(arr, context()), nelems); + return in.readArray((uint32_t*) JS_GetFloat32ArrayData(obj, context()), nelems); case SCTAG_TYPED_ARRAY_FLOAT64: - return in.readArray((uint64_t *) JS_GetFloat64ArrayData(arr, context()), nelems); + return in.readArray((uint64_t*) JS_GetFloat64ArrayData(obj, context()), nelems); case SCTAG_TYPED_ARRAY_UINT8_CLAMPED: - return in.readArray((uint8_t *) JS_GetUint8ClampedArrayData(arr, context()), nelems); + return in.readArray(JS_GetUint8ClampedArrayData(obj, context()), nelems); default: JS_NOT_REACHED("unknown TypedArray type"); return false; diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 356f28e5e76..594ad24806d 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -233,8 +233,7 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp } if (obj->isTypedArray()) { - JSObject *tarray = TypedArray::getTypedArray(obj); - *vp = Int32Value(TypedArray::getLength(tarray)); + *vp = Int32Value(TypedArray::getLength(obj)); return true; } } diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index a05097b61e5..669deb74e3f 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -811,7 +811,7 @@ inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); } inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); } inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); } inline bool JSObject::isString() const { return hasClass(&js::StringClass); } -inline bool JSObject::isTypedArray() const { return IsFastTypedArrayClass(getClass()); } +inline bool JSObject::isTypedArray() const { return IsTypedArrayClass(getClass()); } inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); } inline bool JSObject::isWith() const { return hasClass(&js::WithClass); } inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); } diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 3636896d0f7..aacafa18b9c 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -138,29 +138,27 @@ ToClampedIndex(JSContext *cx, const Value &v, int32_t length, int32_t *out) */ /** - * Walks up the prototype chain to find the actual ArrayBuffer data. - * This MAY return NULL. Callers should always use isArrayBuffer() - * first. + * Walks up the prototype chain to find the actual ArrayBuffer data, if any. */ -JSObject * -ArrayBufferObject::getArrayBuffer(JSObject *obj) +static ArrayBufferObject * +getArrayBuffer(JSObject *obj) { while (obj && !obj->isArrayBuffer()) obj = obj->getProto(); - return obj; + return obj ? &obj->asArrayBuffer() : NULL; } JSBool ArrayBufferObject::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - JSObject *bufobj = getArrayBuffer(obj); - if (!bufobj) { - vp->setInt32(0); - return true; + ArrayBufferObject *buffer = getArrayBuffer(obj); + if (!buffer) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_INCOMPATIBLE_PROTO, "ArrayBuffer", "byteLength", "object"); + return false; } - ArrayBufferObject &arrayBuffer = bufobj->asArrayBuffer(); - vp->setInt32(int32_t(arrayBuffer.byteLength())); + vp->setInt32(int32_t(buffer->byteLength())); return true; } @@ -505,7 +503,15 @@ ArrayBufferObject::obj_getProperty(JSContext *cx, JSObject *obj_, RootedVarObject obj(cx, obj_), receiver(cx, receiver_); RootedVarPropertyName name(cx, name_); - obj = getArrayBuffer(obj); + if (!(obj = getArrayBuffer(obj))) { + JSAutoByteString bs(cx, name); + if (!bs) + return false; + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_INCOMPATIBLE_PROTO, "ArrayBuffer", bs.ptr(), "object"); + return false; + } + if (name == cx->runtime->atomState.byteLengthAtom) { vp->setInt32(obj->asArrayBuffer().byteLength()); return true; @@ -787,12 +793,15 @@ ArrayBufferObject::obj_typeOf(JSContext *cx, JSObject *obj) * the subclasses. */ -JSObject * -TypedArray::getTypedArray(JSObject *obj) +static JSObject * +getTypedArray(JSObject *obj) { - while (!obj->isTypedArray()) - obj = obj->getProto(); - return obj; + MOZ_ASSERT(obj); + do { + if (obj->isTypedArray()) + return obj; + } while ((obj = obj->getProto())); + return NULL; } inline bool @@ -808,75 +817,60 @@ TypedArray::isArrayIndex(JSContext *cx, JSObject *obj, jsid id, uint32_t *ip) return false; } -typedef Value (* TypedArrayPropertyGetter)(JSObject *tarray); - -template -class TypedArrayGetter { - public: - static inline bool get(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - do { - if (obj->isTypedArray()) { - JSObject *tarray = TypedArray::getTypedArray(obj); - if (tarray) - *vp = Get(tarray); - return true; - } - } while ((obj = obj->getProto()) != NULL); - return true; - } -}; - /* * For now (until slots directly hold data) * slots data element points to the JSObject representing the ArrayBuffer. */ -inline Value -getBufferValue(JSObject *tarray) -{ - JSObject *buffer = TypedArray::getBuffer(tarray); - return ObjectValue(*buffer); -} - JSBool TypedArray::prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return TypedArrayGetter::get(cx, obj, id, vp); -} + if (!(obj = getTypedArray(obj))) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "buffer", "object"); + return false; + } -inline Value -getByteOffsetValue(JSObject *tarray) -{ - return Int32Value(TypedArray::getByteOffset(tarray)); + JS_SET_RVAL(cx, vp, ObjectValue(*TypedArray::getBuffer(obj))); + return true; } JSBool TypedArray::prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return TypedArrayGetter::get(cx, obj, id, vp); -} + if (!(obj = getTypedArray(obj))) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "byteOffset", "object"); + return false; + } -inline Value -getByteLengthValue(JSObject *tarray) -{ - return Int32Value(TypedArray::getByteLength(tarray)); + JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getByteOffset(obj))); + return true; } JSBool TypedArray::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return TypedArrayGetter::get(cx, obj, id, vp); -} + if (!(obj = getTypedArray(obj))) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "byteLength", "object"); + return false; + } -inline Value -getLengthValue(JSObject *tarray) -{ - return Int32Value(TypedArray::getLength(tarray)); + JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getByteLength(obj))); + return true; } JSBool TypedArray::prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return TypedArrayGetter::get(cx, obj, id, vp); + if (!(obj = getTypedArray(obj))) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "length", "object"); + return false; + } + + JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getLength(obj))); + return true; } JSBool @@ -1090,7 +1084,7 @@ class TypedArrayTemplate static inline Class *fastClass() { - return &TypedArray::fastClasses[ArrayTypeID()]; + return &TypedArray::classes[ArrayTypeID()]; } static void @@ -1354,7 +1348,7 @@ class TypedArrayTemplate static JSBool obj_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict) { - JSObject *tarray = TypedArray::getTypedArray(obj); + JSObject *tarray = getTypedArray(obj); JS_ASSERT(tarray); if (index < getLength(tarray)) { @@ -1627,56 +1621,52 @@ class TypedArrayTemplate if (!tarray) return true; - // these are the default values - int32_t off = 0; + // first arg must be either a typed array or a JS array + if (args.length() == 0 || !args[0].isObject()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS); + return false; + } + int32_t offset = 0; if (args.length() > 1) { - if (!ToInt32(cx, args[1], &off)) + if (!ToInt32(cx, args[1], &offset)) return false; - if (off < 0 || uint32_t(off) > getLength(tarray)) { + if (offset < 0 || uint32_t(offset) > getLength(tarray)) { // the given offset is bogus - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TYPED_ARRAY_BAD_ARGS); + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_INDEX, "2"); return false; } } - uint32_t offset(off); - - // first arg must be either a typed array or a JS array - if (args.length() == 0 || !args[0].isObject()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TYPED_ARRAY_BAD_ARGS); + if (!args[0].isObject()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } RootedVarObject arg0(cx, args[0].toObjectOrNull()); - if (arg0->isTypedArray()) { - JSObject *src = TypedArray::getTypedArray(arg0); - if (!src || - getLength(src) > getLength(tarray) - offset) - { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TYPED_ARRAY_BAD_ARGS); + RootedVarObject src(getTypedArray(arg0)); + if (src) { + if (getLength(src) > getLength(tarray) - offset) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH); return false; } if (!copyFromTypedArray(cx, obj, src, offset)) return false; } else { + src = arg0; uint32_t len; - if (!js_GetLengthProperty(cx, arg0, &len)) + if (!js_GetLengthProperty(cx, src, &len)) return false; // avoid overflow; we know that offset <= length if (len > getLength(tarray) - offset) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TYPED_ARRAY_BAD_ARGS); + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH); return false; } - if (!copyFromArray(cx, obj, arg0, len, offset)) + if (!copyFromArray(cx, obj, src, len, offset)) return false; } @@ -2145,10 +2135,7 @@ TypedArrayTemplate::copyIndexToValue(JSContext *cx, JSObject *tarray, uin * This could be removed for platforms/compilers known to convert a 32-bit * non-canonical nan to a 64-bit canonical nan. */ - if (JS_UNLIKELY(MOZ_DOUBLE_IS_NaN(dval))) - dval = js_NaN; - - vp->setDouble(dval); + vp->setDouble(JS_CANONICALIZE_NAN(dval)); } template<> @@ -2335,7 +2322,7 @@ NewArrayWithBuffer(JSContext *cx, HandleObject arrayBuffer, int32_t byteoffset, { \ obj = UnwrapObject(obj); \ Class *clasp = obj->getClass(); \ - return (clasp == &TypedArray::fastClasses[TypedArrayTemplate::ArrayTypeID()]); \ + return (clasp == &TypedArray::classes[TypedArrayTemplate::ArrayTypeID()]); \ } IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int8, int8_t) @@ -2350,7 +2337,7 @@ IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float64, double) #define IMPL_TYPED_ARRAY_PROTO_CLASS(_typedArray) \ { \ - #_typedArray, \ + #_typedArray "Prototype", \ JSCLASS_HAS_RESERVED_SLOTS(TypedArray::FIELD_MAX) | \ JSCLASS_HAS_PRIVATE | \ JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \ @@ -2475,7 +2462,7 @@ IMPL_TYPED_ARRAY_STATICS(Float32Array); IMPL_TYPED_ARRAY_STATICS(Float64Array); IMPL_TYPED_ARRAY_STATICS(Uint8ClampedArray); -Class TypedArray::fastClasses[TYPE_MAX] = { +Class TypedArray::classes[TYPE_MAX] = { IMPL_TYPED_ARRAY_FAST_CLASS(Int8Array), IMPL_TYPED_ARRAY_FAST_CLASS(Uint8Array), IMPL_TYPED_ARRAY_FAST_CLASS(Int16Array), @@ -2554,27 +2541,6 @@ js_InitTypedArrayClasses(JSContext *cx, JSObject *obj) return InitArrayBufferClass(cx, global); } -bool -js::IsFastTypedArrayClass(const Class *clasp) -{ - return &TypedArray::fastClasses[0] <= clasp && - clasp < &TypedArray::fastClasses[TypedArray::TYPE_MAX]; -} - -static inline bool -IsSlowTypedArrayClass(const Class *clasp) -{ - return &TypedArray::protoClasses[0] <= clasp && - clasp < &TypedArray::protoClasses[TypedArray::TYPE_MAX]; -} - -bool -js::IsFastOrSlowTypedArray(JSObject *obj) -{ - Class *clasp = obj->getClass(); - return IsFastTypedArrayClass(clasp) || IsSlowTypedArrayClass(clasp); -} - /* JS Friend API */ JS_FRIEND_API(JSBool) diff --git a/js/src/jstypedarray.h b/js/src/jstypedarray.h index 2874179b45d..dfbbc1120c4 100644 --- a/js/src/jstypedarray.h +++ b/js/src/jstypedarray.h @@ -161,9 +161,6 @@ class ArrayBufferObject : public JSObject static JSType obj_typeOf(JSContext *cx, JSObject *obj); - static JSObject * - getArrayBuffer(JSObject *obj); - bool allocateSlots(JSContext *cx, uint32_t size, uint8_t *contents = NULL); @@ -218,7 +215,7 @@ struct TypedArray { }; // and MUST NOT be used to construct new objects. - static Class fastClasses[TYPE_MAX]; + static Class classes[TYPE_MAX]; // These are the proto/original classes, used // fo constructing new objects @@ -226,8 +223,6 @@ struct TypedArray { static JSPropertySpec jsprops[]; - static JSObject *getTypedArray(JSObject *obj); - static JSBool prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp); static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp); static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp); @@ -292,14 +287,31 @@ struct TypedArray { static int dataOffset(); }; -bool -IsFastOrSlowTypedArray(JSObject *obj); +inline bool +IsTypedArrayClass(const Class *clasp) +{ + return &TypedArray::classes[0] <= clasp && + clasp < &TypedArray::classes[TypedArray::TYPE_MAX]; +} -bool -IsFastOrSlowTypedArrayClass(const Class *clasp); +inline bool +IsTypedArrayProtoClass(const Class *clasp) +{ + return &TypedArray::protoClasses[0] <= clasp && + clasp < &TypedArray::protoClasses[TypedArray::TYPE_MAX]; +} -bool -IsFastTypedArrayClass(const Class *clasp); +inline bool +IsTypedArray(JSObject *obj) +{ + return IsTypedArrayClass(obj->getClass()); +} + +inline bool +IsTypedArrayProto(JSObject *obj) +{ + return IsTypedArrayProtoClass(obj->getClass()); +} } // namespace js diff --git a/js/src/jstypedarrayinlines.h b/js/src/jstypedarrayinlines.h index 228897e9ae4..75347504d34 100644 --- a/js/src/jstypedarrayinlines.h +++ b/js/src/jstypedarrayinlines.h @@ -83,37 +83,37 @@ ClampIntForUint8Array(int32_t x) inline uint32_t TypedArray::getLength(JSObject *obj) { - JS_ASSERT(IsFastOrSlowTypedArray(obj)); + JS_ASSERT(obj->isTypedArray()); return obj->getFixedSlot(FIELD_LENGTH).toInt32(); } inline uint32_t TypedArray::getByteOffset(JSObject *obj) { - JS_ASSERT(IsFastOrSlowTypedArray(obj)); + JS_ASSERT(obj->isTypedArray()); return obj->getFixedSlot(FIELD_BYTEOFFSET).toInt32(); } inline uint32_t TypedArray::getByteLength(JSObject *obj) { - JS_ASSERT(IsFastOrSlowTypedArray(obj)); + JS_ASSERT(obj->isTypedArray()); return obj->getFixedSlot(FIELD_BYTELENGTH).toInt32(); } inline uint32_t TypedArray::getType(JSObject *obj) { - JS_ASSERT(IsFastOrSlowTypedArray(obj)); + JS_ASSERT(obj->isTypedArray()); return obj->getFixedSlot(FIELD_TYPE).toInt32(); } inline ArrayBufferObject * TypedArray::getBuffer(JSObject *obj) { - JS_ASSERT(IsFastOrSlowTypedArray(obj)); + JS_ASSERT(obj->isTypedArray()); return &obj->getFixedSlot(FIELD_BUFFER).toObject().asArrayBuffer(); } inline void * TypedArray::getDataOffset(JSObject *obj) { - JS_ASSERT(IsFastOrSlowTypedArray(obj)); + JS_ASSERT(obj->isTypedArray()); return (void *)obj->getPrivate(NUM_FIXED_SLOTS); } diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index b3332411af6..c8255c6d893 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -2319,17 +2319,16 @@ GetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid i ? Int32Key::FromConstant(v.toInt32()) : Int32Key::FromRegister(idRemat.dataReg()); - JSObject *tarray = js::TypedArray::getTypedArray(obj); if (!masm.supportsFloatingPoint() && - (TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32 || - TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT64 || - TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT32)) + (TypedArray::getType(obj) == TypedArray::TYPE_FLOAT32 || + TypedArray::getType(obj) == TypedArray::TYPE_FLOAT64 || + TypedArray::getType(obj) == TypedArray::TYPE_UINT32)) { return disable(f, "fpu not supported"); } MaybeRegisterID tempReg; - masm.loadFromTypedArray(TypedArray::getType(tarray), objReg, key, typeReg, objReg, tempReg); + masm.loadFromTypedArray(TypedArray::getType(obj), objReg, key, typeReg, objReg, tempReg); Jump done = masm.jump(); @@ -2633,18 +2632,17 @@ SetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, int32_t key) // Load the array's packed data vector. masm.loadPtr(Address(objReg, TypedArray::dataOffset()), objReg); - JSObject *tarray = js::TypedArray::getTypedArray(obj); if (!masm.supportsFloatingPoint() && - (TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32 || - TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT64)) + (TypedArray::getType(obj) == TypedArray::TYPE_FLOAT32 || + TypedArray::getType(obj) == TypedArray::TYPE_FLOAT64)) { return disable(f, "fpu not supported"); } - int shift = js::TypedArray::slotWidth(obj); + int shift = TypedArray::slotWidth(obj); if (hasConstantKey) { Address addr(objReg, keyValue * shift); - if (!StoreToTypedArray(cx, masm, tarray, addr, vr, volatileMask)) + if (!StoreToTypedArray(cx, masm, obj, addr, vr, volatileMask)) return error(cx); } else { Assembler::Scale scale = Assembler::TimesOne; @@ -2660,7 +2658,7 @@ SetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, int32_t key) break; } BaseIndex addr(objReg, keyReg, scale); - if (!StoreToTypedArray(cx, masm, tarray, addr, vr, volatileMask)) + if (!StoreToTypedArray(cx, masm, obj, addr, vr, volatileMask)) return error(cx); } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 20aa01878d6..e3cf054398f 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3409,17 +3409,16 @@ Deserialize(JSContext *cx, unsigned argc, jsval *vp) JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize"); return false; } - JSObject *array = TypedArray::getTypedArray(obj); - if ((TypedArray::getByteLength(array) & 7) != 0) { + if ((TypedArray::getByteLength(obj) & 7) != 0) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize"); return false; } - if ((uintptr_t(TypedArray::getDataOffset(array)) & 7) != 0) { + if ((uintptr_t(TypedArray::getDataOffset(obj)) & 7) != 0) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_BAD_ALIGNMENT); return false; } - if (!JS_ReadStructuredClone(cx, (uint64_t *) TypedArray::getDataOffset(array), TypedArray::getByteLength(array), + if (!JS_ReadStructuredClone(cx, (uint64_t *) TypedArray::getDataOffset(obj), TypedArray::getByteLength(obj), JS_STRUCTURED_CLONE_VERSION, v.address(), NULL, NULL)) { return false; } diff --git a/js/src/tests/js1_8_5/extensions/typedarray.js b/js/src/tests/js1_8_5/extensions/typedarray.js index d579e5b7a28..300c26248aa 100644 --- a/js/src/tests/js1_8_5/extensions/typedarray.js +++ b/js/src/tests/js1_8_5/extensions/typedarray.js @@ -28,7 +28,7 @@ function test() var TODO = 1; - function check(fun, todo) { + function check(fun, msg, todo) { var thrown = null; var success = false; try { @@ -60,6 +60,8 @@ function test() var ex = new Error; print ("=== FAILED ==="); + if (msg) + print (msg); print (ex.stack); if (thrown) { print (" threw exception:"); @@ -69,18 +71,29 @@ function test() } } - function checkThrows(fun, todo) { - let thrown = false; + function checkThrows(fun, type, todo) { + var thrown = false; try { fun(); } catch (x) { - thrown = true; + thrown = x; } - check(function() thrown, todo); + if (typeof(type) !== 'undefined') + if (thrown) { + check(function () thrown instanceof type, + "expected " + type.name + " but saw " + thrown, + todo); + } else { + check(function () thrown, "expected " + type.name + " but no exception thrown", todo); + } + else + check(function () thrown, undefined, todo); } - check(function() ArrayBuffer.prototype.byteLength == 0); + function checkThrowsTODO(fun, type) { + checkThrows(fun, type, true); + } var buf, buf2; @@ -101,9 +114,9 @@ function test() var zerobuf2 = new ArrayBuffer(); check(function() zerobuf2.byteLength == 0); - checkThrows(function() new ArrayBuffer(-100)); + checkThrows(function() new ArrayBuffer(-100), RangeError); // this is using js_ValueToECMAUInt32, which is giving 0 for "abc" - checkThrows(function() new ArrayBuffer("abc"), TODO); + checkThrowsTODO(function() new ArrayBuffer("abc"), TypeError); var zeroarray = new Int32Array(0); check(function() zeroarray.length == 0); @@ -187,15 +200,15 @@ function test() check(function() a[1] == 0xbb); // not sure if this is supposed to throw or to treat "foo"" as 0. - checkThrows(function() new Int32Array([0xaa, "foo", 0xbb]), TODO); + checkThrowsTODO(function() new Int32Array([0xaa, "foo", 0xbb]), Error); checkThrows(function() new Int32Array(-100)); a = new Uint8Array(3); // XXX these are ignored now and return undefined - //checkThrows(function() a[5000] = 0); - //checkThrows(function() a["hello"] = 0); - //checkThrows(function() a[-10] = 0); + //checkThrows(function() a[5000] = 0, RangeError); + //checkThrows(function() a["hello"] = 0, TypeError); + //checkThrows(function() a[-10] = 0, RangeError); check(function() (a[0] = "10") && (a[0] == 10)); // check Uint8ClampedArray, which is an extension to this extension @@ -265,8 +278,8 @@ function test() checkThrows(function() a.set([1,2,3], 2147483647)); a.set(ArrayBuffer.prototype); - a.set(Int16Array.prototype); - a.set(Int32Array.prototype); + checkThrows(function () a.set(Int16Array.prototype), TypeError); + checkThrows(function () a.set(Int32Array.prototype), TypeError); a.set([1,2,3]); a.set([4,5,6], 3); @@ -317,16 +330,43 @@ function test() a = new Uint8Array(0x100); checkThrows(function() Uint32Array.prototype.subarray.apply(a, [0, 0x100])); - // The prototypes are objects that don't have a length property, so they act - // like empty arrays. - check(function() new Int32Array(ArrayBuffer.prototype).length == 0); - check(function() new Int32Array(Int32Array.prototype).length == 0); - check(function() new Int32Array(Float64Array.prototype).length == 0); + // webidl section 4.4.6, getter bullet point 2.2: prototypes are not + // platform objects, and calling the getter of any attribute defined on the + // interface should throw a TypeError according to + checkThrows(function() ArrayBuffer.prototype.byteLength, TypeError); + checkThrows(function() Int32Array.prototype.length, TypeError); + checkThrows(function() Int32Array.prototype.byteLength, TypeError); + checkThrows(function() Int32Array.prototype.byteOffset, TypeError); + checkThrows(function() Float64Array.prototype.length, TypeError); + checkThrows(function() Float64Array.prototype.byteLength, TypeError); + checkThrows(function() Float64Array.prototype.byteOffset, TypeError); - // ArrayBuffer, Int32Array and Float64Array are native functions and have a .length - // checkThrows(function() new Int32Array(ArrayBuffer)); - // checkThrows(function() new Int32Array(Int32Array)); - // checkThrows(function() new Int32Array(Float64Array)); + // webidl 4.4.6: a readonly attribute's setter is undefined. From + // observation, that seems to mean it silently does nothing, and returns + // the value that you tried to set it to. + check(function() Int32Array.prototype.length = true); + check(function() Float64Array.prototype.length = true); + check(function() Int32Array.prototype.byteLength = true); + check(function() Float64Array.prototype.byteLength = true); + check(function() Int32Array.prototype.byteOffset = true); + check(function() Float64Array.prototype.byteOffset = true); + + // ArrayBuffer, Int32Array and Float64Array are native functions and have a + // .length, so none of these should throw: + check(function() (new Int32Array(ArrayBuffer)).length >= 0); + check(function() (new Int32Array(Int32Array)).length >= 0); + check(function() (new Int32Array(Float64Array)).length >= 0); + + // webidl 4.4.6, under getters: "The value of the Function object’s + // 'length' property is the Number value 0" + // + // Except this fails in getOwnPropertyDescriptor, I think because + // Int32Array.prototype does not provide a lookup hook, and the fallback + // case ends up calling the getter. Which seems odd to me, but much of this + // stuff baffles me. It does seem strange that there's no way to do + // getOwnPropertyDescriptor on any of these attributes. + // + //check(Object.getOwnPropertyDescriptor(Int32Array.prototype, 'byteOffset')['get'].length == 0); check(function() Int32Array.BYTES_PER_ELEMENT == 4); check(function() (new Int32Array(4)).BYTES_PER_ELEMENT == 4);