Skip to content

Commit 72f93e3

Browse files
committed
chore: sprinkle comments here and there
1 parent 4daa63a commit 72f93e3

File tree

6 files changed

+50
-2
lines changed

6 files changed

+50
-2
lines changed

packages/svelte/src/compiler/phases/3-transform/client/transform-client.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ export function client_component(analysis, options) {
167167
in_constructor: false,
168168
instance_level_snippets: [],
169169
module_level_snippets: [],
170-
is_functional_template_mode: options.templatingMode === 'functional',
170+
is_functional_template_mode: true, //options.templatingMode === 'functional',
171171

172172
// these are set inside the `Fragment` visitor, and cannot be used until then
173173
init: /** @type {any} */ (null),

packages/svelte/src/compiler/phases/3-transform/client/transform-template/to-functions.js

+25
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,20 @@ export function template_to_functions(items, namespace) {
5757
*/
5858
let last_current_element;
5959

60+
// if the first item is a comment we need to add another comment for effect.start
6061
if (items[0].kind === 'create_anchor') {
6162
items.unshift({ kind: 'create_anchor' });
6263
}
6364

6465
for (let instruction of items) {
66+
// on push element we add the element to the stack, from this moment on every insert will
67+
// happen on the last element in the stack
6568
if (instruction.kind === 'push_element' && last_current_element) {
6669
elements_stack.push(last_current_element);
6770
continue;
6871
}
72+
// we closed one element, we remove it from the stack and eventually revert back
73+
// the namespace to the previous one
6974
if (instruction.kind === 'pop_element') {
7075
const removed = elements_stack.pop();
7176
if (removed?.namespaced) {
@@ -77,14 +82,21 @@ export function template_to_functions(items, namespace) {
7782
continue;
7883
}
7984

85+
// if the inserted node is in the svg/mathml we push the namespace to the stack because we need to
86+
// create with createElementNS
8087
if (instruction.metadata?.svg || instruction.metadata?.mathml) {
8188
namespace_stack.push(instruction.metadata.svg ? NAMESPACE_SVG : NAMESPACE_MATHML);
8289
}
8390

8491
// @ts-expect-error we can't be here if `swap_current_element` but TS doesn't know that
8592
const value = map[instruction.kind](
8693
...[
94+
// for set prop we need to send the last element (not the one in the stack since
95+
// it get's added to the stack only after the push_element instruction)...for all the rest
96+
// the first prop is a the scope to generate the name of the variable
8797
...(instruction.kind === 'set_prop' ? [last_current_element] : [scope]),
98+
// for create element we also need to add the namespace...namespaces in the stack get's precedence over
99+
// the "global" namespace (and if we are in a foreignObject we default to html)
88100
...(instruction.kind === 'create_element'
89101
? [
90102
foreign_object_count > 0
@@ -102,16 +114,20 @@ export function template_to_functions(items, namespace) {
102114
);
103115

104116
if (value) {
117+
// this will compose the body of the function
105118
body.push(value.call);
106119
}
107120

121+
// with set_prop we don't need to do anything else, in all other cases we also need to
122+
// append the element/node/anchor to the current active element or push it in the elements array
108123
if (instruction.kind !== 'set_prop') {
109124
if (elements_stack.length >= 1 && value) {
110125
const { call } = map.insert(/** @type {Element} */ (elements_stack.at(-1)), value);
111126
body.push(call);
112127
} else if (value) {
113128
elements.push(b.id(value.name));
114129
}
130+
// keep track of the last created element (it will be pushed to the stack after the props are set)
115131
if (instruction.kind === 'create_element') {
116132
last_current_element = /** @type {Element} */ (value);
117133
if (last_current_element.element === 'foreignObject') {
@@ -120,6 +136,7 @@ export function template_to_functions(items, namespace) {
120136
}
121137
}
122138
}
139+
// every function needs to return a fragment so we create one and push all the elements there
123140
const fragment = scope.generate('fragment');
124141
body.push(b.var(fragment, b.call('document.createDocumentFragment')));
125142
body.push(b.call(fragment + '.append', ...elements));
@@ -159,6 +176,11 @@ function create_element(scope, namespace, element) {
159176
}
160177
const call = b.var(name, b.call(fn, ...args));
161178
/**
179+
* if there's an "is" attribute we can't just add it as a property, it needs to be
180+
* specified on creation like this `document.createElement('button', { is: 'my-button' })`
181+
*
182+
* Since the props are appended after the creation we change the generated call arguments and we push
183+
* the is attribute later on on `set_prop`
162184
* @param {string} value
163185
*/
164186
function add_is(value) {
@@ -208,6 +230,7 @@ function create_text(scope, value) {
208230
* @param {string} value
209231
*/
210232
function set_prop(el, prop, value) {
233+
// see comment above about the "is" attribute
211234
if (prop === 'is') {
212235
el.add_is(value);
213236
return;
@@ -217,6 +240,7 @@ function set_prop(el, prop, value) {
217240
let fn = namespace !== prop ? '.setAttributeNS' : '.setAttribute';
218241
let args = [b.literal(fix_attribute_casing(prop)), b.literal(value ?? '')];
219242

243+
// attributes like `xlink:href` need to be set with the `xlink` namespace
220244
if (namespace === 'xlink') {
221245
args.unshift(b.literal('http://www.w3.org/1999/xlink'));
222246
}
@@ -235,6 +259,7 @@ function set_prop(el, prop, value) {
235259
function insert(el, child, anchor) {
236260
return {
237261
call: b.call(
262+
// if we have a template element we need to push into it's content rather than the element itself
238263
el.name + (el.element === 'template' ? '.content' : '') + '.insertBefore',
239264
b.id(child.name),
240265
b.id(anchor?.name ?? 'undefined')

packages/svelte/src/compiler/phases/3-transform/client/transform-template/to-string.js

+13
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ export function template_to_string(items) {
2020
let last_current_element;
2121

2222
for (let instruction of items) {
23+
// on push element we add the element to the stack, from this moment on every insert will
24+
// happen on the last element in the stack
2325
if (instruction.kind === 'push_element' && last_current_element) {
2426
elements_stack.push(last_current_element);
2527
continue;
2628
}
29+
// we closed one element, we remove it from the stack
2730
if (instruction.kind === 'pop_element') {
2831
elements_stack.pop();
2932
continue;
@@ -34,16 +37,21 @@ export function template_to_string(items) {
3437
// @ts-expect-error we can't be here if `swap_current_element` but TS doesn't know that
3538
const value = map[instruction.kind](
3639
...[
40+
// for set prop we need to send the last element (not the one in the stack since
41+
// it get's added to the stack only after the push_element instruction)
3742
...(instruction.kind === 'set_prop' ? [last_current_element] : []),
3843
...(instruction.args ?? [])
3944
]
4045
);
46+
// with set_prop we don't need to do anything else, in all other cases we also need to
47+
// append the element/node/anchor to the current active element or push it in the elements array
4148
if (instruction.kind !== 'set_prop') {
4249
if (elements_stack.length >= 1 && value) {
4350
map.insert(/** @type {Element} */ (elements_stack.at(-1)), value);
4451
} else if (value) {
4552
elements.push(value);
4653
}
54+
// keep track of the last created element (it will be pushed to the stack after the props are set)
4755
if (instruction.kind === 'create_element') {
4856
last_current_element = /** @type {Element} */ (value);
4957
}
@@ -141,18 +149,23 @@ let map = {
141149
function stringify(el) {
142150
let str = ``;
143151
if (el.kind === 'element') {
152+
// we create the <tagname part
144153
str += `<${el.element}`;
154+
// we concatenate all the prop to it
145155
for (let [prop, value] of Object.entries(el.props ?? {})) {
146156
if (value == null) {
147157
str += ` ${prop}`;
148158
} else {
149159
str += ` ${prop}="${value}"`;
150160
}
151161
}
162+
// then we close the opening tag
152163
str += `>`;
164+
// we stringify all the children and concatenate them
153165
for (let child of el.children ?? []) {
154166
str += stringify(child);
155167
}
168+
// if it's not void we also add the closing tag
156169
if (!is_void(el.element)) {
157170
str += `</${el.element}>`;
158171
}

packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ export function RegularElement(node, context) {
124124
kind: 'set_prop',
125125
args: [
126126
'is',
127+
// if we are using the functional template mode we don't want to escape since we will
128+
// create a text node from it which is already escaped
127129
context.state.is_functional_template_mode
128130
? value.value
129131
: escape_html(value.value, true)
@@ -312,7 +314,9 @@ export function RegularElement(node, context) {
312314
: [
313315
value === true
314316
? ''
315-
: context.state.is_functional_template_mode
317+
: // if we are using the functional template mode we don't want to escape since we will
318+
// create a text node from it which is already escaped
319+
context.state.is_functional_template_mode
316320
? value
317321
: escape_html(value, true)
318322
]

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js

+2
Original file line numberDiff line numberDiff line change
@@ -427,11 +427,13 @@ export function build_component(node, component_name, context, anchor = context.
427427
*/
428428
const template_operations = [];
429429
if (context.state.metadata.namespace === 'svg') {
430+
// this boils down to <g><!></g>
430431
template_operations.push({ kind: 'create_element', args: ['g'] });
431432
template_operations.push({ kind: 'push_element' });
432433
template_operations.push({ kind: 'create_anchor' });
433434
template_operations.push({ kind: 'pop_element' });
434435
} else {
436+
// this boils down to <svelte-css-wrapper style='display: contents'><!></svelte-css-wrapper>
435437
template_operations.push({ kind: 'create_element', args: ['svelte-css-wrapper'] });
436438
template_operations.push({ kind: 'set_prop', args: ['style', 'display: contents'] });
437439
template_operations.push({ kind: 'push_element' });

packages/svelte/src/compiler/phases/3-transform/utils.js

+4
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,16 @@ export function clean_nodes(
276276
// initial newline inside a `<pre>` is disregarded, if not followed by another newline
277277
if (
278278
parent.type === 'RegularElement' &&
279+
// we also want to do the replacement on the textarea if we are in functional template mode because createTextNode behave differently
280+
// then template.innerHTML
279281
(parent.name === 'pre' || (is_functional_template_mode && parent.name === 'textarea')) &&
280282
first?.type === 'Text'
281283
) {
282284
const text = first.data.replace(regex_starts_with_newline, '');
283285
if (text !== first.data) {
284286
const tmp = text.replace(regex_starts_with_newline, '');
287+
// do an extra replacement if we are in functional template mode because createTextNode behave differently
288+
// then template.innerHTML
285289
if (text === tmp || is_functional_template_mode) {
286290
first.data = text;
287291
first.raw = first.raw.replace(regex_starts_with_newline, '');

0 commit comments

Comments
 (0)