diff --git a/addons/hr/static/src/messaging_service_patch.js b/addons/hr/static/src/messaging_service_patch.js index 78ae134bb3c..43d0d66e813 100644 --- a/addons/hr/static/src/messaging_service_patch.js +++ b/addons/hr/static/src/messaging_service_patch.js @@ -2,11 +2,11 @@ import { Messaging } from "@mail/core/common/messaging_service"; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(Messaging.prototype, "hr", { +patch(Messaging.prototype, { setup(...args) { - this._super(...args); + super.setup(...args); this.store.employees = {}; }, }); diff --git a/addons/hr/static/src/thread_service_patch.js b/addons/hr/static/src/thread_service_patch.js index a834e22c33b..bbced6e6a8c 100644 --- a/addons/hr/static/src/thread_service_patch.js +++ b/addons/hr/static/src/thread_service_patch.js @@ -2,15 +2,14 @@ import { _t } from "@web/core/l10n/translation"; import { ThreadService } from "@mail/core/common/thread_service"; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; /** @type {import("@mail/core/common/thread_service").ThreadService} */ const threadServicePatch = { async getChat(person) { const { employeeId } = person; - const _super = this._super.bind(this); if (!employeeId) { - return _super(person); + return super.getChat(person); } let employee = this.store.employees[employeeId]; if (!employee) { @@ -49,8 +48,8 @@ const threadServicePatch = { ); return; } - return _super({ userId: employee.user_id }); + return super.getChat({ userId: employee.user_id }); }, }; -patch(ThreadService.prototype, "hr", threadServicePatch); +patch(ThreadService.prototype, threadServicePatch); diff --git a/addons/mass_mailing/static/tests/mass_mailing_html_tests.js b/addons/mass_mailing/static/tests/mass_mailing_html_tests.js index 4a52703436b..e27dd4c0deb 100644 --- a/addons/mass_mailing/static/tests/mass_mailing_html_tests.js +++ b/addons/mass_mailing/static/tests/mass_mailing_html_tests.js @@ -9,7 +9,6 @@ import { nextTick, patchWithCleanup, } from "@web/../tests/helpers/utils"; -import * as legacyTestUtils from "@web/../tests/legacy/helpers/test_utils"; import { assets } from "@web/core/assets"; import { Wysiwyg } from '@web_editor/js/wysiwyg/wysiwyg'; @@ -47,7 +46,7 @@ QUnit.module('field html', (hooks) => { serverData = { models }; setupViewRegistries(); - legacyTestUtils.mock.patch(Wysiwyg.prototype, { + patchWithCleanup(Wysiwyg.prototype, { async _getColorpickerTemplate() { return weTestUtils.COLOR_PICKER_TEMPLATE; }, @@ -61,9 +60,6 @@ QUnit.module('field html', (hooks) => { }, }); }); - hooks.afterEach(() => { - legacyTestUtils.mock.unpatch(Wysiwyg.prototype); - }); QUnit.test('save arch and html', async function (assert) { assert.expect(2); diff --git a/addons/test_website/static/tests/tours/image_upload_progress.js b/addons/test_website/static/tests/tours/image_upload_progress.js index 84e941cd89c..22f156dc973 100644 --- a/addons/test_website/static/tests/tours/image_upload_progress.js +++ b/addons/test_website/static/tests/tours/image_upload_progress.js @@ -3,10 +3,10 @@ import wTourUtils from "@website/js/tours/tour_utils"; import { FileSelectorControlPanel } from "@web_editor/components/media_dialog/file_selector"; -import { patch, unpatch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; let patchWithError = false; -const patchMediaDialog = () => patch(FileSelectorControlPanel.prototype, 'test_website.mock_image_widgets', { +const patchMediaDialog = () => patch(FileSelectorControlPanel.prototype, { async onChangeFileInput() { const getFileFromB64 = (fileData) => { const binary = atob(fileData[2]); @@ -17,7 +17,7 @@ const patchMediaDialog = () => patch(FileSelectorControlPanel.prototype, 'test_w } return new File([arr], fileData[1], {type: fileData[0]}); }; - + let files = [ getFileFromB64(['image/vnd.microsoft.icon', 'icon.ico', "AAABAAEAAQEAAAEAIAAwAAAAFgAAACgAAAABAAAAAgAAAAEAIAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA=="]), getFileFromB64(['image/webp', 'image.webp', "UklGRhwAAABXRUJQVlA4TBAAAAAvE8AEAAfQhuh//wMR0f8A"]), @@ -36,13 +36,13 @@ const patchMediaDialog = () => patch(FileSelectorControlPanel.prototype, 'test_w } }); -const unpatchMediaDialog = () => unpatch(FileSelectorControlPanel.prototype, 'test_website.mock_image_widgets'); +let unpatchMediaDialog = null; const setupSteps = [{ content: "reload to load patch", trigger: ".o_website_preview", run: () => { - patchMediaDialog(); + unpatchMediaDialog = patchMediaDialog(); }, }, { content: "drop a snippet", diff --git a/addons/web/static/src/legacy/js/core/utils.js b/addons/web/static/src/legacy/js/core/utils.js index b7c28722b8e..b08c8d2e9f8 100644 --- a/addons/web/static/src/legacy/js/core/utils.js +++ b/addons/web/static/src/legacy/js/core/utils.js @@ -205,8 +205,6 @@ var diacriticsMap = { '\u0225': 'z','\u0240': 'z','\u2C6C': 'z','\uA763': 'z', }; -const patchMap = new WeakMap(); - /** * Helper function returning an extraction handler to use on array elements to * return a certain attribute or mutated form of the element. @@ -735,82 +733,6 @@ const utils = { return acc; }, []); }, - /** - * Patch an object and return a function that remove the patch - * when called. - * - * @param {Object} obj Object to patch - * @param {string} patchName - * @param {Object} patch - */ - patch:function (obj, patchName, patch) { - if (!patchMap.has(obj)) { - patchMap.set(obj, { - original: {}, - patches: [], - }); - } - const objDesc = patchMap.get(obj); - if (objDesc.patches.some(p => p.name === patchName)) { - throw new AlreadyDefinedPatchError(`Patch ${patchName} is already defined`); - } - objDesc.patches.push({ - name: patchName, - patch, - }); - - for (const k in patch) { - let prevDesc = null; - let proto = obj; - do { - prevDesc = Object.getOwnPropertyDescriptor(proto, k); - proto = Object.getPrototypeOf(proto); - } while (!prevDesc && proto); - - const newDesc = Object.getOwnPropertyDescriptor(patch, k); - if (!objDesc.original.hasOwnProperty(k)) { - objDesc.original[k] = Object.getOwnPropertyDescriptor(obj, k); - } - - if (prevDesc) { - const patchedFnName = `${k} (patch ${patchName})`; - - if (prevDesc.value && typeof newDesc.value === "function") { - makeIntermediateFunction("value", prevDesc, newDesc, patchedFnName); - } - if (prevDesc.get || prevDesc.set) { - // get and set are defined together. If they are both defined - // in the previous descriptor but only one in the new descriptor - // then the other will be undefined so we need to apply the - // previous descriptor in the new one. - newDesc.get = newDesc.get || prevDesc.get; - newDesc.set = newDesc.set || prevDesc.set; - if (prevDesc.get && typeof newDesc.get === "function") { - makeIntermediateFunction("get", prevDesc, newDesc, patchedFnName); - } - if (prevDesc.set && typeof newDesc.set === "function") { - makeIntermediateFunction("set", prevDesc, newDesc, patchedFnName); - } - } - } - - Object.defineProperty(obj, k, newDesc); - } - - function makeIntermediateFunction(key, prevDesc, newDesc, patchedFnName) { - const _superFn = prevDesc[key]; - const patchFn = newDesc[key]; - newDesc[key] = { - [patchedFnName](...args) { - const prevSuper = this._super; - this._super = _superFn.bind(this); - const result = patchFn.call(this, ...args); - this._super = prevSuper; - return result; - } - }[patchedFnName]; - } - }, /** * performs a half up rounding with a fixed amount of decimals, correcting for float loss of precision * See the corresponding float_round() in server/tools/float_utils.py for more info @@ -1016,42 +938,6 @@ const utils = { }); return casesensetive ? str : str.toLowerCase(); }, - /** - * We define here an unpatch function. This is mostly useful if we want to - * remove a patch. For example, for testing purposes - * - * @param {Object} obj - * @param {string} patchName - * @returns {Object} the removed patch - */ - unpatch: function (obj, patchName) { - const objDesc = patchMap.get(obj); - if (!objDesc || !objDesc.patches.some(p => p.name === patchName)) { - throw new UnknownPatchError(`Could not find patch ${patchName}`); - } - patchMap.delete(obj); - - // Restore original methods on the prototype and the class. - for (const k in objDesc.original) { - if (objDesc.original[k] === undefined) { - delete obj[k]; - } else { - Object.defineProperty(obj, k, objDesc.original[k]); - } - } - - // Re-apply the patches except the one to remove. - let removedPatch; - for (const patchDesc of objDesc.patches) { - if (patchDesc.name !== patchName) { - utils.patch(obj, patchDesc.name, patchDesc.patch); - } else { - removedPatch = patchDesc.patch; - } - } - - return removedPatch; - }, /** * @param {any} node * @param {any} strip_whitespace @@ -1168,10 +1054,8 @@ const utils = { }, }; -export const patch = utils.patch export const confine = utils.confine export const traverse = utils.traverse -export const unpatch = utils.unpatch export const is_email = utils.is_email export const sprintf = utils.sprintf export const groupBy = utils.groupBy diff --git a/addons/web/static/tests/core/utils/patch_tests.js b/addons/web/static/tests/core/utils/patch_tests.js index b7befbbe656..37a5f03d73f 100644 --- a/addons/web/static/tests/core/utils/patch_tests.js +++ b/addons/web/static/tests/core/utils/patch_tests.js @@ -1,7 +1,6 @@ /** @odoo-module **/ import { patch } from "@web/core/utils/patch"; -import legacyUtils from "@web/legacy/js/core/utils"; function makeBaseClass(assert, assertInSetup) { class BaseClass { @@ -1200,27 +1199,5 @@ QUnit.module("utils", () => { assert.verifySteps(["patched", "original"]); }); - - QUnit.test("patch an object with a legacy patch", async function (assert) { - const a = { - doSomething() { - assert.step("a"); - }, - }; - legacyUtils.patch(a, "a.patch.legacy", { - doSomething() { - this._super(); - assert.step("a.patch.legacy"); - }, - }); - patch(a, { - doSomething() { - super.doSomething(); - assert.step("a.patch"); - }, - }); - a.doSomething(); - assert.verifySteps(["a", "a.patch.legacy", "a.patch"]); - }); }); }); diff --git a/addons/web/static/tests/legacy/core/patch_tests.js b/addons/web/static/tests/legacy/core/patch_tests.js deleted file mode 100644 index 94ecb327aab..00000000000 --- a/addons/web/static/tests/legacy/core/patch_tests.js +++ /dev/null @@ -1,1214 +0,0 @@ -/** @odoo-module **/ - -import _utils from "@web/legacy/js/core/utils"; - -function makeBaseClass(assert, assertInSetup) { - class BaseClass { - constructor() { - this.setup(); - } - setup() { - this._dynamic = "base"; - - this.str = "base"; - this.obj = { base: "base" }; - this.arr = ["base"]; - - if (assertInSetup !== false) { - assert.step("base.setup"); - } - } - fn() { - assert.step("base.fn"); - } - async asyncFn() { - // also check this binding - assert.step(`base.${this.str}`); - } - get dynamic() { - return this._dynamic; - } - set dynamic(value) { - this._dynamic = value; - } - } - - BaseClass.staticStr = "base"; - BaseClass.staticObj = { base: "base" }; - BaseClass.staticArr = ["base"]; - BaseClass.staticFn = function () { - assert.step("base.staticFn"); - }; - - return BaseClass; -} - -QUnit.module('core', {}, function () { - - QUnit.module('patch', {}, function () { - QUnit.test('simple patch', async function (assert) { - assert.expect(5); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'base.fn', - 'patch.fn', - ]); - }); - - QUnit.test('two patches on same base class', async function (assert) { - assert.expect(7); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch1', { - setup() { - this._super(); - assert.step('patch1.setup'); - }, - fn() { - this._super(); - assert.step('patch1.fn'); - }, - }); - - _utils.patch(BaseClass.prototype, 'patch2', { - setup() { - this._super(); - assert.step('patch2.setup'); - }, - fn() { - this._super(); - assert.step('patch2.fn'); - }, - }); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch1.setup', - 'patch2.setup', - 'base.fn', - 'patch1.fn', - 'patch2.fn', - ]); - }); - - QUnit.test('two patches with same name on same base class', async function (assert) { - assert.expect(1); - - const A = class {}; - - _utils.patch(A.prototype, 'patch'); - - // keys should be unique - assert.throws(() => { - _utils.patch(A.prototype, 'patch'); - }, _utils.AlreadyDefinedPatchError); - }); - - QUnit.test('unpatch', async function (assert) { - assert.expect(8); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'base.fn', - 'patch.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch'); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'base.fn', - ]); - }); - - QUnit.test('unpatch two patches on the same base class', async function (assert) { - assert.expect(15); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch1', { - setup() { - this._super(); - assert.step('patch1.setup'); - }, - fn() { - this._super(); - assert.step('patch1.fn'); - }, - }); - - _utils.patch(BaseClass.prototype, 'patch2', { - setup() { - this._super(); - assert.step('patch2.setup'); - }, - fn() { - this._super(); - assert.step('patch2.fn'); - }, - }); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch1.setup', - 'patch2.setup', - 'base.fn', - 'patch1.fn', - 'patch2.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch1'); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch2.setup', - 'base.fn', - 'patch2.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch2'); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'base.fn', - ]); - }); - - QUnit.test('unpatch two patches on the same base class (returned by patch)', async function (assert) { - assert.expect(15); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch1', { - setup() { - this._super(); - assert.step('patch1.setup'); - }, - fn() { - this._super(); - assert.step('patch1.fn'); - }, - }); - - _utils.patch(BaseClass.prototype, 'patch2', { - setup() { - this._super(); - assert.step('patch2.setup'); - }, - fn() { - this._super(); - assert.step('patch2.fn'); - }, - }); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch1.setup', - 'patch2.setup', - 'base.fn', - 'patch1.fn', - 'patch2.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch1'); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch2.setup', - 'base.fn', - 'patch2.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch2'); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'base.fn', - ]); - }); - - QUnit.test('unpatch a class that has not been patched', async function (assert) { - assert.expect(1); - - const A = class {}; - assert.throws(() => { - _utils.unpatch(A.prototype, 'patch'); - }, _utils.UnknownPatchError); - }); - - QUnit.test('unpatch twice the same patch name', async function (assert) { - assert.expect(1); - - const A = class {}; - _utils.patch(A.prototype, 'patch'); - - _utils.unpatch(A.prototype, 'patch'); - assert.throws(() => { - _utils.unpatch(A.prototype, 'patch'); - }, _utils.UnknownPatchError); - }); - - QUnit.test('unpatch and re-patch', async function (assert) { - assert.expect(13); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'base.fn', - 'patch.fn', - ]); - - const p =_utils.unpatch(BaseClass.prototype, 'patch'); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'base.fn', - ]); - - _utils.patch(BaseClass.prototype, 'patch', p); - - (new BaseClass()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'base.fn', - 'patch.fn', - ]); - }); - - QUnit.test('patch for specialization', async function (assert) { - assert.expect(1); - - let args = []; - - const A = class { - constructor() { - this.setup(...arguments); - } - setup() { - args = ['A', ...arguments]; - } - }; - - _utils.patch(A.prototype, 'patch', { - setup() { - this._super('patch', ...arguments); - }, - }); - - new A('instantiation'); - - assert.deepEqual(args, ['A', 'patch', 'instantiation']); - }); - - QUnit.test('instance fields', async function (assert) { - assert.expect(3); - - const BaseClass = makeBaseClass(assert, false); - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(...arguments); - - this.str += 'patch'; - this.arr.push('patch'); - this.obj.patch = 'patch'; - } - }); - - const instance = new BaseClass(); - assert.strictEqual(instance.str, 'basepatch'); - assert.deepEqual(instance.arr, ['base', 'patch']); - assert.deepEqual(instance.obj, { base: 'base', patch: 'patch' }); - }); - - QUnit.test('call instance method defined in patch', async function (assert) { - assert.expect(4); - - const BaseClass = makeBaseClass(assert, false); - - assert.notOk((new BaseClass()).f); - - _utils.patch(BaseClass.prototype, 'patch', { - f() { - assert.step('patch.f'); - }, - }); - - (new BaseClass()).f(); - assert.verifySteps(['patch.f']); - - _utils.unpatch(BaseClass.prototype, 'patch'); - - assert.notOk((new BaseClass()).f); - }); - - QUnit.test('class methods', async function (assert) { - assert.expect(7); - - const BaseClass = makeBaseClass(assert); - - BaseClass.staticFn(); - assert.verifySteps(['base.staticFn']); - - _utils.patch(BaseClass, 'patch', { - staticFn() { - this._super(); - assert.step('patch.staticFn'); - } - }); - - BaseClass.staticFn(); - assert.verifySteps(['base.staticFn', 'patch.staticFn']); - - _utils.unpatch(BaseClass, 'patch'); - - BaseClass.staticFn(); - assert.verifySteps(['base.staticFn']); - }); - - QUnit.test('class fields', async function (assert) { - assert.expect(6); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass, 'patch', { - staticStr: BaseClass.staticStr + 'patch', - staticArr: [...BaseClass.staticArr, 'patch'], - staticObj: {...BaseClass.staticObj, patch: 'patch'}, - }); - - assert.strictEqual(BaseClass.staticStr, 'basepatch'); - assert.deepEqual(BaseClass.staticArr, ['base', 'patch']); - assert.deepEqual(BaseClass.staticObj, { base: 'base', patch: 'patch' }); - - _utils.unpatch(BaseClass, 'patch'); - - assert.strictEqual(BaseClass.staticStr, 'base'); - assert.deepEqual(BaseClass.staticArr, ['base']); - assert.deepEqual(BaseClass.staticObj, { base: 'base' }); - }); - - QUnit.test('lazy patch', async function (assert) { - assert.expect(6); - - const BaseClass = makeBaseClass(assert); - const instance = new BaseClass(); - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - // will not be called - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - instance.fn(); - assert.verifySteps([ - 'base.setup', - 'base.fn', - 'patch.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch'); - - instance.fn(); - assert.verifySteps([ - 'base.fn', - ]); - }); - - QUnit.test('getter', async function (assert) { - assert.expect(2); - - const BaseClass = makeBaseClass(assert, false); - - _utils.patch(BaseClass.prototype, 'patch', { - get dynamic() { - return this._super() + 'patch'; - }, - }); - - const instance = new BaseClass(); - assert.strictEqual(instance.dynamic, 'basepatch'); - - _utils.unpatch(BaseClass.prototype, 'patch'); - assert.strictEqual(instance.dynamic, 'base'); - }); - - QUnit.test('setter', async function (assert) { - assert.expect(3); - - const BaseClass = makeBaseClass(assert, false); - - _utils.patch(BaseClass.prototype, 'patch', { - set dynamic(value) { - this._super('patch:' + value); - }, - }); - - const instance = new BaseClass(); - - assert.strictEqual(instance.dynamic, 'base'); - instance.dynamic = 'patch'; - assert.strictEqual(instance.dynamic, 'patch:patch'); - - _utils.unpatch(BaseClass.prototype, 'patch'); - - instance.dynamic = 'base'; - assert.strictEqual(instance.dynamic, 'base'); - }); - - QUnit.test('async function', async function (assert) { - assert.expect(3); - - const BaseClass = makeBaseClass(assert, false); - - _utils.patch(BaseClass.prototype, "patch", { - async asyncFn() { - const _super = this._super; - await Promise.resolve(); - await _super(...arguments); - assert.step('patch.asyncFn'); - }, - }); - - const instance = new BaseClass(); - instance.str = "asyncFn"; - await instance.asyncFn(); - - assert.verifySteps([ - 'base.asyncFn', - 'patch.asyncFn', - ]); - }); - - QUnit.test('async function (multiple patches)', async function (assert) { - assert.expect(4); - - const BaseClass = makeBaseClass(assert, false); - - _utils.patch(BaseClass.prototype, "patch1", { - async asyncFn() { - const _super = this._super; - await Promise.resolve(); - await _super(...arguments); - // also check this binding - assert.step(`patch1.${this.str}`); - }, - }); - _utils.patch(BaseClass.prototype, "patch2", { - async asyncFn() { - const _super = this._super; - await Promise.resolve(); - await _super(...arguments); - // also check this binding - assert.step(`patch2.${this.str}`); - }, - }); - - const instance = new BaseClass(); - instance.str = "asyncFn"; - await instance.asyncFn(); - - assert.verifySteps([ - 'base.asyncFn', - 'patch1.asyncFn', - 'patch2.asyncFn', - ]); - }); - - QUnit.module('inheritance'); - - QUnit.test('inherit a patched class (extends before patch)', async function (assert) { - assert.expect(12); - - const BaseClass = makeBaseClass(assert); - - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'base.fn', - 'extension.fn', - ]); - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'extension.setup', - 'base.fn', - 'patch.fn', - 'extension.fn', - ]); - }); - - QUnit.test('inherit a patched class (extends after patch)', async function (assert) { - assert.expect(7); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - (new Extension()).fn(); - - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'extension.setup', - 'base.fn', - 'patch.fn', - 'extension.fn', - ]); - }); - - QUnit.test('patch an inherited class', async function (assert) { - assert.expect(12); - - const BaseClass = makeBaseClass(assert); - - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'base.fn', - 'extension.fn', - ]); - - _utils.patch(Extension.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'patch.setup', - 'base.fn', - 'extension.fn', - 'patch.fn', - ]); - }); - - QUnit.test('patch an inherited patched class', async function (assert) { - assert.expect(9); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - _utils.patch(Extension.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.extension.setup'); - }, - fn() { - this._super(); - assert.step('patch.extension.fn'); - }, - }); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'extension.setup', - 'patch.extension.setup', - 'base.fn', - 'patch.fn', - 'extension.fn', - 'patch.extension.fn', - ]); - }); - - QUnit.test('unpatch base class', async function (assert) { - assert.expect(12); - - const BaseClass = makeBaseClass(assert); - - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'extension.setup', - 'base.fn', - 'patch.fn', - 'extension.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch'); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'base.fn', - 'extension.fn', - ]); - }); - - QUnit.test('unpatch an inherited class', async function (assert) { - assert.expect(12); - - const BaseClass = makeBaseClass(assert); - - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - _utils.patch(Extension.prototype, 'patch', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'patch.setup', - 'base.fn', - 'extension.fn', - 'patch.fn', - ]); - - _utils.unpatch(Extension.prototype, 'patch'); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'base.fn', - 'extension.fn', - ]); - }); - - QUnit.test('unpatch an inherited class and its base class (unpatch base first)', async function (assert) { - assert.expect(21); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch.BaseClass', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - _utils.patch(Extension.prototype, 'patch.Extension', { - setup() { - this._super(); - assert.step('patch.extension.setup'); - }, - fn() { - this._super(); - assert.step('patch.extension.fn'); - }, - }); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'extension.setup', - 'patch.extension.setup', - 'base.fn', - 'patch.fn', - 'extension.fn', - 'patch.extension.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch.BaseClass'); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'patch.extension.setup', - 'base.fn', - 'extension.fn', - 'patch.extension.fn', - ]); - - _utils.unpatch(Extension.prototype, 'patch.Extension'); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'base.fn', - 'extension.fn', - ]); - }); - - QUnit.test('unpatch an inherited class and its base class (unpatch extension first)', async function (assert) { - assert.expect(21); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass.prototype, 'patch.BaseClass', { - setup() { - this._super(); - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - _utils.patch(Extension.prototype, 'patch.Extension', { - setup() { - this._super(); - assert.step('patch.extension.setup'); - }, - fn() { - this._super(); - assert.step('patch.extension.fn'); - }, - }); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'extension.setup', - 'patch.extension.setup', - 'base.fn', - 'patch.fn', - 'extension.fn', - 'patch.extension.fn', - ]); - - _utils.unpatch(Extension.prototype, 'patch.Extension'); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'patch.setup', - 'extension.setup', - 'base.fn', - 'patch.fn', - 'extension.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch.BaseClass'); - - (new Extension()).fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'base.fn', - 'extension.fn', - ]); - }); - - QUnit.test('class methods', async function (assert) { - assert.expect(12); - - const BaseClass = makeBaseClass(assert); - - class Extension extends BaseClass { - static staticFn() { - super.staticFn(); - assert.step('extension.staticFn'); - } - } - - _utils.patch(BaseClass, 'patch.BaseClass', { - staticFn() { - this._super(); - assert.step('patch.staticFn'); - } - }); - - _utils.patch(Extension, 'patch.Extension', { - staticFn() { - this._super(); - assert.step('patch.extension.staticFn'); - } - }); - - Extension.staticFn(); - assert.verifySteps([ - 'base.staticFn', - 'patch.staticFn', - 'extension.staticFn', - 'patch.extension.staticFn', - ]); - - _utils.unpatch(BaseClass, 'patch.BaseClass'); - - Extension.staticFn(); - assert.verifySteps([ - 'base.staticFn', - 'extension.staticFn', - 'patch.extension.staticFn', - ]); - - _utils.unpatch(Extension, 'patch.Extension'); - - Extension.staticFn(); - assert.verifySteps([ - 'base.staticFn', - 'extension.staticFn', - ]); - }); - - QUnit.test('class fields (patch before inherit)', async function (assert) { - assert.expect(6); - - const BaseClass = makeBaseClass(assert); - - _utils.patch(BaseClass, 'patch.BaseClass', { - staticStr: BaseClass.staticStr + 'patch', - staticArr: [...BaseClass.staticArr, 'patch'], - staticObj: {...BaseClass.staticObj, patch: 'patch'}, - }); - - class Extension extends BaseClass {} - Extension.staticStr = BaseClass.staticStr + 'extension'; - Extension.staticArr = [...BaseClass.staticArr, 'extension']; - Extension.staticObj = {...BaseClass.staticObj, extension: 'extension'}; - - assert.strictEqual(Extension.staticStr, 'basepatchextension'); - assert.deepEqual(Extension.staticArr, ['base', 'patch', 'extension']); - assert.deepEqual(Extension.staticObj, - { base: 'base', patch: 'patch', extension: 'extension' }); - - _utils.unpatch(BaseClass, 'patch.BaseClass'); - - // /!\ WARNING /!\ - // If inherit comes after the patch then extension will still have - // the patched data when unpatching. - assert.strictEqual(Extension.staticStr, 'basepatchextension'); - assert.deepEqual(Extension.staticArr, ['base', 'patch', 'extension']); - assert.deepEqual(Extension.staticObj, - { base: 'base', patch: 'patch', extension: 'extension' }); - }); - - QUnit.test('class fields (inherit before patch)', async function (assert) { - assert.expect(6); - - const BaseClass = makeBaseClass(assert); - - class Extension extends BaseClass {} - Extension.staticStr = BaseClass.staticStr + 'extension'; - Extension.staticArr = [...BaseClass.staticArr, 'extension']; - Extension.staticObj = {...BaseClass.staticObj, extension: 'extension'}; - - // /!\ WARNING /!\ - // If patch comes after the inherit then extension won't have - // the patched data. - _utils.patch(BaseClass, 'patch.BaseClass', { - staticStr: BaseClass.staticStr + 'patch', - staticArr: [...BaseClass.staticArr, 'patch'], - staticObj: {...BaseClass.staticObj, patch: 'patch'}, - }); - - assert.strictEqual(Extension.staticStr, 'baseextension'); - assert.deepEqual(Extension.staticArr, ['base', 'extension']); - assert.deepEqual(Extension.staticObj, - { base: 'base', extension: 'extension' }); - - _utils.unpatch(BaseClass, 'patch.BaseClass'); - - assert.strictEqual(Extension.staticStr, 'baseextension'); - assert.deepEqual(Extension.staticArr, ['base', 'extension']); - assert.deepEqual(Extension.staticObj, - { base: 'base', extension: 'extension' }); - }); - - QUnit.test('lazy patch', async function (assert) { - assert.expect(9); - - const BaseClass = makeBaseClass(assert); - class Extension extends BaseClass { - setup() { - super.setup(); - assert.step('extension.setup'); - } - fn() { - super.fn(); - assert.step('extension.fn'); - } - } - - const instance = new Extension(); - - _utils.patch(BaseClass.prototype, 'patch', { - setup() { - this._super(); - // will not be called - assert.step('patch.setup'); - }, - fn() { - this._super(); - assert.step('patch.fn'); - }, - }); - - instance.fn(); - assert.verifySteps([ - 'base.setup', - 'extension.setup', - 'base.fn', - 'patch.fn', - 'extension.fn', - ]); - - _utils.unpatch(BaseClass.prototype, 'patch'); - - instance.fn(); - assert.verifySteps([ - 'base.fn', - 'extension.fn', - ]); - }); - - QUnit.module('other'); - - QUnit.test('patch an object', async function (assert) { - assert.expect(7); - - const obj = { - var: "obj", - fn() { - assert.step("obj"); - }, - }; - - _utils.patch(obj, "patch", { - var: obj.var + "patch", - fn() { - this._super(...arguments); - assert.step("patch"); - } - }); - - assert.strictEqual(obj.var, "objpatch"); - - obj.fn(); - assert.verifySteps([ "obj", "patch" ]); - - _utils.unpatch(obj, "patch"); - - assert.strictEqual(obj.var, "obj"); - - obj.fn(); - assert.verifySteps([ "obj" ]); - }); - }); -}); diff --git a/addons/web/static/tests/legacy/helpers/test_utils_mock.js b/addons/web/static/tests/legacy/helpers/test_utils_mock.js index dd9e9d3678e..546c2635eca 100644 --- a/addons/web/static/tests/legacy/helpers/test_utils_mock.js +++ b/addons/web/static/tests/legacy/helpers/test_utils_mock.js @@ -11,8 +11,6 @@ import { patchDate } from "@web/../tests/helpers/utils"; -import { uniqueId } from "@web/core/utils/functions"; - //------------------------------------------------------------------------------ // Public functions //------------------------------------------------------------------------------ @@ -70,94 +68,7 @@ function legacyPatchDate(year, month, day, hours, minutes, seconds) { return function () {}; // all calls to that function are now useless } -var patches = {}; -/** - * Patches a given Class or Object with the given properties. - * - * @param {Class|Object} target - * @param {Object} props - */ -function patch(target, props) { - var patchID = uniqueId("patch_"); - target.__patchID = patchID; - patches[patchID] = { - target: target, - otherPatchedProps: [], - ownPatchedProps: [], - }; - if (target.prototype) { - Object.keys(props).forEach((key) => { - if (target.prototype.hasOwnProperty(key)) { - patches[patchID].ownPatchedProps.push({ - key: key, - initialValue: target.prototype[key], - }); - } else { - patches[patchID].otherPatchedProps.push(key); - } - }); - target.include(props); - } else { - for (const [key, value] of Object.entries(props)) { - if (key in target) { - var oldValue = target[key]; - patches[patchID].ownPatchedProps.push({ - key: key, - initialValue: oldValue, - }); - if (typeof value === 'function') { - target[key] = function () { - var oldSuper = this._super; - this._super = oldValue; - var result = value.apply(this, arguments); - if (oldSuper === undefined) { - delete this._super; - } else { - this._super = oldSuper; - } - return result; - }; - } else { - target[key] = value; - } - } else { - patches[patchID].otherPatchedProps.push(key); - target[key] = value; - } - } - } -} - -/** - * Unpatches a given Class or Object. - * - * @param {Class|Object} target - */ -function unpatch(target) { - var patchID = target.__patchID; - var patch = patches[patchID]; - if (target.prototype) { - patch.ownPatchedProps.forEach((p) => { - target.prototype[p.key] = p.initialValue; - }); - patch.otherPatchedProps.forEach((key) => { - delete target.prototype[key]; - }); - } else { - patch.ownPatchedProps.forEach((p) => { - target[p.key] = p.initialValue; - }); - patch.otherPatchedProps.forEach((key) => { - delete target[key]; - }); - } - delete patches[patchID]; - delete target.__patchID; -} - export default { intercept: intercept, patchDate: legacyPatchDate, - patch: patch, - unpatch: unpatch, }; diff --git a/addons/web_editor/static/tests/test_utils.js b/addons/web_editor/static/tests/test_utils.js index 0d38080ad2b..7014423e533 100644 --- a/addons/web_editor/static/tests/test_utils.js +++ b/addons/web_editor/static/tests/test_utils.js @@ -1,9 +1,8 @@ /** @odoo-module **/ -import ajax from "@web/legacy/js/core/ajax"; import { MockServer } from "@web/../tests/helpers/mock_server"; import testUtils from "@web/../tests/legacy/helpers/test_utils"; -import * as coreUtils from "@web/core/utils/patch"; +import { patch } from "@web/core/utils/patch"; import * as OdooEditorLib from "@web_editor/js/editor/odoo-editor/src/OdooEditor"; import { Wysiwyg } from '@web_editor/js/wysiwyg/wysiwyg'; import options from "@web_editor/js/editor/snippets.options"; @@ -94,7 +93,7 @@ const SNIPPETS_TEMPLATE = ` `; -coreUtils.patch(MockServer.prototype, { +patch(MockServer.prototype, { //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- @@ -145,32 +144,6 @@ options.registry.option_test = options.Class.extend({ }, }); -function patch() { - testUtils.mock.patch(ajax, { - loadAsset: function (xmlId) { - if (xmlId === 'template.assets') { - return Promise.resolve({ - cssLibs: [], - cssContents: ['body {background-color: red;}'] - }); - } - if (xmlId === 'template.assets_all_style') { - return Promise.resolve({ - cssLibs: $('link[href]:not([type="image/x-icon"])').map(function () { - return $(this).attr('href'); - }).get(), - cssContents: ['body {background-color: red;}'] - }); - } - throw 'Wrong template'; - }, - }); -} - -function unpatch() { - testUtils.mock.unpatch(ajax); -} - /** * @param {object} data * @returns {object} @@ -819,8 +792,6 @@ export default { testKeyboard: testKeyboard, select: select, keydown: keydown, - patch: patch, - unpatch: unpatch, getGridHtml: getGridHtml, getTableHtml: getTableHtml, getRegularGridHtml: getRegularGridHtml, diff --git a/addons/web_unsplash/static/src/components/media_dialog/image_selector.js b/addons/web_unsplash/static/src/components/media_dialog/image_selector.js index 4ed497b925e..65e8baacb5a 100644 --- a/addons/web_unsplash/static/src/components/media_dialog/image_selector.js +++ b/addons/web_unsplash/static/src/components/media_dialog/image_selector.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; import { KeepLast } from "@web/core/utils/concurrency"; import { MediaDialog, TABS } from '@web_editor/components/media_dialog/media_dialog'; import { ImageSelector } from '@web_editor/components/media_dialog/image_selector'; @@ -38,9 +38,9 @@ UnsplashError.components = { UnsplashCredentials, }; -patch(ImageSelector.prototype, 'image_selector_unsplash', { +patch(ImageSelector.prototype, { setup() { - this._super(); + super.setup(); this.unsplash = useService('unsplash'); this.keepLastUnsplash = new KeepLast(); @@ -69,20 +69,20 @@ patch(ImageSelector.prototype, 'image_selector_unsplash', { get canLoadMore() { if (this.state.searchService === 'all') { - return this._super() || this.state.needle && !this.state.isMaxed && !this.state.unsplashError; + return super.canLoadMore || this.state.needle && !this.state.isMaxed && !this.state.unsplashError; } else if (this.state.searchService === 'unsplash') { return this.state.needle && !this.state.isMaxed && !this.state.unsplashError; } - return this._super(); + return super.canLoadMore; }, get hasContent() { if (this.state.searchService === 'all') { - return this._super() || !!this.state.unsplashRecords.length; + return super.hasContent || !!this.state.unsplashRecords.length; } else if (this.state.searchService === 'unsplash') { return !!this.state.unsplashRecords.length; } - return this._super(); + return super.hasContent; }, get errorTitle() { @@ -104,7 +104,7 @@ patch(ImageSelector.prototype, 'image_selector_unsplash', { }, get isFetching() { - return this._super() || this.state.isFetchingUnsplash; + return super.isFetching || this.state.isFetchingUnsplash; }, get combinedRecords() { @@ -168,7 +168,7 @@ patch(ImageSelector.prototype, 'image_selector_unsplash', { }, async loadMore(...args) { - await this._super(...args); + await super.loadMore(...args); return this.keepLastUnsplash.add(this.fetchUnsplashRecords(this.state.unsplashRecords.length)).then(({ records, isMaxed }) => { // This is never reached if another search or loadMore occurred. this.state.unsplashRecords.push(...records); @@ -177,7 +177,7 @@ patch(ImageSelector.prototype, 'image_selector_unsplash', { }, async search(...args) { - await this._super(...args); + await super.search(...args); await this.searchUnsplash(); }, @@ -212,15 +212,14 @@ ImageSelector.components = { UnsplashError, }; -patch(MediaDialog.prototype, 'media_dialog_unsplash', { +patch(MediaDialog.prototype, { setup() { - this._super(); + super.setup(); this.uploadService = useService('upload'); }, async save() { - const _super = this._super.bind(this); const selectedImages = this.selectedMedia[TABS.IMAGES.id]; if (selectedImages) { const unsplashRecords = selectedImages.filter(media => media.mediaType === 'unsplashRecord'); @@ -231,13 +230,13 @@ patch(MediaDialog.prototype, 'media_dialog_unsplash', { }); } } - return _super(...arguments); + return super.save(...arguments); }, }); -patch(uploadService, 'upload_service_unsplash', { +patch(uploadService, { start(env, { rpc }) { - const service = this._super(...arguments); + const service = super.start(...arguments); return { ...service, async uploadUnsplashRecords(records, { resModel, resId }, onUploaded) { diff --git a/addons/website/static/src/client_actions/website_preview/website_preview_test_mode.js b/addons/website/static/src/client_actions/website_preview/website_preview_test_mode.js index 52f4505dd81..55c12970678 100644 --- a/addons/website/static/src/client_actions/website_preview/website_preview_test_mode.js +++ b/addons/website/static/src/client_actions/website_preview/website_preview_test_mode.js @@ -1,8 +1,8 @@ /** @odoo-module **/ -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; import { WebsitePreview } from '@website/client_actions/website_preview/website_preview'; -patch(WebsitePreview.prototype, 'website_preview_test_mode', { +patch(WebsitePreview.prototype, { /** * @override */ diff --git a/addons/website/static/src/components/burger_menu/burger_menu.js b/addons/website/static/src/components/burger_menu/burger_menu.js index ba15e5a009e..582c15affb5 100644 --- a/addons/website/static/src/components/burger_menu/burger_menu.js +++ b/addons/website/static/src/components/burger_menu/burger_menu.js @@ -3,13 +3,13 @@ import { BurgerMenu } from '@web/webclient/burger_menu/burger_menu'; import { useService } from '@web/core/utils/hooks'; import { registry } from "@web/core/registry"; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; const websiteSystrayRegistry = registry.category('website_systray'); -patch(BurgerMenu.prototype, 'website_burger_menu', { +patch(BurgerMenu.prototype, { setup() { - this._super(); + super.setup(); this.websiteCustomMenus = useService('website_custom_menus'); if (!websiteSystrayRegistry.contains('burger_menu')) { @@ -21,7 +21,7 @@ patch(BurgerMenu.prototype, 'website_burger_menu', { * @override */ get currentAppSections() { - const currentAppSections = this._super(); + const currentAppSections = super.currentAppSections; if (this.currentApp && this.currentApp.xmlid === 'website.menu_website_configuration') { return this.websiteCustomMenus.addCustomMenus(currentAppSections).filter(section => section.childrenTree.length); } @@ -43,7 +43,7 @@ patch(BurgerMenu.prototype, 'website_burger_menu', { this.websiteCustomMenus.open(menu); this._closeBurger(); } else { - this._super(menu); + super._onMenuClicked(menu); } }, }); diff --git a/addons/website/static/src/components/navbar/navbar.js b/addons/website/static/src/components/navbar/navbar.js index 48011944397..d4f198c8c64 100644 --- a/addons/website/static/src/components/navbar/navbar.js +++ b/addons/website/static/src/components/navbar/navbar.js @@ -3,14 +3,14 @@ import { NavBar } from '@web/webclient/navbar/navbar'; import { useService, useBus } from '@web/core/utils/hooks'; import { registry } from "@web/core/registry"; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; const websiteSystrayRegistry = registry.category('website_systray'); const { useEffect } = owl; -patch(NavBar.prototype, 'website_navbar', { +patch(NavBar.prototype, { setup() { - this._super(); + super.setup(); this.websiteService = useService('website'); this.websiteCustomMenus = useService('website_custom_menus'); @@ -55,14 +55,14 @@ patch(NavBar.prototype, 'website_navbar', { .filter((item) => ('isDisplayed' in item ? item.isDisplayed(this.env) : true)) .reverse(); } - return this._super(); + return super.systrayItems; }, /** * @override */ get currentAppSections() { - const currentAppSections = this._super(); + const currentAppSections = super.currentAppSections; if (this.currentApp && this.currentApp.xmlid === 'website.menu_website_configuration') { return this.websiteCustomMenus.addCustomMenus(currentAppSections).filter(section => section.childrenTree.length); } @@ -77,6 +77,6 @@ patch(NavBar.prototype, 'website_navbar', { if (websiteMenu) { return this.websiteCustomMenus.open(menu); } - return this._super(menu); + return super.onNavBarDropdownItemSelection(menu); }, }); diff --git a/addons/website/static/tests/tours/snippets_all_drag_and_drop.js b/addons/website/static/tests/tours/snippets_all_drag_and_drop.js index c291ab00c20..ca7fb9e4f2a 100644 --- a/addons/website/static/tests/tours/snippets_all_drag_and_drop.js +++ b/addons/website/static/tests/tours/snippets_all_drag_and_drop.js @@ -2,18 +2,18 @@ import { WysiwygAdapterComponent } from "@website/components/wysiwyg_adapter/wysiwyg_adapter"; import websiteTourUtils from "@website/js/tours/tour_utils"; -import { patch, unpatch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -const patchWysiwygAdapter = () => patch(WysiwygAdapterComponent.prototype, 'snippets_all_drag_and_drop.wysiwyg_adapter', { +const patchWysiwygAdapter = () => patch(WysiwygAdapterComponent.prototype, { _trigger_up(ev) { - this._super(...arguments); + super._trigger_up(...arguments); if (ev.name === 'snippet_removed') { $('body').attr('test-dd-snippet-removed', true); } } }); -const unpatchWysiwygAdapter = () => unpatch(WysiwygAdapterComponent.prototype, 'snippets_all_drag_and_drop.wysiwyg_adapter'); +let unpatchWysiwygAdapter = null; import { registry } from "@web/core/registry"; @@ -89,7 +89,7 @@ registry.category("web_tour.tours").add("snippets_all_drag_and_drop", { if (steps.length < 220) { console.error(`This test is not behaving as it should, got only ${steps.length} steps.`); } - patchWysiwygAdapter(); + unpatchWysiwygAdapter = patchWysiwygAdapter(); }, }, // This first step is needed as it will be used later for inner snippets diff --git a/addons/website_blog/static/src/js/systray_items/new_content.js b/addons/website_blog/static/src/js/systray_items/new_content.js index 80b7daa020a..3440c3e333c 100644 --- a/addons/website_blog/static/src/js/systray_items/new_content.js +++ b/addons/website_blog/static/src/js/systray_items/new_content.js @@ -1,11 +1,11 @@ /** @odoo-module **/ import { NewContentModal, MODULE_STATUS } from '@website/systray_items/new_content'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(NewContentModal.prototype, 'website_blog_new_content', { +patch(NewContentModal.prototype, { setup() { - this._super(); + super.setup(); const newBlogElement = this.state.newContentElements.find(element => element.moduleXmlId === 'base.module_website_blog'); newBlogElement.createNewContent = () => this.onAddContent('website_blog.blog_post_action_add', true); diff --git a/addons/website_event/static/src/js/systray_items/new_content.js b/addons/website_event/static/src/js/systray_items/new_content.js index e2951f44666..c83b5bd08fe 100644 --- a/addons/website_event/static/src/js/systray_items/new_content.js +++ b/addons/website_event/static/src/js/systray_items/new_content.js @@ -1,11 +1,11 @@ /** @odoo-module **/ import { NewContentModal, MODULE_STATUS } from '@website/systray_items/new_content'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(NewContentModal.prototype, 'website_event_new_content', { +patch(NewContentModal.prototype, { setup() { - this._super(); + super.setup(); const newEventElement = this.state.newContentElements.find(element => element.moduleXmlId === 'base.module_website_event'); newEventElement.createNewContent = () => this.onAddContent('website_event.event_event_action_add', true); diff --git a/addons/website_forum/static/src/js/systray_items/new_content.js b/addons/website_forum/static/src/js/systray_items/new_content.js index 6023685c450..eb0e4bb5cc2 100644 --- a/addons/website_forum/static/src/js/systray_items/new_content.js +++ b/addons/website_forum/static/src/js/systray_items/new_content.js @@ -1,11 +1,11 @@ /** @odoo-module **/ import { NewContentModal, MODULE_STATUS } from '@website/systray_items/new_content'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(NewContentModal.prototype, 'website_forum_new_content', { +patch(NewContentModal.prototype, { setup() { - this._super(); + super.setup(); const newForumElement = this.state.newContentElements.find(element => element.moduleXmlId === 'base.module_website_forum'); newForumElement.createNewContent = () => this.onAddContent('website_forum.forum_forum_action_add'); diff --git a/addons/website_hr_recruitment/static/src/js/systray_items/new_content.js b/addons/website_hr_recruitment/static/src/js/systray_items/new_content.js index 07f248efeca..ae1e8c84341 100644 --- a/addons/website_hr_recruitment/static/src/js/systray_items/new_content.js +++ b/addons/website_hr_recruitment/static/src/js/systray_items/new_content.js @@ -1,11 +1,11 @@ /** @odoo-module **/ import { NewContentModal, MODULE_STATUS } from '@website/systray_items/new_content'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(NewContentModal.prototype, 'website_hr_recruitment_new_content', { +patch(NewContentModal.prototype, { setup() { - this._super(); + super.setup(); const newJobElement = this.state.newContentElements.find(element => element.moduleXmlId === 'base.module_website_hr_recruitment'); newJobElement.createNewContent = () => this.createNewJob(); diff --git a/addons/website_livechat/static/src/js/systray_items/new_content.js b/addons/website_livechat/static/src/js/systray_items/new_content.js index abe966ba1ec..1f72dea4c44 100644 --- a/addons/website_livechat/static/src/js/systray_items/new_content.js +++ b/addons/website_livechat/static/src/js/systray_items/new_content.js @@ -1,11 +1,11 @@ /** @odoo-module **/ import { NewContentModal, MODULE_STATUS } from '@website/systray_items/new_content'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(NewContentModal.prototype, 'website_livechat_new_content', { +patch(NewContentModal.prototype, { setup() { - this._super(); + super.setup(); const newChannelElement = this.state.newContentElements.find(element => element.moduleXmlId === 'base.module_website_livechat'); newChannelElement.createNewContent = () => this.onAddContent('website_livechat.im_livechat_channel_action_add'); diff --git a/addons/website_sale/static/src/js/components/wysiwyg_adapter/wysiwyg_adapter.js b/addons/website_sale/static/src/js/components/wysiwyg_adapter/wysiwyg_adapter.js index ed9b376a0ba..0878f37b52e 100644 --- a/addons/website_sale/static/src/js/components/wysiwyg_adapter/wysiwyg_adapter.js +++ b/addons/website_sale/static/src/js/components/wysiwyg_adapter/wysiwyg_adapter.js @@ -1,16 +1,16 @@ /** @odoo-module **/ import { WysiwygAdapterComponent } from '@website/components/wysiwyg_adapter/wysiwyg_adapter'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; // TODO this whole patch actually seems unnecessary. The bug it solved seems // to stay solved if this is removed. To investigate. -patch(WysiwygAdapterComponent.prototype, 'website_sale_wysiwyg_adapter', { +patch(WysiwygAdapterComponent.prototype, { /** * @override */ _getContentEditableAreas() { - const array = this._super(...arguments); + const array = super._getContentEditableAreas(...arguments); return array.filter(el => { // TODO should really review this system of "ContentEditableAreas + // ReadOnlyAreas", here the "products_header" stuff is duplicated in @@ -24,7 +24,7 @@ patch(WysiwygAdapterComponent.prototype, 'website_sale_wysiwyg_adapter', { * @override */ _getReadOnlyAreas() { - const readOnlyEls = this._super(...arguments); + const readOnlyEls = super._getReadOnlyAreas(...arguments); return [...readOnlyEls].concat( $(this.websiteService.pageDocument).find("#wrapwrap").find('.oe_website_sale .products_header, .oe_website_sale .products_header a').toArray() ); diff --git a/addons/website_sale/static/src/js/systray_items/new_content.js b/addons/website_sale/static/src/js/systray_items/new_content.js index 71526979230..c2cc920b22b 100644 --- a/addons/website_sale/static/src/js/systray_items/new_content.js +++ b/addons/website_sale/static/src/js/systray_items/new_content.js @@ -1,11 +1,11 @@ /** @odoo-module **/ import { NewContentModal, MODULE_STATUS } from '@website/systray_items/new_content'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(NewContentModal.prototype, 'website_sale_new_content', { +patch(NewContentModal.prototype, { setup() { - this._super(); + super.setup(); const newProductElement = this.state.newContentElements.find(element => element.moduleXmlId === 'base.module_website_sale'); newProductElement.createNewContent = () => this.onAddContent('website_sale.product_product_action_add', true); diff --git a/addons/website_sale_loyalty/static/src/js/website_sale_loyalty_delivery.js b/addons/website_sale_loyalty/static/src/js/website_sale_loyalty_delivery.js index f07dbc8829e..5f3a771a1b5 100644 --- a/addons/website_sale_loyalty/static/src/js/website_sale_loyalty_delivery.js +++ b/addons/website_sale_loyalty/static/src/js/website_sale_loyalty_delivery.js @@ -1,12 +1,12 @@ /** @odoo-module **/ import PublicWidget from '@web/legacy/js/public/public_widget'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; import core from "@web/legacy/js/services/core"; const _t = core._t; -patch(PublicWidget.registry.websiteSaleDelivery, 'addons/website_sale_loyalty_delivery/statis/src/js/website_sale_loyalty_delivery.js', { +patch(PublicWidget.registry.websiteSaleDelivery, { //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- @@ -14,8 +14,8 @@ patch(PublicWidget.registry.websiteSaleDelivery, 'addons/website_sale_loyalty_de /** * @override */ - _handleCarrierUpdateResult: async function (carrierInput) { - await this._super.apply(this, arguments); + async _handleCarrierUpdateResult(carrierInput) { + await super._handleCarrierUpdateResult(...arguments); if (this.result.new_amount_order_discounted) { // Update discount of the order $('#order_discounted').html(this.result.new_amount_order_discounted); @@ -24,8 +24,8 @@ patch(PublicWidget.registry.websiteSaleDelivery, 'addons/website_sale_loyalty_de /** * @override */ - _handleCarrierUpdateResultBadge: function (result) { - this._super.apply(this, arguments); + _handleCarrierUpdateResultBadge(result) { + super._handleCarrierUpdateResultBadge(...arguments); if (result.new_amount_order_discounted) { // We are in freeshipping, so every carrier is Free but we don't // want to replace error message by 'Free' diff --git a/addons/website_slides/static/src/js/components/editor.js b/addons/website_slides/static/src/js/components/editor.js index 29611eff21f..9fcb54fd8e1 100644 --- a/addons/website_slides/static/src/js/components/editor.js +++ b/addons/website_slides/static/src/js/components/editor.js @@ -2,9 +2,9 @@ import { WebsiteEditorComponent } from '@website/components/editor/editor'; import { WebsiteTranslator } from '@website/components/translator/translator'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(WebsiteEditorComponent.prototype, 'website_slides_editor', { +patch(WebsiteEditorComponent.prototype, { /** * @override */ @@ -14,12 +14,12 @@ patch(WebsiteEditorComponent.prototype, 'website_slides_editor', { this.websiteContext.edition = false; this.websiteService.goToWebsite({path: `${pathname}?fullscreen=0`, edition: true}); } else { - this._super(...arguments); + super.publicRootReady(...arguments); } } }); -patch(WebsiteTranslator.prototype, 'website_slides_translator', { +patch(WebsiteTranslator.prototype, { /** * When editing translations of a slide in fullscreen mode: force fullscreen off. * Indeed, the fullscreen layout is not fit for content edition. @@ -36,7 +36,7 @@ patch(WebsiteTranslator.prototype, 'website_slides_translator', { translation: true }); } else { - this._super(...arguments); + super.publicRootReady(...arguments); } } }); diff --git a/addons/website_slides/static/src/js/systray_items/new_content.js b/addons/website_slides/static/src/js/systray_items/new_content.js index 03ef9d60b2c..1ff41680670 100644 --- a/addons/website_slides/static/src/js/systray_items/new_content.js +++ b/addons/website_slides/static/src/js/systray_items/new_content.js @@ -1,11 +1,11 @@ /** @odoo-module **/ import { NewContentModal, MODULE_STATUS } from '@website/systray_items/new_content'; -import { patch } from '@web/legacy/js/core/utils'; +import { patch } from "@web/core/utils/patch"; -patch(NewContentModal.prototype, 'website_slides_new_content', { +patch(NewContentModal.prototype, { setup() { - this._super(); + super.setup(); const newSlidesChannelElement = this.state.newContentElements.find(element => element.moduleXmlId === 'base.module_website_slides'); newSlidesChannelElement.createNewContent = () => this.onAddContent('website_slides.slide_channel_action_add');