ripple 0.2.199 → 0.2.201
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 +5 -4
- package/src/compiler/index.d.ts +1 -5
- package/src/compiler/phases/1-parse/index.js +145 -11
- package/src/compiler/phases/2-analyze/index.js +24 -8
- package/src/compiler/phases/2-analyze/prune.js +5 -3
- package/src/compiler/phases/3-transform/client/index.js +312 -165
- package/src/compiler/phases/3-transform/segments.js +220 -70
- package/src/compiler/phases/3-transform/server/index.js +227 -77
- package/src/compiler/source-map-utils.js +74 -10
- package/src/compiler/types/index.d.ts +63 -21
- package/src/compiler/types/parse.d.ts +3 -1
- package/src/compiler/utils.js +34 -0
- package/src/helpers.d.ts +5 -0
- package/src/runtime/index-server.js +27 -47
- package/src/runtime/internal/client/composite.js +5 -0
- package/src/runtime/internal/client/events.js +1 -9
- package/src/runtime/internal/client/for.js +6 -4
- package/src/runtime/internal/client/hydration.js +2 -2
- package/src/runtime/internal/client/index.js +1 -1
- package/src/runtime/internal/client/operations.js +4 -4
- package/src/runtime/internal/client/render.js +0 -2
- package/src/runtime/internal/client/template.js +9 -1
- package/src/runtime/internal/client/types.d.ts +18 -0
- package/src/runtime/internal/client/utils.js +1 -1
- package/src/runtime/internal/server/index.js +106 -3
- package/src/utils/builders.js +25 -5
- package/tests/client/basic/basic.attributes.test.ripple +1 -1
- package/tests/client/basic/basic.components.test.ripple +47 -0
- package/tests/client/basic/basic.rendering.test.ripple +1 -1
- package/tests/client/composite/composite.props.test.ripple +49 -4
- package/tests/client/dynamic-elements.test.ripple +44 -0
- package/tests/client/switch.test.ripple +40 -0
- package/tests/client/tsconfig.json +11 -0
- package/tests/client.d.ts +5 -22
- package/tests/common.d.ts +24 -0
- package/tests/hydration/compiled/server/basic.js +109 -24
- package/tests/hydration/compiled/server/events.js +161 -72
- package/tests/hydration/compiled/server/for.js +202 -102
- package/tests/hydration/compiled/server/if.js +130 -50
- package/tests/hydration/compiled/server/reactivity.js +51 -12
- package/tests/server/__snapshots__/compiler.test.ripple.snap +11 -4
- package/tests/server/basic.attributes.test.ripple +459 -0
- package/tests/server/basic.components.test.ripple +237 -0
- package/tests/server/basic.test.ripple +25 -0
- package/tests/server/compiler.test.ripple +2 -3
- package/tests/server/composite.props.test.ripple +161 -0
- package/tests/server/dynamic-elements.test.ripple +438 -0
- package/tests/server/head.test.ripple +102 -0
- package/tests/server/switch.test.ripple +40 -0
- package/tests/server/tsconfig.json +11 -0
- package/tests/server.d.ts +7 -0
- package/tests/setup-client.js +6 -2
- package/tests/setup-server.js +16 -0
- package/types/index.d.ts +2 -2
- package/types/server.d.ts +4 -3
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
VisitorClientContext,
|
|
9
9
|
TransformClientState,
|
|
10
10
|
ScopeInterface,
|
|
11
|
-
Visitors
|
|
11
|
+
Visitors,
|
|
12
|
+
Binding,
|
|
12
13
|
} from '#compiler';
|
|
13
14
|
@import { RippleCompileError } from 'ripple/compiler';
|
|
15
|
+
@import { RequiredPresent } from '#helpers';
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
/**
|
|
@@ -51,6 +53,7 @@ import {
|
|
|
51
53
|
build_getter,
|
|
52
54
|
determine_namespace_for_children,
|
|
53
55
|
index_to_key,
|
|
56
|
+
is_element_dynamic,
|
|
54
57
|
} from '../../../utils.js';
|
|
55
58
|
import {
|
|
56
59
|
CSS_HASH_IDENTIFIER,
|
|
@@ -68,6 +71,7 @@ import {
|
|
|
68
71
|
} from '../../../../utils/events.js';
|
|
69
72
|
import { createHash } from 'node:crypto';
|
|
70
73
|
import { should_preserve_comment, format_comment } from '../../../comment-utils.js';
|
|
74
|
+
import { set_location } from '../../../../utils/builders.js';
|
|
71
75
|
|
|
72
76
|
/**
|
|
73
77
|
*
|
|
@@ -175,8 +179,8 @@ function visit_head_element(node, context) {
|
|
|
175
179
|
* @param {TransformClientState} state
|
|
176
180
|
*/
|
|
177
181
|
function apply_updates(init, update, state) {
|
|
178
|
-
if (update
|
|
179
|
-
init
|
|
182
|
+
if (update.length === 1 && !update[0].needsPrevTracking) {
|
|
183
|
+
init.push(
|
|
180
184
|
b.stmt(
|
|
181
185
|
b.call(
|
|
182
186
|
'_$_.render',
|
|
@@ -195,18 +199,32 @@ function apply_updates(init, update, state) {
|
|
|
195
199
|
),
|
|
196
200
|
);
|
|
197
201
|
} else {
|
|
202
|
+
/** @type {AST.Property[]} */
|
|
198
203
|
const initial = [];
|
|
204
|
+
/** @type {AST.Statement[]} */
|
|
199
205
|
const render_statements = [];
|
|
200
206
|
let index = 0;
|
|
201
207
|
|
|
208
|
+
/**
|
|
209
|
+
@type {
|
|
210
|
+
Map<
|
|
211
|
+
AST.Identifier | AST.Expression,
|
|
212
|
+
RequiredPresent<
|
|
213
|
+
NonNullable<TransformClientState['update']>[number],
|
|
214
|
+
'initial' | 'identity' | 'expression'
|
|
215
|
+
>[]
|
|
216
|
+
>
|
|
217
|
+
}
|
|
218
|
+
*/
|
|
202
219
|
const grouped_updates = new Map();
|
|
203
220
|
|
|
204
221
|
for (const u of update) {
|
|
205
222
|
if (u.initial) {
|
|
206
|
-
const id =
|
|
207
|
-
u.identity
|
|
208
|
-
? state.scope.get(u.identity.name)
|
|
209
|
-
: u.identity
|
|
223
|
+
const id = /** @type {AST.Identifier | AST.Expression} */ (
|
|
224
|
+
u.identity.type === 'Identifier'
|
|
225
|
+
? /** @type {Binding} */ (state.scope.get(u.identity.name)).node
|
|
226
|
+
: u.identity
|
|
227
|
+
);
|
|
210
228
|
let updates = grouped_updates.get(id);
|
|
211
229
|
|
|
212
230
|
if (updates === undefined) {
|
|
@@ -715,7 +733,11 @@ const visitors = {
|
|
|
715
733
|
context.state.metadata.tracking = true;
|
|
716
734
|
}
|
|
717
735
|
|
|
718
|
-
if (
|
|
736
|
+
if (
|
|
737
|
+
node.tracked ||
|
|
738
|
+
((node.property.type === 'Identifier' || node.property.type === 'Literal') &&
|
|
739
|
+
node.property.tracked)
|
|
740
|
+
) {
|
|
719
741
|
if (context.state.to_ts) {
|
|
720
742
|
// In TypeScript mode, transform @user.@name or @user.@['name'] or @user?.@name
|
|
721
743
|
// to user['#v'].name['#v'] or user['#v']['name']['#v'] or user['#v']?.name['#v']
|
|
@@ -723,10 +745,22 @@ const visitors = {
|
|
|
723
745
|
const visited_property = /** @type {AST.Expression} */ (context.visit(node.property));
|
|
724
746
|
|
|
725
747
|
// Build the member access: object.property or object[property]
|
|
726
|
-
const member = b.member(
|
|
748
|
+
const member = b.member(
|
|
749
|
+
visited_object,
|
|
750
|
+
visited_property,
|
|
751
|
+
node.computed,
|
|
752
|
+
node.optional,
|
|
753
|
+
/** @type {AST.NodeWithLocation} */ (node),
|
|
754
|
+
);
|
|
727
755
|
|
|
728
756
|
// Wrap with ['#v'] access
|
|
729
|
-
return b.member(
|
|
757
|
+
return b.member(
|
|
758
|
+
member,
|
|
759
|
+
b.literal('#v'),
|
|
760
|
+
true,
|
|
761
|
+
undefined,
|
|
762
|
+
/** @type {AST.NodeWithLocation} */ (node),
|
|
763
|
+
);
|
|
730
764
|
} else {
|
|
731
765
|
if (!context.state.to_ts) {
|
|
732
766
|
return b.call(
|
|
@@ -1081,7 +1115,10 @@ const visitors = {
|
|
|
1081
1115
|
/** @type {(AST.Property | AST.SpreadElement)[] | null} */
|
|
1082
1116
|
const spread_attributes = is_spreading ? [] : null;
|
|
1083
1117
|
const child_namespace = is_dom_element
|
|
1084
|
-
? determine_namespace_for_children(
|
|
1118
|
+
? determine_namespace_for_children(
|
|
1119
|
+
/** @type {AST.Identifier} */ (node.id).name,
|
|
1120
|
+
state.namespace,
|
|
1121
|
+
)
|
|
1085
1122
|
: state.namespace;
|
|
1086
1123
|
|
|
1087
1124
|
/**
|
|
@@ -1110,37 +1147,21 @@ const visitors = {
|
|
|
1110
1147
|
};
|
|
1111
1148
|
|
|
1112
1149
|
if (is_dom_element) {
|
|
1150
|
+
/** @type {AST.Attribute | null} */
|
|
1113
1151
|
let class_attribute = null;
|
|
1152
|
+
/** @type {AST.Attribute | null} */
|
|
1114
1153
|
let style_attribute = null;
|
|
1115
|
-
const component = /** @type {AST.Component} */ (state.component);
|
|
1116
1154
|
/** @type {TransformClientState['update']} */
|
|
1117
1155
|
const local_updates = [];
|
|
1118
|
-
const is_void = is_void_element(node.id.name);
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
for (let i = context.path.length - 1; i >= 0; i--) {
|
|
1126
|
-
const anc = context.path[i];
|
|
1127
|
-
if (anc && anc.type === 'Component' && anc.metadata && anc.metadata.inherited_css) {
|
|
1128
|
-
inside_dynamic_children = true;
|
|
1129
|
-
break;
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
if (inside_dynamic_children) {
|
|
1133
|
-
for (let i = context.path.length - 1; i >= 0; i--) {
|
|
1134
|
-
const anc = context.path[i];
|
|
1135
|
-
if (anc && anc.type === 'Component' && anc.css) {
|
|
1136
|
-
scoping_hash = anc.css.hash;
|
|
1137
|
-
break;
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1156
|
+
const is_void = is_void_element(/** @type {AST.Identifier} */ (node.id).name);
|
|
1157
|
+
/** @type {AST.CSS.StyleSheet['hash'] | null} */
|
|
1158
|
+
const scoping_hash =
|
|
1159
|
+
state.applyParentCssScope ??
|
|
1160
|
+
(node.metadata.scoped && state.component?.css
|
|
1161
|
+
? /** @type {AST.CSS.StyleSheet} */ (state.component?.css).hash
|
|
1162
|
+
: null);
|
|
1142
1163
|
|
|
1143
|
-
state.template?.push(`<${node.id.name}`);
|
|
1164
|
+
state.template?.push(`<${/** @type {AST.Identifier} */ (node.id).name}`);
|
|
1144
1165
|
|
|
1145
1166
|
for (const attr of node.attributes) {
|
|
1146
1167
|
if (attr.type === 'Attribute') {
|
|
@@ -1353,7 +1374,9 @@ const visitors = {
|
|
|
1353
1374
|
);
|
|
1354
1375
|
|
|
1355
1376
|
const hash_arg = scoping_hash ? b.literal(scoping_hash) : undefined;
|
|
1356
|
-
const is_html =
|
|
1377
|
+
const is_html =
|
|
1378
|
+
context.state.namespace === 'html' &&
|
|
1379
|
+
/** @type {AST.Identifier} */ (node.id).name !== 'svg';
|
|
1357
1380
|
|
|
1358
1381
|
if (metadata.tracking) {
|
|
1359
1382
|
local_updates.push({
|
|
@@ -1430,7 +1453,7 @@ const visitors = {
|
|
|
1430
1453
|
root: false,
|
|
1431
1454
|
}),
|
|
1432
1455
|
);
|
|
1433
|
-
state.template?.push(`</${node.id.name}>`);
|
|
1456
|
+
state.template?.push(`</${/** @type {AST.Identifier} */ (node.id).name}>`);
|
|
1434
1457
|
|
|
1435
1458
|
// We need to check if any child nodes are dynamic to determine
|
|
1436
1459
|
// if we need to pop the hydration stack to the parent node
|
|
@@ -1472,6 +1495,12 @@ const visitors = {
|
|
|
1472
1495
|
|
|
1473
1496
|
state.template?.push('<!>');
|
|
1474
1497
|
|
|
1498
|
+
if (state.applyParentCssScope) {
|
|
1499
|
+
// We're inside a component, don't continue applying css hash to class
|
|
1500
|
+
state.applyParentCssScope = undefined;
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
const is_dynamic_element = is_element_dynamic(node);
|
|
1475
1504
|
const is_spreading = node.attributes.some((attr) => attr.type === 'SpreadAttribute');
|
|
1476
1505
|
/** @type {(AST.Property | AST.SpreadElement)[]} */
|
|
1477
1506
|
const props = [];
|
|
@@ -1487,7 +1516,7 @@ const visitors = {
|
|
|
1487
1516
|
? b.literal(true)
|
|
1488
1517
|
: /** @type {AST.Expression} */ (visit(attr.value, { ...state, metadata }));
|
|
1489
1518
|
|
|
1490
|
-
if (attr.name.name === 'class' && node.metadata
|
|
1519
|
+
if (attr.name.name === 'class' && node.metadata.scoped && state.component?.css) {
|
|
1491
1520
|
if (property.type === 'Literal') {
|
|
1492
1521
|
property = b.literal(`${state.component.css.hash} ${property.value}`);
|
|
1493
1522
|
} else {
|
|
@@ -1543,7 +1572,7 @@ const visitors = {
|
|
|
1543
1572
|
}
|
|
1544
1573
|
}
|
|
1545
1574
|
|
|
1546
|
-
if (node.metadata
|
|
1575
|
+
if (node.metadata.scoped && state.component?.css) {
|
|
1547
1576
|
const hasClassAttr = node.attributes.some(
|
|
1548
1577
|
(attr) =>
|
|
1549
1578
|
attr.type === 'Attribute' &&
|
|
@@ -1579,17 +1608,19 @@ const visitors = {
|
|
|
1579
1608
|
}
|
|
1580
1609
|
|
|
1581
1610
|
if (children_filtered.length > 0) {
|
|
1582
|
-
const component_scope =
|
|
1611
|
+
const component_scope = state.scopes.get(node);
|
|
1583
1612
|
const children_component = b.component(b.id('children'), [], children_filtered);
|
|
1584
1613
|
|
|
1585
|
-
children_component.metadata = {
|
|
1586
|
-
...(children_component.metadata || {}),
|
|
1587
|
-
inherited_css: true,
|
|
1588
|
-
};
|
|
1589
|
-
|
|
1590
1614
|
const children = /** @type {AST.Expression} */ (
|
|
1591
1615
|
visit(children_component, {
|
|
1592
|
-
...
|
|
1616
|
+
...state,
|
|
1617
|
+
...(state.applyParentCssScope ||
|
|
1618
|
+
(is_dynamic_element && node.metadata.scoped && state.component?.css)
|
|
1619
|
+
? {
|
|
1620
|
+
applyParentCssScope: /** @type {AST.CSS.StyleSheet} */ (state.component?.css)
|
|
1621
|
+
.hash,
|
|
1622
|
+
}
|
|
1623
|
+
: {}),
|
|
1593
1624
|
scope: /** @type {ScopeInterface} */ (component_scope),
|
|
1594
1625
|
namespace: child_namespace,
|
|
1595
1626
|
})
|
|
@@ -1721,13 +1752,6 @@ const visitors = {
|
|
|
1721
1752
|
}),
|
|
1722
1753
|
];
|
|
1723
1754
|
|
|
1724
|
-
/** @type {AST.NodeWithLocation} */
|
|
1725
|
-
const loc_node = {
|
|
1726
|
-
start: /** @type {AST.NodeWithLocation } */ (node).start,
|
|
1727
|
-
end: /** @type {AST.NodeWithLocation } */ (node).end,
|
|
1728
|
-
loc: /** @type {AST.SourceLocation} */ (node.loc),
|
|
1729
|
-
};
|
|
1730
|
-
|
|
1731
1755
|
const func = b.function(
|
|
1732
1756
|
node.id,
|
|
1733
1757
|
node.params.map(
|
|
@@ -1736,14 +1760,22 @@ const visitors = {
|
|
|
1736
1760
|
),
|
|
1737
1761
|
b.block([...style_statements, ...body_statements]),
|
|
1738
1762
|
false,
|
|
1739
|
-
|
|
1763
|
+
/** @type {AST.NodeWithLocation} */ (node),
|
|
1740
1764
|
);
|
|
1741
1765
|
// Mark that this function was originally a component
|
|
1742
1766
|
func.metadata = /** @type {AST.FunctionExpression['metadata']} */ ({
|
|
1743
|
-
...
|
|
1744
|
-
|
|
1767
|
+
...node.metadata,
|
|
1768
|
+
is_component: true,
|
|
1745
1769
|
});
|
|
1746
1770
|
|
|
1771
|
+
if (func.id) {
|
|
1772
|
+
// metadata should be there as func.id === node.id
|
|
1773
|
+
func.id.metadata = /** @type {AST.Identifier['metadata']} */ ({
|
|
1774
|
+
...func.id.metadata,
|
|
1775
|
+
is_component: true,
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1747
1779
|
return func;
|
|
1748
1780
|
}
|
|
1749
1781
|
|
|
@@ -1760,11 +1792,18 @@ const visitors = {
|
|
|
1760
1792
|
}
|
|
1761
1793
|
}
|
|
1762
1794
|
|
|
1795
|
+
const component_scope = context.state.scopes.get(node) || context.state.scope;
|
|
1763
1796
|
const body_statements = [
|
|
1764
1797
|
b.stmt(b.call('_$_.push_component')),
|
|
1765
1798
|
...transform_body(node.body, {
|
|
1766
1799
|
...context,
|
|
1767
|
-
state: {
|
|
1800
|
+
state: {
|
|
1801
|
+
...context.state,
|
|
1802
|
+
flush_node: null,
|
|
1803
|
+
component: node,
|
|
1804
|
+
metadata,
|
|
1805
|
+
scope: component_scope,
|
|
1806
|
+
},
|
|
1768
1807
|
}),
|
|
1769
1808
|
b.stmt(b.call('_$_.pop_component')),
|
|
1770
1809
|
];
|
|
@@ -1786,12 +1825,7 @@ const visitors = {
|
|
|
1786
1825
|
: body_statements),
|
|
1787
1826
|
]),
|
|
1788
1827
|
);
|
|
1789
|
-
|
|
1790
|
-
func.metadata = /** @type {AST.FunctionExpression['metadata']} */ ({
|
|
1791
|
-
...func.metadata,
|
|
1792
|
-
was_component: true,
|
|
1793
|
-
});
|
|
1794
|
-
func.loc = node.loc; // Copy source location for Volar mappings
|
|
1828
|
+
|
|
1795
1829
|
return func;
|
|
1796
1830
|
},
|
|
1797
1831
|
|
|
@@ -1945,7 +1979,12 @@ const visitors = {
|
|
|
1945
1979
|
b.block(
|
|
1946
1980
|
transform_body(/** @type {AST.BlockStatement} */ (node.body).body, {
|
|
1947
1981
|
...context,
|
|
1948
|
-
state: {
|
|
1982
|
+
state: {
|
|
1983
|
+
...context.state,
|
|
1984
|
+
scope: body_scope,
|
|
1985
|
+
namespace: context.state.namespace,
|
|
1986
|
+
flush_node: null,
|
|
1987
|
+
},
|
|
1949
1988
|
}),
|
|
1950
1989
|
),
|
|
1951
1990
|
),
|
|
@@ -1986,7 +2025,7 @@ const visitors = {
|
|
|
1986
2025
|
|
|
1987
2026
|
const block = transform_body(consequent, {
|
|
1988
2027
|
...context,
|
|
1989
|
-
state: { ...context.state, scope: consequent_scope },
|
|
2028
|
+
state: { ...context.state, scope: consequent_scope, flush_node: null },
|
|
1990
2029
|
});
|
|
1991
2030
|
const has_break = consequent.some((stmt) => stmt.type === 'BreakStatement');
|
|
1992
2031
|
const is_last = counter === node.cases.length - 1;
|
|
@@ -2057,7 +2096,7 @@ const visitors = {
|
|
|
2057
2096
|
const consequent = b.block(
|
|
2058
2097
|
transform_body(consequent_body, {
|
|
2059
2098
|
...context,
|
|
2060
|
-
state: { ...context.state, scope: consequent_scope },
|
|
2099
|
+
state: { ...context.state, flush_node: null, scope: consequent_scope },
|
|
2061
2100
|
}),
|
|
2062
2101
|
);
|
|
2063
2102
|
const consequent_id = context.state.scope.generate('consequent');
|
|
@@ -2074,7 +2113,7 @@ const visitors = {
|
|
|
2074
2113
|
const alternate_block = b.block(
|
|
2075
2114
|
transform_body(alternate_body, {
|
|
2076
2115
|
...context,
|
|
2077
|
-
state: { ...context.state, scope: alternate_scope },
|
|
2116
|
+
state: { ...context.state, flush_node: null, scope: alternate_scope },
|
|
2078
2117
|
}),
|
|
2079
2118
|
);
|
|
2080
2119
|
alternate_id = context.state.scope.generate('alternate');
|
|
@@ -2499,7 +2538,7 @@ function transform_ts_child(node, context) {
|
|
|
2499
2538
|
const is_dom_element = is_element_dom_element(node);
|
|
2500
2539
|
const component_scope = /** @type {ScopeInterface} */ (context.state.scopes.get(node));
|
|
2501
2540
|
const thunk =
|
|
2502
|
-
node.id.name === 'style'
|
|
2541
|
+
/** @type {AST.Identifier} */ (node.id).name === 'style'
|
|
2503
2542
|
? null
|
|
2504
2543
|
: b.thunk(
|
|
2505
2544
|
b.block(
|
|
@@ -2508,7 +2547,10 @@ function transform_ts_child(node, context) {
|
|
|
2508
2547
|
state: {
|
|
2509
2548
|
...state,
|
|
2510
2549
|
scope: component_scope,
|
|
2511
|
-
inside_head:
|
|
2550
|
+
inside_head:
|
|
2551
|
+
/** @type {AST.Identifier} */ (node.id).name === 'head'
|
|
2552
|
+
? true
|
|
2553
|
+
: state.inside_head,
|
|
2512
2554
|
},
|
|
2513
2555
|
}),
|
|
2514
2556
|
),
|
|
@@ -2541,6 +2583,20 @@ function transform_ts_child(node, context) {
|
|
|
2541
2583
|
}
|
|
2542
2584
|
}
|
|
2543
2585
|
|
|
2586
|
+
if (node.id.type === 'MemberExpression') {
|
|
2587
|
+
const member = /** @type {AST.MemberExpression} */ (visit(node.id, { ...state }));
|
|
2588
|
+
|
|
2589
|
+
node.id = member;
|
|
2590
|
+
/** @type {ESTreeJSX.RippleJSXOpeningElement} */ (node.openingElement).name = member;
|
|
2591
|
+
if (node.closingElement) {
|
|
2592
|
+
/** @type {ESTreeJSX.RippleJSXClosingElement} */ (node.closingElement).name = set_location(
|
|
2593
|
+
{ ...member },
|
|
2594
|
+
/** @type {AST.NodeWithLocation} */ (node.closingElement.name),
|
|
2595
|
+
true,
|
|
2596
|
+
);
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2544
2600
|
/** @type {ESTreeJSX.JSXElement} */
|
|
2545
2601
|
const jsxElement = b.jsx_element(node, attributes, children);
|
|
2546
2602
|
|
|
@@ -2796,7 +2852,7 @@ function transform_children(children, context) {
|
|
|
2796
2852
|
const get_id = (node) => {
|
|
2797
2853
|
return b.id(
|
|
2798
2854
|
node.type == 'Element' && is_element_dom_element(node)
|
|
2799
|
-
? state.scope.generate(node.id.name)
|
|
2855
|
+
? state.scope.generate(/** @type {AST.Identifier} */ (node.id).name)
|
|
2800
2856
|
: node.type == 'Text'
|
|
2801
2857
|
? state.scope.generate('text')
|
|
2802
2858
|
: state.scope.generate('node'),
|
|
@@ -2837,15 +2893,15 @@ function transform_children(children, context) {
|
|
|
2837
2893
|
let metadata;
|
|
2838
2894
|
/** @type {AST.Expression | undefined} */
|
|
2839
2895
|
let expression = undefined;
|
|
2840
|
-
let
|
|
2896
|
+
let is_create_text_only = false;
|
|
2841
2897
|
if (node.type === 'Text' || node.type === 'Html') {
|
|
2842
2898
|
metadata = { tracking: false, await: false };
|
|
2843
2899
|
expression = /** @type {AST.Expression} */ (visit(node.expression, { ...state, metadata }));
|
|
2844
|
-
|
|
2900
|
+
is_create_text_only =
|
|
2845
2901
|
node.type === 'Text' && normalized.length === 1 && expression.type === 'Literal';
|
|
2846
2902
|
}
|
|
2847
2903
|
|
|
2848
|
-
if (initial === null && root && !
|
|
2904
|
+
if (initial === null && root && !is_create_text_only) {
|
|
2849
2905
|
create_initial(node);
|
|
2850
2906
|
}
|
|
2851
2907
|
|
|
@@ -2882,7 +2938,7 @@ function transform_children(children, context) {
|
|
|
2882
2938
|
cached = id;
|
|
2883
2939
|
return id;
|
|
2884
2940
|
} else {
|
|
2885
|
-
|
|
2941
|
+
return get_id(node);
|
|
2886
2942
|
}
|
|
2887
2943
|
};
|
|
2888
2944
|
|
|
@@ -2941,9 +2997,7 @@ function transform_children(children, context) {
|
|
|
2941
2997
|
state.template?.push(escape_html(expr.value));
|
|
2942
2998
|
} else {
|
|
2943
2999
|
const id = flush_node(true);
|
|
2944
|
-
state.init?.push(
|
|
2945
|
-
b.var(/** @type {AST.Identifier} */ (id), b.call('_$_.create_text', expr)),
|
|
2946
|
-
);
|
|
3000
|
+
state.init?.push(b.var(/** @type {AST.Identifier} */ (id), b.call('_$_.text', expr)));
|
|
2947
3001
|
state.final?.push(b.stmt(b.call('_$_.append', b.id('__anchor'), id)));
|
|
2948
3002
|
}
|
|
2949
3003
|
} else {
|
|
@@ -3095,7 +3149,7 @@ function transform_body(body, { visit, state }) {
|
|
|
3095
3149
|
}
|
|
3096
3150
|
|
|
3097
3151
|
// NOTE: transform_children in `to_ts` mode does NOT add to body_state.update
|
|
3098
|
-
// So, we skip adding
|
|
3152
|
+
// So, we skip adding any actions with body_state.update
|
|
3099
3153
|
}
|
|
3100
3154
|
|
|
3101
3155
|
return [
|
|
@@ -3160,30 +3214,23 @@ function create_tsx_with_typescript_support(comments) {
|
|
|
3160
3214
|
* @param {TransformClientContext} context
|
|
3161
3215
|
*/
|
|
3162
3216
|
const handle_function = (node, context) => {
|
|
3163
|
-
let is_method = false;
|
|
3164
|
-
const parent = node.metadata.path.at(-1);
|
|
3165
|
-
if (
|
|
3166
|
-
node.type === 'FunctionExpression' &&
|
|
3167
|
-
parent &&
|
|
3168
|
-
((parent.type === 'Property' && parent.method === true) || parent.type === 'MethodDefinition')
|
|
3169
|
-
) {
|
|
3170
|
-
is_method = true;
|
|
3171
|
-
}
|
|
3172
3217
|
const loc = /** @type {AST.SourceLocation} */ (node.loc);
|
|
3218
|
+
const start_pos = /** @type {AST.Position} */ ({
|
|
3219
|
+
line: loc.start.line,
|
|
3220
|
+
column: loc.start.column,
|
|
3221
|
+
});
|
|
3173
3222
|
|
|
3174
3223
|
if (node.async) {
|
|
3175
3224
|
context.location(loc.start.line, loc.start.column);
|
|
3176
3225
|
context.write('async ');
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
context.write('function');
|
|
3180
|
-
}
|
|
3181
|
-
} else {
|
|
3182
|
-
if (!is_method) {
|
|
3183
|
-
context.write('function', node);
|
|
3184
|
-
}
|
|
3226
|
+
context.location(loc.start.line, loc.start.column + 'async '.length);
|
|
3227
|
+
start_pos.column += 'async '.length;
|
|
3185
3228
|
}
|
|
3186
3229
|
|
|
3230
|
+
context.location(start_pos.line, start_pos.column);
|
|
3231
|
+
context.write('function');
|
|
3232
|
+
context.location(start_pos.line, start_pos.column + 'function'.length);
|
|
3233
|
+
|
|
3187
3234
|
if (node.generator) {
|
|
3188
3235
|
context.write('*');
|
|
3189
3236
|
}
|
|
@@ -3244,6 +3291,46 @@ function create_tsx_with_typescript_support(comments) {
|
|
|
3244
3291
|
base_tsx.ExpressionStatement?.(node, context);
|
|
3245
3292
|
context.location(loc.end.line, loc.end.column);
|
|
3246
3293
|
},
|
|
3294
|
+
UpdateExpression(node, context) {
|
|
3295
|
+
if (!node.loc) {
|
|
3296
|
+
base_tsx.UpdateExpression?.(node, context);
|
|
3297
|
+
return;
|
|
3298
|
+
}
|
|
3299
|
+
const loc = /** @type {AST.SourceLocation} */ (node.loc);
|
|
3300
|
+
context.location(loc.start.line, loc.start.column);
|
|
3301
|
+
base_tsx.UpdateExpression?.(node, context);
|
|
3302
|
+
context.location(loc.end.line, loc.end.column);
|
|
3303
|
+
},
|
|
3304
|
+
UnaryExpression(node, context) {
|
|
3305
|
+
if (!node.loc) {
|
|
3306
|
+
base_tsx.UnaryExpression?.(node, context);
|
|
3307
|
+
return;
|
|
3308
|
+
}
|
|
3309
|
+
const loc = /** @type {AST.SourceLocation} */ (node.loc);
|
|
3310
|
+
context.location(loc.start.line, loc.start.column);
|
|
3311
|
+
base_tsx.UnaryExpression?.(node, context);
|
|
3312
|
+
context.location(loc.end.line, loc.end.column);
|
|
3313
|
+
},
|
|
3314
|
+
YieldExpression(node, context) {
|
|
3315
|
+
if (!node.loc) {
|
|
3316
|
+
base_tsx.YieldExpression?.(node, context);
|
|
3317
|
+
return;
|
|
3318
|
+
}
|
|
3319
|
+
const loc = /** @type {AST.SourceLocation} */ (node.loc);
|
|
3320
|
+
context.location(loc.start.line, loc.start.column);
|
|
3321
|
+
base_tsx.YieldExpression?.(node, context);
|
|
3322
|
+
context.location(loc.end.line, loc.end.column);
|
|
3323
|
+
},
|
|
3324
|
+
CallExpression(node, context) {
|
|
3325
|
+
if (!node.loc) {
|
|
3326
|
+
base_tsx.CallExpression?.(node, context);
|
|
3327
|
+
return;
|
|
3328
|
+
}
|
|
3329
|
+
const loc = /** @type {AST.SourceLocation} */ (node.loc);
|
|
3330
|
+
context.location(loc.start.line, loc.start.column);
|
|
3331
|
+
base_tsx.CallExpression?.(node, context);
|
|
3332
|
+
context.location(loc.end.line, loc.end.column);
|
|
3333
|
+
},
|
|
3247
3334
|
Literal(node, context) {
|
|
3248
3335
|
if (!node.loc || node.raw === undefined) {
|
|
3249
3336
|
base_tsx.Literal?.(node, context);
|
|
@@ -3346,61 +3433,99 @@ function create_tsx_with_typescript_support(comments) {
|
|
|
3346
3433
|
context.location(loc.end.line, loc.end.column);
|
|
3347
3434
|
},
|
|
3348
3435
|
Property(node, context) {
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
} else if (
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3436
|
+
let start_pos = node.loc?.start;
|
|
3437
|
+
if (node.loc) {
|
|
3438
|
+
start_pos = /** @type {AST.Position} */ ({
|
|
3439
|
+
line: node.loc.start.line,
|
|
3440
|
+
column: node.loc.start.column,
|
|
3441
|
+
});
|
|
3442
|
+
}
|
|
3443
|
+
|
|
3444
|
+
const is_method = node.method || node.kind === 'get' || node.kind === 'set';
|
|
3445
|
+
|
|
3446
|
+
// Handle getters/setters
|
|
3447
|
+
if (node.kind === 'get') {
|
|
3448
|
+
context.write('get ');
|
|
3449
|
+
if (start_pos) {
|
|
3450
|
+
start_pos.column += 'get '.length;
|
|
3451
|
+
}
|
|
3452
|
+
} else if (node.kind === 'set') {
|
|
3453
|
+
if (start_pos) {
|
|
3454
|
+
start_pos.column += 'set '.length;
|
|
3455
|
+
}
|
|
3456
|
+
context.write('set ');
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3459
|
+
// Write async keyword (before *)
|
|
3460
|
+
if (is_method && /** @type {AST.FunctionExpression} */ (node.value).async) {
|
|
3461
|
+
// If not a method, async should be a part of the value e.g. { prop: async function }
|
|
3462
|
+
if (start_pos) {
|
|
3463
|
+
context.location(start_pos.line, start_pos.column);
|
|
3464
|
+
}
|
|
3465
|
+
context.write('async ');
|
|
3466
|
+
if (start_pos) {
|
|
3467
|
+
context.location(start_pos.line, start_pos.column + 'async '.length);
|
|
3468
|
+
start_pos.column += 'async '.length;
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
// Write * for generator methods
|
|
3473
|
+
if (/** @type {AST.FunctionExpression} */ (node.value).generator) {
|
|
3474
|
+
context.write('*');
|
|
3475
|
+
}
|
|
3476
|
+
|
|
3477
|
+
// Write the key
|
|
3478
|
+
if (node.computed) {
|
|
3479
|
+
if (node.key.loc) {
|
|
3480
|
+
context.location(node.key.loc.start.line, node.key.loc.start.column - 1);
|
|
3481
|
+
}
|
|
3482
|
+
context.write('[');
|
|
3483
|
+
context.visit(node.key);
|
|
3484
|
+
context.write(']');
|
|
3485
|
+
if (node.key.loc) {
|
|
3486
|
+
context.location(node.key.loc.end.line, node.key.loc.end.column + 1);
|
|
3399
3487
|
}
|
|
3400
3488
|
} else {
|
|
3401
|
-
|
|
3402
|
-
|
|
3489
|
+
if (node.shorthand) {
|
|
3490
|
+
// only visit value since key and value are the same
|
|
3491
|
+
// or the value will contain the key like in AssignmentPattern: { foo = 1 }
|
|
3492
|
+
context.visit(node.value);
|
|
3493
|
+
return;
|
|
3494
|
+
}
|
|
3495
|
+
|
|
3496
|
+
context.visit(node.key);
|
|
3403
3497
|
}
|
|
3498
|
+
|
|
3499
|
+
// Method shorthand: { foo() {} } or getters/setters - print params and body directly
|
|
3500
|
+
if (is_method) {
|
|
3501
|
+
const fn = /** @type {AST.FunctionExpression} */ (node.value);
|
|
3502
|
+
|
|
3503
|
+
fn.metadata.is_method = true;
|
|
3504
|
+
|
|
3505
|
+
// Type parameters: { foo<T>() {} }
|
|
3506
|
+
if (fn.typeParameters) {
|
|
3507
|
+
context.visit(fn.typeParameters);
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
context.write('(');
|
|
3511
|
+
for (let i = 0; i < fn.params.length; i++) {
|
|
3512
|
+
if (i > 0) context.write(', ');
|
|
3513
|
+
context.visit(fn.params[i]);
|
|
3514
|
+
}
|
|
3515
|
+
context.write(')');
|
|
3516
|
+
|
|
3517
|
+
if (fn.returnType) {
|
|
3518
|
+
context.visit(fn.returnType);
|
|
3519
|
+
}
|
|
3520
|
+
|
|
3521
|
+
context.write(' ');
|
|
3522
|
+
context.visit(fn.body);
|
|
3523
|
+
return;
|
|
3524
|
+
}
|
|
3525
|
+
|
|
3526
|
+
// Regular property: { key: value }
|
|
3527
|
+
context.write(': ');
|
|
3528
|
+
context.visit(node.value);
|
|
3404
3529
|
},
|
|
3405
3530
|
JSXOpeningElement(node, context) {
|
|
3406
3531
|
// Set location for '<'
|
|
@@ -3444,49 +3569,71 @@ function create_tsx_with_typescript_support(comments) {
|
|
|
3444
3569
|
context.location(loc.end.line, loc.end.column);
|
|
3445
3570
|
},
|
|
3446
3571
|
MethodDefinition(node, context) {
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
if (
|
|
3451
|
-
|
|
3452
|
-
|
|
3572
|
+
node.value.metadata.is_method = true;
|
|
3573
|
+
/** @type {AST.Position | undefined} */
|
|
3574
|
+
let start_pos;
|
|
3575
|
+
if (node.loc) {
|
|
3576
|
+
start_pos = /** @type {AST.Position} */ ({
|
|
3577
|
+
line: node.loc.start.line,
|
|
3578
|
+
column: node.loc.start.column,
|
|
3579
|
+
});
|
|
3453
3580
|
}
|
|
3454
3581
|
|
|
3455
|
-
// Has type parameters - we need to manually handle to ensure they're visited
|
|
3456
3582
|
// Write modifiers (static, async, etc.)
|
|
3457
3583
|
if (node.static) {
|
|
3458
3584
|
context.write('static ');
|
|
3585
|
+
if (start_pos) {
|
|
3586
|
+
start_pos.column += 'static '.length;
|
|
3587
|
+
}
|
|
3459
3588
|
}
|
|
3460
3589
|
|
|
3461
|
-
// Handle getters/setters
|
|
3462
3590
|
if (node.kind === 'get') {
|
|
3463
3591
|
context.write('get ');
|
|
3592
|
+
if (start_pos) {
|
|
3593
|
+
start_pos.column += 'get '.length;
|
|
3594
|
+
}
|
|
3464
3595
|
} else if (node.kind === 'set') {
|
|
3596
|
+
if (start_pos) {
|
|
3597
|
+
start_pos.column += 'set '.length;
|
|
3598
|
+
}
|
|
3465
3599
|
context.write('set ');
|
|
3466
3600
|
} else if (node.kind === 'constructor') {
|
|
3467
|
-
|
|
3601
|
+
// skip as it's covered by the key
|
|
3468
3602
|
}
|
|
3469
3603
|
|
|
3470
|
-
// Write
|
|
3471
|
-
if (node.value
|
|
3472
|
-
|
|
3604
|
+
// Write async keyword (before *)
|
|
3605
|
+
if (/** @type {AST.FunctionExpression} */ (node.value).async) {
|
|
3606
|
+
if (start_pos) {
|
|
3607
|
+
context.location(start_pos.line, start_pos.column);
|
|
3608
|
+
}
|
|
3609
|
+
context.write('async ');
|
|
3610
|
+
if (start_pos) {
|
|
3611
|
+
context.location(start_pos.line, start_pos.column + 'async '.length);
|
|
3612
|
+
start_pos.column += 'async '.length;
|
|
3613
|
+
}
|
|
3473
3614
|
}
|
|
3474
3615
|
|
|
3475
|
-
// Write
|
|
3476
|
-
if (node.value
|
|
3477
|
-
context.write('
|
|
3616
|
+
// Write * for generator methods
|
|
3617
|
+
if (node.value.generator) {
|
|
3618
|
+
context.write('*');
|
|
3478
3619
|
}
|
|
3479
3620
|
|
|
3480
3621
|
// Write the method key
|
|
3481
3622
|
if (node.computed) {
|
|
3623
|
+
if (node.key.loc) {
|
|
3624
|
+
context.location(node.key.loc.start.line, node.key.loc.start.column - 1);
|
|
3625
|
+
}
|
|
3482
3626
|
context.write('[');
|
|
3483
3627
|
context.visit(node.key);
|
|
3484
3628
|
context.write(']');
|
|
3629
|
+
if (node.key.loc) {
|
|
3630
|
+
context.location(node.key.loc.end.line, node.key.loc.end.column + 1);
|
|
3631
|
+
}
|
|
3485
3632
|
} else {
|
|
3486
3633
|
context.visit(node.key);
|
|
3487
3634
|
}
|
|
3488
3635
|
|
|
3489
|
-
// Visit typeParameters
|
|
3636
|
+
// Visit typeParameters
|
|
3490
3637
|
// TypeParameters can be on either the MethodDefinition or its value (FunctionExpression)
|
|
3491
3638
|
if (node.typeParameters) {
|
|
3492
3639
|
context.visit(node.typeParameters);
|