ripple 0.2.183 → 0.2.185
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 +2 -2
- package/src/compiler/phases/2-analyze/index.js +7 -2
- package/src/compiler/phases/3-transform/client/index.js +181 -131
- package/src/compiler/phases/3-transform/segments.js +93 -49
- package/src/compiler/phases/3-transform/server/index.js +135 -45
- package/src/compiler/scope.js +11 -16
- package/src/compiler/types/index.d.ts +333 -90
- package/src/compiler/types/parse.d.ts +127 -9
- package/src/runtime/index-server.js +10 -27
- package/src/runtime/internal/client/operations.js +1 -1
- package/src/runtime/internal/client/runtime.js +8 -8
- package/src/runtime/internal/client/types.d.ts +5 -5
- package/src/runtime/internal/server/index.js +268 -17
- package/src/runtime/internal/server/types.d.ts +19 -11
- package/tests/client/switch.test.ripple +73 -23
- package/tests/server/basic.test.ripple +119 -0
- package/tests/server/composite.test.ripple +1 -1
- package/tests/server/context.test.ripple +31 -0
- package/tests/server/switch.test.ripple +21 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
@import { CustomMappingData, PluginActionOverrides } from 'ripple/compiler';
|
|
3
|
+
@import { DocumentHighlightKind } from 'vscode-languageserver-types';
|
|
4
|
+
@import * as AST from 'estree';
|
|
5
|
+
@import * as ESTreeJSX from 'estree-jsx';
|
|
6
|
+
@import {MappingData, CodeMapping, VolarMappingsResult} from 'ripple/compiler';
|
|
7
|
+
@import {CodeMapping as VolarCodeMapping} from '@volar/language-core';
|
|
8
|
+
*/
|
|
3
9
|
|
|
4
10
|
/**
|
|
5
|
-
* @typedef {import('estree').Position} Position
|
|
6
|
-
* @typedef {{start: Position, end: Position}} Location
|
|
7
|
-
* @typedef {import('@volar/language-core').CodeMapping} VolarCodeMapping
|
|
8
|
-
* @typedef {import('ripple/compiler').MappingData} MappingData
|
|
9
|
-
* @typedef {import('ripple/compiler').CodeMapping} CodeMapping
|
|
10
|
-
* @typedef {import('ripple/compiler').VolarMappingsResult} VolarMappingsResult
|
|
11
11
|
* @typedef {{
|
|
12
12
|
* start: number,
|
|
13
13
|
* end: number,
|
|
@@ -61,7 +61,7 @@ function loc_to_offset(line, column, line_offsets) {
|
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Extract CSS source regions from style elements in the AST
|
|
64
|
-
* @param {
|
|
64
|
+
* @param {AST.Node} ast - The parsed AST
|
|
65
65
|
* @param {string} source - Original source code
|
|
66
66
|
* @param {number[]} source_line_offsets
|
|
67
67
|
* @returns {CssSourceRegion[]}
|
|
@@ -74,10 +74,14 @@ function extractCssSourceRegions(ast, source, source_line_offsets) {
|
|
|
74
74
|
Element(node) {
|
|
75
75
|
// Check if this is a style element with CSS content
|
|
76
76
|
if (node.id?.name === 'style' && node.css) {
|
|
77
|
-
const openLoc =
|
|
77
|
+
const openLoc = /** @type {ESTreeJSX.JSXOpeningElement & AST.NodeWithLocation} */ (
|
|
78
|
+
node.openingElement
|
|
79
|
+
).loc;
|
|
78
80
|
const cssStart = loc_to_offset(openLoc.end.line, openLoc.end.column, source_line_offsets);
|
|
79
81
|
|
|
80
|
-
const closeLoc =
|
|
82
|
+
const closeLoc = /** @type {ESTreeJSX.JSXClosingElement & AST.NodeWithLocation} */ (
|
|
83
|
+
node.closingElement
|
|
84
|
+
).loc;
|
|
81
85
|
const cssEnd = loc_to_offset(
|
|
82
86
|
closeLoc.start.line,
|
|
83
87
|
closeLoc.start.column,
|
|
@@ -102,8 +106,8 @@ function extractCssSourceRegions(ast, source, source_line_offsets) {
|
|
|
102
106
|
|
|
103
107
|
/**
|
|
104
108
|
* Create Volar mappings by walking the transformed AST
|
|
105
|
-
* @param {
|
|
106
|
-
* @param {
|
|
109
|
+
* @param {AST.Node} ast - The transformed AST
|
|
110
|
+
* @param {AST.Node} ast_from_source - The original AST from source
|
|
107
111
|
* @param {string} source - Original source code
|
|
108
112
|
* @param {string} generated_code - Generated code (returned in output, not used for searching)
|
|
109
113
|
* @param {object} esrap_source_map - Esrap source map for accurate position lookup
|
|
@@ -147,17 +151,18 @@ export function convert_source_map_to_mappings(
|
|
|
147
151
|
// All tokens must have source/generated text and loc property for accurate positioning
|
|
148
152
|
/**
|
|
149
153
|
* @type {Array<{
|
|
150
|
-
* source: string,
|
|
154
|
+
* source: string | null | undefined,
|
|
151
155
|
* generated: string,
|
|
152
156
|
* is_full_import_statement?: boolean,
|
|
153
|
-
* loc:
|
|
154
|
-
* end_loc?:
|
|
157
|
+
* loc: AST.SourceLocation,
|
|
158
|
+
* end_loc?: AST.SourceLocation,
|
|
155
159
|
* metadata?: PluginActionOverrides
|
|
156
160
|
* }>}
|
|
157
161
|
*/
|
|
158
162
|
const tokens = [];
|
|
159
163
|
|
|
160
164
|
// We have to visit everything in generated order to maintain correct indices
|
|
165
|
+
|
|
161
166
|
walk(ast, null, {
|
|
162
167
|
_(node, { visit }) {
|
|
163
168
|
// Collect key node types: Identifiers, Literals, and JSX Elements
|
|
@@ -231,7 +236,11 @@ export function convert_source_map_to_mappings(
|
|
|
231
236
|
} else if (node.type === 'ImportSpecifier') {
|
|
232
237
|
// If local and imported are the same, only visit local to avoid duplicates
|
|
233
238
|
// Otherwise visit both in order
|
|
234
|
-
if (
|
|
239
|
+
if (
|
|
240
|
+
node.imported &&
|
|
241
|
+
node.local &&
|
|
242
|
+
/** @type {AST.Identifier} */ (node.imported).name !== node.local.name
|
|
243
|
+
) {
|
|
235
244
|
visit(node.imported);
|
|
236
245
|
visit(node.local);
|
|
237
246
|
} else if (node.local) {
|
|
@@ -250,7 +259,12 @@ export function convert_source_map_to_mappings(
|
|
|
250
259
|
} else if (node.type === 'ExportSpecifier') {
|
|
251
260
|
// If local and exported are the same, only visit local to avoid duplicates
|
|
252
261
|
// Otherwise visit both in order
|
|
253
|
-
if (
|
|
262
|
+
if (
|
|
263
|
+
node.local &&
|
|
264
|
+
node.exported &&
|
|
265
|
+
/** @type {AST.Identifier} */ (node.local).name !==
|
|
266
|
+
/** @type {AST.Identifier} */ (node.exported).name
|
|
267
|
+
) {
|
|
254
268
|
visit(node.local);
|
|
255
269
|
visit(node.exported);
|
|
256
270
|
} else if (node.local) {
|
|
@@ -271,7 +285,7 @@ export function convert_source_map_to_mappings(
|
|
|
271
285
|
} else if (node.type === 'ExportDefaultDeclaration') {
|
|
272
286
|
// Visit the declaration
|
|
273
287
|
if (node.declaration) {
|
|
274
|
-
visit(node.declaration);
|
|
288
|
+
visit(/** @type {AST.Node} */ (node.declaration));
|
|
275
289
|
}
|
|
276
290
|
return;
|
|
277
291
|
} else if (node.type === 'ExportAllDeclaration') {
|
|
@@ -357,7 +371,7 @@ export function convert_source_map_to_mappings(
|
|
|
357
371
|
// 2. Visit children in order
|
|
358
372
|
if (node.children) {
|
|
359
373
|
for (const child of node.children) {
|
|
360
|
-
visit(child);
|
|
374
|
+
visit(/** @type {AST.Node} */ (child));
|
|
361
375
|
}
|
|
362
376
|
}
|
|
363
377
|
|
|
@@ -366,7 +380,9 @@ export function convert_source_map_to_mappings(
|
|
|
366
380
|
!node.openingElement?.selfClosing &&
|
|
367
381
|
node.closingElement?.name?.type === 'JSXIdentifier'
|
|
368
382
|
) {
|
|
369
|
-
const closingNameNode =
|
|
383
|
+
const closingNameNode = /** @type {ESTreeJSX.JSXIdentifier & AST.NodeWithLocation} */ (
|
|
384
|
+
node.closingElement.name
|
|
385
|
+
);
|
|
370
386
|
if (closingNameNode.metadata?.is_capitalized) {
|
|
371
387
|
tokens.push({
|
|
372
388
|
source: closingNameNode.metadata.original_name,
|
|
@@ -390,24 +406,25 @@ export function convert_source_map_to_mappings(
|
|
|
390
406
|
) {
|
|
391
407
|
// Add function/component keyword token
|
|
392
408
|
if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') {
|
|
409
|
+
const node_fn = /** @type (typeof node) & AST.NodeWithLocation */ (node);
|
|
393
410
|
const source_keyword = node.metadata?.was_component ? 'component' : 'function';
|
|
394
411
|
// Add token for the keyword - esrap already mapped it via context.write('function', node)
|
|
395
412
|
tokens.push({
|
|
396
413
|
source: source_keyword,
|
|
397
414
|
generated: 'function',
|
|
398
415
|
loc: {
|
|
399
|
-
start: { line:
|
|
416
|
+
start: { line: node_fn.loc.start.line, column: node_fn.loc.start.column },
|
|
400
417
|
end: {
|
|
401
|
-
line:
|
|
402
|
-
column:
|
|
418
|
+
line: node_fn.loc.start.line,
|
|
419
|
+
column: node_fn.loc.start.column + source_keyword.length,
|
|
403
420
|
},
|
|
404
421
|
},
|
|
405
422
|
});
|
|
406
423
|
}
|
|
407
424
|
|
|
408
425
|
// Visit in source order: id, params, body
|
|
409
|
-
if (node.id) {
|
|
410
|
-
visit(node.id);
|
|
426
|
+
if (/** @type {AST.FunctionDeclaration | AST.FunctionExpression} */ (node).id) {
|
|
427
|
+
visit(/** @type {AST.FunctionDeclaration | AST.FunctionExpression} */ (node).id);
|
|
411
428
|
}
|
|
412
429
|
if (node.params) {
|
|
413
430
|
for (const param of node.params) {
|
|
@@ -478,8 +495,8 @@ export function convert_source_map_to_mappings(
|
|
|
478
495
|
visit(node.right);
|
|
479
496
|
}
|
|
480
497
|
// Ripple-specific: index variable
|
|
481
|
-
if (node.index) {
|
|
482
|
-
visit(node.index);
|
|
498
|
+
if (/** @type {AST.ForOfStatement} */ (node).index) {
|
|
499
|
+
visit(/** @type {AST.ForOfStatement} */ (node).index);
|
|
483
500
|
}
|
|
484
501
|
if (node.body) {
|
|
485
502
|
visit(node.body);
|
|
@@ -511,14 +528,17 @@ export function convert_source_map_to_mappings(
|
|
|
511
528
|
if (node.pending) {
|
|
512
529
|
// Add a special token for the 'pending' keyword with customData
|
|
513
530
|
// to suppress TypeScript diagnostics and provide custom hover/definition
|
|
531
|
+
const pending = /** @type {(typeof node.pending) & AST.NodeWithLocation} */ (
|
|
532
|
+
node.pending
|
|
533
|
+
);
|
|
514
534
|
const pendingKeywordLoc = {
|
|
515
535
|
start: {
|
|
516
|
-
line:
|
|
517
|
-
column:
|
|
536
|
+
line: pending.loc.start.line,
|
|
537
|
+
column: pending.loc.start.column - 'pending '.length,
|
|
518
538
|
},
|
|
519
539
|
end: {
|
|
520
|
-
line:
|
|
521
|
-
column:
|
|
540
|
+
line: pending.loc.start.line,
|
|
541
|
+
column: pending.loc.start.column - 1,
|
|
522
542
|
},
|
|
523
543
|
};
|
|
524
544
|
tokens.push({
|
|
@@ -764,8 +784,8 @@ export function convert_source_map_to_mappings(
|
|
|
764
784
|
if (node.argument) {
|
|
765
785
|
visit(node.argument);
|
|
766
786
|
// Visit type annotation if present (for RestElement)
|
|
767
|
-
if (node.argument.typeAnnotation) {
|
|
768
|
-
visit(node.argument.typeAnnotation);
|
|
787
|
+
if (/** @type {AST.Pattern} */ (node.argument).typeAnnotation) {
|
|
788
|
+
visit(/** @type {AST.Pattern} */ (node.argument).typeAnnotation);
|
|
769
789
|
}
|
|
770
790
|
}
|
|
771
791
|
// RestElement itself can have typeAnnotation
|
|
@@ -828,7 +848,7 @@ export function convert_source_map_to_mappings(
|
|
|
828
848
|
// Visit children in order
|
|
829
849
|
if (node.children) {
|
|
830
850
|
for (const child of node.children) {
|
|
831
|
-
visit(child);
|
|
851
|
+
visit(/** @type {AST.Node} */ (child));
|
|
832
852
|
}
|
|
833
853
|
}
|
|
834
854
|
return;
|
|
@@ -956,10 +976,11 @@ export function convert_source_map_to_mappings(
|
|
|
956
976
|
if (node.typeName) {
|
|
957
977
|
visit(node.typeName);
|
|
958
978
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
979
|
+
|
|
980
|
+
// typeParameters and typeArguments (different parsers use different names)
|
|
981
|
+
// tsTypeParameters is a bug in the estree-typescript
|
|
982
|
+
// but we fixed in the analyzer to typeArguments.
|
|
983
|
+
|
|
963
984
|
if (node.typeArguments) {
|
|
964
985
|
visit(node.typeArguments);
|
|
965
986
|
}
|
|
@@ -1004,8 +1025,13 @@ export function convert_source_map_to_mappings(
|
|
|
1004
1025
|
for (const param of node.parameters) {
|
|
1005
1026
|
visit(param);
|
|
1006
1027
|
// Visit type annotation on the parameter
|
|
1007
|
-
if (
|
|
1008
|
-
|
|
1028
|
+
if (
|
|
1029
|
+
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
|
|
1030
|
+
) {
|
|
1031
|
+
visit(
|
|
1032
|
+
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
|
|
1033
|
+
.typeAnnotation,
|
|
1034
|
+
);
|
|
1009
1035
|
}
|
|
1010
1036
|
}
|
|
1011
1037
|
}
|
|
@@ -1042,8 +1068,13 @@ export function convert_source_map_to_mappings(
|
|
|
1042
1068
|
for (const param of node.parameters) {
|
|
1043
1069
|
visit(param);
|
|
1044
1070
|
// Visit type annotation on the parameter
|
|
1045
|
-
if (
|
|
1046
|
-
|
|
1071
|
+
if (
|
|
1072
|
+
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
|
|
1073
|
+
) {
|
|
1074
|
+
visit(
|
|
1075
|
+
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
|
|
1076
|
+
.typeAnnotation,
|
|
1077
|
+
);
|
|
1047
1078
|
}
|
|
1048
1079
|
}
|
|
1049
1080
|
}
|
|
@@ -1057,8 +1088,13 @@ export function convert_source_map_to_mappings(
|
|
|
1057
1088
|
for (const param of node.parameters) {
|
|
1058
1089
|
visit(param);
|
|
1059
1090
|
// Visit type annotation on the parameter
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1091
|
+
if (
|
|
1092
|
+
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
|
|
1093
|
+
) {
|
|
1094
|
+
visit(
|
|
1095
|
+
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
|
|
1096
|
+
.typeAnnotation,
|
|
1097
|
+
);
|
|
1062
1098
|
}
|
|
1063
1099
|
}
|
|
1064
1100
|
}
|
|
@@ -1078,8 +1114,13 @@ export function convert_source_map_to_mappings(
|
|
|
1078
1114
|
for (const param of node.parameters) {
|
|
1079
1115
|
visit(param);
|
|
1080
1116
|
// Visit type annotation on the parameter
|
|
1081
|
-
if (
|
|
1082
|
-
|
|
1117
|
+
if (
|
|
1118
|
+
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
|
|
1119
|
+
) {
|
|
1120
|
+
visit(
|
|
1121
|
+
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
|
|
1122
|
+
.typeAnnotation,
|
|
1123
|
+
);
|
|
1083
1124
|
}
|
|
1084
1125
|
}
|
|
1085
1126
|
}
|
|
@@ -1170,6 +1211,9 @@ export function convert_source_map_to_mappings(
|
|
|
1170
1211
|
if (node.exprName) {
|
|
1171
1212
|
visit(node.exprName);
|
|
1172
1213
|
}
|
|
1214
|
+
if (node.typeArguments) {
|
|
1215
|
+
visit(node.typeArguments);
|
|
1216
|
+
}
|
|
1173
1217
|
return;
|
|
1174
1218
|
} else if (node.type === 'TSInterfaceDeclaration') {
|
|
1175
1219
|
// Interface declaration
|
|
@@ -1327,7 +1371,7 @@ export function convert_source_map_to_mappings(
|
|
|
1327
1371
|
});
|
|
1328
1372
|
|
|
1329
1373
|
for (const token of tokens) {
|
|
1330
|
-
const source_text = token.source;
|
|
1374
|
+
const source_text = token.source ?? '';
|
|
1331
1375
|
const gen_text = token.generated;
|
|
1332
1376
|
|
|
1333
1377
|
const source_start = loc_to_offset(
|
|
@@ -1344,7 +1388,7 @@ export function convert_source_map_to_mappings(
|
|
|
1344
1388
|
let gen_start;
|
|
1345
1389
|
|
|
1346
1390
|
if (token.is_full_import_statement) {
|
|
1347
|
-
const end_loc = /** @type {
|
|
1391
|
+
const end_loc = /** @type {AST.SourceLocation} */ (token.end_loc).end;
|
|
1348
1392
|
const source_end = loc_to_offset(end_loc.line, end_loc.column, source_line_offsets);
|
|
1349
1393
|
|
|
1350
1394
|
// Look up where import keyword and source literal map to in generated code
|
|
@@ -16,6 +16,7 @@ import { walk } from 'zimmerframe';
|
|
|
16
16
|
import ts from 'esrap/languages/ts';
|
|
17
17
|
import path from 'node:path';
|
|
18
18
|
import { print } from 'esrap';
|
|
19
|
+
import is_reference from 'is-reference';
|
|
19
20
|
import {
|
|
20
21
|
determine_namespace_for_children,
|
|
21
22
|
escape_html,
|
|
@@ -30,17 +31,6 @@ import { is_event_attribute } from '../../../../utils/events.js';
|
|
|
30
31
|
import { render_stylesheets } from '../stylesheet.js';
|
|
31
32
|
import { createHash } from 'node:crypto';
|
|
32
33
|
|
|
33
|
-
/**
|
|
34
|
-
* @param {TransformServerContext} context
|
|
35
|
-
*/
|
|
36
|
-
function add_ripple_internal_import(context) {
|
|
37
|
-
if (!context.state.to_ts) {
|
|
38
|
-
if (!context.state.imports.has(`import * as _$_ from 'ripple/internal/server'`)) {
|
|
39
|
-
context.state.imports.add(`import * as _$_ from 'ripple/internal/server'`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
34
|
/**
|
|
45
35
|
* @param {AST.Node[]} children
|
|
46
36
|
* @param {TransformServerContext} context
|
|
@@ -110,8 +100,31 @@ const visitors = {
|
|
|
110
100
|
}
|
|
111
101
|
},
|
|
112
102
|
|
|
103
|
+
Identifier(node, context) {
|
|
104
|
+
const parent = /** @type {AST.Node} */ (context.path.at(-1));
|
|
105
|
+
|
|
106
|
+
if (is_reference(node, parent) && node.tracked) {
|
|
107
|
+
const is_right_side_of_assignment =
|
|
108
|
+
parent.type === 'AssignmentExpression' && parent.right === node;
|
|
109
|
+
if (
|
|
110
|
+
(parent.type !== 'AssignmentExpression' && parent.type !== 'UpdateExpression') ||
|
|
111
|
+
is_right_side_of_assignment
|
|
112
|
+
) {
|
|
113
|
+
return b.call('_$_.get', node);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
113
118
|
Component(node, context) {
|
|
114
|
-
|
|
119
|
+
if (node.params.length > 0) {
|
|
120
|
+
let props_param = node.params[0];
|
|
121
|
+
|
|
122
|
+
if (props_param.type === 'Identifier') {
|
|
123
|
+
delete props_param.typeAnnotation;
|
|
124
|
+
} else if (props_param.type === 'ObjectPattern') {
|
|
125
|
+
delete props_param.typeAnnotation;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
115
128
|
|
|
116
129
|
const metadata = { await: false };
|
|
117
130
|
const body_statements = [
|
|
@@ -608,23 +621,32 @@ const visitors = {
|
|
|
608
621
|
if (!is_inside_component(context)) {
|
|
609
622
|
return context.next();
|
|
610
623
|
}
|
|
624
|
+
|
|
611
625
|
const cases = [];
|
|
626
|
+
|
|
612
627
|
for (const switch_case of node.cases) {
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
628
|
+
const case_body = [];
|
|
629
|
+
|
|
630
|
+
if (switch_case.consequent.length !== 0) {
|
|
631
|
+
const consequent_scope =
|
|
632
|
+
context.state.scopes.get(switch_case.consequent) || context.state.scope;
|
|
633
|
+
const consequent = b.block(
|
|
634
|
+
transform_body(switch_case.consequent, {
|
|
635
|
+
...context,
|
|
636
|
+
state: { ...context.state, scope: consequent_scope },
|
|
637
|
+
}),
|
|
638
|
+
);
|
|
639
|
+
case_body.push(...consequent.body);
|
|
640
|
+
}
|
|
641
|
+
|
|
621
642
|
cases.push(
|
|
622
643
|
b.switch_case(
|
|
623
644
|
switch_case.test ? /** @type {AST.Expression} */ (context.visit(switch_case.test)) : null,
|
|
624
|
-
|
|
645
|
+
case_body,
|
|
625
646
|
),
|
|
626
647
|
);
|
|
627
648
|
}
|
|
649
|
+
|
|
628
650
|
context.state.init?.push(
|
|
629
651
|
b.switch(/** @type {AST.Expression} */ (context.visit(node.discriminant)), cases),
|
|
630
652
|
);
|
|
@@ -698,17 +720,91 @@ const visitors = {
|
|
|
698
720
|
AssignmentExpression(node, context) {
|
|
699
721
|
const left = node.left;
|
|
700
722
|
|
|
723
|
+
if (
|
|
724
|
+
left.type === 'MemberExpression' &&
|
|
725
|
+
(left.tracked || (left.property.type === 'Identifier' && left.property.tracked))
|
|
726
|
+
) {
|
|
727
|
+
const operator = node.operator;
|
|
728
|
+
const right = node.right;
|
|
729
|
+
|
|
730
|
+
return b.call(
|
|
731
|
+
'_$_.set_property',
|
|
732
|
+
/** @type {AST.Expression} */ (context.visit(left.object)),
|
|
733
|
+
left.computed
|
|
734
|
+
? /** @type {AST.Expression} */ (context.visit(left.property))
|
|
735
|
+
: b.literal(/** @type {AST.Identifier} */ (left.property).name),
|
|
736
|
+
operator === '='
|
|
737
|
+
? /** @type {AST.Expression} */ (context.visit(right))
|
|
738
|
+
: b.binary(
|
|
739
|
+
operator === '+=' ? '+' : operator === '-=' ? '-' : operator === '*=' ? '*' : '/',
|
|
740
|
+
b.call(
|
|
741
|
+
'_$_.get_property',
|
|
742
|
+
/** @type {AST.Expression} */ (context.visit(left.object)),
|
|
743
|
+
left.computed
|
|
744
|
+
? /** @type {AST.Expression} */ (context.visit(left.property))
|
|
745
|
+
: b.literal(/** @type {AST.Identifier} */ (left.property).name),
|
|
746
|
+
undefined,
|
|
747
|
+
),
|
|
748
|
+
/** @type {AST.Expression} */ (context.visit(right)),
|
|
749
|
+
),
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
|
|
701
753
|
if (left.type === 'Identifier' && left.tracked) {
|
|
754
|
+
const operator = node.operator;
|
|
755
|
+
const right = node.right;
|
|
756
|
+
|
|
757
|
+
return b.call(
|
|
758
|
+
'_$_.set',
|
|
759
|
+
/** @type {AST.Expression} */ (context.visit(left)),
|
|
760
|
+
operator === '='
|
|
761
|
+
? /** @type {AST.Expression} */ (context.visit(right))
|
|
762
|
+
: b.binary(
|
|
763
|
+
operator === '+=' ? '+' : operator === '-=' ? '-' : operator === '*=' ? '*' : '/',
|
|
764
|
+
b.call('_$_.get', left),
|
|
765
|
+
/** @type {AST.Expression} */ (context.visit(right)),
|
|
766
|
+
),
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
return context.next();
|
|
771
|
+
},
|
|
772
|
+
|
|
773
|
+
UpdateExpression(node, context) {
|
|
774
|
+
const argument = node.argument;
|
|
775
|
+
|
|
776
|
+
if (
|
|
777
|
+
argument.type === 'MemberExpression' &&
|
|
778
|
+
(argument.tracked || (argument.property.type === 'Identifier' && argument.property.tracked))
|
|
779
|
+
) {
|
|
702
780
|
return b.call(
|
|
703
|
-
'
|
|
781
|
+
node.prefix ? '_$_.update_pre_property' : '_$_.update_property',
|
|
704
782
|
/** @type {AST.Expression} */
|
|
705
|
-
(context.visit(
|
|
783
|
+
(context.visit(argument.object, { ...context.state, metadata: { tracking: false } })),
|
|
784
|
+
argument.computed
|
|
785
|
+
? /** @type {AST.Expression} */ (context.visit(argument.property))
|
|
786
|
+
: b.literal(/** @type {AST.Identifier} */ (argument.property).name),
|
|
787
|
+
node.operator === '--' ? b.literal(-1) : undefined,
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
if (argument.type === 'Identifier' && argument.tracked) {
|
|
792
|
+
return b.call(
|
|
793
|
+
node.prefix ? '_$_.update_pre' : '_$_.update',
|
|
706
794
|
/** @type {AST.Expression} */
|
|
707
|
-
(context.visit(
|
|
795
|
+
(context.visit(argument)),
|
|
796
|
+
node.operator === '--' ? b.literal(-1) : undefined,
|
|
708
797
|
);
|
|
709
798
|
}
|
|
710
799
|
|
|
711
|
-
|
|
800
|
+
if (argument.type === 'TrackedExpression') {
|
|
801
|
+
return b.call(
|
|
802
|
+
node.prefix ? '_$_.update_pre' : '_$_.update',
|
|
803
|
+
/** @type {AST.Expression} */
|
|
804
|
+
(context.visit(argument.argument)),
|
|
805
|
+
node.operator === '--' ? b.literal(-1) : undefined,
|
|
806
|
+
);
|
|
807
|
+
}
|
|
712
808
|
},
|
|
713
809
|
|
|
714
810
|
ServerIdentifier(node, context) {
|
|
@@ -832,6 +928,10 @@ const visitors = {
|
|
|
832
928
|
return b.await(/** @type {AST.AwaitExpression} */ (context.visit(node.argument)));
|
|
833
929
|
},
|
|
834
930
|
|
|
931
|
+
TrackedExpression(node, context) {
|
|
932
|
+
return b.call('_$_.get', /** @type {AST.Expression} */ (context.visit(node.argument)));
|
|
933
|
+
},
|
|
934
|
+
|
|
835
935
|
TrackedObjectExpression(node, context) {
|
|
836
936
|
// For SSR, we just evaluate the object as-is since there's no reactivity
|
|
837
937
|
return b.object(
|
|
@@ -852,20 +952,14 @@ const visitors = {
|
|
|
852
952
|
},
|
|
853
953
|
|
|
854
954
|
MemberExpression(node, context) {
|
|
855
|
-
const parent = context.path.at(-1);
|
|
856
|
-
|
|
857
955
|
if (node.tracked || (node.property.type === 'Identifier' && node.property.tracked)) {
|
|
858
956
|
return b.call(
|
|
859
|
-
'
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
(context.visit(node.
|
|
863
|
-
node.
|
|
864
|
-
|
|
865
|
-
: node.property,
|
|
866
|
-
node.computed,
|
|
867
|
-
node.optional,
|
|
868
|
-
),
|
|
957
|
+
'_$_.get_property',
|
|
958
|
+
/** @type {AST.Expression} */ (context.visit(node.object)),
|
|
959
|
+
node.computed
|
|
960
|
+
? /** @type {AST.Expression} */ (context.visit(node.property))
|
|
961
|
+
: b.literal(/** @type {AST.Identifier} */ (node.property).name),
|
|
962
|
+
node.optional ? b.true : undefined,
|
|
869
963
|
);
|
|
870
964
|
}
|
|
871
965
|
|
|
@@ -877,7 +971,7 @@ const visitors = {
|
|
|
877
971
|
let expression = /** @type {AST.Expression} */ (visit(node.expression, { ...state, metadata }));
|
|
878
972
|
|
|
879
973
|
if (expression.type === 'Identifier' && expression.tracked) {
|
|
880
|
-
expression = b.call('get', expression);
|
|
974
|
+
expression = b.call('_$_.get', expression);
|
|
881
975
|
}
|
|
882
976
|
|
|
883
977
|
if (expression.type === 'Literal') {
|
|
@@ -975,6 +1069,8 @@ export function transform_server(filename, source, analysis, minify_css) {
|
|
|
975
1069
|
metadata: {},
|
|
976
1070
|
};
|
|
977
1071
|
|
|
1072
|
+
state.imports.add(`import * as _$_ from 'ripple/internal/server'`);
|
|
1073
|
+
|
|
978
1074
|
const program = walk(analysis.ast, { ...state }, visitors);
|
|
979
1075
|
|
|
980
1076
|
const css = render_stylesheets(state.stylesheets, minify_css);
|
|
@@ -993,17 +1089,11 @@ export function transform_server(filename, source, analysis, minify_css) {
|
|
|
993
1089
|
}
|
|
994
1090
|
|
|
995
1091
|
// Add async property to component functions
|
|
996
|
-
|
|
997
1092
|
for (const import_node of state.imports) {
|
|
998
1093
|
/** @type {AST.Program} */ (program).body.unshift(b.stmt(b.id(import_node)));
|
|
999
1094
|
}
|
|
1000
1095
|
|
|
1001
|
-
|
|
1002
|
-
// Our types from 'estree' are incompatible
|
|
1003
|
-
// So we'll just give it what it wants with an unknown cast.
|
|
1004
|
-
// Functionally, none of the properties that are different between the two types
|
|
1005
|
-
// are used by the printer, so this is safe.
|
|
1006
|
-
const js = print(/** @type {TSESTree.Node} */ (/** @type {unknown} */ (program)), ts(), {
|
|
1096
|
+
const js = print(program, /** @type {Visitors<AST.Node, TransformServerState>} */ (ts()), {
|
|
1007
1097
|
sourceMapContent: source,
|
|
1008
1098
|
sourceMapSource: path.basename(filename),
|
|
1009
1099
|
});
|
package/src/compiler/scope.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
@import {
|
|
3
|
+
Binding,
|
|
4
|
+
ScopeInterface,
|
|
5
|
+
ScopeRoot as ScopeRootInterface,
|
|
6
|
+
Context
|
|
7
|
+
} from '#compiler';
|
|
8
|
+
@import * as AST from 'estree';
|
|
9
|
+
*/
|
|
3
10
|
|
|
4
11
|
import is_reference from 'is-reference';
|
|
5
12
|
import { extract_identifiers, object, unwrap_pattern } from '../utils/ast.js';
|
|
@@ -45,7 +52,7 @@ export function create_scopes(ast, root, parent) {
|
|
|
45
52
|
/**
|
|
46
53
|
* Create a block scope
|
|
47
54
|
* @param {AST.Node} node - AST node
|
|
48
|
-
* @param {
|
|
55
|
+
* @param {Context<AST.Node, State>} context - Visitor context
|
|
49
56
|
*/
|
|
50
57
|
const create_block_scope = (node, { state, next }) => {
|
|
51
58
|
const scope = state.scope.child(true);
|
|
@@ -60,7 +67,7 @@ export function create_scopes(ast, root, parent) {
|
|
|
60
67
|
next({ scope });
|
|
61
68
|
};
|
|
62
69
|
|
|
63
|
-
walk(
|
|
70
|
+
walk(ast, state, {
|
|
64
71
|
// references
|
|
65
72
|
Identifier(node, { path, state }) {
|
|
66
73
|
const parent = path.at(-1);
|
|
@@ -95,12 +102,6 @@ export function create_scopes(ast, root, parent) {
|
|
|
95
102
|
}
|
|
96
103
|
},
|
|
97
104
|
|
|
98
|
-
/**
|
|
99
|
-
* @param {AST.Component} node
|
|
100
|
-
* @param {Object} context
|
|
101
|
-
* @param {any} context.state
|
|
102
|
-
* @param {Function} context.next
|
|
103
|
-
*/
|
|
104
105
|
Component(node, { state, next }) {
|
|
105
106
|
const scope = state.scope.child();
|
|
106
107
|
scopes.set(node, scope);
|
|
@@ -114,12 +115,6 @@ export function create_scopes(ast, root, parent) {
|
|
|
114
115
|
next({ scope });
|
|
115
116
|
},
|
|
116
117
|
|
|
117
|
-
/**
|
|
118
|
-
* @param {AST.Element} node
|
|
119
|
-
* @param {Object} context
|
|
120
|
-
* @param {any} context.state
|
|
121
|
-
* @param {Function} context.next
|
|
122
|
-
*/
|
|
123
118
|
Element(node, { state, next }) {
|
|
124
119
|
const scope = state.scope.child();
|
|
125
120
|
scopes.set(node, scope);
|