ripple 0.3.8 → 0.3.10
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 +19 -0
- package/package.json +2 -2
- package/src/compiler/phases/1-parse/index.js +38 -172
- package/src/compiler/phases/2-analyze/index.js +308 -115
- package/src/compiler/phases/2-analyze/prune.js +13 -5
- package/src/compiler/phases/3-transform/client/index.js +197 -213
- package/src/compiler/phases/3-transform/segments.js +0 -7
- package/src/compiler/phases/3-transform/server/index.js +77 -170
- package/src/compiler/types/acorn.d.ts +1 -1
- package/src/compiler/types/estree.d.ts +1 -1
- package/src/compiler/types/import.d.ts +0 -2
- package/src/compiler/types/index.d.ts +14 -18
- package/src/compiler/types/parse.d.ts +3 -9
- package/src/compiler/utils.js +154 -21
- package/src/runtime/element.js +39 -0
- package/src/runtime/index-client.js +2 -13
- package/src/runtime/index-server.js +2 -2
- package/src/runtime/internal/client/bindings.js +3 -1
- package/src/runtime/internal/client/composite.js +11 -6
- package/src/runtime/internal/client/events.js +1 -1
- package/src/runtime/internal/client/expression.js +218 -0
- package/src/runtime/internal/client/head.js +3 -4
- package/src/runtime/internal/client/index.js +4 -1
- package/src/runtime/internal/client/portal.js +12 -6
- package/src/runtime/internal/client/runtime.js +0 -52
- package/src/runtime/internal/server/index.js +57 -56
- package/tests/client/basic/basic.components.test.ripple +85 -87
- package/tests/client/basic/basic.errors.test.ripple +28 -4
- package/tests/client/basic/basic.reactivity.test.ripple +10 -155
- package/tests/client/basic/basic.rendering.test.ripple +23 -8
- package/tests/client/capture-error.js +12 -0
- package/tests/client/compiler/compiler.basic.test.ripple +107 -18
- package/tests/client/composite/composite.props.test.ripple +5 -9
- package/tests/client/composite/composite.reactivity.test.ripple +35 -36
- package/tests/client/composite/composite.render.test.ripple +45 -13
- package/tests/client/css/global-additional-cases.test.ripple +3 -3
- package/tests/client/dynamic-elements.test.ripple +3 -4
- package/tests/client/lazy-destructuring.test.ripple +69 -12
- package/tests/client/svg.test.ripple +4 -4
- package/tests/hydration/basic.test.js +23 -0
- package/tests/hydration/compiled/client/basic.js +118 -66
- package/tests/hydration/compiled/client/composite.js +90 -37
- package/tests/hydration/compiled/client/events.js +18 -18
- package/tests/hydration/compiled/client/for.js +62 -62
- package/tests/hydration/compiled/client/head.js +10 -10
- package/tests/hydration/compiled/client/hmr.js +13 -10
- package/tests/hydration/compiled/client/html.js +274 -236
- package/tests/hydration/compiled/client/if-children.js +41 -35
- package/tests/hydration/compiled/client/if.js +2 -2
- package/tests/hydration/compiled/client/mixed-control-flow.js +12 -12
- package/tests/hydration/compiled/client/nested-control-flow.js +46 -46
- package/tests/hydration/compiled/client/portal.js +8 -8
- package/tests/hydration/compiled/client/reactivity.js +14 -14
- package/tests/hydration/compiled/client/return.js +2 -2
- package/tests/hydration/compiled/client/try.js +4 -4
- package/tests/hydration/compiled/server/basic.js +64 -31
- package/tests/hydration/compiled/server/composite.js +62 -29
- package/tests/hydration/compiled/server/hmr.js +24 -37
- package/tests/hydration/compiled/server/html.js +472 -611
- package/tests/hydration/compiled/server/if-children.js +77 -103
- package/tests/hydration/compiled/server/portal.js +8 -8
- package/tests/hydration/components/basic.ripple +15 -5
- package/tests/hydration/components/composite.ripple +13 -1
- package/tests/hydration/components/hmr.ripple +1 -3
- package/tests/hydration/components/html.ripple +13 -35
- package/tests/hydration/components/if-children.ripple +4 -8
- package/tests/hydration/composite.test.js +11 -0
- package/tests/server/basic.attributes.test.ripple +50 -0
- package/tests/server/basic.components.test.ripple +22 -28
- package/tests/server/basic.test.ripple +12 -0
- package/tests/server/compiler.test.ripple +43 -4
- package/tests/server/composite.props.test.ripple +5 -9
- package/tests/server/dynamic-elements.test.ripple +3 -4
- package/tests/server/lazy-destructuring.test.ripple +68 -12
- package/tests/server/style-identifier.test.ripple +2 -4
- package/tsconfig.typecheck.json +4 -0
- package/types/index.d.ts +9 -21
- package/tests/client/__snapshots__/tracked-expression.test.ripple.snap +0 -34
- package/tests/client/tracked-expression.test.ripple +0 -26
|
@@ -53,11 +53,13 @@ import {
|
|
|
53
53
|
determine_namespace_for_children,
|
|
54
54
|
index_to_key,
|
|
55
55
|
is_element_dynamic,
|
|
56
|
+
is_children_template_expression,
|
|
56
57
|
is_inside_left_side_assignment,
|
|
57
58
|
hash,
|
|
58
59
|
flatten_switch_consequent,
|
|
59
60
|
get_ripple_namespace_call_name,
|
|
60
61
|
is_ripple_import,
|
|
62
|
+
replace_lazy_param_pattern,
|
|
61
63
|
ripple_import_requires_block,
|
|
62
64
|
} from '../../../utils.js';
|
|
63
65
|
import {
|
|
@@ -111,16 +113,12 @@ function visit_function(node, context) {
|
|
|
111
113
|
// Replace lazy destructuring params with generated identifiers
|
|
112
114
|
const transformed_params = node.params.map((param) => {
|
|
113
115
|
const pattern = param.type === 'AssignmentPattern' ? param.left : param;
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
pattern.lazy &&
|
|
117
|
-
pattern.metadata?.lazy_id
|
|
118
|
-
) {
|
|
119
|
-
const id = b.id(pattern.metadata.lazy_id);
|
|
116
|
+
if (pattern.type === 'ObjectPattern' || pattern.type === 'ArrayPattern') {
|
|
117
|
+
const transformed_pattern = replace_lazy_param_pattern(pattern);
|
|
120
118
|
if (param.type === 'AssignmentPattern') {
|
|
121
|
-
return /** @type {AST.AssignmentPattern} */ ({ ...param, left:
|
|
119
|
+
return /** @type {AST.AssignmentPattern} */ ({ ...param, left: transformed_pattern });
|
|
122
120
|
}
|
|
123
|
-
return
|
|
121
|
+
return transformed_pattern;
|
|
124
122
|
}
|
|
125
123
|
return param;
|
|
126
124
|
});
|
|
@@ -633,7 +631,7 @@ const visitors = {
|
|
|
633
631
|
|
|
634
632
|
const matched_track_call = !context.state.to_ts ? is_ripple_track_call(callee, context) : null;
|
|
635
633
|
if (matched_track_call) {
|
|
636
|
-
const track_method_name =
|
|
634
|
+
const track_method_name = 'track';
|
|
637
635
|
|
|
638
636
|
if (callee.type === 'Identifier' && callee.name === 'track') {
|
|
639
637
|
if (node.arguments.length === 0) {
|
|
@@ -803,71 +801,11 @@ const visitors = {
|
|
|
803
801
|
return b.call('_$_.with_scope', b.id('__block'), b.thunk(new_node));
|
|
804
802
|
},
|
|
805
803
|
|
|
806
|
-
TrackedExpression(node, context) {
|
|
807
|
-
if (context.state.to_ts) {
|
|
808
|
-
const visited = /** @type {AST.Expression} */ (context.visit(node.argument));
|
|
809
|
-
const member = b.member(
|
|
810
|
-
visited,
|
|
811
|
-
b.literal('#v'),
|
|
812
|
-
true,
|
|
813
|
-
!is_inside_left_side_assignment(node),
|
|
814
|
-
/** @type {AST.NodeWithLocation} */ (node),
|
|
815
|
-
);
|
|
816
|
-
member.tracked = true;
|
|
817
|
-
return member;
|
|
818
|
-
}
|
|
819
|
-
return b.call('_$_.get', /** @type {AST.Expression} */ (context.visit(node.argument)));
|
|
820
|
-
},
|
|
821
|
-
|
|
822
804
|
MemberExpression(node, context) {
|
|
823
805
|
if (context.state.metadata?.tracking === false) {
|
|
824
806
|
context.state.metadata.tracking = true;
|
|
825
807
|
}
|
|
826
808
|
|
|
827
|
-
if (
|
|
828
|
-
node.tracked ||
|
|
829
|
-
((node.property.type === 'Identifier' || node.property.type === 'Literal') &&
|
|
830
|
-
node.property.tracked)
|
|
831
|
-
) {
|
|
832
|
-
if (context.state.to_ts) {
|
|
833
|
-
// In TypeScript mode, transform @user.@name or @user.@['name'] or @user?.@name
|
|
834
|
-
// to user['#v'].name['#v'] or user['#v']['name']['#v'] or user['#v']?.name['#v']
|
|
835
|
-
const visited_object = /** @type {AST.Expression} */ (context.visit(node.object));
|
|
836
|
-
const visited_property = /** @type {AST.Expression} */ (context.visit(node.property));
|
|
837
|
-
|
|
838
|
-
// Build the member access: object.property or object[property]
|
|
839
|
-
const member = b.member(
|
|
840
|
-
visited_object,
|
|
841
|
-
visited_property,
|
|
842
|
-
node.computed,
|
|
843
|
-
node.optional,
|
|
844
|
-
/** @type {AST.NodeWithLocation} */ (node),
|
|
845
|
-
);
|
|
846
|
-
|
|
847
|
-
// Wrap with ['#v'] access
|
|
848
|
-
const member_expanded = b.member(
|
|
849
|
-
member,
|
|
850
|
-
b.literal('#v'),
|
|
851
|
-
true,
|
|
852
|
-
!is_inside_left_side_assignment(node),
|
|
853
|
-
/** @type {AST.NodeWithLocation} */ (node),
|
|
854
|
-
);
|
|
855
|
-
member_expanded.tracked = true;
|
|
856
|
-
return member_expanded;
|
|
857
|
-
} else {
|
|
858
|
-
if (!context.state.to_ts) {
|
|
859
|
-
return b.call(
|
|
860
|
-
'_$_.get_property',
|
|
861
|
-
/** @type {AST.Expression} */ (context.visit(node.object)),
|
|
862
|
-
node.computed
|
|
863
|
-
? /** @type {AST.Expression} */ (context.visit(node.property))
|
|
864
|
-
: b.literal(/** @type {AST.Identifier} */ (node.property).name),
|
|
865
|
-
node.optional ? b.true : undefined,
|
|
866
|
-
);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
|
|
871
809
|
if (node.object.type === 'MemberExpression' && node.object.optional) {
|
|
872
810
|
const metadata = { tracking: false, await: false };
|
|
873
811
|
|
|
@@ -1640,7 +1578,8 @@ const visitors = {
|
|
|
1640
1578
|
child.type === 'Html' ||
|
|
1641
1579
|
(child.type === 'Element' &&
|
|
1642
1580
|
(child.id.type !== 'Identifier' || !is_element_dom_element(child))) ||
|
|
1643
|
-
(child.type === '
|
|
1581
|
+
((child.type === 'RippleExpression' || child.type === 'Text') &&
|
|
1582
|
+
child.expression.type !== 'Literal'),
|
|
1644
1583
|
);
|
|
1645
1584
|
|
|
1646
1585
|
if (needs_pop) {
|
|
@@ -1674,7 +1613,7 @@ const visitors = {
|
|
|
1674
1613
|
const is_spreading = node.attributes.some((attr) => attr.type === 'SpreadAttribute');
|
|
1675
1614
|
/** @type {(AST.Property | AST.SpreadElement)[]} */
|
|
1676
1615
|
const props = [];
|
|
1677
|
-
/** @type {AST.
|
|
1616
|
+
/** @type {AST.Property | null} */
|
|
1678
1617
|
let children_prop = null;
|
|
1679
1618
|
|
|
1680
1619
|
for (const attr of node.attributes) {
|
|
@@ -1696,7 +1635,15 @@ const visitors = {
|
|
|
1696
1635
|
|
|
1697
1636
|
if (metadata.tracking || attr.name.tracked) {
|
|
1698
1637
|
if (attr.name.name === 'children') {
|
|
1699
|
-
children_prop = b.
|
|
1638
|
+
children_prop = b.prop(
|
|
1639
|
+
'get',
|
|
1640
|
+
b.id('children'),
|
|
1641
|
+
b.function(
|
|
1642
|
+
null,
|
|
1643
|
+
[],
|
|
1644
|
+
b.block([b.return(b.call('_$_.normalize_children', property))]),
|
|
1645
|
+
),
|
|
1646
|
+
);
|
|
1700
1647
|
continue;
|
|
1701
1648
|
}
|
|
1702
1649
|
|
|
@@ -1708,6 +1655,15 @@ const visitors = {
|
|
|
1708
1655
|
),
|
|
1709
1656
|
);
|
|
1710
1657
|
} else {
|
|
1658
|
+
if (attr.name.name === 'children') {
|
|
1659
|
+
children_prop = b.prop(
|
|
1660
|
+
'init',
|
|
1661
|
+
b.id('children'),
|
|
1662
|
+
b.call('_$_.normalize_children', property),
|
|
1663
|
+
);
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1711
1667
|
props.push(b.prop('init', b.key(attr.name.name), property));
|
|
1712
1668
|
}
|
|
1713
1669
|
} else {
|
|
@@ -1757,60 +1713,62 @@ const visitors = {
|
|
|
1757
1713
|
}
|
|
1758
1714
|
}
|
|
1759
1715
|
|
|
1760
|
-
const children_filtered =
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
if (child.type === 'Component') {
|
|
1764
|
-
// in this case, id cannot be null
|
|
1765
|
-
// as these are direct children of the component
|
|
1766
|
-
const id = /** @type {AST.Identifier} */ (child.id);
|
|
1767
|
-
props.push(
|
|
1768
|
-
b.prop(
|
|
1769
|
-
'init',
|
|
1770
|
-
id,
|
|
1771
|
-
/** @type {AST.Expression} */ (
|
|
1772
|
-
visit(child, { ...state, namespace: child_namespace })
|
|
1773
|
-
),
|
|
1774
|
-
),
|
|
1775
|
-
);
|
|
1776
|
-
} else {
|
|
1777
|
-
children_filtered.push(child);
|
|
1778
|
-
}
|
|
1779
|
-
}
|
|
1716
|
+
const children_filtered = node.children.filter(
|
|
1717
|
+
(child) => child.type !== 'EmptyStatement' && child.type !== 'Component',
|
|
1718
|
+
);
|
|
1780
1719
|
|
|
1781
1720
|
if (children_filtered.length > 0) {
|
|
1782
1721
|
const component_scope = state.scopes.get(node);
|
|
1783
|
-
const children_component = b.component(b.id('
|
|
1784
|
-
|
|
1785
|
-
const children =
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1722
|
+
const children_component = b.component(b.id('render_children'), [], children_filtered);
|
|
1723
|
+
|
|
1724
|
+
const children = b.call(
|
|
1725
|
+
'_$_.ripple_element',
|
|
1726
|
+
/** @type {AST.Expression} */ (
|
|
1727
|
+
visit(children_component, {
|
|
1728
|
+
...state,
|
|
1729
|
+
...(apply_parent_css_scope ||
|
|
1730
|
+
(is_dynamic_element && node.metadata.scoped && state.component?.css)
|
|
1731
|
+
? {
|
|
1732
|
+
applyParentCssScope:
|
|
1733
|
+
apply_parent_css_scope ||
|
|
1734
|
+
/** @type {AST.CSS.StyleSheet} */ (state.component?.css).hash,
|
|
1735
|
+
}
|
|
1736
|
+
: {}),
|
|
1737
|
+
scope: /** @type {ScopeInterface} */ (component_scope),
|
|
1738
|
+
namespace: child_namespace,
|
|
1739
|
+
})
|
|
1740
|
+
),
|
|
1799
1741
|
);
|
|
1800
1742
|
|
|
1801
1743
|
if (children_prop) {
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1744
|
+
if (children_prop.kind === 'get') {
|
|
1745
|
+
/** @type {AST.ReturnStatement} */ (
|
|
1746
|
+
/** @type {AST.FunctionExpression} */ (children_prop.value).body.body[0]
|
|
1747
|
+
).argument = b.logical(
|
|
1748
|
+
'??',
|
|
1749
|
+
/** @type {AST.Expression} */ (
|
|
1750
|
+
/** @type {AST.ReturnStatement} */ (
|
|
1751
|
+
/** @type {AST.FunctionExpression} */ (children_prop.value).body.body[0]
|
|
1752
|
+
).argument
|
|
1753
|
+
),
|
|
1754
|
+
children,
|
|
1755
|
+
);
|
|
1756
|
+
} else {
|
|
1757
|
+
children_prop.value = b.logical(
|
|
1758
|
+
'??',
|
|
1759
|
+
/** @type {AST.Expression} */ (children_prop.value),
|
|
1760
|
+
children,
|
|
1761
|
+
);
|
|
1762
|
+
}
|
|
1809
1763
|
} else {
|
|
1810
|
-
|
|
1764
|
+
children_prop = b.prop('init', b.id('children'), children);
|
|
1811
1765
|
}
|
|
1812
1766
|
}
|
|
1813
1767
|
|
|
1768
|
+
if (children_prop) {
|
|
1769
|
+
props.push(children_prop);
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1814
1772
|
const metadata = { tracking: false, await: false };
|
|
1815
1773
|
// We visit, but only to gather metadata
|
|
1816
1774
|
b.call(/** @type {AST.Expression} */ (visit(node.id, { ...state, metadata })));
|
|
@@ -1986,7 +1944,9 @@ const visitors = {
|
|
|
1986
1944
|
delete props_param.typeAnnotation;
|
|
1987
1945
|
if (!props_param.lazy) {
|
|
1988
1946
|
// Non-lazy destructuring: use the pattern directly as the function param
|
|
1989
|
-
props =
|
|
1947
|
+
props = /** @type {AST.ObjectPattern | AST.ArrayPattern} */ (
|
|
1948
|
+
replace_lazy_param_pattern(props_param)
|
|
1949
|
+
);
|
|
1990
1950
|
}
|
|
1991
1951
|
// Lazy destructuring: props stays as __props, bindings resolved via transforms
|
|
1992
1952
|
}
|
|
@@ -2059,56 +2019,6 @@ const visitors = {
|
|
|
2059
2019
|
}
|
|
2060
2020
|
}
|
|
2061
2021
|
|
|
2062
|
-
if (
|
|
2063
|
-
left.type === 'MemberExpression' &&
|
|
2064
|
-
(left.tracked || (left.property.type === 'Identifier' && left.property.tracked))
|
|
2065
|
-
) {
|
|
2066
|
-
const operator = node.operator;
|
|
2067
|
-
const right = node.right;
|
|
2068
|
-
|
|
2069
|
-
if (operator !== '=' && context.state.metadata?.tracking === false) {
|
|
2070
|
-
context.state.metadata.tracking = true;
|
|
2071
|
-
}
|
|
2072
|
-
|
|
2073
|
-
return b.call(
|
|
2074
|
-
'_$_.set_property',
|
|
2075
|
-
/** @type {AST.Expression} */ (
|
|
2076
|
-
context.visit(left.object, { ...context.state, metadata: { tracking: false } })
|
|
2077
|
-
),
|
|
2078
|
-
left.computed
|
|
2079
|
-
? /** @type {AST.Expression} */ (context.visit(left.property))
|
|
2080
|
-
: b.literal(/** @type {AST.Identifier} */ (left.property).name),
|
|
2081
|
-
operator === '='
|
|
2082
|
-
? /** @type {AST.Expression} */ (context.visit(right))
|
|
2083
|
-
: b.binary(
|
|
2084
|
-
operator === '+=' ? '+' : operator === '-=' ? '-' : operator === '*=' ? '*' : '/',
|
|
2085
|
-
/** @type {AST.Expression} */ (context.visit(left)),
|
|
2086
|
-
/** @type {AST.Expression} */ (context.visit(right)),
|
|
2087
|
-
),
|
|
2088
|
-
);
|
|
2089
|
-
}
|
|
2090
|
-
|
|
2091
|
-
if (left.type === 'Identifier' && left.tracked) {
|
|
2092
|
-
const operator = node.operator;
|
|
2093
|
-
const right = node.right;
|
|
2094
|
-
|
|
2095
|
-
return b.call(
|
|
2096
|
-
'_$_.set',
|
|
2097
|
-
/** @type {AST.Expression} */ (
|
|
2098
|
-
context.visit(left, { ...context.state, metadata: { tracking: null } })
|
|
2099
|
-
),
|
|
2100
|
-
operator === '='
|
|
2101
|
-
? /** @type {AST.Expression} */ (context.visit(right))
|
|
2102
|
-
: b.binary(
|
|
2103
|
-
operator === '+=' ? '+' : operator === '-=' ? '-' : operator === '*=' ? '*' : '/',
|
|
2104
|
-
/** @type {AST.Expression} */ (
|
|
2105
|
-
context.visit(left, { ...context.state, metadata: { tracking: false } })
|
|
2106
|
-
),
|
|
2107
|
-
/** @type {AST.Expression} */ (context.visit(right)),
|
|
2108
|
-
),
|
|
2109
|
-
);
|
|
2110
|
-
}
|
|
2111
|
-
|
|
2112
2022
|
return visit_assignment_expression(node, context, build_assignment) ?? context.next();
|
|
2113
2023
|
},
|
|
2114
2024
|
|
|
@@ -2126,43 +2036,6 @@ const visitors = {
|
|
|
2126
2036
|
}
|
|
2127
2037
|
}
|
|
2128
2038
|
|
|
2129
|
-
if (
|
|
2130
|
-
argument.type === 'MemberExpression' &&
|
|
2131
|
-
(argument.tracked || (argument.property.type === 'Identifier' && argument.property.tracked))
|
|
2132
|
-
) {
|
|
2133
|
-
if (context.state.metadata?.tracking === false) {
|
|
2134
|
-
context.state.metadata.tracking = true;
|
|
2135
|
-
}
|
|
2136
|
-
|
|
2137
|
-
return b.call(
|
|
2138
|
-
node.prefix ? '_$_.update_pre_property' : '_$_.update_property',
|
|
2139
|
-
/** @type {AST.Expression} */
|
|
2140
|
-
(context.visit(argument.object, { ...context.state, metadata: { tracking: false } })),
|
|
2141
|
-
argument.computed
|
|
2142
|
-
? /** @type {AST.Expression} */ (context.visit(argument.property))
|
|
2143
|
-
: b.literal(/** @type {AST.Identifier} */ (argument.property).name),
|
|
2144
|
-
node.operator === '--' ? b.literal(-1) : undefined,
|
|
2145
|
-
);
|
|
2146
|
-
}
|
|
2147
|
-
|
|
2148
|
-
if (argument.type === 'Identifier' && argument.tracked) {
|
|
2149
|
-
return b.call(
|
|
2150
|
-
node.prefix ? '_$_.update_pre' : '_$_.update',
|
|
2151
|
-
/** @type {AST.Expression} */
|
|
2152
|
-
(context.visit(argument, { ...context.state, metadata: { tracking: null } })),
|
|
2153
|
-
node.operator === '--' ? b.literal(-1) : undefined,
|
|
2154
|
-
);
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
|
-
if (argument.type === 'TrackedExpression') {
|
|
2158
|
-
return b.call(
|
|
2159
|
-
node.prefix ? '_$_.update_pre' : '_$_.update',
|
|
2160
|
-
/** @type {AST.Expression} */
|
|
2161
|
-
(context.visit(argument.argument, { ...context.state, metadata: { tracking: null } })),
|
|
2162
|
-
node.operator === '--' ? b.literal(-1) : undefined,
|
|
2163
|
-
);
|
|
2164
|
-
}
|
|
2165
|
-
|
|
2166
2039
|
const left = object(/** @type {AST.MemberExpression | AST.Identifier} */ (argument));
|
|
2167
2040
|
const binding = left && context.state.scope.get(left.name);
|
|
2168
2041
|
const transformers = left && binding?.transform;
|
|
@@ -2786,7 +2659,7 @@ function join_template(items) {
|
|
|
2786
2659
|
function transform_ts_child(node, context) {
|
|
2787
2660
|
const { state, visit } = context;
|
|
2788
2661
|
|
|
2789
|
-
if (node.type === 'Text') {
|
|
2662
|
+
if (node.type === 'RippleExpression' || node.type === 'Text') {
|
|
2790
2663
|
state.init?.push(b.stmt(/** @type {AST.Expression} */ (visit(node.expression, { ...state }))));
|
|
2791
2664
|
} else if (node.type === 'Html') {
|
|
2792
2665
|
// Do we need to do something special here?
|
|
@@ -2953,12 +2826,29 @@ function transform_ts_child(node, context) {
|
|
|
2953
2826
|
// The `is_capitalized` was never handled for MemberExpression
|
|
2954
2827
|
// but it should've been for the `object` part because it starts the tag
|
|
2955
2828
|
// But the plan is to only rely on source_name and creating a const for the tag with ['#v']
|
|
2829
|
+
const source_name = /** @type {AST.Identifier} */ (node.id).name;
|
|
2830
|
+
const capitalized_name = source_name.charAt(0).toUpperCase() + source_name.slice(1);
|
|
2831
|
+
|
|
2832
|
+
// node.id and node.openingElement.name are the SAME object (convert_from_jsx mutates
|
|
2833
|
+
// the JSXIdentifier to an Identifier in-place). Capitalize the name directly so that
|
|
2834
|
+
// the generated JSX uses <Tag> (uppercase) matching the capitalized variable declaration,
|
|
2835
|
+
// preventing the TypeScript "declared but never read" false-negative (ts6133).
|
|
2836
|
+
/** @type {AST.Identifier} */ (node.id).name = capitalized_name;
|
|
2837
|
+
if (!node.id.metadata) node.id.metadata = /** @type {any} */ ({});
|
|
2838
|
+
node.id.metadata.is_capitalized = true;
|
|
2839
|
+
node.id.metadata.source_name = source_name;
|
|
2840
|
+
|
|
2956
2841
|
node.openingElement.metadata = {
|
|
2957
2842
|
...node.openingElement.metadata,
|
|
2958
2843
|
is_capitalized: true,
|
|
2959
2844
|
};
|
|
2960
2845
|
|
|
2961
2846
|
if (!node.selfClosing && !node.unclosed) {
|
|
2847
|
+
// closingElement.name is a separate JSXIdentifier (not the same object as node.id)
|
|
2848
|
+
// so we need to capitalize it separately
|
|
2849
|
+
if (node.closingElement.name && 'name' in node.closingElement.name) {
|
|
2850
|
+
/** @type {{ name: string }} */ (node.closingElement.name).name = capitalized_name;
|
|
2851
|
+
}
|
|
2962
2852
|
node.closingElement.metadata = {
|
|
2963
2853
|
...node.closingElement.metadata,
|
|
2964
2854
|
is_capitalized: true,
|
|
@@ -3212,6 +3102,7 @@ function transform_ts_child(node, context) {
|
|
|
3212
3102
|
function is_template_or_control_flow(node) {
|
|
3213
3103
|
return (
|
|
3214
3104
|
node.type === 'Element' ||
|
|
3105
|
+
node.type === 'RippleExpression' ||
|
|
3215
3106
|
node.type === 'Text' ||
|
|
3216
3107
|
node.type === 'Html' ||
|
|
3217
3108
|
node.type === 'TsxCompat' ||
|
|
@@ -3310,7 +3201,10 @@ function element_has_dynamic_content(element) {
|
|
|
3310
3201
|
) {
|
|
3311
3202
|
return true;
|
|
3312
3203
|
}
|
|
3313
|
-
if (
|
|
3204
|
+
if (
|
|
3205
|
+
(child.type === 'RippleExpression' || child.type === 'Text') &&
|
|
3206
|
+
child.expression.type !== 'Literal'
|
|
3207
|
+
) {
|
|
3314
3208
|
return true;
|
|
3315
3209
|
}
|
|
3316
3210
|
// Non-DOM element (component)
|
|
@@ -3482,6 +3376,14 @@ function transform_children(children, context) {
|
|
|
3482
3376
|
(node.type === 'Element' &&
|
|
3483
3377
|
(node.id.type !== 'Identifier' || !is_element_dom_element(node))),
|
|
3484
3378
|
) ||
|
|
3379
|
+
(normalized.filter(
|
|
3380
|
+
(node) => node.type !== 'VariableDeclaration' && node.type !== 'EmptyStatement',
|
|
3381
|
+
).length === 1 &&
|
|
3382
|
+
normalized.some(
|
|
3383
|
+
(node) =>
|
|
3384
|
+
node.type === 'RippleExpression' &&
|
|
3385
|
+
is_children_template_expression(node.expression, state.scope),
|
|
3386
|
+
)) ||
|
|
3485
3387
|
normalized.filter(
|
|
3486
3388
|
(node) => node.type !== 'VariableDeclaration' && node.type !== 'EmptyStatement',
|
|
3487
3389
|
).length > 1;
|
|
@@ -3496,9 +3398,11 @@ function transform_children(children, context) {
|
|
|
3496
3398
|
return b.id(
|
|
3497
3399
|
node.type == 'Element' && is_element_dom_element(node)
|
|
3498
3400
|
? state.scope.generate(/** @type {AST.Identifier} */ (node.id).name)
|
|
3499
|
-
: node.type == '
|
|
3500
|
-
? state.scope.generate('
|
|
3501
|
-
:
|
|
3401
|
+
: node.type == 'RippleExpression'
|
|
3402
|
+
? state.scope.generate('expression')
|
|
3403
|
+
: node.type == 'Text'
|
|
3404
|
+
? state.scope.generate('text')
|
|
3405
|
+
: state.scope.generate('node'),
|
|
3502
3406
|
/** @type {AST.NodeWithLocation} */ (node.type === 'Element' ? node.openingElement : node),
|
|
3503
3407
|
);
|
|
3504
3408
|
};
|
|
@@ -3652,11 +3556,11 @@ function transform_children(children, context) {
|
|
|
3652
3556
|
/** @type {AST.Expression | undefined} */
|
|
3653
3557
|
let expression = undefined;
|
|
3654
3558
|
let is_create_text_only = false;
|
|
3655
|
-
if (node.type === 'Text' || node.type === 'Html') {
|
|
3559
|
+
if (node.type === 'RippleExpression' || node.type === 'Text' || node.type === 'Html') {
|
|
3656
3560
|
metadata = { tracking: false, await: false };
|
|
3657
3561
|
expression = /** @type {AST.Expression} */ (visit(node.expression, { ...state, metadata }));
|
|
3658
3562
|
is_create_text_only =
|
|
3659
|
-
node.type
|
|
3563
|
+
node.type !== 'Html' && normalized.length === 1 && expression.type === 'Literal';
|
|
3660
3564
|
}
|
|
3661
3565
|
|
|
3662
3566
|
if (initial === null && root && !is_create_text_only) {
|
|
@@ -3752,7 +3656,8 @@ function transform_children(children, context) {
|
|
|
3752
3656
|
child.type === 'Html' ||
|
|
3753
3657
|
(child.type === 'Element' &&
|
|
3754
3658
|
(child.id.type !== 'Identifier' || !is_element_dom_element(child))) ||
|
|
3755
|
-
(child.type === '
|
|
3659
|
+
((child.type === 'RippleExpression' || child.type === 'Text') &&
|
|
3660
|
+
child.expression.type !== 'Literal'),
|
|
3756
3661
|
);
|
|
3757
3662
|
|
|
3758
3663
|
// Add pop() if we have DOM element children AND the Element visitor didn't already add pop()
|
|
@@ -3768,7 +3673,7 @@ function transform_children(children, context) {
|
|
|
3768
3673
|
// Components always generate sibling()
|
|
3769
3674
|
needs_sibling_call = true;
|
|
3770
3675
|
}
|
|
3771
|
-
} else if (next_node.type === 'Text') {
|
|
3676
|
+
} else if (next_node.type === 'RippleExpression' || next_node.type === 'Text') {
|
|
3772
3677
|
// Only dynamic text generates sibling()
|
|
3773
3678
|
needs_sibling_call = next_node.expression.type !== 'Literal';
|
|
3774
3679
|
} else if (
|
|
@@ -3814,6 +3719,85 @@ function transform_children(children, context) {
|
|
|
3814
3719
|
),
|
|
3815
3720
|
),
|
|
3816
3721
|
});
|
|
3722
|
+
} else if (node.type === 'RippleExpression') {
|
|
3723
|
+
const expr = /** @type {AST.Expression} */ (expression);
|
|
3724
|
+
const is_children_expression = is_children_template_expression(
|
|
3725
|
+
node.expression,
|
|
3726
|
+
state.scope,
|
|
3727
|
+
);
|
|
3728
|
+
|
|
3729
|
+
if (expr.type === 'Literal') {
|
|
3730
|
+
if (normalized.length === 1) {
|
|
3731
|
+
skipped++;
|
|
3732
|
+
if (
|
|
3733
|
+
/** @type {NonNullable<TransformClientState['template']>} */ (state.template).length >
|
|
3734
|
+
0
|
|
3735
|
+
) {
|
|
3736
|
+
state.template?.push(escape_html(expr.value));
|
|
3737
|
+
} else {
|
|
3738
|
+
const id = flush_node(true);
|
|
3739
|
+
state.init?.push(b.var(/** @type {AST.Identifier} */ (id), b.call('_$_.text', expr)));
|
|
3740
|
+
state.final?.push(b.stmt(b.call('_$_.append', b.id('__anchor'), id)));
|
|
3741
|
+
}
|
|
3742
|
+
} else {
|
|
3743
|
+
skipped++;
|
|
3744
|
+
state.template?.push(escape_html(expr.value));
|
|
3745
|
+
}
|
|
3746
|
+
} else if (is_children_expression) {
|
|
3747
|
+
skipped = 0;
|
|
3748
|
+
state.template?.push('<!>');
|
|
3749
|
+
const id = flush_node(false);
|
|
3750
|
+
state.update?.push({
|
|
3751
|
+
operation: () => {
|
|
3752
|
+
const call = b.call('_$_.expression', id, b.thunk(expr));
|
|
3753
|
+
return state.namespace !== DEFAULT_NAMESPACE
|
|
3754
|
+
? b.stmt(b.call('_$_.with_ns', b.literal(state.namespace), b.thunk(call)))
|
|
3755
|
+
: b.stmt(call);
|
|
3756
|
+
},
|
|
3757
|
+
});
|
|
3758
|
+
if (metadata?.await) {
|
|
3759
|
+
/** @type {NonNullable<TransformClientState['update']>} */ (state.update).async = true;
|
|
3760
|
+
}
|
|
3761
|
+
} else if (metadata?.tracking) {
|
|
3762
|
+
skipped = 0;
|
|
3763
|
+
state.template?.push(' ');
|
|
3764
|
+
const id = flush_node(true);
|
|
3765
|
+
state.update?.push({
|
|
3766
|
+
operation: (key) => b.stmt(b.call('_$_.set_text', id, key)),
|
|
3767
|
+
expression: expr,
|
|
3768
|
+
identity: node.expression,
|
|
3769
|
+
initial: b.literal(' '),
|
|
3770
|
+
});
|
|
3771
|
+
if (metadata.await) {
|
|
3772
|
+
/** @type {NonNullable<TransformClientState['update']>} */ (state.update).async = true;
|
|
3773
|
+
}
|
|
3774
|
+
} else if (normalized.length === 1) {
|
|
3775
|
+
skipped++;
|
|
3776
|
+
const id = flush_node(true);
|
|
3777
|
+
state.template?.push(' ');
|
|
3778
|
+
state.init?.push(
|
|
3779
|
+
b.stmt(
|
|
3780
|
+
b.assignment(
|
|
3781
|
+
'=',
|
|
3782
|
+
b.member(/** @type {AST.Identifier} */ (id), b.id('nodeValue')),
|
|
3783
|
+
expr,
|
|
3784
|
+
),
|
|
3785
|
+
),
|
|
3786
|
+
);
|
|
3787
|
+
} else {
|
|
3788
|
+
skipped++;
|
|
3789
|
+
state.template?.push(' ');
|
|
3790
|
+
const id = flush_node(true);
|
|
3791
|
+
state.update?.push({
|
|
3792
|
+
operation: (key) => b.stmt(b.call('_$_.set_text', id, key)),
|
|
3793
|
+
expression: expr,
|
|
3794
|
+
identity: node.expression,
|
|
3795
|
+
initial: b.literal(' '),
|
|
3796
|
+
});
|
|
3797
|
+
if (metadata?.await) {
|
|
3798
|
+
/** @type {NonNullable<TransformClientState['update']>} */ (state.update).async = true;
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3817
3801
|
} else if (node.type === 'Text') {
|
|
3818
3802
|
if (metadata?.tracking) {
|
|
3819
3803
|
skipped = 0;
|
|
@@ -1123,13 +1123,6 @@ export function convert_source_map_to_mappings(
|
|
|
1123
1123
|
mapping_data_verify_only,
|
|
1124
1124
|
);
|
|
1125
1125
|
|
|
1126
|
-
if (node.tracked) {
|
|
1127
|
-
mapping.generatedLengths[0] = mapping.generatedLengths[0] + "['#v']".length;
|
|
1128
|
-
if (node.optional) {
|
|
1129
|
-
mapping.generatedLengths[0] = mapping.generatedLengths[0] + '.?'.length;
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
1126
|
mappings.push(mapping);
|
|
1134
1127
|
}
|
|
1135
1128
|
|