Last 12 weeks · 146 commits
5 of 6 standards met
Problem During JSX DOM children reconciliation in , each child in searches using and removes the matched node via . When reconciling large child lists where the order is preserved or appended, this produces $O(N^2)$ linear searches and array shift operations. Root Cause Reconciliation did not check the head of before falling back to full-array and . Fix Check if matches the current child (by string type, key+tag, or tag) and consume it directly via , reducing lookup from $O(N)$ to $O(1)$ for in-order children, while retaining and fallback for reordered or interspersed items. Related to #5306 Testing 1. Added unit test in verifying reconciliation and reordering across 100 keyed items. 2. Ran (all 24 test files pass, 1296 passed).
Summary Fixes an issue where on elements with children (such as HTML void elements `undefined[undefined]src/jsx/base.tscloneElementprops.children``ts const c = (element as JSXNode).props.children childrenToClone = Array.isArray(c) ? c : [c] When an element has no children (e.g. ), props.children is undefined. Because c was undefined, Array.isArray(c) ? c : [c] evaluated to [undefined], passing an array of length 1 containing undefined to jsx(). During SSR stringification (JSXNode.prototype.toStringToBuffer), the self-closing check emptyTags.includes(tag) && children.length === 0 failed because children.length was 1. This resulted in invalid non-self-closing HTML tags like instead of . ###Solution Check if c !== undefined before wrapping it into an array: childrenToClone = c !== undefined ? (Array.isArray(c) ? c : [c]) : [] ###Verification Added a unit test in src/jsx/base.test.tsx verifying that cloning a void element (e.g. cloneElement(, { alt: 'bar' })) preserves self-closing HTML output.
returns the same handler more than once when a request path segment is literally a pattern token. stores a pattern node in under its own key as well as in , so a part equal to that key reaches the node twice — once through the literal lookup, once through the pattern loop. The copies compound per segment: route matched by the path returned the handler 8 times, and 16 times. Because the match list is the middleware chain, this runs middleware more than once: The path doesn't have to be written by hand — decodes the segment, so a request for arrives as , and as . The fix The literal branch does three jobs, and each has to stand down for the patterns the loop already covers — which is a different set for each: the push: the loop makes this itself when an array pattern matches, and never for a string one, so and a prefixed wildcard still need it here; the terminal push: the loop makes it for any pattern node whose pattern accepts the part; the descent: the loop descends through and parameters itself, but not through a prefixed wildcard, so that one still descends from here. Gating all three on one predicate does not work. In particular the push must be gated on , not on "is a pattern node" — the latter drops real matches ( + at path loses the handler, and + at likewise). The existing router suite passes under the wrong gate, so that distinction isn't covered by current tests. Behaviour changes beyond de-duplication Matches are removed where the literal lookup was the only route to a pattern node. Two shapes: 1. A constrained parameter whose regexp rejects its own key. , and reject theirs; accepts. So no longer matches the path , and neither do routes carrying anything after that node (, ). RegExpRouter and PatternRouter return nothing in all of these. 2. A parameter that is not the last segment, e.g. . Its regexp runs against the rest of the path rather than the segment, so the loop consumes the whole remainder and the segment after it is never reached. The literal lookup was the only way through, so on such a route matched only when that segment was literally — already returned nothing. PatternRouter still matches these; RegExpRouter rejects the route outright. Ordinary paths are unaffected in both: still matches , and a terminal is untouched ( still matches and ). Verification Over a corpus of one route per router, with routes and paths being every one-to-three-segment sequence of the tokens , , , , , and — 399 of each, so 159,201 combinations: results containing a repeated handler: 8,008 on , 0 here; combinations disagreeing with both and : 1,478 on , 144 here, and every one of the 144 already disagreed on — nothing new disagrees; no added matches, and no changed params on a surviving match. Tests go in the shared router suite so every configuration covers them. Five of the six run all six new cases; throws for a parameter with a trailing wildcard, so that one case carries a skip alongside its existing entries. Relationship to #5243 Independent of #5243, but the two touch the same lines of and conflict textually in (both insert a block at the same anchor). If #5243 lands first, the descent gate here needs revisiting: its pattern loop walks prefixed wildcards too, which this change deliberately leaves to the literal branch.
Fixes #5310 Description Per RFC 9110 §12.5.1 and §12.5.4, a quality value of indicates that a representation is explicitly not acceptable. The middleware already filters out entries, but in and in the middleware were matching candidates when present. This change skips entries with in both and , falling through to subsequent acceptable values or configured defaults, and adds test coverage including subtype wildcards ( and ). The author should do the following, if applicable [x] Add tests [x] Run tests [x] to format the code [ ] Add TSDoc/JSDoc to document the code
Repository: honojs/hono. Description: Web framework built on Web Standards Stars: 32100, Forks: 1287. Primary language: TypeScript. Languages: TypeScript (99.8%), JavaScript (0.2%), Shell (0%), HTML (0%). License: MIT. Homepage: https://hono.dev Topics: aws-lambda, bun, cloudflare, cloudflare-workers, deno, npm, router, typescript, web-framework. Latest release: v4.13.7 (1d ago). Open PRs: 100, open issues: 281. Last activity: 7m ago. Community health: 75%. Top contributors: yusukebe, usualoma, EdamAme-x, watany-dev, ryuapp, nakasyou, metrue, exoego, sor4chi, yasuaki640 and others.