fix(core): augmentObject should use existing property descriptors whenever possible (#5872)

* fix(core): Augmented objects should use existing property descriptors whenever possible

* add a test for non-enumerable keys
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2023-04-03 17:19:12 +02:00 committed by GitHub
parent 31cd04c476
commit 6a1b7c306b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 8 deletions

View file

@ -1,5 +1,7 @@
import type { IDataObject } from './Interfaces'; import type { IDataObject } from './Interfaces';
const defaultPropertyDescriptor = Object.freeze({ enumerable: true, configurable: true });
const augmentedObjects = new WeakSet<object>(); const augmentedObjects = new WeakSet<object>();
function augment<T>(value: T): T { function augment<T>(value: T): T {
@ -47,7 +49,8 @@ export function augmentArray<T>(data: T[]): T[] {
if (key === 'length') { if (key === 'length') {
return Reflect.getOwnPropertyDescriptor(newData, key); return Reflect.getOwnPropertyDescriptor(newData, key);
} }
return { configurable: true, enumerable: true };
return Object.getOwnPropertyDescriptor(data, key) ?? defaultPropertyDescriptor;
}, },
has(target, key) { has(target, key) {
return Reflect.has(newData !== undefined ? newData : target, key); return Reflect.has(newData !== undefined ? newData : target, key);
@ -124,18 +127,17 @@ export function augmentObject<T extends object>(data: T): T {
return true; return true;
}, },
ownKeys(target) { ownKeys(target) {
return [...new Set([...Reflect.ownKeys(target), ...Object.keys(newData)])].filter( const originalKeys = Reflect.ownKeys(target);
const newKeys = Object.keys(newData);
return [...new Set([...originalKeys, ...newKeys])].filter(
(key) => deletedProperties.indexOf(key) === -1, (key) => deletedProperties.indexOf(key) === -1,
); );
}, },
// eslint-disable-next-line @typescript-eslint/no-unused-vars getOwnPropertyDescriptor(target, key) {
getOwnPropertyDescriptor(k) { return Object.getOwnPropertyDescriptor(data, key) ?? defaultPropertyDescriptor;
return {
enumerable: true,
configurable: true,
};
}, },
}); });

View file

@ -520,5 +520,13 @@ describe('AugmentObject', () => {
expect(timeAugmented).toBeLessThan(timeCopied); expect(timeAugmented).toBeLessThan(timeCopied);
}); });
test('should ignore non-enumerable keys', () => {
const originalObject = { a: 1, b: 2 };
Object.defineProperty(originalObject, '__hiddenProp', { enumerable: false });
const augmentedObject = augmentObject(originalObject);
expect(Object.keys(augmentedObject)).toEqual(['a', 'b']);
});
}); });
}); });