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 +2 -1
- package/src/compiler/phases/1-parse/index.js +40 -1
- package/src/compiler/phases/2-analyze/index.js +18 -3
- package/src/compiler/phases/3-transform/client/index.js +14 -0
- package/src/compiler/phases/3-transform/segments.js +531 -12
- package/src/compiler/phases/3-transform/server/index.js +237 -19
- package/src/compiler/types/index.d.ts +5 -0
- package/src/runtime/index-client.js +2 -0
- package/src/runtime/internal/client/css.js +70 -0
- package/src/runtime/internal/server/css-registry.js +35 -0
- package/src/runtime/internal/server/index.js +32 -17
- package/src/server/index.js +2 -1
- package/tests/client/__snapshots__/tracked-expression.test.ripple.snap +34 -0
- package/tests/client/compiler.test.ripple +98 -10
- package/tests/client/tracked-expression.test.ripple +46 -0
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.
|
|
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} */
|
|
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} */
|
|
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
|
-
|
|
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;
|