ripple 0.2.199 → 0.2.201
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 +5 -4
- package/src/compiler/index.d.ts +1 -5
- package/src/compiler/phases/1-parse/index.js +145 -11
- package/src/compiler/phases/2-analyze/index.js +24 -8
- package/src/compiler/phases/2-analyze/prune.js +5 -3
- package/src/compiler/phases/3-transform/client/index.js +312 -165
- package/src/compiler/phases/3-transform/segments.js +220 -70
- package/src/compiler/phases/3-transform/server/index.js +227 -77
- package/src/compiler/source-map-utils.js +74 -10
- package/src/compiler/types/index.d.ts +63 -21
- package/src/compiler/types/parse.d.ts +3 -1
- package/src/compiler/utils.js +34 -0
- package/src/helpers.d.ts +5 -0
- package/src/runtime/index-server.js +27 -47
- package/src/runtime/internal/client/composite.js +5 -0
- package/src/runtime/internal/client/events.js +1 -9
- package/src/runtime/internal/client/for.js +6 -4
- package/src/runtime/internal/client/hydration.js +2 -2
- package/src/runtime/internal/client/index.js +1 -1
- package/src/runtime/internal/client/operations.js +4 -4
- package/src/runtime/internal/client/render.js +0 -2
- package/src/runtime/internal/client/template.js +9 -1
- package/src/runtime/internal/client/types.d.ts +18 -0
- package/src/runtime/internal/client/utils.js +1 -1
- package/src/runtime/internal/server/index.js +106 -3
- package/src/utils/builders.js +25 -5
- package/tests/client/basic/basic.attributes.test.ripple +1 -1
- package/tests/client/basic/basic.components.test.ripple +47 -0
- package/tests/client/basic/basic.rendering.test.ripple +1 -1
- package/tests/client/composite/composite.props.test.ripple +49 -4
- package/tests/client/dynamic-elements.test.ripple +44 -0
- package/tests/client/switch.test.ripple +40 -0
- package/tests/client/tsconfig.json +11 -0
- package/tests/client.d.ts +5 -22
- package/tests/common.d.ts +24 -0
- package/tests/hydration/compiled/server/basic.js +109 -24
- package/tests/hydration/compiled/server/events.js +161 -72
- package/tests/hydration/compiled/server/for.js +202 -102
- package/tests/hydration/compiled/server/if.js +130 -50
- package/tests/hydration/compiled/server/reactivity.js +51 -12
- package/tests/server/__snapshots__/compiler.test.ripple.snap +11 -4
- package/tests/server/basic.attributes.test.ripple +459 -0
- package/tests/server/basic.components.test.ripple +237 -0
- package/tests/server/basic.test.ripple +25 -0
- package/tests/server/compiler.test.ripple +2 -3
- package/tests/server/composite.props.test.ripple +161 -0
- package/tests/server/dynamic-elements.test.ripple +438 -0
- package/tests/server/head.test.ripple +102 -0
- package/tests/server/switch.test.ripple +40 -0
- package/tests/server/tsconfig.json +11 -0
- package/tests/server.d.ts +7 -0
- package/tests/setup-client.js +6 -2
- package/tests/setup-server.js +16 -0
- package/types/index.d.ts +2 -2
- package/types/server.d.ts +4 -3
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
is_void_element,
|
|
25
25
|
normalize_children,
|
|
26
26
|
is_binding_function,
|
|
27
|
+
build_getter,
|
|
28
|
+
is_element_dynamic,
|
|
27
29
|
} from '../../../utils.js';
|
|
28
30
|
import { escape } from '../../../../utils/escaping.js';
|
|
29
31
|
import { is_event_attribute } from '../../../../utils/events.js';
|
|
@@ -69,9 +71,27 @@ function transform_children(children, context) {
|
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
} else {
|
|
72
|
-
visit(node,
|
|
74
|
+
visit(node, state);
|
|
73
75
|
}
|
|
74
76
|
}
|
|
77
|
+
|
|
78
|
+
const head_elements = /** @type {AST.Element[]} */ (
|
|
79
|
+
children.filter(
|
|
80
|
+
(node) => node.type === 'Element' && node.id.type === 'Identifier' && node.id.name === 'head',
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (head_elements.length) {
|
|
85
|
+
state.init?.push(
|
|
86
|
+
b.stmt(b.assignment('=', b.member(b.id('__output'), b.id('target')), b.literal('head'))),
|
|
87
|
+
);
|
|
88
|
+
for (const head_element of head_elements) {
|
|
89
|
+
transform_children(head_element.children, context);
|
|
90
|
+
}
|
|
91
|
+
state.init?.push(
|
|
92
|
+
b.stmt(b.assignment('=', b.member(b.id('__output'), b.id('target')), b.literal(null))),
|
|
93
|
+
);
|
|
94
|
+
}
|
|
75
95
|
}
|
|
76
96
|
|
|
77
97
|
/**
|
|
@@ -108,15 +128,19 @@ const visitors = {
|
|
|
108
128
|
Identifier(node, context) {
|
|
109
129
|
const parent = /** @type {AST.Node} */ (context.path.at(-1));
|
|
110
130
|
|
|
111
|
-
if (is_reference(node, parent)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
if (is_reference(node, parent)) {
|
|
132
|
+
if (node.tracked) {
|
|
133
|
+
const is_right_side_of_assignment =
|
|
134
|
+
parent.type === 'AssignmentExpression' && parent.right === node;
|
|
135
|
+
if (
|
|
136
|
+
(parent.type !== 'AssignmentExpression' && parent.type !== 'UpdateExpression') ||
|
|
137
|
+
is_right_side_of_assignment
|
|
138
|
+
) {
|
|
139
|
+
return b.call('_$_.get', node);
|
|
140
|
+
}
|
|
119
141
|
}
|
|
142
|
+
|
|
143
|
+
return node;
|
|
120
144
|
}
|
|
121
145
|
},
|
|
122
146
|
|
|
@@ -459,41 +483,73 @@ const visitors = {
|
|
|
459
483
|
Element(node, context) {
|
|
460
484
|
const { state, visit } = context;
|
|
461
485
|
|
|
462
|
-
const
|
|
486
|
+
const dynamic_name = state.dynamicElementName;
|
|
487
|
+
if (dynamic_name) {
|
|
488
|
+
state.dynamicElementName = undefined;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const is_dom_element = !!dynamic_name || is_element_dom_element(node);
|
|
463
492
|
const is_spreading = node.attributes.some((attr) => attr.type === 'SpreadAttribute');
|
|
464
493
|
/** @type {(AST.Property | AST.SpreadElement)[] | null} */
|
|
465
494
|
const spread_attributes = is_spreading ? [] : null;
|
|
466
|
-
const child_namespace =
|
|
467
|
-
|
|
468
|
-
|
|
495
|
+
const child_namespace =
|
|
496
|
+
!dynamic_name && is_dom_element
|
|
497
|
+
? determine_namespace_for_children(
|
|
498
|
+
/** @type {AST.Identifier} */ (node.id).name,
|
|
499
|
+
state.namespace,
|
|
500
|
+
)
|
|
501
|
+
: state.namespace;
|
|
469
502
|
|
|
470
503
|
if (is_dom_element) {
|
|
471
|
-
const is_void =
|
|
504
|
+
const is_void = dynamic_name
|
|
505
|
+
? false
|
|
506
|
+
: is_void_element(/** @type {AST.Identifier} */ (node.id).name);
|
|
507
|
+
const tag_name = dynamic_name
|
|
508
|
+
? dynamic_name
|
|
509
|
+
: b.literal(/** @type {AST.Identifier} */ (node.id).name);
|
|
510
|
+
/** @type {AST.CSS.StyleSheet['hash'] | null} */
|
|
511
|
+
const scoping_hash =
|
|
512
|
+
state.applyParentCssScope ??
|
|
513
|
+
(node.metadata.scoped && state.component?.css
|
|
514
|
+
? /** @type {AST.CSS.StyleSheet} */ (state.component?.css).hash
|
|
515
|
+
: null);
|
|
472
516
|
|
|
473
517
|
state.init?.push(
|
|
474
|
-
b.stmt(
|
|
518
|
+
b.stmt(
|
|
519
|
+
b.call(
|
|
520
|
+
b.member(b.id('__output'), b.id('push')),
|
|
521
|
+
dynamic_name
|
|
522
|
+
? b.template([b.quasi('<', false), b.quasi('', false)], [tag_name])
|
|
523
|
+
: b.literal('<' + /** @type {AST.Literal} */ (tag_name).value),
|
|
524
|
+
),
|
|
525
|
+
),
|
|
475
526
|
);
|
|
476
527
|
let class_attribute = null;
|
|
477
528
|
|
|
478
529
|
/**
|
|
479
530
|
* @param {string} name
|
|
480
|
-
*
|
|
531
|
+
* @param {string | number | bigint | boolean | RegExp | null | undefined} value
|
|
532
|
+
* @param {'push' | 'unshift'} [spread_method]
|
|
481
533
|
*/
|
|
482
|
-
const handle_static_attr = (name, value) => {
|
|
483
|
-
const attr_str = ` ${name}${
|
|
484
|
-
is_boolean_attribute(name) && value === true
|
|
485
|
-
? ''
|
|
486
|
-
: `="${value === true ? '' : escape_html(value, true)}"`
|
|
487
|
-
}`;
|
|
488
|
-
|
|
534
|
+
const handle_static_attr = (name, value, spread_method = 'push') => {
|
|
489
535
|
if (is_spreading) {
|
|
490
536
|
// For spread attributes, store just the actual value, not the full attribute string
|
|
491
537
|
const actual_value =
|
|
492
538
|
is_boolean_attribute(name) && value === true
|
|
493
539
|
? b.literal(true)
|
|
494
540
|
: b.literal(value === true ? '' : value);
|
|
495
|
-
|
|
541
|
+
|
|
542
|
+
// spread_attributes cannot be null based on is_spreading === true
|
|
543
|
+
/** @type {(AST.Property | AST.SpreadElement)[]} */ (spread_attributes)[spread_method](
|
|
544
|
+
b.prop('init', b.literal(name), actual_value),
|
|
545
|
+
);
|
|
496
546
|
} else {
|
|
547
|
+
const attr_str = ` ${name}${
|
|
548
|
+
is_boolean_attribute(name) && value === true
|
|
549
|
+
? ''
|
|
550
|
+
: `="${value === true ? '' : escape_html(value, true)}"`
|
|
551
|
+
}`;
|
|
552
|
+
|
|
497
553
|
state.init?.push(
|
|
498
554
|
b.stmt(b.call(b.member(b.id('__output'), b.id('push')), b.literal(attr_str))),
|
|
499
555
|
);
|
|
@@ -533,7 +589,12 @@ const visitors = {
|
|
|
533
589
|
b.stmt(
|
|
534
590
|
b.call(
|
|
535
591
|
b.member(b.id('__output'), b.id('push')),
|
|
536
|
-
b.call(
|
|
592
|
+
b.call(
|
|
593
|
+
'_$_.attr',
|
|
594
|
+
b.literal(name),
|
|
595
|
+
expression,
|
|
596
|
+
b.literal(is_boolean_attribute(name)),
|
|
597
|
+
),
|
|
537
598
|
),
|
|
538
599
|
),
|
|
539
600
|
);
|
|
@@ -550,8 +611,8 @@ const visitors = {
|
|
|
550
611
|
if (attr_value.type === 'Literal') {
|
|
551
612
|
let value = attr_value.value;
|
|
552
613
|
|
|
553
|
-
if (
|
|
554
|
-
value = `${
|
|
614
|
+
if (scoping_hash) {
|
|
615
|
+
value = `${scoping_hash} ${value}`;
|
|
555
616
|
}
|
|
556
617
|
|
|
557
618
|
handle_static_attr(class_attribute.name.name, value);
|
|
@@ -561,9 +622,9 @@ const visitors = {
|
|
|
561
622
|
visit(attr_value, { ...state, metadata })
|
|
562
623
|
);
|
|
563
624
|
|
|
564
|
-
if (
|
|
625
|
+
if (scoping_hash) {
|
|
565
626
|
// Pass array to clsx so it can handle objects properly
|
|
566
|
-
expression = b.array([expression, b.literal(
|
|
627
|
+
expression = b.array([expression, b.literal(scoping_hash)]);
|
|
567
628
|
}
|
|
568
629
|
|
|
569
630
|
state.init?.push(
|
|
@@ -575,10 +636,8 @@ const visitors = {
|
|
|
575
636
|
),
|
|
576
637
|
);
|
|
577
638
|
}
|
|
578
|
-
} else if (
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
handle_static_attr('class', value);
|
|
639
|
+
} else if (scoping_hash) {
|
|
640
|
+
handle_static_attr('class', scoping_hash, is_spreading ? 'unshift' : 'push');
|
|
582
641
|
}
|
|
583
642
|
|
|
584
643
|
if (spread_attributes !== null && spread_attributes.length > 0) {
|
|
@@ -589,26 +648,60 @@ const visitors = {
|
|
|
589
648
|
b.call(
|
|
590
649
|
'_$_.spread_attrs',
|
|
591
650
|
b.object(spread_attributes),
|
|
592
|
-
|
|
593
|
-
? b.literal(state.component.css.hash)
|
|
594
|
-
: undefined,
|
|
651
|
+
scoping_hash ? b.literal(scoping_hash) : undefined,
|
|
595
652
|
),
|
|
596
653
|
),
|
|
597
654
|
),
|
|
598
655
|
);
|
|
599
656
|
}
|
|
600
657
|
|
|
601
|
-
state.init?.push(
|
|
658
|
+
state.init?.push(
|
|
659
|
+
b.stmt(
|
|
660
|
+
b.call(
|
|
661
|
+
b.member(b.id('__output'), b.id('push')),
|
|
662
|
+
b.literal(!node.selfClosing ? '>' : ' />'),
|
|
663
|
+
),
|
|
664
|
+
),
|
|
665
|
+
);
|
|
602
666
|
|
|
603
667
|
if (!is_void) {
|
|
668
|
+
/** @type {AST.Statement[]} */
|
|
669
|
+
const init = [];
|
|
604
670
|
transform_children(
|
|
605
671
|
node.children,
|
|
606
|
-
/** @type {TransformServerContext} */ ({
|
|
672
|
+
/** @type {TransformServerContext} */ ({
|
|
673
|
+
visit,
|
|
674
|
+
state: {
|
|
675
|
+
...state,
|
|
676
|
+
init,
|
|
677
|
+
...(state.applyParentCssScope ||
|
|
678
|
+
(dynamic_name && node.metadata.scoped && state.component?.css)
|
|
679
|
+
? {
|
|
680
|
+
applyParentCssScope:
|
|
681
|
+
state.applyParentCssScope ||
|
|
682
|
+
/** @type {AST.CSS.StyleSheet} */ (state.component?.css).hash,
|
|
683
|
+
}
|
|
684
|
+
: {}),
|
|
685
|
+
},
|
|
686
|
+
}),
|
|
607
687
|
);
|
|
608
688
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
689
|
+
if (init.length > 0) {
|
|
690
|
+
state.init?.push(b.block(init));
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if (!node.selfClosing) {
|
|
694
|
+
state.init?.push(
|
|
695
|
+
b.stmt(
|
|
696
|
+
b.call(
|
|
697
|
+
b.member(b.id('__output'), b.id('push')),
|
|
698
|
+
dynamic_name
|
|
699
|
+
? b.template([b.quasi('</', false), b.quasi('>', false)], [tag_name])
|
|
700
|
+
: b.literal('</' + /** @type {AST.Literal} */ (tag_name).value + '>'),
|
|
701
|
+
),
|
|
702
|
+
),
|
|
703
|
+
);
|
|
704
|
+
}
|
|
612
705
|
}
|
|
613
706
|
} else {
|
|
614
707
|
/** @type {(AST.Property | AST.SpreadElement)[]} */
|
|
@@ -616,23 +709,31 @@ const visitors = {
|
|
|
616
709
|
/** @type {AST.Expression | null} */
|
|
617
710
|
let children_prop = null;
|
|
618
711
|
|
|
712
|
+
if (state.applyParentCssScope) {
|
|
713
|
+
// We're inside a component, don't continue applying css hash to class
|
|
714
|
+
state.applyParentCssScope = undefined;
|
|
715
|
+
}
|
|
716
|
+
|
|
619
717
|
for (const attr of node.attributes) {
|
|
620
718
|
if (attr.type === 'Attribute') {
|
|
621
719
|
if (attr.name.type === 'Identifier') {
|
|
622
720
|
const metadata = { tracking: false, await: false };
|
|
623
|
-
let property =
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
721
|
+
let property =
|
|
722
|
+
attr.value === null
|
|
723
|
+
? b.literal(true)
|
|
724
|
+
: /** @type {AST.Expression} */ (
|
|
725
|
+
visit(/** @type {AST.Expression} */ (attr.value), {
|
|
726
|
+
...state,
|
|
727
|
+
metadata,
|
|
728
|
+
})
|
|
729
|
+
);
|
|
629
730
|
|
|
630
731
|
if (attr.name.name === 'children') {
|
|
631
|
-
children_prop = b.thunk(property);
|
|
732
|
+
children_prop = attr.name.tracked ? b.thunk(property) : property;
|
|
632
733
|
continue;
|
|
633
734
|
}
|
|
634
735
|
|
|
635
|
-
props.push(b.prop('init', attr.name, property));
|
|
736
|
+
props.push(b.prop('init', b.key(attr.name.name), property));
|
|
636
737
|
}
|
|
637
738
|
} else if (attr.type === 'SpreadAttribute') {
|
|
638
739
|
props.push(
|
|
@@ -666,6 +767,10 @@ const visitors = {
|
|
|
666
767
|
}
|
|
667
768
|
}
|
|
668
769
|
|
|
770
|
+
if (children_prop) {
|
|
771
|
+
props.push(b.prop('init', b.id('children'), children_prop));
|
|
772
|
+
}
|
|
773
|
+
|
|
669
774
|
if (children_filtered.length > 0) {
|
|
670
775
|
const component_scope = /** @type {ScopeInterface} */ (context.state.scopes.get(node));
|
|
671
776
|
const children = /** @type {AST.Expression} */ (
|
|
@@ -676,55 +781,96 @@ const visitors = {
|
|
|
676
781
|
})
|
|
677
782
|
);
|
|
678
783
|
|
|
679
|
-
|
|
680
|
-
/** @type {AST.ArrowFunctionExpression} */ (children_prop).body = b.logical(
|
|
681
|
-
'??',
|
|
682
|
-
/** @type {AST.Expression} */ (
|
|
683
|
-
/** @type {AST.ArrowFunctionExpression} */ (children_prop).body
|
|
684
|
-
),
|
|
685
|
-
children,
|
|
686
|
-
);
|
|
687
|
-
} else {
|
|
688
|
-
props.push(b.prop('init', b.id('children'), children));
|
|
689
|
-
}
|
|
784
|
+
props.push(b.prop('init', b.id('children'), children));
|
|
690
785
|
}
|
|
691
786
|
|
|
692
787
|
// For SSR, determine if we should await based on component metadata
|
|
693
|
-
const
|
|
694
|
-
/** @type {AST.Expression} */ (visit(node.id, state)),
|
|
695
|
-
b.id('__output'),
|
|
696
|
-
b.object(props),
|
|
697
|
-
);
|
|
788
|
+
const args = [b.id('__output'), b.object(props)];
|
|
698
789
|
|
|
699
790
|
// Check if this is a locally defined component and if it's async
|
|
700
791
|
const component_name = node.id.type === 'Identifier' ? node.id.name : null;
|
|
701
792
|
const local_metadata = component_name
|
|
702
793
|
? state.component_metadata.find((m) => m.id === component_name)
|
|
703
794
|
: null;
|
|
795
|
+
const comp_id = b.id('comp');
|
|
796
|
+
const args_id = b.id('args');
|
|
797
|
+
const comp_call = b.call(comp_id, b.spread(args_id));
|
|
798
|
+
const comp_call_regular = b.stmt(comp_call);
|
|
799
|
+
const comp_call_await = b.stmt(b.await(comp_call));
|
|
800
|
+
|
|
801
|
+
/** @type {AST.Statement[]} */
|
|
802
|
+
const init = [];
|
|
803
|
+
/** @type {AST.Statement[]} */
|
|
804
|
+
const statements = [
|
|
805
|
+
b.const(comp_id, /** @type {AST.Expression} */ (visit(node.id, state))),
|
|
806
|
+
b.const(args_id, b.array(args)),
|
|
807
|
+
];
|
|
704
808
|
|
|
705
809
|
if (local_metadata) {
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
810
|
+
if (local_metadata?.async) {
|
|
811
|
+
statements.push(comp_call_await);
|
|
812
|
+
|
|
813
|
+
if (state.metadata?.await === false) {
|
|
814
|
+
state.metadata.await = true;
|
|
815
|
+
}
|
|
709
816
|
} else {
|
|
710
|
-
|
|
817
|
+
statements.push(comp_call_regular);
|
|
818
|
+
}
|
|
819
|
+
} else if (!is_element_dynamic(node)) {
|
|
820
|
+
// it's imported element, so it could be async
|
|
821
|
+
statements.push(
|
|
822
|
+
b.if(
|
|
823
|
+
b.member(comp_id, b.id('async'), false, true),
|
|
824
|
+
b.block([comp_call_await]),
|
|
825
|
+
b.if(comp_id, b.block([comp_call_regular])),
|
|
826
|
+
),
|
|
827
|
+
);
|
|
828
|
+
|
|
829
|
+
if (state.metadata?.await === false) {
|
|
830
|
+
state.metadata.await = true;
|
|
711
831
|
}
|
|
712
832
|
} else {
|
|
713
|
-
//
|
|
714
|
-
//
|
|
715
|
-
|
|
833
|
+
// if it's a dynamic element, build the element output
|
|
834
|
+
// and store the results in the `init` array
|
|
835
|
+
visit(
|
|
836
|
+
node,
|
|
837
|
+
/** @type {TransformServerState} */ ({
|
|
838
|
+
...state,
|
|
839
|
+
dynamicElementName: b.template([b.quasi('', false), b.quasi('', false)], [comp_id]),
|
|
840
|
+
init,
|
|
841
|
+
}),
|
|
842
|
+
);
|
|
843
|
+
|
|
844
|
+
statements.push(
|
|
845
|
+
b.stmt(b.call(b.member(b.id('__output'), b.id('push')), b.literal(BLOCK_OPEN))),
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
statements.push(
|
|
716
849
|
b.if(
|
|
717
|
-
b.
|
|
718
|
-
b.block([
|
|
719
|
-
|
|
850
|
+
b.binary('===', b.unary('typeof', comp_id), b.literal('function')),
|
|
851
|
+
b.block([
|
|
852
|
+
b.if(
|
|
853
|
+
b.member(comp_id, b.id('async')),
|
|
854
|
+
b.block([comp_call_await]),
|
|
855
|
+
b.block([comp_call_regular]),
|
|
856
|
+
),
|
|
857
|
+
]),
|
|
858
|
+
// make sure that falsy values for dynamic element or component don't get rendered
|
|
859
|
+
b.if(comp_id, b.block(init)),
|
|
720
860
|
),
|
|
721
861
|
);
|
|
722
862
|
|
|
723
|
-
|
|
863
|
+
statements.push(
|
|
864
|
+
b.stmt(b.call(b.member(b.id('__output'), b.id('push')), b.literal(BLOCK_CLOSE))),
|
|
865
|
+
);
|
|
866
|
+
|
|
867
|
+
// Mark parent component as async since this child component could potentially be async
|
|
724
868
|
if (state.metadata?.await === false) {
|
|
725
869
|
state.metadata.await = true;
|
|
726
870
|
}
|
|
727
871
|
}
|
|
872
|
+
|
|
873
|
+
state.init?.push(b.block(statements));
|
|
728
874
|
}
|
|
729
875
|
},
|
|
730
876
|
|
|
@@ -1105,7 +1251,11 @@ const visitors = {
|
|
|
1105
1251
|
},
|
|
1106
1252
|
|
|
1107
1253
|
MemberExpression(node, context) {
|
|
1108
|
-
if (
|
|
1254
|
+
if (
|
|
1255
|
+
node.tracked ||
|
|
1256
|
+
((node.property.type === 'Identifier' || node.property.type === 'Literal') &&
|
|
1257
|
+
node.property.tracked)
|
|
1258
|
+
) {
|
|
1109
1259
|
return b.call(
|
|
1110
1260
|
'_$_.get_property',
|
|
1111
1261
|
/** @type {AST.Expression} */ (context.visit(node.object)),
|
|
@@ -39,6 +39,12 @@ export const mapping_data_verify_only = {
|
|
|
39
39
|
verification: true,
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
/** @type {Partial<VolarCodeMapping['data']>} */
|
|
43
|
+
export const mapping_data_verify_complete = {
|
|
44
|
+
verification: true,
|
|
45
|
+
completion: true,
|
|
46
|
+
};
|
|
47
|
+
|
|
42
48
|
/**
|
|
43
49
|
* Convert byte offset to line/column
|
|
44
50
|
* @param {number} offset
|
|
@@ -204,25 +210,42 @@ export function build_src_to_gen_map(
|
|
|
204
210
|
}
|
|
205
211
|
|
|
206
212
|
/**
|
|
207
|
-
* Look up generated position for a given source position
|
|
213
|
+
* Look up generated position for a given source position if it exists
|
|
208
214
|
* @param {number} src_line - 1-based line number in source
|
|
209
215
|
* @param {number} src_column - 0-based column number in source
|
|
210
216
|
* @param {CodeToGeneratedMap} src_to_gen_map - Lookup map
|
|
211
|
-
* @returns {CodePosition} Generated position
|
|
217
|
+
* @returns {CodePosition | Error} Generated position
|
|
212
218
|
*/
|
|
213
|
-
|
|
219
|
+
function maybe_get_generated_position(src_line, src_column, src_to_gen_map) {
|
|
214
220
|
const key = `${src_line}:${src_column}`;
|
|
215
221
|
const positions = src_to_gen_map.get(key);
|
|
216
222
|
|
|
217
223
|
if (!positions || positions.length === 0) {
|
|
218
|
-
|
|
219
|
-
throw new Error(`No source map entry for position "${src_line}:${src_column}"`);
|
|
224
|
+
return new Error(`No source map entry for position "${src_line}:${src_column}"`);
|
|
220
225
|
}
|
|
221
226
|
|
|
222
227
|
// If multiple generated positions map to same source, return the first
|
|
223
228
|
return positions[0];
|
|
224
229
|
}
|
|
225
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Look up generated position for a given source position
|
|
233
|
+
* @param {number} src_line - 1-based line number in source
|
|
234
|
+
* @param {number} src_column - 0-based column number in source
|
|
235
|
+
* @param {CodeToGeneratedMap} src_to_gen_map - Lookup map
|
|
236
|
+
* @returns {CodePosition} Generated position
|
|
237
|
+
*/
|
|
238
|
+
export function get_generated_position(src_line, src_column, src_to_gen_map) {
|
|
239
|
+
const maybe_position = maybe_get_generated_position(src_line, src_column, src_to_gen_map);
|
|
240
|
+
|
|
241
|
+
if (maybe_position instanceof Error) {
|
|
242
|
+
// No mapping found in source map - this shouldn't happen since all tokens should have mappings
|
|
243
|
+
throw maybe_position;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return maybe_position;
|
|
247
|
+
}
|
|
248
|
+
|
|
226
249
|
/**
|
|
227
250
|
* Convert line/column to byte offset
|
|
228
251
|
* @param {number} line
|
|
@@ -255,15 +278,15 @@ export function build_line_offsets(text) {
|
|
|
255
278
|
}
|
|
256
279
|
|
|
257
280
|
/**
|
|
258
|
-
* @param {AST.Node} node
|
|
281
|
+
* @param {AST.Node | AST.NodeWithLocation} node
|
|
259
282
|
* @param {CodeToGeneratedMap} src_to_gen_map
|
|
260
283
|
* @param {number[]} gen_line_offsets
|
|
261
284
|
* @param {Partial<VolarCodeMapping['data']>} [filtered_data]
|
|
262
285
|
* @param {number} [src_max_len]
|
|
263
286
|
* @param {number} [gen_max_len]
|
|
264
|
-
* @returns {CodeMapping}
|
|
287
|
+
* @returns {CodeMapping | Error}
|
|
265
288
|
*/
|
|
266
|
-
|
|
289
|
+
function maybe_get_mapping_from_node(
|
|
267
290
|
node,
|
|
268
291
|
src_to_gen_map,
|
|
269
292
|
gen_line_offsets,
|
|
@@ -276,10 +299,18 @@ export function get_mapping_from_node(
|
|
|
276
299
|
const src_length = src_max_len || src_end_offset - src_start_offset;
|
|
277
300
|
const loc = /** @type {AST.SourceLocation} */ (node.loc);
|
|
278
301
|
|
|
279
|
-
const gen_loc =
|
|
302
|
+
const gen_loc = maybe_get_generated_position(loc.start.line, loc.start.column, src_to_gen_map);
|
|
303
|
+
if (gen_loc instanceof Error) {
|
|
304
|
+
return gen_loc;
|
|
305
|
+
}
|
|
280
306
|
const gen_start_offset = loc_to_offset(gen_loc.line, gen_loc.column, gen_line_offsets);
|
|
281
|
-
|
|
307
|
+
|
|
308
|
+
const gen_end_loc = maybe_get_generated_position(loc.end.line, loc.end.column, src_to_gen_map);
|
|
309
|
+
if (gen_end_loc instanceof Error) {
|
|
310
|
+
return gen_end_loc;
|
|
311
|
+
}
|
|
282
312
|
const gen_end_offset = loc_to_offset(gen_end_loc.line, gen_end_loc.column, gen_line_offsets);
|
|
313
|
+
|
|
283
314
|
const gen_length = gen_max_len || gen_end_offset - gen_start_offset;
|
|
284
315
|
return {
|
|
285
316
|
sourceOffsets: [src_start_offset],
|
|
@@ -294,3 +325,36 @@ export function get_mapping_from_node(
|
|
|
294
325
|
},
|
|
295
326
|
};
|
|
296
327
|
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* @param {AST.Node | AST.NodeWithLocation} node
|
|
331
|
+
* @param {CodeToGeneratedMap} src_to_gen_map
|
|
332
|
+
* @param {number[]} gen_line_offsets
|
|
333
|
+
* @param {Partial<VolarCodeMapping['data']>} [filtered_data]
|
|
334
|
+
* @param {number} [src_max_len]
|
|
335
|
+
* @param {number} [gen_max_len]
|
|
336
|
+
* @returns {CodeMapping}
|
|
337
|
+
*/
|
|
338
|
+
export function get_mapping_from_node(
|
|
339
|
+
node,
|
|
340
|
+
src_to_gen_map,
|
|
341
|
+
gen_line_offsets,
|
|
342
|
+
filtered_data,
|
|
343
|
+
src_max_len,
|
|
344
|
+
gen_max_len,
|
|
345
|
+
) {
|
|
346
|
+
const mapping = maybe_get_mapping_from_node(
|
|
347
|
+
node,
|
|
348
|
+
src_to_gen_map,
|
|
349
|
+
gen_line_offsets,
|
|
350
|
+
filtered_data,
|
|
351
|
+
src_max_len,
|
|
352
|
+
gen_max_len,
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
if (mapping instanceof Error) {
|
|
356
|
+
throw mapping;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return mapping;
|
|
360
|
+
}
|