Add int8/int64 tests and simplify error propagation. b=513783, r=jorendorff
authorDan Witte <dwitte@mozilla.com>
Fri, 25 Sep 2009 09:44:00 -0700
changeset 33051 21c1f047ca90ee724519f1f10996d727d7ab9b8a
parent 33045 12c59fca275b54dc85870563e34253dd2c9ebbe2
child 33053 54ec92df69028993fce5cc9fbe4fdfc388c93feb
push idunknown
push userunknown
push dateunknown
reviewersjorendorff
bugs513783
milestone1.9.3a1pre
Add int8/int64 tests and simplify error propagation. b=513783, r=jorendorff
js/ctypes/Function.cpp
js/ctypes/Function.h
js/ctypes/Library.cpp
js/ctypes/Library.h
js/ctypes/tests/jsctypes-test.cpp
js/ctypes/tests/jsctypes-test.h
js/ctypes/tests/unit/test_jsctypes.js.in
--- a/js/ctypes/Function.cpp
+++ b/js/ctypes/Function.cpp
@@ -119,52 +119,52 @@ ToSource(JSContext* cx, jsval vp)
   JSString* str = JS_ValueToSource(cx, vp);
   if (str)
     return JS_GetStringBytes(str);
 
   JS_ClearPendingException(cx);
   return "<<error converting value to string>>";
 }
 
-static nsresult
+static bool
 TypeError(JSContext* cx, const char* expected, jsval actual)
 {
   const char* src = ToSource(cx, actual);
   JS_ReportErrorNumber(cx, GetErrorMessage, NULL,
                        CTYPESMSG_TYPE_ERROR, expected, src);
-  return NS_ERROR_FAILURE;
+  return false;
 }
 
-static nsresult
+static bool
 GetABI(PRUint16 aCallType, ffi_abi& aResult)
 {
   // determine the ABI from the subset of those available on the
   // given platform. nsIForeignLibrary::DEFAULT specifies the default
   // C calling convention (cdecl) on each platform.
   switch (aCallType) {
   case nsIForeignLibrary::DEFAULT:
     aResult = FFI_DEFAULT_ABI;
-    return NS_OK;
+    return true;
 #if defined(XP_WIN32)
   case nsIForeignLibrary::STDCALL:
     aResult = FFI_STDCALL;
-    return NS_OK;
+    return true;
 #endif
   default:
-    return NS_ERROR_INVALID_ARG;
+    return false;
   }
 }
 
-static nsresult
+static bool
 PrepareType(JSContext* aContext, jsval aType, Type& aResult)
 {
   // for now, the only types we accept are integer values.
   if (!JSVAL_IS_INT(aType)) {
     JS_ReportError(aContext, "Invalid type specification");
-    return NS_ERROR_FAILURE;
+    return false;
   }
 
   PRInt32 type = JSVAL_TO_INT(aType);
 
   switch (type) {
   case nsIForeignLibrary::VOID:
     aResult.mFFIType = ffi_type_void;
     break;
@@ -200,25 +200,25 @@ PrepareType(JSContext* aContext, jsval a
     aResult.mFFIType = ffi_type_double;
     break;
   case nsIForeignLibrary::STRING:
   case nsIForeignLibrary::USTRING:
     aResult.mFFIType = ffi_type_pointer;
     break;
   default:
     JS_ReportError(aContext, "Invalid type specification");
-    return NS_ERROR_NOT_IMPLEMENTED;
+    return false;
   }
 
   aResult.mType = type;
 
-  return NS_OK;
+  return true;
 }
 
-static nsresult
+static bool
 PrepareValue(JSContext* aContext, const Type& aType, jsval aValue, Value& aResult)
 {
   jsdouble d;
 
   switch (aType.mType) {
   case nsIForeignLibrary::BOOL:
     // Do not implicitly lose bits, but allow the values 0, 1, and -0.
     // Programs can convert explicitly, if needed, using `Boolean(v)` or `!!v`.
@@ -325,20 +325,20 @@ PrepareValue(JSContext* aContext, const 
       // with `String(x)` or `""+x`.
       return TypeError(aContext, "ustring", aValue);
     }
 
     aResult.mData = &aResult.mValue.mPointer;
     break;
   default:
     NS_NOTREACHED("invalid type");
-    return NS_ERROR_FAILURE;
+    return false;
   }
 
-  return NS_OK;
+  return true;
 }
 
 static void
 PrepareReturnValue(const Type& aType, Value& aResult)
 {
   switch (aType.mType) {
   case nsIForeignLibrary::VOID:
     aResult.mData = nsnull;
@@ -379,17 +379,17 @@ PrepareReturnValue(const Type& aType, Va
     aResult.mData = &aResult.mValue.mPointer;
     break;
   default:
     NS_NOTREACHED("invalid type");
     break;
   }
 }
 
-static nsresult
+static bool
 ConvertReturnValue(JSContext* aContext,
                    const Type& aResultType,
                    const Value& aResultValue,
                    jsval* aValue)
 {
   switch (aResultType.mType) {
   case nsIForeignLibrary::VOID:
     *aValue = JSVAL_VOID;
@@ -400,80 +400,80 @@ ConvertReturnValue(JSContext* aContext,
   case nsIForeignLibrary::INT8:
     *aValue = INT_TO_JSVAL(aResultValue.mValue.mInt8);
     break;
   case nsIForeignLibrary::INT16:
     *aValue = INT_TO_JSVAL(aResultValue.mValue.mInt16);
     break;
   case nsIForeignLibrary::INT32:
     if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mInt32), aValue))
-      return NS_ERROR_OUT_OF_MEMORY;
+      return false;
     break;
   case nsIForeignLibrary::INT64:
     // Implicit conversion with loss of bits.  :-[
     if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mInt64), aValue))
-      return NS_ERROR_OUT_OF_MEMORY;
+      return false;
     break;
   case nsIForeignLibrary::UINT8:
     *aValue = INT_TO_JSVAL(aResultValue.mValue.mUint8);
     break;
   case nsIForeignLibrary::UINT16:
     *aValue = INT_TO_JSVAL(aResultValue.mValue.mUint16);
     break;
   case nsIForeignLibrary::UINT32:
     if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mUint32), aValue))
-      return NS_ERROR_OUT_OF_MEMORY;
+      return false;
     break;
   case nsIForeignLibrary::UINT64:
     // Implicit conversion with loss of bits.  :-[
     if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mUint64), aValue))
-      return NS_ERROR_OUT_OF_MEMORY;
+      return false;
     break;
   case nsIForeignLibrary::FLOAT:
     if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mFloat), aValue))
-      return NS_ERROR_OUT_OF_MEMORY;
+      return false;
     break;
   case nsIForeignLibrary::DOUBLE:
     if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mDouble), aValue))
-      return NS_ERROR_OUT_OF_MEMORY;
+      return false;
     break;
   case nsIForeignLibrary::STRING: {
     if (!aResultValue.mValue.mPointer) {
       // Allow returning a null pointer.
       *aValue = JSVAL_NULL;
     } else {
       JSString *jsstring = JS_NewStringCopyZ(aContext,
                              reinterpret_cast<const char*>(aResultValue.mValue.mPointer));
       if (!jsstring)
-        return NS_ERROR_OUT_OF_MEMORY;
+        return false;
 
       *aValue = STRING_TO_JSVAL(jsstring);
     }
     break;
   }
   case nsIForeignLibrary::USTRING: {
     if (!aResultValue.mValue.mPointer) {
       // Allow returning a null pointer.
       *aValue = JSVAL_NULL;
     } else {
       JSString *jsstring = JS_NewUCStringCopyZ(aContext,
                              reinterpret_cast<const jschar*>(aResultValue.mValue.mPointer));
       if (!jsstring)
-        return NS_ERROR_OUT_OF_MEMORY;
+        return false;
 
       *aValue = STRING_TO_JSVAL(jsstring);
     }
     break;
   }
   default:
     NS_NOTREACHED("invalid type");
-    return NS_ERROR_FAILURE;
+    return false;
   }
 
-  return NS_OK;
+  return true;
 }
 
 /*******************************************************************************
 ** Function
 *******************************************************************************/
 
 NS_IMPL_ISUPPORTS1(Function, nsIXPCScriptable)
 
@@ -481,82 +481,77 @@ Function::Function()
   : mFunc(nsnull)
 {
 }
 
 Function::~Function()
 {
 }
 
-nsresult
+bool
 Function::Init(JSContext* aContext,
                Library* aLibrary,
                PRFuncPtr aFunc,
                PRUint16 aCallType,
                jsval aResultType,
                const nsTArray<jsval>& aArgTypes)
 {
-  nsresult rv;
-
   mLibrary = aLibrary;
   mFunc = aFunc;
 
   // determine the ABI
-  rv = GetABI(aCallType, mCallType);
-  if (NS_FAILED(rv)) {
+  if (!GetABI(aCallType, mCallType)) {
     JS_ReportError(aContext, "Invalid ABI specification");
-    return rv;
+    return false;
   }
 
   // prepare the result type
-  rv = PrepareType(aContext, aResultType, mResultType);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (!PrepareType(aContext, aResultType, mResultType))
+    return false;
 
   // prepare the argument types
   for (PRUint32 i = 0; i < aArgTypes.Length(); ++i) {
-    rv = PrepareType(aContext, aArgTypes[i], *mArgTypes.AppendElement());
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (!PrepareType(aContext, aArgTypes[i], *mArgTypes.AppendElement()))
+      return false;
 
     // disallow void argument types
     if (mArgTypes[i].mType == nsIForeignLibrary::VOID) {
       JS_ReportError(aContext, "Cannot have void argument type");
-      return NS_ERROR_INVALID_ARG;
+      return false;
     }
 
     // ffi_prep_cif requires an array of ffi_types; prepare it separately.
     mFFITypes.AppendElement(&mArgTypes[i].mFFIType);
   }
 
   ffi_status status = ffi_prep_cif(&mCIF, mCallType, mFFITypes.Length(),
                                    &mResultType.mFFIType, mFFITypes.Elements());
   switch (status) {
   case FFI_OK:
-    return NS_OK;
+    return true;
   case FFI_BAD_ABI:
     JS_ReportError(aContext, "Invalid ABI specification");
-    return NS_ERROR_INVALID_ARG;
+    return false;
   case FFI_BAD_TYPEDEF:
     JS_ReportError(aContext, "Invalid type specification");
-    return NS_ERROR_INVALID_ARG;
+    return false;
   default:
     JS_ReportError(aContext, "Unknown libffi error");
-    return NS_ERROR_FAILURE;
+    return false;
   }
 }
 
-PRBool
+bool
 Function::Execute(JSContext* aContext, PRUint32 aArgc, jsval* aArgv, jsval* aValue)
 {
-  nsresult rv;
-
   // prepare the values for each argument
   nsAutoTArray<Value, 16> values;
   for (PRUint32 i = 0; i < mArgTypes.Length(); ++i) {
-    rv = PrepareValue(aContext, mArgTypes[i], aArgv[i], *values.AppendElement());
-    if (NS_FAILED(rv)) return PR_FALSE;
+    if (!PrepareValue(aContext, mArgTypes[i], aArgv[i], *values.AppendElement()))
+      return false;
   }
 
   // create an array of pointers to each value, for passing to ffi_call
   nsAutoTArray<void*, 16> ffiValues;
   for (PRUint32 i = 0; i < mArgTypes.Length(); ++i) {
     ffiValues.AppendElement(values[i].mData);
   }
 
@@ -568,20 +563,17 @@ Function::Execute(JSContext* aContext, P
   // may block or otherwise take a long time to return.
   jsrefcount rc = JS_SuspendRequest(aContext);
 
   ffi_call(&mCIF, mFunc, resultValue.mData, ffiValues.Elements());
 
   JS_ResumeRequest(aContext, rc);
 
   // prepare a JS object from the result
-  rv = ConvertReturnValue(aContext, mResultType, resultValue, aValue);
-  if (NS_FAILED(rv)) return PR_FALSE;
-
-  return PR_TRUE;
+  return ConvertReturnValue(aContext, mResultType, resultValue, aValue);
 }
 
 /*******************************************************************************
 ** nsIXPCScriptable implementation
 *******************************************************************************/
 
 #define XPC_MAP_CLASSNAME Function
 #define XPC_MAP_QUOTED_CLASSNAME "Function"
@@ -597,27 +589,24 @@ Function::Call(nsIXPConnectWrappedNative
                PRUint32 argc, 
                jsval* argv, 
                jsval* vp, 
                PRBool* _retval)
 {
   if (!mLibrary->IsOpen()) {
     JS_ReportError(cx, "Library is not open");
     *_retval = PR_FALSE;
-    return NS_ERROR_FAILURE;
+    return NS_OK;
   }
 
   if (argc != mArgTypes.Length()) {
     JS_ReportError(cx, "Number of arguments does not match declaration");
     *_retval = PR_FALSE;
-    return NS_ERROR_FAILURE;
+    return NS_OK;
   }
 
   *_retval = Execute(cx, argc, argv, vp);
-  if (!*_retval)
-    return NS_ERROR_FAILURE;
-
   return NS_OK;
 }
 
 }
 }
 
--- a/js/ctypes/Function.h
+++ b/js/ctypes/Function.h
@@ -90,22 +90,22 @@ struct Value
 class Function : public nsIXPCScriptable
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIXPCSCRIPTABLE
 
   Function();
 
-  nsresult Init(JSContext* aContext, Library* aLibrary, PRFuncPtr aFunc, PRUint16 aCallType, jsval aResultType, const nsTArray<jsval>& aArgTypes);
+  bool Init(JSContext* aContext, Library* aLibrary, PRFuncPtr aFunc, PRUint16 aCallType, jsval aResultType, const nsTArray<jsval>& aArgTypes);
 
 private:
   ~Function();
 
-  PRBool Execute(JSContext* aContext, PRUint32 aArgc, jsval* aArgv, jsval* aValue);
+  bool Execute(JSContext* aContext, PRUint32 aArgc, jsval* aArgv, jsval* aValue);
 
 protected:
   // reference to the library our function is in
   nsRefPtr<Library> mLibrary;
 
   PRFuncPtr mFunc;
 
   ffi_abi mCallType;
--- a/js/ctypes/Library.cpp
+++ b/js/ctypes/Library.cpp
@@ -44,41 +44,41 @@
 #include "nsAutoPtr.h"
 #include "nsILocalFile.h"
 #include "prlink.h"
 #include "jsapi.h"
 
 namespace mozilla {
 namespace ctypes {
 
-static inline nsresult
+static inline bool
 jsvalToUint16(JSContext* aContext, jsval aVal, PRUint16& aResult)
 {
   if (JSVAL_IS_INT(aVal)) {
     PRUint32 i = JSVAL_TO_INT(aVal);
     if (i <= PR_UINT16_MAX) {
       aResult = i;
-      return NS_OK;
+      return true;
     }
   }
 
   JS_ReportError(aContext, "Parameter must be a valid ABI constant");
-  return NS_ERROR_INVALID_ARG;
+  return false;
 }
 
-static inline nsresult
+static inline bool
 jsvalToCString(JSContext* aContext, jsval aVal, const char*& aResult)
 {
   if (JSVAL_IS_STRING(aVal)) {
     aResult = JS_GetStringBytes(JSVAL_TO_STRING(aVal));
-    return NS_OK;
+    return true;
   }
 
   JS_ReportError(aContext, "Parameter must be a string");
-  return NS_ERROR_INVALID_ARG;
+  return false;
 }
 
 NS_IMPL_ISUPPORTS1(Library, nsIForeignLibrary)
 
 Library::Library()
   : mLibrary(nsnull)
 {
 }
@@ -131,41 +131,41 @@ Library::Declare(nsISupports** aResult)
   PRUint32 argc;
   jsval *argv;
   ncc->GetArgc(&argc);
   ncc->GetArgvPtr(&argv);
 
   // we always need at least a method name, a call type and a return type
   if (argc < 3) {
     JS_ReportError(ctx, "Insufficient number of arguments");
-    return NS_ERROR_INVALID_ARG;
+    return NS_OK;
   }
 
   const char* name;
-  rv = jsvalToCString(ctx, argv[0], name);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (!jsvalToCString(ctx, argv[0], name))
+    return NS_OK;
 
   PRUint16 callType;
-  rv = jsvalToUint16(ctx, argv[1], callType);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (!jsvalToUint16(ctx, argv[1], callType))
+    return NS_OK;
 
   nsAutoTArray<jsval, 16> argTypes;
   for (PRUint32 i = 3; i < argc; ++i) {
     argTypes.AppendElement(argv[i]);
   }
 
   PRFuncPtr func = PR_FindFunctionSymbol(mLibrary, name);
   if (!func) {
     JS_ReportError(ctx, "Couldn't find function symbol in library");
-    return NS_ERROR_FAILURE;
+    return NS_OK;
   }
 
   nsRefPtr<Function> call = new Function;
-  rv = call->Init(ctx, this, func, callType, argv[2], argTypes);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (!call->Init(ctx, this, func, callType, argv[2], argTypes))
+    return NS_OK;
 
   call.forget(aResult);
-  return rv;
+  return NS_OK;
 }
 
 }
 }
 
--- a/js/ctypes/Library.h
+++ b/js/ctypes/Library.h
@@ -56,17 +56,17 @@ namespace ctypes {
 class Library : public nsIForeignLibrary
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIFOREIGNLIBRARY
 
   Library();
 
-  PRBool IsOpen() { return mLibrary != nsnull; }
+  bool IsOpen() { return mLibrary != nsnull; }
 
 private:
   ~Library();
 
   PRLibrary* mLibrary;
 };
 
 }
--- a/js/ctypes/tests/jsctypes-test.cpp
+++ b/js/ctypes/tests/jsctypes-test.cpp
@@ -45,48 +45,88 @@
 
 void
 test_v()
 {
   // do nothing
   return;
 }
 
-short
-test_s()
+PRInt8
+test_i8()
+{
+  return 123;
+}
+
+PRInt8
+test_i8_i8(PRInt8 number)
+{
+  return number;
+}
+
+PRInt8
+test_i8_i8_sum(PRInt8 number1, PRInt8 number2)
+{
+  return number1 + number2;
+}
+
+PRInt16
+test_i16()
 {
   return 12345;
 }
 
-short
-test_s_s(short number)
+PRInt16
+test_i16_i16(PRInt16 number)
 {
   return number;
 }
 
-short
-test_s_ss(short number1, short number2)
+PRInt16
+test_i16_i16_sum(PRInt16 number1, PRInt16 number2)
 {
   return number1 + number2;
 }
 
-int
-test_i()
+PRInt32
+test_i32()
 {
   return 123456789;
 }
 
-int
-test_i_i(int number)
+PRInt32
+test_i32_i32(PRInt32 number)
 {
   return number;
 }
 
-int
-test_i_ii(int number1, int number2)
+PRInt32
+test_i32_i32_sum(PRInt32 number1, PRInt32 number2)
+{
+  return number1 + number2;
+}
+
+PRInt64
+test_i64()
+{
+#if defined(WIN32) && !defined(__GNUC__)
+  return 0x28590a1c921de000i64;
+#else
+  return 0x28590a1c921de000LL;
+#endif
+}
+
+PRInt64
+test_i64_i64(PRInt64 number)
+{
+  return number;
+}
+
+PRInt64
+test_i64_i64_sum(PRInt64 number1, PRInt64 number2)
 {
   return number1 + number2;
 }
 
 float
 test_f()
 {
   return 123456.5f;
@@ -94,49 +134,49 @@ test_f()
 
 float
 test_f_f(float number)
 {
   return number;
 }
 
 float
-test_f_ff(float number1, float number2)
+test_f_f_sum(float number1, float number2)
 {
   return (number1 + number2);
 }
 
 double
 test_d()
 {
-  return 123456789.5;
+  return 1234567890123456789.5;
 }
 
 double
 test_d_d(double number)
 {
   return number;
 }
 
 double
-test_d_dd(double number1, double number2)
+test_d_d_sum(double number1, double number2)
 {
   return (number1 + number2);
 }
 
-int
+PRInt32
 test_ansi_len(const char* string)
 {
-  return int(strlen(string));
+  return PRInt32(strlen(string));
 }
 
-int
+PRInt32
 test_wide_len(const PRUnichar* string)
 {
-  return int(NS_strlen(string));
+  return PRInt32(NS_strlen(string));
 }
 
 const char *
 test_ansi_ret()
 {
   return "success";
 }
 
@@ -148,14 +188,14 @@ test_wide_ret()
 }
 
 char *
 test_ansi_echo(const char* string)
 {
   return (char*)string;
 }
 
-int
-test_i_if_floor(int number1, float number2)
+PRInt32
+test_floor(PRInt32 number1, float number2)
 {
-  return int(floor(float(number1) + number2));
+  return PRInt32(floor(float(number1) + number2));
 }
 
--- a/js/ctypes/tests/jsctypes-test.h
+++ b/js/ctypes/tests/jsctypes-test.h
@@ -34,67 +34,47 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nscore.h"
+#include "prtypes.h"
 
 NS_EXTERN_C
 {
   NS_EXPORT void test_v();
 
-  NS_EXPORT short test_s();
-  NS_EXPORT short test_s_s(short);
-  NS_EXPORT short test_s_ss(short, short);
+  NS_EXPORT PRInt8 test_i8();
+  NS_EXPORT PRInt8 test_i8_i8(PRInt8);
+  NS_EXPORT PRInt8 test_i8_i8_sum(PRInt8, PRInt8);
+
+  NS_EXPORT PRInt16 test_i16();
+  NS_EXPORT PRInt16 test_i16_i16(PRInt16);
+  NS_EXPORT PRInt16 test_i16_i16_sum(PRInt16, PRInt16);
 
-  NS_EXPORT int test_i();
-  NS_EXPORT int test_i_i(int);
-  NS_EXPORT int test_i_ii(int, int);
+  NS_EXPORT PRInt32 test_i32();
+  NS_EXPORT PRInt32 test_i32_i32(PRInt32);
+  NS_EXPORT PRInt32 test_i32_i32_sum(PRInt32, PRInt32);
+
+  NS_EXPORT PRInt64 test_i64();
+  NS_EXPORT PRInt64 test_i64_i64(PRInt64);
+  NS_EXPORT PRInt64 test_i64_i64_sum(PRInt64, PRInt64);
 
   NS_EXPORT float test_f();
   NS_EXPORT float test_f_f(float);
-  NS_EXPORT float test_f_ff(float, float);
+  NS_EXPORT float test_f_f_sum(float, float);
 
   NS_EXPORT double test_d();
   NS_EXPORT double test_d_d(double);
-  NS_EXPORT double test_d_dd(double, double);
+  NS_EXPORT double test_d_d_sum(double, double);
 
-  NS_EXPORT int test_ansi_len(const char*);
-  NS_EXPORT int test_wide_len(const PRUnichar*);
+  NS_EXPORT PRInt32 test_ansi_len(const char*);
+  NS_EXPORT PRInt32 test_wide_len(const PRUnichar*);
   NS_EXPORT const char* test_ansi_ret();
   NS_EXPORT const PRUnichar* test_wide_ret();
   NS_EXPORT char* test_ansi_echo(const char*);
 
-  NS_EXPORT int test_i_if_floor(int, float);
-
-  struct POINT {
-    int x;
-    int y;
-  };
-
-  struct RECT {
-    int top;
-    int left;
-    int bottom;
-    int right;
-  };
+  NS_EXPORT PRInt32 test_floor(PRInt32, float);
+}
 
-  struct INNER {
-    unsigned char i1;
-    long long int i2;
-    char i3;
-  };
-
-  struct NESTED {
-    int n1;
-    short n2;
-    INNER inner;
-    long long int n3;
-    int n4;
-  };
-
-  NS_EXPORT int test_pt_in_rect(RECT, POINT);
-  NS_EXPORT int test_nested_struct(NESTED);
-  NS_EXPORT POINT test_struct_return(RECT);
-}
--- a/js/ctypes/tests/unit/test_jsctypes.js.in
+++ b/js/ctypes/tests/unit/test_jsctypes.js.in
@@ -72,96 +72,164 @@ function run_test()
   // unsupported OS - don't run the test
   return;
 #endif
 
   // open the library with an nsILocalFile
   var library = ctypes.open(libfile);
 
   run_void_tests(library);
-  run_short_tests(library);
-  run_int_tests(library);
+  run_int8_tests(library);
+  run_int16_tests(library);
+  run_int32_tests(library);
+  run_int64_tests(library);
   run_float_tests(library);
   run_double_tests(library);
   run_string_tests(library);
   run_mixed_tests(library);
 
   // test the string version of ctypes.open() as well
   var libpath = libfile.path;
   library = ctypes.open(libpath);
   run_void_tests(library);
 }
 
 function run_void_tests(library) {
   var test_v = library.declare("test_v", Types.DEFAULT, Types.VOID);
   do_check_eq(test_v(), undefined);
 }
 
-function run_short_tests(library) {
-  var test_s = library.declare("test_s", Types.DEFAULT, Types.INT16);
-  do_check_eq(test_s(), 12345);
+function run_int8_tests(library) {
+  var test_i8 = library.declare("test_i8", Types.DEFAULT, Types.INT8);
+  do_check_eq(test_i8(), 123);
+
+  var test_i8_i8 = library.declare("test_i8_i8", Types.DEFAULT, Types.INT8, Types.INT8);
+  do_check_eq(test_i8_i8(5), 5);
+  do_check_eq(test_i8_i8(0), 0);
+  do_check_eq(test_i8_i8(0x7f), 0x7f);
+  do_check_eq(test_i8_i8(-0x80), -0x80);
+  do_check_eq(1/test_i8_i8(-0), 1/0);  // that is, test_i8_i8(-0) is +0
+  do_check_eq(test_i8_i8(true), 1);
+  do_check_eq(test_i8_i8(false), 0);
+
+  // don't convert anything else to an int8
+  var vals = [0x80, -0x81, 0x100000000, Infinity, -Infinity, NaN,
+              null, undefined, "", "0", {}, [], new Number(16),
+              {toString: function () { return 7; }},
+              {valueOf: function () { return 7; }}];
+  for (var i = 0; i < vals.length; i++)
+    do_check_throws(function () { test_i8_i8(vals[i]); }, TypeError);
 
-  var test_s_s = library.declare("test_s_s", Types.DEFAULT, Types.INT16, Types.INT16);
-  do_check_eq(test_s_s(5), 5);
-  do_check_eq(test_s_s(0), 0);
-  do_check_eq(test_s_s(0x7fff), 0x7fff);
-  do_check_eq(test_s_s(-0x8000), -0x8000);
-  do_check_eq(1/test_s_s(-0), 1/0);  // that is, test_s_s(-0) is +0
-  do_check_eq(test_s_s(true), 1);
-  do_check_eq(test_s_s(false), 0);
+  var test_i8_i8_sum = library.declare("test_i8_i8_sum", Types.DEFAULT, Types.INT8, Types.INT8, Types.INT8);
+  do_check_eq(test_i8_i8_sum(5, 5), 10);
+
+  // test the range of unsigned. (we can reuse the signed C function
+  // here, since it's binary-compatible.)
+  var test_ui8_ui8 = library.declare("test_i8_i8", Types.DEFAULT, Types.UINT8, Types.UINT8);
+  do_check_eq(test_ui8_ui8(0xff), 0xff);
+  do_check_throws(function () { test_ui8_ui8(0x100); }, TypeError);
+  do_check_throws(function () { test_ui8_ui8(-1); }, TypeError);
+}
+
+function run_int16_tests(library) {
+  var test_i16 = library.declare("test_i16", Types.DEFAULT, Types.INT16);
+  do_check_eq(test_i16(), 12345);
+
+  var test_i16_i16 = library.declare("test_i16_i16", Types.DEFAULT, Types.INT16, Types.INT16);
+  do_check_eq(test_i16_i16(5), 5);
+  do_check_eq(test_i16_i16(0), 0);
+  do_check_eq(test_i16_i16(0x7fff), 0x7fff);
+  do_check_eq(test_i16_i16(-0x8000), -0x8000);
+  do_check_eq(1/test_i16_i16(-0), 1/0);  // that is, test_i16_i16(-0) is +0
+  do_check_eq(test_i16_i16(true), 1);
+  do_check_eq(test_i16_i16(false), 0);
 
   // don't convert anything else to an int16
   var vals = [0x8000, -0x8001, 0x100000000, Infinity, -Infinity, NaN,
               null, undefined, "", "0", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (var i = 0; i < vals.length; i++)
-    do_check_throws(function () { test_s_s(vals[i]); }, TypeError);
+    do_check_throws(function () { test_i16_i16(vals[i]); }, TypeError);
 
-  var test_s_ss = library.declare("test_s_ss", Types.DEFAULT, Types.INT16, Types.INT16, Types.INT16);
-  do_check_eq(test_s_ss(5, 5), 10);
+  var test_i16_i16_sum = library.declare("test_i16_i16_sum", Types.DEFAULT, Types.INT16, Types.INT16, Types.INT16);
+  do_check_eq(test_i16_i16_sum(5, 5), 10);
 
   // test the range of unsigned. (we can reuse the signed C function
   // here, since it's binary-compatible.)
-  var test_us_us = library.declare("test_s_s", Types.DEFAULT, Types.UINT16, Types.UINT16);
-  do_check_eq(test_us_us(0xffff), 0xffff);
-  do_check_throws(function () { test_us_us(0x10000); }, TypeError);
-  do_check_throws(function () { test_us_us(-1); }, TypeError);
+  var test_ui16_ui16 = library.declare("test_i16_i16", Types.DEFAULT, Types.UINT16, Types.UINT16);
+  do_check_eq(test_ui16_ui16(0xffff), 0xffff);
+  do_check_throws(function () { test_ui16_ui16(0x10000); }, TypeError);
+  do_check_throws(function () { test_ui16_ui16(-1); }, TypeError);
 }
 
-function run_int_tests(library) {
-  var test_i = library.declare("test_i", Types.DEFAULT, Types.INT32);
-  do_check_eq(test_i(), 123456789);
+function run_int32_tests(library) {
+  var test_i32 = library.declare("test_i32", Types.DEFAULT, Types.INT32);
+  do_check_eq(test_i32(), 123456789);
 
-  var test_i_i = library.declare("test_i_i", Types.DEFAULT, Types.INT32, Types.INT32);
-  do_check_eq(test_i_i(5), 5);
-  do_check_eq(test_i_i(0), 0);
-  do_check_eq(test_i_i(0x7fffffff), 0x7fffffff);
-  do_check_eq(test_i_i(-0x80000000), -0x80000000);
-  do_check_eq(1/test_i_i(-0), 1/0);  // that is, test_i_i(-0) is +0
-  do_check_eq(test_i_i(true), 1);
-  do_check_eq(test_i_i(false), 0);
+  var test_i32_i32 = library.declare("test_i32_i32", Types.DEFAULT, Types.INT32, Types.INT32);
+  do_check_eq(test_i32_i32(5), 5);
+  do_check_eq(test_i32_i32(0), 0);
+  do_check_eq(test_i32_i32(0x7fffffff), 0x7fffffff);
+  do_check_eq(test_i32_i32(-0x80000000), -0x80000000);
+  do_check_eq(1/test_i32_i32(-0), 1/0);  // that is, test_i32_i32(-0) is +0
+  do_check_eq(test_i32_i32(true), 1);
+  do_check_eq(test_i32_i32(false), 0);
 
-  // don't convert anything else to an int
+  // don't convert anything else to an int32
   var vals = [0x80000000, -0x80000001, Infinity, -Infinity, NaN,
               null, undefined, "", "0", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (var i = 0; i < vals.length; i++)
-    do_check_throws(function () { test_i_i(vals[i]); }, TypeError);
+    do_check_throws(function () { test_i32_i32(vals[i]); }, TypeError);
 
-  var test_i_ii = library.declare("test_i_ii", Types.DEFAULT, Types.INT32, Types.INT32, Types.INT32);
-  do_check_eq(test_i_ii(5, 5), 10);
+  var test_i32_i32_sum = library.declare("test_i32_i32_sum", Types.DEFAULT, Types.INT32, Types.INT32, Types.INT32);
+  do_check_eq(test_i32_i32_sum(5, 5), 10);
 
   // test the range of unsigned. (we can reuse the signed C function
   // here, since it's binary-compatible.)
-  var test_ui_ui = library.declare("test_i_i", Types.DEFAULT, Types.UINT32, Types.UINT32);
-  do_check_eq(test_ui_ui(0xffffffff), 0xffffffff);
-  do_check_throws(function () { test_ui_ui(0x100000000); }, TypeError);
-  do_check_throws(function () { test_ui_ui(-1); }, TypeError);
+  var test_ui32_ui32 = library.declare("test_i32_i32", Types.DEFAULT, Types.UINT32, Types.UINT32);
+  do_check_eq(test_ui32_ui32(0xffffffff), 0xffffffff);
+  do_check_throws(function () { test_ui32_ui32(0x100000000); }, TypeError);
+  do_check_throws(function () { test_ui32_ui32(-1); }, TypeError);
+}
+
+function run_int64_tests(library) {
+  var test_i64 = library.declare("test_i64", Types.DEFAULT, Types.INT64);
+  // JS represents 64 bit ints as doubles, so we have to be careful how many
+  // significant digits we use
+  do_check_eq(test_i64(), 0x28590a1c921de000);
+
+  var test_i64_i64 = library.declare("test_i64_i64", Types.DEFAULT, Types.INT64, Types.INT64);
+  do_check_eq(test_i64_i64(5), 5);
+  do_check_eq(test_i64_i64(0), 0);
+  do_check_eq(test_i64_i64(0x7ffffffffffffc00), 0x7ffffffffffffc00);
+  do_check_eq(test_i64_i64(-0x8000000000000000), -0x8000000000000000);
+  do_check_eq(1/test_i64_i64(-0), 1/0);  // that is, test_i64_i64(-0) is +0
+  do_check_eq(test_i64_i64(true), 1);
+  do_check_eq(test_i64_i64(false), 0);
+
+  // don't convert anything else to an int64
+  var vals = [0x8000000000000000, -0x8000000000001000, Infinity, -Infinity, NaN,
+              null, undefined, "", "0", {}, [], new Number(16),
+              {toString: function () { return 7; }},
+              {valueOf: function () { return 7; }}];
+  for (var i = 0; i < vals.length; i++)
+    do_check_throws(function () { test_i64_i64(vals[i]); }, TypeError);
+
+  var test_i64_i64_sum = library.declare("test_i64_i64_sum", Types.DEFAULT, Types.INT64, Types.INT64, Types.INT64);
+  do_check_eq(test_i64_i64_sum(5, 5), 10);
+
+  // test the range of unsigned. (we can reuse the signed C function
+  // here, since it's binary-compatible.)
+  var test_ui64_ui64 = library.declare("test_i64_i64", Types.DEFAULT, Types.UINT64, Types.UINT64);
+  do_check_eq(test_ui64_ui64(0xfffffffffffff800), 0xfffffffffffff800);
+  do_check_throws(function () { test_ui64_ui64(0x10000000000000000); }, TypeError);
+  do_check_throws(function () { test_ui64_ui64(-1); }, TypeError);
 }
 
 function run_float_tests(library) {
   var test_f = library.declare("test_f", Types.DEFAULT, Types.FLOAT);
   do_check_eq(test_f(), 123456.5);
 
   var test_f_f = library.declare("test_f_f", Types.DEFAULT, Types.FLOAT, Types.FLOAT);
   do_check_eq(test_f_f(5), 5);
@@ -176,43 +244,43 @@ function run_float_tests(library) {
 
   // don't convert anything else to a float
   var vals = [true, false, null, undefined, "", "0", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (var i = 0; i < vals.length; i++)
     do_check_throws(function () { test_f_f(vals[i]); }, TypeError);
 
-  var test_f_ff = library.declare("test_f_ff", Types.DEFAULT, Types.FLOAT, Types.FLOAT, Types.FLOAT);
-  do_check_eq(test_f_ff(5, 5), 10);
-  do_check_eq(test_f_ff(5.5, 5.5), 11);
+  var test_f_f_sum = library.declare("test_f_f_sum", Types.DEFAULT, Types.FLOAT, Types.FLOAT, Types.FLOAT);
+  do_check_eq(test_f_f_sum(5, 5), 10);
+  do_check_eq(test_f_f_sum(5.5, 5.5), 11);
 }
 
 function run_double_tests(library) {
   var test_d = library.declare("test_d", Types.DEFAULT, Types.DOUBLE);
-  do_check_eq(test_d(), 123456789.5);
+  do_check_eq(test_d(), 1234567890123456789.5);
 
   var test_d_d = library.declare("test_d_d", Types.DEFAULT, Types.DOUBLE, Types.DOUBLE);
   do_check_eq(test_d_d(5), 5);
   do_check_eq(test_d_d(5.25), 5.25);
   do_check_eq(test_d_d(Infinity), Infinity);
   do_check_eq(test_d_d(-Infinity), -Infinity);
   do_check_eq(isNaN(test_d_d(NaN)), true);
   do_check_eq(1/test_d_d(-0), 1/-0); // that is, test_d_d(-0) is -0
 
   // don't convert anything else to a double
   var vals = [true, false, null, undefined, "", "0", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (var i = 0; i < vals.length; i++)
     do_check_throws(function () { test_d_d(vals[i]); }, TypeError);
 
-  var test_d_dd = library.declare("test_d_dd", Types.DEFAULT, Types.DOUBLE, Types.DOUBLE, Types.DOUBLE);
-  do_check_eq(test_d_dd(5, 5), 10);
-  do_check_eq(test_d_dd(5.5, 5.5), 11);
+  var test_d_d_sum = library.declare("test_d_d_sum", Types.DEFAULT, Types.DOUBLE, Types.DOUBLE, Types.DOUBLE);
+  do_check_eq(test_d_d_sum(5, 5), 10);
+  do_check_eq(test_d_d_sum(5.5, 5.5), 11);
 }
 
 function run_string_tests(library) {
   var test_ansi_len = library.declare("test_ansi_len", Types.DEFAULT, Types.INT32, Types.STRING);
   do_check_eq(test_ansi_len(""), 0);
   do_check_eq(test_ansi_len("hello world"), 11);
 
   // don't convert anything else to a string
@@ -230,13 +298,13 @@ function run_string_tests(library) {
   do_check_eq(test_wide_ret(), "success");
 
   var test_ansi_echo = library.declare("test_ansi_echo", Types.DEFAULT, Types.STRING, Types.STRING);
   do_check_eq(test_ansi_echo("anybody in there?"), "anybody in there?");
   do_check_eq(test_ansi_echo(null), null);
 }
 
 function run_mixed_tests(library) {
-  var test_i_if_floor = library.declare("test_i_if_floor", Types.DEFAULT, Types.INT32, Types.INT32, Types.FLOAT);
-  do_check_eq(test_i_if_floor(5, 5.5), 10);
-  do_check_throws(function() { test_i_if_floor(5.5, 5); }, TypeError);
+  var test_floor = library.declare("test_floor", Types.DEFAULT, Types.INT32, Types.INT32, Types.FLOAT);
+  do_check_eq(test_floor(5, 5.5), 10);
+  do_check_throws(function() { test_floor(5.5, 5); }, TypeError);
 }