
As they are only used by gstreamer for gst-inspect & other tools. Projects like Mutter/gtk have completely dropped them as well, so follow their path Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3505>
195 lines
5.2 KiB
JavaScript
195 lines
5.2 KiB
JavaScript
import GObject from 'gi://GObject';
|
|
|
|
import 'resource:///org/gnome/shell/ui/environment.js';
|
|
|
|
import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js';
|
|
|
|
const FIXED_NUMBER = 42;
|
|
|
|
class Object1 {
|
|
count = 0;
|
|
|
|
getNumber() {
|
|
return FIXED_NUMBER;
|
|
}
|
|
|
|
getCount() {
|
|
return ++this.count;
|
|
}
|
|
}
|
|
|
|
class GObject1 extends GObject.Object {
|
|
static [GObject.properties] = {
|
|
'plonked': GObject.ParamSpec.boolean(
|
|
'plonked', null, null,
|
|
GObject.ParamFlags.READWRITE,
|
|
false),
|
|
};
|
|
|
|
static {
|
|
GObject.registerClass(this);
|
|
}
|
|
}
|
|
|
|
describe('InjectionManager', () => {
|
|
const INJECTIONS = {
|
|
'getNumber': originalMethod => {
|
|
return function () {
|
|
// eslint-disable-next-line no-invalid-this
|
|
const num = originalMethod.call(this);
|
|
return 2 * num;
|
|
};
|
|
},
|
|
'getCount': () => {
|
|
return function () {
|
|
return FIXED_NUMBER;
|
|
};
|
|
},
|
|
'getOtherNumber': () => {
|
|
return function () {
|
|
return FIXED_NUMBER;
|
|
};
|
|
},
|
|
};
|
|
|
|
let injectionManager;
|
|
|
|
function injectAll(obj) {
|
|
for (const func in INJECTIONS) {
|
|
injectionManager.overrideMethod(obj,
|
|
func, INJECTIONS[func]);
|
|
}
|
|
}
|
|
|
|
beforeEach(() => {
|
|
injectionManager = new InjectionManager();
|
|
});
|
|
|
|
afterEach(() => {
|
|
injectionManager.clear();
|
|
});
|
|
|
|
it('can extend prototype methods', () => {
|
|
injectionManager.overrideMethod(Object1.prototype,
|
|
'getNumber', INJECTIONS['getNumber']);
|
|
|
|
const obj = new Object1();
|
|
expect(obj.getNumber()).toEqual(2 * FIXED_NUMBER);
|
|
});
|
|
|
|
it('can replace prototype methods', () => {
|
|
injectionManager.overrideMethod(Object1.prototype,
|
|
'getCount', INJECTIONS['getCount']);
|
|
|
|
const obj = new Object1();
|
|
expect(obj.getCount()).toEqual(42);
|
|
expect(obj.count).toEqual(0);
|
|
});
|
|
|
|
it('can inject methods into prototypes', () => {
|
|
injectionManager.overrideMethod(Object1.prototype,
|
|
'getOtherNumber', INJECTIONS['getOtherNumber']);
|
|
|
|
const obj = new Object1();
|
|
expect(obj.getOtherNumber()).toEqual(42);
|
|
});
|
|
|
|
it('can undo prototype injections', () => {
|
|
injectAll(Object1.prototype);
|
|
|
|
injectionManager.clear();
|
|
|
|
const obj = new Object1();
|
|
expect(obj.getNumber()).toEqual(FIXED_NUMBER);
|
|
expect(obj.getCount()).toEqual(obj.count);
|
|
expect(obj.count).toBeGreaterThan(0);
|
|
expect(() => obj.getOtherNumber()).toThrow();
|
|
});
|
|
|
|
it('can extend instance methods', () => {
|
|
const obj = new Object1();
|
|
injectionManager.overrideMethod(obj,
|
|
'getNumber', INJECTIONS['getNumber']);
|
|
|
|
expect(obj.getNumber()).toEqual(2 * FIXED_NUMBER);
|
|
});
|
|
|
|
it('can replace instance methods', () => {
|
|
const obj = new Object1();
|
|
injectionManager.overrideMethod(obj,
|
|
'getCount', INJECTIONS['getCount']);
|
|
|
|
expect(obj.getCount()).toEqual(42);
|
|
expect(obj.count).toEqual(0);
|
|
});
|
|
|
|
it('can inject methods into instances', () => {
|
|
const obj = new Object1();
|
|
injectionManager.overrideMethod(obj,
|
|
'getOtherNumber', INJECTIONS['getOtherNumber']);
|
|
|
|
expect(obj.getOtherNumber()).toEqual(42);
|
|
});
|
|
|
|
it('can undo instance injections', () => {
|
|
const obj = new Object1();
|
|
|
|
injectAll(obj);
|
|
|
|
injectionManager.clear();
|
|
|
|
expect(obj.getNumber()).toEqual(FIXED_NUMBER);
|
|
expect(obj.getCount()).toEqual(obj.count);
|
|
expect(obj.count).toBeGreaterThan(0);
|
|
expect(() => obj.getOtherNumber()).toThrow();
|
|
});
|
|
|
|
it('can restore an original method', () => {
|
|
const obj = new Object1();
|
|
|
|
injectAll(obj);
|
|
|
|
expect(obj.getNumber()).toEqual(2 * FIXED_NUMBER);
|
|
|
|
injectionManager.restoreMethod(obj, 'getNumber');
|
|
expect(obj.getNumber()).toEqual(FIXED_NUMBER);
|
|
});
|
|
|
|
it('can extend a GObject vfunc', () => {
|
|
const gobj = new GObject1();
|
|
let vfuncCalled;
|
|
|
|
injectionManager.overrideMethod(
|
|
GObject1.prototype, 'vfunc_set_property', originalMethod => {
|
|
return function (...args) {
|
|
// eslint-disable-next-line no-invalid-this
|
|
originalMethod.apply(this, args);
|
|
vfuncCalled = true;
|
|
};
|
|
});
|
|
|
|
vfuncCalled = false;
|
|
gobj.set_property('plonked', true);
|
|
expect(vfuncCalled).toEqual(true);
|
|
});
|
|
|
|
it('can restore a GObject vfunc', () => {
|
|
const gobj = new GObject1();
|
|
let vfuncCalled;
|
|
|
|
injectionManager.overrideMethod(
|
|
GObject1.prototype, 'vfunc_set_property', originalMethod => {
|
|
return function (...args) {
|
|
// eslint-disable-next-line no-invalid-this
|
|
originalMethod.apply(this, args);
|
|
vfuncCalled = true;
|
|
};
|
|
});
|
|
injectionManager.clear();
|
|
|
|
vfuncCalled = false;
|
|
gobj.set_property('plonked', true);
|
|
expect(vfuncCalled).toEqual(false);
|
|
});
|
|
});
|