diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 038602d98075..d1c714dee196 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -2273,6 +2273,7 @@ InitTypeClasses(JSContext* cx, HandleObject ctypesObj) // Attach objects representing ABI constants. if (!DefineABIConstant(cx, ctypesObj, "default_abi", ABI_DEFAULT, ABIProto) || !DefineABIConstant(cx, ctypesObj, "stdcall_abi", ABI_STDCALL, ABIProto) || + !DefineABIConstant(cx, ctypesObj, "thiscall_abi", ABI_THISCALL, ABIProto) || !DefineABIConstant(cx, ctypesObj, "winapi_abi", ABI_WINAPI, ABIProto)) return false; @@ -3917,6 +3918,8 @@ BuildTypeName(JSContext* cx, JSObject* typeObj_) ABICode abi = GetABICode(fninfo->mABI); if (abi == ABI_STDCALL) PrependString(result, "__stdcall"); + else if (abi == ABI_THISCALL) + PrependString(result, "__thiscall"); else if (abi == ABI_WINAPI) PrependString(result, "WINAPI"); @@ -4022,6 +4025,9 @@ BuildTypeSource(JSContext* cx, case ABI_STDCALL: AppendString(result, "ctypes.stdcall_abi, "); break; + case ABI_THISCALL: + AppendString(result, "ctypes.thiscall_abi, "); + break; case ABI_WINAPI: AppendString(result, "ctypes.winapi_abi, "); break; @@ -5012,6 +5018,9 @@ ABI::ToSource(JSContext* cx, unsigned argc, Value* vp) case ABI_STDCALL: result = JS_NewStringCopyZ(cx, "ctypes.stdcall_abi"); break; + case ABI_THISCALL: + result = JS_NewStringCopyZ(cx, "ctypes.thiscall_abi"); + break; case ABI_WINAPI: result = JS_NewStringCopyZ(cx, "ctypes.winapi_abi"); break; @@ -6547,6 +6556,16 @@ GetABI(JSContext* cx, Value abiType, ffi_abi* result) case ABI_DEFAULT: *result = FFI_DEFAULT_ABI; return true; + case ABI_THISCALL: +#if defined(_WIN64) + *result = FFI_WIN64; + return true; +#elif defined(_WIN32) + *result = FFI_THISCALL; + return true; +#else + break; +#endif case ABI_STDCALL: case ABI_WINAPI: #if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2) @@ -6692,6 +6711,7 @@ FunctionType::BuildSymbolName(JSString* name, switch (GetABICode(fninfo->mABI)) { case ABI_DEFAULT: + case ABI_THISCALL: case ABI_WINAPI: // For cdecl or WINAPI functions, no mangling is necessary. AppendString(result, name); diff --git a/js/src/ctypes/CTypes.h b/js/src/ctypes/CTypes.h index 6e44fa6f0382..7289dcba0b17 100644 --- a/js/src/ctypes/CTypes.h +++ b/js/src/ctypes/CTypes.h @@ -211,6 +211,7 @@ enum ErrorNum { enum ABICode { ABI_DEFAULT, ABI_STDCALL, + ABI_THISCALL, ABI_WINAPI, INVALID_ABI }; diff --git a/toolkit/components/ctypes/tests/jsctypes-test.cpp b/toolkit/components/ctypes/tests/jsctypes-test.cpp index 0d5a5282f10b..91eee2420b79 100644 --- a/toolkit/components/ctypes/tests/jsctypes-test.cpp +++ b/toolkit/components/ctypes/tests/jsctypes-test.cpp @@ -384,3 +384,15 @@ test_vector_add_va_cdecl(uint8_t num_vecs, } myRECT data_rect = { -1, -2, 3, 4 }; + +TestClass::TestClass(int32_t a) +{ + mInt =a; +} + +int32_t +TestClass::Add(int32_t aOther) +{ + mInt += aOther; + return mInt; +} diff --git a/toolkit/components/ctypes/tests/jsctypes-test.h b/toolkit/components/ctypes/tests/jsctypes-test.h index 5fec2238ef45..14eb8c9152d4 100644 --- a/toolkit/components/ctypes/tests/jsctypes-test.h +++ b/toolkit/components/ctypes/tests/jsctypes-test.h @@ -185,4 +185,13 @@ MOZ_BEGIN_EXTERN_C MOZ_END_EXTERN_C +class MOZ_EXPORT TestClass final { +public: + explicit TestClass(int32_t); + int32_t Add(int32_t); + +private: + int32_t mInt; +}; + #endif diff --git a/toolkit/components/ctypes/tests/unit/test_jsctypes.js b/toolkit/components/ctypes/tests/unit/test_jsctypes.js index 0a564dfa9221..57d54a8eebef 100644 --- a/toolkit/components/ctypes/tests/unit/test_jsctypes.js +++ b/toolkit/components/ctypes/tests/unit/test_jsctypes.js @@ -182,6 +182,7 @@ function run_test() run_closure_tests(library); run_variadic_tests(library); run_static_data_tests(library); + run_cpp_class_tests(library); // test library.close let test_void_t = library.declare("test_void_t_cdecl", ctypes.default_abi, ctypes.void_t); @@ -2791,6 +2792,42 @@ function run_static_data_tests(library) do_check_eq(ptrValue(data_rect.address()), ptrValue(data_rect_2.address())); } +function run_cpp_class_tests(library) +{ + // try the gcc mangling, unless we're using MSVC. + let OS = get_os(); + let ctor_symbol; + let add_symbol; + let abi; + if (OS == "WINNT") { + // for compatibility for Win32 vs Win64 + abi = ctypes.thiscall_abi; + if (ctypes.size_t.size == 8) { + ctor_symbol = '??0TestClass@@QEAA@H@Z'; + add_symbol = '?Add@TestClass@@QEAAHH@Z'; + } else { + ctor_symbol = '??0TestClass@@QAE@H@Z'; + add_symbol = '?Add@TestClass@@QAEHH@Z'; + } + } else { + abi = ctypes.default_abi; + ctor_symbol = "_ZN9TestClassC1Ei"; + add_symbol = "_ZN9TestClass3AddEi"; + } + + let test_class_ctor = library.declare(ctor_symbol, abi, ctypes.void_t, + ctypes.int32_t.ptr, ctypes.int32_t); + let i = ctypes.int32_t(); + test_class_ctor(i.address(), 8); + do_check_eq(i.value, 8); + + let test_class_add = library.declare(add_symbol, abi, ctypes.int32_t, + ctypes.int32_t.ptr, ctypes.int32_t); + let j = test_class_add(i.address(), 5); + do_check_eq(j, 13); + do_check_eq(i.value, 13); +} + // bug 522360 - try loading system library without full path function run_load_system_library() {