From e3ec7384711e972a8aab3a140685e2ac2cd95dff Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 19 Jul 2023 15:27:59 -0500 Subject: [PATCH] Issue #1240 - Part 5f - Add DataView methods for BigInt access. https://bugzilla.mozilla.org/show_bug.cgi?id=1528582 --- js/src/vm/TypedArrayObject.cpp | 134 ++++++++++++++++++++++++++++++++- js/src/vm/TypedArrayObject.h | 16 ++++ 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 9d82fca6ec..0225c0578c 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -1959,6 +1959,8 @@ template <> struct DataToRepType { typedef uint16_t result; }; template <> struct DataToRepType { typedef uint16_t result; }; template <> struct DataToRepType { typedef uint32_t result; }; template <> struct DataToRepType { typedef uint32_t result; }; +template <> struct DataToRepType { typedef uint64_t result; }; +template <> struct DataToRepType { typedef uint64_t result; }; template <> struct DataToRepType { typedef uint32_t result; }; template <> struct DataToRepType { typedef uint64_t result; }; @@ -2058,6 +2060,28 @@ WebIDLCast(JSContext* cx, HandleValue value, NativeType* out) return true; } +template <> +inline bool WebIDLCast(JSContext* cx, HandleValue value, int64_t* out) +{ + RootedBigInt bi(cx, ToBigInt(cx, value)); + if (!bi) { + return false; + } + *out = BigInt::toInt64(bi); + return true; +} + +template <> +inline bool WebIDLCast(JSContext* cx, HandleValue value, uint64_t* out) +{ + RootedBigInt bi(cx, ToBigInt(cx, value)); + if (!bi) { + return false; + } + *out = BigInt::toUint64(bi); + return true; +} + template <> inline bool WebIDLCast(JSContext* cx, HandleValue value, float* out) @@ -2076,6 +2100,8 @@ WebIDLCast(JSContext* cx, HandleValue value, double* out) return ToNumber(cx, value, out); } +// https://tc39.github.io/ecma262/#sec-setviewvalue +// SetViewValue ( view, requestIndex, isLittleEndian, type, value ) template /* static */ bool DataViewObject::write(JSContext* cx, Handle obj, @@ -2089,7 +2115,7 @@ DataViewObject::write(JSContext* cx, Handle obj, if (!ToIndex(cx, args.get(0), &getIndex)) return false; - // Step 5. Should just call ToNumber (unobservable) + // Step 5. Extended by the BigInt proposal to call either ToBigInt or ToNumber NativeType value; if (!WebIDLCast(cx, args.get(1), &value)) return false; @@ -2245,6 +2271,60 @@ DataViewObject::fun_getUint32(JSContext* cx, unsigned argc, Value* vp) return CallNonGenericMethod(cx, args); } +// BigInt proposal 7.26 +// DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] ) +bool DataViewObject::getBigInt64Impl(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(is(args.thisv())); + + Rooted thisView(cx, &args.thisv().toObject().as()); + + int64_t val; + if (!read(cx, thisView, args, &val, "getBigInt64")) { + return false; + } + + BigInt* bi = BigInt::createFromInt64(cx, val); + if (!bi) { + return false; + } + args.rval().setBigInt(bi); + return true; +} + +bool DataViewObject::fun_getBigInt64(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + +// BigInt proposal 7.27 +// DataView.prototype.getBigUint64 ( byteOffset [ , littleEndian ] ) +bool DataViewObject::getBigUint64Impl(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(is(args.thisv())); + + Rooted thisView(cx, &args.thisv().toObject().as()); + + int64_t val; + if (!read(cx, thisView, args, &val, "getBigUint64")) { + return false; + } + + BigInt* bi = BigInt::createFromUint64(cx, val); + if (!bi) { + return false; + } + args.rval().setBigInt(bi); + return true; +} + +bool DataViewObject::fun_getBigUint64(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + bool DataViewObject::getFloat32Impl(JSContext* cx, const CallArgs& args) { @@ -2409,6 +2489,48 @@ DataViewObject::fun_setUint32(JSContext* cx, unsigned argc, Value* vp) return CallNonGenericMethod(cx, args); } +// BigInt proposal 7.28 +// DataView.prototype.setBigInt64 ( byteOffset, value [ , littleEndian ] ) +bool DataViewObject::setBigInt64Impl(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(is(args.thisv())); + + Rooted thisView(cx, &args.thisv().toObject().as()); + + if (!write(cx, thisView, args, "setBigInt64")) { + return false; + } + args.rval().setUndefined(); + return true; +} + +bool DataViewObject::fun_setBigInt64(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + +// BigInt proposal 7.29 +// DataView.prototype.setBigUint64 ( byteOffset, value [ , littleEndian ] ) +bool DataViewObject::setBigUint64Impl(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(is(args.thisv())); + + Rooted thisView(cx, &args.thisv().toObject().as()); + + if (!write(cx, thisView, args, "setBigUint64")) { + return false; + } + args.rval().setUndefined(); + return true; +} + +bool DataViewObject::fun_setBigUint64(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + bool DataViewObject::setFloat32Impl(JSContext* cx, const CallArgs& args) { @@ -2820,6 +2942,13 @@ const JSFunctionSpec DataViewObject::jsfuncs[] = { JS_FS_END }; +const JSFunctionSpec DataViewObject::bigIntMethods[] = { + JS_FN("getBigInt64", DataViewObject::fun_getBigInt64, 1, 0), + JS_FN("getBigUint64", DataViewObject::fun_getBigUint64, 1, 0), + JS_FN("setBigInt64", DataViewObject::fun_setBigInt64, 2, 0), + JS_FN("setBigUint64", DataViewObject::fun_setBigUint64, 2, 0), + JS_FS_END}; + template bool DataViewObject::getterImpl(JSContext* cx, const CallArgs& args) @@ -2888,6 +3017,9 @@ DataViewObject::initClass(JSContext* cx) if (!JS_DefineFunctions(cx, proto, DataViewObject::jsfuncs)) return false; + if (!JS_DefineFunctions(cx, proto, DataViewObject::bigIntMethods)) + return false; + if (!DefineToStringTag(cx, proto, cx->names().DataView)) return false; diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index 2616402b3d..ccdee22bee 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -521,6 +521,12 @@ class DataViewObject : public NativeObject static bool getUint32Impl(JSContext* cx, const CallArgs& args); static bool fun_getUint32(JSContext* cx, unsigned argc, Value* vp); + static bool getBigInt64Impl(JSContext* cx, const CallArgs& args); + static bool fun_getBigInt64(JSContext* cx, unsigned argc, Value* vp); + + static bool getBigUint64Impl(JSContext* cx, const CallArgs& args); + static bool fun_getBigUint64(JSContext* cx, unsigned argc, Value* vp); + static bool getFloat32Impl(JSContext* cx, const CallArgs& args); static bool fun_getFloat32(JSContext* cx, unsigned argc, Value* vp); @@ -545,6 +551,12 @@ class DataViewObject : public NativeObject static bool setUint32Impl(JSContext* cx, const CallArgs& args); static bool fun_setUint32(JSContext* cx, unsigned argc, Value* vp); + static bool setBigInt64Impl(JSContext* cx, const CallArgs& args); + static bool fun_setBigInt64(JSContext* cx, unsigned argc, Value* vp); + + static bool setBigUint64Impl(JSContext* cx, const CallArgs& args); + static bool fun_setBigUint64(JSContext* cx, unsigned argc, Value* vp); + static bool setFloat32Impl(JSContext* cx, const CallArgs& args); static bool fun_setFloat32(JSContext* cx, unsigned argc, Value* vp); @@ -564,6 +576,10 @@ class DataViewObject : public NativeObject private: static const JSFunctionSpec jsfuncs[]; + + static const JSFunctionSpec bigIntMethods[]; + static bool finishInit(JSContext* cx, JS::HandleObject ctor, + JS::HandleObject proto); }; static inline int32_t