ripple 0.3.54 → 0.3.57
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/CHANGELOG.md +45 -0
- package/package.json +4 -4
- package/src/runtime/internal/client/events.js +5 -5
- package/src/runtime/internal/client/render.js +2 -5
- package/src/runtime/internal/server/index.js +7 -4
- package/tests/client/basic/basic.attributes.test.tsrx +4 -6
- package/tests/client/basic/basic.collections.test.tsrx +8 -12
- package/tests/server/basic.attributes.test.tsrx +4 -6
- package/tests/server/lazy-destructuring.test.tsrx +310 -2
- package/tests/utils/runtime-imports.test.js +38 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# ripple
|
|
2
2
|
|
|
3
|
+
## 0.3.57
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1126](https://github.com/Ripple-TS/ripple/pull/1126)
|
|
8
|
+
[`2b1f746`](https://github.com/Ripple-TS/ripple/commit/2b1f7469ab31713140a5baf912a19fa8eedb9234)
|
|
9
|
+
Thanks [@leonidaz](https://github.com/leonidaz)! - Keep runtime helper imports
|
|
10
|
+
on namespaced runtime subpaths so production app bundles do not pull in
|
|
11
|
+
compiler-only modules.
|
|
12
|
+
|
|
13
|
+
- [#1123](https://github.com/Ripple-TS/ripple/pull/1123)
|
|
14
|
+
[`e4a04dd`](https://github.com/Ripple-TS/ripple/commit/e4a04ddb4bbc8e21a9c7c2c65b179d764b72e4fb)
|
|
15
|
+
Thanks [@leonidaz](https://github.com/leonidaz)! - Nested lazy destructuring
|
|
16
|
+
support for all tsrx targets. Ripple already fully supported it.
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
[[`2b1f746`](https://github.com/Ripple-TS/ripple/commit/2b1f7469ab31713140a5baf912a19fa8eedb9234),
|
|
19
|
+
[`e4a04dd`](https://github.com/Ripple-TS/ripple/commit/e4a04ddb4bbc8e21a9c7c2c65b179d764b72e4fb)]:
|
|
20
|
+
- @tsrx/core@0.1.7
|
|
21
|
+
- ripple@0.3.57
|
|
22
|
+
- @tsrx/ripple@0.1.7
|
|
23
|
+
|
|
24
|
+
## 0.3.56
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- Updated dependencies
|
|
29
|
+
[[`a59ccb8`](https://github.com/Ripple-TS/ripple/commit/a59ccb83b91257bf34fca2ba1415e77d1f815a7b)]:
|
|
30
|
+
- @tsrx/core@0.1.6
|
|
31
|
+
- ripple@0.3.56
|
|
32
|
+
- @tsrx/ripple@0.1.6
|
|
33
|
+
|
|
34
|
+
## 0.3.55
|
|
35
|
+
|
|
36
|
+
### Patch Changes
|
|
37
|
+
|
|
38
|
+
- Updated dependencies
|
|
39
|
+
[[`de27e18`](https://github.com/Ripple-TS/ripple/commit/de27e182d002ea736aee992acca4cbf9873a307d),
|
|
40
|
+
[`59e1e32`](https://github.com/Ripple-TS/ripple/commit/59e1e328607598fe342abbba35f76e5fadb9ca5c),
|
|
41
|
+
[`1256569`](https://github.com/Ripple-TS/ripple/commit/12565695efaa3a4ad429245807721ea671c2ecb5),
|
|
42
|
+
[`1256569`](https://github.com/Ripple-TS/ripple/commit/12565695efaa3a4ad429245807721ea671c2ecb5),
|
|
43
|
+
[`18b4aef`](https://github.com/Ripple-TS/ripple/commit/18b4aefa8127e56a9f1b3058da2d4d2172551579)]:
|
|
44
|
+
- @tsrx/core@0.1.5
|
|
45
|
+
- ripple@0.3.55
|
|
46
|
+
- @tsrx/ripple@0.1.5
|
|
47
|
+
|
|
3
48
|
## 0.3.54
|
|
4
49
|
|
|
5
50
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Ripple is an elegant TypeScript UI framework",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.57",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"esm-env": "^1.2.2",
|
|
77
77
|
"@types/estree": "^1.0.8",
|
|
78
78
|
"@types/estree-jsx": "^1.0.5",
|
|
79
|
-
"@tsrx/core": "0.1.
|
|
80
|
-
"@tsrx/ripple": "0.1.
|
|
79
|
+
"@tsrx/core": "0.1.7",
|
|
80
|
+
"@tsrx/ripple": "0.1.7"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@types/node": "^24.3.0",
|
|
@@ -87,6 +87,6 @@
|
|
|
87
87
|
"vscode-languageserver-types": "^3.17.5"
|
|
88
88
|
},
|
|
89
89
|
"peerDependencies": {
|
|
90
|
-
"ripple": "0.3.
|
|
90
|
+
"ripple": "0.3.57"
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* @typedef {EventTarget & Record<string, any>} DelegatedEventTarget
|
|
4
4
|
*/
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from '@tsrx/core';
|
|
6
|
+
event_name_from_capture,
|
|
7
|
+
is_capture_event,
|
|
8
|
+
is_non_delegated,
|
|
9
|
+
is_passive_event,
|
|
10
|
+
} from '@tsrx/core/runtime/events';
|
|
11
11
|
import {
|
|
12
12
|
active_block,
|
|
13
13
|
active_reaction,
|
|
@@ -10,13 +10,10 @@ import {
|
|
|
10
10
|
get_prototype_of,
|
|
11
11
|
} from '@tsrx/core/runtime/language-helpers';
|
|
12
12
|
import { event } from './events.js';
|
|
13
|
-
import {
|
|
14
|
-
getAttributeEventName as get_attribute_event_name,
|
|
15
|
-
isEventAttribute as is_event_attribute,
|
|
16
|
-
} from '@tsrx/core';
|
|
13
|
+
import { get_attribute_event_name, is_event_attribute } from '@tsrx/core/runtime/events';
|
|
17
14
|
import { get } from './runtime.js';
|
|
18
15
|
import { clsx } from 'clsx';
|
|
19
|
-
import {
|
|
16
|
+
import { normalize_css_property_name } from '@tsrx/core/runtime/html';
|
|
20
17
|
|
|
21
18
|
/**
|
|
22
19
|
* @param {Text} text
|
|
@@ -29,10 +29,13 @@ import {
|
|
|
29
29
|
import { DEV } from 'esm-env';
|
|
30
30
|
import { is_ripple_object } from '../client/utils.js';
|
|
31
31
|
import { array_slice } from '@tsrx/core/runtime/language-helpers';
|
|
32
|
-
import {
|
|
33
|
-
|
|
32
|
+
import {
|
|
33
|
+
escape,
|
|
34
|
+
escape_script,
|
|
35
|
+
is_boolean_attribute,
|
|
36
|
+
normalize_css_property_name,
|
|
37
|
+
} from '@tsrx/core/runtime/html';
|
|
34
38
|
import { clsx } from 'clsx';
|
|
35
|
-
import { normalizeCssPropertyName as normalize_css_property_name } from '@tsrx/core';
|
|
36
39
|
import { create_ref_prop } from '@tsrx/core/runtime/ref';
|
|
37
40
|
import { BLOCK_CLOSE, BLOCK_OPEN } from '../../../constants.js';
|
|
38
41
|
import { is_tsrx_element, normalize_children, tsrx_element } from '../../element.js';
|
|
@@ -53,7 +56,7 @@ import { COMPONENT_BLOCK, TRY_BLOCK } from './constants.js';
|
|
|
53
56
|
|
|
54
57
|
export { escape };
|
|
55
58
|
export { register_component_css as register_css } from './css-registry.js';
|
|
56
|
-
export {
|
|
59
|
+
export { simple_hash, strong_hash } from '@tsrx/core/runtime/hash';
|
|
57
60
|
export { context } from './context.js';
|
|
58
61
|
export { try_block, component_block, regular_block } from './blocks.js';
|
|
59
62
|
export { array_slice };
|
|
@@ -462,12 +462,10 @@ describe('basic client > attribute rendering', () => {
|
|
|
462
462
|
|
|
463
463
|
it('render spread attributes', () => {
|
|
464
464
|
component Basic() {
|
|
465
|
-
let &[attrs] = track<TestAttributes>(
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
},
|
|
470
|
-
);
|
|
465
|
+
let &[attrs] = track<TestAttributes>({
|
|
466
|
+
class: 'initial',
|
|
467
|
+
id: 'test-1',
|
|
468
|
+
});
|
|
471
469
|
|
|
472
470
|
<button
|
|
473
471
|
onClick={() => {
|
|
@@ -4,12 +4,10 @@ import { TRACKED_ARRAY } from '../../../src/runtime/internal/client/constants.js
|
|
|
4
4
|
describe('basic client > collections', () => {
|
|
5
5
|
it('renders with simple reactive objects', () => {
|
|
6
6
|
component Basic() {
|
|
7
|
-
let &[user] = track(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
);
|
|
7
|
+
let &[user] = track({
|
|
8
|
+
name: 'John',
|
|
9
|
+
age: 25,
|
|
10
|
+
});
|
|
13
11
|
|
|
14
12
|
<div class="name">{user.name}</div>
|
|
15
13
|
<div class="age">{user.age}</div>
|
|
@@ -40,12 +38,10 @@ describe('basic client > collections', () => {
|
|
|
40
38
|
|
|
41
39
|
it('renders with nested reactive objects', () => {
|
|
42
40
|
component Basic() {
|
|
43
|
-
let &[user] = track(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
},
|
|
48
|
-
);
|
|
41
|
+
let &[user] = track({
|
|
42
|
+
name: track('John'),
|
|
43
|
+
age: track(25),
|
|
44
|
+
});
|
|
49
45
|
|
|
50
46
|
<div class="name">{user.name.value}</div>
|
|
51
47
|
<div class="age">{user.age.value}</div>
|
|
@@ -493,12 +493,10 @@ describe('basic server > attribute rendering', () => {
|
|
|
493
493
|
|
|
494
494
|
it('render spread attributes', async () => {
|
|
495
495
|
component Basic() {
|
|
496
|
-
let &[attrs] = track<TestAttributes>(
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
},
|
|
501
|
-
);
|
|
496
|
+
let &[attrs] = track<TestAttributes>({
|
|
497
|
+
class: 'initial',
|
|
498
|
+
id: 'test-1',
|
|
499
|
+
});
|
|
502
500
|
|
|
503
501
|
<div {...attrs}>{'Spread Attributes'}</div>
|
|
504
502
|
}
|
|
@@ -140,7 +140,11 @@ describe('lazy destructuring', () => {
|
|
|
140
140
|
it(
|
|
141
141
|
'preserves lazy getter/setter behavior for RestElement nested destructuring in non-lazy component params',
|
|
142
142
|
async () => {
|
|
143
|
-
component Inner({
|
|
143
|
+
component Inner({
|
|
144
|
+
values: [head, ...&{ 0: first_rest, length: rest_length }],
|
|
145
|
+
}: {
|
|
146
|
+
values: number[];
|
|
147
|
+
}) {
|
|
144
148
|
const before = `${first_rest}-${rest_length}`;
|
|
145
149
|
rest_length = 0;
|
|
146
150
|
<pre>{`${head}-${before}-${first_rest}-${rest_length}`}</pre>
|
|
@@ -159,7 +163,11 @@ describe('lazy destructuring', () => {
|
|
|
159
163
|
'preserves lazy getter/setter behavior for RestElement nested destructuring in non-lazy function params',
|
|
160
164
|
async () => {
|
|
161
165
|
component Test() {
|
|
162
|
-
function getInfo({
|
|
166
|
+
function getInfo({
|
|
167
|
+
values: [head, ...&{ 0: first_rest, length: rest_length }],
|
|
168
|
+
}: {
|
|
169
|
+
values: number[];
|
|
170
|
+
}) {
|
|
163
171
|
const before = `${first_rest}-${rest_length}`;
|
|
164
172
|
rest_length = 0;
|
|
165
173
|
return `${head}-${before}-${first_rest}-${rest_length}`;
|
|
@@ -228,4 +236,304 @@ describe('lazy destructuring', () => {
|
|
|
228
236
|
const { body } = await render(Test);
|
|
229
237
|
expect(body).toBeHtml('<pre>10-20</pre>');
|
|
230
238
|
});
|
|
239
|
+
|
|
240
|
+
describe('nested lazy destructuring', () => {
|
|
241
|
+
it('preserves nested lazy object access inside lazy object as component params', async () => {
|
|
242
|
+
let inner_value = 7;
|
|
243
|
+
|
|
244
|
+
component Inner(&{ outer: &{ inner } }: { outer: { inner: number } }) {
|
|
245
|
+
const before = inner;
|
|
246
|
+
inner_value = 8;
|
|
247
|
+
<pre>{`${before}-${inner}`}</pre>
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
component Test() {
|
|
251
|
+
const outer = {
|
|
252
|
+
get inner() {
|
|
253
|
+
return inner_value;
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
<Inner {outer} />
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const { body } = await render(Test);
|
|
260
|
+
expect(body).toBeHtml('<pre>7-8</pre>');
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('preserves nested lazy array access inside regular object as component params', async () => {
|
|
264
|
+
let first_value = 3;
|
|
265
|
+
let second_value = 4;
|
|
266
|
+
|
|
267
|
+
component Inner({ pair: &[first, second] }: { pair: [number, number] }) {
|
|
268
|
+
const before = `${first}-${second}`;
|
|
269
|
+
first_value = 5;
|
|
270
|
+
second_value = 6;
|
|
271
|
+
<pre>{`${before}-${first}-${second}`}</pre>
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
component Test() {
|
|
275
|
+
const pair = [0, 0] as [number, number];
|
|
276
|
+
Object.defineProperty(pair, 0, { get: () => first_value });
|
|
277
|
+
Object.defineProperty(pair, 1, { get: () => second_value });
|
|
278
|
+
<Inner {pair} />
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const { body } = await render(Test);
|
|
282
|
+
expect(body).toBeHtml('<pre>3-4-5-6</pre>');
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('preserves nested lazy object access inside lazy array as function params', async () => {
|
|
286
|
+
component Test() {
|
|
287
|
+
let name_value = 'Alice';
|
|
288
|
+
function getName(&[&{ name }]: [{ name: string }]) {
|
|
289
|
+
const before = name;
|
|
290
|
+
name_value = 'Bob';
|
|
291
|
+
return `${before}-${name}`;
|
|
292
|
+
}
|
|
293
|
+
const user = {
|
|
294
|
+
get name() {
|
|
295
|
+
return name_value;
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
<pre>{getName([user])}</pre>
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const { body } = await render(Test);
|
|
302
|
+
expect(body).toBeHtml('<pre>Alice-Bob</pre>');
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('preserves nested lazy array access inside lazy array as function params', async () => {
|
|
306
|
+
component Test() {
|
|
307
|
+
let first_value = 5;
|
|
308
|
+
let second_value = 6;
|
|
309
|
+
function getValues(&[&[a, b]]: [[number, number]]) {
|
|
310
|
+
const before = `${a}-${b}`;
|
|
311
|
+
first_value = 7;
|
|
312
|
+
second_value = 8;
|
|
313
|
+
return `${before}-${a}-${b}`;
|
|
314
|
+
}
|
|
315
|
+
const pair = [0, 0] as [number, number];
|
|
316
|
+
Object.defineProperty(pair, 0, { get: () => first_value });
|
|
317
|
+
Object.defineProperty(pair, 1, { get: () => second_value });
|
|
318
|
+
<pre>{getValues([pair])}</pre>
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const { body } = await render(Test);
|
|
322
|
+
expect(body).toBeHtml('<pre>5-6-7-8</pre>');
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it('preserves three-level lazy object access as component params', async () => {
|
|
326
|
+
let c_value = 42;
|
|
327
|
+
|
|
328
|
+
component Inner(&{ a: &{ b: &{ c } } }: { a: { b: { c: number } } }) {
|
|
329
|
+
const before = c;
|
|
330
|
+
c_value = 43;
|
|
331
|
+
<pre>{`${before}-${c}`}</pre>
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
component Test() {
|
|
335
|
+
const a = {
|
|
336
|
+
b: {
|
|
337
|
+
get c() {
|
|
338
|
+
return c_value;
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
<Inner {a} />
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const { body } = await render(Test);
|
|
346
|
+
expect(body).toBeHtml('<pre>42-43</pre>');
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('preserves nested lazy object access inside lazy object as function params', async () => {
|
|
350
|
+
component Test() {
|
|
351
|
+
let inner_value = 11;
|
|
352
|
+
function getValue(&{ outer: &{ inner } }: { outer: { inner: number } }) {
|
|
353
|
+
const before = inner;
|
|
354
|
+
inner_value = 12;
|
|
355
|
+
return `${before}-${inner}`;
|
|
356
|
+
}
|
|
357
|
+
const outer = {
|
|
358
|
+
get inner() {
|
|
359
|
+
return inner_value;
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
<pre>{getValue({ outer })}</pre>
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const { body } = await render(Test);
|
|
366
|
+
expect(body).toBeHtml('<pre>11-12</pre>');
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it(
|
|
370
|
+
'supports nested lazy array inside lazy object as function params with writeback',
|
|
371
|
+
async () => {
|
|
372
|
+
component Test() {
|
|
373
|
+
const obj = { pair: [1, 2] as [number, number] };
|
|
374
|
+
function bump(&{ pair: &[first, second] }: { pair: [number, number] }) {
|
|
375
|
+
first = first + 10;
|
|
376
|
+
second = second + 20;
|
|
377
|
+
}
|
|
378
|
+
bump(obj);
|
|
379
|
+
<pre>{`${obj.pair[0]}-${obj.pair[1]}`}</pre>
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const { body } = await render(Test);
|
|
383
|
+
expect(body).toBeHtml('<pre>11-22</pre>');
|
|
384
|
+
},
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
it('preserves three-level lazy object access as function params', async () => {
|
|
388
|
+
component Test() {
|
|
389
|
+
let c_value = 99;
|
|
390
|
+
function getValue(&{ a: &{ b: &{ c } } }: { a: { b: { c: number } } }) {
|
|
391
|
+
const before = c;
|
|
392
|
+
c_value = 100;
|
|
393
|
+
return `${before}-${c}`;
|
|
394
|
+
}
|
|
395
|
+
const a = {
|
|
396
|
+
b: {
|
|
397
|
+
get c() {
|
|
398
|
+
return c_value;
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
<pre>{getValue({ a })}</pre>
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const { body } = await render(Test);
|
|
406
|
+
expect(body).toBeHtml('<pre>99-100</pre>');
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('preserves nested lazy object access inside lazy object in const declaration', async () => {
|
|
410
|
+
component Test() {
|
|
411
|
+
let inner_value = 5;
|
|
412
|
+
const data = {
|
|
413
|
+
outer: {
|
|
414
|
+
get inner() {
|
|
415
|
+
return inner_value;
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
const &{ outer: &{ inner } } = data;
|
|
420
|
+
const before = inner;
|
|
421
|
+
inner_value = 6;
|
|
422
|
+
<pre>{`${before}-${inner}`}</pre>
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const { body } = await render(Test);
|
|
426
|
+
expect(body).toBeHtml('<pre>5-6</pre>');
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('supports nested lazy object inside lazy object in let with writeback', async () => {
|
|
430
|
+
component Test() {
|
|
431
|
+
const data = { outer: { inner: 5 } };
|
|
432
|
+
let &{ outer: &{ inner } } = data;
|
|
433
|
+
inner = 50;
|
|
434
|
+
<pre>{data.outer.inner}</pre>
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const { body } = await render(Test);
|
|
438
|
+
expect(body).toBeHtml('<pre>50</pre>');
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('supports nested lazy array inside lazy object in let with writeback', async () => {
|
|
442
|
+
component Test() {
|
|
443
|
+
const data = { pair: [1, 2] as [number, number] };
|
|
444
|
+
let &{ pair: &[first, second] } = data;
|
|
445
|
+
first = 100;
|
|
446
|
+
second = 200;
|
|
447
|
+
<pre>{`${data.pair[0]}-${data.pair[1]}`}</pre>
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const { body } = await render(Test);
|
|
451
|
+
expect(body).toBeHtml('<pre>100-200</pre>');
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it('supports three-level lazy object nesting in let with writeback', async () => {
|
|
455
|
+
component Test() {
|
|
456
|
+
const data = { a: { b: { c: 1 } } };
|
|
457
|
+
let &{ a: &{ b: &{ c } } } = data;
|
|
458
|
+
c = 999;
|
|
459
|
+
<pre>{data.a.b.c}</pre>
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const { body } = await render(Test);
|
|
463
|
+
expect(body).toBeHtml('<pre>999</pre>');
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
it('supports compound assignment on deeply nested lazy bindings', async () => {
|
|
467
|
+
component Test() {
|
|
468
|
+
const data = { a: { b: { c: 5 } } };
|
|
469
|
+
let &{ a: &{ b: &{ c } } } = data;
|
|
470
|
+
c += 10;
|
|
471
|
+
c *= 2;
|
|
472
|
+
<pre>{data.a.b.c}</pre>
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const { body } = await render(Test);
|
|
476
|
+
expect(body).toBeHtml('<pre>30</pre>');
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it('preserves default values inside nested lazy destructuring', async () => {
|
|
480
|
+
component Test() {
|
|
481
|
+
let inner_value: number | undefined;
|
|
482
|
+
const data: { outer: { inner?: number } } = {
|
|
483
|
+
outer: {
|
|
484
|
+
get inner() {
|
|
485
|
+
return inner_value;
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
const &{ outer: &{ inner = 42 } } = data;
|
|
490
|
+
const before = inner;
|
|
491
|
+
inner_value = 43;
|
|
492
|
+
<pre>{`${before}-${inner}`}</pre>
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const { body } = await render(Test);
|
|
496
|
+
expect(body).toBeHtml('<pre>42-43</pre>');
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it('preserves multiple sibling nested lazy destructures', async () => {
|
|
500
|
+
component Test() {
|
|
501
|
+
let x_value = 1;
|
|
502
|
+
let y_value = 2;
|
|
503
|
+
const data = {
|
|
504
|
+
a: {
|
|
505
|
+
get x() {
|
|
506
|
+
return x_value;
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
b: {
|
|
510
|
+
get y() {
|
|
511
|
+
return y_value;
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
};
|
|
515
|
+
const &{ a: &{ x }, b: &{ y } } = data;
|
|
516
|
+
const before = `${x}-${y}`;
|
|
517
|
+
x_value = 3;
|
|
518
|
+
y_value = 4;
|
|
519
|
+
<pre>{`${before}-${x}-${y}`}</pre>
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const { body } = await render(Test);
|
|
523
|
+
expect(body).toBeHtml('<pre>1-2-3-4</pre>');
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
it('supports multiple sibling nested lazy destructures with writeback', async () => {
|
|
527
|
+
component Test() {
|
|
528
|
+
const data = { a: { x: 1 }, b: { y: 2 } };
|
|
529
|
+
let &{ a: &{ x }, b: &{ y } } = data;
|
|
530
|
+
x = 11;
|
|
531
|
+
y = 22;
|
|
532
|
+
<pre>{`${data.a.x}-${data.b.y}`}</pre>
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const { body } = await render(Test);
|
|
536
|
+
expect(body).toBeHtml('<pre>11-22</pre>');
|
|
537
|
+
});
|
|
538
|
+
});
|
|
231
539
|
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
|
|
5
|
+
const runtime_dir = new URL('../../src/runtime/', import.meta.url);
|
|
6
|
+
|
|
7
|
+
/** @param {string} dir */
|
|
8
|
+
async function get_js_files(dir) {
|
|
9
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
10
|
+
const files = [];
|
|
11
|
+
|
|
12
|
+
for (const entry of entries) {
|
|
13
|
+
const path = join(dir, entry.name);
|
|
14
|
+
if (entry.isDirectory()) {
|
|
15
|
+
files.push(...(await get_js_files(path)));
|
|
16
|
+
} else if (entry.isFile() && entry.name.endsWith('.js')) {
|
|
17
|
+
files.push(path);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return files;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe('runtime imports', () => {
|
|
25
|
+
it('does not import the @tsrx/core compiler barrel', async () => {
|
|
26
|
+
const files = await get_js_files(runtime_dir.pathname);
|
|
27
|
+
const barrel_imports = [];
|
|
28
|
+
|
|
29
|
+
for (const file of files) {
|
|
30
|
+
const source = await readFile(file, 'utf8');
|
|
31
|
+
if (/from\s+['"]@tsrx\/core['"]/.test(source)) {
|
|
32
|
+
barrel_imports.push(file);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
expect(barrel_imports).toEqual([]);
|
|
37
|
+
});
|
|
38
|
+
});
|