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

This commit is contained in:
Dan Witte 2010-03-11 17:17:36 -08:00
Родитель f621917024
Коммит 2626e52ff3
4 изменённых файлов: 150 добавлений и 137 удалений

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

@ -36,13 +36,13 @@
*
* ***** END LICENSE BLOCK ***** */
#include "jscntxt.h"
#include "CTypes.h"
#include "nsAutoPtr.h"
#include "nsUTF8Utils.h"
#include "nsCRTGlue.h"
#include "prlog.h"
#include "prdtoa.h"
#include "jscntxt.h"
#include "jsnum.h"
namespace mozilla {
@ -100,7 +100,7 @@ static JSPropertySpec sCTypeProps[] = {
{ "name", 0, CTYPESPROP_FLAGS, CType::NameGetter, NULL },
{ "size", 0, CTYPESPROP_FLAGS, CType::SizeGetter, NULL },
{ "ptr", 0, CTYPESPROP_FLAGS, CType::PtrGetter, NULL },
{ "prototype", 0, CTYPESPROP_FLAGS, CType::ProtoGetter, NULL },
{ "prototype", 0, CTYPESPROP_FLAGS, CType::PrototypeGetter, NULL },
{ 0, 0, 0, NULL, NULL }
};
@ -123,7 +123,7 @@ static JSFunctionSpec sPointerFunction =
JS_FN("PointerType", PointerType::Create, 1, CTYPESFN_FLAGS);
static JSPropertySpec sPointerProps[] = {
{ "targetType", 0, CTYPESPROP_FLAGS, PointerType::TargetGetter, NULL },
{ "targetType", 0, CTYPESPROP_FLAGS, PointerType::TargetTypeGetter, NULL },
{ 0, 0, 0, NULL, NULL }
};
@ -230,6 +230,20 @@ static JSFunctionSpec sUInt64Functions[] = {
JS_FS_END
};
JS_ALWAYS_INLINE void
ASSERT_OK(JSBool ok)
{
JS_ASSERT(ok);
}
JS_ALWAYS_INLINE JSString*
NewUCString(JSContext* cx, const nsString& from)
{
JS_ASSERT(from.get());
return JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(from.get()), from.Length());
}
ABICode
GetABICode(JSContext* cx, JSObject* obj)
{
@ -239,7 +253,7 @@ GetABICode(JSContext* cx, JSObject* obj)
return INVALID_ABI;
jsval result;
JS_GetReservedSlot(cx, obj, SLOT_ABICODE, &result);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_ABICODE, &result));
return ABICode(JSVAL_TO_INT(result));
}
@ -360,7 +374,7 @@ InitInt64Class(JSContext* cx,
// Stash ctypes.{Int64,UInt64}.prototype on a reserved slot of the 'join'
// function.
jsval join;
JS_GetProperty(cx, ctor, "join", &join);
ASSERT_OK(JS_GetProperty(cx, ctor, "join", &join));
if (!JS_SetReservedSlot(cx, JSVAL_TO_OBJECT(join), SLOT_FN_INT64PROTO,
OBJECT_TO_JSVAL(prototype)))
return NULL;
@ -374,7 +388,7 @@ InitInt64Class(JSContext* cx,
static JSBool
AttachProtos(JSContext* cx, JSObject* proto, JSObject** protos)
{
// For a given 'proto' of class [[CTypeProto]], attach each of the 'protos'
// For a given 'proto' of [[Class]] CTypeProto, attach each of the 'protos'
// to the appropriate CTypeProtoSlot.
for (PRUint32 i = 0; i < CTYPEPROTO_SLOTS; ++i) {
if (!JS_SetReservedSlot(cx, proto, i, OBJECT_TO_JSVAL(protos[i])))
@ -389,12 +403,12 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
{
// Initialize the ctypes.CType class. This acts as an abstract base class for
// the various types, and provides the common API functions. It has:
// * Class [[Function]]
// * [[Class]] "Function"
// * __proto__ === Function.prototype
// * A constructor that throws a TypeError. (You can't construct an
// abstract type!)
// * 'prototype' property:
// * Class [[CTypeProto]]
// * [[Class]] "CTypeProto"
// * __proto__ === Function.prototype === ctypes.CType.__proto__
// * 'constructor' property === ctypes.CType
JSObject* CTypeProto = JS_InitClass(cx, parent, NULL, &sCTypeProtoClass,
@ -428,12 +442,12 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
// Create objects representing the builtin types, and attach them to the
// ctypes object. Each type object 't' has:
// * Class [[CType]]
// * [[Class]] "CType"
// * __proto__ === ctypes.CType.prototype
// * A constructor which creates and returns a CData object, containing
// binary data of the given type.
// * 'prototype' property:
// * Class [[Object]]
// * [[Class]] "Object"
// * __proto__ === Object.prototype
// * 'constructor' property === 't'
#define DEFINE_TYPE(name, type, ffiType) \
@ -454,11 +468,11 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
// Create and attach the special class constructors:
// ctypes.PointerType, ctypes.ArrayType, and ctypes.StructType.
// Each of these has, respectively:
// * Class [[Function]]
// * [[Class]] "Function"
// * __proto__ === Function.prototype
// * A constructor that creates a user-defined type.
// * 'prototype' property:
// * Class [[CTypeProto]]
// * [[Class]] "CTypeProto"
// * __proto__ === ctypes.CType.prototype
// * 'constructor' property === ctypes.{Pointer,Array,Struct}Type
JSObject* protos[CTYPEPROTO_SLOTS];
@ -477,10 +491,10 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
// Create and attach the ctypes.{Int64,UInt64} constructors.
// Each of these has, respectively:
// * Class [[Function]]
// * [[Class]] "Function"
// * A constructor that creates a ctypes.{Int64,UInt64} object, respectively.
// * 'prototype' property:
// * Class [[{Int64Proto,UInt64Proto}]]
// * [[Class]] {"Int64Proto","UInt64Proto"}
// * __proto__ === Function.prototype === ctypes.{Int64,UInt64}.__proto__
// * 'constructor' property === ctypes.{Int64,UInt64}
protos[SLOT_INT64PROTO] = InitInt64Class(cx, parent, &sInt64ProtoClass,
@ -496,12 +510,12 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
// the special type constructors, and Int64/UInt64 types, so we can access
// them when constructing instances of those types. An instance 't' of
// ctypes.{Pointer,Array,Struct}Type will have, resp.:
// * Class [[CType]]
// * [[Class]] "CType"
// * __proto__ === ctypes.{Pointer,Array,Struct}Type.prototype
// * A constructor which creates and returns a CData object, containing
// binary data of the given type.
// * 'prototype' property:
// * Class [[Object]]
// * [[Class]] "Object"
// * __proto__ === Object.prototype
// * 'constructor' property === t
if (!AttachProtos(cx, CTypeProto, protos) ||
@ -544,6 +558,7 @@ PR_STATIC_ASSERT(sizeof(long) == 4 || sizeof(long) == 8);
PR_STATIC_ASSERT(sizeof(long long) == 8);
PR_STATIC_ASSERT(sizeof(size_t) == sizeof(uintptr_t));
PR_STATIC_ASSERT(sizeof(float) == 4);
PR_STATIC_ASSERT(sizeof(jschar) == sizeof(PRUnichar));
template<class IntegerType>
static JS_ALWAYS_INLINE IntegerType
@ -605,7 +620,7 @@ jsvalToBool(JSContext* cx, jsval val, bool* result)
if (JSVAL_IS_DOUBLE(val)) {
jsdouble d = *JSVAL_TO_DOUBLE(val);
*result = d != 0;
// Disallow -0.
// Allow -0.
return d == 1 || d == 0;
}
// Don't silently convert null to bool. It's probably a mistake.
@ -1108,7 +1123,7 @@ ConvertToJS(JSContext* cx,
}
#define DEFINE_CHAR_TYPE(name, type, ffiType) \
case TYPE_##name: \
/* Convert to an integer. (We have no idea what character encoding to */ \
/* Convert to an integer. We have no idea what character encoding to */ \
/* use, if any. */ \
*result = INT_TO_JSVAL(*static_cast<type*>(data)); \
break;
@ -1217,14 +1232,13 @@ ImplicitConvert(JSContext* cx,
case TYPE_##name: { \
/* Convert from a 1-character string, regardless of encoding, */ \
/* or from an integer, provided the result fits in 'type'. */ \
/* TODO: Check IsASCII(chars) for 8-bit char types? */ \
type result; \
if (JSVAL_IS_STRING(val)) { \
JSString* str = JSVAL_TO_STRING(val); \
if (JS_GetStringLength(str) != 1) \
return TypeError(cx, #name, val); \
\
jschar c = *JS_GetStringCharsZ(cx, str); \
jschar c = *JS_GetStringChars(str); \
result = c; \
if (jschar(result) != c) \
return TypeError(cx, #name, val); \
@ -1513,7 +1527,7 @@ ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer)
case TYPE_bool: {
// Convert according to the ECMAScript ToBoolean() function.
JSBool result;
JS_ValueToBoolean(cx, val, &result);
ASSERT_OK(JS_ValueToBoolean(cx, val, &result));
*static_cast<bool*>(buffer) = result != JS_FALSE;
break;
}
@ -1780,8 +1794,22 @@ BuildDataSource(JSContext* cx, JSObject* typeObj, void* data, bool isImplicit)
/* Serialize as an integer. */ \
result.Append(IntegerToString(*static_cast<type*>(data), 10)); \
break;
#define DEFINE_JSCHAR_TYPE(x, y, z) DEFINE_CHAR_TYPE(x, y, z)
#include "typedefs.h"
case TYPE_jschar: {
/* Serialize as a 1-character JS string. */
JSString* str = JS_NewUCStringCopyN(cx, static_cast<jschar*>(data), 1);
if (!str)
break;
JSString* src = JS_ValueToSource(cx, STRING_TO_JSVAL(str));
if (!src)
break;
const jschar* srcChars = JS_GetStringChars(src);
size_t srclen = JS_GetStringLength(src);
result.Append(reinterpret_cast<const PRUnichar*>(srcChars), srclen);
break;
}
case TYPE_pointer: {
if (isImplicit) {
// The result must be able to ImplicitConvert successfully.
@ -1889,7 +1917,7 @@ CType::ConstructData(JSContext* cx,
// How we construct the CData object depends on what type we represent.
// An instance 'd' of a CData object of type 't' has:
// * Class [[CData]]
// * [[Class]] "CData"
// * __proto__ === t.prototype
switch (GetTypeCode(cx, obj)) {
case TYPE_void_t:
@ -1946,13 +1974,13 @@ CType::Create(JSContext* cx,
{
// Create a CType object with the properties and slots common to all CTypes.
// Each type object 't' has:
// * Class [[CType]]
// * [[Class]] "CType"
// * __proto__ === 'proto'; one of ctypes.{CType,PointerType,ArrayType,
// StructType}.prototype
// * A constructor which creates and returns a CData object, containing
// binary data of the given type.
// * 'prototype' property:
// * Class [[Object]]
// * [[Class]] "Object"
// * __proto__ === Object.prototype
// * 'constructor' property === 't'
JSObject* typeObj = JS_NewObject(cx, &sCTypeClass, proto, NULL);
@ -2053,7 +2081,7 @@ CType::Finalize(JSContext* cx, JSObject* obj)
switch (TypeCode(JSVAL_TO_INT(slot))) {
case TYPE_struct:
// Free the FieldInfo array.
JS_GetReservedSlot(cx, obj, SLOT_FIELDINFO, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FIELDINFO, &slot));
if (!JSVAL_IS_VOID(slot))
delete static_cast<nsTArray<FieldInfo>*>(JSVAL_TO_PRIVATE(slot));
@ -2061,7 +2089,7 @@ CType::Finalize(JSContext* cx, JSObject* obj)
case TYPE_array: {
// Free the ffi_type info.
jsval slot;
JS_GetReservedSlot(cx, obj, SLOT_FFITYPE, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FFITYPE, &slot));
if (!JSVAL_IS_VOID(slot) && JSVAL_TO_PRIVATE(slot)) {
ffi_type* ffiType = static_cast<ffi_type*>(JSVAL_TO_PRIVATE(slot));
delete[] ffiType->elements;
@ -2088,7 +2116,7 @@ CType::GetTypeCode(JSContext* cx, JSObject* typeObj)
JS_ASSERT(IsCType(cx, typeObj));
jsval result;
JS_GetReservedSlot(cx, typeObj, SLOT_TYPECODE, &result);
ASSERT_OK(JS_GetReservedSlot(cx, typeObj, SLOT_TYPECODE, &result));
return TypeCode(JSVAL_TO_INT(result));
}
@ -2148,7 +2176,7 @@ CType::GetSafeSize(JSContext* cx, JSObject* obj, size_t* result)
JS_ASSERT(CType::IsCType(cx, obj));
jsval size;
JS_GetReservedSlot(cx, obj, SLOT_SIZE, &size);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_SIZE, &size));
// The "size" property can be a jsint, a jsdouble, or JSVAL_VOID
// (for arrays of undefined length), and must always fit in a size_t.
@ -2171,7 +2199,7 @@ CType::GetSize(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::IsCType(cx, obj));
jsval size;
JS_GetReservedSlot(cx, obj, SLOT_SIZE, &size);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_SIZE, &size));
JS_ASSERT(!JSVAL_IS_VOID(size));
@ -2189,7 +2217,7 @@ CType::IsSizeDefined(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::IsCType(cx, obj));
jsval size;
JS_GetReservedSlot(cx, obj, SLOT_SIZE, &size);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_SIZE, &size));
// The "size" property can be a jsint, a jsdouble, or JSVAL_VOID
// (for arrays of undefined length), and must always fit in a size_t.
@ -2203,7 +2231,7 @@ CType::GetAlignment(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::IsCType(cx, obj));
jsval slot;
JS_GetReservedSlot(cx, obj, SLOT_ALIGN, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_ALIGN, &slot));
return static_cast<size_t>(JSVAL_TO_INT(slot));
}
@ -2213,7 +2241,7 @@ CType::GetFFIType(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::IsCType(cx, obj));
jsval slot;
JS_GetReservedSlot(cx, obj, SLOT_FFITYPE, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FFITYPE, &slot));
ffi_type* result = static_cast<ffi_type*>(JSVAL_TO_PRIVATE(slot));
JS_ASSERT(result);
@ -2226,24 +2254,22 @@ CType::GetName(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::IsCType(cx, obj));
jsval string;
JS_GetReservedSlot(cx, obj, SLOT_NAME, &string);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_NAME, &string));
return JSVAL_TO_STRING(string);
}
JSObject*
CType::GetProtoFromCtor(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
CType::GetProtoFromCtor(JSContext* cx, JSObject* obj)
{
// Look at the 'prototype' property of the type constructor.
jsval prototype;
JS_GetProperty(cx, obj, "prototype", &prototype);
ASSERT_OK(JS_GetProperty(cx, obj, "prototype", &prototype));
JSObject* proto = JSVAL_TO_OBJECT(prototype);
JS_ASSERT(proto);
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sCTypeProtoClass);
// Get the requested ctypes.{Pointer,Array,Struct}Type.prototype.
jsval result;
JS_GetReservedSlot(cx, proto, slot, &result);
return JSVAL_TO_OBJECT(result);
// Return the desired ctypes.{Pointer,Array,Struct}Type.prototype.
return proto;
}
JSObject*
@ -2258,19 +2284,19 @@ CType::GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
// Get the requested ctypes.{Pointer,Array,Struct}Type.prototype.
jsval result;
JS_GetReservedSlot(cx, proto, slot, &result);
ASSERT_OK(JS_GetReservedSlot(cx, proto, slot, &result));
return JSVAL_TO_OBJECT(result);
}
JSBool
CType::ProtoGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
CType::PrototypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
{
if (!CType::IsCType(cx, obj)) {
JS_ReportError(cx, "not a CType");
return JS_FALSE;
}
JS_GetReservedSlot(cx, obj, SLOT_PROTO, vp);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_PROTO, vp));
JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
return JS_TRUE;
}
@ -2283,7 +2309,7 @@ CType::NameGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
return JS_FALSE;
}
JS_GetReservedSlot(cx, obj, SLOT_NAME, vp);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_NAME, vp));
JS_ASSERT(JSVAL_IS_STRING(*vp));
return JS_TRUE;
}
@ -2296,7 +2322,7 @@ CType::SizeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
return JS_FALSE;
}
JS_GetReservedSlot(cx, obj, SLOT_SIZE, vp);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_SIZE, vp));
JS_ASSERT(JSVAL_IS_NUMBER(*vp) || JSVAL_IS_VOID(*vp));
return JS_TRUE;
}
@ -2367,8 +2393,7 @@ CType::ToString(JSContext* cx, uintN argc, jsval *vp)
size_t rightlen = JS_GetStringLength(right);
type.Append(reinterpret_cast<const PRUnichar*>(rightChars), rightlen);
JSString* result = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(type.get()), type.Length());
JSString* result = NewUCString(cx, type);
if (!result)
return JS_FALSE;
@ -2388,8 +2413,7 @@ CType::ToSource(JSContext* cx, uintN argc, jsval *vp)
}
nsAutoString source = BuildTypeSource(cx, obj, false);
JSString* result = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(source.get()), source.Length());
JSString* result = NewUCString(cx, source);
if (!result)
return JS_FALSE;
@ -2447,7 +2471,7 @@ PointerType::CreateInternal(JSContext* cx,
if (baseType) {
// check if we have a cached PointerType on our base CType.
jsval slot;
JS_GetReservedSlot(cx, baseType, SLOT_PTR, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, baseType, SLOT_PTR, &slot));
if (!JSVAL_IS_VOID(slot))
return JSVAL_TO_OBJECT(slot);
}
@ -2456,7 +2480,7 @@ PointerType::CreateInternal(JSContext* cx,
// whichever was provided.
JSObject* proto;
if (ctor)
proto = CType::GetProtoFromCtor(cx, ctor, SLOT_POINTERPROTO);
proto = CType::GetProtoFromCtor(cx, ctor);
else
proto = CType::GetProtoFromType(cx, baseType, SLOT_POINTERPROTO);
@ -2477,8 +2501,7 @@ PointerType::CreateInternal(JSContext* cx,
if (baseType) {
// Determine the name of the PointerType, since it wasn't supplied.
nsAutoString typeName = BuildTypeName(cx, typeObj);
JSString* nameStr = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(typeName.get()), typeName.Length());
JSString* nameStr = NewUCString(cx, typeName);
if (!nameStr ||
!JS_SetReservedSlot(cx, typeObj, SLOT_NAME, STRING_TO_JSVAL(nameStr)))
return NULL;
@ -2528,19 +2551,22 @@ PointerType::GetBaseType(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_pointer);
jsval type;
JS_GetReservedSlot(cx, obj, SLOT_TARGET_T, &type);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_TARGET_T, &type));
return JSVAL_TO_OBJECT(type);
}
JSBool
PointerType::TargetGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
PointerType::TargetTypeGetter(JSContext* cx,
JSObject* obj,
jsval idval,
jsval* vp)
{
if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_pointer) {
JS_ReportError(cx, "not a PointerType");
return JS_FALSE;
}
JS_GetReservedSlot(cx, obj, SLOT_TARGET_T, vp);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_TARGET_T, vp));
JS_ASSERT(JSVAL_IS_OBJECT(*vp));
return JS_TRUE;
}
@ -2746,8 +2772,7 @@ ArrayType::CreateInternal(JSContext* cx,
// Determine the name of the ArrayType.
nsAutoString typeName = BuildTypeName(cx, typeObj);
JSString* name = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(typeName.get()), typeName.Length());
JSString* name = NewUCString(cx, typeName);
if (!name ||
!JS_SetReservedSlot(cx, typeObj, SLOT_NAME, STRING_TO_JSVAL(name)))
return NULL;
@ -2866,7 +2891,7 @@ ArrayType::GetBaseType(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_array);
jsval type;
JS_GetReservedSlot(cx, obj, SLOT_ELEMENT_T, &type);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_ELEMENT_T, &type));
return JSVAL_TO_OBJECT(type);
}
@ -2877,7 +2902,7 @@ ArrayType::GetSafeLength(JSContext* cx, JSObject* obj, size_t* result)
JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_array);
jsval length;
JS_GetReservedSlot(cx, obj, SLOT_LENGTH, &length);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_LENGTH, &length));
// The "length" property can be a jsint, a jsdouble, or JSVAL_VOID
// (for arrays of undefined length), and must always fit in a size_t.
@ -2901,7 +2926,7 @@ ArrayType::GetLength(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_array);
jsval length;
JS_GetReservedSlot(cx, obj, SLOT_LENGTH, &length);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_LENGTH, &length));
JS_ASSERT(!JSVAL_IS_VOID(length));
@ -2921,7 +2946,7 @@ ArrayType::ElementTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v
return JS_FALSE;
}
JS_GetReservedSlot(cx, obj, SLOT_ELEMENT_T, vp);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_ELEMENT_T, vp));
JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
return JS_TRUE;
}
@ -2939,7 +2964,7 @@ ArrayType::LengthGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
return JS_FALSE;
}
JS_GetReservedSlot(cx, obj, SLOT_LENGTH, vp);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_LENGTH, vp));
JS_ASSERT(JSVAL_IS_NUMBER(*vp) || JSVAL_IS_VOID(*vp));
return JS_TRUE;
}
@ -3088,10 +3113,6 @@ ExtractStructField(JSContext* cx, jsval val, FieldInfo* field)
jsid id;
if (!JS_NextProperty(cx, iter, &id))
return false;
if (JSVAL_IS_VOID(id)) {
JS_ReportError(cx, "struct field descriptors require a valid name and type");
return false;
}
jsval nameVal;
if (!JS_IdToValue(cx, id, &nameVal))
@ -3193,7 +3214,7 @@ StructType::Create(JSContext* cx, uintN argc, jsval* vp)
// Process the field types and fill in the ffi_type fields.
JSObject* fieldsObj = JSVAL_TO_OBJECT(argv[1]);
jsuint len;
JS_GetArrayLength(cx, fieldsObj, &len);
ASSERT_OK(JS_GetArrayLength(cx, fieldsObj, &len));
nsAutoPtr<ffi_type> ffiType(new ffi_type);
if (!ffiType) {
@ -3325,7 +3346,7 @@ StructType::Create(JSContext* cx, uintN argc, jsval* vp)
// Get ctypes.StructType.prototype from the ctypes.StructType constructor.
JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
JSObject* proto = CType::GetProtoFromCtor(cx, callee, SLOT_STRUCTPROTO);
JSObject* proto = CType::GetProtoFromCtor(cx, callee);
// Create a new CType object with the common properties and slots.
JSObject* typeObj = CType::Create(cx, proto, TYPE_struct, name,
@ -3371,61 +3392,56 @@ StructType::ConstructData(JSContext* cx,
*rval = OBJECT_TO_JSVAL(result);
if (argc != 0) {
char* buffer = static_cast<char*>(CData::GetData(cx, result));
nsTArray<FieldInfo>* fields = GetFieldInfo(cx, obj);
if (argc == 0)
return JS_TRUE;
if (argc == 1) {
// There are two possible interpretations of the argument:
// 1) It may be an object '{ ... }' with properties representing the
// struct fields intended to ExplicitConvert wholesale to our StructType.
// 2) If the struct contains one field, the arg may be intended to
// ImplicitConvert directly to that arg's CType.
// Thankfully, the conditions for these two possibilities to succeed
// are mutually exclusive, so we can pick the right one.
char* buffer = static_cast<char*>(CData::GetData(cx, result));
nsTArray<FieldInfo>* fields = GetFieldInfo(cx, obj);
// Try option 1) first.
if (ExplicitConvert(cx, argv[0], obj, buffer))
return JS_TRUE;
if (argc == 1) {
// There are two possible interpretations of the argument:
// 1) It may be an object '{ ... }' with properties representing the
// struct fields intended to ExplicitConvert wholesale to our StructType.
// 2) If the struct contains one field, the arg may be intended to
// ImplicitConvert directly to that arg's CType.
// Thankfully, the conditions for these two possibilities to succeed
// are mutually exclusive, so we can pick the right one.
// If ExplicitConvert failed, and there is no pending exception, then assume
// hard failure (out of memory, or some other similarly serious condition).
if (!JS_IsExceptionPending(cx))
return JS_FALSE;
// Try option 1) first.
if (ExplicitConvert(cx, argv[0], obj, buffer))
return JS_TRUE;
// Otherwise, assume soft failure, and clear the pending exception so that we
// can throw a different one as required.
JS_ClearPendingException(cx);
if (fields->Length() != 1) {
JS_ReportError(cx, "constructor takes 0, 1, or %u arguments",
fields->Length());
return JS_FALSE;
}
// Try option 2).
FieldInfo& field = fields->ElementAt(0);
return ImplicitConvert(cx, argv[0], field.mType, buffer + field.mOffset,
false, NULL);
}
if (argc != fields->Length()) {
JS_ReportError(cx, "constructor takes 0, 1, or %u arguments",
fields->Length());
if (fields->Length() != 1)
return JS_FALSE;
}
// Otherwise, we have a type constructor of the form
// 'ctypes.StructType(a, b, c, ...)'. ImplicitConvert each field.
// If ExplicitConvert failed, and there is no pending exception, then assume
// hard failure (out of memory, or some other similarly serious condition).
if (!JS_IsExceptionPending(cx))
return JS_FALSE;
// Otherwise, assume soft failure, and clear the pending exception so that we
// can throw a different one as required.
JS_ClearPendingException(cx);
// Fall through to try option 2).
}
// We have a type constructor of the form 'ctypes.StructType(a, b, c, ...)'.
// ImplicitConvert each field.
if (argc == fields->Length()) {
for (PRUint32 i = 0; i < fields->Length(); ++i) {
FieldInfo& field = fields->ElementAt(i);
if (!ImplicitConvert(cx, argv[i], field.mType, buffer + field.mOffset,
false, NULL))
return JS_FALSE;
}
return JS_TRUE;
}
return JS_TRUE;
JS_ReportError(cx, "constructor takes 0, 1, or %u arguments",
fields->Length());
return JS_FALSE;
}
nsTArray<FieldInfo>*
@ -3435,7 +3451,7 @@ StructType::GetFieldInfo(JSContext* cx, JSObject* obj)
JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_struct);
jsval slot;
JS_GetReservedSlot(cx, obj, SLOT_FIELDINFO, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FIELDINFO, &slot));
JS_ASSERT(!JSVAL_IS_VOID(slot) && JSVAL_TO_PRIVATE(slot));
return static_cast<nsTArray<FieldInfo>*>(JSVAL_TO_PRIVATE(slot));
@ -3473,7 +3489,7 @@ StructType::FieldsArrayGetter(JSContext* cx, JSObject* obj, jsval idval, jsval*
return JS_FALSE;
}
JS_GetReservedSlot(cx, obj, SLOT_FIELDS, vp);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FIELDS, vp));
JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp) &&
JS_IsArrayObject(cx, JSVAL_TO_OBJECT(*vp)));
return JS_TRUE;
@ -3575,11 +3591,11 @@ StructType::AddressOfField(JSContext* cx, uintN argc, jsval *vp)
// Create a new CData object of type 'typeObj' containing binary data supplied
// in 'source', optionally with a referent CData object 'baseObj'.
// * 'typeObj' must be a CType of defined (but possibly zero) size.
// * If a CData object 'parentObj' is supplied, the new CData object becomes
// * If a CData object 'baseObj' is supplied, the new CData object becomes
// dependent on the given parent and its buffer refers to a slice of the
// parent's buffer, supplied in 'source'. 'parentObj' will be held alive by
// parent's buffer, supplied in 'source'. 'baseObj' will be held alive by
// the resulting CData object.
// * If 'parentObj' is null, the new CData object will create a new buffer of
// * If 'baseObj' is null, the new CData object will create a new buffer of
// size given by 'typeObj'. If 'source' data is supplied, the data will be
// copied from 'source' into the new buffer; otherwise, the entirety of the
// new buffer will be initialized to zero.
@ -3594,7 +3610,7 @@ CData::Create(JSContext* cx, JSObject* typeObj, JSObject* baseObj, void* source)
// Get the 'prototype' property from the type.
jsval slot;
JS_GetReservedSlot(cx, typeObj, SLOT_PROTO, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, typeObj, SLOT_PROTO, &slot));
JS_ASSERT(!JSVAL_IS_PRIMITIVE(slot));
JSObject* proto = JSVAL_TO_OBJECT(slot);
@ -3674,7 +3690,7 @@ CData::GetCType(JSContext* cx, JSObject* dataObj)
JS_ASSERT(CData::IsCData(cx, dataObj));
jsval slot;
JS_GetReservedSlot(cx, dataObj, SLOT_CTYPE, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, dataObj, SLOT_CTYPE, &slot));
JSObject* typeObj = JSVAL_TO_OBJECT(slot);
JS_ASSERT(CType::IsCType(cx, typeObj));
return typeObj;
@ -3686,7 +3702,7 @@ CData::GetData(JSContext* cx, JSObject* dataObj)
JS_ASSERT(CData::IsCData(cx, dataObj));
jsval slot;
JS_GetReservedSlot(cx, dataObj, SLOT_DATA, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, dataObj, SLOT_DATA, &slot));
void** buffer = static_cast<void**>(JSVAL_TO_PRIVATE(slot));
JS_ASSERT(buffer);
@ -3868,9 +3884,7 @@ CData::ReadString(JSContext* cx, uintN argc, jsval *vp)
return JS_FALSE;
}
NS_ConvertUTF8toUTF16 converted(string);
result = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(converted.get()), converted.Length());
result = NewUCString(cx, NS_ConvertUTF8toUTF16(string));
break;
}
case TYPE_int16_t:
@ -3924,8 +3938,7 @@ CData::ToSource(JSContext* cx, uintN argc, jsval *vp)
source.Append(BuildDataSource(cx, typeObj, data, false));
source.Append(')');
JSString* result = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(source.get()), source.Length());
JSString* result = NewUCString(cx, source);
if (!result)
return JS_FALSE;
@ -3982,7 +3995,7 @@ Int64Base::GetInt(JSContext* cx, JSObject* obj) {
JS_ASSERT(Int64::IsInt64(cx, obj) || UInt64::IsUInt64(cx, obj));
jsval slot;
JS_GetReservedSlot(cx, obj, SLOT_INT64, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_INT64, &slot));
return *static_cast<PRUint64*>(JSVAL_TO_PRIVATE(slot));
}
@ -4016,8 +4029,7 @@ Int64Base::ToString(JSContext* cx,
intString = IntegerToString(static_cast<PRInt64>(GetInt(cx, obj)), radix);
}
JSString *result = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(intString.get()), intString.Length());
JSString *result = NewUCString(cx, intString);
if (!result)
return JS_FALSE;
@ -4048,8 +4060,7 @@ Int64Base::ToSource(JSContext* cx,
}
source.Append(NS_LITERAL_STRING("\")"));
JSString *result = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(source.get()), source.Length());
JSString *result = NewUCString(cx, source);
if (!result)
return JS_FALSE;
@ -4076,7 +4087,8 @@ Int64::Construct(JSContext* cx,
// Get ctypes.Int64.prototype from the 'prototype' property of the ctor.
jsval slot;
JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)), "prototype", &slot);
ASSERT_OK(JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)),
"prototype", &slot));
JSObject* proto = JSVAL_TO_OBJECT(slot);
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sInt64ProtoClass);
@ -4217,7 +4229,7 @@ Int64::Join(JSContext* cx, uintN argc, jsval* vp)
JSObject* callee = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv));
jsval slot;
JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
JSObject* proto = JSVAL_TO_OBJECT(slot);
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sInt64ProtoClass);
@ -4248,7 +4260,8 @@ UInt64::Construct(JSContext* cx,
// Get ctypes.UInt64.prototype from the 'prototype' property of the ctor.
jsval slot;
JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)), "prototype", &slot);
ASSERT_OK(JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)),
"prototype", &slot));
JSObject* proto = JSVAL_TO_OBJECT(slot);
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sUInt64ProtoClass);
@ -4385,7 +4398,7 @@ UInt64::Join(JSContext* cx, uintN argc, jsval* vp)
JSObject* callee = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv));
jsval slot;
JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot);
ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
JSObject* proto = JSVAL_TO_OBJECT(slot);
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sUInt64ProtoClass);

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

@ -175,10 +175,10 @@ public:
static size_t GetAlignment(JSContext* cx, JSObject* obj);
static ffi_type* GetFFIType(JSContext* cx, JSObject* obj);
static JSString* GetName(JSContext* cx, JSObject* obj);
static JSObject* GetProtoFromCtor(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
static JSObject* GetProtoFromCtor(JSContext* cx, JSObject* obj);
static JSObject* GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
static JSBool ProtoGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool PrototypeGetter(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);
@ -196,7 +196,7 @@ public:
static JSObject* GetBaseType(JSContext* cx, JSObject* obj);
static JSBool TargetGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool TargetTypeGetter(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);
};

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

@ -129,7 +129,7 @@ Library::Create(JSContext* cx, jsval aPath)
nsISupports* file = xpc->GetNativeOfWrapper(cx, JSVAL_TO_OBJECT(aPath));
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file);
if (!localFile) {
JS_ReportError(cx, "open takes a string or nsIFile argument");
JS_ReportError(cx, "open takes a string or nsILocalFile argument");
return NULL;
}

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

@ -1111,7 +1111,7 @@ function run_jschar_tests(library, t, name, limits) {
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(), "ctypes." + name + "(\"" + d.value + "\")");
do_check_eq(d.toSource(), d.toString());
// Test string autoconversion (and lack thereof).