Improve escape_html_attr performance - #4024
Conversation
| '"': '"' | ||
| }; | ||
|
|
||
| const escape_html_attr_regex = new RegExp( |
There was a problem hiding this comment.
can we add a comment about why this is needed?
There was a problem hiding this comment.
Why delete < and >
they break HTML if not escaped
we had issue #3773
There was a problem hiding this comment.
@PH4NTOMiki That was about escape_json_in_html, this is about escape_html_attr.
@benmccann Sorry about the comments, the previous code didn't have them and I thought they weren't necessary. I'll add some.
c6de435 to
4514809
Compare
|
4514809 to
4d146d0
Compare
|
Nice, I did a naive benchmark locally and this is way faster |
Resolves the TODO in `escape.js` from #4024, which planned to simplify the surrogate pattern with lookbehind assertions once widely supported. Lookbehind has been safe everywhere relevant since Safari 16.4, but `\p{Surrogate}` with the `u` flag is simpler still and supported even longer (ES2018). Under the `u` flag a valid surrogate pair forms a single astral code point, so `\p{Surrogate}` matches only unpaired surrogates and the pattern's other two branches disappear, including the branch that existed only to match valid pairs so the replace callback could return them unchanged. That branch is also why this is a perf change rather than a cleanup. Every valid pair in rendered content currently invokes the replace callback just to pass through. With the new pattern pairs never match, so `escape_html` measures about 2x faster on emoji-heavy content in a quick microbench, with plain ASCII at parity. Output is unchanged. I diffed the old and new implementations over 200k fuzzed strings built from surrogate halves, dict characters and astral pairs, plus curated edge cases, in both modes, all byte-identical. `escape.spec.js` passes as-is. --- ### Please don't delete this checklist! Before submitting the PR, please make sure you do the following: - [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs - [x] This message body should clearly illustrate what problems it solves. - [ ] Ideally, include a test that fails without this PR but passes with it. ### Tests - [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check` ### Changesets - [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`. ### Edits - [x] Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.
Closes #4016.
Depends on #4015.
Replaces the character-by-character loop with a regex-based
str.replacecall.Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm testand lint the project withpnpm lintandpnpm checkChangesets
pnpx changesetand following the prompts. All changesets should bepatchuntil SvelteKit 1.0