Skip to content

Commit 0699621

Browse files
committed
🔧 fix: #1416 check if object is frozen before merging, add try-catch to prevent crash
1 parent 17d5086 commit 0699621

File tree

5 files changed

+22
-96
lines changed

5 files changed

+22
-96
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Improvement:
44
- coerce union status value and return type
55
- add `BunHTMLBundleLike` to Elysia inline handler
66
- prevent Elysia from being a dependency of itself
7+
- [#1416](https://github.com/elysiajs/elysia/issues/1416) check if object is frozen before merging, add try-catch to prevent crash
78
- [#1419](https://github.com/elysiajs/elysia/issues/1419) guard doesn't apply scoped/global schema to object macro
89
- [#1425](https://github.com/elysiajs/elysia/issues/1425) DELETE doesn't ihnerit derive/resolve type
910

example/a.ts

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,5 @@
11
import { Elysia, t } from '../src'
2-
import { openapi } from '@elysiajs/openapi'
32

4-
const macroMiddleware1 = new Elysia({ name: 'my-middleware-1' })
5-
.guard({
6-
as: 'scoped',
7-
headers: t.Object({
8-
role: t.UnionEnum(['admin', 'user'])
9-
}),
10-
body: t.Object({
11-
foo: t.String()
12-
})
13-
})
14-
.macro({
15-
auth: {
16-
resolve: ({
17-
headers, // Record<string, string | undefined> <------- ERROR IS HERE - should be typed
18-
body // unknown <------- ERROR IS HERE - should be typed
19-
}) => {
20-
console.log('headers and body are still validated at runtime!')
21-
console.log(headers, body) // will not allow e.g. headers: { foo: 123 }
22-
}
23-
}
24-
})
25-
26-
const macroMiddleware2 = new Elysia({ name: 'my-middleware-2' })
27-
.guard({
28-
as: 'scoped',
29-
headers: t.Object({
30-
role: t.UnionEnum(['admin', 'user'])
31-
}),
32-
body: t.Object({
33-
foo: t.String()
34-
})
35-
})
36-
.macro('auth', {
37-
resolve: ({
38-
headers, // { role: "admin" | "user" } <------- no error
39-
body // { foo: string } <------- no error
40-
}) => {
41-
console.log('headers and body are still validated at runtime!')
42-
console.log(headers, body) // will not allow e.g. headers: { foo: 123 }
43-
}
44-
})
45-
46-
const app1 = new Elysia()
47-
.use(macroMiddleware1)
48-
.post('/', () => 'Hello World 1', {
49-
auth: true
50-
})
51-
52-
const app2 = new Elysia()
53-
.use(macroMiddleware2)
54-
.post('/', () => 'Hello World 2', {
55-
auth: true
56-
})
3+
new Elysia()
4+
.decorate("db", Object.freeze({ hello: "world" }))
5+
.guard({}, app => app)

src/utils.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,17 +81,22 @@ export const mergeDeep = <
8181
}
8282

8383
if (!isObject(value) || !(key in target) || isClass(value)) {
84-
if (override || !(key in target))
85-
target[key as keyof typeof target] = value
84+
if ((override || !(key in target)) && !Object.isFrozen(target))
85+
try {
86+
target[key as keyof typeof target] = value
87+
} catch {}
8688

8789
continue
8890
}
8991

90-
target[key as keyof typeof target] = mergeDeep(
91-
(target as any)[key] as any,
92-
value,
93-
{ skipKeys, override, mergeArray }
94-
)
92+
if (!Object.isFrozen(target[key]))
93+
try {
94+
target[key as keyof typeof target] = mergeDeep(
95+
(target as any)[key] as any,
96+
value,
97+
{ skipKeys, override, mergeArray }
98+
)
99+
} catch {}
95100
}
96101

97102
return target as A & B

test/a.test.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.

test/units/merge-deep.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,10 @@ describe('mergeDeep', () => {
8080

8181
expect(response).toBe('ok')
8282
})
83+
84+
it('handle freezed object', () => {
85+
new Elysia()
86+
.decorate('db', Object.freeze({ hello: 'world' }))
87+
.guard({}, (app) => app)
88+
})
8389
})

0 commit comments

Comments
 (0)