mirror of
https://github.com/elysiajs/elysia
synced 2026-08-09 12:35:48 +00:00
Merge branch 'main' into next
This commit is contained in:
+27
-8
@@ -399,18 +399,37 @@ const hasReturn = (v: string | HookContainer<any> | Function) => {
|
||||
? v.fn.toString()
|
||||
: typeof v === 'string'
|
||||
? v.toString()
|
||||
: v
|
||||
: v.toString()
|
||||
|
||||
const parenthesisEnd = fnLiteral.indexOf(')')
|
||||
|
||||
// Is direct arrow function return eg. () => 1
|
||||
if (
|
||||
fnLiteral.charCodeAt(parenthesisEnd + 2) === 61 &&
|
||||
fnLiteral.charCodeAt(parenthesisEnd + 5) !== 123
|
||||
) {
|
||||
if (isObject) v.hasReturn = true
|
||||
// Check for arrow function expression (direct return without braces)
|
||||
// Handle both `) => x` and `)=>x` formats (with or without spaces)
|
||||
const arrowIndex = fnLiteral.indexOf('=>', parenthesisEnd)
|
||||
|
||||
return true
|
||||
if (arrowIndex !== -1) {
|
||||
// Skip any whitespace after `=>` (space, tab, newline, carriage return)
|
||||
let afterArrow = arrowIndex + 2
|
||||
let charCode: number
|
||||
while (
|
||||
afterArrow < fnLiteral.length &&
|
||||
((charCode = fnLiteral.charCodeAt(afterArrow)) === 32 || // space
|
||||
charCode === 9 || // tab
|
||||
charCode === 10 || // newline
|
||||
charCode === 13) // carriage return
|
||||
) {
|
||||
afterArrow++
|
||||
}
|
||||
|
||||
// If the first non-whitespace char after `=>` is not `{`, it's a direct return
|
||||
if (
|
||||
afterArrow < fnLiteral.length &&
|
||||
fnLiteral.charCodeAt(afterArrow) !== 123
|
||||
) {
|
||||
if (isObject) v.hasReturn = true
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
const result = fnLiteral.includes('return')
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
import { describe, expect, it } from 'bun:test'
|
||||
import { Elysia } from '../../src'
|
||||
|
||||
describe('beforeHandle with arrow functions', () => {
|
||||
it('should execute beforeHandle with arrow function expression', async () => {
|
||||
let beforeHandleCalled = false
|
||||
|
||||
const app = new Elysia()
|
||||
.get('/test', () => 'ok', {
|
||||
// Arrow function expression (no braces) - this was broken with minified code
|
||||
beforeHandle: () => {
|
||||
beforeHandleCalled = true
|
||||
}
|
||||
})
|
||||
|
||||
const response = await app.handle(new Request('http://localhost/test'))
|
||||
expect(response.status).toBe(200)
|
||||
expect(beforeHandleCalled).toBe(true)
|
||||
})
|
||||
|
||||
it('should execute beforeHandle with arrow function returning value', async () => {
|
||||
const app = new Elysia()
|
||||
.get('/test', () => 'should not reach', {
|
||||
// Arrow function expression that returns early
|
||||
beforeHandle: () => 'intercepted'
|
||||
})
|
||||
|
||||
const response = await app.handle(new Request('http://localhost/test'))
|
||||
expect(await response.text()).toBe('intercepted')
|
||||
})
|
||||
|
||||
it('should execute async beforeHandle with arrow function expression', async () => {
|
||||
let beforeHandleCalled = false
|
||||
|
||||
const app = new Elysia()
|
||||
.get('/test', () => 'ok', {
|
||||
// Async arrow function expression
|
||||
beforeHandle: async () => {
|
||||
beforeHandleCalled = true
|
||||
}
|
||||
})
|
||||
|
||||
const response = await app.handle(new Request('http://localhost/test'))
|
||||
expect(response.status).toBe(200)
|
||||
expect(beforeHandleCalled).toBe(true)
|
||||
})
|
||||
|
||||
it('should execute beforeHandle with complex arrow expression', async () => {
|
||||
let validatorCalled = false
|
||||
const validator = () => {
|
||||
validatorCalled = true
|
||||
}
|
||||
|
||||
const app = new Elysia()
|
||||
.get('/test', () => 'ok', {
|
||||
// Complex arrow expression like: async ({status}) => requireSignature()({status})
|
||||
// This pattern was broken when code is minified
|
||||
beforeHandle: () => validator()
|
||||
})
|
||||
|
||||
const response = await app.handle(new Request('http://localhost/test'))
|
||||
expect(response.status).toBe(200)
|
||||
expect(validatorCalled).toBe(true)
|
||||
})
|
||||
|
||||
it('should execute beforeHandle with arrow function block', async () => {
|
||||
let beforeHandleCalled = false
|
||||
|
||||
const app = new Elysia()
|
||||
.get('/test', () => 'ok', {
|
||||
// Arrow function with block (this always worked)
|
||||
beforeHandle: () => {
|
||||
beforeHandleCalled = true
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
const response = await app.handle(new Request('http://localhost/test'))
|
||||
expect(response.status).toBe(200)
|
||||
expect(beforeHandleCalled).toBe(true)
|
||||
})
|
||||
|
||||
it('should handle multiple beforeHandle hooks with arrow expressions', async () => {
|
||||
const callOrder: number[] = []
|
||||
|
||||
const app = new Elysia()
|
||||
.get('/test', () => 'ok', {
|
||||
beforeHandle: [
|
||||
() => {
|
||||
callOrder.push(1)
|
||||
},
|
||||
() => {
|
||||
callOrder.push(2)
|
||||
},
|
||||
() => {
|
||||
callOrder.push(3)
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const response = await app.handle(new Request('http://localhost/test'))
|
||||
expect(response.status).toBe(200)
|
||||
expect(callOrder).toEqual([1, 2, 3])
|
||||
})
|
||||
|
||||
// Test with truly minified code (no spaces around arrow)
|
||||
// This simulates what happens when code is bundled and minified
|
||||
it('should execute beforeHandle with truly minified arrow function (no spaces)', async () => {
|
||||
// Construct a function with no spaces: async()=>'intercepted'
|
||||
// This is what real minifiers produce
|
||||
const minifiedHandler = Function("return async()=>'intercepted'")()
|
||||
|
||||
const app = new Elysia().get('/test', () => 'should not reach', {
|
||||
beforeHandle: minifiedHandler
|
||||
})
|
||||
|
||||
const response = await app.handle(new Request('http://localhost/test'))
|
||||
expect(await response.text()).toBe('intercepted')
|
||||
})
|
||||
|
||||
// Test with actual HTTP server (not just app.handle)
|
||||
it('should work with live server', async () => {
|
||||
let beforeHandleCalled = false
|
||||
|
||||
const app = new Elysia()
|
||||
.get('/test', () => 'ok', {
|
||||
beforeHandle: () => {
|
||||
beforeHandleCalled = true
|
||||
}
|
||||
})
|
||||
.listen(0)
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`http://localhost:${app.server?.port}/test`
|
||||
)
|
||||
expect(response.status).toBe(200)
|
||||
expect(beforeHandleCalled).toBe(true)
|
||||
} finally {
|
||||
await app.stop()
|
||||
}
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user