From db23f8af33398c4851d6ba36436592f406b35a0d Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Wed, 7 Jul 2021 12:48:12 +0200 Subject: [PATCH] Fix `this` value for `Core.enableLegacyInheritance()` (#4380) Without explicitly binding `this` to `thisValue`, it will be `constructed` resulting in missing data only present in `thisValue`. --- ts/WoltLabSuite/Core/Core.ts | 15 +++++++++++++++ .../install/files/js/WoltLabSuite/Core/Core.js | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/ts/WoltLabSuite/Core/Core.ts b/ts/WoltLabSuite/Core/Core.ts index d5635967c3..9d5c0f5b26 100644 --- a/ts/WoltLabSuite/Core/Core.ts +++ b/ts/WoltLabSuite/Core/Core.ts @@ -270,11 +270,26 @@ export function debounce( }; } +const defaultFunctions = Object.getOwnPropertyNames(Object.getPrototypeOf({})); + export function enableLegacyInheritance(legacyClass: T): void { (legacyClass as any).call = function (thisValue, ...args) { + if (window.ENABLE_DEVELOPER_TOOLS) { + console.log("Relying on legacy inheritance for ", legacyClass, thisValue); + } + const constructed = Reflect.construct(legacyClass as any, args, thisValue.constructor); Object.entries(constructed).forEach(([key, value]) => { thisValue[key] = value; }); + + let object = thisValue; + while ((object = Object.getPrototypeOf(object))) { + Object.getOwnPropertyNames(object).forEach((name) => { + if (typeof object[name] === "function" && !defaultFunctions.includes(name)) { + object[name] = object[name].bind(thisValue); + } + }); + } }; } diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Core.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Core.js index 5256fff96b..64932b0c8f 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Core.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Core.js @@ -238,12 +238,24 @@ define(["require", "exports"], function (require, exports) { }; } exports.debounce = debounce; + const defaultFunctions = Object.getOwnPropertyNames(Object.getPrototypeOf({})); function enableLegacyInheritance(legacyClass) { legacyClass.call = function (thisValue, ...args) { + if (window.ENABLE_DEVELOPER_TOOLS) { + console.log("Relying on legacy inheritance for ", legacyClass, thisValue); + } const constructed = Reflect.construct(legacyClass, args, thisValue.constructor); Object.entries(constructed).forEach(([key, value]) => { thisValue[key] = value; }); + let object = thisValue; + while ((object = Object.getPrototypeOf(object))) { + Object.getOwnPropertyNames(object).forEach((name) => { + if (typeof object[name] === "function" && !defaultFunctions.includes(name)) { + object[name] = object[name].bind(thisValue); + } + }); + } }; } exports.enableLegacyInheritance = enableLegacyInheritance; -- 2.20.1