ripple 0.2.68 → 0.2.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/compiler/phases/1-parse/index.js +131 -0
- package/src/compiler/phases/2-analyze/index.js +17 -11
- package/src/compiler/phases/3-transform/index.js +78 -31
- package/src/compiler/scope.js +403 -397
- package/src/compiler/utils.js +16 -0
- package/src/constants.js +4 -0
- package/src/runtime/array.js +33 -24
- package/src/runtime/internal/client/for.js +69 -31
- package/src/runtime/internal/client/render.js +9 -3
- package/src/runtime/internal/client/template.js +51 -5
- package/tests/__snapshots__/basic.test.ripple.snap +18 -0
- package/tests/__snapshots__/for.test.ripple.snap +78 -0
- package/tests/basic.test.ripple +15 -0
- package/tests/for.test.ripple +32 -2
- package/tests/svg.test.ripple +282 -0
package/src/compiler/utils.js
CHANGED
|
@@ -378,6 +378,18 @@ export function is_component_level_function(context) {
|
|
|
378
378
|
return true;
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
+
export function is_ripple_track_call(callee, context) {
|
|
382
|
+
return (
|
|
383
|
+
(callee.type === 'Identifier' && callee.name === 'track') ||
|
|
384
|
+
(callee.type === 'MemberExpression' &&
|
|
385
|
+
callee.object.type === 'Identifier' &&
|
|
386
|
+
callee.property.type === 'Identifier' &&
|
|
387
|
+
callee.property.name === 'track' &&
|
|
388
|
+
!callee.computed &&
|
|
389
|
+
is_ripple_import(callee, context))
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
381
393
|
export function is_inside_call_expression(context) {
|
|
382
394
|
for (let i = context.path.length - 1; i >= 0; i -= 1) {
|
|
383
395
|
const context_node = context.path[i];
|
|
@@ -391,6 +403,10 @@ export function is_inside_call_expression(context) {
|
|
|
391
403
|
return false;
|
|
392
404
|
}
|
|
393
405
|
if (type === 'CallExpression') {
|
|
406
|
+
const callee = context_node.callee;
|
|
407
|
+
if (is_ripple_track_call(callee, context)) {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
394
410
|
return true;
|
|
395
411
|
}
|
|
396
412
|
}
|
package/src/constants.js
CHANGED
package/src/runtime/array.js
CHANGED
|
@@ -105,17 +105,24 @@ function proxy({ elements, block, from_static = false, use_array = false }) {
|
|
|
105
105
|
|
|
106
106
|
var result = Reflect.get(target, prop, receiver);
|
|
107
107
|
|
|
108
|
-
if (typeof result ===
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
if (typeof result === 'function') {
|
|
109
|
+
if (methods_returning_arrays.has(prop)) {
|
|
110
|
+
/** @type {(this: any, ...args: any[]) => any} */
|
|
111
|
+
return function (...args) {
|
|
112
|
+
var output = Reflect.apply(result, receiver, args);
|
|
113
|
+
|
|
114
|
+
if (Array.isArray(output) && output !== target) {
|
|
115
|
+
return proxy({ elements: output, block, use_array: true });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return output;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
116
121
|
|
|
117
|
-
|
|
118
|
-
|
|
122
|
+
// When generating an iterator, we need to ensure that length is tracked
|
|
123
|
+
if (prop === 'entries' || prop === 'values' || prop === 'keys') {
|
|
124
|
+
receiver.length;
|
|
125
|
+
}
|
|
119
126
|
}
|
|
120
127
|
|
|
121
128
|
return result;
|
|
@@ -229,14 +236,16 @@ function proxy({ elements, block, from_static = false, use_array = false }) {
|
|
|
229
236
|
// target object — which we avoid, so that state can be forked — we will run
|
|
230
237
|
// afoul of the various invariants
|
|
231
238
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/getOwnPropertyDescriptor#invariants
|
|
232
|
-
throw new Error(
|
|
239
|
+
throw new Error(
|
|
240
|
+
'Only basic property descriptors are supported with value and configurable, enumerable, and writable set to true',
|
|
241
|
+
);
|
|
233
242
|
}
|
|
234
243
|
|
|
235
244
|
var t = tracked_elements.get(prop);
|
|
236
245
|
|
|
237
246
|
if (t === undefined) {
|
|
238
|
-
|
|
239
|
-
|
|
247
|
+
t = tracked(descriptor.value, block);
|
|
248
|
+
tracked_elements.set(prop, t);
|
|
240
249
|
} else {
|
|
241
250
|
set(t, descriptor.value, block);
|
|
242
251
|
}
|
|
@@ -266,15 +275,15 @@ function get_first_if_length(array) {
|
|
|
266
275
|
}
|
|
267
276
|
|
|
268
277
|
const methods_returning_arrays = new Set([
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
278
|
+
'concat',
|
|
279
|
+
'filter',
|
|
280
|
+
'flat',
|
|
281
|
+
'flatMap',
|
|
282
|
+
'map',
|
|
283
|
+
'slice',
|
|
284
|
+
'splice',
|
|
285
|
+
'toReversed',
|
|
286
|
+
'toSorted',
|
|
287
|
+
'toSpliced',
|
|
288
|
+
'with',
|
|
280
289
|
]);
|
|
@@ -1,13 +1,32 @@
|
|
|
1
|
-
import { IS_CONTROLLED } from '../../../constants.js';
|
|
1
|
+
import { IS_CONTROLLED, IS_INDEXED } from '../../../constants.js';
|
|
2
2
|
import { branch, destroy_block, destroy_block_children, render } from './blocks.js';
|
|
3
3
|
import { FOR_BLOCK, TRACKED_ARRAY } from './constants.js';
|
|
4
4
|
import { create_text } from './operations.js';
|
|
5
|
-
import { active_block, untrack } from './runtime.js';
|
|
5
|
+
import { active_block, set, tracked, untrack } from './runtime.js';
|
|
6
6
|
import { array_from, is_array } from './utils.js';
|
|
7
7
|
|
|
8
|
-
function create_item(anchor, value, render_fn) {
|
|
8
|
+
function create_item(anchor, value, index, render_fn, is_indexed) {
|
|
9
9
|
var b = branch(() => {
|
|
10
|
-
|
|
10
|
+
var tracked_index;
|
|
11
|
+
|
|
12
|
+
if (is_indexed) {
|
|
13
|
+
var block = /** @type {Block} */ (active_block);
|
|
14
|
+
|
|
15
|
+
if (block.s === null) {
|
|
16
|
+
tracked_index = tracked(index, block);
|
|
17
|
+
|
|
18
|
+
block.s = {
|
|
19
|
+
start: null,
|
|
20
|
+
end: null,
|
|
21
|
+
i: tracked_index,
|
|
22
|
+
};
|
|
23
|
+
} else {
|
|
24
|
+
tracked_index = block.s.i;
|
|
25
|
+
}
|
|
26
|
+
render_fn(anchor, value, tracked_index);
|
|
27
|
+
} else {
|
|
28
|
+
render_fn(anchor, value);
|
|
29
|
+
}
|
|
11
30
|
});
|
|
12
31
|
return b;
|
|
13
32
|
}
|
|
@@ -27,8 +46,21 @@ function move(block, anchor) {
|
|
|
27
46
|
}
|
|
28
47
|
}
|
|
29
48
|
|
|
49
|
+
function collection_to_array(collection) {
|
|
50
|
+
var array = is_array(collection) ? collection : collection == null ? [] : array_from(collection);
|
|
51
|
+
|
|
52
|
+
// If we are working with a tracked array, then we need to get a copy of
|
|
53
|
+
// the elements, as the array itself is proxied, and not useful in diffing
|
|
54
|
+
if (TRACKED_ARRAY in array) {
|
|
55
|
+
array = array_from(array);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return array;
|
|
59
|
+
}
|
|
60
|
+
|
|
30
61
|
export function for_block(node, get_collection, render_fn, flags) {
|
|
31
62
|
var is_controlled = (flags & IS_CONTROLLED) !== 0;
|
|
63
|
+
var is_indexed = (flags & IS_INDEXED) !== 0;
|
|
32
64
|
var anchor = node;
|
|
33
65
|
|
|
34
66
|
if (is_controlled) {
|
|
@@ -36,21 +68,13 @@ export function for_block(node, get_collection, render_fn, flags) {
|
|
|
36
68
|
}
|
|
37
69
|
|
|
38
70
|
render(() => {
|
|
39
|
-
var block = active_block;
|
|
71
|
+
var block = /** @type {Block} */ (active_block);
|
|
40
72
|
var collection = get_collection();
|
|
41
|
-
var array =
|
|
42
|
-
? collection
|
|
43
|
-
: collection == null
|
|
44
|
-
? []
|
|
45
|
-
: array_from(collection);
|
|
46
|
-
|
|
47
|
-
// If we are working with a tracked array, then we need to get a copy of
|
|
48
|
-
// the elements, as the array itself is proxied, and not useful in diffing
|
|
49
|
-
if (TRACKED_ARRAY in array) {
|
|
50
|
-
array = array_from(array);
|
|
51
|
-
}
|
|
73
|
+
var array = collection_to_array(collection);
|
|
52
74
|
|
|
53
|
-
untrack(() =>
|
|
75
|
+
untrack(() => {
|
|
76
|
+
reconcile(anchor, block, array, render_fn, is_controlled, is_indexed);
|
|
77
|
+
});
|
|
54
78
|
}, FOR_BLOCK);
|
|
55
79
|
}
|
|
56
80
|
|
|
@@ -64,7 +88,11 @@ function reconcile_fast_clear(anchor, block, array) {
|
|
|
64
88
|
state.blocks = [];
|
|
65
89
|
}
|
|
66
90
|
|
|
67
|
-
function
|
|
91
|
+
function update_index(block, index) {
|
|
92
|
+
set(block.s.i, index, block);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function reconcile(anchor, block, b, render_fn, is_controlled, is_indexed) {
|
|
68
96
|
var state = block.s;
|
|
69
97
|
|
|
70
98
|
if (state === null) {
|
|
@@ -91,7 +119,7 @@ function reconcile(anchor, block, b, render_fn, is_controlled) {
|
|
|
91
119
|
// Fast-path for create
|
|
92
120
|
if (a_length === 0) {
|
|
93
121
|
for (; j < b_length; j++) {
|
|
94
|
-
b_blocks[j] = create_item(anchor, b[j], render_fn);
|
|
122
|
+
b_blocks[j] = create_item(anchor, b[j], j, render_fn, is_indexed);
|
|
95
123
|
}
|
|
96
124
|
state.array = b;
|
|
97
125
|
state.blocks = b_blocks;
|
|
@@ -103,11 +131,15 @@ function reconcile(anchor, block, b, render_fn, is_controlled) {
|
|
|
103
131
|
var b_val = b[j];
|
|
104
132
|
var a_end = a_length - 1;
|
|
105
133
|
var b_end = b_length - 1;
|
|
134
|
+
var b_block;
|
|
106
135
|
|
|
107
136
|
outer: {
|
|
108
137
|
while (a_val === b_val) {
|
|
109
138
|
a[j] = b_val;
|
|
110
|
-
b_blocks[j] = a_blocks[j];
|
|
139
|
+
b_block = b_blocks[j] = a_blocks[j];
|
|
140
|
+
if (is_indexed) {
|
|
141
|
+
update_index(b_block, j);
|
|
142
|
+
}
|
|
111
143
|
++j;
|
|
112
144
|
if (j > a_end || j > b_end) {
|
|
113
145
|
break outer;
|
|
@@ -121,7 +153,10 @@ function reconcile(anchor, block, b, render_fn, is_controlled) {
|
|
|
121
153
|
|
|
122
154
|
while (a_val === b_val) {
|
|
123
155
|
a[a_end] = b_val;
|
|
124
|
-
b_blocks[b_end] = a_blocks[a_end];
|
|
156
|
+
b_block = b_blocks[b_end] = a_blocks[a_end];
|
|
157
|
+
if (is_indexed) {
|
|
158
|
+
update_index(b_block, b_end);
|
|
159
|
+
}
|
|
125
160
|
a_end--;
|
|
126
161
|
b_end--;
|
|
127
162
|
if (j > a_end || j > b_end) {
|
|
@@ -137,7 +172,8 @@ function reconcile(anchor, block, b, render_fn, is_controlled) {
|
|
|
137
172
|
while (j <= b_end) {
|
|
138
173
|
b_val = b[j];
|
|
139
174
|
var target = j >= a_length ? anchor : a_blocks[j].s.start;
|
|
140
|
-
b_blocks[j
|
|
175
|
+
b_blocks[j] = create_item(target, b_val, j, render_fn, is_indexed);
|
|
176
|
+
j++;
|
|
141
177
|
}
|
|
142
178
|
}
|
|
143
179
|
} else if (j > b_end) {
|
|
@@ -177,7 +213,10 @@ function reconcile(anchor, block, b, render_fn, is_controlled) {
|
|
|
177
213
|
} else {
|
|
178
214
|
pos = j;
|
|
179
215
|
}
|
|
180
|
-
b_blocks[j] = a_blocks[i];
|
|
216
|
+
b_block = b_blocks[j] = a_blocks[i];
|
|
217
|
+
if (is_indexed) {
|
|
218
|
+
update_index(b_block, j);
|
|
219
|
+
}
|
|
181
220
|
++patched;
|
|
182
221
|
break;
|
|
183
222
|
}
|
|
@@ -216,7 +255,10 @@ function reconcile(anchor, block, b, render_fn, is_controlled) {
|
|
|
216
255
|
pos = j;
|
|
217
256
|
}
|
|
218
257
|
b_val = b[j];
|
|
219
|
-
b_blocks[j] = a_blocks[i];
|
|
258
|
+
block = b_blocks[j] = a_blocks[i];
|
|
259
|
+
if (is_indexed) {
|
|
260
|
+
update_index(block, j);
|
|
261
|
+
}
|
|
220
262
|
++patched;
|
|
221
263
|
} else if (!fast_path_removal) {
|
|
222
264
|
destroy_block(a_blocks[i]);
|
|
@@ -244,7 +286,7 @@ function reconcile(anchor, block, b, render_fn, is_controlled) {
|
|
|
244
286
|
next_pos = pos + 1;
|
|
245
287
|
|
|
246
288
|
var target = next_pos < b_length ? b_blocks[next_pos].s.start : anchor;
|
|
247
|
-
b_blocks[pos] = create_item(target, b_val, render_fn);
|
|
289
|
+
b_blocks[pos] = create_item(target, b_val, pos, render_fn, is_indexed);
|
|
248
290
|
} else if (j < 0 || i !== seq[j]) {
|
|
249
291
|
pos = i + b_start;
|
|
250
292
|
b_val = b[pos];
|
|
@@ -264,7 +306,7 @@ function reconcile(anchor, block, b, render_fn, is_controlled) {
|
|
|
264
306
|
next_pos = pos + 1;
|
|
265
307
|
|
|
266
308
|
var target = next_pos < b_length ? b_blocks[next_pos].s.start : anchor;
|
|
267
|
-
b_blocks[pos] = create_item(target, b_val, render_fn);
|
|
309
|
+
b_blocks[pos] = create_item(target, b_val, pos, render_fn, is_indexed);
|
|
268
310
|
}
|
|
269
311
|
}
|
|
270
312
|
}
|
|
@@ -361,11 +403,7 @@ export function keyed(collection, key_fn) {
|
|
|
361
403
|
throw new Error('Duplicate keys are not allowed');
|
|
362
404
|
}
|
|
363
405
|
|
|
364
|
-
var b_array =
|
|
365
|
-
? collection
|
|
366
|
-
: collection == null
|
|
367
|
-
? []
|
|
368
|
-
: array_from(collection);
|
|
406
|
+
var b_array = collection_to_array(collection);
|
|
369
407
|
var b_keys = b_array.map(key_fn);
|
|
370
408
|
|
|
371
409
|
// We only need to do this in DEV
|
|
@@ -84,7 +84,8 @@ export function set_attributes(element, attributes) {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
if (key === 'class') {
|
|
87
|
-
|
|
87
|
+
const is_html = element.namespaceURI === 'http://www.w3.org/1999/xhtml';
|
|
88
|
+
set_class(element, value, undefined, is_html);
|
|
88
89
|
} else if (key === '#class') {
|
|
89
90
|
// Special case for static class when spreading props
|
|
90
91
|
element.classList.add(value);
|
|
@@ -120,9 +121,10 @@ function to_class(value, hash) {
|
|
|
120
121
|
* @param {HTMLElement} dom
|
|
121
122
|
* @param {string} value
|
|
122
123
|
* @param {string} [hash]
|
|
124
|
+
* @param {boolean} [is_html]
|
|
123
125
|
* @returns {void}
|
|
124
126
|
*/
|
|
125
|
-
export function set_class(dom, value, hash) {
|
|
127
|
+
export function set_class(dom, value, hash, is_html = true) {
|
|
126
128
|
// @ts-expect-error need to add __className to patched prototype
|
|
127
129
|
var prev_class_name = dom.__className;
|
|
128
130
|
var next_class_name = to_class(value, hash);
|
|
@@ -134,7 +136,11 @@ export function set_class(dom, value, hash) {
|
|
|
134
136
|
if (value == null && !hash) {
|
|
135
137
|
dom.removeAttribute('class');
|
|
136
138
|
} else {
|
|
137
|
-
|
|
139
|
+
if (is_html) {
|
|
140
|
+
dom.className = next_class_name;
|
|
141
|
+
} else {
|
|
142
|
+
dom.setAttribute('class', next_class_name);
|
|
143
|
+
}
|
|
138
144
|
}
|
|
139
145
|
|
|
140
146
|
// @ts-expect-error need to add __className to patched prototype
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
TEMPLATE_FRAGMENT,
|
|
3
|
+
TEMPLATE_USE_IMPORT_NODE,
|
|
4
|
+
TEMPLATE_SVG_NAMESPACE,
|
|
5
|
+
TEMPLATE_MATHML_NAMESPACE,
|
|
6
|
+
} from '../../../constants.js';
|
|
2
7
|
import { first_child, is_firefox } from './operations.js';
|
|
3
8
|
import { active_block } from './runtime.js';
|
|
4
9
|
|
|
@@ -8,21 +13,33 @@ import { active_block } from './runtime.js';
|
|
|
8
13
|
* @param {Node} end - The end node.
|
|
9
14
|
*/
|
|
10
15
|
export function assign_nodes(start, end) {
|
|
11
|
-
var block = /** @type {
|
|
12
|
-
|
|
16
|
+
var block = /** @type {Block} */ (active_block);
|
|
17
|
+
var s = block.s;
|
|
18
|
+
if (s === null) {
|
|
13
19
|
block.s = {
|
|
14
20
|
start,
|
|
15
21
|
end,
|
|
16
22
|
};
|
|
23
|
+
} else if (s.start === null) {
|
|
24
|
+
s.start = start;
|
|
25
|
+
s.end = end;
|
|
17
26
|
}
|
|
18
27
|
}
|
|
19
28
|
|
|
20
29
|
/**
|
|
21
30
|
* Creates a DocumentFragment from an HTML string.
|
|
22
31
|
* @param {string} html - The HTML string.
|
|
32
|
+
* @param {boolean} use_svg_namespace - Whether to use SVG namespace.
|
|
33
|
+
* @param {boolean} use_mathml_namespace - Whether to use MathML namespace.
|
|
23
34
|
* @returns {DocumentFragment}
|
|
24
35
|
*/
|
|
25
|
-
function create_fragment_from_html(html) {
|
|
36
|
+
function create_fragment_from_html(html, use_svg_namespace = false, use_mathml_namespace = false) {
|
|
37
|
+
if (use_svg_namespace) {
|
|
38
|
+
return from_namespace(html, 'svg');
|
|
39
|
+
}
|
|
40
|
+
if (use_mathml_namespace) {
|
|
41
|
+
return from_namespace(html, 'math');
|
|
42
|
+
}
|
|
26
43
|
var elem = document.createElement('template');
|
|
27
44
|
elem.innerHTML = html;
|
|
28
45
|
return elem.content;
|
|
@@ -37,12 +54,18 @@ function create_fragment_from_html(html) {
|
|
|
37
54
|
export function template(content, flags) {
|
|
38
55
|
var is_fragment = (flags & TEMPLATE_FRAGMENT) !== 0;
|
|
39
56
|
var use_import_node = (flags & TEMPLATE_USE_IMPORT_NODE) !== 0;
|
|
57
|
+
var use_svg_namespace = (flags & TEMPLATE_SVG_NAMESPACE) !== 0;
|
|
58
|
+
var use_mathml_namespace = (flags & TEMPLATE_MATHML_NAMESPACE) !== 0;
|
|
40
59
|
var node;
|
|
41
60
|
var has_start = !content.startsWith('<!>');
|
|
42
61
|
|
|
43
62
|
return () => {
|
|
44
63
|
if (node === undefined) {
|
|
45
|
-
node = create_fragment_from_html(
|
|
64
|
+
node = create_fragment_from_html(
|
|
65
|
+
has_start ? content : '<!>' + content,
|
|
66
|
+
use_svg_namespace,
|
|
67
|
+
use_mathml_namespace,
|
|
68
|
+
);
|
|
46
69
|
if (!is_fragment) node = first_child(node);
|
|
47
70
|
}
|
|
48
71
|
|
|
@@ -70,3 +93,26 @@ export function template(content, flags) {
|
|
|
70
93
|
export function append(anchor, dom) {
|
|
71
94
|
anchor.before(/** @type {Node} */ (dom));
|
|
72
95
|
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Create fragment with proper namespace using Svelte's wrapping approach
|
|
99
|
+
* @param {string} content
|
|
100
|
+
* @param {'svg' | 'math'} ns
|
|
101
|
+
* @returns {DocumentFragment}
|
|
102
|
+
*/
|
|
103
|
+
function from_namespace(content, ns = 'svg') {
|
|
104
|
+
var wrapped = `<${ns}>${content}</${ns}>`;
|
|
105
|
+
|
|
106
|
+
var elem = document.createElement('template');
|
|
107
|
+
elem.innerHTML = wrapped;
|
|
108
|
+
var fragment = elem.content;
|
|
109
|
+
|
|
110
|
+
var root = /** @type {Element} */ (first_child(fragment));
|
|
111
|
+
var result = document.createDocumentFragment();
|
|
112
|
+
|
|
113
|
+
while (first_child(root)) {
|
|
114
|
+
result.appendChild(/** @type {Node} */ (first_child(root)));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
@@ -18,6 +18,24 @@ exports[`basic > basic operations 1`] = `
|
|
|
18
18
|
</div>
|
|
19
19
|
`;
|
|
20
20
|
|
|
21
|
+
exports[`basic > correctly renders adjacent text nodes 1`] = `
|
|
22
|
+
<div>
|
|
23
|
+
<div>
|
|
24
|
+
11
|
|
25
|
+
</div>
|
|
26
|
+
<div>
|
|
27
|
+
11
|
|
28
|
+
</div>
|
|
29
|
+
<div>
|
|
30
|
+
truetrue
|
|
31
|
+
</div>
|
|
32
|
+
<div>
|
|
33
|
+
truetrue
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
</div>
|
|
37
|
+
`;
|
|
38
|
+
|
|
21
39
|
exports[`basic > handles boolean attributes with no prop value provides 1`] = `
|
|
22
40
|
<div>
|
|
23
41
|
<div
|
|
@@ -1,5 +1,83 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
+
exports[`for statements > correctly handle the index in a for...of loop 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div>
|
|
6
|
+
<div>
|
|
7
|
+
0 : a
|
|
8
|
+
</div>
|
|
9
|
+
<div>
|
|
10
|
+
1 : b
|
|
11
|
+
</div>
|
|
12
|
+
<div>
|
|
13
|
+
2 : c
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
<button>
|
|
18
|
+
Add Item
|
|
19
|
+
</button>
|
|
20
|
+
<button>
|
|
21
|
+
Reverse
|
|
22
|
+
</button>
|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
exports[`for statements > correctly handle the index in a for...of loop 2`] = `
|
|
28
|
+
<div>
|
|
29
|
+
<div>
|
|
30
|
+
<div>
|
|
31
|
+
0 : a
|
|
32
|
+
</div>
|
|
33
|
+
<div>
|
|
34
|
+
1 : b
|
|
35
|
+
</div>
|
|
36
|
+
<div>
|
|
37
|
+
2 : c
|
|
38
|
+
</div>
|
|
39
|
+
<div>
|
|
40
|
+
3 : d
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
<button>
|
|
45
|
+
Add Item
|
|
46
|
+
</button>
|
|
47
|
+
<button>
|
|
48
|
+
Reverse
|
|
49
|
+
</button>
|
|
50
|
+
|
|
51
|
+
</div>
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
exports[`for statements > correctly handle the index in a for...of loop 3`] = `
|
|
55
|
+
<div>
|
|
56
|
+
<div>
|
|
57
|
+
<div>
|
|
58
|
+
0 : d
|
|
59
|
+
</div>
|
|
60
|
+
<div>
|
|
61
|
+
1 : c
|
|
62
|
+
</div>
|
|
63
|
+
<div>
|
|
64
|
+
2 : b
|
|
65
|
+
</div>
|
|
66
|
+
<div>
|
|
67
|
+
3 : a
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
</div>
|
|
71
|
+
<button>
|
|
72
|
+
Add Item
|
|
73
|
+
</button>
|
|
74
|
+
<button>
|
|
75
|
+
Reverse
|
|
76
|
+
</button>
|
|
77
|
+
|
|
78
|
+
</div>
|
|
79
|
+
`;
|
|
80
|
+
|
|
3
81
|
exports[`for statements > correctly handles intermediate statements in for block 1`] = `
|
|
4
82
|
<div>
|
|
5
83
|
<div>
|
package/tests/basic.test.ripple
CHANGED
|
@@ -1271,4 +1271,19 @@ describe('basic', () => {
|
|
|
1271
1271
|
render(App);
|
|
1272
1272
|
expect(container).toMatchSnapshot();
|
|
1273
1273
|
});
|
|
1274
|
+
|
|
1275
|
+
it('correctly renders adjacent text nodes', () => {
|
|
1276
|
+
component App() {
|
|
1277
|
+
let a = 1;
|
|
1278
|
+
let b = 1;
|
|
1279
|
+
<div>{1}{1}</div>
|
|
1280
|
+
<div>{a}{b}</div>
|
|
1281
|
+
<div>{true}{true}</div>
|
|
1282
|
+
<div>{true}{true}</div>
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
render(App);
|
|
1286
|
+
|
|
1287
|
+
expect(container).toMatchSnapshot();
|
|
1288
|
+
});
|
|
1274
1289
|
});
|
package/tests/for.test.ripple
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
|
|
3
2
|
import { mount, flushSync, TrackedArray } from 'ripple';
|
|
4
3
|
|
|
5
4
|
describe('for statements', () => {
|
|
@@ -84,5 +83,36 @@ describe('for statements', () => {
|
|
|
84
83
|
flushSync();
|
|
85
84
|
|
|
86
85
|
expect(container).toMatchSnapshot();
|
|
87
|
-
})
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('correctly handle the index in a for...of loop', () => {
|
|
89
|
+
component App() {
|
|
90
|
+
const items = new TrackedArray('a', 'b', 'c');
|
|
91
|
+
|
|
92
|
+
<div>
|
|
93
|
+
for (let item of items; index i) {
|
|
94
|
+
<div>{i + ' : ' + item}</div>
|
|
95
|
+
}
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<button onClick={() => items.push(String.fromCharCode(97 + items.length))}>{'Add Item'}</button>
|
|
99
|
+
<button onClick={() => items.reverse()}>{'Reverse'}</button>
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
render(App);
|
|
103
|
+
|
|
104
|
+
expect(container).toMatchSnapshot();
|
|
105
|
+
|
|
106
|
+
const [button, button2] = container.querySelectorAll('button');
|
|
107
|
+
|
|
108
|
+
button.click();
|
|
109
|
+
flushSync();
|
|
110
|
+
|
|
111
|
+
expect(container).toMatchSnapshot();
|
|
112
|
+
|
|
113
|
+
button2.click();
|
|
114
|
+
flushSync();
|
|
115
|
+
|
|
116
|
+
expect(container).toMatchSnapshot();
|
|
117
|
+
});
|
|
88
118
|
});
|