From 9a9ce0d4194be50e383cd133ccdd44964d83eb7d Mon Sep 17 00:00:00 2001 From: Matthieu Riegler Date: Tue, 26 Mar 2024 22:41:18 -0700 Subject: [PATCH] refactor(devtools): prevent exeception on state serializer (#55061) `Object.getPrototypeOf(obj)` returns `null` if `obj` is an empty object. `Object.getOwnPropertyDescriptors` throws on `null`/`undefined` PR Close #55061 --- .../src/lib/state-serializer/object-utils.ts | 3 ++- .../src/lib/state-serializer/state-serializer.spec.ts | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/devtools/projects/ng-devtools-backend/src/lib/state-serializer/object-utils.ts b/devtools/projects/ng-devtools-backend/src/lib/state-serializer/object-utils.ts index b1405d3ec8c..d3465c2b28a 100644 --- a/devtools/projects/ng-devtools-backend/src/lib/state-serializer/object-utils.ts +++ b/devtools/projects/ng-devtools-backend/src/lib/state-serializer/object-utils.ts @@ -21,7 +21,8 @@ export function getKeys(obj: {}): string[] { obj = unwrapSignal(obj); const properties = Object.getOwnPropertyNames(obj); - const prototypeMembers = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(obj)); + // Object.getPrototypeOf can return null, on empty objectwithout prototype for example + const prototypeMembers = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(obj) ?? {}); const ignoreList = ['__proto__']; const gettersAndSetters = Object.keys(prototypeMembers).filter((methodName) => { diff --git a/devtools/projects/ng-devtools-backend/src/lib/state-serializer/state-serializer.spec.ts b/devtools/projects/ng-devtools-backend/src/lib/state-serializer/state-serializer.spec.ts index 64da4d2d41f..a6ea2bd340c 100644 --- a/devtools/projects/ng-devtools-backend/src/lib/state-serializer/state-serializer.spec.ts +++ b/devtools/projects/ng-devtools-backend/src/lib/state-serializer/state-serializer.spec.ts @@ -531,6 +531,13 @@ describe('deeplySerializeSelectedProperties', () => { expect(getKeys(instance)).toEqual(['baz', 'foo', 'bar']); }); + it('getKeys should not throw on empty object without prototype', () => { + // creates an object without a prototype + const instance = Object.create(null); + + expect(getKeys(instance)).toEqual([]); + }); + it('getKeys would ignore getters and setters for "__proto__"', () => { const instance = { baz: 2,