ripple 0.1.1 → 0.2.0
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/LICENSE +21 -0
- package/package.json +56 -24
- package/src/ai.js +292 -0
- package/src/compiler/errors.js +26 -0
- package/src/compiler/index.js +26 -0
- package/src/compiler/phases/1-parse/index.js +543 -0
- package/src/compiler/phases/1-parse/style.js +566 -0
- package/src/compiler/phases/2-analyze/index.js +509 -0
- package/src/compiler/phases/2-analyze/prune.js +572 -0
- package/src/compiler/phases/3-transform/index.js +1572 -0
- package/src/compiler/phases/3-transform/segments.js +91 -0
- package/src/compiler/phases/3-transform/stylesheet.js +372 -0
- package/src/compiler/scope.js +421 -0
- package/src/compiler/utils.js +552 -0
- package/src/constants.js +4 -0
- package/src/jsx-runtime.d.ts +94 -0
- package/src/jsx-runtime.js +46 -0
- package/src/runtime/array.js +215 -0
- package/src/runtime/index.js +39 -0
- package/src/runtime/internal/client/blocks.js +247 -0
- package/src/runtime/internal/client/constants.js +23 -0
- package/src/runtime/internal/client/events.js +223 -0
- package/src/runtime/internal/client/for.js +388 -0
- package/src/runtime/internal/client/if.js +35 -0
- package/src/runtime/internal/client/index.js +53 -0
- package/src/runtime/internal/client/operations.js +72 -0
- package/src/runtime/internal/client/portal.js +33 -0
- package/src/runtime/internal/client/render.js +156 -0
- package/src/runtime/internal/client/runtime.js +909 -0
- package/src/runtime/internal/client/template.js +51 -0
- package/src/runtime/internal/client/try.js +139 -0
- package/src/runtime/internal/client/utils.js +16 -0
- package/src/utils/ast.js +214 -0
- package/src/utils/builders.js +733 -0
- package/src/utils/patterns.js +23 -0
- package/src/utils/sanitize_template_string.js +7 -0
- package/test-mappings.js +0 -0
- package/types/index.d.ts +2 -0
- package/.npmignore +0 -2
- package/History.md +0 -3
- package/Readme.md +0 -151
- package/lib/exec/index.js +0 -60
- package/ripple.js +0 -645
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
import * as acorn from 'acorn';
|
|
2
|
+
import { tsPlugin } from 'acorn-typescript';
|
|
3
|
+
import { parse_style } from './style.js';
|
|
4
|
+
|
|
5
|
+
const parser = acorn.Parser.extend(tsPlugin({ allowSatisfies: true }), RipplePlugin());
|
|
6
|
+
|
|
7
|
+
function RipplePlugin(config) {
|
|
8
|
+
return (Parser) => {
|
|
9
|
+
const original = acorn.Parser.prototype;
|
|
10
|
+
const tt = Parser.tokTypes || acorn.tokTypes;
|
|
11
|
+
const tc = Parser.tokContexts || acorn.tokContexts;
|
|
12
|
+
|
|
13
|
+
class RippleParser extends Parser {
|
|
14
|
+
#path = [];
|
|
15
|
+
|
|
16
|
+
shouldParseExportStatement() {
|
|
17
|
+
if (super.shouldParseExportStatement()) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (this.value === 'component' || this.value === 'fragment') {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return this.type.keyword === 'var';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
jsx_parseExpressionContainer() {
|
|
27
|
+
const tok = this.acornTypeScript.tokTypes;
|
|
28
|
+
let node = this.startNode();
|
|
29
|
+
this.next();
|
|
30
|
+
|
|
31
|
+
if (this.type === tok.at) {
|
|
32
|
+
this.next();
|
|
33
|
+
|
|
34
|
+
if (this.value === 'fragment') {
|
|
35
|
+
node.decorator = 'fragment';
|
|
36
|
+
this.next();
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error(`Invalid syntax @` + this.value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
node.expression =
|
|
43
|
+
this.type === tt.braceR ? this.jsx_parseEmptyExpression() : this.parseExpression();
|
|
44
|
+
this.expect(tt.braceR);
|
|
45
|
+
return this.finishNode(node, 'JSXExpressionContainer');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
jsx_parseTupleContainer() {
|
|
49
|
+
var t = this.startNode();
|
|
50
|
+
return (
|
|
51
|
+
this.next(),
|
|
52
|
+
(t.expression =
|
|
53
|
+
this.type === tt.bracketR ? this.jsx_parseEmptyExpression() : this.parseExpression()),
|
|
54
|
+
this.expect(tt.bracketR),
|
|
55
|
+
this.finishNode(t, 'JSXExpressionContainer')
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
jsx_parseAttribute() {
|
|
60
|
+
let node = this.startNode();
|
|
61
|
+
if (this.eat(tt.braceL)) {
|
|
62
|
+
if (this.lookahead().type === tt.ellipsis) {
|
|
63
|
+
this.expect(tt.ellipsis);
|
|
64
|
+
node.argument = this.parseMaybeAssign();
|
|
65
|
+
this.expect(tt.braceR);
|
|
66
|
+
return this.finishNode(node, 'SpreadAttribute');
|
|
67
|
+
} else {
|
|
68
|
+
const id = this.parseIdentNode();
|
|
69
|
+
this.finishNode(id, 'Identifier');
|
|
70
|
+
node.name = id;
|
|
71
|
+
node.value = id;
|
|
72
|
+
this.next();
|
|
73
|
+
this.expect(tt.braceR);
|
|
74
|
+
return this.finishNode(node, 'Attribute');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
node.name = this.jsx_parseNamespacedName();
|
|
78
|
+
node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null;
|
|
79
|
+
return this.finishNode(node, 'JSXAttribute');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
jsx_parseAttributeValue() {
|
|
83
|
+
const tok = this.acornTypeScript.tokTypes;
|
|
84
|
+
|
|
85
|
+
switch (this.type) {
|
|
86
|
+
case tt.braceL:
|
|
87
|
+
var t = this.jsx_parseExpressionContainer();
|
|
88
|
+
return (
|
|
89
|
+
'JSXEmptyExpression' === t.expression.type &&
|
|
90
|
+
this.raise(t.start, 'attributes must only be assigned a non-empty expression'),
|
|
91
|
+
t
|
|
92
|
+
);
|
|
93
|
+
// case tt.bracketL:
|
|
94
|
+
// var t = this.jsx_parseTupleContainer();
|
|
95
|
+
// return (
|
|
96
|
+
// 'JSXEmptyExpression' === t.expression.type &&
|
|
97
|
+
// this.raise(t.start, 'attributes must only be assigned a non-empty expression'),
|
|
98
|
+
// t
|
|
99
|
+
// );
|
|
100
|
+
case tok.jsxTagStart:
|
|
101
|
+
case tt.string:
|
|
102
|
+
return this.parseExprAtom();
|
|
103
|
+
default:
|
|
104
|
+
this.raise(this.start, 'value should be either an expression or a quoted text');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
parseTryStatement(node) {
|
|
109
|
+
this.next();
|
|
110
|
+
node.block = this.parseBlock();
|
|
111
|
+
node.handler = null;
|
|
112
|
+
if (this.type === tt._catch) {
|
|
113
|
+
var clause = this.startNode();
|
|
114
|
+
this.next();
|
|
115
|
+
if (this.eat(tt.parenL)) {
|
|
116
|
+
clause.param = this.parseCatchClauseParam();
|
|
117
|
+
} else {
|
|
118
|
+
if (this.options.ecmaVersion < 10) {
|
|
119
|
+
this.unexpected();
|
|
120
|
+
}
|
|
121
|
+
clause.param = null;
|
|
122
|
+
this.enterScope(0);
|
|
123
|
+
}
|
|
124
|
+
clause.body = this.parseBlock(false);
|
|
125
|
+
this.exitScope();
|
|
126
|
+
node.handler = this.finishNode(clause, 'CatchClause');
|
|
127
|
+
}
|
|
128
|
+
node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null;
|
|
129
|
+
|
|
130
|
+
if (this.value === 'async') {
|
|
131
|
+
this.next();
|
|
132
|
+
node.async = this.parseBlock();
|
|
133
|
+
} else {
|
|
134
|
+
node.async = null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!node.handler && !node.finalizer && !node.async) {
|
|
138
|
+
this.raise(node.start, 'Missing catch or finally clause');
|
|
139
|
+
}
|
|
140
|
+
return this.finishNode(node, 'TryStatement');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
jsx_readToken() {
|
|
144
|
+
let out = '',
|
|
145
|
+
chunkStart = this.pos;
|
|
146
|
+
const tok = this.acornTypeScript.tokTypes;
|
|
147
|
+
|
|
148
|
+
for (;;) {
|
|
149
|
+
if (this.pos >= this.input.length) this.raise(this.start, 'Unterminated JSX contents');
|
|
150
|
+
let ch = this.input.charCodeAt(this.pos);
|
|
151
|
+
|
|
152
|
+
switch (ch) {
|
|
153
|
+
case 60: // '<'
|
|
154
|
+
case 123: // '{'
|
|
155
|
+
if (ch === 60 && this.exprAllowed) {
|
|
156
|
+
++this.pos;
|
|
157
|
+
return this.finishToken(tok.jsxTagStart);
|
|
158
|
+
}
|
|
159
|
+
if (ch === 123 && this.exprAllowed) {
|
|
160
|
+
return this.getTokenFromCode(ch);
|
|
161
|
+
}
|
|
162
|
+
debugger;
|
|
163
|
+
throw new Error('TODO: Invalid syntax');
|
|
164
|
+
|
|
165
|
+
case 47: // '/'
|
|
166
|
+
// Check if this is a comment (// or /*)
|
|
167
|
+
if (this.input.charCodeAt(this.pos + 1) === 47) {
|
|
168
|
+
// '//'
|
|
169
|
+
// Line comment - handle it properly
|
|
170
|
+
const commentStart = this.pos;
|
|
171
|
+
const startLoc = this.curPosition();
|
|
172
|
+
this.pos += 2;
|
|
173
|
+
|
|
174
|
+
let commentText = '';
|
|
175
|
+
while (this.pos < this.input.length) {
|
|
176
|
+
const nextCh = this.input.charCodeAt(this.pos);
|
|
177
|
+
if (acorn.isNewLine(nextCh)) break;
|
|
178
|
+
commentText += this.input[this.pos];
|
|
179
|
+
this.pos++;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const commentEnd = this.pos;
|
|
183
|
+
const endLoc = this.curPosition();
|
|
184
|
+
|
|
185
|
+
// Call onComment if it exists
|
|
186
|
+
if (this.options.onComment) {
|
|
187
|
+
this.options.onComment(
|
|
188
|
+
false,
|
|
189
|
+
commentText,
|
|
190
|
+
commentStart,
|
|
191
|
+
commentEnd,
|
|
192
|
+
startLoc,
|
|
193
|
+
endLoc
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Continue processing from current position
|
|
198
|
+
break;
|
|
199
|
+
} else if (this.input.charCodeAt(this.pos + 1) === 42) {
|
|
200
|
+
// '/*'
|
|
201
|
+
// Block comment - handle it properly
|
|
202
|
+
const commentStart = this.pos;
|
|
203
|
+
const startLoc = this.curPosition();
|
|
204
|
+
this.pos += 2;
|
|
205
|
+
|
|
206
|
+
let commentText = '';
|
|
207
|
+
while (this.pos < this.input.length - 1) {
|
|
208
|
+
if (
|
|
209
|
+
this.input.charCodeAt(this.pos) === 42 &&
|
|
210
|
+
this.input.charCodeAt(this.pos + 1) === 47
|
|
211
|
+
) {
|
|
212
|
+
this.pos += 2;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
commentText += this.input[this.pos];
|
|
216
|
+
this.pos++;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const commentEnd = this.pos;
|
|
220
|
+
const endLoc = this.curPosition();
|
|
221
|
+
|
|
222
|
+
// Call onComment if it exists
|
|
223
|
+
if (this.options.onComment) {
|
|
224
|
+
this.options.onComment(
|
|
225
|
+
true,
|
|
226
|
+
commentText,
|
|
227
|
+
commentStart,
|
|
228
|
+
commentEnd,
|
|
229
|
+
startLoc,
|
|
230
|
+
endLoc
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Continue processing from current position
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
// If not a comment, fall through to default case
|
|
238
|
+
this.context.push(tc.b_stat);
|
|
239
|
+
this.exprAllowed = true;
|
|
240
|
+
return original.readToken.call(this, ch);
|
|
241
|
+
|
|
242
|
+
case 38: // '&'
|
|
243
|
+
out += this.input.slice(chunkStart, this.pos);
|
|
244
|
+
out += this.jsx_readEntity();
|
|
245
|
+
chunkStart = this.pos;
|
|
246
|
+
break;
|
|
247
|
+
|
|
248
|
+
case 62: // '>'
|
|
249
|
+
case 125: {
|
|
250
|
+
// '}'
|
|
251
|
+
if (
|
|
252
|
+
ch === 125 &&
|
|
253
|
+
(this.#path.at(-1).type === 'Component' || this.#path.at(-1).type === 'Fragment')
|
|
254
|
+
) {
|
|
255
|
+
return original.readToken.call(this, ch);
|
|
256
|
+
}
|
|
257
|
+
this.raise(
|
|
258
|
+
this.pos,
|
|
259
|
+
'Unexpected token `' +
|
|
260
|
+
this.input[this.pos] +
|
|
261
|
+
'`. Did you mean `' +
|
|
262
|
+
(ch === 62 ? '>' : '}') +
|
|
263
|
+
'` or ' +
|
|
264
|
+
'`{"' +
|
|
265
|
+
this.input[this.pos] +
|
|
266
|
+
'"}' +
|
|
267
|
+
'`?'
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
default:
|
|
272
|
+
if (acorn.isNewLine(ch)) {
|
|
273
|
+
out += this.input.slice(chunkStart, this.pos);
|
|
274
|
+
out += this.jsx_readNewLine(true);
|
|
275
|
+
chunkStart = this.pos;
|
|
276
|
+
} else if (ch === 32) {
|
|
277
|
+
++this.pos;
|
|
278
|
+
} else {
|
|
279
|
+
this.context.push(tc.b_stat);
|
|
280
|
+
this.exprAllowed = true;
|
|
281
|
+
return original.readToken.call(this, ch);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
parseElement() {
|
|
288
|
+
const tok = this.acornTypeScript.tokTypes;
|
|
289
|
+
// Adjust the start so we capture the `<` as part of the element
|
|
290
|
+
const prev_pos = this.pos;
|
|
291
|
+
this.pos = this.start - 1;
|
|
292
|
+
const position = this.curPosition();
|
|
293
|
+
this.pos = prev_pos;
|
|
294
|
+
|
|
295
|
+
const element = this.startNode();
|
|
296
|
+
element.start = position.index;
|
|
297
|
+
element.loc.start = position;
|
|
298
|
+
element.type = 'Element';
|
|
299
|
+
this.#path.push(element);
|
|
300
|
+
element.children = [];
|
|
301
|
+
const open = this.jsx_parseOpeningElementAt();
|
|
302
|
+
for (const attr of open.attributes) {
|
|
303
|
+
if (attr.type === 'JSXAttribute') {
|
|
304
|
+
attr.type = 'Attribute';
|
|
305
|
+
if (attr.name.type === 'JSXIdentifier') {
|
|
306
|
+
attr.name.type = 'Identifier';
|
|
307
|
+
}
|
|
308
|
+
if (attr.value.type === 'JSXExpressionContainer') {
|
|
309
|
+
attr.value = attr.value.expression;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (open.name.type === 'JSXIdentifier') {
|
|
314
|
+
open.name.type = 'Identifier';
|
|
315
|
+
}
|
|
316
|
+
element.id = open.name;
|
|
317
|
+
element.id.type = 'Identifier';
|
|
318
|
+
element.attributes = open.attributes;
|
|
319
|
+
element.selfClosing = open.selfClosing;
|
|
320
|
+
element.metadata = {};
|
|
321
|
+
|
|
322
|
+
if (element.selfClosing) {
|
|
323
|
+
this.#path.pop();
|
|
324
|
+
if (this.type !== tok.jsxTagStart) {
|
|
325
|
+
// Eat the closing `/>`
|
|
326
|
+
this.pos--;
|
|
327
|
+
this.next();
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
if (open.name.name === 'style') {
|
|
331
|
+
const start = this.start;
|
|
332
|
+
const input = this.input.slice(start);
|
|
333
|
+
const end = input.indexOf('</style>');
|
|
334
|
+
const content = input.slice(0, end);
|
|
335
|
+
|
|
336
|
+
const component = this.#path.findLast((n) => n.type === 'Component');
|
|
337
|
+
if (component.css !== null) {
|
|
338
|
+
throw new Error('Components can only have one style tag');
|
|
339
|
+
}
|
|
340
|
+
component.css = parse_style(content);
|
|
341
|
+
|
|
342
|
+
this.pos = start + end + 1;
|
|
343
|
+
this.type = tok.jsxTagStart;
|
|
344
|
+
this.next();
|
|
345
|
+
if (this.value === '/') {
|
|
346
|
+
this.next();
|
|
347
|
+
this.jsx_parseElementName();
|
|
348
|
+
this.exprAllowed = true;
|
|
349
|
+
this.#path.pop();
|
|
350
|
+
this.next();
|
|
351
|
+
}
|
|
352
|
+
return null;
|
|
353
|
+
} else {
|
|
354
|
+
this.parseTemplateBody(element.children);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
this.finishNode(element, 'Element');
|
|
359
|
+
return element;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
parseTemplateBody(body) {
|
|
363
|
+
var inside_func =
|
|
364
|
+
this.context.some((n) => n.token === 'function') || this.scopeStack.length > 1;
|
|
365
|
+
|
|
366
|
+
if (!inside_func) {
|
|
367
|
+
if (this.type.label === 'return') {
|
|
368
|
+
throw new Error('`return` statements are not allowed in components');
|
|
369
|
+
}
|
|
370
|
+
if (this.type.label === 'continue') {
|
|
371
|
+
throw new Error('`continue` statements are not allowed in components');
|
|
372
|
+
}
|
|
373
|
+
if (this.type.label === 'break') {
|
|
374
|
+
throw new Error('`break` statements are not allowed in components');
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (this.type.label === '{') {
|
|
379
|
+
const node = this.jsx_parseExpressionContainer();
|
|
380
|
+
node.type = node.decorator === 'fragment' ? 'RenderFragment' : 'Text';
|
|
381
|
+
if (node.decorator === 'fragment' && node.expression.type !== 'CallExpression') {
|
|
382
|
+
throw new Error('{@fragment} must be a function call');
|
|
383
|
+
}
|
|
384
|
+
body.push(node);
|
|
385
|
+
} else if (this.type.label === '}') {
|
|
386
|
+
return;
|
|
387
|
+
} else if (this.type.label === 'jsxTagStart') {
|
|
388
|
+
this.next();
|
|
389
|
+
if (this.value === '/') {
|
|
390
|
+
this.next();
|
|
391
|
+
this.jsx_parseElementName();
|
|
392
|
+
this.exprAllowed = true;
|
|
393
|
+
this.#path.pop();
|
|
394
|
+
this.next();
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const node = this.parseElement();
|
|
398
|
+
if (node !== null) {
|
|
399
|
+
body.push(node);
|
|
400
|
+
}
|
|
401
|
+
} else {
|
|
402
|
+
const node = this.parseStatement(null);
|
|
403
|
+
body.push(node);
|
|
404
|
+
}
|
|
405
|
+
this.parseTemplateBody(body);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
parseStatement(context, topLevel, exports) {
|
|
409
|
+
const tok = this.acornTypeScript.tokContexts;
|
|
410
|
+
|
|
411
|
+
if (
|
|
412
|
+
context !== 'for' &&
|
|
413
|
+
context !== 'if' &&
|
|
414
|
+
this.context.at(-1) === tc.b_stat &&
|
|
415
|
+
this.type === tt.braceL &&
|
|
416
|
+
this.context.some((c) => c === tok.tc_expr)
|
|
417
|
+
) {
|
|
418
|
+
this.next();
|
|
419
|
+
const node = this.jsx_parseExpressionContainer();
|
|
420
|
+
node.type = 'Text';
|
|
421
|
+
this.next();
|
|
422
|
+
this.context.pop();
|
|
423
|
+
this.context.pop();
|
|
424
|
+
return node;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (this.value === 'component') {
|
|
428
|
+
const node = this.startNode();
|
|
429
|
+
node.type = 'Component';
|
|
430
|
+
node.css = null;
|
|
431
|
+
this.next();
|
|
432
|
+
this.enterScope(0);
|
|
433
|
+
node.id = this.parseIdent();
|
|
434
|
+
this.parseFunctionParams(node);
|
|
435
|
+
this.eat(tt.braceL);
|
|
436
|
+
node.body = [];
|
|
437
|
+
this.#path.push(node);
|
|
438
|
+
|
|
439
|
+
this.parseTemplateBody(node.body);
|
|
440
|
+
|
|
441
|
+
this.#path.pop();
|
|
442
|
+
this.exitScope();
|
|
443
|
+
|
|
444
|
+
this.next();
|
|
445
|
+
this.finishNode(node, 'Component');
|
|
446
|
+
this.awaitPos = 0;
|
|
447
|
+
|
|
448
|
+
return node;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (this.value === 'fragment') {
|
|
452
|
+
const node = this.startNode();
|
|
453
|
+
node.type = 'Fragment';
|
|
454
|
+
this.next();
|
|
455
|
+
this.enterScope(0);
|
|
456
|
+
node.id = this.parseIdent();
|
|
457
|
+
this.parseFunctionParams(node);
|
|
458
|
+
this.eat(tt.braceL);
|
|
459
|
+
node.body = [];
|
|
460
|
+
this.#path.push(node);
|
|
461
|
+
|
|
462
|
+
this.parseTemplateBody(node.body);
|
|
463
|
+
|
|
464
|
+
this.#path.pop();
|
|
465
|
+
this.exitScope();
|
|
466
|
+
|
|
467
|
+
this.finishNode(node, 'Fragment');
|
|
468
|
+
this.next();
|
|
469
|
+
this.awaitPos = 0;
|
|
470
|
+
|
|
471
|
+
return node;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return super.parseStatement(context, topLevel, exports);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
parseBlock(createNewLexicalScope, node, exitStrict) {
|
|
478
|
+
const parent = this.#path.at(-1);
|
|
479
|
+
|
|
480
|
+
if (
|
|
481
|
+
parent?.type === 'Component' ||
|
|
482
|
+
parent?.type === 'Fragment' ||
|
|
483
|
+
parent?.type === 'Element'
|
|
484
|
+
) {
|
|
485
|
+
if (createNewLexicalScope === void 0) createNewLexicalScope = true;
|
|
486
|
+
if (node === void 0) node = this.startNode();
|
|
487
|
+
|
|
488
|
+
node.body = [];
|
|
489
|
+
this.expect(tt.braceL);
|
|
490
|
+
if (createNewLexicalScope) {
|
|
491
|
+
this.enterScope(0);
|
|
492
|
+
}
|
|
493
|
+
this.parseTemplateBody(node.body);
|
|
494
|
+
|
|
495
|
+
if (exitStrict) {
|
|
496
|
+
this.strict = false;
|
|
497
|
+
}
|
|
498
|
+
this.exprAllowed = true;
|
|
499
|
+
|
|
500
|
+
this.next();
|
|
501
|
+
if (createNewLexicalScope) {
|
|
502
|
+
this.exitScope();
|
|
503
|
+
}
|
|
504
|
+
return this.finishNode(node, 'BlockStatement');
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return super.parseBlock(createNewLexicalScope, node, exitStrict);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return RippleParser;
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export function parse(source) {
|
|
516
|
+
const comments = [];
|
|
517
|
+
let ast;
|
|
518
|
+
|
|
519
|
+
try {
|
|
520
|
+
ast = parser.parse(source, {
|
|
521
|
+
sourceType: 'module',
|
|
522
|
+
ecmaVersion: 13,
|
|
523
|
+
locations: true,
|
|
524
|
+
onComment: (block, text, start, end, startLoc, endLoc) => {
|
|
525
|
+
comments.push({
|
|
526
|
+
type: block ? 'Block' : 'Line',
|
|
527
|
+
value: text,
|
|
528
|
+
start,
|
|
529
|
+
end,
|
|
530
|
+
loc: {
|
|
531
|
+
start: startLoc,
|
|
532
|
+
end: endLoc
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
} catch (e) {
|
|
538
|
+
throw e;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
ast.comments = comments;
|
|
542
|
+
return ast;
|
|
543
|
+
}
|