Bug 891107 - Part 2: Report argument length error as TypeError in js-ctypes. r=jorendorff
☠☠ backed out by 2bd7ce78571b ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Wed, 22 Apr 2015 18:26:14 +0900
changeset 240414 951ec7d134c26e325ff92e021a8cc742d4d61b5f
parent 240413 b2b956ba0acd53acb035eae3383a9a75c3389dfe
child 240415 467559ddc08f63606136089eeba1ec7b191283d6
push id58825
push userarai_a@mac.com
push dateWed, 22 Apr 2015 09:32:30 +0000
treeherdermozilla-inbound@467559ddc08f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs891107
milestone40.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 891107 - Part 2: Report argument length error as TypeError in js-ctypes. r=jorendorff
js/src/ctypes/CTypes.cpp
js/src/ctypes/ctypes.msg
js/src/jit-test/tests/ctypes/argument-length-abi.js
js/src/jit-test/tests/ctypes/argument-length-array.js
js/src/jit-test/tests/ctypes/argument-length-cdata.js
js/src/jit-test/tests/ctypes/argument-length-ctypes.js
js/src/jit-test/tests/ctypes/argument-length-finalizer.js
js/src/jit-test/tests/ctypes/argument-length-function.js
js/src/jit-test/tests/ctypes/argument-length-int64.js
js/src/jit-test/tests/ctypes/argument-length-pointer.js
js/src/jit-test/tests/ctypes/argument-length-primitive.js
js/src/jit-test/tests/ctypes/argument-length-struct.js
toolkit/components/ctypes/tests/unit/test_jsctypes.js
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -1230,16 +1230,25 @@ ArgumentConvError(JSContext* cx, HandleV
   JS_snprintf(indexStr, 16, "%u", argIndex + 1);
 
   JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
                        CTYPESMSG_CONV_ERROR_ARG, valStr, indexStr, funStr);
   return false;
 }
 
 static bool
+ArgumentLengthError(JSContext* cx, const char* fun, const char* count,
+                    const char* s)
+{
+  JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
+                       CTYPESMSG_WRONG_ARG_LENGTH, fun, count, s);
+  return false;
+}
+
+static bool
 ArrayLengthMismatch(JSContext* cx, unsigned expectedLength, HandleObject arrObj,
                     unsigned actualLength, HandleValue actual,
                     ConversionType convType)
 {
   MOZ_ASSERT(arrObj && CType::IsCType(arrObj));
 
   JSAutoByteString valBytes;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
@@ -3829,18 +3838,17 @@ CType::ConstructData(JSContext* cx,
 }
 
 bool
 CType::ConstructBasic(JSContext* cx,
                       HandleObject obj,
                       const CallArgs& args)
 {
   if (args.length() > 1) {
-    JS_ReportError(cx, "CType constructor takes zero or one argument");
-    return false;
+    return ArgumentLengthError(cx, "CType constructor", "at most one", "");
   }
 
   // construct a CData object
   RootedObject result(cx, CData::Create(cx, obj, NullPtr(), nullptr, true));
   if (!result)
     return false;
 
   if (args.length() == 1) {
@@ -4352,18 +4360,17 @@ CType::CreateArray(JSContext* cx, unsign
     return false;
   if (!CType::IsCType(baseType)) {
     JS_ReportError(cx, "not a CType");
     return false;
   }
 
   // Construct and return a new ArrayType object.
   if (args.length() > 1) {
-    JS_ReportError(cx, "array takes zero or one argument");
-    return false;
+    return ArgumentLengthError(cx, "CType.prototype.array", "at most one", "");
   }
 
   // Convert the length argument to a size_t.
   size_t length = 0;
   if (args.length() == 1 && !jsvalToSize(cx, args[0], false, &length)) {
     JS_ReportError(cx, "argument must be a nonnegative integer");
     return false;
   }
@@ -4492,18 +4499,17 @@ ABI::IsABI(JSObject* obj)
   return JS_GetClass(obj) == &sCABIClass;
 }
 
 bool
 ABI::ToSource(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 0) {
-    JS_ReportError(cx, "toSource takes zero arguments");
-    return false;
+    return ArgumentLengthError(cx, "ABI.prototype.toSource", "no", "s");
   }
 
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
     return false;
   if (!ABI::IsABI(obj)) {
     JS_ReportError(cx, "not an ABI");
     return false;
@@ -4537,18 +4543,17 @@ ABI::ToSource(JSContext* cx, unsigned ar
 *******************************************************************************/
 
 bool
 PointerType::Create(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   // Construct and return a new PointerType object.
   if (args.length() != 1) {
-    JS_ReportError(cx, "PointerType takes one argument");
-    return false;
+    return ArgumentLengthError(cx, "PointerType", "one", "");
   }
 
   jsval arg = args[0];
   RootedObject obj(cx);
   if (arg.isPrimitive() || !CType::IsCType(obj = &arg.toObject())) {
     JS_ReportError(cx, "first argument must be a CType");
     return false;
   }
@@ -4603,18 +4608,18 @@ PointerType::ConstructData(JSContext* cx
                            const CallArgs& args)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_pointer) {
     JS_ReportError(cx, "not a PointerType");
     return false;
   }
 
   if (args.length() > 3) {
-    JS_ReportError(cx, "constructor takes 0, 1, 2, or 3 arguments");
-    return false;
+    return ArgumentLengthError(cx, "PointerType constructor", "0, 1, 2, or 3",
+                               "s");
   }
 
   RootedObject result(cx, CData::Create(cx, obj, NullPtr(), nullptr, true));
   if (!result)
     return false;
 
   // Set return value early, must not observe *vp after
   args.rval().setObject(*result);
@@ -4638,18 +4643,17 @@ PointerType::ConstructData(JSContext* cx
   bool looksLikeClosure = CType::GetTypeCode(baseObj) == TYPE_function &&
                           args[0].isObject() && JS::IsCallable(&args[0].toObject());
 
   //
   // Case 2 - Initialized pointer
   //
   if (!looksLikeClosure) {
     if (args.length() != 1) {
-      JS_ReportError(cx, "first argument must be a function");
-      return false;
+      return ArgumentLengthError(cx, "FunctionType constructor", "one", "");
     }
     return ExplicitConvert(cx, args[0], obj, CData::GetData(result),
                            ConversionType::Construct);
   }
 
   //
   // Case 3 - Closure
   //
@@ -4840,18 +4844,17 @@ PointerType::ContentsSetter(JSContext* c
 *******************************************************************************/
 
 bool
 ArrayType::Create(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   // Construct and return a new ArrayType object.
   if (args.length() < 1 || args.length() > 2) {
-    JS_ReportError(cx, "ArrayType takes one or two arguments");
-    return false;
+    return ArgumentLengthError(cx, "ArrayType", "one or two", "s");
   }
 
   if (args[0].isPrimitive() ||
       !CType::IsCType(&args[0].toObject())) {
     JS_ReportError(cx, "first argument must be a CType");
     return false;
   }
 
@@ -4941,24 +4944,24 @@ ArrayType::ConstructData(JSContext* cx,
   // Decide whether we have an object to initialize from. We'll override this
   // if we get a length argument instead.
   bool convertObject = args.length() == 1;
 
   // Check if we're an array of undefined length. If we are, allow construction
   // with a length argument, or with an actual JS array.
   if (CType::IsSizeDefined(obj)) {
     if (args.length() > 1) {
-      JS_ReportError(cx, "constructor takes zero or one argument");
-      return false;
+      return ArgumentLengthError(cx, "size defined ArrayType constructor",
+                                 "at most one", "");
     }
 
   } else {
     if (args.length() != 1) {
-      JS_ReportError(cx, "constructor takes one argument");
-      return false;
+      return ArgumentLengthError(cx, "size undefined ArrayType constructor",
+                                 "one", "");
     }
 
     RootedObject baseType(cx, GetBaseType(obj));
 
     size_t length;
     if (jsvalToSize(cx, args[0], false, &length)) {
       // Have a length, rather than an object to initialize from.
       convertObject = false;
@@ -5263,18 +5266,18 @@ ArrayType::AddressOfElement(JSContext* c
 
   RootedObject typeObj(cx, CData::GetCType(obj));
   if (CType::GetTypeCode(typeObj) != TYPE_array) {
     JS_ReportError(cx, "not an ArrayType");
     return false;
   }
 
   if (args.length() != 1) {
-    JS_ReportError(cx, "addressOfElement takes one argument");
-    return false;
+    return ArgumentLengthError(cx, "ArrayType.prototype.addressOfElement",
+                               "one", "");
   }
 
   RootedObject baseType(cx, GetBaseType(typeObj));
   RootedObject pointerType(cx, PointerType::CreateInternal(cx, baseType));
   if (!pointerType)
     return false;
 
   // Create a PointerType CData object containing null.
@@ -5384,18 +5387,17 @@ AddFieldToArray(JSContext* cx,
 
 bool
 StructType::Create(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   // Construct and return a new StructType object.
   if (args.length() < 1 || args.length() > 2) {
-    JS_ReportError(cx, "StructType takes one or two arguments");
-    return false;
+    return ArgumentLengthError(cx, "StructType", "one or two", "s");
   }
 
   jsval name = args[0];
   if (!name.isString()) {
     JS_ReportError(cx, "first argument must be a string");
     return false;
   }
 
@@ -5679,18 +5681,17 @@ StructType::Define(JSContext* cx, unsign
   }
 
   if (CType::IsSizeDefined(obj)) {
     JS_ReportError(cx, "StructType has already been defined");
     return false;
   }
 
   if (args.length() != 1) {
-    JS_ReportError(cx, "define takes one argument");
-    return false;
+    return ArgumentLengthError(cx, "StructType.prototype.define", "one", "");
   }
 
   jsval arg = args[0];
   if (arg.isPrimitive()) {
     JS_ReportError(cx, "argument must be an array");
     return false;
   }
   RootedObject arr(cx, arg.toObjectOrNull());
@@ -5767,19 +5768,24 @@ StructType::ConstructData(JSContext* cx,
                            buffer + field.mOffset, ConversionType::Construct,
                            nullptr, NullPtr(), 0, obj, field.mIndex))
         return false;
     }
 
     return true;
   }
 
-  JS_ReportError(cx, "constructor takes 0, 1, or %u arguments",
-    fields->count());
-  return false;
+  size_t count = fields->count();
+  if (count >= 2) {
+    char fieldLengthStr[32];
+    JS_snprintf(fieldLengthStr, 32, "0, 1, or %u", count);
+    return ArgumentLengthError(cx, "StructType constructor", fieldLengthStr,
+                               "s");
+  }
+  return ArgumentLengthError(cx, "StructType constructor", "at most one", "");
 }
 
 const FieldInfoHash*
 StructType::GetFieldInfo(JSObject* obj)
 {
   MOZ_ASSERT(CType::IsCType(obj));
   MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_struct);
 
@@ -5965,18 +5971,18 @@ StructType::AddressOfField(JSContext* cx
 
   JSObject* typeObj = CData::GetCType(obj);
   if (CType::GetTypeCode(typeObj) != TYPE_struct) {
     JS_ReportError(cx, "not a StructType");
     return false;
   }
 
   if (args.length() != 1) {
-    JS_ReportError(cx, "addressOfField takes one argument");
-    return false;
+    return ArgumentLengthError(cx, "StructType.prototype.addressOfField",
+                               "one", "");
   }
 
   if (!args[0].isString()) {
     JS_ReportError(cx, "argument must be a string");
     return false;
   }
 
   JSFlatString* str = JS_FlattenString(cx, args[0].toString());
@@ -6310,18 +6316,17 @@ CreateFunctionInfo(JSContext* cx,
 }
 
 bool
 FunctionType::Create(JSContext* cx, unsigned argc, jsval* vp)
 {
   // Construct and return a new FunctionType object.
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() < 2 || args.length() > 3) {
-    JS_ReportError(cx, "FunctionType takes two or three arguments");
-    return false;
+    return ArgumentLengthError(cx, "FunctionType", "two or three", "s");
   }
 
   AutoValueVector argTypes(cx);
   RootedObject arrayObj(cx, nullptr);
 
   if (args.length() == 3) {
     // Prepare an array of jsvals for the arguments.
     if (args[2].isObject())
@@ -7156,18 +7161,17 @@ CData::ValueSetter(JSContext* cx, JS::Ca
                          ConversionType::Setter, nullptr);
 }
 
 bool
 CData::Address(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 0) {
-    JS_ReportError(cx, "address takes zero arguments");
-    return false;
+    return ArgumentLengthError(cx, "CData.prototype.address", "no", "s");
   }
 
   RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
   if (!obj)
     return false;
   if (!IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return false;
@@ -7191,18 +7195,17 @@ CData::Address(JSContext* cx, unsigned a
   return true;
 }
 
 bool
 CData::Cast(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 2) {
-    JS_ReportError(cx, "cast takes two arguments");
-    return false;
+    return ArgumentLengthError(cx, "ctypes.cast", "two", "s");
   }
 
   if (args[0].isPrimitive() || !CData::IsCData(&args[0].toObject())) {
     JS_ReportError(cx, "first argument must be a CData");
     return false;
   }
   RootedObject sourceData(cx, &args[0].toObject());
   JSObject* sourceType = CData::GetCType(sourceData);
@@ -7232,18 +7235,17 @@ CData::Cast(JSContext* cx, unsigned argc
   return true;
 }
 
 bool
 CData::GetRuntime(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 1) {
-    JS_ReportError(cx, "getRuntime takes one argument");
-    return false;
+    return ArgumentLengthError(cx, "ctypes.getRuntime", "one", "");
   }
 
   if (args[0].isPrimitive() || !CType::IsCType(&args[0].toObject())) {
     JS_ReportError(cx, "first argument must be a CType");
     return false;
   }
 
   RootedObject targetType(cx, &args[0].toObject());
@@ -7265,18 +7267,21 @@ CData::GetRuntime(JSContext* cx, unsigne
 
 typedef JS::TwoByteCharsZ (*InflateUTF8Method)(JSContext*, const JS::UTF8Chars, size_t*);
 
 static bool
 ReadStringCommon(JSContext* cx, InflateUTF8Method inflateUTF8, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 0) {
-    JS_ReportError(cx, "readString takes zero arguments");
-    return false;
+    if (inflateUTF8 == JS::UTF8CharsToNewTwoByteCharsZ) {
+      return ArgumentLengthError(cx, "CData.prototype.readString", "no", "s");
+    }
+    return ArgumentLengthError(cx, "CData.prototype.readStringReplaceMalformed",
+                               "no", "s");
   }
 
   JSObject* obj = CDataFinalizer::GetCData(cx, JS_THIS_OBJECT(cx, vp));
   if (!obj || !CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return false;
   }
 
@@ -7381,18 +7386,17 @@ CData::GetSourceString(JSContext* cx, Ha
   return NewUCString(cx, source);
 }
 
 bool
 CData::ToSource(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 0) {
-    JS_ReportError(cx, "toSource takes zero arguments");
-    return false;
+    return ArgumentLengthError(cx, "CData.prototype.toSource", "no", "s");
   }
 
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
     return false;
   if (!CData::IsCData(obj) && !CData::IsCDataProto(obj)) {
     JS_ReportError(cx, "not a CData");
     return false;
@@ -7610,18 +7614,17 @@ CDataFinalizer::Construct(JSContext* cx,
   // Get arguments
   if (args.length() == 0) { // Special case: the empty (already finalized) object
     JSObject* objResult = JS_NewObjectWithGivenProto(cx, &sCDataFinalizerClass, objProto);
     args.rval().setObject(*objResult);
     return true;
   }
 
   if (args.length() != 2) {
-    JS_ReportError(cx, "CDataFinalizer takes 2 arguments");
-    return false;
+    return ArgumentLengthError(cx, "CDataFinalizer constructor", "two", "s");
   }
 
   JS::HandleValue valCodePtr = args[1];
   if (!valCodePtr.isObject()) {
     return TypeError(cx, "_a CData object_ of a function pointer type",
                      valCodePtr);
   }
   JSObject* objCodePtr = &valCodePtr.toObject();
@@ -7825,18 +7828,18 @@ CDataFinalizer::CallFinalizer(CDataFinal
  * Does not call the finalizer. Cleans up the Private memory and releases all
  * strong references.
  */
 bool
 CDataFinalizer::Methods::Forget(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 0) {
-    JS_ReportError(cx, "CDataFinalizer.prototype.forget takes no arguments");
-    return false;
+    return ArgumentLengthError(cx, "CDataFinalizer.prototype.forget", "no",
+                               "s");
   }
 
   JS::Rooted<JSObject*> obj(cx, args.thisv().toObjectOrNull());
   if (!obj)
     return false;
   if (!CDataFinalizer::IsCDataFinalizer(obj)) {
     JS_ReportError(cx, "not a CDataFinalizer");
     return false;
@@ -7873,18 +7876,18 @@ CDataFinalizer::Methods::Forget(JSContex
  * Calls the finalizer, cleans up the Private memory and releases all
  * strong references.
  */
 bool
 CDataFinalizer::Methods::Dispose(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 0) {
-    JS_ReportError(cx, "CDataFinalizer.prototype.dispose takes no arguments");
-    return false;
+    return ArgumentLengthError(cx, "CDataFinalizer.prototype.dispose", "no",
+                               "s");
   }
 
   RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
   if (!obj)
     return false;
   if (!CDataFinalizer::IsCDataFinalizer(obj)) {
     JS_ReportError(cx, "not a CDataFinalizer");
     return false;
@@ -8047,18 +8050,22 @@ Int64Base::GetInt(JSObject* obj) {
 
 bool
 Int64Base::ToString(JSContext* cx,
                     JSObject* obj,
                     const CallArgs& args,
                     bool isUnsigned)
 {
   if (args.length() > 1) {
-    JS_ReportError(cx, "toString takes zero or one argument");
-    return false;
+    if (isUnsigned) {
+      return ArgumentLengthError(cx, "UInt64.prototype.toString",
+                                 "at most one", "");
+    }
+    return ArgumentLengthError(cx, "Int64.prototype.toString",
+                               "at most one", "");
   }
 
   int radix = 10;
   if (args.length() == 1) {
     jsval arg = args[0];
     if (arg.isInt32())
       radix = arg.toInt32();
     if (!arg.isInt32() || radix < 2 || radix > 36) {
@@ -8084,18 +8091,20 @@ Int64Base::ToString(JSContext* cx,
 
 bool
 Int64Base::ToSource(JSContext* cx,
                     JSObject* obj,
                     const CallArgs& args,
                     bool isUnsigned)
 {
   if (args.length() != 0) {
-    JS_ReportError(cx, "toSource takes zero arguments");
-    return false;
+    if (isUnsigned) {
+      return ArgumentLengthError(cx, "UInt64.prototype.toSource", "no", "s");
+    }
+    return ArgumentLengthError(cx, "Int64.prototype.toSource", "no", "s");
   }
 
   // Return a decimal string suitable for constructing the number.
   AutoString source;
   if (isUnsigned) {
     AppendString(source, "ctypes.UInt64(\"");
     IntegerToString(GetInt(obj), 10, source);
   } else {
@@ -8116,18 +8125,17 @@ bool
 Int64::Construct(JSContext* cx,
                  unsigned argc,
                  jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   // Construct and return a new Int64 object.
   if (args.length() != 1) {
-    JS_ReportError(cx, "Int64 takes one argument");
-    return false;
+    return ArgumentLengthError(cx, "Int64 constructor", "one", "");
   }
 
   int64_t i = 0;
   if (!jsvalToBigInteger(cx, args[0], true, &i)) {
     return ArgumentConvError(cx, args[0], "Int64", 0);
   }
 
   // Get ctypes.Int64.prototype from the 'prototype' property of the ctor.
@@ -8180,18 +8188,20 @@ Int64::ToSource(JSContext* cx, unsigned 
 
   return Int64Base::ToSource(cx, obj, args, false);
 }
 
 bool
 Int64::Compare(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
-  if (args.length() != 2 ||
-      args[0].isPrimitive() ||
+  if (args.length() != 2) {
+    return ArgumentLengthError(cx, "Int64.compare", "two", "s");
+  }
+  if (args[0].isPrimitive() ||
       args[1].isPrimitive() ||
       !Int64::IsInt64(&args[0].toObject()) ||
       !Int64::IsInt64(&args[1].toObject())) {
     JS_ReportError(cx, "compare takes two Int64 arguments");
     return false;
   }
 
   JSObject* obj1 = &args[0].toObject();
@@ -8213,36 +8223,40 @@ Int64::Compare(JSContext* cx, unsigned a
 #define LO_MASK ((uint64_t(1) << 32) - 1)
 #define INT64_LO(i) ((i) & LO_MASK)
 #define INT64_HI(i) ((i) >> 32)
 
 bool
 Int64::Lo(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
-  if (args.length() != 1 || args[0].isPrimitive() ||
-      !Int64::IsInt64(&args[0].toObject())) {
+  if (args.length() != 1) {
+    return ArgumentLengthError(cx, "Int64.lo", "one", "");
+  }
+  if (args[0].isPrimitive() || !Int64::IsInt64(&args[0].toObject())) {
     JS_ReportError(cx, "lo takes one Int64 argument");
     return false;
   }
 
   JSObject* obj = &args[0].toObject();
   int64_t u = Int64Base::GetInt(obj);
   double d = uint32_t(INT64_LO(u));
 
   args.rval().setNumber(d);
   return true;
 }
 
 bool
 Int64::Hi(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
-  if (args.length() != 1 || args[0].isPrimitive() ||
-      !Int64::IsInt64(&args[0].toObject())) {
+  if (args.length() != 1) {
+    return ArgumentLengthError(cx, "Int64.hi", "one", "");
+  }
+  if (args[0].isPrimitive() || !Int64::IsInt64(&args[0].toObject())) {
     JS_ReportError(cx, "hi takes one Int64 argument");
     return false;
   }
 
   JSObject* obj = &args[0].toObject();
   int64_t u = Int64Base::GetInt(obj);
   double d = int32_t(INT64_HI(u));
 
@@ -8250,18 +8264,17 @@ Int64::Hi(JSContext* cx, unsigned argc, 
   return true;
 }
 
 bool
 Int64::Join(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 2) {
-    JS_ReportError(cx, "join takes two arguments");
-    return false;
+    return ArgumentLengthError(cx, "Int64.join", "two", "s");
   }
 
   int32_t hi;
   uint32_t lo;
   if (!jsvalToInteger(cx, args[0], &hi))
     return ArgumentConvError(cx, args[0], "Int64.join", 0);
   if (!jsvalToInteger(cx, args[1], &lo))
     return ArgumentConvError(cx, args[1], "Int64.join", 1);
@@ -8287,18 +8300,17 @@ bool
 UInt64::Construct(JSContext* cx,
                   unsigned argc,
                   jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   // Construct and return a new UInt64 object.
   if (args.length() != 1) {
-    JS_ReportError(cx, "UInt64 takes one argument");
-    return false;
+    return ArgumentLengthError(cx, "UInt64 constructor", "one", "");
   }
 
   uint64_t u = 0;
   if (!jsvalToBigInteger(cx, args[0], true, &u)) {
     return ArgumentConvError(cx, args[0], "UInt64", 0);
   }
 
   // Get ctypes.UInt64.prototype from the 'prototype' property of the ctor.
@@ -8351,18 +8363,20 @@ UInt64::ToSource(JSContext* cx, unsigned
 
   return Int64Base::ToSource(cx, obj, args, true);
 }
 
 bool
 UInt64::Compare(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
-  if (args.length() != 2 ||
-      args[0].isPrimitive() ||
+  if (args.length() != 2) {
+    return ArgumentLengthError(cx, "UInt64.compare", "two", "s");
+  }
+  if (args[0].isPrimitive() ||
       args[1].isPrimitive() ||
       !UInt64::IsUInt64(&args[0].toObject()) ||
       !UInt64::IsUInt64(&args[1].toObject())) {
     JS_ReportError(cx, "compare takes two UInt64 arguments");
     return false;
   }
 
   JSObject* obj1 = &args[0].toObject();
@@ -8380,36 +8394,40 @@ UInt64::Compare(JSContext* cx, unsigned 
 
   return true;
 }
 
 bool
 UInt64::Lo(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
-  if (args.length() != 1 || args[0].isPrimitive() ||
-      !UInt64::IsUInt64(&args[0].toObject())) {
+  if (args.length() != 1) {
+    return ArgumentLengthError(cx, "UInt64.lo", "one", "");
+  }
+  if (args[0].isPrimitive() || !UInt64::IsUInt64(&args[0].toObject())) {
     JS_ReportError(cx, "lo takes one UInt64 argument");
     return false;
   }
 
   JSObject* obj = &args[0].toObject();
   uint64_t u = Int64Base::GetInt(obj);
   double d = uint32_t(INT64_LO(u));
 
   args.rval().setDouble(d);
   return true;
 }
 
 bool
 UInt64::Hi(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
-  if (args.length() != 1 || args[0].isPrimitive() ||
-      !UInt64::IsUInt64(&args[0].toObject())) {
+  if (args.length() != 1) {
+    return ArgumentLengthError(cx, "UInt64.hi", "one", "");
+  }
+  if (args[0].isPrimitive() || !UInt64::IsUInt64(&args[0].toObject())) {
     JS_ReportError(cx, "hi takes one UInt64 argument");
     return false;
   }
 
   JSObject* obj = &args[0].toObject();
   uint64_t u = Int64Base::GetInt(obj);
   double d = uint32_t(INT64_HI(u));
 
@@ -8417,18 +8435,17 @@ UInt64::Hi(JSContext* cx, unsigned argc,
   return true;
 }
 
 bool
 UInt64::Join(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   if (args.length() != 2) {
-    JS_ReportError(cx, "join takes two arguments");
-    return false;
+    return ArgumentLengthError(cx, "UInt64.join", "two", "s");
   }
 
   uint32_t hi;
   uint32_t lo;
   if (!jsvalToInteger(cx, args[0], &hi))
     return ArgumentConvError(cx, args[0], "UInt64.join", 0);
   if (!jsvalToInteger(cx, args[1], &lo))
     return ArgumentConvError(cx, args[1], "UInt64.join", 1);
--- a/js/src/ctypes/ctypes.msg
+++ b/js/src/ctypes/ctypes.msg
@@ -27,8 +27,11 @@ MSG_DEF(CTYPESMSG_ARRAY_OVERFLOW,4, JSEX
 
 /* struct */
 MSG_DEF(CTYPESMSG_FIELD_MISMATCH,5, JSEXN_TYPEERR, "property count of {0} does not match to field count of the type {1} (expected {2}, got {3}){4}")
 MSG_DEF(CTYPESMSG_PROP_NONSTRING,3, JSEXN_TYPEERR, "property name {0} of {1} is not a string{2}")
 
 /* data finalizer */
 MSG_DEF(CTYPESMSG_EMPTY_FIN,     1, JSEXN_TYPEERR, "attempting to convert an empty CDataFinalizer{0}")
 MSG_DEF(CTYPESMSG_FIN_SIZE_ERROR,2, JSEXN_TYPEERR, "expected an object with the same size as argument 1 of {0}, got {1}")
+
+/* native function */
+MSG_DEF(CTYPESMSG_WRONG_ARG_LENGTH,3, JSEXN_TYPEERR, "{0} takes {1} argument{2}")
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-abi.js
@@ -0,0 +1,9 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.default_abi.toSource(1); },
+                         "ABI.prototype.toSource takes no arguments");
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-array.js
@@ -0,0 +1,15 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.ArrayType(); },
+                         "ArrayType takes one or two arguments");
+  assertTypeErrorMessage(() => { ctypes.int32_t.array(10)(1, 2); },
+                         "size defined ArrayType constructor takes at most one argument");
+  assertTypeErrorMessage(() => { ctypes.int32_t.array()(1, 2); },
+                         "size undefined ArrayType constructor takes one argument");
+  assertTypeErrorMessage(() => { ctypes.int32_t.array(10)().addressOfElement(); },
+                         "ArrayType.prototype.addressOfElement takes one argument");
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-cdata.js
@@ -0,0 +1,15 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.int32_t(0).address(1); },
+                         "CData.prototype.address takes no arguments");
+  assertTypeErrorMessage(() => { ctypes.char.array(10)().readString(1); },
+                         "CData.prototype.readString takes no arguments");
+  assertTypeErrorMessage(() => { ctypes.char.array(10)().readStringReplaceMalformed(1); },
+                         "CData.prototype.readStringReplaceMalformed takes no arguments");
+  assertTypeErrorMessage(() => { ctypes.int32_t(0).toSource(1); },
+                         "CData.prototype.toSource takes no arguments");
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-ctypes.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.cast(); },
+                         "ctypes.cast takes two arguments");
+  assertTypeErrorMessage(() => { ctypes.getRuntime(); },
+                         "ctypes.getRuntime takes one argument");
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-finalizer.js
@@ -0,0 +1,16 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.CDataFinalizer(1); },
+                         "CDataFinalizer constructor takes two arguments");
+
+  let fin = ctypes.CDataFinalizer(ctypes.int32_t(0), ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.int32_t]).ptr(x => x));
+  assertTypeErrorMessage(() => { fin.forget(1); },
+                         "CDataFinalizer.prototype.forget takes no arguments");
+  assertTypeErrorMessage(() => { fin.dispose(1); },
+                         "CDataFinalizer.prototype.dispose takes no arguments");
+  fin.forget();
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-function.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.FunctionType(); },
+                         "FunctionType takes two or three arguments");
+  assertTypeErrorMessage(() => { ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, []).ptr({}, 1); },
+                         "FunctionType constructor takes one argument");
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-int64.js
@@ -0,0 +1,36 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.Int64(1).toString(1, 2); },
+                         "Int64.prototype.toString takes at most one argument");
+  assertTypeErrorMessage(() => { ctypes.Int64(1).toSource(1); },
+                         "Int64.prototype.toSource takes no arguments");
+  assertTypeErrorMessage(() => { ctypes.Int64(); },
+                         "Int64 constructor takes one argument");
+  assertTypeErrorMessage(() => { ctypes.Int64.compare(); },
+                         "Int64.compare takes two arguments");
+  assertTypeErrorMessage(() => { ctypes.Int64.lo(); },
+                         "Int64.lo takes one argument");
+  assertTypeErrorMessage(() => { ctypes.Int64.hi(); },
+                         "Int64.hi takes one argument");
+  assertTypeErrorMessage(() => { ctypes.Int64.join(); },
+                         "Int64.join takes two arguments");
+
+  assertTypeErrorMessage(() => { ctypes.UInt64(1).toString(1, 2); },
+                         "UInt64.prototype.toString takes at most one argument");
+  assertTypeErrorMessage(() => { ctypes.UInt64(1).toSource(1); },
+                         "UInt64.prototype.toSource takes no arguments");
+  assertTypeErrorMessage(() => { ctypes.UInt64(); },
+                         "UInt64 constructor takes one argument");
+  assertTypeErrorMessage(() => { ctypes.UInt64.compare(); },
+                         "UInt64.compare takes two arguments");
+  assertTypeErrorMessage(() => { ctypes.UInt64.lo(); },
+                         "UInt64.lo takes one argument");
+  assertTypeErrorMessage(() => { ctypes.UInt64.hi(); },
+                         "UInt64.hi takes one argument");
+  assertTypeErrorMessage(() => { ctypes.UInt64.join(); },
+                         "UInt64.join takes two arguments");
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-pointer.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.PointerType(); },
+                         "PointerType takes one argument");
+  assertTypeErrorMessage(() => { ctypes.int32_t.ptr(1, 2, 3, 4); },
+                         "PointerType constructor takes 0, 1, 2, or 3 arguments");
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-primitive.js
@@ -0,0 +1,11 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.int32_t(1, 2, 3); },
+                         "CType constructor takes at most one argument");
+  assertTypeErrorMessage(() => { ctypes.int32_t.array(1, 2); },
+                         "CType.prototype.array takes at most one argument");
+}
+
+if (typeof ctypes === "object")
+  test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ctypes/argument-length-struct.js
@@ -0,0 +1,17 @@
+load(libdir + 'asserts.js');
+
+function test() {
+  assertTypeErrorMessage(() => { ctypes.StructType(); },
+                         "StructType takes one or two arguments");
+  assertTypeErrorMessage(() => { ctypes.StructType("a").define(); },
+                         "StructType.prototype.define takes one argument");
+  assertTypeErrorMessage(() => { ctypes.StructType("a", [])(1, 2, 3); },
+                         "StructType constructor takes at most one argument");
+  assertTypeErrorMessage(() => { ctypes.StructType("a", [ {"x": ctypes.int32_t }, {"y": ctypes.int32_t }, {"z": ctypes.int32_t }])(1, 2); },
+                         "StructType constructor takes 0, 1, or 3 arguments");
+  assertTypeErrorMessage(() => { ctypes.StructType("a", [ {"x": ctypes.int32_t } ])().addressOfField(); },
+                         "StructType.prototype.addressOfField takes one argument");
+}
+
+if (typeof ctypes === "object")
+  test();
--- a/toolkit/components/ctypes/tests/unit/test_jsctypes.js
+++ b/toolkit/components/ctypes/tests/unit/test_jsctypes.js
@@ -295,17 +295,17 @@ function run_abstract_class_tests()
 
   // toString and toSource are called by the web console during inspection,
   // so we don't want them to throw.
   do_check_eq(ctypes.CData.prototype.toString(), '[CData proto object]');
   do_check_eq(ctypes.CData.prototype.toSource(), '[CData proto object]');
 }
 
 function run_Int64_tests() {
-  do_check_throws(function() { ctypes.Int64(); }, Error);
+  do_check_throws(function() { ctypes.Int64(); }, TypeError);
 
   // Test that classes and prototypes are set up correctly.
   do_check_class(ctypes.Int64, "Function");
   do_check_class(ctypes.Int64.prototype, "Int64");
 
   do_check_true(ctypes.Int64.hasOwnProperty("prototype"));
   do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor"));
   do_check_true(ctypes.Int64.prototype.constructor === ctypes.Int64);
@@ -329,21 +329,21 @@ function run_Int64_tests() {
 
   // Test Int64.toString([radix]).
   do_check_eq(i.toString(), "0");
   for (let radix = 2; radix <= 36; ++radix)
     do_check_eq(i.toString(radix), "0");
   do_check_throws(function() { i.toString(0); }, Error);
   do_check_throws(function() { i.toString(1); }, Error);
   do_check_throws(function() { i.toString(37); }, Error);
-  do_check_throws(function() { i.toString(10, 2); }, Error);
+  do_check_throws(function() { i.toString(10, 2); }, TypeError);
 
   // Test Int64.toSource().
   do_check_eq(i.toSource(), "ctypes.Int64(\"0\")");
-  do_check_throws(function() { i.toSource(10); }, Error);
+  do_check_throws(function() { i.toSource(10); }, TypeError);
 
   i = ctypes.Int64("0x28590a1c921def71");
   do_check_eq(i.toString(), i.toString(10));
   do_check_eq(i.toString(10), "2907366152271163249");
   do_check_eq(i.toString(16), "28590a1c921def71");
   do_check_eq(i.toString(2), "10100001011001000010100001110010010010000111011110111101110001");
   do_check_eq(i.toSource(), "ctypes.Int64(\"" + i.toString(10) + "\")");
 
@@ -466,17 +466,17 @@ function run_Int64_tests() {
   do_check_eq(ctypes.Int64.join(-0x80000000, 0x00000000).toString(16), "-8000000000000000");
   do_check_throws(function() { ctypes.Int64.join(-0x80000001, 0); }, TypeError);
   do_check_throws(function() { ctypes.Int64.join(0x80000000, 0); }, TypeError);
   do_check_throws(function() { ctypes.Int64.join(0, -0x1); }, TypeError);
   do_check_throws(function() { ctypes.Int64.join(0, 0x800000000); }, TypeError);
 }
 
 function run_UInt64_tests() {
-  do_check_throws(function() { ctypes.UInt64(); }, Error);
+  do_check_throws(function() { ctypes.UInt64(); }, TypeError);
 
   // Test that classes and prototypes are set up correctly.
   do_check_class(ctypes.UInt64, "Function");
   do_check_class(ctypes.UInt64.prototype, "UInt64");
 
   do_check_true(ctypes.UInt64.hasOwnProperty("prototype"));
   do_check_true(ctypes.UInt64.prototype.hasOwnProperty("constructor"));
   do_check_true(ctypes.UInt64.prototype.constructor === ctypes.UInt64);
@@ -500,21 +500,21 @@ function run_UInt64_tests() {
 
   // Test UInt64.toString([radix]).
   do_check_eq(i.toString(), "0");
   for (let radix = 2; radix <= 36; ++radix)
     do_check_eq(i.toString(radix), "0");
   do_check_throws(function() { i.toString(0); }, Error);
   do_check_throws(function() { i.toString(1); }, Error);
   do_check_throws(function() { i.toString(37); }, Error);
-  do_check_throws(function() { i.toString(10, 2); }, Error);
+  do_check_throws(function() { i.toString(10, 2); }, TypeError);
 
   // Test UInt64.toSource().
   do_check_eq(i.toSource(), "ctypes.UInt64(\"0\")");
-  do_check_throws(function() { i.toSource(10); }, Error);
+  do_check_throws(function() { i.toSource(10); }, TypeError);
 
   i = ctypes.UInt64("0x28590a1c921def71");
   do_check_eq(i.toString(), i.toString(10));
   do_check_eq(i.toString(10), "2907366152271163249");
   do_check_eq(i.toString(16), "28590a1c921def71");
   do_check_eq(i.toString(2), "10100001011001000010100001110010010010000111011110111101110001");
   do_check_eq(i.toSource(), "ctypes.UInt64(\"" + i.toString(10) + "\")");
 
@@ -1367,18 +1367,18 @@ function run_type_ctor_class_tests(c, t,
 }
 
 function run_StructType_tests() {
   run_type_ctor_class_tests(ctypes.StructType,
     ctypes.StructType("s", [{"a": ctypes.int32_t}, {"b": ctypes.int64_t}]),
     ctypes.StructType("t", [{"c": ctypes.int32_t}, {"d": ctypes.int64_t}]),
     [ "fields" ], [ "define" ], [], [ "addressOfField" ], [ "a", "b" ]);
 
-  do_check_throws(function() { ctypes.StructType(); }, Error);
-  do_check_throws(function() { ctypes.StructType("a", [], 5); }, Error);
+  do_check_throws(function() { ctypes.StructType(); }, TypeError);
+  do_check_throws(function() { ctypes.StructType("a", [], 5); }, TypeError);
   do_check_throws(function() { ctypes.StructType(null, []); }, Error);
   do_check_throws(function() { ctypes.StructType("a", null); }, Error);
 
   // Check that malformed descriptors are an error.
   do_check_throws(function() {
     ctypes.StructType("a", [{"x":ctypes.int32_t}, {"x":ctypes.int8_t}]);
   }, Error);
   do_check_throws(function() {
@@ -1419,18 +1419,18 @@ function run_StructType_tests() {
   let opaqueptr = opaqueptr_t();
   opaqueptr.value = opaqueptr_t(1);
   do_check_eq(ptrValue(opaqueptr), 1);
   do_check_throws(function() {
     opaqueptr.value = ctypes.StructType("a").ptr();
   }, TypeError);
 
   // Check that 'define' works.
-  do_check_throws(function() { opaque_t.define(); }, Error);
-  do_check_throws(function() { opaque_t.define([], 0); }, Error);
+  do_check_throws(function() { opaque_t.define(); }, TypeError);
+  do_check_throws(function() { opaque_t.define([], 0); }, TypeError);
   do_check_throws(function() { opaque_t.define([{}]); }, Error);
   do_check_throws(function() { opaque_t.define([{ a: 0 }]); }, Error);
   do_check_throws(function() {
     opaque_t.define([{ a: ctypes.int32_t, b: ctypes.int64_t }]);
   }, Error);
   do_check_throws(function() {
     opaque_t.define([{ a: ctypes.int32_t }, { b: 0 }]);
   }, Error);
@@ -1546,17 +1546,17 @@ function run_StructType_tests() {
 
   let g = g_t();
   do_check_eq(g.a, 0);
   do_check_eq(g.b, 0);
   g = new g_t(1, 2);
   do_check_eq(g.a, 1);
   do_check_eq(g.b, 2);
   do_check_throws(function() { g_t(1); }, TypeError);
-  do_check_throws(function() { g_t(1, 2, 3); }, Error);
+  do_check_throws(function() { g_t(1, 2, 3); }, TypeError);
 
   for (let field in g)
     do_check_true(field == "a" || field == "b");
 
   let g_a = g.address();
   do_check_true(g_a.constructor === g_t.ptr);
   do_check_eq(g_a.contents.a, g.a);
 
@@ -1571,19 +1571,19 @@ function run_StructType_tests() {
   do_check_eq(g2.a, 1);
   g2.a = 7;
   do_check_eq(g2.a, 7);
   do_check_eq(s.b.a, 7);
 
   g_a = s.addressOfField("b");
   do_check_true(g_a.constructor === g_t.ptr);
   do_check_eq(g_a.contents.a, s.b.a);
-  do_check_throws(function() { s.addressOfField(); }, Error);
+  do_check_throws(function() { s.addressOfField(); }, TypeError);
   do_check_throws(function() { s.addressOfField("d"); }, Error);
-  do_check_throws(function() { s.addressOfField("a", 2); }, Error);
+  do_check_throws(function() { s.addressOfField("a", 2); }, TypeError);
 
   do_check_eq(s.toSource(), "s_t(4, {\"a\": 7, \"b\": 2}, 10)");
   do_check_eq(s.toSource(), s.toString());
   eval("let s2 = " + s.toSource());
   do_check_true(s2.constructor === s_t);
   do_check_eq(s.b.b, s2.b.b);
 
   // Test that structs can be set from an object using 'value'.
@@ -1652,18 +1652,18 @@ function ptrValue(p) {
   return ctypes.cast(p, ctypes.uintptr_t).value.toString();
 }
 
 function run_PointerType_tests() {
   run_type_ctor_class_tests(ctypes.PointerType,
     ctypes.PointerType(ctypes.int32_t), ctypes.PointerType(ctypes.int64_t),
     [ "targetType" ], [], [ "contents" ], [ "isNull", "increment", "decrement" ], []);
 
-  do_check_throws(function() { ctypes.PointerType(); }, Error);
-  do_check_throws(function() { ctypes.PointerType(ctypes.int32_t, 5); }, Error);
+  do_check_throws(function() { ctypes.PointerType(); }, TypeError);
+  do_check_throws(function() { ctypes.PointerType(ctypes.int32_t, 5); }, TypeError);
   do_check_throws(function() { ctypes.PointerType(null); }, Error);
   do_check_throws(function() { ctypes.PointerType(ctypes.int32_t()); }, Error);
   do_check_throws(function() { ctypes.PointerType("void"); }, Error);
 
   let name = "g_t";
   let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
   let g = g_t(1, 2);
 
@@ -1830,23 +1830,23 @@ function run_PointerType_tests() {
 
 function run_FunctionType_tests() {
   run_type_ctor_class_tests(ctypes.FunctionType,
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t),
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ ctypes.int32_t ]),
     [ "abi", "returnType", "argTypes", "isVariadic" ],
     undefined, undefined, undefined, undefined);
 
-  do_check_throws(function() { ctypes.FunctionType(); }, Error);
+  do_check_throws(function() { ctypes.FunctionType(); }, TypeError);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ ctypes.void_t ]);
   }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ ctypes.void_t ], 5);
-  }, Error);
+  }, TypeError);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, ctypes.void_t);
   }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, null);
   }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t());
@@ -1955,19 +1955,19 @@ function run_FunctionType_tests() {
   }
 }
 
 function run_ArrayType_tests() {
   run_type_ctor_class_tests(ctypes.ArrayType,
     ctypes.ArrayType(ctypes.int32_t, 10), ctypes.ArrayType(ctypes.int64_t),
     [ "elementType", "length" ], [], [ "length" ], [ "addressOfElement" ]);
 
-  do_check_throws(function() { ctypes.ArrayType(); }, Error);
+  do_check_throws(function() { ctypes.ArrayType(); }, TypeError);
   do_check_throws(function() { ctypes.ArrayType(null); }, Error);
-  do_check_throws(function() { ctypes.ArrayType(ctypes.int32_t, 1, 5); }, Error);
+  do_check_throws(function() { ctypes.ArrayType(ctypes.int32_t, 1, 5); }, TypeError);
   do_check_throws(function() { ctypes.ArrayType(ctypes.int32_t, -1); }, Error);
 
   let name = "g_t";
   let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
   let g = g_t(1, 2);
 
   let a_t = ctypes.ArrayType(g_t, 10);
   do_check_eq(a_t.name, name + "[10]");
@@ -2006,17 +2006,17 @@ function run_ArrayType_tests() {
   let a2_t = ctypes.ArrayType(g_t);
   do_check_eq(a2_t.name, "g_t[]");
   do_check_eq(a2_t.length, undefined);
   do_check_eq(a2_t.size, undefined);
   let a2 = new a2_t(5);
   do_check_eq(a2.constructor.length, 5);
   do_check_eq(a2.length, 5);
   do_check_eq(a2.constructor.size, g_t.size * 5);
-  do_check_throws(function() { new a2_t(); }, Error);
+  do_check_throws(function() { new a2_t(); }, TypeError);
   do_check_throws(function() { ctypes.ArrayType(ctypes.ArrayType(g_t)); }, Error);
   do_check_throws(function() { ctypes.ArrayType(ctypes.ArrayType(g_t), 5); }, Error);
 
   let b_t = ctypes.int8_t.array(ctypes.UInt64(0xffff));
   do_check_eq(b_t.length, 0xffff);
   b_t = ctypes.int8_t.array(ctypes.Int64(0xffff));
   do_check_eq(b_t.length, 0xffff);