ripple 0.2.216 → 0.3.1
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/CHANGELOG.md +52 -0
- package/package.json +16 -7
- package/src/compiler/errors.js +1 -1
- package/src/compiler/identifier-utils.js +2 -0
- package/src/compiler/index.d.ts +2 -6
- package/src/compiler/phases/1-parse/index.js +171 -233
- package/src/compiler/phases/2-analyze/index.js +192 -16
- package/src/compiler/phases/2-analyze/prune.js +2 -2
- package/src/compiler/phases/3-transform/client/index.js +308 -91
- package/src/compiler/phases/3-transform/segments.js +43 -15
- package/src/compiler/phases/3-transform/server/index.js +71 -21
- package/src/compiler/scope.js +31 -12
- package/src/compiler/source-map-utils.js +4 -6
- package/src/compiler/types/acorn.d.ts +11 -0
- package/src/compiler/types/estree-jsx.d.ts +11 -0
- package/src/compiler/types/estree.d.ts +11 -0
- package/src/compiler/types/import.d.ts +32 -18
- package/src/compiler/types/index.d.ts +75 -23
- package/src/compiler/types/parse.d.ts +7 -10
- package/src/compiler/utils.js +48 -0
- package/src/runtime/array.js +53 -22
- package/src/runtime/date.js +15 -5
- package/src/runtime/index-client.js +41 -7
- package/src/runtime/index-server.js +7 -7
- package/src/runtime/internal/client/bindings.js +2 -2
- package/src/runtime/internal/client/blocks.js +40 -1
- package/src/runtime/internal/client/context.js +8 -0
- package/src/runtime/internal/client/for.js +3 -3
- package/src/runtime/internal/client/index.js +27 -5
- package/src/runtime/internal/client/render.js +20 -8
- package/src/runtime/internal/client/runtime.js +9 -7
- package/src/runtime/internal/client/try.js +15 -22
- package/src/runtime/internal/client/utils.js +1 -1
- package/src/runtime/internal/server/context.js +8 -0
- package/src/runtime/internal/server/index.js +99 -6
- package/src/runtime/map.js +7 -7
- package/src/runtime/media-query.js +10 -1
- package/src/runtime/object.js +6 -6
- package/src/runtime/proxy.js +6 -6
- package/src/runtime/set.js +11 -11
- package/src/runtime/url-search-params.js +13 -2
- package/src/runtime/url.js +15 -5
- package/src/utils/builders.js +13 -3
- package/tests/client/array/array.copy-within.test.ripple +11 -11
- package/tests/client/array/array.derived.test.ripple +42 -42
- package/tests/client/array/array.iteration.test.ripple +12 -12
- package/tests/client/array/array.mutations.test.ripple +25 -25
- package/tests/client/array/array.static.test.ripple +103 -106
- package/tests/client/array/array.to-methods.test.ripple +8 -8
- package/tests/client/async-suspend.test.ripple +94 -0
- package/tests/client/basic/basic.attributes.test.ripple +31 -31
- package/tests/client/basic/basic.collections.test.ripple +7 -7
- package/tests/client/basic/basic.components.test.ripple +48 -10
- package/tests/client/basic/basic.errors.test.ripple +46 -31
- package/tests/client/basic/basic.events.test.ripple +11 -11
- package/tests/client/basic/basic.get-set.test.ripple +18 -18
- package/tests/client/basic/basic.reactivity.test.ripple +47 -42
- package/tests/client/basic/basic.rendering.test.ripple +7 -7
- package/tests/client/basic/basic.utilities.test.ripple +4 -4
- package/tests/client/boundaries.test.ripple +7 -7
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +2 -2
- package/tests/client/compiler/compiler.assignments.test.ripple +21 -21
- package/tests/client/compiler/compiler.basic.test.ripple +223 -82
- package/tests/client/compiler/compiler.tracked-access.test.ripple +8 -9
- package/tests/client/composite/composite.dynamic-components.test.ripple +8 -8
- package/tests/client/composite/composite.generics.test.ripple +4 -4
- package/tests/client/composite/composite.props.test.ripple +9 -9
- package/tests/client/composite/composite.reactivity.test.ripple +32 -26
- package/tests/client/composite/composite.render.test.ripple +13 -4
- package/tests/client/computed-properties.test.ripple +3 -3
- package/tests/client/context.test.ripple +3 -3
- package/tests/client/css/global-additional-cases.test.ripple +4 -4
- package/tests/client/css/style-identifier.test.ripple +49 -41
- package/tests/client/date.test.ripple +40 -40
- package/tests/client/dynamic-elements.test.ripple +165 -30
- package/tests/client/events.test.ripple +25 -25
- package/tests/client/for.test.ripple +76 -8
- package/tests/client/function-overload.test.ripple +0 -1
- package/tests/client/head.test.ripple +7 -7
- package/tests/client/html.test.ripple +2 -2
- package/tests/client/input-value.test.ripple +174 -176
- package/tests/client/map.test.ripple +21 -21
- package/tests/client/media-query.test.ripple +4 -4
- package/tests/client/object.test.ripple +12 -12
- package/tests/client/portal.test.ripple +4 -4
- package/tests/client/ref.test.ripple +5 -5
- package/tests/client/return.test.ripple +17 -17
- package/tests/client/set.test.ripple +16 -16
- package/tests/client/svg.test.ripple +6 -7
- package/tests/client/switch.test.ripple +10 -10
- package/tests/client/tracked-expression.test.ripple +1 -3
- package/tests/client/try.test.ripple +33 -4
- package/tests/client/url/url.derived.test.ripple +10 -9
- package/tests/client/url/url.parsing.test.ripple +10 -10
- package/tests/client/url/url.partial-removal.test.ripple +10 -10
- package/tests/client/url/url.reactivity.test.ripple +17 -17
- package/tests/client/url/url.serialization.test.ripple +4 -4
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +11 -10
- package/tests/client/url-search-params/url-search-params.initialization.test.ripple +5 -7
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +13 -13
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +19 -19
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +17 -17
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +5 -5
- package/tests/client/url-search-params/url-search-params.tracked-url.test.ripple +5 -5
- package/tests/hydration/compiled/client/events.js +8 -11
- package/tests/hydration/compiled/client/for.js +20 -23
- package/tests/hydration/compiled/client/head.js +17 -19
- package/tests/hydration/compiled/client/hmr.js +1 -3
- package/tests/hydration/compiled/client/html.js +1 -15
- package/tests/hydration/compiled/client/if-children.js +7 -9
- package/tests/hydration/compiled/client/if.js +5 -7
- package/tests/hydration/compiled/client/mixed-control-flow.js +3 -5
- package/tests/hydration/compiled/client/portal.js +1 -1
- package/tests/hydration/compiled/client/reactivity.js +9 -11
- package/tests/hydration/compiled/client/return.js +11 -13
- package/tests/hydration/compiled/client/switch.js +4 -6
- package/tests/hydration/compiled/server/basic.js +0 -1
- package/tests/hydration/compiled/server/composite.js +0 -3
- package/tests/hydration/compiled/server/events.js +8 -12
- package/tests/hydration/compiled/server/for.js +20 -23
- package/tests/hydration/compiled/server/head.js +17 -19
- package/tests/hydration/compiled/server/hmr.js +1 -4
- package/tests/hydration/compiled/server/html.js +1 -35
- package/tests/hydration/compiled/server/if-children.js +7 -11
- package/tests/hydration/compiled/server/if.js +5 -7
- package/tests/hydration/compiled/server/mixed-control-flow.js +3 -5
- package/tests/hydration/compiled/server/portal.js +1 -9
- package/tests/hydration/compiled/server/reactivity.js +9 -11
- package/tests/hydration/compiled/server/return.js +11 -13
- package/tests/hydration/compiled/server/switch.js +4 -6
- package/tests/hydration/components/events.ripple +8 -9
- package/tests/hydration/components/for.ripple +20 -21
- package/tests/hydration/components/head.ripple +6 -8
- package/tests/hydration/components/hmr.ripple +1 -2
- package/tests/hydration/components/html.ripple +1 -3
- package/tests/hydration/components/if-children.ripple +7 -8
- package/tests/hydration/components/if.ripple +5 -6
- package/tests/hydration/components/mixed-control-flow.ripple +4 -6
- package/tests/hydration/components/portal.ripple +1 -1
- package/tests/hydration/components/reactivity.ripple +9 -10
- package/tests/hydration/components/return.ripple +11 -12
- package/tests/hydration/components/switch.ripple +6 -8
- package/tests/server/await.test.ripple +2 -2
- package/tests/server/basic.attributes.test.ripple +19 -21
- package/tests/server/basic.components.test.ripple +13 -7
- package/tests/server/basic.test.ripple +20 -21
- package/tests/server/compiler.test.ripple +5 -5
- package/tests/server/composite.props.test.ripple +6 -7
- package/tests/server/composite.test.ripple +4 -4
- package/tests/server/context.test.ripple +1 -3
- package/tests/server/dynamic-elements.test.ripple +24 -24
- package/tests/server/head.test.ripple +5 -7
- package/tests/server/style-identifier.test.ripple +16 -17
- package/types/index.d.ts +266 -62
- package/types/server.d.ts +6 -6
|
@@ -183,6 +183,53 @@ function RipplePlugin(config) {
|
|
|
183
183
|
this.#filename = options?.rippleOptions.filename || null;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
/**
|
|
187
|
+
* @param {number} position
|
|
188
|
+
* @param {string} message
|
|
189
|
+
*/
|
|
190
|
+
#report_recoverable_error(position, message) {
|
|
191
|
+
const start = Math.max(0, Math.min(position, this.input.length));
|
|
192
|
+
const end = Math.min(this.input.length, start + 1);
|
|
193
|
+
const start_loc = acorn.getLineInfo(this.input, start);
|
|
194
|
+
const end_loc = acorn.getLineInfo(this.input, end);
|
|
195
|
+
|
|
196
|
+
error(
|
|
197
|
+
message,
|
|
198
|
+
this.#filename,
|
|
199
|
+
/** @type {AST.NodeWithLocation} */ ({
|
|
200
|
+
start,
|
|
201
|
+
end,
|
|
202
|
+
loc: {
|
|
203
|
+
start: start_loc,
|
|
204
|
+
end: end_loc,
|
|
205
|
+
},
|
|
206
|
+
}),
|
|
207
|
+
this.#loose ? this.#errors : undefined,
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* In loose mode, keep parsing after duplicate declaration diagnostics so
|
|
213
|
+
* editor tooling can continue producing AST and mappings.
|
|
214
|
+
* @param {number} position
|
|
215
|
+
* @param {string | { message?: string }} message
|
|
216
|
+
*/
|
|
217
|
+
raiseRecoverable(position, message) {
|
|
218
|
+
const error_message =
|
|
219
|
+
typeof message === 'string'
|
|
220
|
+
? message
|
|
221
|
+
: typeof message?.message === 'string'
|
|
222
|
+
? message.message
|
|
223
|
+
: String(message);
|
|
224
|
+
|
|
225
|
+
if (error_message.includes('has already been declared')) {
|
|
226
|
+
this.#report_recoverable_error(position, error_message);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return super.raiseRecoverable(position, error_message);
|
|
231
|
+
}
|
|
232
|
+
|
|
186
233
|
/**
|
|
187
234
|
* Override to allow single-parameter generic arrow functions without trailing comma.
|
|
188
235
|
* By default, @sveltejs/acorn-typescript throws an error for `<T>() => {}` when JSX is enabled
|
|
@@ -593,141 +640,72 @@ function RipplePlugin(config) {
|
|
|
593
640
|
|
|
594
641
|
if (code === 35) {
|
|
595
642
|
// # character
|
|
596
|
-
// Look ahead to see if this is followed by [ for tuple syntax or 'server' keyword
|
|
597
643
|
if (this.pos + 1 < this.input.length) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
644
|
+
/** @param {string} value */
|
|
645
|
+
const startsWith = (value) =>
|
|
646
|
+
this.input.slice(this.pos, this.pos + value.length) === value;
|
|
647
|
+
/** @param {number} length */
|
|
648
|
+
const char_after = (length) =>
|
|
649
|
+
this.pos + length < this.input.length ? this.input.charCodeAt(this.pos + length) : -1;
|
|
650
|
+
/** @param {number} ch */
|
|
651
|
+
const is_ripple_delimiter = (ch) =>
|
|
652
|
+
ch === 40 || // (
|
|
653
|
+
ch === 41 || // )
|
|
654
|
+
ch === 60 || // <
|
|
655
|
+
ch === 46 || // .
|
|
656
|
+
ch === 44 || // ,
|
|
657
|
+
ch === 59 || // ;
|
|
658
|
+
ch === 91 || // [
|
|
659
|
+
ch === 93 || // ]
|
|
660
|
+
ch === 123 || // {
|
|
661
|
+
ch === 125 || // }
|
|
662
|
+
ch === 32 || // space
|
|
663
|
+
ch === 9 || // tab
|
|
664
|
+
ch === 10 || // newline
|
|
665
|
+
ch === 13 || // carriage return
|
|
666
|
+
ch === -1; // EOF
|
|
667
|
+
|
|
668
|
+
if (startsWith('#ripple[')) {
|
|
669
|
+
this.pos += 8;
|
|
670
|
+
return this.finishToken(tt.bracketL, '#ripple[');
|
|
610
671
|
}
|
|
611
672
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
this.pos + 4 < this.input.length ? this.input.charCodeAt(this.pos + 4) : -1;
|
|
616
|
-
if (charAfter === 40 || charAfter === 60) {
|
|
617
|
-
// ( or < character (for generics like #Map<string, number>)
|
|
618
|
-
this.pos += 4; // consume '#Map'
|
|
619
|
-
return this.finishToken(tt.name, '#Map');
|
|
620
|
-
} else if (this.#loose) {
|
|
621
|
-
// In loose mode, produce token even without parens (incomplete syntax)
|
|
622
|
-
this.pos += 4; // consume '#Map'
|
|
623
|
-
return this.finishToken(tt.name, '#Map');
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
if (this.input.slice(this.pos, this.pos + 4) === '#Set') {
|
|
627
|
-
const charAfter =
|
|
628
|
-
this.pos + 4 < this.input.length ? this.input.charCodeAt(this.pos + 4) : -1;
|
|
629
|
-
if (charAfter === 40 || charAfter === 60) {
|
|
630
|
-
// ( or < character (for generics like #Set<number>)
|
|
631
|
-
this.pos += 4; // consume '#Set'
|
|
632
|
-
return this.finishToken(tt.name, '#Set');
|
|
633
|
-
} else if (this.#loose) {
|
|
634
|
-
// In loose mode, produce token even without parens (incomplete syntax)
|
|
635
|
-
this.pos += 4; // consume '#Set'
|
|
636
|
-
return this.finishToken(tt.name, '#Set');
|
|
637
|
-
}
|
|
673
|
+
if (startsWith('#ripple{')) {
|
|
674
|
+
this.pos += 8;
|
|
675
|
+
return this.finishToken(tt.braceL, '#ripple{');
|
|
638
676
|
}
|
|
639
677
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
}
|
|
678
|
+
const ripple_keywords = [
|
|
679
|
+
'#ripple.map',
|
|
680
|
+
'#ripple.set',
|
|
681
|
+
'#ripple.array',
|
|
682
|
+
'#ripple.object',
|
|
683
|
+
'#ripple.track',
|
|
684
|
+
'#ripple.trackSplit',
|
|
685
|
+
'#ripple.untrack',
|
|
686
|
+
'#ripple.effect',
|
|
687
|
+
'#ripple.context',
|
|
688
|
+
'#ripple.date',
|
|
689
|
+
'#ripple.url',
|
|
690
|
+
'#ripple.urlSearchParams',
|
|
691
|
+
'#ripple.mediaQuery',
|
|
692
|
+
'#ripple.server',
|
|
693
|
+
'#ripple.style',
|
|
694
|
+
'#ripple.validate',
|
|
695
|
+
];
|
|
659
696
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
this.pos
|
|
664
|
-
|
|
665
|
-
charAfter === 46 || // . (dot)
|
|
666
|
-
charAfter === 91 || // [
|
|
667
|
-
charAfter === 32 || // space
|
|
668
|
-
charAfter === 9 || // tab
|
|
669
|
-
charAfter === 10 || // newline
|
|
670
|
-
charAfter === 13 || // carriage return
|
|
671
|
-
charAfter === -1 // EOF
|
|
672
|
-
) {
|
|
673
|
-
// { or . or whitespace or EOF
|
|
674
|
-
this.pos += 6; // consume '#style'
|
|
675
|
-
return this.finishToken(tt.name, '#style');
|
|
697
|
+
for (let i = 0; i < ripple_keywords.length; i++) {
|
|
698
|
+
const keyword = ripple_keywords[i];
|
|
699
|
+
if (startsWith(keyword) && is_ripple_delimiter(char_after(keyword.length))) {
|
|
700
|
+
this.pos += keyword.length;
|
|
701
|
+
return this.finishToken(tt.name, keyword);
|
|
676
702
|
}
|
|
677
703
|
}
|
|
678
704
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
// In loose mode, allow incomplete identifiers like #M, #Ma, #S, #Se for autocomplete
|
|
683
|
-
if (nextChar >= 65 && nextChar <= 90) {
|
|
684
|
-
// A-Z
|
|
685
|
-
// Extract the identifier name
|
|
686
|
-
let identEnd = this.pos + 1;
|
|
687
|
-
while (identEnd < this.input.length) {
|
|
688
|
-
const ch = this.input.charCodeAt(identEnd);
|
|
689
|
-
if (
|
|
690
|
-
(ch >= 65 && ch <= 90) ||
|
|
691
|
-
(ch >= 97 && ch <= 122) ||
|
|
692
|
-
(ch >= 48 && ch <= 57) ||
|
|
693
|
-
ch === 95
|
|
694
|
-
) {
|
|
695
|
-
// A-Z, a-z, 0-9, _
|
|
696
|
-
identEnd++;
|
|
697
|
-
} else {
|
|
698
|
-
break;
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
const identName = this.input.slice(this.pos + 1, identEnd);
|
|
702
|
-
if (identName !== 'Map' && identName !== 'Set') {
|
|
703
|
-
// In loose mode, allow incomplete identifiers (prefixes of Map/Set)
|
|
704
|
-
// This supports autocomplete scenarios where user is still typing
|
|
705
|
-
const isIncompleteMap = 'Map'.startsWith(identName);
|
|
706
|
-
const isIncompleteSet = 'Set'.startsWith(identName);
|
|
707
|
-
|
|
708
|
-
if (!this.#loose || (!isIncompleteMap && !isIncompleteSet)) {
|
|
709
|
-
this.raise(
|
|
710
|
-
this.pos,
|
|
711
|
-
`Invalid tracked syntax '#${identName}'. Only #Map and #Set are currently supported using shorthand tracked syntax.`,
|
|
712
|
-
);
|
|
713
|
-
} else {
|
|
714
|
-
// In loose mode with valid prefix, consume the token and return it
|
|
715
|
-
// This allows the parser to handle incomplete syntax gracefully
|
|
716
|
-
this.pos = identEnd; // consume '#' + identifier
|
|
717
|
-
return this.finishToken(tt.name, '#' + identName);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
// In loose mode, handle bare # or # followed by unrecognized characters
|
|
723
|
-
if (this.#loose) {
|
|
724
|
-
this.pos++; // consume '#'
|
|
725
|
-
return this.finishToken(tt.name, '#');
|
|
705
|
+
if (this.#loose && startsWith('#ripple') && is_ripple_delimiter(char_after(7))) {
|
|
706
|
+
this.pos += 7;
|
|
707
|
+
return this.finishToken(tt.name, '#ripple');
|
|
726
708
|
}
|
|
727
|
-
} else if (this.#loose) {
|
|
728
|
-
// In loose mode, handle bare # at EOF
|
|
729
|
-
this.pos++; // consume '#'
|
|
730
|
-
return this.finishToken(tt.name, '#');
|
|
731
709
|
}
|
|
732
710
|
}
|
|
733
711
|
if (code === 64) {
|
|
@@ -927,40 +905,66 @@ function RipplePlugin(config) {
|
|
|
927
905
|
}
|
|
928
906
|
|
|
929
907
|
/**
|
|
930
|
-
* Parse expression atom - handles
|
|
908
|
+
* Parse expression atom - handles RippleArray and RippleObject literals
|
|
931
909
|
* @type {Parse.Parser['parseExprAtom']}
|
|
932
910
|
*/
|
|
933
911
|
parseExprAtom(refDestructuringErrors, forNew, forInit) {
|
|
912
|
+
const lookahead_type = this.lookahead().type;
|
|
913
|
+
const is_next_call_token = lookahead_type === tt.parenL || lookahead_type === tt.relational;
|
|
914
|
+
|
|
934
915
|
// Check if this is @(expression) for unboxing tracked values
|
|
935
916
|
if (this.type === tt.parenL && this.value === '@(') {
|
|
936
917
|
return this.parseTrackedExpression();
|
|
937
918
|
}
|
|
938
919
|
|
|
939
|
-
// Check if this is #server identifier for server function calls
|
|
940
|
-
if (this.type === tt.name && this.value === '#server') {
|
|
920
|
+
// Check if this is #ripple.server identifier for server function calls
|
|
921
|
+
if (this.type === tt.name && this.value === '#ripple.server') {
|
|
941
922
|
const node = this.startNode();
|
|
942
923
|
this.next();
|
|
943
924
|
return /** @type {AST.ServerIdentifier} */ (this.finishNode(node, 'ServerIdentifier'));
|
|
944
925
|
}
|
|
945
926
|
|
|
946
|
-
if (this.type === tt.name && this.value === '#style') {
|
|
927
|
+
if (this.type === tt.name && this.value === '#ripple.style') {
|
|
947
928
|
const node = this.startNode();
|
|
948
929
|
this.next();
|
|
949
930
|
return /** @type {AST.StyleIdentifier} */ (this.finishNode(node, 'StyleIdentifier'));
|
|
950
931
|
}
|
|
951
932
|
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
933
|
+
if (this.type === tt.name && typeof this.value === 'string') {
|
|
934
|
+
const ripple_identifier_map = {
|
|
935
|
+
'#ripple.array': 'RippleArray',
|
|
936
|
+
'#ripple.object': 'RippleObject',
|
|
937
|
+
'#ripple.track': 'track',
|
|
938
|
+
'#ripple.trackSplit': 'trackSplit',
|
|
939
|
+
'#ripple.untrack': 'untrack',
|
|
940
|
+
'#ripple.effect': 'effect',
|
|
941
|
+
'#ripple.context': 'Context',
|
|
942
|
+
'#ripple.date': 'RippleDate',
|
|
943
|
+
'#ripple.map': 'RippleMap',
|
|
944
|
+
'#ripple.set': 'RippleSet',
|
|
945
|
+
'#ripple.url': 'RippleURL',
|
|
946
|
+
'#ripple.urlSearchParams': 'RippleURLSearchParams',
|
|
947
|
+
'#ripple.mediaQuery': 'MediaQuery',
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
const identifier_name =
|
|
951
|
+
ripple_identifier_map[/** @type {keyof typeof ripple_identifier_map} */ (this.value)];
|
|
952
|
+
if (identifier_name !== undefined) {
|
|
953
|
+
const node = /** @type {AST.Identifier} */ (this.startNode());
|
|
954
|
+
node.name = identifier_name;
|
|
955
|
+
node.metadata ??= { path: [] };
|
|
956
|
+
node.metadata.source_name = this.value;
|
|
957
|
+
this.next();
|
|
958
|
+
return this.finishNode(node, 'Identifier');
|
|
959
|
+
}
|
|
956
960
|
}
|
|
957
961
|
|
|
958
|
-
// In loose mode, handle incomplete #
|
|
962
|
+
// In loose mode, handle incomplete #ripple prefixes for autocomplete
|
|
959
963
|
if (
|
|
960
964
|
this.#loose &&
|
|
961
965
|
this.type === tt.name &&
|
|
962
966
|
typeof this.value === 'string' &&
|
|
963
|
-
this.value
|
|
967
|
+
this.value === '#ripple'
|
|
964
968
|
) {
|
|
965
969
|
// Return an Identifier node for incomplete tracked syntax
|
|
966
970
|
const node = /** @type {AST.Identifier} */ (this.startNode());
|
|
@@ -969,11 +973,11 @@ function RipplePlugin(config) {
|
|
|
969
973
|
return this.finishNode(node, 'Identifier');
|
|
970
974
|
}
|
|
971
975
|
|
|
972
|
-
// Check if this is a tuple literal starting with #[
|
|
973
|
-
if (this.type === tt.bracketL && this.value === '#[') {
|
|
974
|
-
return this.
|
|
975
|
-
} else if (this.type === tt.braceL && this.value === '#{') {
|
|
976
|
-
return this.
|
|
976
|
+
// Check if this is a tuple literal starting with #ripple[
|
|
977
|
+
if (this.type === tt.bracketL && this.value === '#ripple[') {
|
|
978
|
+
return this.parseRippleArrayExpression();
|
|
979
|
+
} else if (this.type === tt.braceL && this.value === '#ripple{') {
|
|
980
|
+
return this.parseRippleObjectExpression();
|
|
977
981
|
}
|
|
978
982
|
|
|
979
983
|
// Check if this is a component expression (e.g., in object literal values)
|
|
@@ -1077,79 +1081,11 @@ function RipplePlugin(config) {
|
|
|
1077
1081
|
}
|
|
1078
1082
|
|
|
1079
1083
|
/**
|
|
1080
|
-
* Parse
|
|
1081
|
-
* Creates a TrackedMap or TrackedSet node with the arguments property
|
|
1082
|
-
* @type {Parse.Parser['parseTrackedCollectionExpression']}
|
|
1083
|
-
*/
|
|
1084
|
-
parseTrackedCollectionExpression(type) {
|
|
1085
|
-
const node =
|
|
1086
|
-
/** @type {(AST.TrackedMapExpression | AST.TrackedSetExpression) & AST.NodeWithLocation} */ (
|
|
1087
|
-
this.startNode()
|
|
1088
|
-
);
|
|
1089
|
-
this.next(); // consume '#Map' or '#Set'
|
|
1090
|
-
|
|
1091
|
-
// Check if we should NOT consume the parentheses
|
|
1092
|
-
// This happens when #Map/#Set appears as a callee in 'new #Map(...)'
|
|
1093
|
-
// In this case, the parentheses and arguments belong to the NewExpression
|
|
1094
|
-
// We detect this by checking if next token is '(' but we just consumed a token
|
|
1095
|
-
// that came right after 'new' keyword (indicated by context or recent token)
|
|
1096
|
-
|
|
1097
|
-
// Simple heuristic: if the input around our start position looks like 'new #Map('
|
|
1098
|
-
// then don't consume the parens
|
|
1099
|
-
const beforeStart = this.input.substring(Math.max(0, node.start - 5), node.start);
|
|
1100
|
-
const isAfterNew = /new\s*$/.test(beforeStart);
|
|
1101
|
-
|
|
1102
|
-
if (!isAfterNew) {
|
|
1103
|
-
// If we reach here, it means #Map or #Set is being called without 'new'
|
|
1104
|
-
// Throw a TypeError to match JavaScript class constructor behavior
|
|
1105
|
-
const constructorName =
|
|
1106
|
-
type === 'TrackedMapExpression' ? '#Map (TrackedMap)' : '#Set (TrackedSet)';
|
|
1107
|
-
this.raise(
|
|
1108
|
-
node.start,
|
|
1109
|
-
`TypeError: Class constructor ${constructorName} cannot be invoked without 'new'`,
|
|
1110
|
-
);
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
// Don't consume parens or generics - they belong to NewExpression
|
|
1114
|
-
// When used as "new #Map(...)" the next token is '('
|
|
1115
|
-
// When used as "new #Map<K,V>(...)" the next token is '<' (relational)
|
|
1116
|
-
if (this.type === tt.parenL || (this.type === tt.relational && this.value === '<')) {
|
|
1117
|
-
node.arguments = [];
|
|
1118
|
-
return this.finishNode(node, type);
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
this.expect(tt.parenL); // expect '('
|
|
1122
|
-
|
|
1123
|
-
node.arguments = [];
|
|
1124
|
-
// Parse arguments similar to function call arguments
|
|
1125
|
-
let first = true;
|
|
1126
|
-
while (!this.eat(tt.parenR)) {
|
|
1127
|
-
if (!first) {
|
|
1128
|
-
this.expect(tt.comma);
|
|
1129
|
-
if (this.afterTrailingComma(tt.parenR)) break;
|
|
1130
|
-
} else {
|
|
1131
|
-
first = false;
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
if (this.type === tt.ellipsis) {
|
|
1135
|
-
// Spread argument
|
|
1136
|
-
const arg = this.parseSpread();
|
|
1137
|
-
node.arguments.push(arg);
|
|
1138
|
-
} else {
|
|
1139
|
-
// Regular argument
|
|
1140
|
-
node.arguments.push(this.parseMaybeAssign(false));
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
return this.finishNode(node, type);
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
/**
|
|
1148
|
-
* @type {Parse.Parser['parseTrackedArrayExpression']}
|
|
1084
|
+
* @type {Parse.Parser['parseRippleArrayExpression']}
|
|
1149
1085
|
*/
|
|
1150
|
-
|
|
1151
|
-
const node = /** @type {AST.
|
|
1152
|
-
this.next(); // consume the '#['
|
|
1086
|
+
parseRippleArrayExpression() {
|
|
1087
|
+
const node = /** @type {AST.RippleArrayExpression} */ (this.startNode());
|
|
1088
|
+
this.next(); // consume the '#ripple['
|
|
1153
1089
|
|
|
1154
1090
|
node.elements = [];
|
|
1155
1091
|
|
|
@@ -1179,15 +1115,15 @@ function RipplePlugin(config) {
|
|
|
1179
1115
|
}
|
|
1180
1116
|
}
|
|
1181
1117
|
|
|
1182
|
-
return this.finishNode(node, '
|
|
1118
|
+
return this.finishNode(node, 'RippleArrayExpression');
|
|
1183
1119
|
}
|
|
1184
1120
|
|
|
1185
1121
|
/**
|
|
1186
|
-
* @type {Parse.Parser['
|
|
1122
|
+
* @type {Parse.Parser['parseRippleObjectExpression']}
|
|
1187
1123
|
*/
|
|
1188
|
-
|
|
1189
|
-
const node = /** @type {AST.
|
|
1190
|
-
this.next(); // consume the '#{'
|
|
1124
|
+
parseRippleObjectExpression() {
|
|
1125
|
+
const node = /** @type {AST.RippleObjectExpression} */ (this.startNode());
|
|
1126
|
+
this.next(); // consume the '#ripple{'
|
|
1191
1127
|
|
|
1192
1128
|
node.properties = [];
|
|
1193
1129
|
|
|
@@ -1214,7 +1150,7 @@ function RipplePlugin(config) {
|
|
|
1214
1150
|
}
|
|
1215
1151
|
}
|
|
1216
1152
|
|
|
1217
|
-
return this.finishNode(node, '
|
|
1153
|
+
return this.finishNode(node, 'RippleObjectExpression');
|
|
1218
1154
|
}
|
|
1219
1155
|
|
|
1220
1156
|
/**
|
|
@@ -1247,7 +1183,7 @@ function RipplePlugin(config) {
|
|
|
1247
1183
|
if (declareName) {
|
|
1248
1184
|
this.declareName(
|
|
1249
1185
|
node.id.name,
|
|
1250
|
-
BINDING_TYPES.
|
|
1186
|
+
BINDING_TYPES.BIND_FUNCTION,
|
|
1251
1187
|
/** @type {AST.NodeWithLocation} */ (node.id).start,
|
|
1252
1188
|
);
|
|
1253
1189
|
}
|
|
@@ -1256,7 +1192,7 @@ function RipplePlugin(config) {
|
|
|
1256
1192
|
if (declareName && node.id) {
|
|
1257
1193
|
this.declareName(
|
|
1258
1194
|
node.id.name,
|
|
1259
|
-
BINDING_TYPES.
|
|
1195
|
+
BINDING_TYPES.BIND_FUNCTION,
|
|
1260
1196
|
/** @type {AST.NodeWithLocation} */ (node.id).start,
|
|
1261
1197
|
);
|
|
1262
1198
|
}
|
|
@@ -2098,13 +2034,15 @@ function RipplePlugin(config) {
|
|
|
2098
2034
|
);
|
|
2099
2035
|
|
|
2100
2036
|
element.children = [
|
|
2101
|
-
/** @type {AST.ScriptContent} */ (
|
|
2102
|
-
type
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2037
|
+
/** @type {AST.ScriptContent} */ (
|
|
2038
|
+
/** @type {unknown} */ ({
|
|
2039
|
+
type: 'ScriptContent',
|
|
2040
|
+
content,
|
|
2041
|
+
start,
|
|
2042
|
+
end: closingStart,
|
|
2043
|
+
loc: { start: contentStartLoc, end: contentEndLoc },
|
|
2044
|
+
})
|
|
2045
|
+
),
|
|
2108
2046
|
];
|
|
2109
2047
|
|
|
2110
2048
|
this.#path.pop();
|
|
@@ -2495,16 +2433,16 @@ function RipplePlugin(config) {
|
|
|
2495
2433
|
);
|
|
2496
2434
|
}
|
|
2497
2435
|
|
|
2498
|
-
if (this.value === '#server') {
|
|
2499
|
-
// Peek ahead to see if this is a server block (#server { ... }) vs
|
|
2500
|
-
// a server identifier expression (#server.fn(), #server.fn().then())
|
|
2436
|
+
if (this.value === '#ripple.server') {
|
|
2437
|
+
// Peek ahead to see if this is a server block (#ripple.server { ... }) vs
|
|
2438
|
+
// a server identifier expression (#ripple.server.fn(), #ripple.server.fn().then())
|
|
2501
2439
|
let peek_pos = this.end;
|
|
2502
2440
|
while (peek_pos < this.input.length && /\s/.test(this.input[peek_pos])) peek_pos++;
|
|
2503
2441
|
if (peek_pos < this.input.length && this.input.charCodeAt(peek_pos) === 123) {
|
|
2504
2442
|
// Next non-whitespace character is '{' — parse as server block
|
|
2505
2443
|
return this.parseServerBlock();
|
|
2506
2444
|
}
|
|
2507
|
-
// Otherwise fall through to parse as expression statement (e.g., #server.fn().then(...))
|
|
2445
|
+
// Otherwise fall through to parse as expression statement (e.g., #ripple.server.fn().then(...))
|
|
2508
2446
|
}
|
|
2509
2447
|
|
|
2510
2448
|
if (this.value === 'component') {
|
|
@@ -2967,12 +2905,12 @@ function get_comment_handlers(source, comments, index = 0) {
|
|
|
2967
2905
|
node_array = parent.consequent;
|
|
2968
2906
|
} else if (
|
|
2969
2907
|
parent.type === 'ArrayExpression' ||
|
|
2970
|
-
parent.type === '
|
|
2908
|
+
parent.type === 'RippleArrayExpression'
|
|
2971
2909
|
) {
|
|
2972
2910
|
node_array = parent.elements;
|
|
2973
2911
|
} else if (
|
|
2974
2912
|
parent.type === 'ObjectExpression' ||
|
|
2975
|
-
parent.type === '
|
|
2913
|
+
parent.type === 'RippleObjectExpression'
|
|
2976
2914
|
) {
|
|
2977
2915
|
node_array = parent.properties;
|
|
2978
2916
|
} else if (
|