@@ -29,6 +29,61 @@ export type ComponentProps<T extends ValidComponent> = T extends Component<infer
29
29
? JSX . IntrinsicElements [ T ]
30
30
: Record < string , unknown > ;
31
31
32
+ // these methods are duplicates from solid-js/web
33
+ // we need a better solution for this in the future
34
+ function escape ( s : any , attr ?: boolean ) {
35
+ const t = typeof s ;
36
+ if ( t !== "string" ) {
37
+ if ( ! attr && t === "function" ) return escape ( s ( ) ) ;
38
+ if ( ! attr && Array . isArray ( s ) ) {
39
+ for ( let i = 0 ; i < s . length ; i ++ ) s [ i ] = escape ( s [ i ] ) ;
40
+ return s ;
41
+ }
42
+ if ( attr && t === "boolean" ) return String ( s ) ;
43
+ return s ;
44
+ }
45
+ const delim = attr ? '"' : "<" ;
46
+ const escDelim = attr ? """ : "<" ;
47
+ let iDelim = s . indexOf ( delim ) ;
48
+ let iAmp = s . indexOf ( "&" ) ;
49
+
50
+ if ( iDelim < 0 && iAmp < 0 ) return s ;
51
+
52
+ let left = 0 ,
53
+ out = "" ;
54
+
55
+ while ( iDelim >= 0 && iAmp >= 0 ) {
56
+ if ( iDelim < iAmp ) {
57
+ if ( left < iDelim ) out += s . substring ( left , iDelim ) ;
58
+ out += escDelim ;
59
+ left = iDelim + 1 ;
60
+ iDelim = s . indexOf ( delim , left ) ;
61
+ } else {
62
+ if ( left < iAmp ) out += s . substring ( left , iAmp ) ;
63
+ out += "&" ;
64
+ left = iAmp + 1 ;
65
+ iAmp = s . indexOf ( "&" , left ) ;
66
+ }
67
+ }
68
+
69
+ if ( iDelim >= 0 ) {
70
+ do {
71
+ if ( left < iDelim ) out += s . substring ( left , iDelim ) ;
72
+ out += escDelim ;
73
+ left = iDelim + 1 ;
74
+ iDelim = s . indexOf ( delim , left ) ;
75
+ } while ( iDelim >= 0 ) ;
76
+ } else
77
+ while ( iAmp >= 0 ) {
78
+ if ( left < iAmp ) out += s . substring ( left , iAmp ) ;
79
+ out += "&" ;
80
+ left = iAmp + 1 ;
81
+ iAmp = s . indexOf ( "&" , left ) ;
82
+ }
83
+
84
+ return left < s . length ? out + s . substring ( left ) : out ;
85
+ }
86
+
32
87
function resolveSSRNode ( node : any ) : string {
33
88
const t = typeof node ;
34
89
if ( t === "string" ) return node ;
@@ -304,7 +359,7 @@ export function ErrorBoundary(props: {
304
359
} ) ;
305
360
if ( error ) return displayFallback ( ) ;
306
361
sync = false ;
307
- return { t : `<!--!$e${ id } -->${ resolveSSRNode ( res ) } <!--!$/e${ id } -->` } ;
362
+ return { t : `<!--!$e${ id } -->${ resolveSSRNode ( escape ( res ) ) } <!--!$/e${ id } -->` } ;
308
363
}
309
364
310
365
// Suspense Context
@@ -376,9 +431,9 @@ export function createResource<T, S>(
376
431
) : ResourceReturn < T > | ResourceReturn < T | undefined > {
377
432
378
433
if ( typeof fetcher !== "function" ) {
379
- source = true as ResourceSource < S > ;
380
- fetcher = source as ResourceFetcher < S , T > ;
381
434
options = ( fetcher || { } ) as ResourceOptions < T > | ResourceOptions < undefined > ;
435
+ fetcher = source as ResourceFetcher < S , T > ;
436
+ source = true as ResourceSource < S > ;
382
437
}
383
438
384
439
const contexts = new Set < SuspenseContextType > ( ) ;
@@ -585,7 +640,7 @@ export function Suspense(props: { fallback?: string; children: string }) {
585
640
completed : ( ) => {
586
641
const res = runSuspense ( ) ;
587
642
if ( suspenseComplete ( value ) ) {
588
- done ! ( resolveSSRNode ( res ) ) ;
643
+ done ! ( resolveSSRNode ( escape ( res ) ) ) ;
589
644
}
590
645
}
591
646
} ) ;
@@ -623,7 +678,7 @@ export function Suspense(props: { fallback?: string; children: string }) {
623
678
if ( ctx . async ) {
624
679
setHydrateContext ( { ...ctx , count : 0 , id : ctx . id + "0F" , noHydrate : true } ) ;
625
680
const res = {
626
- t : `<template id="pl-${ id } "></template>${ resolveSSRNode ( props . fallback ) } <!--pl-${ id } -->`
681
+ t : `<template id="pl-${ id } "></template>${ resolveSSRNode ( escape ( props . fallback ) ) } <!--pl-${ id } -->`
627
682
} ;
628
683
setHydrateContext ( ctx ) ;
629
684
return res ;
0 commit comments