mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
add patch/unpatch utility methods
This commit is contained in:
@@ -125,3 +125,54 @@ export function shallowEqual(objA, objB) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function patch(C: any, patchName: string, patch: any) {
|
||||||
|
const proto = C.prototype;
|
||||||
|
if (!proto.__patches) {
|
||||||
|
proto.__patches = {
|
||||||
|
origMethods: {},
|
||||||
|
patches: {},
|
||||||
|
current: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (proto.__patches.patches[patchName]) {
|
||||||
|
throw new Error(`Patch [${patchName}] already exists`);
|
||||||
|
}
|
||||||
|
proto.__patches.patches[patchName] = patch;
|
||||||
|
applyPatch(proto, patch);
|
||||||
|
proto.__patches.current.push(patchName);
|
||||||
|
|
||||||
|
function applyPatch(proto, patch) {
|
||||||
|
Object.keys(patch).forEach(function(methodName) {
|
||||||
|
const method = patch[methodName];
|
||||||
|
if (typeof method === "function") {
|
||||||
|
const original = proto[methodName];
|
||||||
|
if (!(methodName in proto.__patches.origMethods)) {
|
||||||
|
proto.__patches.origMethods[methodName] = original;
|
||||||
|
}
|
||||||
|
proto[methodName] = function(...args) {
|
||||||
|
this._super = original;
|
||||||
|
return method.call(this, ...args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unpatch(C: any, patchName: string) {
|
||||||
|
const proto = C.prototype;
|
||||||
|
const patchInfo = proto.__patches;
|
||||||
|
delete proto.__patches;
|
||||||
|
|
||||||
|
// reset to original
|
||||||
|
for (let k in patchInfo.origMethods) {
|
||||||
|
proto[k] = patchInfo.origMethods[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply other patches
|
||||||
|
for (let name of patchInfo.current) {
|
||||||
|
if (name !== patchName) {
|
||||||
|
patch(C, name, patchInfo.patches[name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+56
-1
@@ -5,7 +5,9 @@ import {
|
|||||||
memoize,
|
memoize,
|
||||||
debounce,
|
debounce,
|
||||||
findInTree,
|
findInTree,
|
||||||
shallowEqual
|
shallowEqual,
|
||||||
|
patch,
|
||||||
|
unpatch
|
||||||
} from "../src/utils";
|
} from "../src/utils";
|
||||||
|
|
||||||
describe("escape", () => {
|
describe("escape", () => {
|
||||||
@@ -103,3 +105,56 @@ describe("shallowEqual", () => {
|
|||||||
expect(shallowEqual({ a: 1 }, ["a"])).toBe(false);
|
expect(shallowEqual({ a: 1 }, ["a"])).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("patch/unpatch", () => {
|
||||||
|
test("can monkey patch a class", () => {
|
||||||
|
class Test {
|
||||||
|
n = 1;
|
||||||
|
|
||||||
|
doSomething(): string {
|
||||||
|
return "hey";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
patch(Test, "some_custo", {
|
||||||
|
doSomething(): string {
|
||||||
|
this.n = this.n + 1;
|
||||||
|
return this._super();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const t = new Test();
|
||||||
|
expect(t.n).toBe(1);
|
||||||
|
expect(t.doSomething()).toBe("hey");
|
||||||
|
expect(t.n).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("cannot patch a class twice with same patch name", () => {
|
||||||
|
class Test {}
|
||||||
|
|
||||||
|
patch(Test, "some_custo", {});
|
||||||
|
expect(() => {
|
||||||
|
patch(Test, "some_custo", {});
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("can unpatch a class", () => {
|
||||||
|
class Test {
|
||||||
|
doSomething(): number {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
patch(Test, "some_custo", {
|
||||||
|
doSomething(): number {
|
||||||
|
return this._super() + 2;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const t = new Test();
|
||||||
|
expect(t.doSomething()).toBe(3);
|
||||||
|
|
||||||
|
unpatch(Test, "some_custo");
|
||||||
|
expect(t.doSomething()).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user