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

--HG--
extra : rebase_source : e88b147e55d6dd1bdd9de34272d347e932ef09b7
This commit is contained in:
Jeff Walden 2013-09-12 15:45:42 -07:00
Родитель e57e0ba4ce
Коммит 6c4de76931
2 изменённых файлов: 74 добавлений и 45 удалений

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

@ -228,24 +228,28 @@ namespace PointerType {
} }
namespace ArrayType { namespace ArrayType {
bool IsArrayType(HandleValue v);
bool IsArrayOrArrayType(HandleValue v);
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 ElementTypeGetter(JSContext* cx, HandleObject obj, HandleId idval, bool ElementTypeGetter(JSContext* cx, JS::CallArgs args);
MutableHandleValue vp); bool LengthGetter(JSContext* cx, JS::CallArgs args);
static bool LengthGetter(JSContext* cx, HandleObject obj, HandleId idval,
MutableHandleValue vp);
static bool Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp); static bool Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp);
static bool Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp); static bool Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp);
static bool AddressOfElement(JSContext* cx, unsigned argc, jsval* vp); static bool AddressOfElement(JSContext* cx, unsigned argc, jsval* vp);
} }
namespace StructType { namespace StructType {
bool IsStruct(HandleValue v);
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 FieldsArrayGetter(JSContext* cx, HandleObject obj, HandleId idval, bool FieldsArrayGetter(JSContext* cx, JS::CallArgs args);
MutableHandleValue vp);
static bool FieldGetter(JSContext* cx, HandleObject obj, HandleId idval, static bool FieldGetter(JSContext* cx, HandleObject obj, HandleId idval,
MutableHandleValue vp); MutableHandleValue vp);
static bool FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, static bool FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, bool strict,
@ -652,11 +656,13 @@ static const JSFunctionSpec sArrayFunction =
JS_FN("ArrayType", ArrayType::Create, 1, CTYPESCTOR_FLAGS); JS_FN("ArrayType", ArrayType::Create, 1, CTYPESCTOR_FLAGS);
static const JSPropertySpec sArrayProps[] = { static const JSPropertySpec sArrayProps[] = {
{ "elementType", 0, CTYPESPROP_FLAGS, JS_PSG("elementType",
JSOP_WRAPPER(ArrayType::ElementTypeGetter), JSOP_NULLWRAPPER }, (Property<ArrayType::IsArrayType, ArrayType::ElementTypeGetter>::Fun),
{ "length", 0, CTYPESPROP_FLAGS, CTYPESACC_FLAGS),
JSOP_WRAPPER(ArrayType::LengthGetter), JSOP_NULLWRAPPER }, JS_PSG("length",
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } (Property<ArrayType::IsArrayOrArrayType, ArrayType::LengthGetter>::Fun),
CTYPESACC_FLAGS),
JS_PS_END
}; };
static const JSFunctionSpec sArrayInstanceFunctions[] = { static const JSFunctionSpec sArrayInstanceFunctions[] = {
@ -665,18 +671,20 @@ static const JSFunctionSpec sArrayInstanceFunctions[] = {
}; };
static const JSPropertySpec sArrayInstanceProps[] = { static const JSPropertySpec sArrayInstanceProps[] = {
{ "length", 0, JSPROP_SHARED | JSPROP_READONLY | JSPROP_PERMANENT, JS_PSG("length",
JSOP_WRAPPER(ArrayType::LengthGetter), JSOP_NULLWRAPPER }, (Property<ArrayType::IsArrayOrArrayType, ArrayType::LengthGetter>::Fun),
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } JSPROP_PERMANENT),
JS_PS_END
}; };
static const JSFunctionSpec sStructFunction = static const JSFunctionSpec sStructFunction =
JS_FN("StructType", StructType::Create, 2, CTYPESCTOR_FLAGS); JS_FN("StructType", StructType::Create, 2, CTYPESCTOR_FLAGS);
static const JSPropertySpec sStructProps[] = { static const JSPropertySpec sStructProps[] = {
{ "fields", 0, CTYPESPROP_FLAGS, JS_PSG("fields",
JSOP_WRAPPER(StructType::FieldsArrayGetter), JSOP_NULLWRAPPER }, (Property<StructType::IsStruct, StructType::FieldsArrayGetter>::Fun),
{ 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } CTYPESACC_FLAGS),
JS_PS_END
}; };
static const JSFunctionSpec sStructFunctions[] = { static const JSFunctionSpec sStructFunctions[] = {
@ -4444,35 +4452,50 @@ ArrayType::BuildFFIType(JSContext* cx, JSObject* obj)
} }
bool bool
ArrayType::ElementTypeGetter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp) ArrayType::IsArrayType(HandleValue v)
{ {
if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_array) { if (!v.isObject())
JS_ReportError(cx, "not an ArrayType");
return false; return false;
} JSObject* obj = &v.toObject();
return CType::IsCType(obj) && CType::GetTypeCode(obj) == TYPE_array;
}
vp.set(JS_GetReservedSlot(obj, SLOT_ELEMENT_T)); bool
JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp)); ArrayType::IsArrayOrArrayType(HandleValue v)
{
if (!v.isObject())
return false;
JSObject* obj = &v.toObject();
// Allow both CTypes and CDatas of the ArrayType persuasion by extracting the
// CType if we're dealing with a CData.
if (CData::IsCData(obj)) {
obj = CData::GetCType(obj);
}
return CType::IsCType(obj) && CType::GetTypeCode(obj) == TYPE_array;
}
bool
ArrayType::ElementTypeGetter(JSContext* cx, JS::CallArgs args)
{
RootedObject obj(cx, &args.thisv().toObject());
args.rval().set(JS_GetReservedSlot(obj, SLOT_ELEMENT_T));
MOZ_ASSERT(args.rval().isObject());
return true; return true;
} }
bool bool
ArrayType::LengthGetter(JSContext* cx, HandleObject obj_, HandleId idval, MutableHandleValue vp) ArrayType::LengthGetter(JSContext* cx, JS::CallArgs args)
{ {
JSObject *obj = obj_; JSObject *obj = &args.thisv().toObject();
// This getter exists for both CTypes and CDatas of the ArrayType persuasion. // This getter exists for both CTypes and CDatas of the ArrayType persuasion.
// If we're dealing with a CData, get the CType from it. // If we're dealing with a CData, get the CType from it.
if (CData::IsCData(obj)) if (CData::IsCData(obj))
obj = CData::GetCType(obj); obj = CData::GetCType(obj);
if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_array) { args.rval().set(JS_GetReservedSlot(obj, SLOT_LENGTH));
JS_ReportError(cx, "not an ArrayType"); JS_ASSERT(args.rval().isNumber() || args.rval().isUndefined());
return false;
}
vp.set(JS_GetReservedSlot(obj, SLOT_LENGTH));
JS_ASSERT(vp.isNumber() || vp.isUndefined());
return true; return true;
} }
@ -5124,33 +5147,39 @@ StructType::BuildFieldsArray(JSContext* cx, JSObject* obj)
return fieldsProp; return fieldsProp;
} }
bool /* static */ bool
StructType::FieldsArrayGetter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp) StructType::IsStruct(HandleValue v)
{ {
if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_struct) { if (!v.isObject())
JS_ReportError(cx, "not a StructType");
return false; return false;
} JSObject* obj = &v.toObject();
return CType::IsCType(obj) && CType::GetTypeCode(obj) == TYPE_struct;
}
vp.set(JS_GetReservedSlot(obj, SLOT_FIELDS)); bool
StructType::FieldsArrayGetter(JSContext* cx, JS::CallArgs args)
{
RootedObject obj(cx, &args.thisv().toObject());
args.rval().set(JS_GetReservedSlot(obj, SLOT_FIELDS));
if (!CType::IsSizeDefined(obj)) { if (!CType::IsSizeDefined(obj)) {
JS_ASSERT(JSVAL_IS_VOID(vp)); MOZ_ASSERT(args.rval().isUndefined());
return true; return true;
} }
if (JSVAL_IS_VOID(vp)) { if (args.rval().isUndefined()) {
// Build the 'fields' array lazily. // Build the 'fields' array lazily.
JSObject* fields = BuildFieldsArray(cx, obj); JSObject* fields = BuildFieldsArray(cx, obj);
if (!fields) if (!fields)
return false; return false;
JS_SetReservedSlot(obj, SLOT_FIELDS, OBJECT_TO_JSVAL(fields)); JS_SetReservedSlot(obj, SLOT_FIELDS, OBJECT_TO_JSVAL(fields));
vp.setObject(*fields); args.rval().setObject(*fields);
} }
JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp) && MOZ_ASSERT(args.rval().isObject());
JS_IsArrayObject(cx, JSVAL_TO_OBJECT(vp))); MOZ_ASSERT(JS_IsArrayObject(cx, &args.rval().toObject()));
return true; return true;
} }

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

@ -1334,8 +1334,8 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
// Check that the shared properties and functions on 't.prototype.__proto__' // Check that the shared properties and functions on 't.prototype.__proto__'
// (and thus also 't.prototype') throw. // (and thus also 't.prototype') throw.
for each (let p in instanceProps) { for each (let p in instanceProps) {
do_check_throws(function() { t.prototype.__proto__[p]; }, Error); do_check_throws(function() { t.prototype.__proto__[p]; }, TypeError);
do_check_throws(function() { t.prototype[p]; }, Error); do_check_throws(function() { t.prototype[p]; }, TypeError);
} }
for each (let f in instanceFns) { for each (let f in instanceFns) {
do_check_throws(function() { t.prototype.__proto__[f]() }, Error); do_check_throws(function() { t.prototype.__proto__[f]() }, Error);