Adopt EventEmitter class instead of injecting Signal methods

Introduce a new class, EventEmitter, which implements signal
handling for pure JavaScript classes. EventEmitter still
utilizes GJS' addSignalMethods internally.

EventEmitter allows static typechecking to understand the
structure of event-emitting JS classes and makes creating
child classes simpler.

The name 'EventEmitter' mirrors a common name for this pattern
in Node and in JS libraries.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2043>
This commit is contained in:
Evan Welsh
2022-07-04 18:30:44 -04:00
parent 9e30afe678
commit a88e59c1a8
39 changed files with 204 additions and 169 deletions

View File

@ -3,7 +3,7 @@
const { Clutter, Gio, GLib, GObject, IBus, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const Signals = imports.signals;
const Signals = imports.misc.signals;
const IBusManager = imports.misc.ibusManager;
const KeyboardManager = imports.misc.keyboardManager;
@ -32,8 +32,10 @@ class LayoutMenuItem extends PopupMenu.PopupBaseMenuItem {
}
});
var InputSource = class {
var InputSource = class extends Signals.EventEmitter {
constructor(type, id, displayName, shortName, index) {
super();
this.type = type;
this.id = id;
this.displayName = displayName;
@ -69,7 +71,6 @@ var InputSource = class {
return engineDesc.layout;
}
};
Signals.addSignalMethods(InputSource.prototype);
var InputSourcePopup = GObject.registerClass(
class InputSourcePopup extends SwitcherPopup.SwitcherPopup {
@ -135,8 +136,10 @@ class InputSourceSwitcher extends SwitcherPopup.SwitcherList {
}
});
var InputSourceSettings = class {
var InputSourceSettings = class extends Signals.EventEmitter {
constructor() {
super();
if (this.constructor === InputSourceSettings)
throw new TypeError(`Cannot instantiate abstract class ${this.constructor.name}`);
}
@ -173,7 +176,6 @@ var InputSourceSettings = class {
return false;
}
};
Signals.addSignalMethods(InputSourceSettings.prototype);
var InputSourceSystemSettings = class extends InputSourceSettings {
constructor() {
@ -300,8 +302,10 @@ var InputSourceSessionSettings = class extends InputSourceSettings {
}
};
var InputSourceManager = class {
var InputSourceManager = class extends Signals.EventEmitter {
constructor() {
super();
// All valid input sources currently in the gsettings
// KEY_INPUT_SOURCES list indexed by their index there
this._inputSources = {};
@ -771,7 +775,6 @@ var InputSourceManager = class {
return this._keyboardManager;
}
};
Signals.addSignalMethods(InputSourceManager.prototype);
let _inputSourceManager = null;

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NMApplet */
const { Clutter, Gio, GLib, GObject, Meta, NM, Polkit, St } = imports.gi;
const Signals = imports.signals;
const Signals = imports.misc.signals;
const Animation = imports.ui.animation;
const Main = imports.ui.main;
@ -107,8 +107,10 @@ function launchSettingsPanel(panel, ...args) {
}
}
var NMConnectionItem = class {
var NMConnectionItem = class extends Signals.EventEmitter {
constructor(section, connection) {
super();
this._section = section;
this._connection = connection;
this._activeConnection = null;
@ -193,10 +195,11 @@ var NMConnectionItem = class {
this._sync();
}
};
Signals.addSignalMethods(NMConnectionItem.prototype);
var NMConnectionSection = class NMConnectionSection {
var NMConnectionSection = class NMConnectionSection extends Signals.EventEmitter {
constructor(client) {
super();
if (this.constructor === NMConnectionSection)
throw new TypeError(`Cannot instantiate abstract type ${this.constructor.name}`);
@ -320,7 +323,6 @@ var NMConnectionSection = class NMConnectionSection {
this._sync();
}
};
Signals.addSignalMethods(NMConnectionSection.prototype);
var NMConnectionDevice = class NMConnectionDevice extends NMConnectionSection {
constructor(client, device) {
@ -1242,8 +1244,10 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
}
});
var NMDeviceWireless = class {
var NMDeviceWireless = class extends Signals.EventEmitter {
constructor(client, device) {
super();
this._client = client;
this._device = device;
@ -1433,7 +1437,6 @@ var NMDeviceWireless = class {
return 'network-wireless-no-route-symbolic';
}
};
Signals.addSignalMethods(NMDeviceWireless.prototype);
var NMWireguardItem = class extends NMConnectionItem {
_buildUI() {
@ -1657,7 +1660,6 @@ var NMVpnSection = class extends NMConnectionSection {
return '';
}
};
Signals.addSignalMethods(NMVpnSection.prototype);
var DeviceCategory = class extends PopupMenu.PopupMenuSection {
constructor(category) {

View File

@ -2,7 +2,7 @@
/* exported Indicator */
const { Gio, GObject } = imports.gi;
const Signals = imports.signals;
const Signals = imports.misc.signals;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
@ -16,18 +16,20 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill';
const RfkillManagerInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Rfkill');
const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface);
var RfkillManager = class {
var RfkillManager = class extends Signals.EventEmitter {
constructor() {
super();
this._proxy = new RfkillManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
(proxy, error) => {
if (error) {
log(error.message);
return;
}
this._proxy.connect('g-properties-changed',
this._changed.bind(this));
this._changed();
});
(proxy, error) => {
if (error) {
log(error.message);
return;
}
this._proxy.connect('g-properties-changed',
this._changed.bind(this));
this._changed();
});
}
get airplaneMode() {
@ -50,7 +52,6 @@ var RfkillManager = class {
this.emit('airplane-mode-changed');
}
};
Signals.addSignalMethods(RfkillManager.prototype);
var _manager;
function getRfkillManager() {

View File

@ -4,7 +4,7 @@
// the following is a modified version of bolt/contrib/js/client.js
const { Gio, GLib, GObject, Polkit, Shell } = imports.gi;
const Signals = imports.signals;
const Signals = imports.misc.signals;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
@ -49,8 +49,10 @@ const BOLT_DBUS_CLIENT_IFACE = 'org.freedesktop.bolt1.Manager';
const BOLT_DBUS_NAME = 'org.freedesktop.bolt';
const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
var Client = class {
var Client = class extends Signals.EventEmitter {
constructor() {
super();
this._proxy = null;
this.probing = false;
this._getProxy();
@ -127,11 +129,12 @@ var Client = class {
return this._proxy.AuthMode;
}
};
Signals.addSignalMethods(Client.prototype);
/* helper class to automatically authorize new devices */
var AuthRobot = class {
var AuthRobot = class extends Signals.EventEmitter {
constructor(client) {
super();
this._client = client;
this._devicesToEnroll = [];
@ -217,7 +220,6 @@ var AuthRobot = class {
return GLib.SOURCE_REMOVE;
}
};
Signals.addSignalMethods(AuthRobot.prototype);
/* eof client.js */

View File

@ -2,7 +2,7 @@
/* exported Indicator */
const { Clutter, Gio, GLib, GObject, Gvc, St } = imports.gi;
const Signals = imports.signals;
const Signals = imports.misc.signals;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
@ -29,8 +29,10 @@ function getMixerControl() {
return _mixerControl;
}
var StreamSlider = class {
var StreamSlider = class extends Signals.EventEmitter {
constructor(control) {
super();
this._control = control;
this.item = new PopupMenu.PopupBaseMenuItem({ activate: false });
@ -213,7 +215,6 @@ var StreamSlider = class {
return maxVolume / this._control.get_vol_max_norm();
}
};
Signals.addSignalMethods(StreamSlider.prototype);
var OutputStreamSlider = class extends StreamSlider {
constructor(control) {