Bug 704147 - Make ctypes function pointers callable via call and apply. r=bholley

This commit is contained in:
Josh Matthews 2012-02-14 16:26:05 -05:00
parent b6361415fa
commit 6bc17c8afa
2 changed files with 34 additions and 9 deletions

View File

@ -411,6 +411,12 @@ static JSPropertySpec sFunctionProps[] = {
{ 0, 0, 0, NULL, NULL }
};
static JSFunctionSpec sFunctionInstanceFunctions[] = {
JS_FN("call", js_fun_call, 1, CDATAFN_FLAGS),
JS_FN("apply", js_fun_apply, 2, CDATAFN_FLAGS),
JS_FS_END
};
static JSClass sInt64ProtoClass = {
"Int64",
0,
@ -857,8 +863,8 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
return false;
js::AutoObjectRooter sroot(cx, protos[SLOT_STRUCTDATAPROTO]);
if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
sFunctionFunction, NULL, sFunctionProps, NULL, NULL,
if (!InitTypeConstructor(cx, parent, CTypeProto, protos[SLOT_POINTERDATAPROTO],
sFunctionFunction, NULL, sFunctionProps, sFunctionInstanceFunctions, NULL,
protos[SLOT_FUNCTIONPROTO], protos[SLOT_FUNCTIONDATAPROTO]))
return false;
js::AutoObjectRooter froot(cx, protos[SLOT_FUNCTIONDATAPROTO]);
@ -3319,11 +3325,11 @@ PointerType::CreateInternal(JSContext* cx, JSObject* baseType)
return JSVAL_TO_OBJECT(slot);
// Get ctypes.PointerType.prototype and the common prototype for CData objects
// of this type.
JSObject* typeProto;
JSObject* dataProto;
typeProto = CType::GetProtoFromType(baseType, SLOT_POINTERPROTO);
dataProto = CType::GetProtoFromType(baseType, SLOT_POINTERDATAPROTO);
// of this type, or ctypes.FunctionType.prototype for function pointers.
CTypeProtoSlot slotId = CType::GetTypeCode(baseType) == TYPE_function ?
SLOT_FUNCTIONDATAPROTO : SLOT_POINTERDATAPROTO;
JSObject* dataProto = CType::GetProtoFromType(baseType, slotId);
JSObject* typeProto = CType::GetProtoFromType(baseType, SLOT_POINTERPROTO);
// Create a new CType object with the common properties and slots.
JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_pointer,

View File

@ -1328,7 +1328,10 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
// equal to 't2.prototype.__proto__' where 't2' is a different CType
// constructed from 'c'.
do_check_true(t.prototype.__proto__ === t2.prototype.__proto__);
do_check_true(t.prototype.__proto__.__proto__ === ctypes.CData.prototype);
if (t instanceof ctypes.FunctionType)
do_check_true(t.prototype.__proto__.__proto__ === ctypes.PointerType.prototype.prototype);
else
do_check_true(t.prototype.__proto__.__proto__ === ctypes.CData.prototype);
do_check_true(t.prototype instanceof ctypes.CData);
do_check_true(t.prototype.constructor === t);
@ -1359,7 +1362,10 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
do_check_throws(function() { t.prototype[p]; }, Error);
// Make sure we can access 'prototype' on a CTypeProto.
do_check_true(Object.getPrototypeOf(c.prototype.prototype) === ctypes.CType.prototype.prototype);
if (t instanceof ctypes.FunctionType)
do_check_true(Object.getPrototypeOf(c.prototype.prototype) === ctypes.PointerType.prototype.prototype);
else
do_check_true(Object.getPrototypeOf(c.prototype.prototype) === ctypes.CType.prototype.prototype);
// Test that an instance 'd' of 't' is a CData.
if (t.__proto__ != ctypes.FunctionType.prototype) {
@ -2289,6 +2295,19 @@ function run_function_tests(library)
// Test that we can call ptr().
do_check_eq(ptr("function pointers rule!"), 23);
// Test that we can call via call and apply
do_check_eq(ptr.call(null, "function pointers rule!"), 23);
do_check_eq(ptr.apply(null, ["function pointers rule!"]), 23);
// Test that we cannot call non-function pointers via call and apply
let p_t = ctypes.PointerType(ctypes.int32_t);
let p = p_t();
do_check_throws(function() { p.call(null, "woo"); }, TypeError);
do_check_throws(function() { p.apply(null, ["woo"]); }, TypeError);
// Test the function pointers still behave as regular pointers
do_check_false(ptr.isNull(), "PointerType methods should still be valid");
// Test that library.declare() returns data of type FunctionType.ptr, and that
// it is immutable.
do_check_true(test_ansi_len.constructor.targetType.__proto__ ===