Skip to content

Commit

Permalink
fix(jsx): ignore function object in attribute value in toString() (#2161
Browse files Browse the repository at this point in the history
)

* refactor(jsx): ignore function object in attribute value in toString()

* test(jsx): fix lint error

* chore: denoify
  • Loading branch information
usualoma committed Feb 7, 2024
1 parent 82dab25 commit 1549c70
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 1 deletion.
5 changes: 5 additions & 0 deletions deno_dist/jsx/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ export class JSXNode implements HtmlEscaped {
} else if (v instanceof Promise) {
buffer[0] += ` ${key}="`
buffer.unshift('"', v)
} else if (typeof v === 'function') {
if (!key.startsWith('on')) {
throw `Invalid prop '${key}' of type 'function' supplied to '${tag}'.`
}
// maybe event handler for client components, just ignore in server components
} else {
buffer[0] += ` ${key}="`
escapeToBuffer(v.toString(), buffer)
Expand Down
5 changes: 5 additions & 0 deletions src/jsx/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ export class JSXNode implements HtmlEscaped {
} else if (v instanceof Promise) {
buffer[0] += ` ${key}="`
buffer.unshift('"', v)
} else if (typeof v === 'function') {
if (!key.startsWith('on')) {
throw `Invalid prop '${key}' of type 'function' supplied to '${tag}'.`
}
// maybe event handler for client components, just ignore in server components
} else {
buffer[0] += ` ${key}="`
escapeToBuffer(v.toString(), buffer)
Expand Down
14 changes: 14 additions & 0 deletions src/jsx/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,20 @@ describe('render to string', () => {
})
})

describe('Function', () => {
it('should be ignored used in on* props', () => {
const onClick = () => {}
const template = <button onClick={onClick}>Click</button>
expect(template.toString()).toBe('<button>Click</button>')
})

it('should raise an error if used in other props', () => {
const onClick = () => {}
const template = <button data-handler={onClick}>Click</button>
expect(() => template.toString()).toThrow()
})
})

// https://en.reactjs.org/docs/jsx-in-depth.html#functions-as-children
describe('Functions as Children', () => {
it('Function', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/jsx/streaming.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { JSDOM } from 'jsdom'
import { raw } from '../helper/html'
import { HtmlEscapedCallbackPhase, resolveCallback } from '../utils/html'
import type { HtmlEscapedString } from '../utils/html'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { jsx, Fragment } from './base'
import { use } from './hooks'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { Suspense, renderToReadableStream } from './streaming'

function replacementResult(html: string) {
Expand Down

0 comments on commit 1549c70

Please sign in to comment.