ripple 0.2.125 → 0.2.128

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.125",
6
+ "version": "0.2.128",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -109,7 +109,7 @@ const visitors = {
109
109
  const parent = context.path.at(-1);
110
110
 
111
111
  if (
112
- is_reference(node, /** @type {Node} */ (parent)) &&
112
+ is_reference(node, /** @type {Node} */(parent)) &&
113
113
  binding &&
114
114
  context.state.inside_server_block &&
115
115
  context.state.scope.server_block
@@ -144,7 +144,7 @@ const visitors = {
144
144
  }
145
145
 
146
146
  if (
147
- is_reference(node, /** @type {Node} */ (parent)) &&
147
+ is_reference(node, /** @type {Node} */(parent)) &&
148
148
  node.tracked &&
149
149
  binding?.node !== node
150
150
  ) {
@@ -155,7 +155,7 @@ const visitors = {
155
155
  }
156
156
 
157
157
  if (
158
- is_reference(node, /** @type {Node} */ (parent)) &&
158
+ is_reference(node, /** @type {Node} */(parent)) &&
159
159
  node.tracked &&
160
160
  binding?.node !== node
161
161
  ) {
@@ -174,6 +174,18 @@ const visitors = {
174
174
  context.state.metadata.tracking = true;
175
175
  }
176
176
 
177
+ if (node.object.type === 'Identifier' && !node.object.tracked) {
178
+ const binding = context.state.scope.get(node.object.name);
179
+
180
+ if (binding !== null && binding.initial?.type === 'CallExpression' && is_ripple_track_call(binding.initial.callee, context)) {
181
+ error(
182
+ `Accessing a tracked object directly is not allowed, use the \`@\` prefix to read the value inside a tracked object - for example \`@${node.object.name}${node.property.type === 'Identifier' ? `.${node.property.name}` : ''}\``,
183
+ context.state.analysis.module.filename,
184
+ node,
185
+ )
186
+ }
187
+ }
188
+
177
189
  context.next();
178
190
  },
179
191
 
@@ -424,10 +436,10 @@ const visitors = {
424
436
 
425
437
  if (!node.metadata.has_template && !node.metadata.has_await) {
426
438
  error(
427
- 'Component for...of loops must contain a template or an await expression in their body. Move the for loop into an effect if it does not render anything.',
428
- context.state.analysis.module.filename,
429
- node,
430
- );
439
+ 'Component for...of loops must contain a template or an await expression in their body. Move the for loop into an effect if it does not render anything.',
440
+ context.state.analysis.module.filename,
441
+ node,
442
+ );
431
443
  }
432
444
  },
433
445
 
@@ -477,10 +489,10 @@ const visitors = {
477
489
 
478
490
  if (!node.metadata.has_template && !node.metadata.has_await) {
479
491
  error(
480
- 'Component if statements must contain a template or an await expression in their "then" body. Move the if statement into an effect if it does not render anything.',
481
- context.state.analysis.module.filename,
482
- node,
483
- );
492
+ 'Component if statements must contain a template or an await expression in their "then" body. Move the if statement into an effect if it does not render anything.',
493
+ context.state.analysis.module.filename,
494
+ node,
495
+ );
484
496
  }
485
497
 
486
498
  if (node.alternate) {
@@ -490,10 +502,10 @@ const visitors = {
490
502
 
491
503
  if (!node.metadata.has_template && !node.metadata.has_await) {
492
504
  error(
493
- 'Component if statements must contain a template or an await expression in their "else" body. Move the if statement into an effect if it does not render anything.',
494
- context.state.analysis.module.filename,
495
- node,
496
- );
505
+ 'Component if statements must contain a template or an await expression in their "else" body. Move the if statement into an effect if it does not render anything.',
506
+ context.state.analysis.module.filename,
507
+ node,
508
+ );
497
509
  }
498
510
  }
499
511
  },
@@ -599,9 +611,9 @@ const visitors = {
599
611
  state.elements.push(node);
600
612
  // Mark dynamic elements as scoped by default since we can't match CSS at compile time
601
613
  if (state.component?.css) {
602
- node.metadata.scoped = true;
614
+ node.metadata.scoped = true;
603
615
  }
604
- }
616
+ }
605
617
  }
606
618
 
607
619
  if (is_dom_element) {
@@ -756,12 +768,12 @@ const visitors = {
756
768
  mark_control_flow_has_template(context.path);
757
769
  context.next();
758
770
  },
759
-
760
- /**
761
- *
762
- * @param {any} node
763
- * @param {any} context
764
- */
771
+
772
+ /**
773
+ *
774
+ * @param {any} node
775
+ * @param {any} context
776
+ */
765
777
  AwaitExpression(node, context) {
766
778
  if (is_inside_component(context)) {
767
779
  if (context.state.metadata?.await === false) {
@@ -786,7 +798,7 @@ const visitors = {
786
798
  }
787
799
  parent_block.metadata.has_await = true;
788
800
  }
789
-
801
+
790
802
  context.next();
791
803
  },
792
804
  };
@@ -48,6 +48,12 @@ function add_ripple_internal_import(context) {
48
48
  }
49
49
 
50
50
  function visit_function(node, context) {
51
+ // Function overload signatures don't have a body - they're TypeScript-only
52
+ // Remove them when compiling to JavaScript
53
+ if (!context.state.to_ts && !node.body) {
54
+ return b.empty;
55
+ }
56
+
51
57
  if (context.state.to_ts) {
52
58
  return context.next(context.state);
53
59
  }
@@ -545,10 +551,9 @@ const visitors = {
545
551
 
546
552
  const handle_static_attr = (name, value) => {
547
553
  const attr_value = b.literal(
548
- ` ${name}${
549
- is_boolean_attribute(name) && value === true
550
- ? ''
551
- : `="${value === true ? '' : escape_html(value, true)}"`
554
+ ` ${name}${is_boolean_attribute(name) && value === true
555
+ ? ''
556
+ : `="${value === true ? '' : escape_html(value, true)}"`
552
557
  }`,
553
558
  );
554
559
 
@@ -880,16 +885,16 @@ const visitors = {
880
885
  }
881
886
  }
882
887
 
883
- if (node.metadata.scoped && state.component.css) {
884
- const hasClassAttr = node.attributes.some(attr =>
885
- attr.type === 'Attribute' && attr.name.type === 'Identifier' && attr.name.name === 'class'
886
- );
887
- if (!hasClassAttr) {
888
- const name = is_spreading ? '#class' : 'class';
889
- const value = state.component.css.hash;
890
- props.push(b.prop('init', b.key(name), b.literal(value)));
888
+ if (node.metadata.scoped && state.component.css) {
889
+ const hasClassAttr = node.attributes.some(attr =>
890
+ attr.type === 'Attribute' && attr.name.type === 'Identifier' && attr.name.name === 'class'
891
+ );
892
+ if (!hasClassAttr) {
893
+ const name = is_spreading ? '#class' : 'class';
894
+ const value = state.component.css.hash;
895
+ props.push(b.prop('init', b.key(name), b.literal(value)));
896
+ }
891
897
  }
892
- }
893
898
 
894
899
  const children_filtered = [];
895
900
 
@@ -1039,10 +1044,10 @@ const visitors = {
1039
1044
  operator === '='
1040
1045
  ? context.visit(right)
1041
1046
  : b.binary(
1042
- operator === '+=' ? '+' : operator === '-=' ? '-' : operator === '*=' ? '*' : '/',
1043
- /** @type {Expression} */ (context.visit(left)),
1044
- /** @type {Expression} */ (context.visit(right)),
1045
- ),
1047
+ operator === '+=' ? '+' : operator === '-=' ? '-' : operator === '*=' ? '*' : '/',
1048
+ /** @type {Expression} */(context.visit(left)),
1049
+ /** @type {Expression} */(context.visit(right)),
1050
+ ),
1046
1051
  b.id('__block'),
1047
1052
  );
1048
1053
  }
@@ -1058,12 +1063,12 @@ const visitors = {
1058
1063
  operator === '='
1059
1064
  ? context.visit(right)
1060
1065
  : b.binary(
1061
- operator === '+=' ? '+' : operator === '-=' ? '-' : operator === '*=' ? '*' : '/',
1062
- /** @type {Expression} */ (
1063
- context.visit(left, { ...context.state, metadata: { tracking: false } })
1064
- ),
1065
- /** @type {Expression} */ (context.visit(right)),
1066
+ operator === '+=' ? '+' : operator === '-=' ? '-' : operator === '*=' ? '*' : '/',
1067
+ /** @type {Expression} */(
1068
+ context.visit(left, { ...context.state, metadata: { tracking: false } })
1066
1069
  ),
1070
+ /** @type {Expression} */(context.visit(right)),
1071
+ ),
1067
1072
  b.id('__block'),
1068
1073
  );
1069
1074
  }
@@ -1270,12 +1275,12 @@ const visitors = {
1270
1275
  b.stmt(b.call(b.id('__render'), b.id(consequent_id))),
1271
1276
  alternate_id
1272
1277
  ? b.stmt(
1273
- b.call(
1274
- b.id('__render'),
1275
- b.id(alternate_id),
1276
- node.alternate ? b.literal(false) : undefined,
1277
- ),
1278
- )
1278
+ b.call(
1279
+ b.id('__render'),
1280
+ b.id(alternate_id),
1281
+ node.alternate ? b.literal(false) : undefined,
1282
+ ),
1283
+ )
1279
1284
  : undefined,
1280
1285
  ),
1281
1286
  ]),
@@ -1307,6 +1312,22 @@ const visitors = {
1307
1312
  return b.empty;
1308
1313
  }
1309
1314
 
1315
+ // Remove TSDeclareFunction nodes (function overload signatures) in JavaScript mode
1316
+ if (!context.state.to_ts && node.declaration?.type === 'TSDeclareFunction') {
1317
+ return b.empty;
1318
+ }
1319
+
1320
+ return context.next();
1321
+ },
1322
+
1323
+ TSDeclareFunction(node, context) {
1324
+ // TSDeclareFunction nodes are TypeScript overload signatures - remove in JavaScript mode
1325
+ if (!context.state.to_ts) {
1326
+ return b.empty;
1327
+ }
1328
+
1329
+ // In TypeScript mode, keep as TSDeclareFunction - esrap will print it with 'declare'
1330
+ // We'll remove the 'declare' keyword in post-processing
1310
1331
  return context.next();
1311
1332
  },
1312
1333
 
@@ -1336,9 +1357,9 @@ const visitors = {
1336
1357
  node.handler === null
1337
1358
  ? b.literal(null)
1338
1359
  : b.arrow(
1339
- [b.id('__anchor'), ...(node.handler.param ? [node.handler.param] : [])],
1340
- b.block(transform_body(node.handler.body.body, context)),
1341
- ),
1360
+ [b.id('__anchor'), ...(node.handler.param ? [node.handler.param] : [])],
1361
+ b.block(transform_body(node.handler.body.body, context)),
1362
+ ),
1342
1363
  node.pending === null
1343
1364
  ? undefined
1344
1365
  : b.arrow([b.id('__anchor')], b.block(transform_body(node.pending.body, context))),
@@ -1464,7 +1485,7 @@ function join_template(items) {
1464
1485
  }
1465
1486
 
1466
1487
  for (const quasi of template.quasis) {
1467
- quasi.value.raw = sanitize_template_string(/** @type {string} */ (quasi.value.cooked));
1488
+ quasi.value.raw = sanitize_template_string(/** @type {string} */(quasi.value.cooked));
1468
1489
  }
1469
1490
 
1470
1491
  quasi.tail = true;
@@ -1947,7 +1968,7 @@ export function transform_client(filename, source, analysis, to_ts) {
1947
1968
  };
1948
1969
 
1949
1970
  const program = /** @type {Program} */ (
1950
- walk(/** @type {Node} */ (analysis.ast), { ...state, namespace: 'html' }, visitors)
1971
+ walk(/** @type {Node} */(analysis.ast), { ...state, namespace: 'html' }, visitors)
1951
1972
  );
1952
1973
 
1953
1974
  for (const hoisted of state.hoisted) {
@@ -1971,6 +1992,15 @@ export function transform_client(filename, source, analysis, to_ts) {
1971
1992
  sourceMapSource: path.basename(filename),
1972
1993
  });
1973
1994
 
1995
+ // Post-process TypeScript output to remove 'declare' from function overload signatures
1996
+ // Function overload signatures in regular .ts files should not have 'declare' keyword
1997
+ if (to_ts) {
1998
+ // Remove 'export declare function' -> 'export function' (for overloads only, not implementations)
1999
+ // Match: export declare function name(...): type;
2000
+ // Don't match: export declare function name(...): type { (has body)
2001
+ js.code = js.code.replace(/^(export\s+)declare\s+(function\s+\w+[^{\n]*;)$/gm, '$1$2');
2002
+ }
2003
+
1974
2004
  const css = render_stylesheets(state.stylesheets);
1975
2005
 
1976
2006
  return {
@@ -1111,6 +1111,42 @@ export function convert_source_map_to_mappings(ast, source, generated_code, sour
1111
1111
  } else if (node.type === 'TSAnyKeyword' || node.type === 'TSUnknownKeyword' || node.type === 'TSNumberKeyword' || node.type === 'TSObjectKeyword' || node.type === 'TSBooleanKeyword' || node.type === 'TSBigIntKeyword' || node.type === 'TSStringKeyword' || node.type === 'TSSymbolKeyword' || node.type === 'TSVoidKeyword' || node.type === 'TSUndefinedKeyword' || node.type === 'TSNullKeyword' || node.type === 'TSNeverKeyword' || node.type === 'TSThisType' || node.type === 'TSIntrinsicKeyword') {
1112
1112
  // Primitive type keywords - leaf nodes, no children
1113
1113
  return;
1114
+ } else if (node.type === 'TSDeclareFunction') {
1115
+ // TypeScript declare function: declare function foo(): void;
1116
+ // Visit in source order: id, typeParameters, params, returnType
1117
+ if (node.id) {
1118
+ visit(node.id);
1119
+ }
1120
+ if (node.typeParameters) {
1121
+ visit(node.typeParameters);
1122
+ }
1123
+ if (node.params) {
1124
+ for (const param of node.params) {
1125
+ visit(param);
1126
+ }
1127
+ }
1128
+ if (node.returnType) {
1129
+ visit(node.returnType);
1130
+ }
1131
+ return;
1132
+ } else if (node.type === 'TSExportAssignment') {
1133
+ // TypeScript export assignment: export = foo;
1134
+ if (node.expression) {
1135
+ visit(node.expression);
1136
+ }
1137
+ return;
1138
+ } else if (node.type === 'TSNamespaceExportDeclaration') {
1139
+ // TypeScript namespace export: export as namespace foo;
1140
+ if (node.id) {
1141
+ visit(node.id);
1142
+ }
1143
+ return;
1144
+ } else if (node.type === 'TSExternalModuleReference') {
1145
+ // TypeScript external module reference: import foo = require('bar');
1146
+ if (node.expression) {
1147
+ visit(node.expression);
1148
+ }
1149
+ return;
1114
1150
  }
1115
1151
 
1116
1152
  throw new Error(`Unhandled AST node type in mapping walker: ${node.type}`);
@@ -1,4 +1,4 @@
1
- /** @import { Identifier, Pattern, Super, FunctionExpression, FunctionDeclaration, ArrowFunctionExpression, MemberExpression, AssignmentExpression, Expression, Node, AssignmentOperator } from 'estree' */
1
+ /** @import { Identifier, Pattern, Super, FunctionExpression, FunctionDeclaration, ArrowFunctionExpression, MemberExpression, AssignmentExpression, Expression, Node, AssignmentOperator, CallExpression } from 'estree' */
2
2
  /** @import { Component, Element, Attribute, SpreadAttribute, ScopeInterface, Binding, RippleNode, CompilerState, TransformContext, DelegatedEventResult, TextNode } from '#compiler' */
3
3
  import { build_assignment_value, extract_paths } from '../utils/ast.js';
4
4
  import * as b from '../utils/builders.js';
@@ -352,7 +352,7 @@ export function build_hoisted_params(node, context) {
352
352
  }
353
353
  } else {
354
354
  for (const param of node.params) {
355
- params.push(/** @type {Pattern} */ (context.visit(param)));
355
+ params.push(/** @type {Pattern} */(context.visit(param)));
356
356
  }
357
357
  }
358
358
 
@@ -554,7 +554,7 @@ export function is_ripple_import(callee, context) {
554
554
  * @returns {boolean}
555
555
  */
556
556
  export function is_declared_function_within_component(node, context) {
557
- const component = context.path?.find(/** @param {RippleNode} n */ (n) => n.type === 'Component');
557
+ const component = context.path?.find(/** @param {RippleNode} n */(n) => n.type === 'Component');
558
558
 
559
559
  if (node.type === 'Identifier' && component) {
560
560
  const binding = context.state.scope.get(node.name);
@@ -611,8 +611,8 @@ export function visit_assignment_expression(node, context, build_assignment) {
611
611
  assignment ??
612
612
  b.assignment(
613
613
  '=',
614
- /** @type {Pattern} */ (context.visit(path.node)),
615
- /** @type {Expression} */ (context.visit(value)),
614
+ /** @type {Pattern} */(context.visit(path.node)),
615
+ /** @type {Expression} */(context.visit(value)),
616
616
  )
617
617
  );
618
618
  });
@@ -702,8 +702,8 @@ export function build_assignment(operator, left, right, context) {
702
702
  object,
703
703
  b.assignment(
704
704
  operator,
705
- /** @type {Pattern} */ (context.visit(left)),
706
- /** @type {Expression} */ (context.visit(right)),
705
+ /** @type {Pattern} */(context.visit(left)),
706
+ /** @type {Expression} */(context.visit(right)),
707
707
  ),
708
708
  );
709
709
  }
@@ -830,7 +830,7 @@ function normalize_child(node, normalized, context) {
830
830
  */
831
831
  export function get_parent_block_node(context) {
832
832
  const path = context.path;
833
-
833
+
834
834
  for (let i = path.length - 1; i >= 0; i -= 1) {
835
835
  const context_node = path[i];
836
836
  if (
@@ -167,6 +167,7 @@ export function bindValue(maybe_tracked) {
167
167
  value = [].map.call(select.querySelectorAll(query), get_option_value);
168
168
  } else {
169
169
  /** @type {HTMLOptionElement | null} */
170
+ // @ts-ignore
170
171
  var selected_option =
171
172
  select.querySelector(query) ??
172
173
  // will fall back to first non-disabled option if no option is selected
@@ -184,6 +185,7 @@ export function bindValue(maybe_tracked) {
184
185
  // Mounting and value undefined -> take selection from dom
185
186
  if (mounting && value === undefined) {
186
187
  /** @type {HTMLOptionElement | null} */
188
+ // @ts-ignore
187
189
  var selected_option = select.querySelector(':checked');
188
190
  if (selected_option !== null) {
189
191
  value = get_option_value(selected_option);
@@ -1,7 +1,7 @@
1
1
  /** @import { Block } from '#client' */
2
2
 
3
3
  import { destroy_block, ref } from './blocks.js';
4
- import { REF_PROP } from './constants.js';
4
+ import { REF_PROP, TRACKED, TRACKED_OBJECT } from './constants.js';
5
5
  import {
6
6
  get_descriptors,
7
7
  get_own_property_symbols,
@@ -310,6 +310,10 @@ export function apply_element_spread(element, fn) {
310
310
  }
311
311
 
312
312
  for (const symbol of get_own_property_symbols(next)) {
313
+ // Ensure we are not trying to write to a proxied object
314
+ if (TRACKED_OBJECT in next) {
315
+ next = {...next};
316
+ }
313
317
  var ref_fn = next[symbol];
314
318
 
315
319
  if (symbol.description === REF_PROP && (!prev || ref_fn !== prev[symbol])) {
@@ -1,5 +1,6 @@
1
1
  /** @import { Block, Component, Dependency, Derived, Tracked } from '#client' */
2
2
 
3
+ import { DEV } from 'esm-env';
3
4
  import {
4
5
  destroy_block,
5
6
  destroy_non_branch_children,
@@ -24,6 +25,7 @@ import {
24
25
  TRY_BLOCK,
25
26
  UNINITIALIZED,
26
27
  REF_PROP,
28
+ TRACKED_OBJECT,
27
29
  } from './constants.js';
28
30
  import { capture, suspend } from './try.js';
29
31
  import {
@@ -137,13 +139,13 @@ export function run_teardown(block) {
137
139
  * @param {Derived} computed
138
140
  */
139
141
  function update_derived(computed) {
140
- var value = computed.v;
142
+ var value = computed.__v;
141
143
 
142
144
  if (value === UNINITIALIZED || is_tracking_dirty(computed.d)) {
143
145
  value = run_derived(computed);
144
146
 
145
- if (value !== computed.v) {
146
- computed.v = value;
147
+ if (value !== computed.__v) {
148
+ computed.__v = value;
147
149
  computed.c = increment_clock();
148
150
  }
149
151
  }
@@ -276,12 +278,23 @@ var empty_get_set = { get: undefined, set: undefined };
276
278
  */
277
279
  export function tracked(v, block, get, set) {
278
280
  // TODO: now we expose tracked, we should likely block access in DEV somehow
281
+ if (DEV) {
282
+ return {
283
+ DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY: true,
284
+ a: get || set ? { get, set } : empty_get_set,
285
+ b: block || active_block,
286
+ c: 0,
287
+ f: TRACKED,
288
+ __v: v,
289
+ };
290
+ }
291
+
279
292
  return {
280
293
  a: get || set ? { get, set } : empty_get_set,
281
294
  b: block || active_block,
282
295
  c: 0,
283
296
  f: TRACKED,
284
- v,
297
+ __v: v,
285
298
  };
286
299
  }
287
300
 
@@ -293,6 +306,21 @@ export function tracked(v, block, get, set) {
293
306
  * @returns {Derived}
294
307
  */
295
308
  export function derived(fn, block, get, set) {
309
+ if (DEV) {
310
+ return {
311
+ DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY: true,
312
+ a: get || set ? { get, set } : empty_get_set,
313
+ b: block || active_block,
314
+ blocks: null,
315
+ c: 0,
316
+ co: active_component,
317
+ d: null,
318
+ f: TRACKED | DERIVED,
319
+ fn,
320
+ __v: UNINITIALIZED,
321
+ };
322
+ }
323
+
296
324
  return {
297
325
  a: get || set ? { get, set } : empty_get_set,
298
326
  b: block || active_block,
@@ -302,7 +330,7 @@ export function derived(fn, block, get, set) {
302
330
  d: null,
303
331
  f: TRACKED | DERIVED,
304
332
  fn,
305
- v: UNINITIALIZED,
333
+ __v: UNINITIALIZED,
306
334
  };
307
335
  }
308
336
 
@@ -353,7 +381,7 @@ export function track_split(v, l, b) {
353
381
  t = tracked(undefined, b);
354
382
  exists = !!descriptors[key];
355
383
  if (exists) {
356
- t = define_property(t, 'v', descriptors[key]);
384
+ t = define_property(t, '__v', descriptors[key]);
357
385
  }
358
386
  }
359
387
 
@@ -412,7 +440,7 @@ function is_tracking_dirty(tracking) {
412
440
  var tracked = tracking.t;
413
441
 
414
442
  if ((tracked.f & DERIVED) !== 0) {
415
- update_derived(/** @type {Derived} **/ (tracked));
443
+ update_derived(/** @type {Derived} **/(tracked));
416
444
  }
417
445
 
418
446
  if (tracked.c > tracking.c) {
@@ -467,19 +495,19 @@ export function async_computed(fn, block) {
467
495
  } else {
468
496
  for (var i = 0; i < deferred.length; i++) {
469
497
  var tracked = deferred[i];
470
- new_values.set(tracked, { v: tracked.v, c: tracked.c });
498
+ new_values.set(tracked, { v: tracked.__v, c: tracked.c });
471
499
  }
472
500
  }
473
501
 
474
502
  promise.then((v) => {
475
- if (parent && is_destroyed(/** @type {Block} */ (parent))) {
503
+ if (parent && is_destroyed(/** @type {Block} */(parent))) {
476
504
  return;
477
505
  }
478
- if (promise === current && t.v !== v) {
506
+ if (promise === current && t.__v !== v) {
479
507
  restore();
480
508
 
481
- if (t.v === UNINITIALIZED) {
482
- t.v = v;
509
+ if (t.__v === UNINITIALIZED) {
510
+ t.__v = v;
483
511
  } else {
484
512
  set(t, v, block);
485
513
  }
@@ -492,7 +520,7 @@ export function async_computed(fn, block) {
492
520
  var tracked = deferred[i];
493
521
  var stored = /** @type {{ v: any, c: number }} */ (new_values.get(tracked));
494
522
  var { v, c } = stored;
495
- tracked.v = v;
523
+ tracked.__v = v;
496
524
  tracked.c = c;
497
525
  schedule_update(tracked.b);
498
526
  }
@@ -730,10 +758,10 @@ export function get_derived(computed) {
730
758
  }
731
759
  var get = computed.a.get;
732
760
  if (get !== undefined) {
733
- computed.v = trigger_track_get(get, computed.v);
761
+ computed.__v = trigger_track_get(get, computed.__v);
734
762
  }
735
763
 
736
- return computed.v;
764
+ return computed.__v;
737
765
  }
738
766
 
739
767
  /**
@@ -746,7 +774,7 @@ export function get(tracked) {
746
774
  }
747
775
 
748
776
  return (tracked.f & DERIVED) !== 0
749
- ? get_derived(/** @type {Derived} */ (tracked))
777
+ ? get_derived(/** @type {Derived} */(tracked))
750
778
  : get_tracked(tracked);
751
779
  }
752
780
 
@@ -754,7 +782,7 @@ export function get(tracked) {
754
782
  * @param {Tracked} tracked
755
783
  */
756
784
  export function get_tracked(tracked) {
757
- var value = tracked.v;
785
+ var value = tracked.__v;
758
786
  if (tracking) {
759
787
  register_dependency(tracked);
760
788
  }
@@ -790,7 +818,7 @@ export function set(tracked, value, block) {
790
818
  );
791
819
  }
792
820
 
793
- var old_value = tracked.v;
821
+ var old_value = tracked.__v;
794
822
 
795
823
  if (value !== old_value) {
796
824
  var tracked_block = tracked.b;
@@ -808,7 +836,7 @@ export function set(tracked, value, block) {
808
836
  value = untrack(() => set(value, old_value));
809
837
  }
810
838
 
811
- tracked.v = value;
839
+ tracked.__v = value;
812
840
  tracked.c = increment_clock();
813
841
  schedule_update(tracked_block);
814
842
  }
@@ -872,7 +900,7 @@ export function flush_sync(fn) {
872
900
  * @returns {Object}
873
901
  */
874
902
  export function spread_props(fn, block) {
875
- let computed = derived(fn, block);
903
+ var computed = derived(fn, block);
876
904
 
877
905
  return new Proxy(
878
906
  {},
@@ -882,9 +910,23 @@ export function spread_props(fn, block) {
882
910
  return obj[property];
883
911
  },
884
912
  has(target, property) {
913
+ if (property === TRACKED_OBJECT) {
914
+ return true;
915
+ }
885
916
  const obj = get_derived(computed);
886
917
  return property in obj;
887
918
  },
919
+ getOwnPropertyDescriptor(target, key) {
920
+ const obj = get_derived(computed);
921
+
922
+ if (key in obj) {
923
+ return {
924
+ enumerable: true,
925
+ configurable: true,
926
+ value: obj[key],
927
+ };
928
+ }
929
+ },
888
930
  ownKeys() {
889
931
  const obj = get_derived(computed);
890
932
  return Reflect.ownKeys(obj);
@@ -976,7 +1018,7 @@ export function update(tracked, block, d = 1) {
976
1018
  * @returns {void}
977
1019
  */
978
1020
  export function increment(tracked, block) {
979
- set(tracked, tracked.v + 1, block);
1021
+ set(tracked, tracked.__v + 1, block);
980
1022
  }
981
1023
 
982
1024
  /**
@@ -985,7 +1027,7 @@ export function increment(tracked, block) {
985
1027
  * @returns {void}
986
1028
  */
987
1029
  export function decrement(tracked, block) {
988
- set(tracked, tracked.v - 1, block);
1030
+ set(tracked, tracked.__v - 1, block);
989
1031
  }
990
1032
 
991
1033
  /**
@@ -1164,7 +1206,7 @@ export async function maybe_tracked(v) {
1164
1206
  } else {
1165
1207
  value = await async_computed(async () => {
1166
1208
  return await get_tracked(v);
1167
- }, /** @type {Block} */ (active_block));
1209
+ }, /** @type {Block} */(active_block));
1168
1210
  }
1169
1211
  } else {
1170
1212
  value = await v;
@@ -18,14 +18,16 @@ export type Dependency = {
18
18
  };
19
19
 
20
20
  export type Tracked<V = any> = {
21
+ DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY?: true;
21
22
  a: { get?: Function, set?: Function };
22
23
  b: Block;
23
24
  c: number;
24
25
  f: number;
25
- v: V;
26
+ __v: V;
26
27
  };
27
28
 
28
29
  export type Derived = {
30
+ DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY?: true;
29
31
  a: { get?: Function, set?: Function };
30
32
  b: Block;
31
33
  blocks: null | Block[];
@@ -34,7 +36,7 @@ export type Derived = {
34
36
  d: null;
35
37
  f: number;
36
38
  fn: Function;
37
- v: any;
39
+ __v: any;
38
40
  };
39
41
 
40
42
  export type Block = {
@@ -62,7 +62,9 @@ class Output {
62
62
  /** @type {render} */
63
63
  export async function render(component) {
64
64
  const output = new Output(null);
65
- let head, body, css;
65
+ let head = '';
66
+ let body = '';
67
+ let css = new Set();
66
68
 
67
69
  try {
68
70
  if (component.async) {
@@ -40,6 +40,7 @@ export function proxy(value, block) {
40
40
  return value;
41
41
  }
42
42
 
43
+ /** @type {Map<any,Tracked>} */
43
44
  var tracked_elements = new Map();
44
45
  var is_proxied_array = is_array(value);
45
46
  /** @type {Tracked} */
@@ -97,8 +98,8 @@ export function proxy(value, block) {
97
98
  var t = tracked_elements.get(prop);
98
99
  var exists = prop in target;
99
100
 
100
- if (is_proxied_array && prop === 'length') {
101
- for (var i = value; i < t.v; i += 1) {
101
+ if (is_proxied_array && prop === 'length' && t !== undefined) {
102
+ for (var i = value; i < t.__v; i += 1) {
102
103
  var other_t = tracked_elements.get(i + '');
103
104
  if (other_t !== undefined) {
104
105
  set(other_t, UNINITIALIZED, block);
@@ -124,7 +125,7 @@ export function proxy(value, block) {
124
125
  tracked_elements.set(prop, t);
125
126
  }
126
127
  } else {
127
- exists = t.v !== UNINITIALIZED;
128
+ exists = t.__v !== UNINITIALIZED;
128
129
 
129
130
  set(t, value, block);
130
131
  }
@@ -143,7 +144,7 @@ export function proxy(value, block) {
143
144
  // will not cause the length to be out of sync.
144
145
  var n = Number(prop);
145
146
 
146
- if (Number.isInteger(n) && n >= tracked_len.v) {
147
+ if (Number.isInteger(n) && n >= tracked_len.__v) {
147
148
  set(tracked_len, n + 1, block);
148
149
  }
149
150
  }
@@ -180,7 +181,7 @@ export function proxy(value, block) {
180
181
  }
181
182
 
182
183
  var t = tracked_elements.get(prop);
183
- var exists = (t !== undefined && t.v !== UNINITIALIZED) || Reflect.has(target, prop);
184
+ var exists = (t !== undefined && t.__v !== UNINITIALIZED) || Reflect.has(target, prop);
184
185
 
185
186
  if (t !== undefined || !exists || get_descriptor(target, prop)?.writable) {
186
187
  if (t === undefined) {
@@ -229,11 +230,11 @@ export function proxy(value, block) {
229
230
  ownKeys(target) {
230
231
  var own_keys = Reflect.ownKeys(target).filter((key) => {
231
232
  var t = tracked_elements.get(key);
232
- return t === undefined || t.v !== UNINITIALIZED;
233
+ return t === undefined || t.__v !== UNINITIALIZED;
233
234
  });
234
235
 
235
236
  for (var [key, t] of tracked_elements) {
236
- if (t.v !== UNINITIALIZED && !(key in target)) {
237
+ if (t.__v !== UNINITIALIZED && !(key in target)) {
237
238
  own_keys.push(key);
238
239
  }
239
240
  }
@@ -249,7 +250,7 @@ export function proxy(value, block) {
249
250
  if (t) descriptor.value = get(t);
250
251
  } else if (descriptor === undefined) {
251
252
  var t = tracked_elements.get(prop);
252
- var value = t?.v;
253
+ var value = t?.__v;
253
254
 
254
255
  if (t !== undefined && value !== UNINITIALIZED) {
255
256
  return {
@@ -0,0 +1,10 @@
1
+ export function test(arg: string): string
2
+ export function test(arg: number): string
3
+
4
+ export function test(arg: string | number): string {
5
+ if (typeof arg === 'string') {
6
+ return arg;
7
+ }
8
+
9
+ return arg.toString();
10
+ }
@@ -0,0 +1,40 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mount, flushSync } from 'ripple';
3
+
4
+ import { test } from './function-overload-import.ripple';
5
+
6
+ describe('function overload import tests', () => {
7
+ describe('function overloads', () => {
8
+ it('test function with string argument returns the string', () => {
9
+ const result = test('hello');
10
+ expect(result).toBe('hello');
11
+ expect(typeof result).toBe('string');
12
+ });
13
+
14
+ it('test function with number argument returns string representation', () => {
15
+ const result = test(42);
16
+ expect(result).toBe('42');
17
+ expect(typeof result).toBe('string');
18
+ });
19
+
20
+ it('test function with zero returns "0"', () => {
21
+ const result = test(0);
22
+ expect(result).toBe('0');
23
+ });
24
+
25
+ it('test function with negative number returns string representation', () => {
26
+ const result = test(-100);
27
+ expect(result).toBe('-100');
28
+ });
29
+
30
+ it('test function with empty string returns empty string', () => {
31
+ const result = test('');
32
+ expect(result).toBe('');
33
+ });
34
+
35
+ it('test function with decimal number returns string representation', () => {
36
+ const result = test(3.14159);
37
+ expect(result).toBe('3.14159');
38
+ });
39
+ });
40
+ });