Skip to content

Commit 0a06a3f

Browse files
authored
feat: skip over static subtrees (#12849)
* feat: skip over static subtrees * regenerate * a few more * prettier
1 parent 6b6f915 commit 0a06a3f

File tree

40 files changed

+184
-90
lines changed

40 files changed

+184
-90
lines changed

.changeset/neat-ducks-jam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
feat: skip over static subtrees

packages/svelte/src/compiler/phases/1-parse/utils/create.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ export function create_fragment(transparent = false) {
77
return {
88
type: 'Fragment',
99
nodes: [],
10-
transparent
10+
metadata: {
11+
transparent,
12+
dynamic: false
13+
}
1114
};
1215
}

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ import { TaggedTemplateExpression } from './visitors/TaggedTemplateExpression.js
6161
import { Text } from './visitors/Text.js';
6262
import { TitleElement } from './visitors/TitleElement.js';
6363
import { UpdateExpression } from './visitors/UpdateExpression.js';
64+
import { UseDirective } from './visitors/UseDirective.js';
6465
import { VariableDeclarator } from './visitors/VariableDeclarator.js';
6566
import is_reference from 'is-reference';
6667

@@ -166,6 +167,7 @@ const visitors = {
166167
Text,
167168
TitleElement,
168169
UpdateExpression,
170+
UseDirective,
169171
VariableDeclarator
170172
};
171173

packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/** @import { ArrowFunctionExpression, Expression, FunctionDeclaration, FunctionExpression } from 'estree' */
2-
/** @import { Attribute, DelegatedEvent, RegularElement } from '#compiler' */
2+
/** @import { Attribute, DelegatedEvent, RegularElement, SvelteNode } from '#compiler' */
33
/** @import { Context } from '../types' */
44
import { is_capture_event, is_delegated } from '../../../../utils.js';
55
import {
66
get_attribute_chunks,
77
get_attribute_expression,
88
is_event_attribute
99
} from '../../../utils/ast.js';
10+
import { mark_subtree_dynamic } from './shared/fragment.js';
1011

1112
/**
1213
* @param {Attribute} node
@@ -15,6 +16,14 @@ import {
1516
export function Attribute(node, context) {
1617
context.next();
1718

19+
// special case
20+
if (node.name === 'value') {
21+
const parent = /** @type {SvelteNode} */ (context.path.at(-1));
22+
if (parent.type === 'RegularElement' && parent.name === 'option') {
23+
mark_subtree_dynamic(context.path);
24+
}
25+
}
26+
1827
if (node.value !== true) {
1928
for (const chunk of get_attribute_chunks(node.value)) {
2029
if (chunk.type !== 'ExpressionTag') continue;

packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitBlock.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/** @import { Context } from '../types' */
33
import { validate_block_not_empty, validate_opening_tag } from './shared/utils.js';
44
import * as e from '../../../errors.js';
5+
import { mark_subtree_dynamic } from './shared/fragment.js';
56

67
/**
78
* @param {AwaitBlock} node
@@ -38,5 +39,7 @@ export function AwaitBlock(node, context) {
3839
}
3940
}
4041

42+
mark_subtree_dynamic(context.path);
43+
4144
context.next();
4245
}

packages/svelte/src/compiler/phases/2-analyze/visitors/EachBlock.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/** @import { Context } from '../types' */
33
/** @import { Scope } from '../../scope' */
44
import * as e from '../../../errors.js';
5+
import { mark_subtree_dynamic } from './shared/fragment.js';
56
import { validate_block_not_empty, validate_opening_tag } from './shared/utils.js';
67

78
/**
@@ -36,4 +37,6 @@ export function EachBlock(node, context) {
3637
context.visit(node.body);
3738
if (node.key) context.visit(node.key);
3839
if (node.fallback) context.visit(node.fallback);
40+
41+
mark_subtree_dynamic(context.path);
3942
}

packages/svelte/src/compiler/phases/2-analyze/visitors/ExpressionTag.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/** @import { Context } from '../types' */
33
import { is_tag_valid_with_parent } from '../../../../html-tree-validation.js';
44
import * as e from '../../../errors.js';
5+
import { mark_subtree_dynamic } from './shared/fragment.js';
56

67
/**
78
* @param {ExpressionTag} node
@@ -14,5 +15,9 @@ export function ExpressionTag(node, context) {
1415
}
1516
}
1617

18+
// TODO ideally we wouldn't do this here, we'd just do it on encountering
19+
// an `Identifier` within the tag. But we currently need to handle `{42}` etc
20+
mark_subtree_dynamic(context.path);
21+
1722
context.next({ ...context.state, expression: node.metadata.expression });
1823
}

packages/svelte/src/compiler/phases/2-analyze/visitors/HtmlTag.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/** @import { HtmlTag } from '#compiler' */
22
/** @import { Context } from '../types' */
3+
import { mark_subtree_dynamic } from './shared/fragment.js';
34
import { validate_opening_tag } from './shared/utils.js';
45

56
/**
@@ -11,5 +12,8 @@ export function HtmlTag(node, context) {
1112
validate_opening_tag(node, context.state, '@');
1213
}
1314

15+
// unfortunately this is necessary in order to fix invalid HTML
16+
mark_subtree_dynamic(context.path);
17+
1418
context.next();
1519
}

packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { should_proxy } from '../../3-transform/client/utils.js';
66
import * as e from '../../../errors.js';
77
import * as w from '../../../warnings.js';
88
import { is_rune } from '../../../../utils.js';
9+
import { mark_subtree_dynamic } from './shared/fragment.js';
910

1011
/**
1112
* @param {Identifier} node
@@ -19,6 +20,8 @@ export function Identifier(node, context) {
1920
return;
2021
}
2122

23+
mark_subtree_dynamic(context.path);
24+
2225
// If we are using arguments outside of a function, then throw an error
2326
if (
2427
node.name === 'arguments' &&

packages/svelte/src/compiler/phases/2-analyze/visitors/IfBlock.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/** @import { IfBlock } from '#compiler' */
22
/** @import { Context } from '../types' */
3+
import { mark_subtree_dynamic } from './shared/fragment.js';
34
import { validate_block_not_empty, validate_opening_tag } from './shared/utils.js';
45

56
/**
@@ -22,5 +23,7 @@ export function IfBlock(node, context) {
2223
validate_opening_tag(node, context.state, expected);
2324
}
2425

26+
mark_subtree_dynamic(context.path);
27+
2528
context.next();
2629
}

0 commit comments

Comments
 (0)