fix: ignore inherited enumerable properties · unjs/defu@11ba022

2 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -9,12 +9,12 @@ function _defu<T>(baseObject: T, defaults: any, namespace = ".", merger?: Merger

99
1010

const object = { ...defaults };

1111
12-

for (const key in baseObject) {

12+

for (const key of Object.keys(baseObject as Record<string, any>)) {

1313

if (key === "__proto__" || key === "constructor") {

1414

continue;

1515

}

1616
17-

const value = baseObject[key];

17+

const value = (baseObject as Record<string, any>)[key];

1818
1919

if (value === null || value === undefined) {

2020

continue;

Original file line numberDiff line numberDiff line change

@@ -116,6 +116,25 @@ describe("defu", () => {

116116

expect({}.isAdmin).toBe(undefined);

117117

});

118118
119+

it("should ignore inherited enumerable properties", () => {

120+

Object.defineProperty(Object.prototype, "pollutedEnum", {

121+

value: 123,

122+

enumerable: true,

123+

configurable: true,

124+

writable: true,

125+

});

126+
127+

try {

128+

const result = defu({ nested: {} }, { nested: {} });

129+
130+

expect(result).toEqual({ nested: {} });

131+

expect(Object.keys(result)).toEqual(["nested"]);

132+

expect(Object.keys(result.nested)).toEqual([]);

133+

} finally {

134+

delete (Object.prototype as Record<string, unknown>)["pollutedEnum"];

135+

}

136+

});

137+
119138

it("should ignore non-object arguments", () => {

120139

expect(defu(null, { foo: 1 }, false, 123, { bar: 2 })).toEqual({

121140

foo: 1,