Skip to content

super.<vfunc>() recurses for invoker-backed vfuncs (e.g. get_request_mode) #452

Description

@romgrk

Background

#451 adds super.<vfunc>() chain-up by installing a bridge on the parent GI class's prototype that invokes the parent's native vfunc implementation. This works for pure vfuncs — ones without a same-named public invoker method (snapshot_line, query_data, begin, end, constructed, …).

Problem

For invoker-backed vfuncs it recurses instead of chaining. Example: GtkWidget.get_request_mode is both a vfunc and a public method gtk_widget_get_request_mode. Gtk.Widget.prototype.getRequestMode therefore already exists as the invoker method, which dispatches virtually (GTK_WIDGET_GET_CLASS(self)->get_request_mode(self)). From a subclass override:

class W extends Gtk.Widget {
  getRequestMode() { return super.getRequestMode() } // -> invoker -> our own override -> ∞
}

super.getRequestMode() resolves to the pre-existing invoker method (not our bridge — the bridge is skipped because the prototype already owns that key), and the invoker re-dispatches through the instance's vtable back into the override → RangeError: Maximum call stack size exceeded.

So in #451 the bridge is intentionally not installed when the parent prototype already owns the key, and invoker-backed vfuncs are documented as unsupported via super.

Why this is the same collision gjs avoids

gjs sidesteps this by naming vfunc overrides vfunc_get_request_mode (distinct from the method get_request_mode), so chain-up via super.vfunc_get_request_mode() never collides with the invoker. node-gtk maps overrides to the plain camelCase name, so the method and the chain-up share one name.

Possible directions

  1. Expose an explicit escape hatch that always targets the parent impl regardless of name collision, e.g. gi.callParentVFunc(this, 'getRequestMode', ...args) (internally the same CallVFunc resolving through the parent GType). Reliable for invoker-backed vfuncs; opt-in.
  2. Adopt a vfunc_-prefixed convention for overrides/chain-up (larger change; diverges from node-gtk's current plain-name override mapping).
  3. Detect the collision at registerClass time and console.warn that super.<name>() will recurse for that vfunc.

Option 1 is the least invasive and composes with the existing CallVFunc. Filing as follow-up to #451; the pure-vfunc case (which covers the motivating GtkSourceView gutter use) already works.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions