зеркало из https://github.com/mozilla/pjs.git
Revise js-facing API for js-ctypes, patch v2. b=513788, r=jorendorff
This commit is contained in:
Родитель
e574d00485
Коммит
6f563a4504
13
configure.in
13
configure.in
|
@ -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,
|
||||
|
|
1292
js/ctypes/CTypes.cpp
1292
js/ctypes/CTypes.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче