ripple 0.2.182 → 0.2.184

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