ripple 0.3.13 → 0.3.15

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/package.json +5 -30
  3. package/src/runtime/array.js +38 -38
  4. package/src/runtime/create-subscriber.js +2 -2
  5. package/src/runtime/internal/client/bindings.js +4 -6
  6. package/src/runtime/internal/client/events.js +8 -3
  7. package/src/runtime/internal/client/hmr.js +5 -17
  8. package/src/runtime/internal/client/runtime.js +1 -0
  9. package/src/runtime/internal/server/blocks.js +7 -9
  10. package/src/runtime/internal/server/index.js +14 -22
  11. package/src/runtime/media-query.js +34 -33
  12. package/src/runtime/object.js +7 -10
  13. package/src/runtime/proxy.js +2 -3
  14. package/src/runtime/reactive-value.js +23 -21
  15. package/src/utils/ast.js +1 -1
  16. package/src/utils/attributes.js +43 -0
  17. package/src/utils/builders.js +2 -2
  18. package/tests/client/basic/basic.components.test.rsrx +103 -1
  19. package/tests/client/basic/basic.errors.test.rsrx +1 -1
  20. package/tests/client/basic/basic.styling.test.rsrx +1 -1
  21. package/tests/client/compiler/compiler.assignments.test.rsrx +1 -1
  22. package/tests/client/compiler/compiler.attributes.test.rsrx +1 -1
  23. package/tests/client/compiler/compiler.basic.test.rsrx +51 -14
  24. package/tests/client/compiler/compiler.tracked-access.test.rsrx +1 -1
  25. package/tests/client/compiler/compiler.try-in-function.test.rsrx +1 -1
  26. package/tests/client/compiler/compiler.typescript.test.rsrx +1 -1
  27. package/tests/client/css/global-additional-cases.test.rsrx +1 -1
  28. package/tests/client/css/global-advanced-selectors.test.rsrx +1 -1
  29. package/tests/client/css/global-at-rules.test.rsrx +1 -1
  30. package/tests/client/css/global-basic.test.rsrx +1 -1
  31. package/tests/client/css/global-classes-ids.test.rsrx +1 -1
  32. package/tests/client/css/global-combinators.test.rsrx +1 -1
  33. package/tests/client/css/global-complex-nesting.test.rsrx +1 -1
  34. package/tests/client/css/global-edge-cases.test.rsrx +1 -1
  35. package/tests/client/css/global-keyframes.test.rsrx +1 -1
  36. package/tests/client/css/global-nested.test.rsrx +1 -1
  37. package/tests/client/css/global-pseudo.test.rsrx +1 -1
  38. package/tests/client/css/global-scoping.test.rsrx +1 -1
  39. package/tests/client/css/style-identifier.test.rsrx +1 -1
  40. package/tests/client/return.test.rsrx +1 -1
  41. package/tests/hydration/build-components.js +1 -1
  42. package/tests/server/basic.components.test.rsrx +114 -0
  43. package/tests/server/compiler.test.rsrx +38 -1
  44. package/tests/server/style-identifier.test.rsrx +1 -1
  45. package/tests/setup-server.js +1 -1
  46. package/tests/utils/compiler-compat-config.test.js +1 -1
  47. package/types/index.d.ts +1 -1
  48. package/src/compiler/comment-utils.js +0 -91
  49. package/src/compiler/errors.js +0 -77
  50. package/src/compiler/identifier-utils.js +0 -80
  51. package/src/compiler/index.d.ts +0 -127
  52. package/src/compiler/index.js +0 -89
  53. package/src/compiler/phases/1-parse/index.js +0 -3007
  54. package/src/compiler/phases/1-parse/style.js +0 -704
  55. package/src/compiler/phases/2-analyze/css-analyze.js +0 -160
  56. package/src/compiler/phases/2-analyze/index.js +0 -2208
  57. package/src/compiler/phases/2-analyze/prune.js +0 -1131
  58. package/src/compiler/phases/2-analyze/validation.js +0 -168
  59. package/src/compiler/phases/3-transform/client/index.js +0 -5264
  60. package/src/compiler/phases/3-transform/segments.js +0 -2125
  61. package/src/compiler/phases/3-transform/server/index.js +0 -1749
  62. package/src/compiler/phases/3-transform/stylesheet.js +0 -545
  63. package/src/compiler/scope.js +0 -476
  64. package/src/compiler/source-map-utils.js +0 -358
  65. package/src/compiler/types/acorn.d.ts +0 -11
  66. package/src/compiler/types/estree-jsx.d.ts +0 -11
  67. package/src/compiler/types/estree.d.ts +0 -11
  68. package/src/compiler/types/index.d.ts +0 -1411
  69. package/src/compiler/types/parse.d.ts +0 -1723
  70. package/src/compiler/utils.js +0 -1258
@@ -1,476 +0,0 @@
1
- /**
2
- @import {
3
- Binding,
4
- ScopeInterface,
5
- ScopeRoot as ScopeRootInterface,
6
- Context,
7
- ScopeConstructorInterface,
8
- ScopeConstructorParameters
9
- } from '#compiler';
10
- @import * as AST from 'estree';
11
- */
12
-
13
- import is_reference from 'is-reference';
14
- import { extract_identifiers, object, unwrap_pattern } from '../utils/ast.js';
15
- import { walk } from 'zimmerframe';
16
- import { is_reserved } from './utils.js';
17
- import { error } from './errors.js';
18
- import { IDENTIFIER_OBFUSCATION_PREFIX } from './identifier-utils.js';
19
- import * as b from '../utils/builders.js';
20
-
21
- /**
22
- * Create scopes for an AST
23
- * @param {AST.Node} ast - The AST to create scopes for
24
- * @param {ScopeRootInterface} root - Root scope manager
25
- * @param {ScopeInterface | null} parent - Parent scope
26
- * @param {ScopeConstructorInterface['error_options']} error_options - Error options
27
- * @returns {{ scope: ScopeInterface, scopes: Map<AST.Node, ScopeInterface> }} Scope information
28
- */
29
- export function create_scopes(ast, root, parent, error_options) {
30
- /** @typedef {{ scope: ScopeInterface }} State */
31
-
32
- /** @type {Map<AST.Node, ScopeInterface>} */
33
- const scopes = new Map();
34
- const scope = new Scope(root, parent, false, error_options);
35
- scopes.set(ast, scope);
36
-
37
- /** @type {State} */
38
- const state = { scope };
39
- /** @type {Array<[ScopeInterface, { node: AST.Identifier, path: AST.Node[] }]>} */
40
- const references = [];
41
- /** @type {Array<[ScopeInterface, AST.Pattern | AST.MemberExpression]>} */
42
- const updates = [];
43
-
44
- /**
45
- * Add parameters to scope
46
- * @param {ScopeInterface} scope - The scope to add parameters to
47
- * @param {AST.Pattern[]} params - Parameter nodes
48
- */
49
- function add_params(scope, params) {
50
- for (const param of params) {
51
- for (const node of extract_identifiers(param)) {
52
- scope.declare(node, 'normal', param.type === 'RestElement' ? 'rest_param' : 'param');
53
- }
54
- }
55
- }
56
-
57
- /**
58
- * Create a block scope
59
- * @param {AST.Node} node - AST node
60
- * @param {Context<AST.Node, State>} context - Visitor context
61
- */
62
- const create_block_scope = (node, { state, next }) => {
63
- const scope = state.scope.child(true);
64
- scopes.set(node, scope);
65
-
66
- if (node.type === 'ForOfStatement') {
67
- if (node.index) {
68
- state.scope.declare(node.index, 'normal', 'let');
69
- }
70
- }
71
-
72
- next({ scope });
73
- };
74
-
75
- walk(ast, state, {
76
- // references
77
- Identifier(node, { path, state }) {
78
- const parent = path.at(-1);
79
- if (
80
- parent &&
81
- is_reference(node, /** @type {AST.Node} */ (parent)) &&
82
- // TSTypeAnnotation, TSInterfaceDeclaration etc - these are normally already filtered out,
83
- // but for the migration they aren't, so we need to filter them out here
84
- // TODO -> once migration script is gone we can remove this check
85
- !parent.type.startsWith('TS')
86
- ) {
87
- references.push([state.scope, { node, path: path.slice() }]);
88
- }
89
- },
90
-
91
- AssignmentExpression(node, { state, next }) {
92
- updates.push([state.scope, node.left]);
93
- next();
94
- },
95
-
96
- UpdateExpression(node, { state, next }) {
97
- updates.push([
98
- state.scope,
99
- /** @type {AST.Identifier | AST.MemberExpression} */ (node.argument),
100
- ]);
101
- next();
102
- },
103
-
104
- ImportDeclaration(node, { state }) {
105
- for (const specifier of node.specifiers) {
106
- state.scope.declare(specifier.local, 'normal', 'import', node);
107
- }
108
- },
109
-
110
- Component(node, { state, next }) {
111
- const scope = state.scope.child();
112
- scopes.set(node, scope);
113
-
114
- // Only declare the component name if it has an id (not anonymous)
115
- if (node.id) {
116
- scope.declare(node.id, 'normal', 'component');
117
- }
118
-
119
- add_params(scope, node.params);
120
- next({ scope });
121
- },
122
-
123
- Element(node, { state, next }) {
124
- const scope = state.scope.child();
125
- scopes.set(node, scope);
126
-
127
- next({ scope });
128
- },
129
-
130
- ServerBlock(node, { state, next }) {
131
- const scope = state.scope.child();
132
- scope.server_block = true;
133
- scopes.set(node, scope);
134
-
135
- next({ scope });
136
- },
137
-
138
- FunctionExpression(node, { state, next }) {
139
- const scope = state.scope.child();
140
- scopes.set(node, scope);
141
-
142
- if (node.id) scope.declare(node.id, 'normal', 'function');
143
-
144
- add_params(scope, node.params);
145
- next({ scope });
146
- },
147
-
148
- FunctionDeclaration(node, { state, next }) {
149
- if (node.id) state.scope.declare(node.id, 'normal', 'function', node);
150
-
151
- const scope = state.scope.child();
152
- scopes.set(node, scope);
153
-
154
- add_params(scope, node.params);
155
- next({ scope });
156
- },
157
-
158
- ArrowFunctionExpression(node, { state, next }) {
159
- const scope = state.scope.child();
160
- scopes.set(node, scope);
161
-
162
- add_params(scope, node.params);
163
- next({ scope });
164
- },
165
-
166
- ForStatement: create_block_scope,
167
- ForInStatement: create_block_scope,
168
- ForOfStatement: create_block_scope,
169
- SwitchStatement: create_block_scope,
170
- BlockStatement(node, context) {
171
- const parent = context.path.at(-1);
172
- if (
173
- parent?.type === 'FunctionDeclaration' ||
174
- parent?.type === 'FunctionExpression' ||
175
- parent?.type === 'ArrowFunctionExpression'
176
- ) {
177
- // We already created a new scope for the function
178
- context.next();
179
- } else {
180
- create_block_scope(node, context);
181
- }
182
- },
183
-
184
- ClassDeclaration(node, { state, next }) {
185
- if (node.id) state.scope.declare(node.id, 'normal', 'let', node);
186
- next();
187
- },
188
-
189
- VariableDeclaration(node, { state, path, next }) {
190
- for (const declarator of node.declarations) {
191
- /** @type {Binding[]} */
192
- const bindings = [];
193
-
194
- state.scope.declarators.set(declarator, bindings);
195
-
196
- for (const id of extract_identifiers(declarator.id)) {
197
- const binding = state.scope.declare(id, 'normal', node.kind, declarator.init);
198
- bindings.push(binding);
199
- }
200
- }
201
-
202
- next();
203
- },
204
-
205
- CatchClause(node, { state, next }) {
206
- if (node.param) {
207
- const scope = state.scope.child(true);
208
- scopes.set(node, scope);
209
-
210
- for (const id of extract_identifiers(node.param)) {
211
- scope.declare(id, 'normal', 'let');
212
- }
213
-
214
- next({ scope });
215
- } else {
216
- next();
217
- }
218
- },
219
- });
220
-
221
- for (const [scope, { node, path }] of references) {
222
- scope.reference(node, path);
223
- }
224
-
225
- for (const [scope, node] of updates) {
226
- for (const expression of unwrap_pattern(node)) {
227
- const left = object(expression);
228
- const binding = left && scope.get(left.name);
229
-
230
- if (binding !== null && left !== binding.node) {
231
- binding.updated = true;
232
-
233
- if (left === expression) {
234
- binding.reassigned = true;
235
- } else {
236
- binding.mutated = true;
237
- }
238
- }
239
- }
240
- }
241
-
242
- return {
243
- scope,
244
- scopes,
245
- };
246
- }
247
-
248
- /** @implements {ScopeInterface} */
249
- export class Scope {
250
- /** @type {ScopeRootInterface} */
251
- root;
252
-
253
- /**
254
- * The immediate parent scope
255
- * @type {ScopeInterface['parent']}
256
- */
257
- parent;
258
-
259
- /**
260
- * Whether or not `var` declarations are contained by this scope
261
- * @type {boolean}
262
- */
263
- #porous;
264
-
265
- /**
266
- * A map of every identifier declared by this scope, and all the
267
- * identifiers that reference it
268
- * @type {ScopeInterface['declarations']}
269
- */
270
- declarations = new Map();
271
-
272
- /**
273
- * A map of declarators to the bindings they declare
274
- * @type {ScopeInterface['declarators']}
275
- */
276
- declarators = new Map();
277
-
278
- /**
279
- * A set of all the names referenced with this scope
280
- * — useful for generating unique names
281
- * @type {ScopeInterface['references']}
282
- */
283
- references = new Map();
284
-
285
- /**
286
- * The scope depth allows us to determine if a state variable is referenced in its own scope,
287
- * which is usually an error. Block statements do not increase this value
288
- * @type {ScopeInterface['function_depth']}
289
- */
290
- function_depth = 0;
291
-
292
- /**
293
- * If tracing of reactive dependencies is enabled for this scope
294
- * @type {ScopeInterface['tracing']}
295
- */
296
- tracing = null;
297
-
298
- /**
299
- * Is this scope a top-level server block scope
300
- * @type {ScopeInterface['server_block']}
301
- */
302
- server_block = false;
303
-
304
- /** @type {ScopeConstructorInterface['error_options']} */
305
- #error_options;
306
-
307
- /**
308
- * @param {ScopeConstructorParameters} params
309
- */
310
- constructor(...params) {
311
- const [root, parent, porous, error_options] = params;
312
- this.root = root;
313
- this.parent = parent;
314
- this.#porous = porous;
315
- this.function_depth = parent ? parent.function_depth + (porous ? 0 : 1) : 0;
316
- this.#error_options = error_options ?? {};
317
- }
318
-
319
- /**
320
- * @type {ScopeInterface['declare']}
321
- */
322
- declare(node, kind, declaration_kind, initial = null) {
323
- if (this.parent) {
324
- if (declaration_kind === 'var' && this.#porous) {
325
- return this.parent.declare(node, kind, declaration_kind);
326
- }
327
-
328
- if (declaration_kind === 'import' && !this.parent.server_block) {
329
- return this.parent.declare(node, kind, declaration_kind, initial);
330
- }
331
- }
332
-
333
- if (node.name.startsWith(IDENTIFIER_OBFUSCATION_PREFIX)) {
334
- error(
335
- `Cannot declare a variable named "${node.name}" as identifiers starting with "${IDENTIFIER_OBFUSCATION_PREFIX}" are reserved`,
336
- this.#error_options.filename,
337
- node,
338
- this.#error_options.loose ? this.#error_options.errors : undefined,
339
- this.#error_options.comments,
340
- );
341
- }
342
-
343
- if (this.declarations.has(node.name)) {
344
- error(
345
- `'${node.name}' has already been declared in the current scope`,
346
- this.#error_options.filename,
347
- node,
348
- this.#error_options.loose ? this.#error_options.errors : undefined,
349
- this.#error_options.comments,
350
- );
351
- }
352
-
353
- /** @type {Binding} */
354
- const binding = {
355
- node,
356
- references: [],
357
- initial,
358
- reassigned: false,
359
- mutated: false,
360
- updated: false,
361
- scope: this,
362
- kind,
363
- declaration_kind,
364
- is_called: false,
365
- metadata: null,
366
- };
367
-
368
- this.declarations.set(node.name, binding);
369
- this.root.conflicts.add(node.name);
370
- return binding;
371
- }
372
-
373
- /**
374
- * @type {ScopeInterface['child']}
375
- */
376
- child(porous = false) {
377
- return new Scope(this.root, this, porous, this.#error_options);
378
- }
379
-
380
- /**
381
- * @type {ScopeInterface['generate']}
382
- */
383
- generate(preferred_name) {
384
- if (this.#porous) {
385
- return /** @type {ScopeInterface} */ (this.parent).generate(preferred_name);
386
- }
387
-
388
- preferred_name = preferred_name.replace(/[^a-zA-Z0-9_$]/g, '_').replace(/^[0-9]/, '_');
389
- let name = preferred_name;
390
- let n = 1;
391
-
392
- while (
393
- this.references.has(name) ||
394
- this.declarations.has(name) ||
395
- this.root.conflicts.has(name) ||
396
- is_reserved(name)
397
- ) {
398
- name = `${preferred_name}_${n++}`;
399
- }
400
-
401
- this.references.set(name, []);
402
- this.root.conflicts.add(name);
403
- return name;
404
- }
405
-
406
- /**
407
- * @type {ScopeInterface['get']}
408
- */
409
- get(name) {
410
- return this.declarations.get(name) ?? this.parent?.get(name) ?? null;
411
- }
412
-
413
- /**
414
- * @type {ScopeInterface['get_bindings']}
415
- */
416
- get_bindings(node) {
417
- const bindings = this.declarators.get(node);
418
- if (!bindings) {
419
- throw new Error('No binding found for declarator');
420
- }
421
- return bindings;
422
- }
423
-
424
- /**
425
- * @type {ScopeInterface['owner']}
426
- */
427
- owner(name) {
428
- return this.declarations.has(name) ? this : this.parent && this.parent.owner(name);
429
- }
430
-
431
- /**
432
- * @type {ScopeInterface['reference']}
433
- */
434
- reference(node, path) {
435
- path = [...path]; // ensure that mutations to path afterwards don't affect this reference
436
- let references = this.references.get(node.name);
437
-
438
- if (!references) this.references.set(node.name, (references = []));
439
-
440
- references.push({ node, path });
441
-
442
- const binding = this.declarations.get(node.name);
443
- if (binding) {
444
- binding.references.push({ node, path });
445
- } else if (this.parent) {
446
- this.parent.reference(node, path);
447
- } else {
448
- // no binding was found, and this is the top level scope,
449
- // which means this is a global
450
- this.root.conflicts.add(node.name);
451
- }
452
- }
453
- }
454
-
455
- /** @implements {ScopeRootInterface} */
456
- export class ScopeRoot {
457
- /** @type {ScopeRootInterface['conflicts']} */
458
- conflicts = new Set();
459
-
460
- /**
461
- * @type {ScopeRootInterface['unique']}
462
- */
463
- unique(preferred_name) {
464
- preferred_name = preferred_name.replace(/[^a-zA-Z0-9_$]/g, '_');
465
- let final_name = preferred_name;
466
- let n = 1;
467
-
468
- while (this.conflicts.has(final_name)) {
469
- final_name = `${preferred_name}_${n++}`;
470
- }
471
-
472
- this.conflicts.add(final_name);
473
- const id = b.id(final_name);
474
- return id;
475
- }
476
- }