ripple 0.2.180 → 0.2.183
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 +4 -2
- package/src/compiler/errors.js +3 -1
- package/src/compiler/index.d.ts +2 -1
- package/src/compiler/phases/1-parse/index.js +525 -311
- package/src/compiler/phases/1-parse/style.js +3 -1
- package/src/compiler/phases/2-analyze/css-analyze.js +116 -97
- package/src/compiler/phases/2-analyze/index.js +80 -50
- package/src/compiler/phases/2-analyze/prune.js +200 -58
- package/src/compiler/phases/2-analyze/validation.js +9 -7
- package/src/compiler/phases/3-transform/client/index.js +871 -394
- package/src/compiler/phases/3-transform/segments.js +6 -4
- package/src/compiler/phases/3-transform/server/index.js +278 -121
- package/src/compiler/scope.js +45 -93
- package/src/compiler/types/index.d.ts +619 -199
- package/src/compiler/types/parse.d.ts +1580 -0
- package/src/compiler/utils.js +62 -74
- package/src/runtime/internal/client/blocks.js +4 -1
- package/src/utils/ast.js +247 -192
- package/src/utils/builders.js +309 -247
- package/src/utils/sanitize_template_string.js +2 -2
package/src/utils/ast.js
CHANGED
|
@@ -1,218 +1,273 @@
|
|
|
1
|
+
/** @import * as AST from 'estree' */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents the path of a destructured assignment from either a declaration
|
|
5
|
+
* or assignment expression. For example, given `const { foo: { bar: baz } } = quux`,
|
|
6
|
+
* the path of `baz` is `foo.bar`
|
|
7
|
+
* @typedef {{
|
|
8
|
+
* node: AST.Identifier | AST.MemberExpression;
|
|
9
|
+
* is_rest: boolean;
|
|
10
|
+
* has_default_value: boolean;
|
|
11
|
+
* expression: (object: AST.Identifier | AST.CallExpression) => AST.Expression;
|
|
12
|
+
* update_expression: (object: AST.Identifier) => AST.Expression;
|
|
13
|
+
* }} DestructuredAssignment
|
|
14
|
+
* - `node`: The node the destructuring path ends in. Can be a member expression only for assignment expressions
|
|
15
|
+
* - `is_rest`: `true` if this is a `...rest` destructuring
|
|
16
|
+
* - `has_default_value`: `true` if this has a fallback value like `const { foo = 'bar' } = ..`
|
|
17
|
+
* - `expression`: The value of the current path. Will be a call expression if a rest element or default is involved — e.g. `const { foo: { bar: baz = 42 }, ...rest } = quux` — since we can't represent `baz` or `rest` purely as a path. Will be an await expression in case of an async default value (`const { foo = await bar } = ...`)
|
|
18
|
+
* - `update_expression`: Like `expression` but without default values.
|
|
19
|
+
*/
|
|
20
|
+
|
|
1
21
|
import * as b from './builders.js';
|
|
2
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Gets the left-most identifier of a member expression or identifier.
|
|
25
|
+
* @param {AST.MemberExpression | AST.Identifier} expression
|
|
26
|
+
* @returns {AST.Identifier | null}
|
|
27
|
+
*/
|
|
3
28
|
export function object(expression) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
29
|
+
while (expression.type === 'MemberExpression') {
|
|
30
|
+
expression = /** @type {AST.MemberExpression | AST.Identifier} */ (expression.object);
|
|
31
|
+
}
|
|
7
32
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
33
|
+
if (expression.type !== 'Identifier') {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
11
36
|
|
|
12
|
-
|
|
37
|
+
return expression;
|
|
13
38
|
}
|
|
14
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Extracts all identifiers and member expressions from a pattern.
|
|
42
|
+
* @param {AST.Pattern} pattern
|
|
43
|
+
* @param {Array<AST.Identifier | AST.MemberExpression>} [nodes]
|
|
44
|
+
* @returns {Array<AST.Identifier | AST.MemberExpression>}
|
|
45
|
+
*/
|
|
15
46
|
export function unwrap_pattern(pattern, nodes = []) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
switch (pattern.type) {
|
|
48
|
+
case 'Identifier':
|
|
49
|
+
nodes.push(pattern);
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
case 'MemberExpression':
|
|
53
|
+
// member expressions can be part of an assignment pattern, but not a binding pattern
|
|
54
|
+
// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#binding_and_assignment
|
|
55
|
+
nodes.push(pattern);
|
|
56
|
+
break;
|
|
57
|
+
|
|
58
|
+
case 'ObjectPattern':
|
|
59
|
+
for (const prop of pattern.properties) {
|
|
60
|
+
if (prop.type === 'RestElement') {
|
|
61
|
+
unwrap_pattern(prop.argument, nodes);
|
|
62
|
+
} else {
|
|
63
|
+
unwrap_pattern(prop.value, nodes);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
break;
|
|
68
|
+
|
|
69
|
+
case 'ArrayPattern':
|
|
70
|
+
for (const element of pattern.elements) {
|
|
71
|
+
if (element) unwrap_pattern(element, nodes);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
break;
|
|
75
|
+
|
|
76
|
+
case 'RestElement':
|
|
77
|
+
unwrap_pattern(pattern.argument, nodes);
|
|
78
|
+
break;
|
|
79
|
+
|
|
80
|
+
case 'AssignmentPattern':
|
|
81
|
+
unwrap_pattern(pattern.left, nodes);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return nodes;
|
|
55
86
|
}
|
|
56
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Extracts all identifiers from a pattern.
|
|
90
|
+
* @param {AST.Pattern} pattern
|
|
91
|
+
* @returns {AST.Identifier[]}
|
|
92
|
+
*/
|
|
57
93
|
export function extract_identifiers(pattern) {
|
|
58
|
-
|
|
94
|
+
return unwrap_pattern(pattern, []).filter((node) => node.type === 'Identifier');
|
|
59
95
|
}
|
|
60
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Extracts all destructured assignments from a pattern.
|
|
99
|
+
* @param {AST.Node} param
|
|
100
|
+
* @returns {DestructuredAssignment[]}
|
|
101
|
+
*/
|
|
61
102
|
export function extract_paths(param) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
103
|
+
return _extract_paths(
|
|
104
|
+
[],
|
|
105
|
+
param,
|
|
106
|
+
/** @param {AST.Identifier | AST.MemberExpression | AST.CallExpression} node */
|
|
107
|
+
(node) => node,
|
|
108
|
+
/** @param {AST.Identifier | AST.MemberExpression} node */
|
|
109
|
+
(node) => node,
|
|
110
|
+
false,
|
|
111
|
+
);
|
|
69
112
|
}
|
|
70
113
|
|
|
114
|
+
/**
|
|
115
|
+
* @param {DestructuredAssignment[]} assignments
|
|
116
|
+
* @param {AST.Node} param
|
|
117
|
+
* @param {DestructuredAssignment['expression']} expression
|
|
118
|
+
* @param {DestructuredAssignment['update_expression']} update_expression
|
|
119
|
+
* @param {boolean} has_default_value
|
|
120
|
+
* @returns {DestructuredAssignment[]}
|
|
121
|
+
*/
|
|
71
122
|
function _extract_paths(assignments = [], param, expression, update_expression, has_default_value) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
123
|
+
switch (param.type) {
|
|
124
|
+
case 'Identifier':
|
|
125
|
+
case 'MemberExpression':
|
|
126
|
+
assignments.push({
|
|
127
|
+
node: param,
|
|
128
|
+
is_rest: false,
|
|
129
|
+
has_default_value,
|
|
130
|
+
expression,
|
|
131
|
+
update_expression,
|
|
132
|
+
});
|
|
133
|
+
break;
|
|
134
|
+
|
|
135
|
+
case 'ObjectPattern':
|
|
136
|
+
for (const prop of param.properties) {
|
|
137
|
+
if (prop.type === 'RestElement') {
|
|
138
|
+
/** @type {DestructuredAssignment['expression']} */
|
|
139
|
+
const rest_expression = (object) => {
|
|
140
|
+
/** @type {AST.Expression[]} */
|
|
141
|
+
const props = [];
|
|
142
|
+
|
|
143
|
+
for (const p of param.properties) {
|
|
144
|
+
if (p.type === 'Property' && p.key.type !== 'PrivateIdentifier') {
|
|
145
|
+
if (p.key.type === 'Identifier' && !p.computed) {
|
|
146
|
+
props.push(b.literal(p.key.name));
|
|
147
|
+
} else if (p.key.type === 'Literal') {
|
|
148
|
+
props.push(b.literal(String(p.key.value)));
|
|
149
|
+
} else {
|
|
150
|
+
props.push(b.call('String', p.key));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return b.call('_$_.exclude_from_object', expression(object), b.array(props));
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
if (prop.argument.type === 'Identifier') {
|
|
159
|
+
assignments.push({
|
|
160
|
+
node: prop.argument,
|
|
161
|
+
is_rest: true,
|
|
162
|
+
has_default_value,
|
|
163
|
+
expression: rest_expression,
|
|
164
|
+
update_expression: rest_expression,
|
|
165
|
+
});
|
|
166
|
+
} else {
|
|
167
|
+
_extract_paths(
|
|
168
|
+
assignments,
|
|
169
|
+
prop.argument,
|
|
170
|
+
rest_expression,
|
|
171
|
+
rest_expression,
|
|
172
|
+
has_default_value,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
/** @type {DestructuredAssignment['expression']} */
|
|
177
|
+
const object_expression = (object) =>
|
|
178
|
+
b.member(expression(object), prop.key, prop.computed || prop.key.type !== 'Identifier');
|
|
179
|
+
_extract_paths(
|
|
180
|
+
assignments,
|
|
181
|
+
prop.value,
|
|
182
|
+
object_expression,
|
|
183
|
+
object_expression,
|
|
184
|
+
has_default_value,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
break;
|
|
190
|
+
|
|
191
|
+
case 'ArrayPattern':
|
|
192
|
+
for (let i = 0; i < param.elements.length; i += 1) {
|
|
193
|
+
const element = param.elements[i];
|
|
194
|
+
if (element) {
|
|
195
|
+
if (element.type === 'RestElement') {
|
|
196
|
+
/** @type {DestructuredAssignment['expression']} */
|
|
197
|
+
const rest_expression = (object) =>
|
|
198
|
+
b.call(b.member(expression(object), 'slice'), b.literal(i));
|
|
199
|
+
if (element.argument.type === 'Identifier') {
|
|
200
|
+
assignments.push({
|
|
201
|
+
node: element.argument,
|
|
202
|
+
is_rest: true,
|
|
203
|
+
has_default_value,
|
|
204
|
+
expression: rest_expression,
|
|
205
|
+
update_expression: rest_expression,
|
|
206
|
+
});
|
|
207
|
+
} else {
|
|
208
|
+
_extract_paths(
|
|
209
|
+
assignments,
|
|
210
|
+
element.argument,
|
|
211
|
+
rest_expression,
|
|
212
|
+
rest_expression,
|
|
213
|
+
has_default_value,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
/** @type {DestructuredAssignment['expression']} */
|
|
218
|
+
const array_expression = (object) => b.member(expression(object), b.literal(i), true);
|
|
219
|
+
_extract_paths(
|
|
220
|
+
assignments,
|
|
221
|
+
element,
|
|
222
|
+
array_expression,
|
|
223
|
+
array_expression,
|
|
224
|
+
has_default_value,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
break;
|
|
231
|
+
|
|
232
|
+
case 'AssignmentPattern': {
|
|
233
|
+
/** @type {DestructuredAssignment['expression']} */
|
|
234
|
+
const fallback_expression = (object) => build_fallback(expression(object), param.right);
|
|
235
|
+
|
|
236
|
+
if (param.left.type === 'Identifier') {
|
|
237
|
+
assignments.push({
|
|
238
|
+
node: param.left,
|
|
239
|
+
is_rest: false,
|
|
240
|
+
has_default_value: true,
|
|
241
|
+
expression: fallback_expression,
|
|
242
|
+
update_expression,
|
|
243
|
+
});
|
|
244
|
+
} else {
|
|
245
|
+
_extract_paths(assignments, param.left, fallback_expression, update_expression, true);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return assignments;
|
|
202
253
|
}
|
|
203
254
|
|
|
255
|
+
/**
|
|
256
|
+
* @param {AST.Expression} expression
|
|
257
|
+
* @param {AST.Expression} fallback
|
|
258
|
+
*/
|
|
204
259
|
export function build_fallback(expression, fallback) {
|
|
205
|
-
|
|
260
|
+
return b.call('_$_.fallback', expression, fallback);
|
|
206
261
|
}
|
|
207
262
|
|
|
208
263
|
/**
|
|
209
|
-
* @param {
|
|
210
|
-
* @param {
|
|
211
|
-
* @param {
|
|
264
|
+
* @param {AST.AssignmentOperator} operator
|
|
265
|
+
* @param {AST.Identifier | AST.MemberExpression} left
|
|
266
|
+
* @param {AST.Expression} right
|
|
212
267
|
*/
|
|
213
268
|
export function build_assignment_value(operator, left, right) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
269
|
+
return operator === '='
|
|
270
|
+
? right
|
|
271
|
+
: // turn something like x += 1 into x = x + 1
|
|
272
|
+
b.binary(/** @type {AST.BinaryOperator} */ (operator.slice(0, -1)), left, right);
|
|
218
273
|
}
|