Revise js-facing API for js-ctypes, patch v2. b=513788, r=jorendorff

This commit is contained in:
Dan Witte 2010-03-11 17:17:36 -08:00
Родитель e574d00485
Коммит 6f563a4504
13 изменённых файлов: 1289 добавлений и 714 удалений

Просмотреть файл

@ -2798,6 +2798,19 @@ AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_MSG_CHECKING(for ssize_t)
AC_CACHE_VAL(ac_cv_type_ssize_t,
[AC_TRY_COMPILE([#include <stdio.h>
#include <sys/types.h>],
[ssize_t foo = 0;],
[ac_cv_type_ssize_t=true],
[ac_cv_type_ssize_t=false])])
if test "$ac_cv_type_ssize_t" = true ; then
AC_DEFINE(HAVE_SSIZE_T)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AC_STRUCT_ST_BLKSIZE
AC_MSG_CHECKING(for siginfo_t)
AC_CACHE_VAL(ac_cv_siginfo_t,

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -57,7 +57,7 @@ enum ErrorNum {
const JSErrorFormatString*
GetErrorMessage(void* userRef, const char* locale, const uintN errorNumber);
bool TypeError(JSContext* cx, const char* expected, jsval actual);
JSBool TypeError(JSContext* cx, const char* expected, jsval actual);
/**
* ABI constants that specify the calling convention to use.
@ -84,16 +84,26 @@ ABICode GetABICode(JSContext* cx, JSObject* obj);
struct FieldInfo
{
nsCString mName;
nsString mName;
JSObject* mType;
size_t mOffset;
};
bool InitTypeClasses(JSContext* cx, JSObject* parent);
// Just like JSPropertySpec, but with a Unicode name.
struct PropertySpec
{
const jschar* name;
size_t namelen;
uint8 flags;
JSPropertyOp getter;
JSPropertyOp setter;
};
bool ConvertToJS(JSContext* cx, JSObject* typeObj, JSObject* dataObj, void* data, bool wantPrimitive, jsval* result);
bool ImplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer, bool isArgument, bool* freePointer);
bool ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer);
JSBool InitTypeClasses(JSContext* cx, JSObject* parent);
JSBool ConvertToJS(JSContext* cx, JSObject* typeObj, JSObject* dataObj, void* data, bool wantPrimitive, jsval* result);
JSBool ImplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer, bool isArgument, bool* freePointer);
JSBool ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer);
// Contents of the various slots on each JSClass. The slot indexes are given
// enumerated names for readability.
@ -112,11 +122,20 @@ enum CTypeProtoSlot {
};
enum CTypeSlot {
SLOT_TYPECODE = 0, // TypeCode of the CType object
SLOT_FFITYPE = 1, // ffi_type representing the type
SLOT_ALIGN = 2, // alignment of the data type, in bytes
SLOT_PTR = 3, // cached PointerType object for type.ptr
SLOT_FIELDINFO = 4, // (StructTypes only) FieldInfo array
SLOT_PROTO = 0, // 'prototype' property of the CType object
SLOT_TYPECODE = 1, // TypeCode of the CType object
SLOT_FFITYPE = 2, // ffi_type representing the type
SLOT_NAME = 3, // name of the type
SLOT_SIZE = 4, // size of the type, in bytes
SLOT_ALIGN = 5, // alignment of the type, in bytes
SLOT_PTR = 6, // cached PointerType object for type.ptr
// Note that some of the slots below can overlap, since they're for
// mutually exclusive types.
SLOT_TARGET_T = 7, // (PointerTypes only) 'targetType' property
SLOT_ELEMENT_T = 7, // (ArrayTypes only) 'elementType' property
SLOT_LENGTH = 8, // (ArrayTypes only) 'length' property
SLOT_FIELDS = 7, // (StructTypes only) 'fields' property
SLOT_FIELDINFO = 8, // (StructTypes only) FieldInfo array
CTYPE_SLOTS
};
@ -139,7 +158,7 @@ enum Int64FunctionSlot {
class CType {
public:
static JSObject* Create(JSContext* cx, JSObject* proto, JSString* name, TypeCode type, jsval size, jsval align, ffi_type* ffiType);
static JSObject* Create(JSContext* cx, JSObject* proto, TypeCode type, jsval name, jsval size, jsval align, ffi_type* ffiType, JSFunctionSpec* fs, PropertySpec* ps);
static JSObject* DefineBuiltin(JSContext* cx, JSObject* parent, const char* propName, JSObject* proto, const char* name, TypeCode type, jsval size, jsval align, ffi_type* ffiType);
static void Finalize(JSContext* cx, JSObject* obj);
@ -159,6 +178,9 @@ public:
static JSObject* GetProtoFromCtor(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
static JSObject* GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
static JSBool ProtoGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool NameGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool SizeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool PtrGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool Array(JSContext* cx, uintN argc, jsval* vp);
static JSBool ToString(JSContext* cx, uintN argc, jsval* vp);
@ -171,10 +193,10 @@ public:
static JSObject* CreateInternal(JSContext* cx, JSObject* ctor, JSObject* baseType, JSString* name);
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static JSObject* ConstructInternal(JSContext* cx, JSObject* typeObj, JSObject* parentObj, void* data);
static JSObject* GetBaseType(JSContext* cx, JSObject* obj);
static JSBool TargetGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool ContentsGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool ContentsSetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
};
@ -185,12 +207,13 @@ public:
static JSObject* CreateInternal(JSContext* cx, JSObject* baseType, size_t length, bool lengthDefined);
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static JSObject* ConstructInternal(JSContext* cx, JSObject* typeObj, JSObject* parentObj, void* data);
static JSObject* GetBaseType(JSContext* cx, JSObject* obj);
static size_t GetLength(JSContext* cx, JSObject* obj);
static bool GetSafeLength(JSContext* cx, JSObject* obj, size_t* result);
static JSBool ElementTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool LengthGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool Getter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool Setter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool AddressOfElement(JSContext* cx, uintN argc, jsval* vp);
@ -201,11 +224,11 @@ public:
static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static JSObject* ConstructInternal(JSContext* cx, JSObject* typeObj, JSObject* parentObj, void* data);
static nsTArray<FieldInfo>* GetFieldInfo(JSContext* cx, JSObject* obj);
static FieldInfo* LookupField(JSContext* cx, JSObject* obj, jsval idval);
static JSBool FieldsArrayGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool FieldGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool FieldSetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool AddressOfField(JSContext* cx, uintN argc, jsval* vp);

Просмотреть файл

@ -53,7 +53,7 @@ namespace ctypes {
static bool
GetABI(JSContext* cx, jsval aCallType, ffi_abi& aResult)
{
if (!JSVAL_IS_OBJECT(aCallType) || JSVAL_IS_NULL(aCallType))
if (JSVAL_IS_PRIMITIVE(aCallType))
return false;
ABICode abi = GetABICode(cx, JSVAL_TO_OBJECT(aCallType));
@ -76,11 +76,10 @@ GetABI(JSContext* cx, jsval aCallType, ffi_abi& aResult)
return false;
}
static bool
static JSBool
PrepareType(JSContext* aContext, jsval aType, Type& aResult)
{
if (!JSVAL_IS_OBJECT(aType) ||
JSVAL_IS_NULL(aType) ||
if (JSVAL_IS_PRIMITIVE(aType) ||
!CType::IsCType(aContext, JSVAL_TO_OBJECT(aType))) {
JS_ReportError(aContext, "not a ctypes type");
return false;
@ -94,10 +93,9 @@ PrepareType(JSContext* aContext, jsval aType, Type& aResult)
// ImplicitConvert will do the same, when passing an array as data.
JSObject* baseType = ArrayType::GetBaseType(aContext, typeObj);
typeObj = PointerType::CreateInternal(aContext, NULL, baseType, NULL);
if (!typeObj) {
JS_ReportError(aContext, "couldn't create pointer type from array");
if (!typeObj)
return false;
}
} else if (typeCode == TYPE_void_t) {
// disallow void argument types
JS_ReportError(aContext, "Cannot have void argument type");
@ -112,11 +110,10 @@ PrepareType(JSContext* aContext, jsval aType, Type& aResult)
return true;
}
static bool
static JSBool
PrepareResultType(JSContext* aContext, jsval aType, Type& aResult)
{
if (!JSVAL_IS_OBJECT(aType) ||
JSVAL_IS_NULL(aType) ||
if (JSVAL_IS_PRIMITIVE(aType) ||
!CType::IsCType(aContext, JSVAL_TO_OBJECT(aType))) {
JS_ReportError(aContext, "not a ctypes type");
return false;
@ -131,15 +128,6 @@ PrepareResultType(JSContext* aContext, jsval aType, Type& aResult)
return false;
}
#ifdef _MSC_VER
// Our libffi_msvc fork doesn't support returning structs by value yet.
if (typeCode == TYPE_struct) {
JS_ReportError(aContext,
"Returning structs by value is unsupported on Windows");
return false;
}
#endif
// libffi cannot pass types of zero size by value.
JS_ASSERT(typeCode == TYPE_void_t || CType::GetSize(aContext, typeObj) != 0);
@ -161,7 +149,7 @@ Function::~Function()
{
}
bool
JSBool
Function::Init(JSContext* aContext,
PRFuncPtr aFunc,
jsval aCallType,
@ -208,7 +196,7 @@ Function::Init(JSContext* aContext,
}
}
bool
JSBool
Function::Execute(JSContext* cx, PRUint32 argc, jsval* vp)
{
if (argc != mArgTypes.Length()) {
@ -290,8 +278,10 @@ Function::Create(JSContext* aContext,
{
// create new Function instance
nsAutoPtr<Function> self(new Function());
if (!self)
if (!self) {
JS_ReportOutOfMemory(aContext);
return NULL;
}
// deduce and check the ABI and parameter types
if (!self->Init(aContext, aFunc, aCallType, aResultType, aArgTypes, aArgLength))

Просмотреть файл

@ -66,7 +66,7 @@ struct AutoValue
~AutoValue()
{
delete static_cast<char*>(mData);
delete[] static_cast<char*>(mData);
}
bool SizeToType(JSContext* cx, JSObject* type)
@ -95,8 +95,8 @@ public:
~Function();
private:
bool Init(JSContext* aContext, PRFuncPtr aFunc, jsval aCallType, jsval aResultType, jsval* aArgTypes, uintN aArgLength);
bool Execute(JSContext* cx, PRUint32 argc, jsval* vp);
JSBool Init(JSContext* aContext, PRFuncPtr aFunc, jsval aCallType, jsval aResultType, jsval* aArgTypes, uintN aArgLength);
JSBool Execute(JSContext* cx, PRUint32 argc, jsval* vp);
protected:
PRFuncPtr mFunc;

Просмотреть файл

@ -118,23 +118,30 @@ Library::Create(JSContext* cx, jsval aPath)
libSpec.type = PR_LibSpec_Pathname;
#endif
library = PR_LoadLibraryWithFlags(libSpec, 0);
if (!library)
if (!library) {
JS_ReportError(cx, "couldn't open library");
return NULL;
}
} else if (JSVAL_IS_OBJECT(aPath)) {
} else if (!JSVAL_IS_PRIMITIVE(aPath)) {
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
nsISupports* file = xpc->GetNativeOfWrapper(cx, JSVAL_TO_OBJECT(aPath));
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file);
if (!localFile)
if (!localFile) {
JS_ReportError(cx, "open takes a string or nsIFile argument");
return NULL;
}
rv = localFile->Load(&library);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
JS_ReportError(cx, "couldn't open library");
return NULL;
}
} else {
// don't convert the argument
JS_ReportError(cx, "open takes a string or nsIFile argument");
return NULL;
}
@ -166,13 +173,13 @@ GetFunctionList(JSContext* cx, JSObject* obj)
return static_cast<Function*>(JSVAL_TO_PRIVATE(slot));
}
bool
JSBool
Library::AddFunction(JSContext* cx, JSObject* aLibrary, Function* aFunction)
{
// add the new Function instance to the head of the list
aFunction->Next() = GetFunctionList(cx, aLibrary);
return JS_SetReservedSlot(cx, aLibrary, SLOT_FUNCTIONLIST,
PRIVATE_TO_JSVAL(aFunction)) != JS_FALSE;
PRIVATE_TO_JSVAL(aFunction));
}
void
@ -213,10 +220,8 @@ Library::Open(JSContext* cx, uintN argc, jsval *vp)
}
JSObject* library = Create(cx, JS_ARGV(cx, vp)[0]);
if (!library) {
JS_ReportError(cx, "couldn't open library");
if (!library)
return JS_FALSE;
}
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(library));
return JS_TRUE;
@ -273,6 +278,9 @@ Library::Declare(JSContext* cx, uintN argc, jsval* vp)
}
const char* name = JS_GetStringBytesZ(cx, JSVAL_TO_STRING(argv[0]));
if (!name)
return JS_FALSE;
PRFuncPtr func = PR_FindFunctionSymbol(library, name);
if (!func) {
JS_ReportError(cx, "couldn't find function symbol in library");

Просмотреть файл

@ -61,7 +61,7 @@ public:
static void Finalize(JSContext* cx, JSObject* obj);
static PRLibrary* GetLibrary(JSContext* cx, JSObject* obj);
static bool AddFunction(JSContext* cx, JSObject* aLibrary, Function* aFunction);
static JSBool AddFunction(JSContext* cx, JSObject* aLibrary, Function* aFunction);
// JSFastNative functions
static JSBool Open(JSContext* cx, uintN argc, jsval* vp);

Просмотреть файл

@ -93,7 +93,7 @@ static JSFunctionSpec sModuleFunctions[] = {
JS_FS_END
};
bool
JSBool
Module::Init(JSContext* cx, JSObject* aGlobal)
{
// attach ctypes property to global object

Просмотреть файл

@ -53,7 +53,7 @@ public:
Module();
// Creates the ctypes object and attaches it to the global object.
bool Init(JSContext* aContext, JSObject* aGlobal);
JSBool Init(JSContext* aContext, JSObject* aGlobal);
private:
~Module();

Просмотреть файл

@ -228,3 +228,88 @@ test_struct_return(RECT r)
return p;
}
RECT
test_large_struct_return(RECT a, RECT b)
{
RECT r;
r.left = a.left; r.right = a.right;
r.top = b.top; r.bottom = b.bottom;
return r;
}
ONE_BYTE
test_1_byte_struct_return(RECT r)
{
ONE_BYTE s;
s.a = r.top;
return s;
}
TWO_BYTE
test_2_byte_struct_return(RECT r)
{
TWO_BYTE s;
s.a = r.top;
s.b = r.left;
return s;
}
THREE_BYTE
test_3_byte_struct_return(RECT r)
{
THREE_BYTE s;
s.a = r.top;
s.b = r.left;
s.c = r.bottom;
return s;
}
FOUR_BYTE
test_4_byte_struct_return(RECT r)
{
FOUR_BYTE s;
s.a = r.top;
s.b = r.left;
s.c = r.bottom;
s.d = r.right;
return s;
}
FIVE_BYTE
test_5_byte_struct_return(RECT r)
{
FIVE_BYTE s;
s.a = r.top;
s.b = r.left;
s.c = r.bottom;
s.d = r.right;
s.e = r.top;
return s;
}
SIX_BYTE
test_6_byte_struct_return(RECT r)
{
SIX_BYTE s;
s.a = r.top;
s.b = r.left;
s.c = r.bottom;
s.d = r.right;
s.e = r.top;
s.f = r.left;
return s;
}
SEVEN_BYTE
test_7_byte_struct_return(RECT r)
{
SEVEN_BYTE s;
s.a = r.top;
s.b = r.left;
s.c = r.bottom;
s.d = r.right;
s.e = r.top;
s.f = r.left;
s.g = r.bottom;
return s;
}

Просмотреть файл

@ -97,6 +97,55 @@ NS_EXTERN_C
NS_EXPORT const PRUnichar* test_wide_ret();
NS_EXPORT char* test_ansi_echo(const char*);
struct ONE_BYTE {
char a;
};
struct TWO_BYTE {
char a;
char b;
};
struct THREE_BYTE {
char a;
char b;
char c;
};
struct FOUR_BYTE {
char a;
char b;
char c;
char d;
};
struct FIVE_BYTE {
char a;
char b;
char c;
char d;
char e;
};
struct SIX_BYTE {
char a;
char b;
char c;
char d;
char e;
char f;
};
struct SEVEN_BYTE {
char a;
char b;
char c;
char d;
char e;
char f;
char g;
};
struct POINT {
PRInt32 x;
PRInt32 y;
@ -128,5 +177,13 @@ NS_EXTERN_C
NS_EXPORT PRInt32 test_nested_struct(NESTED);
NS_EXPORT POINT test_struct_return(RECT);
NS_EXPORT RECT test_large_struct_return(RECT, RECT);
NS_EXPORT ONE_BYTE test_1_byte_struct_return(RECT);
NS_EXPORT TWO_BYTE test_2_byte_struct_return(RECT);
NS_EXPORT THREE_BYTE test_3_byte_struct_return(RECT);
NS_EXPORT FOUR_BYTE test_4_byte_struct_return(RECT);
NS_EXPORT FIVE_BYTE test_5_byte_struct_return(RECT);
NS_EXPORT SIX_BYTE test_6_byte_struct_return(RECT);
NS_EXPORT SEVEN_BYTE test_7_byte_struct_return(RECT);
}

Просмотреть файл

@ -79,6 +79,15 @@ function run_test()
do_check_throws(function() { ctypes.CType(12); }, Error);
do_check_throws(function() { new ctypes.CType(12) }, Error);
// Check that the shared properties and functions on ctypes.CType.prototype throw.
do_check_throws(function() { ctypes.CType.prototype.name; }, Error);
do_check_throws(function() { ctypes.CType.prototype.size; }, Error);
do_check_throws(function() { ctypes.CType.prototype.ptr; }, Error);
do_check_throws(function() { ctypes.CType.prototype.prototype; }, Error);
do_check_throws(function() { ctypes.CType.prototype.array(); }, Error);
do_check_throws(function() { ctypes.CType.prototype.toString(); }, Error);
do_check_throws(function() { ctypes.CType.prototype.toSource(); }, Error);
// Test the basic bool, integer, and float types.
run_bool_tests(library);
@ -92,7 +101,7 @@ function run_test()
run_integer_tests(library, ctypes.unsigned_short, "unsigned_short", 2, false, [0, 0xffff]);
run_integer_tests(library, ctypes.int, "int", 4, true, [-0x80000000, 0x7fffffff]);
run_integer_tests(library, ctypes.unsigned_int, "unsigned_int", 4, false, [0, 0xffffffff]);
run_integer_tests(library, ctypes.unsigned, "unsigned", 4, false, [0, 0xffffffff]);
run_integer_tests(library, ctypes.unsigned, "unsigned_int", 4, false, [0, 0xffffffff]);
run_float_tests(library, ctypes.float32_t, "float32_t", 4);
run_float_tests(library, ctypes.float64_t, "float64_t", 8);
@ -155,7 +164,7 @@ function run_test()
run_char_tests(library, ctypes.char, "char", 1, true, [-0x80, 0x7f]);
run_char_tests(library, ctypes.signed_char, "signed_char", 1, true, [-0x80, 0x7f]);
run_char_tests(library, ctypes.unsigned_char, "unsigned_char", 1, false, [0, 0xff]);
run_char_tests(library, ctypes.jschar, "jschar", 2, false, [0, 0xffff]);
run_jschar_tests(library, ctypes.jschar, "jschar", [0, 0xffff]);
// Test the special types.
run_StructType_tests();
@ -225,24 +234,32 @@ function run_Int64_tests() {
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);
// Test Int64.toSource().
do_check_eq(i.toSource(), "ctypes.Int64(\"0\")");
do_check_throws(function() { i.toSource(10); }, Error);
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) + "\")");
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) + "\")");
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) + "\")");
// Test Int64(primitive double) constructor.
i = ctypes.Int64(-0);
@ -366,18 +383,25 @@ function run_UInt64_tests() {
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);
// Test UInt64.toSource().
do_check_eq(i.toSource(), "ctypes.UInt64(\"0\")");
do_check_throws(function() { i.toSource(10); }, Error);
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) + "\")");
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) + "\")");
// Test UInt64(primitive double) constructor.
i = ctypes.UInt64(-0);
@ -527,7 +551,7 @@ function check_struct_stats(library, t) {
let get_stats = library.declare("get_" + t.name + "_stats",
ctypes.default_abi, ctypes.void_t,
ctypes.size_t.ptr, ctypes.size_t.ptr, ctypes.size_t.ptr, ctypes.size_t.ptr,
ctypes.size_t.array().ptr);
ctypes.size_t.array());
let align = ctypes.size_t();
let size = ctypes.size_t();
@ -535,7 +559,7 @@ function check_struct_stats(library, t) {
let nsize = ctypes.size_t();
let offsets = ctypes.size_t.array(3)();
get_stats(align.address(), size.address(), nalign.address(), nsize.address(),
offsets.address());
offsets);
do_check_eq(size.value, s_t.size);
do_check_eq(align.value, s_t.size - t.size);
@ -569,6 +593,11 @@ function run_bool_tests(library) {
do_check_true(t.__proto__ === ctypes.CType.prototype);
do_check_true(t.prototype.constructor === t);
do_check_throws(function() { t.prototype.address(); }, Error);
do_check_throws(function() { t.prototype.readString(); }, Error);
do_check_throws(function() { t.prototype.toString(); }, Error);
do_check_throws(function() { t.prototype.toSource(); }, Error);
do_check_eq(t.toString(), "type " + name);
do_check_eq(t.toSource(), "ctypes." + name);
do_check_true(t.ptr === ctypes.PointerType(t));
@ -629,6 +658,11 @@ function run_integer_tests(library, t, name, size, signed, limits) {
do_check_true(t.__proto__ === ctypes.CType.prototype);
do_check_true(t.prototype.constructor === t);
do_check_throws(function() { t.prototype.address(); }, Error);
do_check_throws(function() { t.prototype.readString(); }, Error);
do_check_throws(function() { t.prototype.toString(); }, Error);
do_check_throws(function() { t.prototype.toSource(); }, Error);
do_check_eq(t.toString(), "type " + name);
do_check_eq(t.toSource(), "ctypes." + name);
do_check_true(t.ptr === ctypes.PointerType(t));
@ -717,6 +751,11 @@ function run_float_tests(library, t, name, size) {
do_check_true(t.__proto__ === ctypes.CType.prototype);
do_check_true(t.prototype.constructor === t);
do_check_throws(function() { t.prototype.address(); }, Error);
do_check_throws(function() { t.prototype.readString(); }, Error);
do_check_throws(function() { t.prototype.toString(); }, Error);
do_check_throws(function() { t.prototype.toSource(); }, Error);
do_check_eq(t.toString(), "type " + name);
do_check_eq(t.toSource(), "ctypes." + name);
do_check_true(t.ptr === ctypes.PointerType(t));
@ -738,12 +777,9 @@ function run_float_tests(library, t, name, size) {
d = new t(20);
do_check_eq(d.value, 20);
d.value = ctypes.Int64(5);
do_check_eq(d.value, 5);
d.value = ctypes.Int64(-5);
do_check_eq(d.value, -5);
d.value = ctypes.UInt64(5);
do_check_eq(d.value, 5);
do_check_throws(function() { d.value = ctypes.Int64(5); }, TypeError);
do_check_throws(function() { d.value = ctypes.Int64(-5); }, TypeError);
do_check_throws(function() { d.value = ctypes.UInt64(5); }, TypeError);
if (size == 4) {
d.value = 0x7fffff;
@ -760,9 +796,7 @@ function run_float_tests(library, t, name, size) {
d.value = 0xfffffffffffff000;
do_check_eq(d.value, 0xfffffffffffff000);
// allow values that can't be represented precisely as a double
d.value = ctypes.Int64("0x7fffffffffffffff");
do_check_eq(d.value, 0x7fffffffffffffff);
do_check_throws(function() { d.value = ctypes.Int64("0x7fffffffffffffff"); }, TypeError);
}
d.value = Infinity;
@ -823,6 +857,11 @@ function run_wrapped_integer_tests(library, t, name, size, signed, w, wname, lim
do_check_true(t.__proto__ === ctypes.CType.prototype);
do_check_true(t.prototype.constructor === t);
do_check_throws(function() { t.prototype.address(); }, Error);
do_check_throws(function() { t.prototype.readString(); }, Error);
do_check_throws(function() { t.prototype.toString(); }, Error);
do_check_throws(function() { t.prototype.toSource(); }, Error);
do_check_eq(t.toString(), "type " + name);
do_check_eq(t.toSource(), "ctypes." + name);
do_check_true(t.ptr === ctypes.PointerType(t));
@ -906,6 +945,11 @@ function run_char_tests(library, t, name, size, signed, limits) {
do_check_true(t.__proto__ === ctypes.CType.prototype);
do_check_true(t.prototype.constructor === t);
do_check_throws(function() { t.prototype.address(); }, Error);
do_check_throws(function() { t.prototype.readString(); }, Error);
do_check_throws(function() { t.prototype.toString(); }, Error);
do_check_throws(function() { t.prototype.toSource(); }, Error);
do_check_eq(t.toString(), "type " + name);
do_check_eq(t.toSource(), "ctypes." + name);
do_check_true(t.ptr === ctypes.PointerType(t));
@ -915,57 +959,45 @@ function run_char_tests(library, t, name, size, signed, limits) {
let d = t();
do_check_true(d.__proto__ === t.prototype);
do_check_true(d.constructor === t);
do_check_eq(d.value.length, 1);
do_check_eq(d.value.charCodeAt(0), 0);
do_check_eq(d.value, 0);
d.value = 5;
do_check_eq(d.value.length, 1);
do_check_eq(d.value.charCodeAt(0), 5);
do_check_eq(d.value, 5);
d = t(10);
do_check_eq(d.value.charCodeAt(0), 10);
function toprimitive(a) {
let r = a.charCodeAt(0);
if (signed) {
if (t.size == 1)
return r > 0x7f ? r - 0x100 : r;
return r > 0x7fff ? r - 0x10000 : r;
}
return r;
}
do_check_eq(d.value, 10);
if (signed) {
d.value = -10;
do_check_eq(toprimitive(d.value), -10);
do_check_eq(d.value, -10);
} else {
do_check_throws(function() { d.value = -10; }, TypeError);
}
d = new t(20);
do_check_eq(d.value.charCodeAt(0), 20);
do_check_eq(d.value, 20);
function toprimitive(a) { return a; }
d.value = ctypes.Int64(5);
do_check_eq(d.value.charCodeAt(0), 5);
do_check_eq(d.value, 5);
if (signed) {
d.value = ctypes.Int64(-10);
do_check_eq(toprimitive(d.value), -10);
do_check_eq(d.value, -10);
}
d.value = ctypes.UInt64(5);
do_check_eq(d.value.charCodeAt(0), 5);
do_check_eq(d.value, 5);
d.value = limits[0];
do_check_eq(toprimitive(d.value), limits[0]);
do_check_eq(d.value, limits[0]);
d.value = limits[1];
do_check_eq(d.value.charCodeAt(0), limits[1]);
do_check_eq(d.value, limits[1]);
d.value = 0;
do_check_eq(d.value.charCodeAt(0), 0);
do_check_eq(d.value, 0);
d.value = -0;
do_check_eq(1/d.value.charCodeAt(0), 1/0);
do_check_eq(1/d.value, 1/0);
d.value = false;
do_check_eq(d.value.charCodeAt(0), 0);
do_check_eq(d.value, 0);
d.value = true;
do_check_eq(d.value.charCodeAt(0), 1);
do_check_eq(d.value, 1);
d.value = "\0";
do_check_eq(d.value.charCodeAt(0), 0);
d.value = "a";
do_check_eq(d.value, "a");
do_check_throws(function() { d.value = "5"; }, TypeError);
// don't convert anything else
let vals = [limits[0] - 1, limits[1] + 1, Infinity, -Infinity, NaN, 0.1,
@ -976,8 +1008,8 @@ function run_char_tests(library, t, name, size, signed, limits) {
do_check_throws(function () { d.value = vals[i]; }, TypeError);
do_check_true(d.address().constructor === t.ptr);
do_check_eq(d.address().contents, "a");
do_check_eq(d.toSource(), "ctypes." + name + "(" + d.value.charCodeAt(0) + ")");
do_check_eq(d.address().contents, 1);
do_check_eq(d.toSource(), "ctypes." + name + "(" + d.value + ")");
do_check_eq(d.toSource(), d.toString());
// Test string autoconversion (and lack thereof).
@ -1009,9 +1041,146 @@ function run_char_tests(library, t, name, size, signed, limits) {
18 ] ]);
}
function run_jschar_tests(library, t, name, limits) {
do_check_eq(t.name, name);
do_check_eq(t.size, 2);
do_check_true(t instanceof ctypes.CType);
do_check_true(t.constructor === ctypes.CType);
do_check_true(t.__proto__ === ctypes.CType.prototype);
do_check_true(t.prototype.constructor === t);
do_check_throws(function() { t.prototype.address(); }, Error);
do_check_throws(function() { t.prototype.readString(); }, Error);
do_check_throws(function() { t.prototype.toString(); }, Error);
do_check_throws(function() { t.prototype.toSource(); }, Error);
do_check_eq(t.toString(), "type " + name);
do_check_eq(t.toSource(), "ctypes." + name);
do_check_true(t.ptr === ctypes.PointerType(t));
do_check_eq(t.array().name, name + "[]");
do_check_eq(t.array(5).name, name + "[5]");
function toprimitive(a) { return a.charCodeAt(0); }
let d = t();
do_check_true(d.__proto__ === t.prototype);
do_check_true(d.constructor === t);
do_check_eq(d.value.length, 1);
do_check_eq(toprimitive(d.value), 0);
d.value = 5;
do_check_eq(d.value.length, 1);
do_check_eq(toprimitive(d.value), 5);
d = t(10);
do_check_eq(toprimitive(d.value), 10);
do_check_throws(function() { d.value = -10; }, TypeError);
d = new t(20);
do_check_eq(toprimitive(d.value), 20);
d.value = ctypes.Int64(5);
do_check_eq(d.value.charCodeAt(0), 5);
do_check_throws(function() { d.value = ctypes.Int64(-10); }, TypeError);
d.value = ctypes.UInt64(5);
do_check_eq(d.value.charCodeAt(0), 5);
d.value = limits[0];
do_check_eq(toprimitive(d.value), limits[0]);
d.value = limits[1];
do_check_eq(toprimitive(d.value), limits[1]);
d.value = 0;
do_check_eq(toprimitive(d.value), 0);
d.value = -0;
do_check_eq(1/toprimitive(d.value), 1/0);
d.value = false;
do_check_eq(toprimitive(d.value), 0);
d.value = true;
do_check_eq(toprimitive(d.value), 1);
d.value = "\0";
do_check_eq(toprimitive(d.value), 0);
d.value = "a";
do_check_eq(d.value, "a");
// don't convert anything else
let vals = [limits[0] - 1, limits[1] + 1, Infinity, -Infinity, NaN, 0.1,
null, undefined, "", "aa", {}, [], new Number(16),
{toString: function () { return 7; }},
{valueOf: function () { return 7; }}];
for (let i = 0; i < vals.length; i++)
do_check_throws(function () { d.value = vals[i]; }, TypeError);
do_check_true(d.address().constructor === t.ptr);
do_check_eq(d.address().contents, "a");
do_check_eq(d.toSource(), "ctypes." + name + "(" + toprimitive(d.value) + ")");
do_check_eq(d.toSource(), d.toString());
// Test string autoconversion (and lack thereof).
let literal = "autoconverted";
let s = t.array()(literal);
do_check_eq(s.readString(), literal);
do_check_eq(s.constructor.length, literal.length + 1);
s = t.array(50)(literal);
do_check_eq(s.readString(), literal);
do_check_throws(function() { t.array(3)(literal); }, Error);
do_check_throws(function() { t.ptr(literal); }, TypeError);
let p = t.ptr(s);
do_check_eq(p.readString(), literal);
// Test the function call ABI for calls involving the type,
// and check the alignment of the type against what C says.
run_basic_abi_tests(library, t, name, toprimitive,
109,
[ 0, limits[0], limits[1] ],
[ [ 0, 0, 0 ], [ 0, 1, 1 ], [ 1, 0, 1 ], [ 1, 1, 2 ],
[ limits[0], 1, limits[0] + 1 ],
[ limits[1], 1, limits[0] ] ],
[ [ 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
18 ] ]);
}
function extreme_size()
{
// Return something larger than the largest representable size value,
// depending on platform. (Sizes must fit in both size_t and jsdouble.)
return ctypes.size_t.size == 4 ?
0x800000000 :
ctypes.UInt64("0xffffffffffffffff")
}
function run_StructType_tests() {
do_check_throws(function() { ctypes.StructType(); }, Error);
do_check_throws(function() { ctypes.StructType("a"); }, Error);
do_check_throws(function() { ctypes.StructType("a", [], 5); }, Error);
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() {
ctypes.StructType("a", [5]);
}, Error);
do_check_throws(function() {
ctypes.StructType("a", [{}]);
}, Error);
do_check_throws(function() {
ctypes.StructType("a", [{5:ctypes.int32_t}]);
}, Error);
do_check_throws(function() {
ctypes.StructType("a", [{"5":ctypes.int32_t}]);
}, Error);
do_check_throws(function() {
ctypes.StructType("a", [{"x":5}]);
}, Error);
do_check_throws(function() {
ctypes.StructType("a", [{"x":ctypes.int32_t()}]);
}, Error);
// StructType size, alignment, and offset calculations have already been
// checked for each basic type. We do not need to check them again.
@ -1025,6 +1194,13 @@ function run_StructType_tests() {
do_check_true(g_t.__proto__ === ctypes.StructType.prototype);
do_check_true(g_t.prototype.constructor === g_t);
do_check_throws(function() { g_t.prototype.address(); }, Error);
do_check_throws(function() { g_t.prototype.readString(); }, Error);
do_check_throws(function() { g_t.prototype.toString(); }, Error);
do_check_throws(function() { g_t.prototype.toSource(); }, Error);
do_check_throws(function() { ctypes.StructType.prototype.fields; }, Error);
do_check_throws(function() { g_t.prototype.addressOfField(); }, Error);
do_check_eq(g_t.toString(), "type " + name);
do_check_eq(g_t.toSource(),
"ctypes.StructType(\"g_t\", [{ \"a\": ctypes.int32_t }, { \"b\": ctypes.double }])");
@ -1058,18 +1234,26 @@ function run_StructType_tests() {
do_check_eq(g.a, 1);
do_check_eq(g.b, 2);
do_check_throws(function() { g_t(1); }, Error);
do_check_throws(function() { g_t(1, 2, 3); }, Error);
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);
let s = new s_t(4, g, 10);
let s = new s_t(3, g, 10);
do_check_eq(s.a, 3);
s.a = 4;
do_check_eq(s.a, 4);
do_check_eq(s.b.a, 1);
do_check_eq(s.b.b, 2);
do_check_eq(s.c, 10);
let g2 = s.b;
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");
@ -1079,20 +1263,26 @@ function run_StructType_tests() {
do_check_throws(function() { s.addressOfField("d"); }, Error);
do_check_throws(function() { s.addressOfField("a", 2); }, Error);
do_check_eq(s.toSource(), "s_t(4, { \"a\": 7, \"b\": 2 }, 10)");
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 constructed through ImplicitConvert.
// Test that structs can be set from an object using 'value'.
do_check_throws(function() { s.value; }, Error);
s.value = { "a": 2, "b": { "a": 9, "b": 5 }, "c": 13 };
let s_init = { "a": 2, "b": { "a": 9, "b": 5 }, "c": 13 };
s.value = s_init;
do_check_eq(s.b.a, 9);
do_check_eq(s.c, 13);
do_check_throws(function() { s.value = 5; }, Error);
do_check_throws(function() { s.value = ctypes.int32_t(); }, Error);
do_check_throws(function() { s.value = {}; }, Error);
do_check_throws(function() { s.value = { "a": 2 }; }, Error);
do_check_throws(function() { s.value = { "a": 2, "b": 5, "c": 10 }; }, Error);
do_check_throws(function() {
s.value = { "5": 2, "b": { "a": 9, "b": 5 }, "c": 13 };
}, Error);
do_check_throws(function() {
s.value = { "a": 2, "b": { "a": 9, "b": 5 }, "c": 13, "d": 17 };
}, Error);
@ -1100,6 +1290,28 @@ function run_StructType_tests() {
s.value = { "a": 2, "b": { "a": 9, "b": 5, "e": 9 }, "c": 13 };
}, Error);
// Test that structs can be constructed similarly through ExplicitConvert,
// and that the single-field case is disambiguated correctly.
s = s_t(s_init);
do_check_eq(s.b.a, 9);
do_check_eq(s.c, 13);
let v_t = ctypes.StructType("v_t", [{ "x": ctypes.int32_t }]);
let v = v_t({ "x": 5 });
do_check_eq(v.x, 5);
v = v_t(8);
do_check_eq(v.x, 8);
let w_t = ctypes.StructType("w_t", [{ "y": v_t }]);
do_check_throws(function() { w_t(9); }, Error);
let w = w_t({ "x": 3 });
do_check_eq(w.y.x, 3);
w = w_t({ "y": { "x": 19 } });
do_check_eq(w.y.x, 19);
let u_t = ctypes.StructType("u_t", [{ "z": ctypes.ArrayType(ctypes.int32_t, 3) }]);
let u = u_t([1, 2, 3]);
do_check_eq(u.z[1], 2);
u = u_t({ "z": [4, 5, 6] });
do_check_eq(u.z[1], 5);
// Check that the empty struct has size 1.
let z_t = ctypes.StructType("z_t", []);
do_check_eq(z_t.size, 1);
@ -1125,6 +1337,9 @@ function ptrValue(p) {
function run_PointerType_tests() {
do_check_throws(function() { ctypes.PointerType(); }, Error);
do_check_throws(function() { ctypes.PointerType(ctypes.int32_t, 5); }, Error);
do_check_throws(function() { ctypes.PointerType(null); }, Error);
do_check_throws(function() { ctypes.PointerType(ctypes.int32_t()); }, Error);
let name = "g_t";
let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
@ -1142,6 +1357,14 @@ function run_PointerType_tests() {
do_check_true(p_t.__proto__ === ctypes.PointerType.prototype);
do_check_true(p_t.prototype.constructor === p_t);
do_check_throws(function() { p_t.prototype.address(); }, Error);
do_check_throws(function() { p_t.prototype.readString(); }, Error);
do_check_throws(function() { p_t.prototype.toString(); }, Error);
do_check_throws(function() { p_t.prototype.toSource(); }, Error);
do_check_throws(function() { ctypes.PointerType.prototype.targetType; }, Error);
do_check_throws(function() { p_t.prototype.contents; }, Error);
do_check_throws(function() { p_t.prototype.contents = g.address(); }, Error);
do_check_eq(p_t.toString(), "type " + name + "*");
do_check_eq(p_t.toSource(),
"ctypes.StructType(\"g_t\", [{ \"a\": ctypes.int32_t }, { \"b\": ctypes.double }]).ptr");
@ -1154,6 +1377,7 @@ function run_PointerType_tests() {
do_check_throws(function() { p.value; }, Error);
do_check_eq(ptrValue(p), 0);
do_check_throws(function() { p.contents; }, Error);
do_check_throws(function() { p.contents = g; }, Error);
p = p_t(5);
do_check_eq(ptrValue(p), 5);
p = p_t(ctypes.UInt64(10));
@ -1169,6 +1393,9 @@ function run_PointerType_tests() {
do_check_eq(f_t.name, "FILE*");
let f = new f_t();
do_check_throws(function() { f.contents; }, Error);
do_check_throws(function() { f.contents = 0; }, Error);
let f = f_t(5);
do_check_throws(function() { f.contents = 0; }, Error);
do_check_throws(function() { f_t(p); }, Error);
do_check_throws(function() { f.value = p; }, Error);
@ -1184,6 +1411,8 @@ function run_PointerType_tests() {
let i = ctypes.int32_t(9);
p = i.address();
do_check_eq(p.contents, i.value);
p.contents = ctypes.int32_t(12);
do_check_eq(i.value, 12);
// Check that pointers to arrays of undefined or zero length are legal,
// but that the former cannot be dereferenced.
@ -1198,6 +1427,14 @@ function run_PointerType_tests() {
function run_ArrayType_tests() {
do_check_throws(function() { ctypes.ArrayType(); }, Error);
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); }, Error);
// Check that array size overflows are caught.
do_check_throws(function() {
ctypes.ArrayType(ctypes.int8_t, extreme_size());
}, Error);
let name = "g_t";
let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
@ -1215,6 +1452,15 @@ function run_ArrayType_tests() {
do_check_true(a_t.__proto__ === ctypes.ArrayType.prototype);
do_check_true(a_t.prototype.constructor === a_t);
do_check_throws(function() { a_t.prototype.address(); }, Error);
do_check_throws(function() { a_t.prototype.readString(); }, Error);
do_check_throws(function() { a_t.prototype.toString(); }, Error);
do_check_throws(function() { a_t.prototype.toSource(); }, Error);
do_check_throws(function() { ctypes.ArrayType.prototype.elementType; }, Error);
do_check_throws(function() { ctypes.ArrayType.prototype.length; }, Error);
do_check_throws(function() { a_t.prototype.addressOfElement(); }, Error);
do_check_throws(function() { a_t.prototype.length; }, Error);
do_check_eq(a_t.toString(), "type " + name + "[10]");
do_check_eq(a_t.toSource(),
"ctypes.StructType(\"g_t\", [{ \"a\": ctypes.int32_t }, { \"b\": ctypes.double }]).array(10)");
@ -1282,7 +1528,7 @@ function run_ArrayType_tests() {
let c_t = ctypes.int32_t.array(6);
let c = c_t();
c.value = [1, 2, 3, 4, 5, 6];
do_check_eq(c.toSource(), "ctypes.int32_t.array(6)([ 1, 2, 3, 4, 5, 6 ])");
do_check_eq(c.toSource(), "ctypes.int32_t.array(6)([1, 2, 3, 4, 5, 6])");
do_check_eq(c.toSource(), c.toString());
eval("let c2 = " + c.toSource());
do_check_eq(c2.constructor.name, "int32_t[6]");
@ -1410,19 +1656,23 @@ function run_struct_tests(library) {
// add up all the numbers and make sure the C function agrees
do_check_eq(test_nested_struct(nested), 26284238);
#ifdef XP_WIN
// Returning structs by value doesn't yet work on MSVC/Win32.
// Make sure it throws.
do_check_throws(function() {
library.declare("test_struct_return", ctypes.default_abi, point_t, rect_t);
}, Error);
#else
// test returning a struct by value
let test_struct_return = library.declare("test_struct_return", ctypes.default_abi, point_t, rect_t);
let ret = test_struct_return(rect);
do_check_eq(ret.x, rect.left);
do_check_eq(ret.y, rect.top);
#endif
// struct parameter ABI depends on size; test returning a large struct by value
test_struct_return = library.declare("test_large_struct_return", ctypes.default_abi, rect_t, rect_t, rect_t);
ret = test_struct_return(rect_t(1, 2, 3, 4), rect_t(5, 6, 7, 8));
do_check_eq(ret.left, 2);
do_check_eq(ret.right, 4);
do_check_eq(ret.top, 5);
do_check_eq(ret.bottom, 7);
// ... and tests structs < 8 bytes in size
for (let i = 1; i < 8; ++i)
run_small_struct_test(library, rect_t, i);
// test passing a struct by pointer
let test_init_pt = library.declare("test_init_pt", ctypes.default_abi, ctypes.void_t, point_t.ptr, ctypes.int32_t, ctypes.int32_t);
@ -1431,6 +1681,28 @@ function run_struct_tests(library) {
do_check_eq(pt1.y, 10);
}
function run_small_struct_test(library, rect_t, bytes)
{
let fields = [];
for (let i = 0; i < bytes; ++i) {
let field = {};
field["f" + i] = ctypes.uint8_t;
fields.push(field);
}
const small_t = new ctypes.StructType("SMALL", fields);
let test_small_struct_return = library.declare("test_" + bytes + "_byte_struct_return", ctypes.default_abi, small_t, rect_t);
let ret = test_small_struct_return(rect_t(1, 7, 13, 45));
let exp = [1, 7, 13, 45];
let j = 0;
for (let i = 0; i < bytes; ++i) {
do_check_eq(ret["f" + i], exp[j]);
if (++j == 4)
j = 0;
}
}
// bug 522360 - try loading system library without full path
function run_load_system_library()
{

Просмотреть файл

@ -36,10 +36,25 @@
*
* ***** END LICENSE BLOCK ***** */
/**
* This header contains the builtin types available for arguments and return
* values, representing their C counterparts. They are listed inside macros
* that the #includer is expected to #define. Format is:
*
* DEFINE_X_TYPE(typename, ctype, ffitype)
*
* where 'typename' is the name of the type constructor (accessible as
* ctypes.typename), 'ctype' is the corresponding C type declaration (from
* which sizeof(ctype) and templated type conversions will be derived), and
* 'ffitype' is the ffi_type to use. (Special types, such as 'void' and the
* pointer, array, and struct types are handled separately.)
*/
// If we're not breaking the types out, combine them together under one
// DEFINE_TYPE macro. Otherwise, turn off whichever ones we're not using.
#if defined(DEFINE_TYPE)
# define DEFINE_CHAR_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_JSCHAR_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_BOOL_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_INT_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
@ -51,6 +66,9 @@
# ifndef DEFINE_CHAR_TYPE
# define DEFINE_CHAR_TYPE(x, y, z)
# endif
# ifndef DEFINE_JSCHAR_TYPE
# define DEFINE_JSCHAR_TYPE(x, y, z)
# endif
# ifndef DEFINE_INT_TYPE
# define DEFINE_INT_TYPE(x, y, z)
# endif
@ -63,7 +81,7 @@
#endif
// MSVC doesn't have ssize_t. Help it along a little.
#ifndef _MSC_VER
#ifdef HAVE_SSIZE_T
#define CTYPES_SSIZE_T ssize_t
#else
#define CTYPES_SSIZE_T intptr_t
@ -71,7 +89,9 @@
// Some #defines to make handling of types whose length varies by platform
// easier. These could be implemented as configure tests, but the expressions
// are all statically resolvable so there's no need.
// are all statically resolvable so there's no need. (See CTypes.cpp for the
// appropriate PR_STATIC_ASSERTs; they can't go here since this header is
// used in places where such asserts are illegal.)
#define CTYPES_FFI_BOOL (sizeof(bool) == 1 ? ffi_type_uint8 : ffi_type_uint32)
#define CTYPES_FFI_LONG (sizeof(long) == 4 ? ffi_type_sint32 : ffi_type_sint64)
#define CTYPES_FFI_ULONG (sizeof(long) == 4 ? ffi_type_uint32 : ffi_type_uint64)
@ -80,18 +100,7 @@
#define CTYPES_FFI_INTPTR_T (sizeof(uintptr_t) == 4 ? ffi_type_sint32 : ffi_type_sint64)
#define CTYPES_FFI_UINTPTR_T (sizeof(uintptr_t) == 4 ? ffi_type_uint32 : ffi_type_uint64)
/**
* Builtin types available for arguments and return values, representing
* their C counterparts. Format is:
*
* DEFINE_X_TYPE(typename, ctype, ffitype)
*
* where 'typename' is the name of the type constructor (accessible as
* ctypes.typename), 'ctype' is the corresponding C type declaration (from
* which sizeof(ctype) and templated type conversions will be derived), and
* 'ffitype' is the ffi_type to use. (Special types, such as 'void' and the
* pointer, array, and struct types are handled separately.)
*/
// The meat.
DEFINE_BOOL_TYPE (bool, bool, CTYPES_FFI_BOOL)
DEFINE_INT_TYPE (int8_t, PRInt8, ffi_type_sint8)
DEFINE_INT_TYPE (int16_t, PRInt16, ffi_type_sint16)
@ -103,7 +112,6 @@ DEFINE_INT_TYPE (short, short, ffi_type_sint16)
DEFINE_INT_TYPE (unsigned_short, unsigned short, ffi_type_uint16)
DEFINE_INT_TYPE (int, int, ffi_type_sint32)
DEFINE_INT_TYPE (unsigned_int, unsigned int, ffi_type_uint32)
DEFINE_INT_TYPE (unsigned, unsigned, ffi_type_uint32)
DEFINE_WRAPPED_INT_TYPE(int64_t, PRInt64, ffi_type_sint64)
DEFINE_WRAPPED_INT_TYPE(uint64_t, PRUint64, ffi_type_uint64)
DEFINE_WRAPPED_INT_TYPE(long, long, CTYPES_FFI_LONG)
@ -121,7 +129,7 @@ DEFINE_FLOAT_TYPE (double, double, ffi_type_double)
DEFINE_CHAR_TYPE (char, char, ffi_type_uint8)
DEFINE_CHAR_TYPE (signed_char, signed char, ffi_type_sint8)
DEFINE_CHAR_TYPE (unsigned_char, unsigned char, ffi_type_uint8)
DEFINE_CHAR_TYPE (jschar, jschar, ffi_type_uint16)
DEFINE_JSCHAR_TYPE (jschar, jschar, ffi_type_uint16)
#undef CTYPES_SSIZE_T
#undef CTYPES_FFI_BOOL
@ -134,6 +142,7 @@ DEFINE_CHAR_TYPE (jschar, jschar, ffi_type_uint16)
#undef DEFINE_TYPE
#undef DEFINE_CHAR_TYPE
#undef DEFINE_JSCHAR_TYPE
#undef DEFINE_BOOL_TYPE
#undef DEFINE_INT_TYPE
#undef DEFINE_WRAPPED_INT_TYPE