mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 560002 - Opaque struct and definition support in ctypes. Part 2: Remove opaque pointers. r=benjamn
This commit is contained in:
parent
91a57c32a3
commit
70dd2657d6
@ -905,7 +905,7 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
|
|||||||
if (!typeObj)
|
if (!typeObj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
typeObj = PointerType::CreateInternal(cx, NULL, typeObj, NULL);
|
typeObj = PointerType::CreateInternal(cx, typeObj);
|
||||||
if (!typeObj)
|
if (!typeObj)
|
||||||
return false;
|
return false;
|
||||||
if (!JS_DefineProperty(cx, parent, "voidptr_t", OBJECT_TO_JSVAL(typeObj),
|
if (!JS_DefineProperty(cx, parent, "voidptr_t", OBJECT_TO_JSVAL(typeObj),
|
||||||
@ -1703,20 +1703,18 @@ ImplicitConvert(JSContext* cx,
|
|||||||
}
|
}
|
||||||
#include "typedefs.h"
|
#include "typedefs.h"
|
||||||
case TYPE_pointer: {
|
case TYPE_pointer: {
|
||||||
JSObject* baseType = PointerType::GetBaseType(cx, targetType);
|
|
||||||
|
|
||||||
if (JSVAL_IS_NULL(val)) {
|
if (JSVAL_IS_NULL(val)) {
|
||||||
// Convert to a null pointer.
|
// Convert to a null pointer.
|
||||||
*static_cast<void**>(buffer) = NULL;
|
*static_cast<void**>(buffer) = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSObject* baseType = PointerType::GetBaseType(cx, targetType);
|
||||||
if (sourceData) {
|
if (sourceData) {
|
||||||
// First, determine if the targetType is ctypes.void_t.ptr.
|
// First, determine if the targetType is ctypes.void_t.ptr.
|
||||||
TypeCode sourceCode = CType::GetTypeCode(cx, sourceType);
|
TypeCode sourceCode = CType::GetTypeCode(cx, sourceType);
|
||||||
void* sourceBuffer = CData::GetData(cx, sourceData);
|
void* sourceBuffer = CData::GetData(cx, sourceData);
|
||||||
bool voidptrTarget = baseType &&
|
bool voidptrTarget = CType::GetTypeCode(cx, baseType) == TYPE_void_t;
|
||||||
CType::GetTypeCode(cx, baseType) == TYPE_void_t;
|
|
||||||
|
|
||||||
if (sourceCode == TYPE_pointer && voidptrTarget) {
|
if (sourceCode == TYPE_pointer && voidptrTarget) {
|
||||||
// Autoconvert if targetType is ctypes.voidptr_t.
|
// Autoconvert if targetType is ctypes.voidptr_t.
|
||||||
@ -1733,7 +1731,7 @@ ImplicitConvert(JSContext* cx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (isArgument && baseType && JSVAL_IS_STRING(val)) {
|
} else if (isArgument && JSVAL_IS_STRING(val)) {
|
||||||
// Convert the string for the ffi call. This requires allocating space
|
// Convert the string for the ffi call. This requires allocating space
|
||||||
// which the caller assumes ownership of.
|
// which the caller assumes ownership of.
|
||||||
// TODO: Extend this so we can safely convert strings at other times also.
|
// TODO: Extend this so we can safely convert strings at other times also.
|
||||||
@ -2037,23 +2035,15 @@ BuildTypeName(JSContext* cx, JSObject* typeObj)
|
|||||||
// pointers on the left and arrays on the right. An excellent description
|
// pointers on the left and arrays on the right. An excellent description
|
||||||
// of the rules for building C type declarations can be found at:
|
// of the rules for building C type declarations can be found at:
|
||||||
// http://unixwiz.net/techtips/reading-cdecl.html
|
// http://unixwiz.net/techtips/reading-cdecl.html
|
||||||
JSObject* currentType = typeObj;
|
TypeCode prevGrouping = CType::GetTypeCode(cx, typeObj), currentGrouping;
|
||||||
JSObject* nextType;
|
|
||||||
TypeCode prevGrouping = CType::GetTypeCode(cx, currentType), currentGrouping;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
currentGrouping = CType::GetTypeCode(cx, currentType);
|
currentGrouping = CType::GetTypeCode(cx, typeObj);
|
||||||
switch (currentGrouping) {
|
switch (currentGrouping) {
|
||||||
case TYPE_pointer: {
|
case TYPE_pointer: {
|
||||||
nextType = PointerType::GetBaseType(cx, currentType);
|
|
||||||
if (!nextType) {
|
|
||||||
// Opaque pointer type. Use the type's name as the base type.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pointer types go on the left.
|
// Pointer types go on the left.
|
||||||
PrependString(result, "*");
|
PrependString(result, "*");
|
||||||
|
|
||||||
currentType = nextType;
|
typeObj = PointerType::GetBaseType(cx, typeObj);
|
||||||
prevGrouping = currentGrouping;
|
prevGrouping = currentGrouping;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2067,17 +2057,17 @@ BuildTypeName(JSContext* cx, JSObject* typeObj)
|
|||||||
// Array types go on the right.
|
// Array types go on the right.
|
||||||
AppendString(result, "[");
|
AppendString(result, "[");
|
||||||
size_t length;
|
size_t length;
|
||||||
if (ArrayType::GetSafeLength(cx, currentType, &length))
|
if (ArrayType::GetSafeLength(cx, typeObj, &length))
|
||||||
IntegerToString(length, 10, result);
|
IntegerToString(length, 10, result);
|
||||||
|
|
||||||
AppendString(result, "]");
|
AppendString(result, "]");
|
||||||
|
|
||||||
currentType = ArrayType::GetBaseType(cx, currentType);
|
typeObj = ArrayType::GetBaseType(cx, typeObj);
|
||||||
prevGrouping = currentGrouping;
|
prevGrouping = currentGrouping;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case TYPE_function: {
|
case TYPE_function: {
|
||||||
FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, currentType);
|
FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, typeObj);
|
||||||
|
|
||||||
// Add in the calling convention, if it's not cdecl.
|
// Add in the calling convention, if it's not cdecl.
|
||||||
if (GetABICode(cx, fninfo->mABI) == ABI_STDCALL)
|
if (GetABICode(cx, fninfo->mABI) == ABI_STDCALL)
|
||||||
@ -2100,10 +2090,10 @@ BuildTypeName(JSContext* cx, JSObject* typeObj)
|
|||||||
AppendString(result, "...");
|
AppendString(result, "...");
|
||||||
AppendString(result, ")");
|
AppendString(result, ")");
|
||||||
|
|
||||||
// Set 'currentType' to the return type, and let the loop process it.
|
// Set 'typeObj' to the return type, and let the loop process it.
|
||||||
// 'prevGrouping' doesn't matter here, because functions cannot return
|
// 'prevGrouping' doesn't matter here, because functions cannot return
|
||||||
// arrays -- thus the parenthetical rules don't get tickled.
|
// arrays -- thus the parenthetical rules don't get tickled.
|
||||||
currentType = fninfo->mReturnType;
|
typeObj = fninfo->mReturnType;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -2114,7 +2104,7 @@ BuildTypeName(JSContext* cx, JSObject* typeObj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stick the base type and derived type parts together.
|
// Stick the base type and derived type parts together.
|
||||||
JSString* baseName = CType::GetName(cx, currentType);
|
JSString* baseName = CType::GetName(cx, typeObj);
|
||||||
PrependString(result, baseName);
|
PrependString(result, baseName);
|
||||||
return NewUCString(cx, result);
|
return NewUCString(cx, result);
|
||||||
}
|
}
|
||||||
@ -2146,14 +2136,6 @@ BuildTypeSource(JSContext* cx,
|
|||||||
}
|
}
|
||||||
case TYPE_pointer: {
|
case TYPE_pointer: {
|
||||||
JSObject* baseType = PointerType::GetBaseType(cx, typeObj);
|
JSObject* baseType = PointerType::GetBaseType(cx, typeObj);
|
||||||
if (!baseType) {
|
|
||||||
// Opaque pointer type. Use the type's name.
|
|
||||||
AppendString(result, "ctypes.PointerType(\"");
|
|
||||||
JSString* baseName = CType::GetName(cx, typeObj);
|
|
||||||
AppendString(result, baseName);
|
|
||||||
AppendString(result, "\")");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specialcase ctypes.voidptr_t.
|
// Specialcase ctypes.voidptr_t.
|
||||||
if (CType::GetTypeCode(cx, baseType) == TYPE_void_t) {
|
if (CType::GetTypeCode(cx, baseType) == TYPE_void_t) {
|
||||||
@ -2729,18 +2711,9 @@ CType::TypesEqual(JSContext* cx, JSObject* t1, JSObject* t2)
|
|||||||
// Determine whether the types require shallow or deep comparison.
|
// Determine whether the types require shallow or deep comparison.
|
||||||
switch (c1) {
|
switch (c1) {
|
||||||
case TYPE_pointer: {
|
case TYPE_pointer: {
|
||||||
|
// Compare base types.
|
||||||
JSObject* b1 = PointerType::GetBaseType(cx, t1);
|
JSObject* b1 = PointerType::GetBaseType(cx, t1);
|
||||||
JSObject* b2 = PointerType::GetBaseType(cx, t2);
|
JSObject* b2 = PointerType::GetBaseType(cx, t2);
|
||||||
|
|
||||||
if (!b1 || !b2) {
|
|
||||||
// One or both pointers are opaque.
|
|
||||||
// If both are opaque, compare names.
|
|
||||||
JSString* n1 = GetName(cx, t1);
|
|
||||||
JSString* n2 = GetName(cx, t2);
|
|
||||||
return b1 == b2 && JS_CompareStrings(n1, n2) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare base types.
|
|
||||||
return TypesEqual(cx, b1, b2);
|
return TypesEqual(cx, b1, b2);
|
||||||
}
|
}
|
||||||
case TYPE_function: {
|
case TYPE_function: {
|
||||||
@ -2957,7 +2930,7 @@ CType::PtrGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* pointerType = PointerType::CreateInternal(cx, NULL, obj, NULL);
|
JSObject* pointerType = PointerType::CreateInternal(cx, obj);
|
||||||
if (!pointerType)
|
if (!pointerType)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
@ -3081,23 +3054,12 @@ PointerType::Create(JSContext* cx, uintN argc, jsval* vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
jsval arg = JS_ARGV(cx, vp)[0];
|
jsval arg = JS_ARGV(cx, vp)[0];
|
||||||
JSObject* baseType = NULL;
|
if (JSVAL_IS_PRIMITIVE(arg) || !CType::IsCType(cx, JSVAL_TO_OBJECT(arg))) {
|
||||||
JSString* name = NULL;
|
JS_ReportError(cx, "first argument must be a CType");
|
||||||
if (!JSVAL_IS_PRIMITIVE(arg) &&
|
|
||||||
CType::IsCType(cx, JSVAL_TO_OBJECT(arg))) {
|
|
||||||
baseType = JSVAL_TO_OBJECT(arg);
|
|
||||||
|
|
||||||
} else if (JSVAL_IS_STRING(arg)) {
|
|
||||||
// Construct an opaque pointer type from a string.
|
|
||||||
name = JSVAL_TO_STRING(arg);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
JS_ReportError(cx, "first argument must be a CType or a string");
|
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
|
JSObject* result = CreateInternal(cx, JSVAL_TO_OBJECT(arg));
|
||||||
JSObject* result = CreateInternal(cx, callee, baseType, name);
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
@ -3106,37 +3068,24 @@ PointerType::Create(JSContext* cx, uintN argc, jsval* vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
PointerType::CreateInternal(JSContext* cx,
|
PointerType::CreateInternal(JSContext* cx, JSObject* baseType)
|
||||||
JSObject* ctor,
|
|
||||||
JSObject* baseType,
|
|
||||||
JSString* name)
|
|
||||||
{
|
{
|
||||||
JS_ASSERT(ctor || baseType);
|
|
||||||
JS_ASSERT((baseType && !name) || (!baseType && name));
|
|
||||||
|
|
||||||
if (baseType) {
|
|
||||||
// check if we have a cached PointerType on our base CType.
|
// check if we have a cached PointerType on our base CType.
|
||||||
jsval slot;
|
jsval slot;
|
||||||
ASSERT_OK(JS_GetReservedSlot(cx, baseType, SLOT_PTR, &slot));
|
ASSERT_OK(JS_GetReservedSlot(cx, baseType, SLOT_PTR, &slot));
|
||||||
if (!JSVAL_IS_VOID(slot))
|
if (!JSVAL_IS_VOID(slot))
|
||||||
return JSVAL_TO_OBJECT(slot);
|
return JSVAL_TO_OBJECT(slot);
|
||||||
}
|
|
||||||
|
|
||||||
// Get ctypes.PointerType.prototype and the common prototype for CData objects
|
// Get ctypes.PointerType.prototype and the common prototype for CData objects
|
||||||
// of this type, either from ctor or the baseType, whichever was provided.
|
// of this type.
|
||||||
JSObject* typeProto;
|
JSObject* typeProto;
|
||||||
JSObject* dataProto;
|
JSObject* dataProto;
|
||||||
if (ctor) {
|
|
||||||
typeProto = CType::GetProtoFromCtor(cx, ctor, SLOT_POINTERPROTO);
|
|
||||||
dataProto = CType::GetProtoFromCtor(cx, ctor, SLOT_POINTERDATAPROTO);
|
|
||||||
} else {
|
|
||||||
typeProto = CType::GetProtoFromType(cx, baseType, SLOT_POINTERPROTO);
|
typeProto = CType::GetProtoFromType(cx, baseType, SLOT_POINTERPROTO);
|
||||||
dataProto = CType::GetProtoFromType(cx, baseType, SLOT_POINTERDATAPROTO);
|
dataProto = CType::GetProtoFromType(cx, baseType, SLOT_POINTERDATAPROTO);
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new CType object with the common properties and slots.
|
// Create a new CType object with the common properties and slots.
|
||||||
JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_pointer,
|
JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_pointer,
|
||||||
name, INT_TO_JSVAL(sizeof(void*)),
|
NULL, INT_TO_JSVAL(sizeof(void*)),
|
||||||
INT_TO_JSVAL(ffi_type_pointer.alignment),
|
INT_TO_JSVAL(ffi_type_pointer.alignment),
|
||||||
&ffi_type_pointer);
|
&ffi_type_pointer);
|
||||||
if (!typeObj)
|
if (!typeObj)
|
||||||
@ -3147,8 +3096,7 @@ PointerType::CreateInternal(JSContext* cx,
|
|||||||
if (!JS_SetReservedSlot(cx, typeObj, SLOT_TARGET_T, OBJECT_TO_JSVAL(baseType)))
|
if (!JS_SetReservedSlot(cx, typeObj, SLOT_TARGET_T, OBJECT_TO_JSVAL(baseType)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (baseType) {
|
// Determine the name of the PointerType.
|
||||||
// Determine the name of the PointerType, since it wasn't supplied.
|
|
||||||
JSString* nameStr = BuildTypeName(cx, typeObj);
|
JSString* nameStr = BuildTypeName(cx, typeObj);
|
||||||
if (!nameStr ||
|
if (!nameStr ||
|
||||||
!JS_SetReservedSlot(cx, typeObj, SLOT_NAME, STRING_TO_JSVAL(nameStr)))
|
!JS_SetReservedSlot(cx, typeObj, SLOT_NAME, STRING_TO_JSVAL(nameStr)))
|
||||||
@ -3157,7 +3105,6 @@ PointerType::CreateInternal(JSContext* cx,
|
|||||||
// Finally, cache our newly-created PointerType on our pointed-to CType.
|
// Finally, cache our newly-created PointerType on our pointed-to CType.
|
||||||
if (!JS_SetReservedSlot(cx, baseType, SLOT_PTR, OBJECT_TO_JSVAL(typeObj)))
|
if (!JS_SetReservedSlot(cx, baseType, SLOT_PTR, OBJECT_TO_JSVAL(typeObj)))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
return typeObj;
|
return typeObj;
|
||||||
}
|
}
|
||||||
@ -3192,7 +3139,7 @@ PointerType::ConstructData(JSContext* cx,
|
|||||||
|
|
||||||
if (argc >= 1) {
|
if (argc >= 1) {
|
||||||
JSObject* baseObj = PointerType::GetBaseType(cx, obj);
|
JSObject* baseObj = PointerType::GetBaseType(cx, obj);
|
||||||
if (baseObj && CType::GetTypeCode(cx, baseObj) == TYPE_function &&
|
if (CType::GetTypeCode(cx, baseObj) == TYPE_function &&
|
||||||
JSVAL_IS_OBJECT(argv[0]) &&
|
JSVAL_IS_OBJECT(argv[0]) &&
|
||||||
JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[0]))) {
|
JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[0]))) {
|
||||||
// Construct a FunctionType.ptr from a JS function, and allow an
|
// Construct a FunctionType.ptr from a JS function, and allow an
|
||||||
@ -3227,6 +3174,7 @@ PointerType::GetBaseType(JSContext* cx, JSObject* obj)
|
|||||||
|
|
||||||
jsval type;
|
jsval type;
|
||||||
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_TARGET_T, &type));
|
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_TARGET_T, &type));
|
||||||
|
JS_ASSERT(!JSVAL_IS_NULL(type));
|
||||||
return JSVAL_TO_OBJECT(type);
|
return JSVAL_TO_OBJECT(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3289,11 +3237,6 @@ PointerType::ContentsGetter(JSContext* cx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSObject* baseType = GetBaseType(cx, typeObj);
|
JSObject* baseType = GetBaseType(cx, typeObj);
|
||||||
if (!baseType) {
|
|
||||||
JS_ReportError(cx, "cannot get contents of an opaque pointer type");
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CType::IsSizeDefined(cx, baseType)) {
|
if (!CType::IsSizeDefined(cx, baseType)) {
|
||||||
JS_ReportError(cx, "cannot get contents of undefined size");
|
JS_ReportError(cx, "cannot get contents of undefined size");
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
@ -3332,13 +3275,8 @@ PointerType::ContentsSetter(JSContext* cx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSObject* baseType = GetBaseType(cx, typeObj);
|
JSObject* baseType = GetBaseType(cx, typeObj);
|
||||||
if (!baseType) {
|
|
||||||
JS_ReportError(cx, "cannot set contents of an opaque pointer type");
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CType::IsSizeDefined(cx, baseType)) {
|
if (!CType::IsSizeDefined(cx, baseType)) {
|
||||||
JS_ReportError(cx, "cannot get contents of undefined size");
|
JS_ReportError(cx, "cannot set contents of undefined size");
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3586,6 +3524,7 @@ ArrayType::GetBaseType(JSContext* cx, JSObject* obj)
|
|||||||
|
|
||||||
jsval type;
|
jsval type;
|
||||||
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_ELEMENT_T, &type));
|
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_ELEMENT_T, &type));
|
||||||
|
JS_ASSERT(!JSVAL_IS_NULL(type));
|
||||||
return JSVAL_TO_OBJECT(type);
|
return JSVAL_TO_OBJECT(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3756,7 +3695,7 @@ ArrayType::AddressOfElement(JSContext* cx, uintN argc, jsval *vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSObject* baseType = GetBaseType(cx, typeObj);
|
JSObject* baseType = GetBaseType(cx, typeObj);
|
||||||
JSObject* pointerType = PointerType::CreateInternal(cx, NULL, baseType, NULL);
|
JSObject* pointerType = PointerType::CreateInternal(cx, baseType);
|
||||||
if (!pointerType)
|
if (!pointerType)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
js::AutoValueRooter root(cx, pointerType);
|
js::AutoValueRooter root(cx, pointerType);
|
||||||
@ -4332,7 +4271,7 @@ StructType::AddressOfField(JSContext* cx, uintN argc, jsval *vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
JSObject* baseType = field->mType;
|
JSObject* baseType = field->mType;
|
||||||
JSObject* pointerType = PointerType::CreateInternal(cx, NULL, baseType, NULL);
|
JSObject* pointerType = PointerType::CreateInternal(cx, baseType);
|
||||||
if (!pointerType)
|
if (!pointerType)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
js::AutoValueRooter root(cx, pointerType);
|
js::AutoValueRooter root(cx, pointerType);
|
||||||
@ -4418,7 +4357,7 @@ PrepareType(JSContext* cx, jsval type)
|
|||||||
// convert array argument types to pointers, just like C.
|
// convert array argument types to pointers, just like C.
|
||||||
// ImplicitConvert will do the same, when passing an array as data.
|
// ImplicitConvert will do the same, when passing an array as data.
|
||||||
JSObject* baseType = ArrayType::GetBaseType(cx, result);
|
JSObject* baseType = ArrayType::GetBaseType(cx, result);
|
||||||
result = PointerType::CreateInternal(cx, NULL, baseType, NULL);
|
result = PointerType::CreateInternal(cx, baseType);
|
||||||
if (!result)
|
if (!result)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -4762,9 +4701,13 @@ FunctionType::Call(JSContext* cx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSObject* typeObj = CData::GetCType(cx, obj);
|
JSObject* typeObj = CData::GetCType(cx, obj);
|
||||||
if (CType::GetTypeCode(cx, typeObj) != TYPE_pointer ||
|
if (CType::GetTypeCode(cx, typeObj) != TYPE_pointer) {
|
||||||
!(typeObj = PointerType::GetBaseType(cx, typeObj)) ||
|
JS_ReportError(cx, "not a FunctionType.ptr");
|
||||||
CType::GetTypeCode(cx, typeObj) != TYPE_function) {
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
typeObj = PointerType::GetBaseType(cx, typeObj);
|
||||||
|
if (CType::GetTypeCode(cx, typeObj) != TYPE_function) {
|
||||||
JS_ReportError(cx, "not a FunctionType.ptr");
|
JS_ReportError(cx, "not a FunctionType.ptr");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -5347,7 +5290,7 @@ CData::Address(JSContext* cx, uintN argc, jsval *vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSObject* typeObj = CData::GetCType(cx, obj);
|
JSObject* typeObj = CData::GetCType(cx, obj);
|
||||||
JSObject* pointerType = PointerType::CreateInternal(cx, NULL, typeObj, NULL);
|
JSObject* pointerType = PointerType::CreateInternal(cx, typeObj);
|
||||||
if (!pointerType)
|
if (!pointerType)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
js::AutoValueRooter root(cx, pointerType);
|
js::AutoValueRooter root(cx, pointerType);
|
||||||
@ -5434,11 +5377,6 @@ CData::ReadString(JSContext* cx, uintN argc, jsval *vp)
|
|||||||
switch (typeCode) {
|
switch (typeCode) {
|
||||||
case TYPE_pointer:
|
case TYPE_pointer:
|
||||||
baseType = PointerType::GetBaseType(cx, typeObj);
|
baseType = PointerType::GetBaseType(cx, typeObj);
|
||||||
if (!baseType) {
|
|
||||||
JS_ReportError(cx, "cannot read contents of pointer to opaque type");
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = *static_cast<void**>(GetData(cx, obj));
|
data = *static_cast<void**>(GetData(cx, obj));
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
JS_ReportError(cx, "cannot read contents of null pointer");
|
JS_ReportError(cx, "cannot read contents of null pointer");
|
||||||
|
@ -405,8 +405,7 @@ namespace CType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace PointerType {
|
namespace PointerType {
|
||||||
JSObject* CreateInternal(JSContext* cx, JSObject* ctor, JSObject* baseType,
|
JSObject* CreateInternal(JSContext* cx, JSObject* baseType);
|
||||||
JSString* name);
|
|
||||||
|
|
||||||
JSObject* GetBaseType(JSContext* cx, JSObject* obj);
|
JSObject* GetBaseType(JSContext* cx, JSObject* obj);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ Library::Declare(JSContext* cx, uintN argc, jsval* vp)
|
|||||||
root.setObject(typeObj);
|
root.setObject(typeObj);
|
||||||
|
|
||||||
// Make a function pointer type.
|
// Make a function pointer type.
|
||||||
typeObj = PointerType::CreateInternal(cx, NULL, typeObj, NULL);
|
typeObj = PointerType::CreateInternal(cx, typeObj);
|
||||||
if (!typeObj)
|
if (!typeObj)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
root.setObject(typeObj);
|
root.setObject(typeObj);
|
||||||
|
@ -1633,13 +1633,14 @@ function ptrValue(p) {
|
|||||||
|
|
||||||
function run_PointerType_tests() {
|
function run_PointerType_tests() {
|
||||||
run_type_ctor_class_tests(ctypes.PointerType,
|
run_type_ctor_class_tests(ctypes.PointerType,
|
||||||
ctypes.PointerType(ctypes.int32_t), ctypes.PointerType("FILE"),
|
ctypes.PointerType(ctypes.int32_t), ctypes.PointerType(ctypes.int64_t),
|
||||||
[ "targetType" ], [], [ "contents" ], [ "isNull" ], []);
|
[ "targetType" ], [], [ "contents" ], [ "isNull" ], []);
|
||||||
|
|
||||||
do_check_throws(function() { ctypes.PointerType(); }, Error);
|
do_check_throws(function() { ctypes.PointerType(); }, Error);
|
||||||
do_check_throws(function() { ctypes.PointerType(ctypes.int32_t, 5); }, 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(null); }, Error);
|
||||||
do_check_throws(function() { ctypes.PointerType(ctypes.int32_t()); }, Error);
|
do_check_throws(function() { ctypes.PointerType(ctypes.int32_t()); }, Error);
|
||||||
|
do_check_throws(function() { ctypes.PointerType("void"); }, Error);
|
||||||
|
|
||||||
let name = "g_t";
|
let name = "g_t";
|
||||||
let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
|
let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
|
||||||
@ -1675,15 +1676,15 @@ function run_PointerType_tests() {
|
|||||||
do_check_throws(function() { p.value = 5; }, Error);
|
do_check_throws(function() { p.value = 5; }, Error);
|
||||||
|
|
||||||
// Test opaque pointers.
|
// Test opaque pointers.
|
||||||
let f_t = ctypes.PointerType("FILE*");
|
let f_t = ctypes.StructType("FILE").ptr;
|
||||||
do_check_eq(f_t.name, "FILE*");
|
do_check_eq(f_t.name, "FILE*");
|
||||||
do_check_eq(f_t.toSource(), "ctypes.PointerType(\"FILE*\")");
|
do_check_eq(f_t.toSource(), 'ctypes.StructType("FILE").ptr');
|
||||||
let f = new f_t();
|
let f = new f_t();
|
||||||
do_check_throws(function() { f.contents; }, Error);
|
do_check_throws(function() { f.contents; }, Error);
|
||||||
do_check_throws(function() { f.contents = 0; }, Error);
|
do_check_throws(function() { f.contents = 0; }, Error);
|
||||||
let f = f_t(5);
|
let f = f_t(5);
|
||||||
do_check_throws(function() { f.contents = 0; }, Error);
|
do_check_throws(function() { f.contents = 0; }, Error);
|
||||||
do_check_eq(f.toSource(), "ctypes.PointerType(\"FILE*\")(ctypes.UInt64(\"0x5\"))");
|
do_check_eq(f.toSource(), 'FILE.ptr(ctypes.UInt64("0x5"))');
|
||||||
|
|
||||||
do_check_throws(function() { f_t(p); }, Error);
|
do_check_throws(function() { f_t(p); }, Error);
|
||||||
do_check_throws(function() { f.value = p; }, Error);
|
do_check_throws(function() { f.value = p; }, Error);
|
||||||
|
Loading…
Reference in New Issue
Block a user