Skip to content

Commit 61c87a2

Browse files
authored
fix: stack overflow when config have both default and named exports (#49)
1 parent 542d7c7 commit 61c87a2

File tree

2 files changed

+98
-9
lines changed

2 files changed

+98
-9
lines changed

packages/unconfig/src/interop.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ export function interopDefault<T>(mod: T & { default?: T }): T {
99

1010
for (const key in mod) {
1111
try {
12-
if (!(key in defaultValue)) {
13-
Object.defineProperty(defaultValue, key, {
14-
enumerable: key !== 'default',
15-
configurable: key !== 'default',
16-
get() {
17-
return (mod as any)[key]
18-
},
19-
})
20-
}
12+
if (key in defaultValue || key === 'default' || (mod as any)[key] === defaultValue)
13+
continue
14+
15+
Object.defineProperty(defaultValue, key, {
16+
configurable: true,
17+
enumerable: true,
18+
get() {
19+
return (mod as any)[key]
20+
},
21+
})
2122
}
2223
catch {}
2324
}

packages/unconfig/test/run.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,94 @@ it.each([
124124
expect(result2.config).toEqual({
125125
value: 'two',
126126
})
127+
128+
// Test config with default and named exports simultaneously
129+
await writeFile(configPath, `export const config = {
130+
value: 'three',
131+
}
132+
export default config`, 'utf8')
133+
134+
const result3 = await loadConfig({
135+
sources: [{ files: configFileName }],
136+
cwd,
137+
})
138+
139+
expect(result3.config).toEqual({
140+
value: 'three',
141+
})
142+
143+
// Test config with several named exports only
144+
await writeFile(configPath, `export const config1 = {
145+
value1: 'config-1',
146+
}
147+
export const config2= {
148+
value2: 'config-2',
149+
}`, 'utf8')
150+
151+
const result4 = await loadConfig({
152+
sources: [{ files: configFileName }],
153+
cwd,
154+
})
155+
156+
expect(result4.config).toEqual({
157+
config1: {
158+
value1: 'config-1',
159+
},
160+
config2: {
161+
value2: 'config-2',
162+
},
163+
})
164+
165+
// Test config with default and several named exports simultaneously
166+
await writeFile(configPath, `export const config1 = {
167+
value1: 'config-1',
168+
}
169+
export const config2= {
170+
value2: 'config-2',
171+
}
172+
export const config3= {
173+
value3: 'config-3',
174+
}
175+
export default config3`, 'utf8')
176+
177+
const result5 = await loadConfig({
178+
sources: [{ files: configFileName }],
179+
cwd,
180+
})
181+
182+
expect(result5.config).toEqual({
183+
config1: {
184+
value1: 'config-1',
185+
},
186+
config2: {
187+
value2: 'config-2',
188+
},
189+
value3: 'config-3',
190+
})
191+
192+
// Test config when default export property and named export itself have similar names
193+
await writeFile(configPath, `export const config1 = {
194+
value1: 'config-1',
195+
}
196+
export const config2= {
197+
value2: 'config-2',
198+
}
199+
export const config3= {
200+
config1: 'config-3',
201+
}
202+
export default config3`, 'utf8')
203+
204+
const result6 = await loadConfig({
205+
sources: [{ files: configFileName }],
206+
cwd,
207+
})
208+
209+
expect(result6.config).toEqual({
210+
config1: 'config-3',
211+
config2: {
212+
value2: 'config-2',
213+
},
214+
})
127215
})
128216

129217
it('custom parser', async () => {

0 commit comments

Comments
 (0)