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/compiler/scope.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/** @import {
|
|
2
|
-
/** @import
|
|
3
|
-
/** @import { RippleNode } from '#compiler' */
|
|
1
|
+
/** @import { Binding, ScopeInterface, ScopeRoot as ScopeRootInterface } from '#compiler' */
|
|
2
|
+
/** @import * as AST from 'estree' */
|
|
4
3
|
|
|
5
4
|
import is_reference from 'is-reference';
|
|
6
5
|
import { extract_identifiers, object, unwrap_pattern } from '../utils/ast.js';
|
|
@@ -8,79 +7,32 @@ import { walk } from 'zimmerframe';
|
|
|
8
7
|
import { is_reserved } from './utils.js';
|
|
9
8
|
import * as b from '../utils/builders.js';
|
|
10
9
|
|
|
11
|
-
export class Binding {
|
|
12
|
-
/** @type {Scope} */
|
|
13
|
-
scope;
|
|
14
|
-
|
|
15
|
-
/** @type {Identifier} */
|
|
16
|
-
node;
|
|
17
|
-
|
|
18
|
-
/** @type {BindingKind} */
|
|
19
|
-
kind;
|
|
20
|
-
|
|
21
|
-
/** @type {DeclarationKind} */
|
|
22
|
-
declaration_kind;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* What the value was initialized with
|
|
26
|
-
* @type {null | Expression | FunctionDeclaration | ClassDeclaration | ImportDeclaration}
|
|
27
|
-
*/
|
|
28
|
-
initial = null;
|
|
29
|
-
|
|
30
|
-
/** @type {Array<{ node: Identifier; path: RippleNode[] }>} */
|
|
31
|
-
references = [];
|
|
32
|
-
|
|
33
|
-
mutated = false;
|
|
34
|
-
reassigned = false;
|
|
35
|
-
is_called = false;
|
|
36
|
-
metadata = null;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {Scope} scope
|
|
40
|
-
* @param {Identifier} node
|
|
41
|
-
* @param {BindingKind} kind
|
|
42
|
-
* @param {DeclarationKind} declaration_kind
|
|
43
|
-
* @param {Binding['initial']} initial
|
|
44
|
-
*/
|
|
45
|
-
constructor(scope, node, kind, declaration_kind, initial) {
|
|
46
|
-
this.scope = scope;
|
|
47
|
-
this.node = node;
|
|
48
|
-
this.initial = initial;
|
|
49
|
-
this.kind = kind;
|
|
50
|
-
this.declaration_kind = declaration_kind;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
get updated() {
|
|
54
|
-
return this.mutated || this.reassigned;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
10
|
/**
|
|
59
11
|
* Create scopes for an AST
|
|
60
|
-
* @param {Node} ast - The AST to create scopes for
|
|
61
|
-
* @param {
|
|
62
|
-
* @param {
|
|
63
|
-
* @returns {{ scope:
|
|
12
|
+
* @param {AST.Node} ast - The AST to create scopes for
|
|
13
|
+
* @param {ScopeRootInterface} root - Root scope manager
|
|
14
|
+
* @param {ScopeInterface | null} parent - Parent scope
|
|
15
|
+
* @returns {{ scope: ScopeInterface, scopes: Map<AST.Node, ScopeInterface> }} Scope information
|
|
64
16
|
*/
|
|
65
17
|
export function create_scopes(ast, root, parent) {
|
|
66
|
-
/** @typedef {{ scope:
|
|
18
|
+
/** @typedef {{ scope: ScopeInterface }} State */
|
|
67
19
|
|
|
68
|
-
/** @type {Map<
|
|
20
|
+
/** @type {Map<AST.Node, ScopeInterface>} */
|
|
69
21
|
const scopes = new Map();
|
|
70
22
|
const scope = new Scope(root, parent, false);
|
|
71
23
|
scopes.set(ast, scope);
|
|
72
24
|
|
|
73
25
|
/** @type {State} */
|
|
74
26
|
const state = { scope };
|
|
75
|
-
/** @type {Array<[
|
|
27
|
+
/** @type {Array<[ScopeInterface, { node: AST.Identifier, path: AST.Node[] }]>} */
|
|
76
28
|
const references = [];
|
|
77
|
-
/** @type {Array<[
|
|
29
|
+
/** @type {Array<[ScopeInterface, AST.Pattern | AST.MemberExpression]>} */
|
|
78
30
|
const updates = [];
|
|
79
31
|
|
|
80
32
|
/**
|
|
81
33
|
* Add parameters to scope
|
|
82
|
-
* @param {
|
|
83
|
-
* @param {Pattern[]} params - Parameter nodes
|
|
34
|
+
* @param {ScopeInterface} scope - The scope to add parameters to
|
|
35
|
+
* @param {AST.Pattern[]} params - Parameter nodes
|
|
84
36
|
*/
|
|
85
37
|
function add_params(scope, params) {
|
|
86
38
|
for (const param of params) {
|
|
@@ -92,7 +44,7 @@ export function create_scopes(ast, root, parent) {
|
|
|
92
44
|
|
|
93
45
|
/**
|
|
94
46
|
* Create a block scope
|
|
95
|
-
* @param {
|
|
47
|
+
* @param {AST.Node} node - AST node
|
|
96
48
|
* @param {{ state: any, next: Function }} context - Visitor context
|
|
97
49
|
*/
|
|
98
50
|
const create_block_scope = (node, { state, next }) => {
|
|
@@ -108,13 +60,13 @@ export function create_scopes(ast, root, parent) {
|
|
|
108
60
|
next({ scope });
|
|
109
61
|
};
|
|
110
62
|
|
|
111
|
-
walk(/** @type {
|
|
63
|
+
walk(/** @type {AST.Node} */ (ast), state, {
|
|
112
64
|
// references
|
|
113
65
|
Identifier(node, { path, state }) {
|
|
114
66
|
const parent = path.at(-1);
|
|
115
67
|
if (
|
|
116
68
|
parent &&
|
|
117
|
-
is_reference(node, /** @type {Node} */ (parent)) &&
|
|
69
|
+
is_reference(node, /** @type {AST.Node} */ (parent)) &&
|
|
118
70
|
// TSTypeAnnotation, TSInterfaceDeclaration etc - these are normally already filtered out,
|
|
119
71
|
// but for the migration they aren't, so we need to filter them out here
|
|
120
72
|
// TODO -> once migration script is gone we can remove this check
|
|
@@ -130,7 +82,10 @@ export function create_scopes(ast, root, parent) {
|
|
|
130
82
|
},
|
|
131
83
|
|
|
132
84
|
UpdateExpression(node, { state, next }) {
|
|
133
|
-
updates.push([
|
|
85
|
+
updates.push([
|
|
86
|
+
state.scope,
|
|
87
|
+
/** @type {AST.Identifier | AST.MemberExpression} */ (node.argument),
|
|
88
|
+
]);
|
|
134
89
|
next();
|
|
135
90
|
},
|
|
136
91
|
|
|
@@ -141,7 +96,7 @@ export function create_scopes(ast, root, parent) {
|
|
|
141
96
|
},
|
|
142
97
|
|
|
143
98
|
/**
|
|
144
|
-
* @param {Component} node
|
|
99
|
+
* @param {AST.Component} node
|
|
145
100
|
* @param {Object} context
|
|
146
101
|
* @param {any} context.state
|
|
147
102
|
* @param {Function} context.next
|
|
@@ -160,7 +115,7 @@ export function create_scopes(ast, root, parent) {
|
|
|
160
115
|
},
|
|
161
116
|
|
|
162
117
|
/**
|
|
163
|
-
* @param {Element} node
|
|
118
|
+
* @param {AST.Element} node
|
|
164
119
|
* @param {Object} context
|
|
165
120
|
* @param {any} context.state
|
|
166
121
|
* @param {Function} context.next
|
|
@@ -290,13 +245,14 @@ export function create_scopes(ast, root, parent) {
|
|
|
290
245
|
};
|
|
291
246
|
}
|
|
292
247
|
|
|
248
|
+
/** @implements {ScopeInterface} */
|
|
293
249
|
export class Scope {
|
|
294
|
-
/** @type {
|
|
250
|
+
/** @type {ScopeRootInterface} */
|
|
295
251
|
root;
|
|
296
252
|
|
|
297
253
|
/**
|
|
298
254
|
* The immediate parent scope
|
|
299
|
-
* @type {
|
|
255
|
+
* @type {ScopeInterface['parent']}
|
|
300
256
|
*/
|
|
301
257
|
parent;
|
|
302
258
|
|
|
@@ -309,45 +265,46 @@ export class Scope {
|
|
|
309
265
|
/**
|
|
310
266
|
* A map of every identifier declared by this scope, and all the
|
|
311
267
|
* identifiers that reference it
|
|
312
|
-
* @type {
|
|
268
|
+
* @type {ScopeInterface['declarations']}
|
|
313
269
|
*/
|
|
314
270
|
declarations = new Map();
|
|
315
271
|
|
|
316
272
|
/**
|
|
317
273
|
* A map of declarators to the bindings they declare
|
|
318
|
-
* @type {
|
|
274
|
+
* @type {ScopeInterface['declarators']}
|
|
319
275
|
*/
|
|
320
276
|
declarators = new Map();
|
|
321
277
|
|
|
322
278
|
/**
|
|
323
279
|
* A set of all the names referenced with this scope
|
|
324
280
|
* — useful for generating unique names
|
|
325
|
-
* @type {
|
|
281
|
+
* @type {ScopeInterface['references']}
|
|
326
282
|
*/
|
|
327
283
|
references = new Map();
|
|
328
284
|
|
|
329
285
|
/**
|
|
330
286
|
* The scope depth allows us to determine if a state variable is referenced in its own scope,
|
|
331
287
|
* which is usually an error. Block statements do not increase this value
|
|
288
|
+
* @type {ScopeInterface['function_depth']}
|
|
332
289
|
*/
|
|
333
290
|
function_depth = 0;
|
|
334
291
|
|
|
335
292
|
/**
|
|
336
293
|
* If tracing of reactive dependencies is enabled for this scope
|
|
337
|
-
* @type {
|
|
294
|
+
* @type {ScopeInterface['tracing']}
|
|
338
295
|
*/
|
|
339
296
|
tracing = null;
|
|
340
297
|
|
|
341
298
|
/**
|
|
342
299
|
* Is this scope a top-level server block scope
|
|
343
|
-
* @type {
|
|
300
|
+
* @type {ScopeInterface['server_block']}
|
|
344
301
|
*/
|
|
345
302
|
server_block = false;
|
|
346
303
|
|
|
347
304
|
/**
|
|
348
305
|
*
|
|
349
|
-
* @param {
|
|
350
|
-
* @param {
|
|
306
|
+
* @param {ScopeRootInterface} root
|
|
307
|
+
* @param {ScopeInterface | null} parent
|
|
351
308
|
* @param {boolean} porous
|
|
352
309
|
*/
|
|
353
310
|
constructor(root, parent, porous) {
|
|
@@ -358,11 +315,7 @@ export class Scope {
|
|
|
358
315
|
}
|
|
359
316
|
|
|
360
317
|
/**
|
|
361
|
-
* @
|
|
362
|
-
* @param {Binding['kind']} kind
|
|
363
|
-
* @param {DeclarationKind} declaration_kind
|
|
364
|
-
* @param {null | Expression | FunctionDeclaration | ClassDeclaration | ImportDeclaration} initial
|
|
365
|
-
* @returns {Binding}
|
|
318
|
+
* @type {ScopeInterface['declare']}
|
|
366
319
|
*/
|
|
367
320
|
declare(node, kind, declaration_kind, initial = null) {
|
|
368
321
|
if (this.parent) {
|
|
@@ -403,17 +356,19 @@ export class Scope {
|
|
|
403
356
|
return binding;
|
|
404
357
|
}
|
|
405
358
|
|
|
359
|
+
/**
|
|
360
|
+
* @type {ScopeInterface['child']}
|
|
361
|
+
*/
|
|
406
362
|
child(porous = false) {
|
|
407
363
|
return new Scope(this.root, this, porous);
|
|
408
364
|
}
|
|
409
365
|
|
|
410
366
|
/**
|
|
411
|
-
* @
|
|
412
|
-
* @returns {string}
|
|
367
|
+
* @type {ScopeInterface['generate']}
|
|
413
368
|
*/
|
|
414
369
|
generate(preferred_name) {
|
|
415
370
|
if (this.#porous) {
|
|
416
|
-
return /** @type {
|
|
371
|
+
return /** @type {ScopeInterface} */ (this.parent).generate(preferred_name);
|
|
417
372
|
}
|
|
418
373
|
|
|
419
374
|
preferred_name = preferred_name.replace(/[^a-zA-Z0-9_$]/g, '_').replace(/^[0-9]/, '_');
|
|
@@ -435,16 +390,14 @@ export class Scope {
|
|
|
435
390
|
}
|
|
436
391
|
|
|
437
392
|
/**
|
|
438
|
-
* @
|
|
439
|
-
* @returns {Binding | null}
|
|
393
|
+
* @type {ScopeInterface['get']}
|
|
440
394
|
*/
|
|
441
395
|
get(name) {
|
|
442
396
|
return this.declarations.get(name) ?? this.parent?.get(name) ?? null;
|
|
443
397
|
}
|
|
444
398
|
|
|
445
399
|
/**
|
|
446
|
-
* @
|
|
447
|
-
* @returns {Binding[]}
|
|
400
|
+
* @type {ScopeInterface['get_bindings']}
|
|
448
401
|
*/
|
|
449
402
|
get_bindings(node) {
|
|
450
403
|
const bindings = this.declarators.get(node);
|
|
@@ -455,16 +408,14 @@ export class Scope {
|
|
|
455
408
|
}
|
|
456
409
|
|
|
457
410
|
/**
|
|
458
|
-
* @
|
|
459
|
-
* @returns {Scope | null}
|
|
411
|
+
* @type {ScopeInterface['owner']}
|
|
460
412
|
*/
|
|
461
413
|
owner(name) {
|
|
462
414
|
return this.declarations.has(name) ? this : this.parent && this.parent.owner(name);
|
|
463
415
|
}
|
|
464
416
|
|
|
465
417
|
/**
|
|
466
|
-
* @
|
|
467
|
-
* @param {RippleNode[]} path
|
|
418
|
+
* @type {ScopeInterface['reference']}
|
|
468
419
|
*/
|
|
469
420
|
reference(node, path) {
|
|
470
421
|
path = [...path]; // ensure that mutations to path afterwards don't affect this reference
|
|
@@ -487,12 +438,13 @@ export class Scope {
|
|
|
487
438
|
}
|
|
488
439
|
}
|
|
489
440
|
|
|
441
|
+
/** @implements {ScopeRootInterface} */
|
|
490
442
|
export class ScopeRoot {
|
|
491
|
-
/** @type {
|
|
443
|
+
/** @type {ScopeRootInterface['conflicts']} */
|
|
492
444
|
conflicts = new Set();
|
|
493
445
|
|
|
494
446
|
/**
|
|
495
|
-
* @
|
|
447
|
+
* @type {ScopeRootInterface['unique']}
|
|
496
448
|
*/
|
|
497
449
|
unique(preferred_name) {
|
|
498
450
|
preferred_name = preferred_name.replace(/[^a-zA-Z0-9_$]/g, '_');
|