fix: whitespace completely removed in each loop#11937
fix: whitespace completely removed in each loop#11937paoloricciuti wants to merge 1 commit intosveltejs:mainfrom paoloricciuti:fix-whitespace-in-each
Conversation
🦋 Changeset detectedLatest commit: 170ef6f The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
I believe the purpose of using export function set_text(dom, value) {
const next = stringify(value);
if (dom.nodeValue !== next) {
dom.nodeValue = next;
}
}@trueadm might have more background. It was introduced here: https://github.com/sveltejs/svelte-octane/pull/413 |
|
Another thing that would work is changing the default I'd be curious to see some benchmarks to know whether we're gaining anything by using |
|
Maybe the __nodeValue should be ‘ ‘ instead? It definitely is faster than reading the he getter, as the getter has overhead that we want to avoid. |
There's a comment about this specific issue too https://github.com/sveltejs/svelte-octane/pull/413#discussion_r1347106724 |
What do you mean? It's already |
|
We could do this check only when the value is |
|
I'm doing some microbenchmarks locally, and Text.prototype.__x = '';
const iterations = 1e6;
function a() {
console.time('expando property on prototype');
for (let i = 0; i < iterations; i += 1) {
const text = document.createTextNode('');
if (text.__x !== i) {
text.__x = i;
text.nodeValue = '' + i;
}
}
console.timeEnd('expando property on prototype');
}
function b() {
console.time('expando property not on prototype');
for (let i = 0; i < iterations; i += 1) {
const text = document.createTextNode('');
if (text.__y !== i) {
text.__y = i;
text.nodeValue = '' + i;
}
}
console.timeEnd('expando property not on prototype');
}
function c() {
console.time('nodeValue with explicit coercion');
for (let i = 0; i < iterations; i += 1) {
const text = document.createTextNode('');
const str = '' + i;
if (text.nodeValue !== str) {
text.nodeValue = str;
}
}
console.timeEnd('nodeValue with explicit coercion');
}
function d() {
console.time('nodeValue with implicit coercion');
for (let i = 0; i < iterations; i += 1) {
const text = document.createTextNode('');
if (text.nodeValue !== i) {
text.nodeValue = i;
}
}
console.timeEnd('nodeValue with implicit coercion');
}AFAICT reading |
|
Actually, subsequent |
|
I'll take a look into this properly tomorrow. |
Svelte 5 rewrite
Closes #11932
I don't know if this is the best fix but basically the problem is that the empty text node that get passed to
set_textis never touched if the text to update is' '...this is because theprev_node_valuewasdom.__nodeValuewhich by default is' '. However the actual text of the text node is''. So this is never touched and the result is that every node that has' 'is basically cancelled.My fix was to check if
nodeValueand__nodeValueare equals so that if they are notnodeValueis given precedence asprev_node_value.Other fixes i've thought of are:
__touchedproperty yoTextNodeprototype so that we know if the node has ben touched or not. I think messing with the prototype is worst than this.__nodeValue===' 'since the dissonance between the default value of__nodeValueand the "default value" of the empty text node is what's causing the issue.let me know if you think one of those two solutions is better.
Please note that the Svelte codebase is currently being rewritten for Svelte 5. Changes should target Svelte 5, which lives on the default branch (
main).If your PR concerns Svelte 4 (including updates to svelte.dev.docs), please ensure the base branch is
svelte-4and notmain.Before submitting the PR, please make sure you do the following
feat:,fix:,chore:, ordocs:.Tests and linting
pnpm testand lint the project withpnpm lint