Search code examples
javascriptgnome-shell-extensions

After GNOME Shell extension's monkey-patching, this.parent is unexpected


For the raise-activated GNOME Shell 3.16 extension I'm trying to monkey-patch the AppSwitcherPopup._finish method. Like the original, the patched version calls this.parent:

function _modifiedFinish(timestamp) {
    // ...monkey-patched code...
    this.parent(timestamp);
}

function enable() {
    _originalFinish = AltTab.AppSwitcherPopup.prototype._finish;
    AltTab.AppSwitcherPopup.prototype._finish = _modifiedFinish;
}

(full code)

But I get this stack trace in the console (from running gnome-shell --replace):

(gnome-shell:24452): Gjs-WARNING **: JS ERROR: TypeError: The method '_keyReleaseEvent' is not on the superclass
_parent@resource:///org/gnome/gjs/modules/lang.js:129
_modifiedFinish@/home/lastorset/.local/share/gnome-shell/extensions/[email protected]/extension.js:34
SwitcherPopup<._keyReleaseEvent@resource:///org/gnome/shell/ui/switcherPopup.js:199
wrapper@resource:///org/gnome/gjs/modules/lang.js:169

In this case, SwitcherPopup._keyReleaseEvent is calling this, and this should be an instance of the AppSwitcherPopup subclass. I believe this.parent should be the same after patching—why is it now trying to call the caller? And for that matter, why doesn't that succeed?

I looked up the GJS code that generated this.parent, but I can't quite spot what's missing.


Solution

  • After digging a bit more I found a way to fix it. In the GJS class model, the parent function is actually looking for the method's owner's superclass in order to call the method of the same name. Looks like every GJS class has a wrapFunction helper that sets _owner. I used that to patch the function instead:

    AltTab.AppSwitcherPopup.prototype._finish = AltTab.AppSwitcherPopup.wrapFunction('_finish', _modifiedFinish);