Bug 921631 - Convert CTypes away from using propertyops to using JSNative-backed getters/setters, part 2. r=bholley

--HG--
extra : rebase_source : fe8676172e19e987d72b33e94bc636c7baac36eb
This commit is contained in:
Jeff Walden 2013-09-12 15:45:42 -07:00
parent 870e0b94b5
commit 055996bd20
3 changed files with 71 additions and 86 deletions

View File

@ -212,12 +212,13 @@ namespace PointerType {
static bool Create(JSContext* cx, unsigned argc, jsval* vp); static bool Create(JSContext* cx, unsigned argc, jsval* vp);
static bool ConstructData(JSContext* cx, HandleObject obj, const CallArgs& args); static bool ConstructData(JSContext* cx, HandleObject obj, const CallArgs& args);
static bool TargetTypeGetter(JSContext* cx, HandleObject obj, HandleId idval, bool IsPointerType(HandleValue v);
MutableHandleValue vp); bool IsPointer(HandleValue v);
static bool ContentsGetter(JSContext* cx, HandleObject obj, HandleId idval,
MutableHandleValue vp); bool TargetTypeGetter(JSContext* cx, JS::CallArgs args);
static bool ContentsSetter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, bool ContentsGetter(JSContext* cx, JS::CallArgs args);
MutableHandleValue vp); bool ContentsSetter(JSContext* cx, JS::CallArgs args);
static bool IsNull(JSContext* cx, unsigned argc, jsval* vp); static bool IsNull(JSContext* cx, unsigned argc, jsval* vp);
static bool Increment(JSContext* cx, unsigned argc, jsval* vp); static bool Increment(JSContext* cx, unsigned argc, jsval* vp);
static bool Decrement(JSContext* cx, unsigned argc, jsval* vp); static bool Decrement(JSContext* cx, unsigned argc, jsval* vp);
@ -281,10 +282,9 @@ namespace CClosure {
namespace CData { namespace CData {
static void Finalize(JSFreeOp *fop, JSObject* obj); static void Finalize(JSFreeOp *fop, JSObject* obj);
static bool ValueGetter(JSContext* cx, HandleObject obj, HandleId idval, bool ValueGetter(JSContext* cx, JS::CallArgs args);
MutableHandleValue vp); bool ValueSetter(JSContext* cx, JS::CallArgs args);
static bool ValueSetter(JSContext* cx, HandleObject obj, HandleId idval,
bool strict, MutableHandleValue vp);
static bool Address(JSContext* cx, unsigned argc, jsval* vp); static bool Address(JSContext* cx, unsigned argc, jsval* vp);
static bool ReadString(JSContext* cx, unsigned argc, jsval* vp); static bool ReadString(JSContext* cx, unsigned argc, jsval* vp);
static bool ReadStringReplaceMalformed(JSContext* cx, unsigned argc, jsval* vp); static bool ReadStringReplaceMalformed(JSContext* cx, unsigned argc, jsval* vp);
@ -594,9 +594,11 @@ static const JSFunctionSpec sCABIFunctions[] = {
}; };
static const JSPropertySpec sCDataProps[] = { static const JSPropertySpec sCDataProps[] = {
{ "value", 0, JSPROP_SHARED | JSPROP_PERMANENT, JS_PSGS("value",
JSOP_WRAPPER(CData::ValueGetter), JSOP_WRAPPER(CData::ValueSetter) }, (Property<CData::IsCData, CData::ValueGetter>::Fun),
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } (Property<CData::IsCData, CData::ValueSetter>::Fun),
JSPROP_PERMANENT),
JS_PS_END
}; };
static const JSFunctionSpec sCDataFunctions[] = { static const JSFunctionSpec sCDataFunctions[] = {
@ -625,9 +627,10 @@ static const JSFunctionSpec sPointerFunction =
JS_FN("PointerType", PointerType::Create, 1, CTYPESCTOR_FLAGS); JS_FN("PointerType", PointerType::Create, 1, CTYPESCTOR_FLAGS);
static const JSPropertySpec sPointerProps[] = { static const JSPropertySpec sPointerProps[] = {
{ "targetType", 0, CTYPESPROP_FLAGS, JS_PSG("targetType",
JSOP_WRAPPER(PointerType::TargetTypeGetter), JSOP_NULLWRAPPER }, (Property<PointerType::IsPointerType, PointerType::TargetTypeGetter>::Fun),
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } CTYPESACC_FLAGS),
JS_PS_END
}; };
static const JSFunctionSpec sPointerInstanceFunctions[] = { static const JSFunctionSpec sPointerInstanceFunctions[] = {
@ -638,10 +641,11 @@ static const JSFunctionSpec sPointerInstanceFunctions[] = {
}; };
static const JSPropertySpec sPointerInstanceProps[] = { static const JSPropertySpec sPointerInstanceProps[] = {
{ "contents", 0, JSPROP_SHARED | JSPROP_PERMANENT, JS_PSGS("contents",
JSOP_WRAPPER(PointerType::ContentsGetter), (Property<PointerType::IsPointer, PointerType::ContentsGetter>::Fun),
JSOP_WRAPPER(PointerType::ContentsSetter) }, (Property<PointerType::IsPointer, PointerType::ContentsSetter>::Fun),
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } JSPROP_PERMANENT),
JS_PS_END
}; };
static const JSFunctionSpec sArrayFunction = static const JSFunctionSpec sArrayFunction =
@ -4008,18 +4012,29 @@ PointerType::GetBaseType(JSObject* obj)
} }
bool bool
PointerType::TargetTypeGetter(JSContext* cx, PointerType::IsPointerType(HandleValue v)
HandleObject obj,
HandleId idval,
MutableHandleValue vp)
{ {
if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_pointer) { if (!v.isObject())
JS_ReportError(cx, "not a PointerType");
return false; return false;
} JSObject* obj = &v.toObject();
return CType::IsCType(obj) && CType::GetTypeCode(obj) == TYPE_pointer;
}
vp.set(JS_GetReservedSlot(obj, SLOT_TARGET_T)); bool
JS_ASSERT(vp.isObject()); PointerType::IsPointer(HandleValue v)
{
if (!v.isObject())
return false;
JSObject* obj = &v.toObject();
return CData::IsCData(obj) && CType::GetTypeCode(CData::GetCType(obj)) == TYPE_pointer;
}
bool
PointerType::TargetTypeGetter(JSContext* cx, JS::CallArgs args)
{
RootedObject obj(cx, &args.thisv().toObject());
args.rval().set(JS_GetReservedSlot(obj, SLOT_TARGET_T));
MOZ_ASSERT(args.rval().isObject());
return true; return true;
} }
@ -4098,24 +4113,10 @@ PointerType::Decrement(JSContext* cx, unsigned argc, jsval* vp)
} }
bool bool
PointerType::ContentsGetter(JSContext* cx, PointerType::ContentsGetter(JSContext* cx, JS::CallArgs args)
HandleObject obj,
HandleId idval,
MutableHandleValue vp)
{ {
if (!CData::IsCData(obj)) { RootedObject obj(cx, &args.thisv().toObject());
JS_ReportError(cx, "not a CData"); RootedObject baseType(cx, GetBaseType(CData::GetCType(obj)));
return false;
}
// Get pointer type and base type.
JSObject* typeObj = CData::GetCType(obj);
if (CType::GetTypeCode(typeObj) != TYPE_pointer) {
JS_ReportError(cx, "not a PointerType");
return false;
}
RootedObject baseType(cx, GetBaseType(typeObj));
if (!CType::IsSizeDefined(baseType)) { if (!CType::IsSizeDefined(baseType)) {
JS_ReportError(cx, "cannot get contents of undefined size"); JS_ReportError(cx, "cannot get contents of undefined size");
return false; return false;
@ -4131,30 +4132,15 @@ PointerType::ContentsGetter(JSContext* cx,
if (!ConvertToJS(cx, baseType, NullPtr(), data, false, false, result.address())) if (!ConvertToJS(cx, baseType, NullPtr(), data, false, false, result.address()))
return false; return false;
vp.set(result); args.rval().set(result);
return true; return true;
} }
bool bool
PointerType::ContentsSetter(JSContext* cx, PointerType::ContentsSetter(JSContext* cx, JS::CallArgs args)
HandleObject obj,
HandleId idval,
bool strict,
MutableHandleValue vp)
{ {
if (!CData::IsCData(obj)) { RootedObject obj(cx, &args.thisv().toObject());
JS_ReportError(cx, "not a CData"); RootedObject baseType(cx, GetBaseType(CData::GetCType(obj)));
return false;
}
// Get pointer type and base type.
JSObject* typeObj = CData::GetCType(obj);
if (CType::GetTypeCode(typeObj) != TYPE_pointer) {
JS_ReportError(cx, "not a PointerType");
return false;
}
JSObject* baseType = GetBaseType(typeObj);
if (!CType::IsSizeDefined(baseType)) { if (!CType::IsSizeDefined(baseType)) {
JS_ReportError(cx, "cannot set contents of undefined size"); JS_ReportError(cx, "cannot set contents of undefined size");
return false; return false;
@ -4166,7 +4152,8 @@ PointerType::ContentsSetter(JSContext* cx,
return false; return false;
} }
return ImplicitConvert(cx, vp, baseType, data, false, nullptr); args.rval().setUndefined();
return ImplicitConvert(cx, args.get(0), baseType, data, false, nullptr);
} }
/******************************************************************************* /*******************************************************************************
@ -6389,6 +6376,12 @@ CData::IsCData(JSObject* obj)
return JS_GetClass(obj) == &sCDataClass; return JS_GetClass(obj) == &sCDataClass;
} }
bool
CData::IsCData(HandleValue v)
{
return v.isObject() && CData::IsCData(&v.toObject());
}
bool bool
CData::IsCDataProto(JSObject* obj) CData::IsCDataProto(JSObject* obj)
{ {
@ -6396,30 +6389,21 @@ CData::IsCDataProto(JSObject* obj)
} }
bool bool
CData::ValueGetter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp) CData::ValueGetter(JSContext* cx, JS::CallArgs args)
{ {
if (!IsCData(obj)) { RootedObject obj(cx, &args.thisv().toObject());
JS_ReportError(cx, "not a CData");
return false;
}
// Convert the value to a primitive; do not create a new CData object. // Convert the value to a primitive; do not create a new CData object.
RootedObject ctype(cx, GetCType(obj)); RootedObject ctype(cx, GetCType(obj));
if (!ConvertToJS(cx, ctype, NullPtr(), GetData(obj), true, false, vp.address())) return ConvertToJS(cx, ctype, NullPtr(), GetData(obj), true, false, args.rval().address());
return false;
return true;
} }
bool bool
CData::ValueSetter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp) CData::ValueSetter(JSContext* cx, JS::CallArgs args)
{ {
if (!IsCData(obj)) { RootedObject obj(cx, &args.thisv().toObject());
JS_ReportError(cx, "not a CData"); args.rval().setUndefined();
return false; return ImplicitConvert(cx, args.get(0), GetCType(obj), GetData(obj), false, nullptr);
}
return ImplicitConvert(cx, vp, GetCType(obj), GetData(obj), false, nullptr);
} }
bool bool

View File

@ -476,6 +476,7 @@ namespace CData {
JSObject* GetCType(JSObject* dataObj); JSObject* GetCType(JSObject* dataObj);
void* GetData(JSObject* dataObj); void* GetData(JSObject* dataObj);
bool IsCData(JSObject* obj); bool IsCData(JSObject* obj);
bool IsCData(HandleValue v);
bool IsCDataProto(JSObject* obj); bool IsCDataProto(JSObject* obj);
// Attached by JSAPI as the function 'ctypes.cast' // Attached by JSAPI as the function 'ctypes.cast'

View File

@ -288,8 +288,8 @@ function run_abstract_class_tests()
do_check_true(ctypes.CData.prototype.hasOwnProperty("toSource")); do_check_true(ctypes.CData.prototype.hasOwnProperty("toSource"));
// Check that the shared properties and functions on ctypes.CData.prototype throw. // Check that the shared properties and functions on ctypes.CData.prototype throw.
do_check_throws(function() { ctypes.CData.prototype.value; }, Error); do_check_throws(function() { ctypes.CData.prototype.value; }, TypeError);
do_check_throws(function() { ctypes.CData.prototype.value = null; }, Error); do_check_throws(function() { ctypes.CData.prototype.value = null; }, TypeError);
do_check_throws(function() { ctypes.CData.prototype.address(); }, Error); do_check_throws(function() { ctypes.CData.prototype.address(); }, Error);
do_check_throws(function() { ctypes.CData.prototype.readString(); }, Error); do_check_throws(function() { ctypes.CData.prototype.readString(); }, Error);
@ -750,8 +750,8 @@ function run_basic_class_tests(t)
do_check_true(t.prototype.constructor === t); do_check_true(t.prototype.constructor === t);
// Check that the shared properties and functions on 't.prototype' throw. // Check that the shared properties and functions on 't.prototype' throw.
do_check_throws(function() { t.prototype.value; }, Error); do_check_throws(function() { t.prototype.value; }, TypeError);
do_check_throws(function() { t.prototype.value = null; }, Error); do_check_throws(function() { t.prototype.value = null; }, TypeError);
do_check_throws(function() { t.prototype.address(); }, Error); do_check_throws(function() { t.prototype.address(); }, Error);
do_check_throws(function() { t.prototype.readString(); }, Error); do_check_throws(function() { t.prototype.readString(); }, Error);