ripple 0.2.42 → 0.2.44
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 +1 -1
- package/src/compiler/phases/1-parse/index.js +4 -5
- package/src/compiler/phases/3-transform/index.js +78 -40
- package/src/compiler/phases/3-transform/segments.js +2 -2
- package/src/runtime/array.js +393 -57
- package/src/runtime/index.js +1 -0
- package/src/runtime/internal/client/blocks.js +5 -5
- package/src/runtime/internal/client/constants.js +2 -1
- package/src/runtime/internal/client/index.js +3 -2
- package/src/runtime/internal/client/render.js +6 -6
- package/src/runtime/internal/client/runtime.js +52 -18
- package/src/runtime/internal/client/utils.js +18 -0
- package/tests/__snapshots__/basic.test.ripple.snap +14 -0
- package/tests/array.test.ripple +1424 -10
- package/tests/basic.test.ripple +180 -4
- package/tests/compiler.test.ripple +31 -1
- package/tests/{decorators.test.ripple → ref.test.ripple} +4 -4
- package/types/index.d.ts +2 -0
package/package.json
CHANGED
|
@@ -139,15 +139,14 @@ function RipplePlugin(config) {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
if (this.eat(tt.braceL)) {
|
|
142
|
-
if (this.
|
|
142
|
+
if (this.value === 'ref') {
|
|
143
143
|
this.next();
|
|
144
|
-
if (this.
|
|
145
|
-
this.
|
|
144
|
+
if (this.type === tt.braceR) {
|
|
145
|
+
this.raise(this.start, '"ref" is a Ripple keyword and must be used in the form {ref fn}');
|
|
146
146
|
}
|
|
147
|
-
this.next();
|
|
148
147
|
node.argument = this.parseMaybeAssign();
|
|
149
148
|
this.expect(tt.braceR);
|
|
150
|
-
return this.finishNode(node, '
|
|
149
|
+
return this.finishNode(node, 'RefAttribute');
|
|
151
150
|
} else if (this.type === tt.ellipsis) {
|
|
152
151
|
this.expect(tt.ellipsis);
|
|
153
152
|
node.argument = this.parseMaybeAssign();
|
|
@@ -150,40 +150,57 @@ const visitors = {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
// Handle array methods that access the array
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
153
|
+
if (callee.type === 'MemberExpression') {
|
|
154
|
+
const property = callee.property;
|
|
155
|
+
|
|
156
|
+
if (property.type === 'Identifier' && !callee.optional) {
|
|
157
|
+
const name = property.name;
|
|
158
|
+
if (
|
|
159
|
+
// TODO support the missing array methods
|
|
160
|
+
name === 'reduce' ||
|
|
161
|
+
name === 'map' ||
|
|
162
|
+
name === 'forEach' ||
|
|
163
|
+
name === 'join' ||
|
|
164
|
+
name === 'includes' ||
|
|
165
|
+
name === 'indexOf' ||
|
|
166
|
+
name === 'lastIndexOf' ||
|
|
167
|
+
name === 'filter' ||
|
|
168
|
+
name === 'every' ||
|
|
169
|
+
name === 'some' ||
|
|
170
|
+
name === 'toSpliced' ||
|
|
171
|
+
name === 'toSorted' ||
|
|
172
|
+
name === 'toString' ||
|
|
173
|
+
name === 'values' ||
|
|
174
|
+
name === 'entries'
|
|
175
|
+
) {
|
|
176
|
+
return b.call(
|
|
177
|
+
'$.with_scope',
|
|
178
|
+
b.id('__block'),
|
|
179
|
+
b.thunk(
|
|
180
|
+
b.call(
|
|
181
|
+
'$.array_' + name,
|
|
182
|
+
context.visit(callee.object),
|
|
183
|
+
...node.arguments.map((arg) => context.visit(arg)),
|
|
184
|
+
),
|
|
185
|
+
),
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (callee.computed) {
|
|
177
191
|
return b.call(
|
|
178
192
|
'$.with_scope',
|
|
179
193
|
b.id('__block'),
|
|
180
194
|
b.thunk(
|
|
181
195
|
b.call(
|
|
182
|
-
'$.
|
|
196
|
+
'$.call_property',
|
|
183
197
|
context.visit(callee.object),
|
|
198
|
+
context.visit(property),
|
|
199
|
+
callee.optional ? b.true : undefined,
|
|
200
|
+
node.optional ? b.true : undefined,
|
|
184
201
|
...node.arguments.map((arg) => context.visit(arg)),
|
|
185
|
-
)
|
|
186
|
-
)
|
|
202
|
+
)
|
|
203
|
+
)
|
|
187
204
|
);
|
|
188
205
|
}
|
|
189
206
|
}
|
|
@@ -213,6 +230,13 @@ const visitors = {
|
|
|
213
230
|
context.next();
|
|
214
231
|
},
|
|
215
232
|
|
|
233
|
+
TSMappedType(_, context) {
|
|
234
|
+
if (!context.state.to_ts) {
|
|
235
|
+
return b.empty;
|
|
236
|
+
}
|
|
237
|
+
context.next();
|
|
238
|
+
},
|
|
239
|
+
|
|
216
240
|
NewExpression(node, context) {
|
|
217
241
|
const callee = node.callee;
|
|
218
242
|
const parent = context.path.at(-1);
|
|
@@ -483,7 +507,11 @@ const visitors = {
|
|
|
483
507
|
);
|
|
484
508
|
|
|
485
509
|
if (is_spreading) {
|
|
486
|
-
|
|
510
|
+
// For spread attributes, store just the actual value, not the full attribute string
|
|
511
|
+
const actual_value = is_boolean_attribute(name) && value === true
|
|
512
|
+
? b.literal(true)
|
|
513
|
+
: b.literal(value === true ? '' : value);
|
|
514
|
+
spread_attributes.push(b.prop('init', b.literal(name), actual_value));
|
|
487
515
|
} else {
|
|
488
516
|
state.template.push(attr_value);
|
|
489
517
|
}
|
|
@@ -637,9 +665,9 @@ const visitors = {
|
|
|
637
665
|
}
|
|
638
666
|
} else if (attr.type === 'SpreadAttribute') {
|
|
639
667
|
spread_attributes.push(b.spread(b.call('$.spread_object', visit(attr.argument, state))));
|
|
640
|
-
} else if (attr.type === '
|
|
668
|
+
} else if (attr.type === 'RefAttribute') {
|
|
641
669
|
const id = state.flush_node();
|
|
642
|
-
state.init.push(b.stmt(b.call('$.
|
|
670
|
+
state.init.push(b.stmt(b.call('$.ref', id, b.thunk(visit(attr.argument, state)))));
|
|
643
671
|
}
|
|
644
672
|
}
|
|
645
673
|
|
|
@@ -742,8 +770,8 @@ const visitors = {
|
|
|
742
770
|
),
|
|
743
771
|
),
|
|
744
772
|
);
|
|
745
|
-
} else if (attr.type === '
|
|
746
|
-
props.push(b.prop('init', b.call('$.
|
|
773
|
+
} else if (attr.type === 'RefAttribute') {
|
|
774
|
+
props.push(b.prop('init', b.call('$.ref_prop'), visit(attr.argument, state), true));
|
|
747
775
|
} else if (attr.type === 'AccessorAttribute') {
|
|
748
776
|
// # means it's an accessor to the runtime
|
|
749
777
|
tracked.push(b.literal('#' + attr.name.name));
|
|
@@ -973,7 +1001,8 @@ const visitors = {
|
|
|
973
1001
|
const left = node.left;
|
|
974
1002
|
|
|
975
1003
|
if (left.type === 'MemberExpression') {
|
|
976
|
-
|
|
1004
|
+
// need to capture setting length of array to throw a runtime error
|
|
1005
|
+
if (left.property.type === 'Identifier' && (is_tracked_name(left.property.name) || left.property.name === 'length')) {
|
|
977
1006
|
if (left.property.name !== '$length') {
|
|
978
1007
|
return b.call(
|
|
979
1008
|
'$.set_property',
|
|
@@ -1269,6 +1298,15 @@ const visitors = {
|
|
|
1269
1298
|
return b.binary(node.operator, context.visit(node.left), context.visit(node.right));
|
|
1270
1299
|
},
|
|
1271
1300
|
|
|
1301
|
+
TemplateLiteral(node, context) {
|
|
1302
|
+
if (node.expressions.length === 0) {
|
|
1303
|
+
return b.literal(node.quasis[0].value.cooked);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
const expressions = node.expressions.map(expr => context.visit(expr));
|
|
1307
|
+
return b.template(node.quasis, expressions);
|
|
1308
|
+
},
|
|
1309
|
+
|
|
1272
1310
|
RenderFragment(node, context) {
|
|
1273
1311
|
const identifer = node.expression.callee;
|
|
1274
1312
|
|
|
@@ -1375,12 +1413,12 @@ function transform_ts_child(node, context) {
|
|
|
1375
1413
|
const children = [];
|
|
1376
1414
|
let has_children_props = false;
|
|
1377
1415
|
|
|
1378
|
-
// Filter out
|
|
1379
|
-
const
|
|
1416
|
+
// Filter out RefAttributes and handle them separately
|
|
1417
|
+
const ref_attributes = [];
|
|
1380
1418
|
const attributes = node.attributes
|
|
1381
1419
|
.filter((attr) => {
|
|
1382
|
-
if (attr.type === '
|
|
1383
|
-
|
|
1420
|
+
if (attr.type === 'RefAttribute') {
|
|
1421
|
+
ref_attributes.push(attr);
|
|
1384
1422
|
return false;
|
|
1385
1423
|
}
|
|
1386
1424
|
return true;
|
|
@@ -1404,10 +1442,10 @@ function transform_ts_child(node, context) {
|
|
|
1404
1442
|
}
|
|
1405
1443
|
});
|
|
1406
1444
|
|
|
1407
|
-
// Add
|
|
1408
|
-
for (const
|
|
1445
|
+
// Add RefAttribute references separately for sourcemap purposes
|
|
1446
|
+
for (const ref_attr of ref_attributes) {
|
|
1409
1447
|
const metadata = { await: false };
|
|
1410
|
-
const argument = visit(
|
|
1448
|
+
const argument = visit(ref_attr.argument, { ...state, metadata });
|
|
1411
1449
|
state.init.push(b.stmt(argument));
|
|
1412
1450
|
}
|
|
1413
1451
|
|
|
@@ -61,8 +61,8 @@ export function convert_source_map_to_mappings(source_map, source, generated_cod
|
|
|
61
61
|
);
|
|
62
62
|
const source_content = source.substring(source_offset, source_offset + segment_length);
|
|
63
63
|
|
|
64
|
-
// Skip mappings for
|
|
65
|
-
if (source_content.includes('{
|
|
64
|
+
// Skip mappings for RefAttribute syntax to avoid overlapping sourcemaps
|
|
65
|
+
if (source_content.includes('{ref ') || source_content.match(/\{\s*ref\s+/)) {
|
|
66
66
|
continue;
|
|
67
67
|
}
|
|
68
68
|
|