diff --git a/src/bindings/girepository.js b/src/bindings/girepository.js index 8e61efe..0b1cc06 100644 --- a/src/bindings/girepository.js +++ b/src/bindings/girepository.js @@ -28,6 +28,7 @@ const { g } = openLib(libName("girepository-1.0", 1), { }, base_info: { get_name: $string($pointer), + get_container: $pointer($pointer), is_deprecated: $bool($pointer), get_type: $i32($pointer), ref: $void($pointer), @@ -75,6 +76,7 @@ const { g } = openLib(libName("girepository-1.0", 1), { get_n_fields: $i32($pointer), get_field: $pointer($pointer, $i32), get_size: $i32($pointer), + find_field: $pointer($pointer, $string), }, object_info: { get_n_methods: $i32($pointer), @@ -110,7 +112,7 @@ const { g } = openLib(libName("girepository-1.0", 1), { field_info: { get_flags: $i32($pointer), get_type: $pointer($pointer), - get_field: $i32($pointer,$pointer, $buffer), + get_field: $bool($pointer,$pointer, $buffer), set_field: $i32($pointer,$pointer, $buffer), get_offset: $i32($pointer), }, diff --git a/src/types/callable.js b/src/types/callable.js index 4226c4e..8d00a8f 100644 --- a/src/types/callable.js +++ b/src/types/callable.js @@ -1,3 +1,4 @@ +import { cast_ptr_u64, deref_buf } from "../base_utils/convert.ts"; import { GIDirection, GIFunctionInfoFlags, @@ -11,6 +12,7 @@ import { createConstructor } from "./callable/constructor.js"; import { createFunction } from "./callable/function.js"; import { createMethod } from "./callable/method.js"; import { createVFunc } from "./callable/vfunc.js"; +import { createCallback } from "./callback.js"; export function createArg(info) { const type = g.arg_info.get_type(info); @@ -120,19 +122,44 @@ export function handleCallable(target, info) { } case GIInfoType.VFUNC: { - if (Object.hasOwn(target.prototype, name)) { - return; - } - const value = createVFunc(info); Object.defineProperty(target.prototype, `vfunc_` + name, { enumerable: true, - value(...args) { - return value( - Reflect.getOwnMetadata("gi:ref", this), + get() { + return (...args) => { + return value( + Reflect.getOwnMetadata("gi:ref", this), + Reflect.getOwnMetadata("gi:gtype", this.constructor), + ...args, + ); + }; + }, + set(value) { + const cName = g.base_info.get_name(info); + + const objectInfo = g.base_info.get_container(info); + const classStruct = g.object_info.get_class_struct(objectInfo); + const fieldInfo = g.struct_info.find_field(classStruct, cName); + + if (!fieldInfo) { + // This vfunc doesn't have a corresponding field in the class struct + return; + } + + const klass = g.type_class.ref( Reflect.getOwnMetadata("gi:gtype", this.constructor), - ...args, ); + + const cb = createCallback(info, value); + const offset = g.field_info.get_offset(fieldInfo); + const dataView = new ExtendedDataView( + deref_buf( + klass, + offset + 8, + offset, + ), + ); + dataView.setBigUint64(cast_ptr_u64(cb.pointer)); }, }); return;