[FIX] web: fix patch descriptor
Before this commit, patching a getter of a class made it enumerable
(`Object.keys({ a: 1 })` -> `["a"]`).
In javascript, getters of a class are not enumerable but
getters of an object are enumerable.
When patching, the system replaced the descriptor of the old class
member by the member of the object.
Now, it replaces some info of the old descriptor by the new descriptor
but not the entire descriptor.
closes odoo/odoo#95921
X-original-commit: fd7c2c0c14bfaac228abacb265278157eec4aad0
Signed-off-by: Géry Debongnie <ged@odoo.com>
Signed-off-by: Michaël Mattiello <mcm@odoo.com>
This commit is contained in:
@@ -39,7 +39,7 @@ export function patch(obj, patchName, patchValue, options = {}) {
|
||||
proto = Object.getPrototypeOf(proto);
|
||||
} while (!prevDesc && proto);
|
||||
|
||||
const newDesc = Object.getOwnPropertyDescriptor(patchValue, k);
|
||||
let newDesc = Object.getOwnPropertyDescriptor(patchValue, k);
|
||||
if (!objDesc.original.hasOwnProperty(k)) {
|
||||
objDesc.original[k] = Object.getOwnPropertyDescriptor(obj, k);
|
||||
}
|
||||
@@ -48,6 +48,7 @@ export function patch(obj, patchName, patchValue, options = {}) {
|
||||
const patchedFnName = `${k} (patch ${patchName})`;
|
||||
|
||||
if (prevDesc.value && typeof newDesc.value === "function") {
|
||||
newDesc = { ...prevDesc, value: newDesc.value };
|
||||
makeIntermediateFunction("value", prevDesc, newDesc, patchedFnName);
|
||||
}
|
||||
if ((newDesc.get || newDesc.set) && (prevDesc.get || prevDesc.set)) {
|
||||
@@ -55,8 +56,11 @@ export function patch(obj, patchName, patchValue, options = {}) {
|
||||
// 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;
|
||||
newDesc = {
|
||||
...prevDesc,
|
||||
get: newDesc.get || prevDesc.get,
|
||||
set: newDesc.set || prevDesc.set,
|
||||
};
|
||||
if (prevDesc.get && typeof newDesc.get === "function") {
|
||||
makeIntermediateFunction("get", prevDesc, newDesc, patchedFnName);
|
||||
}
|
||||
|
||||
@@ -1085,6 +1085,30 @@ QUnit.module("utils", () => {
|
||||
assert.verifySteps(["base.fn", "extension.fn"]);
|
||||
});
|
||||
|
||||
QUnit.test("keep original descriptor details", async function (assert) {
|
||||
class BaseClass {
|
||||
// getter declared in classes are not enumerable
|
||||
get getter() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let descriptor = Object.getOwnPropertyDescriptor(BaseClass.prototype, "getter");
|
||||
let getterFn = descriptor.get;
|
||||
assert.strictEqual(descriptor.configurable, true);
|
||||
assert.strictEqual(descriptor.enumerable, false);
|
||||
|
||||
patch(BaseClass.prototype, "patch", {
|
||||
// getter declared in object are enumerable
|
||||
get getter() {
|
||||
return true;
|
||||
},
|
||||
});
|
||||
descriptor = Object.getOwnPropertyDescriptor(BaseClass.prototype, "getter");
|
||||
assert.strictEqual(descriptor.configurable, true);
|
||||
assert.strictEqual(descriptor.enumerable, false);
|
||||
assert.notStrictEqual(getterFn, descriptor.get);
|
||||
});
|
||||
|
||||
QUnit.module("other");
|
||||
|
||||
QUnit.test("patch an object", async function (assert) {
|
||||
|
||||
Reference in New Issue
Block a user