Skip to content

Commit

Permalink
Allow calling toString and valueOf on the proxy object
Browse files Browse the repository at this point in the history
Fixes #2509

When a hono client is instantiated in expo and then console.log(client)
is called, an error is thrown:

`TypeError: Cannot determine default value of object`

This is because the hermes javascript engine expects `new String(val)`
to always return a string. But the proxy object would return a
ClientRequestImpl object instead.

This commit makes a string / function returned in the cases where
.toString() and .valueOf() is called on the function.name or function
respectively.

Also see facebook/hermes#205
  • Loading branch information
ibash committed Apr 15, 2024
1 parent 13c3156 commit f33f9b3
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
21 changes: 20 additions & 1 deletion deno_dist/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,28 @@ export const hc = <T extends Hono<any, any, any>>(
baseUrl: string,
options?: ClientRequestOptions
) =>
createProxy((opts) => {
createProxy(function proxyCallback(opts) {
const parts = [...opts.path]

// allow calling .toString() and .valueOf() on the proxy
if (parts[parts.length - 1] === 'toString') {
if (parts[parts.length - 2] === 'name') {
// e.g. hc().somePath.name.toString() -> "somePath"
return parts[parts.length - 3] || ''
}
// e.g. hc().somePath.toString()
return proxyCallback.toString()
}

if (parts[parts.length - 1] === 'valueOf') {
if (parts[parts.length - 2] === 'name') {
// e.g. hc().somePath.name.valueOf() -> "somePath"
return parts[parts.length - 3] || ''
}
// e.g. hc().somePath.valueOf()
return proxyCallback
}

let method = ''
if (/^\$/.test(parts[parts.length - 1])) {
const last = parts.pop()
Expand Down
22 changes: 22 additions & 0 deletions src/client/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,3 +742,25 @@ describe('WebSocket URL Protocol Translation', () => {
expect(webSocketMock).toHaveBeenCalledWith('wss://localhost/index')
})
})

describe('Client can be console.log in react native', () => {
it('Returns a function name with function.name.toString', async () => {
const client = hc('http://localhost')
expect(client.posts.name.toString()).toEqual('posts')
})

it('Returns a function name with function.name.valueOf', async () => {
const client = hc('http://localhost')
expect(client.posts.name.valueOf()).toEqual('posts')
})

it('Returns a function with function.valueOf', async () => {
const client = hc('http://localhost')
expect(typeof client.posts.valueOf()).toEqual('function')
})

it('Returns a function source with function.toString', async () => {
const client = hc('http://localhost')
expect(client.posts.toString()).toMatch('function proxyCallback')
})
})
21 changes: 20 additions & 1 deletion src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,28 @@ export const hc = <T extends Hono<any, any, any>>(
baseUrl: string,
options?: ClientRequestOptions
) =>
createProxy((opts) => {
createProxy(function proxyCallback(opts) {
const parts = [...opts.path]

// allow calling .toString() and .valueOf() on the proxy
if (parts[parts.length - 1] === 'toString') {
if (parts[parts.length - 2] === 'name') {
// e.g. hc().somePath.name.toString() -> "somePath"
return parts[parts.length - 3] || ''
}
// e.g. hc().somePath.toString()
return proxyCallback.toString()
}

if (parts[parts.length - 1] === 'valueOf') {
if (parts[parts.length - 2] === 'name') {
// e.g. hc().somePath.name.valueOf() -> "somePath"
return parts[parts.length - 3] || ''
}
// e.g. hc().somePath.valueOf()
return proxyCallback
}

let method = ''
if (/^\$/.test(parts[parts.length - 1])) {
const last = parts.pop()
Expand Down

0 comments on commit f33f9b3

Please sign in to comment.