ripple 0.3.10 → 0.3.11
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 +31 -0
- package/package.json +2 -2
- package/src/compiler/errors.js +1 -1
- package/src/compiler/index.d.ts +3 -1
- package/src/compiler/phases/1-parse/index.js +170 -8
- package/src/compiler/phases/2-analyze/index.js +231 -20
- package/src/compiler/phases/3-transform/client/index.js +169 -77
- package/src/compiler/phases/3-transform/server/index.js +46 -3
- package/src/compiler/types/index.d.ts +19 -2
- package/src/compiler/types/parse.d.ts +1 -1
- package/src/compiler/utils.js +174 -0
- package/src/runtime/index-client.js +14 -4
- package/src/runtime/internal/client/composite.js +2 -2
- package/src/runtime/internal/client/expression.js +64 -2
- package/src/runtime/internal/client/portal.js +1 -1
- package/src/utils/builders.js +30 -0
- package/tests/client/basic/__snapshots__/basic.rendering.test.ripple.snap +1 -0
- package/tests/client/basic/basic.rendering.test.ripple +4 -2
- package/tests/client/composite/composite.render.test.ripple +46 -0
- package/tests/client/return.test.ripple +101 -0
- package/tests/client/tsx.test.ripple +486 -0
- package/tests/hydration/compiled/client/basic.js +8 -24
- package/tests/hydration/compiled/client/composite.js +6 -24
- package/tests/hydration/compiled/client/events.js +9 -54
- package/tests/hydration/compiled/client/for.js +59 -152
- package/tests/hydration/compiled/client/head.js +5 -20
- package/tests/hydration/compiled/client/hmr.js +2 -8
- package/tests/hydration/compiled/client/html.js +59 -226
- package/tests/hydration/compiled/client/if-children.js +6 -22
- package/tests/hydration/compiled/client/mixed-control-flow.js +18 -66
- package/tests/hydration/compiled/client/nested-control-flow.js +92 -368
- package/tests/hydration/compiled/client/portal.js +4 -16
- package/tests/hydration/compiled/client/reactivity.js +7 -40
- package/tests/hydration/compiled/client/return.js +1 -4
- package/tests/hydration/compiled/client/try.js +2 -2
- package/tests/utils/compiler-compat-config.test.js +38 -0
- package/tests/utils/vite-plugin-config.test.js +113 -0
- package/tsconfig.typecheck.json +2 -1
- package/types/index.d.ts +2 -12
|
@@ -41,6 +41,123 @@ import { validate_nesting } from './validation.js';
|
|
|
41
41
|
|
|
42
42
|
const valid_in_head = new Set(['title', 'base', 'link', 'meta', 'style', 'script', 'noscript']);
|
|
43
43
|
|
|
44
|
+
const mutating_method_names = new Set([
|
|
45
|
+
'add',
|
|
46
|
+
'append',
|
|
47
|
+
'clear',
|
|
48
|
+
'copyWithin',
|
|
49
|
+
'delete',
|
|
50
|
+
'fill',
|
|
51
|
+
'pop',
|
|
52
|
+
'push',
|
|
53
|
+
'reverse',
|
|
54
|
+
'set',
|
|
55
|
+
'shift',
|
|
56
|
+
'sort',
|
|
57
|
+
'splice',
|
|
58
|
+
'unshift',
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {AST.MemberExpression} node
|
|
63
|
+
* @returns {string | null}
|
|
64
|
+
*/
|
|
65
|
+
function get_member_name(node) {
|
|
66
|
+
if (!node.computed && node.property.type === 'Identifier') {
|
|
67
|
+
return node.property.name;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (node.computed && node.property.type === 'Literal') {
|
|
71
|
+
return typeof node.property.value === 'string' ? node.property.value : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {AST.CallExpression} node
|
|
79
|
+
* @returns {boolean}
|
|
80
|
+
*/
|
|
81
|
+
function is_mutating_call_expression(node) {
|
|
82
|
+
return (
|
|
83
|
+
node.callee.type === 'MemberExpression' &&
|
|
84
|
+
mutating_method_names.has(get_member_name(node.callee) ?? '')
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Check if an expression contains side effects or other impure operations.
|
|
90
|
+
* Template expressions should be pure reads.
|
|
91
|
+
* @param {AST.Expression | AST.SpreadElement | AST.Super | AST.Pattern} node
|
|
92
|
+
* @returns {boolean}
|
|
93
|
+
*/
|
|
94
|
+
function expression_has_side_effects(node) {
|
|
95
|
+
switch (node.type) {
|
|
96
|
+
case 'AssignmentExpression':
|
|
97
|
+
case 'UpdateExpression':
|
|
98
|
+
return true;
|
|
99
|
+
case 'SequenceExpression':
|
|
100
|
+
return node.expressions.some(expression_has_side_effects);
|
|
101
|
+
case 'ConditionalExpression':
|
|
102
|
+
return (
|
|
103
|
+
expression_has_side_effects(node.test) ||
|
|
104
|
+
expression_has_side_effects(node.consequent) ||
|
|
105
|
+
expression_has_side_effects(node.alternate)
|
|
106
|
+
);
|
|
107
|
+
case 'LogicalExpression':
|
|
108
|
+
case 'BinaryExpression':
|
|
109
|
+
return (
|
|
110
|
+
expression_has_side_effects(/** @type {AST.Expression} */ (node.left)) ||
|
|
111
|
+
expression_has_side_effects(node.right)
|
|
112
|
+
);
|
|
113
|
+
case 'UnaryExpression':
|
|
114
|
+
// delete operator has side effects (removes object properties)
|
|
115
|
+
if (node.operator === 'delete') return true;
|
|
116
|
+
return expression_has_side_effects(node.argument);
|
|
117
|
+
case 'AwaitExpression':
|
|
118
|
+
return expression_has_side_effects(node.argument);
|
|
119
|
+
case 'ChainExpression':
|
|
120
|
+
return expression_has_side_effects(node.expression);
|
|
121
|
+
case 'MemberExpression':
|
|
122
|
+
return (
|
|
123
|
+
expression_has_side_effects(node.object) ||
|
|
124
|
+
(node.computed &&
|
|
125
|
+
expression_has_side_effects(/** @type {AST.Expression} */ (node.property)))
|
|
126
|
+
);
|
|
127
|
+
case 'CallExpression':
|
|
128
|
+
return (
|
|
129
|
+
is_mutating_call_expression(node) ||
|
|
130
|
+
expression_has_side_effects(node.callee) ||
|
|
131
|
+
node.arguments.some(expression_has_side_effects)
|
|
132
|
+
);
|
|
133
|
+
case 'NewExpression':
|
|
134
|
+
return (
|
|
135
|
+
expression_has_side_effects(node.callee) || node.arguments.some(expression_has_side_effects)
|
|
136
|
+
);
|
|
137
|
+
case 'TemplateLiteral':
|
|
138
|
+
return node.expressions.some(expression_has_side_effects);
|
|
139
|
+
case 'TaggedTemplateExpression':
|
|
140
|
+
return (
|
|
141
|
+
expression_has_side_effects(node.tag) ||
|
|
142
|
+
node.quasi.expressions.some(expression_has_side_effects)
|
|
143
|
+
);
|
|
144
|
+
case 'ArrayExpression':
|
|
145
|
+
return node.elements.some((el) => el !== null && expression_has_side_effects(el));
|
|
146
|
+
case 'ObjectExpression':
|
|
147
|
+
return node.properties.some((prop) =>
|
|
148
|
+
prop.type === 'SpreadElement'
|
|
149
|
+
? expression_has_side_effects(prop.argument)
|
|
150
|
+
: expression_has_side_effects(prop.value) ||
|
|
151
|
+
(prop.computed &&
|
|
152
|
+
expression_has_side_effects(/** @type {AST.Expression} */ (prop.key))),
|
|
153
|
+
);
|
|
154
|
+
case 'SpreadElement':
|
|
155
|
+
return expression_has_side_effects(node.argument);
|
|
156
|
+
default:
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
44
161
|
/**
|
|
45
162
|
* @param {AnalysisContext['path']} path
|
|
46
163
|
*/
|
|
@@ -63,6 +180,7 @@ function mark_control_flow_has_template(path) {
|
|
|
63
180
|
node.type === 'TryStatement' ||
|
|
64
181
|
node.type === 'IfStatement' ||
|
|
65
182
|
node.type === 'SwitchStatement' ||
|
|
183
|
+
node.type === 'Tsx' ||
|
|
66
184
|
node.type === 'TsxCompat'
|
|
67
185
|
) {
|
|
68
186
|
node.metadata.has_template = true;
|
|
@@ -125,7 +243,11 @@ function setup_lazy_transforms(pattern, source_id, state, writable, is_track_cal
|
|
|
125
243
|
|
|
126
244
|
if (node.prefix) {
|
|
127
245
|
// ++count: return new value
|
|
128
|
-
return b.assignment(
|
|
246
|
+
return b.assignment(
|
|
247
|
+
'=',
|
|
248
|
+
/** @type {AST.Pattern} */ (member),
|
|
249
|
+
b.binary('+', fallback_read, delta),
|
|
250
|
+
);
|
|
129
251
|
} else {
|
|
130
252
|
// count++: return old value, write new value
|
|
131
253
|
// Use IIFE to declare temp variable
|
|
@@ -135,7 +257,13 @@ function setup_lazy_transforms(pattern, source_id, state, writable, is_track_cal
|
|
|
135
257
|
[],
|
|
136
258
|
b.block([
|
|
137
259
|
b.var(temp, fallback_read),
|
|
138
|
-
b.stmt(
|
|
260
|
+
b.stmt(
|
|
261
|
+
b.assignment(
|
|
262
|
+
'=',
|
|
263
|
+
/** @type {AST.Pattern} */ (member),
|
|
264
|
+
b.binary('+', temp, delta),
|
|
265
|
+
),
|
|
266
|
+
),
|
|
139
267
|
b.return(temp),
|
|
140
268
|
]),
|
|
141
269
|
),
|
|
@@ -198,7 +326,12 @@ function setup_lazy_array_transforms(pattern, source_id, state, writable) {
|
|
|
198
326
|
if (i === 0) {
|
|
199
327
|
// Fast path for index 0: use _$_.get(source) instead of source[0]
|
|
200
328
|
const read_expr = has_fallback
|
|
201
|
-
? () =>
|
|
329
|
+
? () =>
|
|
330
|
+
b.call(
|
|
331
|
+
'_$_.fallback',
|
|
332
|
+
b.call('_$_.get', source_id),
|
|
333
|
+
/** @type {AST.Expression} */ (fallback_value),
|
|
334
|
+
)
|
|
202
335
|
: () => b.call('_$_.get', source_id);
|
|
203
336
|
|
|
204
337
|
// Signal that read already produces an unwrapped value (calls _$_.get internally)
|
|
@@ -247,6 +380,7 @@ function setup_lazy_array_transforms(pattern, source_id, state, writable) {
|
|
|
247
380
|
} else {
|
|
248
381
|
binding.transform.update = (node) => {
|
|
249
382
|
const fn_name = node.prefix ? '_$_.update_pre' : '_$_.update';
|
|
383
|
+
/** @type {AST.Expression[]} */
|
|
250
384
|
const args = [source_id];
|
|
251
385
|
if (node.operator === '--') {
|
|
252
386
|
args.push(b.literal(-1));
|
|
@@ -280,7 +414,10 @@ function setup_lazy_array_transforms(pattern, source_id, state, writable) {
|
|
|
280
414
|
binding.kind = path.has_default_value ? 'lazy_fallback' : 'lazy';
|
|
281
415
|
|
|
282
416
|
binding.transform = {
|
|
283
|
-
read: (_) =>
|
|
417
|
+
read: (_) =>
|
|
418
|
+
path.expression(
|
|
419
|
+
/** @type {AST.Identifier | AST.CallExpression} */ (base_expression(source_id)),
|
|
420
|
+
),
|
|
284
421
|
};
|
|
285
422
|
|
|
286
423
|
if (writable) {
|
|
@@ -288,7 +425,7 @@ function setup_lazy_array_transforms(pattern, source_id, state, writable) {
|
|
|
288
425
|
return b.assignment(
|
|
289
426
|
'=',
|
|
290
427
|
/** @type {AST.MemberExpression} */ (
|
|
291
|
-
path.update_expression(base_expression(source_id))
|
|
428
|
+
path.update_expression(/** @type {AST.Identifier} */ (base_expression(source_id)))
|
|
292
429
|
),
|
|
293
430
|
value,
|
|
294
431
|
);
|
|
@@ -296,12 +433,20 @@ function setup_lazy_array_transforms(pattern, source_id, state, writable) {
|
|
|
296
433
|
|
|
297
434
|
if (path.has_default_value) {
|
|
298
435
|
binding.transform.update = (node) => {
|
|
299
|
-
const member = path.update_expression(
|
|
300
|
-
|
|
436
|
+
const member = path.update_expression(
|
|
437
|
+
/** @type {AST.Identifier} */ (base_expression(source_id)),
|
|
438
|
+
);
|
|
439
|
+
const fallback_read = path.expression(
|
|
440
|
+
/** @type {AST.Identifier | AST.CallExpression} */ (base_expression(source_id)),
|
|
441
|
+
);
|
|
301
442
|
const delta = node.operator === '++' ? b.literal(1) : b.literal(-1);
|
|
302
443
|
|
|
303
444
|
if (node.prefix) {
|
|
304
|
-
return b.assignment(
|
|
445
|
+
return b.assignment(
|
|
446
|
+
'=',
|
|
447
|
+
/** @type {AST.Pattern} */ (member),
|
|
448
|
+
b.binary('+', fallback_read, delta),
|
|
449
|
+
);
|
|
305
450
|
} else {
|
|
306
451
|
const temp = b.id('_v');
|
|
307
452
|
return b.call(
|
|
@@ -309,7 +454,13 @@ function setup_lazy_array_transforms(pattern, source_id, state, writable) {
|
|
|
309
454
|
[],
|
|
310
455
|
b.block([
|
|
311
456
|
b.var(temp, fallback_read),
|
|
312
|
-
b.stmt(
|
|
457
|
+
b.stmt(
|
|
458
|
+
b.assignment(
|
|
459
|
+
'=',
|
|
460
|
+
/** @type {AST.Pattern} */ (member),
|
|
461
|
+
b.binary('+', temp, delta),
|
|
462
|
+
),
|
|
463
|
+
),
|
|
313
464
|
b.return(temp),
|
|
314
465
|
]),
|
|
315
466
|
),
|
|
@@ -320,7 +471,7 @@ function setup_lazy_array_transforms(pattern, source_id, state, writable) {
|
|
|
320
471
|
binding.transform.update = (node) =>
|
|
321
472
|
b.update(
|
|
322
473
|
node.operator,
|
|
323
|
-
path.update_expression(base_expression(source_id)),
|
|
474
|
+
path.update_expression(/** @type {AST.Identifier} */ (base_expression(source_id))),
|
|
324
475
|
node.prefix,
|
|
325
476
|
);
|
|
326
477
|
}
|
|
@@ -348,11 +499,11 @@ function unwrap_type_annotation(type_annotation) {
|
|
|
348
499
|
|
|
349
500
|
while (annotation) {
|
|
350
501
|
if (annotation.type === 'TSParenthesizedType') {
|
|
351
|
-
annotation = annotation.typeAnnotation;
|
|
502
|
+
annotation = /** @type {AST.TypeNode | undefined} */ (annotation.typeAnnotation);
|
|
352
503
|
continue;
|
|
353
504
|
}
|
|
354
505
|
if (annotation.type === 'TSOptionalType') {
|
|
355
|
-
annotation = annotation.typeAnnotation;
|
|
506
|
+
annotation = /** @type {AST.TypeNode | undefined} */ (annotation.typeAnnotation);
|
|
356
507
|
continue;
|
|
357
508
|
}
|
|
358
509
|
break;
|
|
@@ -375,11 +526,11 @@ function normalize_tuple_element_type(type_annotation) {
|
|
|
375
526
|
continue;
|
|
376
527
|
}
|
|
377
528
|
if (annotation.type === 'TSParenthesizedType') {
|
|
378
|
-
annotation = annotation.typeAnnotation;
|
|
529
|
+
annotation = /** @type {AST.TypeNode} */ (annotation.typeAnnotation);
|
|
379
530
|
continue;
|
|
380
531
|
}
|
|
381
532
|
if (annotation.type === 'TSOptionalType') {
|
|
382
|
-
annotation = annotation.typeAnnotation;
|
|
533
|
+
annotation = /** @type {AST.TypeNode} */ (annotation.typeAnnotation);
|
|
383
534
|
continue;
|
|
384
535
|
}
|
|
385
536
|
break;
|
|
@@ -431,7 +582,7 @@ function get_object_property_type_annotation(type_annotation, property) {
|
|
|
431
582
|
return undefined;
|
|
432
583
|
}
|
|
433
584
|
|
|
434
|
-
const key_name = get_object_pattern_key_name(property.key);
|
|
585
|
+
const key_name = get_object_pattern_key_name(/** @type {AST.Expression} */ (property.key));
|
|
435
586
|
if (key_name === null) {
|
|
436
587
|
return undefined;
|
|
437
588
|
}
|
|
@@ -928,7 +1079,9 @@ const visitors = {
|
|
|
928
1079
|
const callee = node.callee;
|
|
929
1080
|
|
|
930
1081
|
if (
|
|
931
|
-
!context.path.some(
|
|
1082
|
+
!context.path.some(
|
|
1083
|
+
(path_node) => path_node.type === 'TsxCompat' || path_node.type === 'Tsx',
|
|
1084
|
+
) &&
|
|
932
1085
|
is_children_template_expression(/** @type {AST.Expression} */ (callee), context)
|
|
933
1086
|
) {
|
|
934
1087
|
error(
|
|
@@ -1415,6 +1568,7 @@ const visitors = {
|
|
|
1415
1568
|
...node.metadata,
|
|
1416
1569
|
has_template: false,
|
|
1417
1570
|
has_await: false,
|
|
1571
|
+
has_throw: false,
|
|
1418
1572
|
};
|
|
1419
1573
|
|
|
1420
1574
|
const test_metadata = { tracking: false };
|
|
@@ -1436,7 +1590,7 @@ const visitors = {
|
|
|
1436
1590
|
node.metadata.lone_return = true;
|
|
1437
1591
|
}
|
|
1438
1592
|
|
|
1439
|
-
if (!node.metadata.has_template && !node.metadata.has_return) {
|
|
1593
|
+
if (!node.metadata.has_template && !node.metadata.has_return && !node.metadata.has_throw) {
|
|
1440
1594
|
error(
|
|
1441
1595
|
'Component if statements must contain a template in their "then" body. Move the if statement into an effect if it does not render anything.',
|
|
1442
1596
|
context.state.analysis.module.filename,
|
|
@@ -1451,9 +1605,10 @@ const visitors = {
|
|
|
1451
1605
|
const saved_returns = node.metadata.returns;
|
|
1452
1606
|
node.metadata.has_template = false;
|
|
1453
1607
|
node.metadata.has_await = false;
|
|
1608
|
+
node.metadata.has_throw = false;
|
|
1454
1609
|
context.visit(node.alternate, context.state);
|
|
1455
1610
|
|
|
1456
|
-
if (!node.metadata.has_template && !node.metadata.has_return) {
|
|
1611
|
+
if (!node.metadata.has_template && !node.metadata.has_return && !node.metadata.has_throw) {
|
|
1457
1612
|
error(
|
|
1458
1613
|
'Component if statements must contain a template in their "else" body. Move the if statement into an effect if it does not render anything.',
|
|
1459
1614
|
context.state.analysis.module.filename,
|
|
@@ -1522,6 +1677,33 @@ const visitors = {
|
|
|
1522
1677
|
}
|
|
1523
1678
|
},
|
|
1524
1679
|
|
|
1680
|
+
ThrowStatement(node, context) {
|
|
1681
|
+
if (!is_inside_component(context)) {
|
|
1682
|
+
return context.next();
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
for (let i = context.path.length - 1; i >= 0; i--) {
|
|
1686
|
+
const ancestor = context.path[i];
|
|
1687
|
+
|
|
1688
|
+
if (
|
|
1689
|
+
ancestor.type === 'Component' ||
|
|
1690
|
+
ancestor.type === 'FunctionExpression' ||
|
|
1691
|
+
ancestor.type === 'ArrowFunctionExpression' ||
|
|
1692
|
+
ancestor.type === 'FunctionDeclaration'
|
|
1693
|
+
) {
|
|
1694
|
+
break;
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
if (ancestor.type === 'IfStatement') {
|
|
1698
|
+
if (!ancestor.metadata.has_throw) {
|
|
1699
|
+
ancestor.metadata.has_throw = true;
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
context.next();
|
|
1705
|
+
},
|
|
1706
|
+
|
|
1525
1707
|
TryStatement(node, context) {
|
|
1526
1708
|
const { state } = context;
|
|
1527
1709
|
if (!is_inside_component(context)) {
|
|
@@ -1617,7 +1799,7 @@ const visitors = {
|
|
|
1617
1799
|
},
|
|
1618
1800
|
|
|
1619
1801
|
JSXElement(node, context) {
|
|
1620
|
-
const inside_tsx_compat = context.path.some((n) => n.type === 'TsxCompat');
|
|
1802
|
+
const inside_tsx_compat = context.path.some((n) => n.type === 'TsxCompat' || n.type === 'Tsx');
|
|
1621
1803
|
|
|
1622
1804
|
if (inside_tsx_compat) {
|
|
1623
1805
|
return context.next();
|
|
@@ -1630,11 +1812,28 @@ const visitors = {
|
|
|
1630
1812
|
);
|
|
1631
1813
|
},
|
|
1632
1814
|
|
|
1633
|
-
|
|
1815
|
+
Tsx(_, context) {
|
|
1634
1816
|
mark_control_flow_has_template(context.path);
|
|
1635
1817
|
return context.next();
|
|
1636
1818
|
},
|
|
1637
1819
|
|
|
1820
|
+
TsxCompat(node, context) {
|
|
1821
|
+
mark_control_flow_has_template(context.path);
|
|
1822
|
+
|
|
1823
|
+
const configured_compat_kinds = context.state.configured_compat_kinds;
|
|
1824
|
+
if (configured_compat_kinds !== undefined && !configured_compat_kinds.has(node.kind)) {
|
|
1825
|
+
error(
|
|
1826
|
+
`<tsx:${node.kind}> requires "${node.kind}" compat to be configured in ripple.config.ts.`,
|
|
1827
|
+
context.state.analysis.module.filename,
|
|
1828
|
+
node,
|
|
1829
|
+
context.state.loose ? context.state.analysis.errors : undefined,
|
|
1830
|
+
context.state.analysis.comments,
|
|
1831
|
+
);
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
return context.next();
|
|
1835
|
+
},
|
|
1836
|
+
|
|
1638
1837
|
Element(node, context) {
|
|
1639
1838
|
if (!is_inside_component(context)) {
|
|
1640
1839
|
error(
|
|
@@ -1910,6 +2109,16 @@ const visitors = {
|
|
|
1910
2109
|
RippleExpression(node, context) {
|
|
1911
2110
|
mark_control_flow_has_template(context.path);
|
|
1912
2111
|
|
|
2112
|
+
if (expression_has_side_effects(node.expression)) {
|
|
2113
|
+
error(
|
|
2114
|
+
'Template expressions must not contain side effects.',
|
|
2115
|
+
context.state.analysis.module.filename,
|
|
2116
|
+
node.expression,
|
|
2117
|
+
context.state.loose ? context.state.analysis.errors : undefined,
|
|
2118
|
+
context.state.analysis.comments,
|
|
2119
|
+
);
|
|
2120
|
+
}
|
|
2121
|
+
|
|
1913
2122
|
context.next();
|
|
1914
2123
|
},
|
|
1915
2124
|
|
|
@@ -2017,6 +2226,8 @@ export function analyze(ast, filename, options = {}) {
|
|
|
2017
2226
|
ancestor_server_block: undefined,
|
|
2018
2227
|
to_ts: options.to_ts ?? false,
|
|
2019
2228
|
loose,
|
|
2229
|
+
configured_compat_kinds:
|
|
2230
|
+
options.compat_kinds === undefined ? undefined : new Set(options.compat_kinds),
|
|
2020
2231
|
metadata: {},
|
|
2021
2232
|
mode: options.mode,
|
|
2022
2233
|
},
|