ripple 0.2.103 → 0.2.105

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Ripple is an elegant TypeScript UI framework",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.2.103",
6
+ "version": "0.2.105",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -67,6 +67,7 @@
67
67
  "@sveltejs/acorn-typescript": "^1.0.6",
68
68
  "acorn": "^8.15.0",
69
69
  "clsx": "^2.1.1",
70
+ "esm-env": "^1.2.2",
70
71
  "esrap": "^2.1.0",
71
72
  "is-reference": "^3.0.3",
72
73
  "magic-string": "^0.30.18",
@@ -167,9 +167,16 @@ function RipplePlugin(config) {
167
167
 
168
168
  if (code === 64) {
169
169
  // @ character
170
- // Look ahead to see if this is followed by a valid identifier character
170
+ // Look ahead to see if this is followed by a valid identifier character or opening paren
171
171
  if (this.pos + 1 < this.input.length) {
172
172
  const nextChar = this.input.charCodeAt(this.pos + 1);
173
+
174
+ // Check if this is @( for unboxing expression syntax
175
+ if (nextChar === 40) { // ( character
176
+ this.pos += 2; // skip '@('
177
+ return this.finishToken(tt.parenL, '@(');
178
+ }
179
+
173
180
  // Check if the next character can start an identifier
174
181
  if (
175
182
  (nextChar >= 65 && nextChar <= 90) || // A-Z
@@ -348,6 +355,11 @@ function RipplePlugin(config) {
348
355
  * @returns {any} Parsed expression atom
349
356
  */
350
357
  parseExprAtom(refDestructuringErrors, forNew, forInit) {
358
+ // Check if this is @(expression) for unboxing tracked values
359
+ if (this.type === tt.parenL && this.value === '@(') {
360
+ return this.parseTrackedExpression();
361
+ }
362
+
351
363
  // Check if this is a tuple literal starting with #[
352
364
  if (this.type === tt.bracketL && this.value === '#[') {
353
365
  return this.parseTrackedArrayExpression();
@@ -358,6 +370,33 @@ function RipplePlugin(config) {
358
370
  return super.parseExprAtom(refDestructuringErrors, forNew, forInit);
359
371
  }
360
372
 
373
+ /**
374
+ * Parse `@(expression)` syntax for unboxing tracked values
375
+ * Creates a TrackedExpression node with the argument property
376
+ * @returns {any} TrackedExpression node
377
+ */
378
+ parseTrackedExpression() {
379
+ const node = this.startNode();
380
+ this.next(); // consume '@(' token
381
+ node.argument = this.parseExpression();
382
+ this.expect(tt.parenR); // expect ')'
383
+ return this.finishNode(node, 'TrackedExpression');
384
+ }
385
+
386
+ /**
387
+ * Override to allow TrackedExpression as a valid lvalue for update expressions
388
+ * @param {any} expr - Expression to check
389
+ * @param {any} bindingType - Binding type
390
+ * @param {any} checkClashes - Check for clashes
391
+ */
392
+ checkLValSimple(expr, bindingType, checkClashes) {
393
+ // Allow TrackedExpression as a valid lvalue for ++/-- operators
394
+ if (expr.type === 'TrackedExpression') {
395
+ return;
396
+ }
397
+ return super.checkLValSimple(expr, bindingType, checkClashes);
398
+ }
399
+
361
400
  parseTrackedArrayExpression() {
362
401
  const node = this.startNode();
363
402
  this.next(); // consume the '#['
@@ -106,7 +106,7 @@ const visitors = {
106
106
  }
107
107
 
108
108
  if (
109
- is_reference(node, /** @type {Node} */ (parent)) &&
109
+ is_reference(node, /** @type {Node} */(parent)) &&
110
110
  node.tracked &&
111
111
  binding?.node !== node
112
112
  ) {
@@ -117,7 +117,7 @@ const visitors = {
117
117
  }
118
118
 
119
119
  if (
120
- is_reference(node, /** @type {Node} */ (parent)) &&
120
+ is_reference(node, /** @type {Node} */(parent)) &&
121
121
  node.tracked &&
122
122
  binding?.node !== node
123
123
  ) {
@@ -250,7 +250,10 @@ const visitors = {
250
250
  }
251
251
  const elements = [];
252
252
 
253
- context.next({ ...context.state, elements, function_depth: context.state.function_depth + 1 });
253
+ // Track metadata for this component
254
+ const metadata = { await: false };
255
+
256
+ context.next({ ...context.state, elements, function_depth: context.state.function_depth + 1, metadata });
254
257
 
255
258
  const css = node.css;
256
259
 
@@ -259,6 +262,12 @@ const visitors = {
259
262
  prune_css(css, node);
260
263
  }
261
264
  }
265
+
266
+ // Store component metadata in analysis
267
+ context.state.analysis.component_metadata.push({
268
+ id: node.id.name,
269
+ async: metadata.await,
270
+ });
262
271
  },
263
272
 
264
273
  ForStatement(node, context) {
@@ -357,6 +366,11 @@ const visitors = {
357
366
  }
358
367
 
359
368
  if (node.pending) {
369
+ // Try/pending blocks indicate async operations
370
+ if (context.state.metadata?.await === false) {
371
+ context.state.metadata.await = true;
372
+ }
373
+
360
374
  node.metadata = {
361
375
  has_template: false,
362
376
  };
@@ -594,6 +608,7 @@ export function analyze(ast, filename) {
594
608
  ast,
595
609
  scope,
596
610
  scopes,
611
+ component_metadata: [],
597
612
  };
598
613
 
599
614
  walk(
@@ -362,6 +362,10 @@ const visitors = {
362
362
  );
363
363
  },
364
364
 
365
+ TrackedExpression(node, context) {
366
+ return b.call('_$_.get', context.visit(node.argument));
367
+ },
368
+
365
369
  MemberExpression(node, context) {
366
370
  const parent = context.path.at(-1);
367
371
 
@@ -1001,6 +1005,16 @@ const visitors = {
1001
1005
  );
1002
1006
  }
1003
1007
 
1008
+ if (argument.type === 'TrackedExpression') {
1009
+ return b.call(
1010
+ node.prefix ? '_$_.update_pre' : '_$_.update',
1011
+ context.visit(argument.argument, { ...context.state, metadata: { tracking: null } }),
1012
+ b.id('__block'),
1013
+ node.operator === '--' ? b.literal(-1) : undefined,
1014
+ );
1015
+ }
1016
+
1017
+
1004
1018
  const left = object(argument);
1005
1019
  const binding = context.state.scope.get(left.name);
1006
1020
  const transformers = left && binding?.transform;