ripple 0.3.6 → 0.3.8
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 +43 -0
- package/package.json +2 -2
- package/src/compiler/phases/1-parse/index.js +37 -194
- package/src/compiler/phases/2-analyze/index.js +290 -26
- package/src/compiler/phases/3-transform/client/index.js +54 -14
- package/src/compiler/phases/3-transform/server/index.js +19 -35
- package/src/compiler/types/index.d.ts +3 -1
- package/src/compiler/types/parse.d.ts +0 -8
- package/src/compiler/utils.js +10 -6
- package/src/runtime/internal/client/composite.js +2 -2
- package/src/runtime/internal/client/index.js +2 -0
- package/src/runtime/internal/client/runtime.js +95 -45
- package/src/runtime/internal/client/types.d.ts +10 -0
- package/src/runtime/internal/client/utils.js +12 -0
- package/src/runtime/internal/server/index.js +89 -17
- package/src/runtime/internal/server/types.d.ts +10 -0
- package/src/utils/ast.js +1 -1
- package/tests/client/array/array.copy-within.test.ripple +12 -12
- package/tests/client/array/array.derived.test.ripple +46 -46
- package/tests/client/array/array.iteration.test.ripple +10 -10
- package/tests/client/array/array.mutations.test.ripple +20 -20
- package/tests/client/array/array.to-methods.test.ripple +6 -6
- package/tests/client/async-suspend.test.ripple +5 -5
- package/tests/client/basic/basic.attributes.test.ripple +81 -81
- package/tests/client/basic/basic.collections.test.ripple +9 -9
- package/tests/client/basic/basic.components.test.ripple +28 -28
- package/tests/client/basic/basic.errors.test.ripple +18 -18
- package/tests/client/basic/basic.events.test.ripple +37 -37
- package/tests/client/basic/basic.get-set.test.ripple +6 -6
- package/tests/client/basic/basic.reactivity.test.ripple +68 -68
- package/tests/client/basic/basic.rendering.test.ripple +19 -19
- package/tests/client/basic/basic.utilities.test.ripple +3 -3
- package/tests/client/boundaries.test.ripple +12 -12
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
- package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
- package/tests/client/compiler/compiler.basic.test.ripple +44 -15
- package/tests/client/compiler/compiler.tracked-access.test.ripple +68 -2
- package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
- package/tests/client/composite/composite.props.test.ripple +11 -11
- package/tests/client/composite/composite.reactivity.test.ripple +43 -43
- package/tests/client/composite/composite.render.test.ripple +3 -3
- package/tests/client/computed-properties.test.ripple +4 -4
- package/tests/client/date.test.ripple +42 -42
- package/tests/client/dynamic-elements.test.ripple +42 -42
- package/tests/client/events.test.ripple +70 -70
- package/tests/client/for.test.ripple +25 -25
- package/tests/client/head.test.ripple +19 -19
- package/tests/client/html.test.ripple +3 -3
- package/tests/client/input-value.test.ripple +84 -84
- package/tests/client/lazy-destructuring.test.ripple +123 -14
- package/tests/client/map.test.ripple +16 -16
- package/tests/client/media-query.test.ripple +7 -7
- package/tests/client/portal.test.ripple +11 -11
- package/tests/client/ref.test.ripple +4 -4
- package/tests/client/return.test.ripple +52 -52
- package/tests/client/set.test.ripple +6 -6
- package/tests/client/svg.test.ripple +5 -5
- package/tests/client/switch.test.ripple +44 -44
- package/tests/client/try.test.ripple +5 -5
- package/tests/client/url/url.derived.test.ripple +6 -6
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
- package/tests/hydration/compiled/client/events.js +25 -25
- package/tests/hydration/compiled/client/for.js +70 -66
- package/tests/hydration/compiled/client/head.js +25 -25
- package/tests/hydration/compiled/client/hmr.js +2 -2
- package/tests/hydration/compiled/client/html.js +3 -3
- package/tests/hydration/compiled/client/if-children.js +24 -24
- package/tests/hydration/compiled/client/if.js +18 -18
- package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
- package/tests/hydration/compiled/client/portal.js +3 -3
- package/tests/hydration/compiled/client/reactivity.js +16 -16
- package/tests/hydration/compiled/client/return.js +40 -40
- package/tests/hydration/compiled/client/switch.js +12 -12
- package/tests/hydration/compiled/server/events.js +19 -19
- package/tests/hydration/compiled/server/for.js +41 -41
- package/tests/hydration/compiled/server/head.js +26 -26
- package/tests/hydration/compiled/server/hmr.js +2 -2
- package/tests/hydration/compiled/server/html.js +2 -2
- package/tests/hydration/compiled/server/if-children.js +16 -16
- package/tests/hydration/compiled/server/if.js +11 -11
- package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
- package/tests/hydration/compiled/server/portal.js +2 -2
- package/tests/hydration/compiled/server/reactivity.js +16 -16
- package/tests/hydration/compiled/server/return.js +25 -25
- package/tests/hydration/compiled/server/switch.js +8 -8
- package/tests/hydration/components/events.ripple +25 -25
- package/tests/hydration/components/for.ripple +66 -66
- package/tests/hydration/components/head.ripple +16 -16
- package/tests/hydration/components/hmr.ripple +2 -2
- package/tests/hydration/components/html.ripple +3 -3
- package/tests/hydration/components/if-children.ripple +24 -24
- package/tests/hydration/components/if.ripple +18 -18
- package/tests/hydration/components/mixed-control-flow.ripple +9 -9
- package/tests/hydration/components/portal.ripple +3 -3
- package/tests/hydration/components/reactivity.ripple +16 -16
- package/tests/hydration/components/return.ripple +40 -40
- package/tests/hydration/components/switch.ripple +20 -20
- package/tests/server/await.test.ripple +3 -3
- package/tests/server/basic.attributes.test.ripple +34 -34
- package/tests/server/basic.components.test.ripple +10 -10
- package/tests/server/basic.test.ripple +38 -40
- package/tests/server/composite.props.test.ripple +9 -9
- package/tests/server/dynamic-elements.test.ripple +13 -12
- package/tests/server/head.test.ripple +11 -11
- package/tests/server/lazy-destructuring.test.ripple +72 -0
- package/types/index.d.ts +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# ripple
|
|
2
2
|
|
|
3
|
+
## 0.3.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies []:
|
|
8
|
+
- ripple@0.3.8
|
|
9
|
+
|
|
10
|
+
## 0.3.7
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- [#832](https://github.com/Ripple-TS/ripple/pull/832)
|
|
15
|
+
[`9ca9310`](https://github.com/Ripple-TS/ripple/commit/9ca9310550a800f4435821ed84b24bdd4f243117)
|
|
16
|
+
Thanks [@trueadm](https://github.com/trueadm)! - Fix lazy array rest
|
|
17
|
+
destructuring for tracked and array-like values by routing rest extraction
|
|
18
|
+
through a shared `array_slice` helper instead of calling `.slice()` directly on
|
|
19
|
+
the source.
|
|
20
|
+
|
|
21
|
+
- [#832](https://github.com/Ripple-TS/ripple/pull/832)
|
|
22
|
+
[`9ca9310`](https://github.com/Ripple-TS/ripple/commit/9ca9310550a800f4435821ed84b24bdd4f243117)
|
|
23
|
+
Thanks [@trueadm](https://github.com/trueadm)! - Allow tracked tuple `.length`
|
|
24
|
+
member access in compiler analysis and simplify tracked direct-access validation
|
|
25
|
+
into a single combined condition.
|
|
26
|
+
|
|
27
|
+
- [#832](https://github.com/Ripple-TS/ripple/pull/832)
|
|
28
|
+
[`9ca9310`](https://github.com/Ripple-TS/ripple/commit/9ca9310550a800f4435821ed84b24bdd4f243117)
|
|
29
|
+
Thanks [@trueadm](https://github.com/trueadm)! - Fix `to_ts` output for lazy
|
|
30
|
+
array destructuring so it keeps direct destructuring syntax for `track()` and
|
|
31
|
+
`trackSplit()` instead of expanding through an intermediate `lazy` variable.
|
|
32
|
+
|
|
33
|
+
- [#832](https://github.com/Ripple-TS/ripple/pull/832)
|
|
34
|
+
[`9ca9310`](https://github.com/Ripple-TS/ripple/commit/9ca9310550a800f4435821ed84b24bdd4f243117)
|
|
35
|
+
Thanks [@trueadm](https://github.com/trueadm)! - Replace tracked `get()`/`set()`
|
|
36
|
+
APIs with a `value` getter/setter across runtime, types, analyzer tracked-access
|
|
37
|
+
rules, and lazy destructuring tests.
|
|
38
|
+
|
|
39
|
+
- Updated dependencies
|
|
40
|
+
[[`9ca9310`](https://github.com/Ripple-TS/ripple/commit/9ca9310550a800f4435821ed84b24bdd4f243117),
|
|
41
|
+
[`9ca9310`](https://github.com/Ripple-TS/ripple/commit/9ca9310550a800f4435821ed84b24bdd4f243117),
|
|
42
|
+
[`9ca9310`](https://github.com/Ripple-TS/ripple/commit/9ca9310550a800f4435821ed84b24bdd4f243117),
|
|
43
|
+
[`9ca9310`](https://github.com/Ripple-TS/ripple/commit/9ca9310550a800f4435821ed84b24bdd4f243117)]:
|
|
44
|
+
- ripple@0.3.7
|
|
45
|
+
|
|
3
46
|
## 0.3.6
|
|
4
47
|
|
|
5
48
|
### 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.8",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -105,6 +105,6 @@
|
|
|
105
105
|
"vscode-languageserver-types": "^3.17.5"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|
|
108
|
-
"ripple": "0.3.
|
|
108
|
+
"ripple": "0.3.8"
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -52,16 +52,6 @@ function DestructuringErrors() {
|
|
|
52
52
|
return this;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
/**
|
|
56
|
-
* @param {AST.Identifier | ESTreeJSX.JSXIdentifier} node
|
|
57
|
-
* @param {string} name
|
|
58
|
-
*/
|
|
59
|
-
function set_tracked_name(node, name) {
|
|
60
|
-
node.name = name.slice(1);
|
|
61
|
-
node.metadata ??= { path: [] };
|
|
62
|
-
node.metadata.source_name = name;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
55
|
/**
|
|
66
56
|
* Convert JSX node types to regular JavaScript node types
|
|
67
57
|
* @param {ESTreeJSX.JSXIdentifier | ESTreeJSX.JSXMemberExpression | AST.Node} node - The JSX node to convert
|
|
@@ -678,7 +668,7 @@ function RipplePlugin(config) {
|
|
|
678
668
|
}
|
|
679
669
|
if (code === 64) {
|
|
680
670
|
// @ character
|
|
681
|
-
// Look ahead to see if this is followed by
|
|
671
|
+
// Look ahead to see if this is followed by an opening paren
|
|
682
672
|
if (this.pos + 1 < this.input.length) {
|
|
683
673
|
const nextChar = this.input.charCodeAt(this.pos + 1);
|
|
684
674
|
|
|
@@ -688,114 +678,11 @@ function RipplePlugin(config) {
|
|
|
688
678
|
this.pos += 2; // skip '@('
|
|
689
679
|
return this.finishToken(tt.parenL, '@(');
|
|
690
680
|
}
|
|
691
|
-
|
|
692
|
-
// Check if the next character can start an identifier
|
|
693
|
-
if (
|
|
694
|
-
(nextChar >= 65 && nextChar <= 90) || // A-Z
|
|
695
|
-
(nextChar >= 97 && nextChar <= 122) || // a-z
|
|
696
|
-
nextChar === 95 ||
|
|
697
|
-
nextChar === 36
|
|
698
|
-
) {
|
|
699
|
-
// _ or $
|
|
700
|
-
|
|
701
|
-
// Check if we're in an expression context
|
|
702
|
-
// In JSX expressions, inside parentheses, assignments, etc.
|
|
703
|
-
// we want to treat @ as an identifier prefix rather than decorator
|
|
704
|
-
const currentType = this.type;
|
|
705
|
-
/**
|
|
706
|
-
* @param {Parse.TokenType} type
|
|
707
|
-
* @param {Parse.Parser} parser
|
|
708
|
-
* @param {Parse.TokTypes} tt
|
|
709
|
-
* @returns {boolean}
|
|
710
|
-
*/
|
|
711
|
-
function inExpression(type, parser, tt) {
|
|
712
|
-
return (
|
|
713
|
-
parser.exprAllowed ||
|
|
714
|
-
type === tt.braceL || // Inside { }
|
|
715
|
-
type === tt.parenL || // Inside ( )
|
|
716
|
-
type === tt.eq || // After =
|
|
717
|
-
type === tt.comma || // After ,
|
|
718
|
-
type === tt.colon || // After :
|
|
719
|
-
type === tt.question || // After ?
|
|
720
|
-
type === tt.logicalOR || // After ||
|
|
721
|
-
type === tt.logicalAND || // After &&
|
|
722
|
-
type === tt.dot || // After . (for member expressions like obj.@prop)
|
|
723
|
-
type === tt.questionDot // After ?. (for optional chaining like obj?.@prop)
|
|
724
|
-
);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
/**
|
|
728
|
-
* @param {Parse.Parser} parser
|
|
729
|
-
* @param {Parse.TokTypes} tt
|
|
730
|
-
* @returns {boolean}
|
|
731
|
-
*/
|
|
732
|
-
function inAwait(parser, tt) {
|
|
733
|
-
return currentType === tt.name &&
|
|
734
|
-
parser.value === 'await' &&
|
|
735
|
-
parser.canAwait &&
|
|
736
|
-
parser.preToken
|
|
737
|
-
? inExpression(parser.preToken, parser, tt)
|
|
738
|
-
: false;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
if (inExpression(currentType, this, tt) || inAwait(this, tt)) {
|
|
742
|
-
return this.readAtIdentifier();
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
681
|
}
|
|
746
682
|
}
|
|
747
683
|
return super.getTokenFromCode(code);
|
|
748
684
|
}
|
|
749
685
|
|
|
750
|
-
/**
|
|
751
|
-
* Read an @ prefixed identifier
|
|
752
|
-
* @type {Parse.Parser['readAtIdentifier']}
|
|
753
|
-
*/
|
|
754
|
-
readAtIdentifier() {
|
|
755
|
-
const start = this.pos;
|
|
756
|
-
this.pos++; // skip '@'
|
|
757
|
-
|
|
758
|
-
// Read the identifier part manually
|
|
759
|
-
let word = '';
|
|
760
|
-
while (this.pos < this.input.length) {
|
|
761
|
-
const ch = this.input.charCodeAt(this.pos);
|
|
762
|
-
if (
|
|
763
|
-
(ch >= 65 && ch <= 90) || // A-Z
|
|
764
|
-
(ch >= 97 && ch <= 122) || // a-z
|
|
765
|
-
(ch >= 48 && ch <= 57) || // 0-9
|
|
766
|
-
ch === 95 ||
|
|
767
|
-
ch === 36
|
|
768
|
-
) {
|
|
769
|
-
// _ or $
|
|
770
|
-
word += this.input[this.pos++];
|
|
771
|
-
} else {
|
|
772
|
-
break;
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
if (word === '') {
|
|
777
|
-
this.raise(start, 'Invalid @ identifier');
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
// Return the full identifier including @
|
|
781
|
-
return this.finishToken(tt.name, '@' + word);
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
/**
|
|
785
|
-
* Override parseIdent to mark @ identifiers as tracked
|
|
786
|
-
* @type {Parse.Parser['parseIdent']}
|
|
787
|
-
*/
|
|
788
|
-
parseIdent(liberal) {
|
|
789
|
-
const node = /** @type {AST.Identifier &AST.NodeWithLocation} */ (
|
|
790
|
-
super.parseIdent(liberal)
|
|
791
|
-
);
|
|
792
|
-
if (node.name && node.name.startsWith('@')) {
|
|
793
|
-
set_tracked_name(node, node.name);
|
|
794
|
-
node.tracked = true;
|
|
795
|
-
}
|
|
796
|
-
return node;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
686
|
/**
|
|
800
687
|
* Override parseSubscripts to handle `.@[expression]` syntax for reactive computed member access
|
|
801
688
|
* @type {Parse.Parser['parseSubscripts']}
|
|
@@ -1342,7 +1229,6 @@ function RipplePlugin(config) {
|
|
|
1342
1229
|
jsx_parseExpressionContainer() {
|
|
1343
1230
|
let node = /** @type {ESTreeJSX.JSXExpressionContainer} */ (this.startNode());
|
|
1344
1231
|
this.next();
|
|
1345
|
-
let tracked = false;
|
|
1346
1232
|
|
|
1347
1233
|
if (this.value === 'html') {
|
|
1348
1234
|
node.html = true;
|
|
@@ -1353,20 +1239,12 @@ function RipplePlugin(config) {
|
|
|
1353
1239
|
'"html" is a Ripple keyword and must be used in the form {html some_content}',
|
|
1354
1240
|
);
|
|
1355
1241
|
}
|
|
1356
|
-
if (this.type.label === '@') {
|
|
1357
|
-
this.next(); // consume @
|
|
1358
|
-
tracked = true;
|
|
1359
|
-
}
|
|
1360
1242
|
}
|
|
1361
1243
|
|
|
1362
1244
|
node.expression =
|
|
1363
1245
|
this.type === tt.braceR ? this.jsx_parseEmptyExpression() : this.parseExpression();
|
|
1364
1246
|
this.expect(tt.braceR);
|
|
1365
1247
|
|
|
1366
|
-
if (tracked && node.expression.type === 'Identifier') {
|
|
1367
|
-
node.expression.tracked = true;
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
1248
|
return this.finishNode(node, 'JSXExpressionContainer');
|
|
1371
1249
|
}
|
|
1372
1250
|
|
|
@@ -1429,10 +1307,6 @@ function RipplePlugin(config) {
|
|
|
1429
1307
|
} else {
|
|
1430
1308
|
const id = /** @type {AST.Identifier} */ (this.parseIdentNode());
|
|
1431
1309
|
id.tracked = false;
|
|
1432
|
-
if (id.name.startsWith('@')) {
|
|
1433
|
-
set_tracked_name(id, id.name);
|
|
1434
|
-
id.tracked = true;
|
|
1435
|
-
}
|
|
1436
1310
|
this.finishNode(id, 'Identifier');
|
|
1437
1311
|
/** @type {AST.Attribute} */ (node).name = id;
|
|
1438
1312
|
/** @type {AST.Attribute} */ (node).value = id;
|
|
@@ -1484,14 +1358,6 @@ function RipplePlugin(config) {
|
|
|
1484
1358
|
// Unexpected token after @
|
|
1485
1359
|
this.unexpected();
|
|
1486
1360
|
}
|
|
1487
|
-
} else if (
|
|
1488
|
-
(this.type === tt.name || this.type === tstt.jsxName) &&
|
|
1489
|
-
this.value &&
|
|
1490
|
-
/** @type {string} */ (this.value).startsWith('@')
|
|
1491
|
-
) {
|
|
1492
|
-
set_tracked_name(node, /** @type {string} */ (this.value));
|
|
1493
|
-
node.tracked = true;
|
|
1494
|
-
this.next();
|
|
1495
1361
|
} else if (this.type === tt.name || this.type.keyword || this.type === tstt.jsxName) {
|
|
1496
1362
|
node.name = /** @type {string} */ (this.value);
|
|
1497
1363
|
node.tracked = false; // Explicitly mark as not tracked
|
|
@@ -1550,15 +1416,14 @@ function RipplePlugin(config) {
|
|
|
1550
1416
|
// Expect closing bracket
|
|
1551
1417
|
this.expect(tt.bracketR);
|
|
1552
1418
|
} else {
|
|
1553
|
-
|
|
1554
|
-
memberExpr.property = this.jsx_parseIdentifier();
|
|
1555
|
-
memberExpr.computed = false;
|
|
1419
|
+
this.unexpected();
|
|
1556
1420
|
}
|
|
1557
1421
|
} else {
|
|
1558
1422
|
// Regular dot notation
|
|
1559
1423
|
memberExpr.property = this.jsx_parseIdentifier();
|
|
1560
1424
|
memberExpr.computed = false;
|
|
1561
1425
|
}
|
|
1426
|
+
memberExpr = this.finishNode(memberExpr, 'JSXMemberExpression');
|
|
1562
1427
|
while (this.eat(tt.dot)) {
|
|
1563
1428
|
let newMemberExpr = /** @type {ESTreeJSX.JSXMemberExpression} */ (
|
|
1564
1429
|
this.startNodeAt(
|
|
@@ -1571,7 +1436,7 @@ function RipplePlugin(config) {
|
|
|
1571
1436
|
newMemberExpr.computed = false;
|
|
1572
1437
|
memberExpr = this.finishNode(newMemberExpr, 'JSXMemberExpression');
|
|
1573
1438
|
}
|
|
1574
|
-
return
|
|
1439
|
+
return memberExpr;
|
|
1575
1440
|
}
|
|
1576
1441
|
return node;
|
|
1577
1442
|
}
|
|
@@ -2355,53 +2220,6 @@ function RipplePlugin(config) {
|
|
|
2355
2220
|
this.awaitPos = 0;
|
|
2356
2221
|
return this.parseComponent({ requireName: true, declareName: true });
|
|
2357
2222
|
}
|
|
2358
|
-
if (this.type.label === '@') {
|
|
2359
|
-
// Try to parse as an expression statement first using tryParse
|
|
2360
|
-
// This allows us to handle Ripple @ syntax like @count++ without
|
|
2361
|
-
// interfering with legitimate decorator syntax
|
|
2362
|
-
this.skip_decorator = true;
|
|
2363
|
-
const expressionResult = this.tryParse(() => {
|
|
2364
|
-
const node = /** @type {AST.ExpressionStatement} */ (this.startNode());
|
|
2365
|
-
this.next();
|
|
2366
|
-
// Force expression context to ensure @ is tokenized correctly
|
|
2367
|
-
const old_expr_allowed = this.exprAllowed;
|
|
2368
|
-
this.exprAllowed = true;
|
|
2369
|
-
node.expression = this.parseExpression();
|
|
2370
|
-
|
|
2371
|
-
if (node.expression.type === 'UpdateExpression') {
|
|
2372
|
-
/** @type {AST.Expression} */
|
|
2373
|
-
let object = node.expression.argument;
|
|
2374
|
-
while (object.type === 'MemberExpression') {
|
|
2375
|
-
object = /** @type {AST.Expression} */ (object.object);
|
|
2376
|
-
}
|
|
2377
|
-
if (object.type === 'Identifier') {
|
|
2378
|
-
object.tracked = true;
|
|
2379
|
-
}
|
|
2380
|
-
} else if (node.expression.type === 'AssignmentExpression') {
|
|
2381
|
-
/** @type {AST.Expression | AST.Pattern | AST.Identifier} */
|
|
2382
|
-
let object = node.expression.left;
|
|
2383
|
-
while (object.type === 'MemberExpression') {
|
|
2384
|
-
object = /** @type {AST.Expression} */ (object.object);
|
|
2385
|
-
}
|
|
2386
|
-
if (object.type === 'Identifier') {
|
|
2387
|
-
object.tracked = true;
|
|
2388
|
-
}
|
|
2389
|
-
} else if (node.expression.type === 'Identifier') {
|
|
2390
|
-
node.expression.tracked = true;
|
|
2391
|
-
} else {
|
|
2392
|
-
// TODO?
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
|
-
this.exprAllowed = old_expr_allowed;
|
|
2396
|
-
return this.finishNode(node, 'ExpressionStatement');
|
|
2397
|
-
});
|
|
2398
|
-
this.skip_decorator = false;
|
|
2399
|
-
|
|
2400
|
-
// If parsing as expression statement succeeded, use that result
|
|
2401
|
-
if (expressionResult.node) {
|
|
2402
|
-
return expressionResult.node;
|
|
2403
|
-
}
|
|
2404
|
-
}
|
|
2405
2223
|
|
|
2406
2224
|
if (this.type === tstt.jsxTagStart) {
|
|
2407
2225
|
this.next();
|
|
@@ -2416,6 +2234,37 @@ function RipplePlugin(config) {
|
|
|
2416
2234
|
return node;
|
|
2417
2235
|
}
|
|
2418
2236
|
|
|
2237
|
+
// &[ or &{ at statement level — lazy destructuring assignment
|
|
2238
|
+
// e.g., &[data] = track(0); or &{x, y} = obj;
|
|
2239
|
+
if (this.type === tt.bitwiseAND) {
|
|
2240
|
+
const charAfterAmp = this.input.charCodeAt(this.end);
|
|
2241
|
+
if (charAfterAmp === 123 || charAfterAmp === 91) {
|
|
2242
|
+
const node = /** @type {AST.ExpressionStatement} */ (this.startNode());
|
|
2243
|
+
const assign_node = /** @type {AST.AssignmentExpression} */ (this.startNode());
|
|
2244
|
+
this.next(); // consume &
|
|
2245
|
+
// Parse the left-hand side (array or object expression)
|
|
2246
|
+
const left = /** @type {AST.ArrayPattern | AST.ObjectPattern} */ (
|
|
2247
|
+
/** @type {unknown} */ (this.parseExprAtom())
|
|
2248
|
+
);
|
|
2249
|
+
// Convert expression to destructuring pattern
|
|
2250
|
+
this.toAssignable(left, false);
|
|
2251
|
+
left.lazy = true;
|
|
2252
|
+
// Expect = operator
|
|
2253
|
+
this.expect(tt.eq);
|
|
2254
|
+
// Parse the right-hand side
|
|
2255
|
+
assign_node.operator = '=';
|
|
2256
|
+
assign_node.left = left;
|
|
2257
|
+
assign_node.right = /** @type {AST.Expression} */ (this.parseMaybeAssign());
|
|
2258
|
+
node.expression = /** @type {AST.AssignmentExpression} */ (
|
|
2259
|
+
this.finishNode(assign_node, 'AssignmentExpression')
|
|
2260
|
+
);
|
|
2261
|
+
this.semicolon();
|
|
2262
|
+
return /** @type {AST.ExpressionStatement} */ (
|
|
2263
|
+
this.finishNode(node, 'ExpressionStatement')
|
|
2264
|
+
);
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2419
2268
|
return super.parseStatement(context, topLevel, exports);
|
|
2420
2269
|
}
|
|
2421
2270
|
|
|
@@ -2809,15 +2658,9 @@ function get_comment_handlers(source, comments, index = 0) {
|
|
|
2809
2658
|
isSwitchCaseSibling = true;
|
|
2810
2659
|
} else if (parent.type === 'SwitchCase') {
|
|
2811
2660
|
node_array = parent.consequent;
|
|
2812
|
-
} else if (
|
|
2813
|
-
parent.type === 'ArrayExpression' ||
|
|
2814
|
-
parent.type === 'RippleArrayExpression'
|
|
2815
|
-
) {
|
|
2661
|
+
} else if (parent.type === 'ArrayExpression') {
|
|
2816
2662
|
node_array = parent.elements;
|
|
2817
|
-
} else if (
|
|
2818
|
-
parent.type === 'ObjectExpression' ||
|
|
2819
|
-
parent.type === 'RippleObjectExpression'
|
|
2820
|
-
) {
|
|
2663
|
+
} else if (parent.type === 'ObjectExpression') {
|
|
2821
2664
|
node_array = parent.properties;
|
|
2822
2665
|
} else if (
|
|
2823
2666
|
parent.type === 'FunctionDeclaration' ||
|