ripple 0.2.44 → 0.2.46
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 +83 -0
- package/src/compiler/phases/2-analyze/index.js +48 -9
- package/src/compiler/phases/2-analyze/prune.js +3 -1
- package/src/compiler/phases/3-transform/index.js +136 -43
- package/src/compiler/utils.js +48 -14
- package/src/runtime/array.js +118 -25
- package/src/runtime/index.js +1 -1
- package/src/runtime/internal/client/array.js +16 -16
- package/src/runtime/internal/client/blocks.js +0 -1
- package/src/runtime/internal/client/constants.js +5 -2
- package/src/runtime/internal/client/index.js +4 -0
- package/src/runtime/internal/client/portal.js +3 -3
- package/src/runtime/internal/client/runtime.js +47 -15
- package/tests/array.test.ripple +125 -37
- package/tests/basic.test.ripple +11 -5
package/tests/array.test.ripple
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
2
|
import { mount, flushSync, effect, untrack, RippleArray } from 'ripple';
|
|
3
|
-
import { ARRAY_SET_INDEX_AT } from '../src/runtime/internal/client/constants.js';
|
|
3
|
+
import { ARRAY_SET_INDEX_AT, MAX_ARRAY_LENGTH } from '../src/runtime/internal/client/constants.js';
|
|
4
4
|
|
|
5
5
|
describe('RippleArray', () => {
|
|
6
6
|
let container;
|
|
@@ -1244,37 +1244,34 @@ describe('RippleArray', () => {
|
|
|
1244
1244
|
expect(container.querySelector('pre').textContent).toBe('Cannot set length on RippleArray, use $length instead');
|
|
1245
1245
|
});
|
|
1246
1246
|
|
|
1247
|
-
('fromAsync' in Array.prototype ? describe : describe.skip)('RippleArray fromAsync', () => {
|
|
1247
|
+
('fromAsync' in Array.prototype ? describe : describe.skip)('RippleArray fromAsync', async () => {
|
|
1248
1248
|
it('handles static fromAsync method with reactivity', async () => {
|
|
1249
|
-
component
|
|
1250
|
-
let itemsPromise = RippleArray.fromAsync(Promise.resolve([1, 2, 3]));
|
|
1251
|
-
let items = null;
|
|
1252
|
-
let error = null;
|
|
1253
|
-
|
|
1249
|
+
component Parent() {
|
|
1254
1250
|
try {
|
|
1255
|
-
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1251
|
+
<ArrayTest />
|
|
1252
|
+
} async {
|
|
1253
|
+
<div>{'Loading placeholder...'}</div>
|
|
1258
1254
|
}
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
component ArrayTest() {
|
|
1258
|
+
let items = await RippleArray.fromAsync([1, 2, 3]);
|
|
1259
1259
|
|
|
1260
1260
|
<button onClick={() => {
|
|
1261
|
-
|
|
1261
|
+
if (items) items.push(4);
|
|
1262
1262
|
}}>{'add item'}</button>
|
|
1263
|
-
|
|
1264
|
-
<pre>{
|
|
1263
|
+
|
|
1264
|
+
<pre>{JSON.stringify(items)}</pre>
|
|
1265
1265
|
}
|
|
1266
1266
|
|
|
1267
|
-
render(
|
|
1267
|
+
render(Parent);
|
|
1268
1268
|
|
|
1269
|
-
|
|
1270
|
-
await new Promise(resolve => setTimeout(resolve, 50));
|
|
1269
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
1271
1270
|
flushSync();
|
|
1272
1271
|
|
|
1273
1272
|
const addButton = container.querySelector('button');
|
|
1274
1273
|
|
|
1275
|
-
|
|
1276
|
-
expect(container.querySelectorAll('pre')[0].textContent).toBe('Loaded');
|
|
1277
|
-
expect(container.querySelectorAll('pre')[1].textContent).toBe('[1,2,3]');
|
|
1274
|
+
expect(container.querySelectorAll('pre')[0].textContent).toBe('[1,2,3]');
|
|
1278
1275
|
|
|
1279
1276
|
// Test adding an item to the async-created array
|
|
1280
1277
|
addButton.click();
|
|
@@ -1284,33 +1281,35 @@ describe('RippleArray', () => {
|
|
|
1284
1281
|
});
|
|
1285
1282
|
|
|
1286
1283
|
it('handles static fromAsync method with mapping function', async () => {
|
|
1284
|
+
component Parent() {
|
|
1285
|
+
try {
|
|
1286
|
+
<ArrayTest />
|
|
1287
|
+
} async {
|
|
1288
|
+
<div>{'Loading placeholder...'}</div>
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1287
1292
|
component ArrayTest() {
|
|
1288
|
-
let
|
|
1289
|
-
|
|
1290
|
-
|
|
1293
|
+
let items = await RippleArray.fromAsync(
|
|
1294
|
+
[1, 2, 3],
|
|
1295
|
+
x => x * 2
|
|
1291
1296
|
);
|
|
1292
|
-
let items = null;
|
|
1293
|
-
|
|
1294
|
-
items = await itemsPromise;
|
|
1295
1297
|
|
|
1296
1298
|
<button onClick={() => {
|
|
1297
|
-
|
|
1299
|
+
if (items) items.push(8);
|
|
1298
1300
|
}}>{'add item'}</button>
|
|
1299
1301
|
<pre>{items ? JSON.stringify(items) : 'Loading...'}</pre>
|
|
1300
1302
|
}
|
|
1301
1303
|
|
|
1302
|
-
render(
|
|
1304
|
+
render(Parent);
|
|
1303
1305
|
|
|
1304
|
-
|
|
1305
|
-
await new Promise(resolve => setTimeout(resolve, 50));
|
|
1306
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
1306
1307
|
flushSync();
|
|
1307
1308
|
|
|
1308
1309
|
const addButton = container.querySelector('button');
|
|
1309
1310
|
|
|
1310
|
-
// Check that the promise resolved correctly with mapping applied
|
|
1311
1311
|
expect(container.querySelector('pre').textContent).toBe('[2,4,6]');
|
|
1312
1312
|
|
|
1313
|
-
// Test adding an item to the async-created array
|
|
1314
1313
|
addButton.click();
|
|
1315
1314
|
flushSync();
|
|
1316
1315
|
|
|
@@ -1318,13 +1317,20 @@ describe('RippleArray', () => {
|
|
|
1318
1317
|
});
|
|
1319
1318
|
|
|
1320
1319
|
it('handles error in fromAsync method', async () => {
|
|
1320
|
+
component Parent() {
|
|
1321
|
+
try {
|
|
1322
|
+
<ArrayTest />
|
|
1323
|
+
} async {
|
|
1324
|
+
<div>{'Loading placeholder...'}</div>
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1321
1328
|
component ArrayTest() {
|
|
1322
|
-
let itemsPromise = RippleArray.fromAsync(Promise.reject(new Error('Async error')));
|
|
1323
1329
|
let items = null;
|
|
1324
1330
|
let error = null;
|
|
1325
1331
|
|
|
1326
1332
|
try {
|
|
1327
|
-
items = await
|
|
1333
|
+
items = await RippleArray.fromAsync(Promise.reject(new Error('Async error')));
|
|
1328
1334
|
} catch (e) {
|
|
1329
1335
|
error = e.message;
|
|
1330
1336
|
}
|
|
@@ -1333,13 +1339,11 @@ describe('RippleArray', () => {
|
|
|
1333
1339
|
<pre>{items ? JSON.stringify(items) : 'No items'}</pre>
|
|
1334
1340
|
}
|
|
1335
1341
|
|
|
1336
|
-
render(
|
|
1342
|
+
render(Parent);
|
|
1337
1343
|
|
|
1338
|
-
|
|
1339
|
-
await new Promise(resolve => setTimeout(resolve, 50));
|
|
1344
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
1340
1345
|
flushSync();
|
|
1341
1346
|
|
|
1342
|
-
// Check that the error was caught correctly
|
|
1343
1347
|
expect(container.querySelectorAll('pre')[0].textContent).toBe('Error: Async error');
|
|
1344
1348
|
expect(container.querySelectorAll('pre')[1].textContent).toBe('No items');
|
|
1345
1349
|
});
|
|
@@ -1463,6 +1467,90 @@ describe('RippleArray', () => {
|
|
|
1463
1467
|
expect(container.querySelectorAll('pre')[5].textContent).toBe('items[4]: 4');
|
|
1464
1468
|
});
|
|
1465
1469
|
});
|
|
1470
|
+
|
|
1471
|
+
describe('Creates RippleArray with a single element', () => {
|
|
1472
|
+
it('specifies int', () => {
|
|
1473
|
+
component ArrayTest() {
|
|
1474
|
+
let items = new RippleArray(3);
|
|
1475
|
+
<pre>{JSON.stringify(items)}</pre>
|
|
1476
|
+
<pre>{items.$length}</pre>
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
render(ArrayTest);
|
|
1480
|
+
|
|
1481
|
+
expect(container.querySelectorAll('pre')[0].textContent).toBe('[null,null,null]');
|
|
1482
|
+
expect(container.querySelectorAll('pre')[1].textContent).toBe('3');
|
|
1483
|
+
});
|
|
1484
|
+
|
|
1485
|
+
it('errors on exceeding max array size', () => {
|
|
1486
|
+
component ArrayTest() {
|
|
1487
|
+
let error = null;
|
|
1488
|
+
|
|
1489
|
+
try {
|
|
1490
|
+
new RippleArray(MAX_ARRAY_LENGTH + 1);
|
|
1491
|
+
} catch (e) {
|
|
1492
|
+
error = e.message;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
<pre>{error}</pre>
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
render(ArrayTest);
|
|
1499
|
+
|
|
1500
|
+
expect(container.querySelector('pre').textContent).toBe('Invalid array length');
|
|
1501
|
+
});
|
|
1502
|
+
|
|
1503
|
+
it('specifies int using static from method', () => {
|
|
1504
|
+
component ArrayTest() {
|
|
1505
|
+
let items = RippleArray.from([4]);
|
|
1506
|
+
<pre>{JSON.stringify(items)}</pre>
|
|
1507
|
+
<pre>{items.$length}</pre>
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
render(ArrayTest);
|
|
1511
|
+
|
|
1512
|
+
expect(container.querySelectorAll('pre')[0].textContent).toBe('[4]');
|
|
1513
|
+
// expect(container.querySelectorAll('pre')[1].textContent).toBe('1');
|
|
1514
|
+
});
|
|
1515
|
+
|
|
1516
|
+
it('specifies int using static of method', () => {
|
|
1517
|
+
component ArrayTest() {
|
|
1518
|
+
let items = RippleArray.of(5);
|
|
1519
|
+
<pre>{JSON.stringify(items)}</pre>
|
|
1520
|
+
<pre>{items.$length}</pre>
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
render(ArrayTest);
|
|
1524
|
+
|
|
1525
|
+
expect(container.querySelectorAll('pre')[0].textContent).toBe('[5]');
|
|
1526
|
+
expect(container.querySelectorAll('pre')[1].textContent).toBe('1');
|
|
1527
|
+
});
|
|
1528
|
+
|
|
1529
|
+
('fromAsync' in Array.prototype ? it : it.skip)('specifies int using static fromAsync method', async () => {
|
|
1530
|
+
component Parent() {
|
|
1531
|
+
try {
|
|
1532
|
+
<ArrayTest />
|
|
1533
|
+
} async {
|
|
1534
|
+
<div>{'Loading placeholder...'}</div>
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
component ArrayTest() {
|
|
1539
|
+
const items = await RippleArray.fromAsync([6]);
|
|
1540
|
+
|
|
1541
|
+
<pre>{items ? JSON.stringify(items) : 'Loading...'}</pre>
|
|
1542
|
+
<pre>{items ? items.$length : ''}</pre>
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
render(Parent);
|
|
1546
|
+
|
|
1547
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
1548
|
+
flushSync();
|
|
1549
|
+
|
|
1550
|
+
expect(container.querySelectorAll('pre')[0].textContent).toBe('[6]');
|
|
1551
|
+
expect(container.querySelectorAll('pre')[1].textContent).toBe('1');
|
|
1552
|
+
});
|
|
1553
|
+
});
|
|
1466
1554
|
});
|
|
1467
1555
|
|
|
1468
1556
|
|
package/tests/basic.test.ripple
CHANGED
|
@@ -115,6 +115,12 @@ describe('basic', () => {
|
|
|
115
115
|
|
|
116
116
|
<button onClick={() => $active = !$active}>{'Toggle'}</button>
|
|
117
117
|
<div $class={$active ? 'active' : 'inactive'}>{'Dynamic Class'}</div>
|
|
118
|
+
|
|
119
|
+
<style>
|
|
120
|
+
.active {
|
|
121
|
+
color: green;
|
|
122
|
+
}
|
|
123
|
+
</style>
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
render(Basic);
|
|
@@ -122,17 +128,17 @@ describe('basic', () => {
|
|
|
122
128
|
const button = container.querySelector('button');
|
|
123
129
|
const div = container.querySelector('div');
|
|
124
130
|
|
|
125
|
-
expect(div.
|
|
126
|
-
|
|
131
|
+
expect(Array.from(div.classList).some(className => className.startsWith('ripple-'))).toBe(true);
|
|
132
|
+
expect(div.classList.contains('inactive')).toBe(true);
|
|
133
|
+
|
|
127
134
|
button.click();
|
|
128
135
|
flushSync();
|
|
129
|
-
|
|
130
|
-
expect(div.className).toBe('active');
|
|
136
|
+
expect(div.classList.contains('active')).toBe(true);
|
|
131
137
|
|
|
132
138
|
button.click();
|
|
133
139
|
flushSync();
|
|
134
140
|
|
|
135
|
-
expect(div.
|
|
141
|
+
expect(div.classList.contains('inactive')).toBe(true);
|
|
136
142
|
});
|
|
137
143
|
|
|
138
144
|
it('render dynamic id attribute', () => {
|