Bug 1528582 - Add DataView methods for BigInt access r=wingo,jwalden
authorRobin Templeton <robin@igalia.com>
Fri, 22 Feb 2019 23:31:53 +0000
changeset 460727 ed6150abbe586459ae8014b340e9f26e094a9190
parent 460726 4ab8d4f3c348f84cc199c448e821eb994db47682
child 460728 28b53210d52239f7ebe715becd6681e0c5ffd707
push id35599
push usercsabou@mozilla.com
push dateSat, 23 Feb 2019 21:38:35 +0000
treeherdermozilla-central@98e5989a2840 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswingo, jwalden
bugs1528582
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1528582 - Add DataView methods for BigInt access r=wingo,jwalden Differential Revision: https://phabricator.services.mozilla.com/D20081
js/src/builtin/DataViewObject.cpp
js/src/builtin/DataViewObject.h
js/src/tests/jstests.list
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -308,16 +308,24 @@ template <>
 struct DataToRepType<int32_t> {
   typedef uint32_t result;
 };
 template <>
 struct DataToRepType<uint32_t> {
   typedef uint32_t result;
 };
 template <>
+struct DataToRepType<int64_t> {
+  typedef uint64_t result;
+};
+template <>
+struct DataToRepType<uint64_t> {
+  typedef uint64_t result;
+};
+template <>
 struct DataToRepType<float> {
   typedef uint32_t result;
 };
 template <>
 struct DataToRepType<double> {
   typedef uint64_t result;
 };
 
@@ -414,44 +422,68 @@ static inline bool WebIDLCast(JSContext*
   // Technically, the behavior of assigning an out of range value to a signed
   // variable is undefined. In practice, compilers seem to do what we want
   // without issuing any warnings.
   *out = static_cast<NativeType>(temp);
   return true;
 }
 
 template <>
+inline bool WebIDLCast<int64_t>(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<uint64_t>(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<float>(JSContext* cx, HandleValue value, float* out) {
   double temp;
   if (!ToNumber(cx, value, &temp)) {
     return false;
   }
   *out = static_cast<float>(temp);
   return true;
 }
 
 template <>
 inline bool WebIDLCast<double>(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 <typename NativeType>
 /* static */ bool DataViewObject::write(JSContext* cx,
                                         Handle<DataViewObject*> obj,
                                         const CallArgs& args) {
   // Steps 1-2. done by the caller
   // Step 3. unnecessary assert
 
   // Step 4.
   uint64_t getIndex;
   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;
   }
 
 #ifdef JS_MORE_DETERMINISTIC
   // See the comment in ElementSpecific::doubleToNative.
   if (TypeIsFloatingPoint<NativeType>()) {
@@ -597,16 +629,68 @@ bool DataViewObject::getUint32Impl(JSCon
   return true;
 }
 
 bool DataViewObject::fun_getUint32(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   return CallNonGenericMethod<is, getUint32Impl>(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<DataViewObject*> thisView(
+      cx, &args.thisv().toObject().as<DataViewObject>());
+
+  int64_t val;
+  if (!read(cx, thisView, args, &val)) {
+    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<is, getBigInt64Impl>(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<DataViewObject*> thisView(
+      cx, &args.thisv().toObject().as<DataViewObject>());
+
+  int64_t val;
+  if (!read(cx, thisView, args, &val)) {
+    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<is, getBigUint64Impl>(cx, args);
+}
+
 bool DataViewObject::getFloat32Impl(JSContext* cx, const CallArgs& args) {
   MOZ_ASSERT(is(args.thisv()));
 
   Rooted<DataViewObject*> thisView(
       cx, &args.thisv().toObject().as<DataViewObject>());
 
   float val;
   if (!read(cx, thisView, args, &val)) {
@@ -745,16 +829,56 @@ bool DataViewObject::setUint32Impl(JSCon
   return true;
 }
 
 bool DataViewObject::fun_setUint32(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   return CallNonGenericMethod<is, setUint32Impl>(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<DataViewObject*> thisView(
+      cx, &args.thisv().toObject().as<DataViewObject>());
+
+  if (!write<int64_t>(cx, thisView, args)) {
+    return false;
+  }
+  args.rval().setUndefined();
+  return true;
+}
+
+bool DataViewObject::fun_setBigInt64(JSContext* cx, unsigned argc, Value* vp) {
+  CallArgs args = CallArgsFromVp(argc, vp);
+  return CallNonGenericMethod<is, setBigInt64Impl>(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<DataViewObject*> thisView(
+      cx, &args.thisv().toObject().as<DataViewObject>());
+
+  if (!write<uint64_t>(cx, thisView, args)) {
+    return false;
+  }
+  args.rval().setUndefined();
+  return true;
+}
+
+bool DataViewObject::fun_setBigUint64(JSContext* cx, unsigned argc, Value* vp) {
+  CallArgs args = CallArgsFromVp(argc, vp);
+  return CallNonGenericMethod<is, setBigUint64Impl>(cx, args);
+}
+
 bool DataViewObject::setFloat32Impl(JSContext* cx, const CallArgs& args) {
   MOZ_ASSERT(is(args.thisv()));
 
   Rooted<DataViewObject*> thisView(
       cx, &args.thisv().toObject().as<DataViewObject>());
 
   if (!write<float>(cx, thisView, args)) {
     return false;
@@ -840,16 +964,25 @@ bool DataViewObject::byteOffsetGetter(JS
   return CallNonGenericMethod<is, byteOffsetGetterImpl>(cx, args);
 }
 
 JSObject* DataViewObject::CreatePrototype(JSContext* cx, JSProtoKey key) {
   return GlobalObject::createBlankPrototype(cx, cx->global(),
                                             &DataViewObject::protoClass_);
 }
 
+// Add extra methods for BigInt if its run-time option is enabled.
+bool DataViewObject::finishInit(JSContext* cx, JS::HandleObject ctor,
+                                JS::HandleObject proto) {
+  if (cx->realm()->creationOptions().getBigIntEnabled()) {
+    return JS_DefineFunctions(cx, proto, bigIntMethods);
+  }
+  return true;
+}
+
 static const ClassOps DataViewObjectClassOps = {nullptr, /* addProperty */
                                                 nullptr, /* delProperty */
                                                 nullptr, /* enumerate */
                                                 nullptr, /* newEnumerate */
                                                 nullptr, /* resolve */
                                                 nullptr, /* mayResolve */
                                                 nullptr, /* finalize */
                                                 nullptr, /* call */
@@ -860,16 +993,17 @@ static const ClassOps DataViewObjectClas
 const ClassSpec DataViewObject::classSpec_ = {
     GenericCreateConstructor<DataViewObject::construct, 1,
                              gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<DataViewObject>,
     nullptr,
     nullptr,
     DataViewObject::methods,
     DataViewObject::properties,
+    DataViewObject::finishInit
 };
 
 const Class DataViewObject::class_ = {
     "DataView",
     JSCLASS_HAS_PRIVATE |
         JSCLASS_HAS_RESERVED_SLOTS(DataViewObject::RESERVED_SLOTS) |
         JSCLASS_HAS_CACHED_PROTO(JSProto_DataView),
     &DataViewObjectClassOps, &DataViewObject::classSpec_};
@@ -892,16 +1026,23 @@ const JSFunctionSpec DataViewObject::met
     JS_FN("setInt16", DataViewObject::fun_setInt16, 2, 0),
     JS_FN("setUint16", DataViewObject::fun_setUint16, 2, 0),
     JS_FN("setInt32", DataViewObject::fun_setInt32, 2, 0),
     JS_FN("setUint32", DataViewObject::fun_setUint32, 2, 0),
     JS_FN("setFloat32", DataViewObject::fun_setFloat32, 2, 0),
     JS_FN("setFloat64", DataViewObject::fun_setFloat64, 2, 0),
     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};
+
 const JSPropertySpec DataViewObject::properties[] = {
     JS_PSG("buffer", DataViewObject::bufferGetter, 0),
     JS_PSG("byteLength", DataViewObject::byteLengthGetter, 0),
     JS_PSG("byteOffset", DataViewObject::byteOffsetGetter, 0),
     JS_STRING_SYM_PS(toStringTag, "DataView", JSPROP_READONLY), JS_PS_END};
 
 JS_FRIEND_API JSObject* JS_NewDataView(JSContext* cx, HandleObject buffer,
                                        uint32_t byteOffset,
--- a/js/src/builtin/DataViewObject.h
+++ b/js/src/builtin/DataViewObject.h
@@ -96,16 +96,22 @@ class DataViewObject : public ArrayBuffe
   static bool fun_getUint16(JSContext* cx, unsigned argc, Value* vp);
 
   static bool getInt32Impl(JSContext* cx, const CallArgs& args);
   static bool fun_getInt32(JSContext* cx, unsigned argc, Value* vp);
 
   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);
 
   static bool getFloat64Impl(JSContext* cx, const CallArgs& args);
   static bool fun_getFloat64(JSContext* cx, unsigned argc, Value* vp);
 
   static bool setInt8Impl(JSContext* cx, const CallArgs& args);
   static bool fun_setInt8(JSContext* cx, unsigned argc, Value* vp);
@@ -120,29 +126,39 @@ class DataViewObject : public ArrayBuffe
   static bool fun_setUint16(JSContext* cx, unsigned argc, Value* vp);
 
   static bool setInt32Impl(JSContext* cx, const CallArgs& args);
   static bool fun_setInt32(JSContext* cx, unsigned argc, Value* vp);
 
   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);
 
   static bool setFloat64Impl(JSContext* cx, const CallArgs& args);
   static bool fun_setFloat64(JSContext* cx, unsigned argc, Value* vp);
 
   template <typename NativeType>
   static bool read(JSContext* cx, Handle<DataViewObject*> obj,
                    const CallArgs& args, NativeType* val);
   template <typename NativeType>
   static bool write(JSContext* cx, Handle<DataViewObject*> obj,
                     const CallArgs& args);
 
  private:
   static const JSFunctionSpec methods[];
   static const JSPropertySpec properties[];
+
+  static const JSFunctionSpec bigIntMethods[];
+  static bool finishInit(JSContext* cx, JS::HandleObject ctor,
+                         JS::HandleObject proto);
 };
 
 }  // namespace js
 
 #endif /* vm_DataViewObject_h */
--- a/js/src/tests/jstests.list
+++ b/js/src/tests/jstests.list
@@ -913,58 +913,16 @@ skip script test262/built-ins/TypedArray
 skip script test262/built-ins/TypedArrayConstructors/prototype/every/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/reduce/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/fill/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/reduceRight/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/copyWithin/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/map/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/set/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/sort/bigint-inherited.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/negative-byteoffset-throws.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/return-value-clean-arraybuffer.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/return-abrupt-from-tonumber-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/return-values-custom-offset.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/name.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/detached-buffer-after-toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-errors.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/to-boolean-littleendian.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/length.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-toprimitive.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/return-values.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/index-is-out-of-range.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-wrapped-values.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/return-abrupt-from-tobigint-value.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/index-check-before-value-conversion.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/negative-byteoffset-throws.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/return-abrupt-from-tonumber-byteoffset.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/set-values-little-endian-order.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/name.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-after-toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/set-values-return-undefined.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-after-bigint-value.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/to-boolean-littleendian.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/length.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/index-is-out-of-range.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/range-check-after-value-conversion.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/negative-byteoffset-throws.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/return-value-clean-arraybuffer.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/return-abrupt-from-tonumber-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/return-values-custom-offset.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/name.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/detached-buffer-after-toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-errors.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/to-boolean-littleendian.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/length.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-toprimitive.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/return-values.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/index-is-out-of-range.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-wrapped-values.js
 
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1317405
 skip script test262/language/computed-property-names/class/static/method-number.js
 skip script test262/language/computed-property-names/class/static/method-string.js
 skip script test262/language/computed-property-names/class/static/method-symbol.js
 
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1286997
 # Bug 1286997 probably doesn't cover all spec violations.