@@ -2,24 +2,26 @@ import { untrack } from '../index-client.js';
22import { ReactiveURLSearchParams } from './url-search-params.js' ;
33import { make_reactive } from './utils.js' ;
44
5- //
65// had to create a subclass for URLWithReactiveSearchParams
76// because we cannot change the internal `searchParams` reference (which links to the web api implementation) so it requires
87// some custom logic
9- //
108class URLWithReactiveSearchParams extends URL {
119 /**
1210 * @type {InstanceType<ReactiveURLSearchParams> }
1311 */
1412 #reactive_search_params;
1513
14+ /**
15+ * @type {boolean }
16+ */
17+ #is_in_middle_of_update = false ;
18+
1619 /**
1720 * @param {ConstructorParameters<typeof URL> } params
1821 */
1922 constructor ( ...params ) {
2023 super ( ...params ) ;
21-
22- this . #reactive_search_params = new ReactiveURLSearchParams ( super . searchParams ) ;
24+ this . #reactive_search_params = new ReactiveURLSearchParams ( super . search ) ;
2325 }
2426
2527 /**
@@ -34,88 +36,87 @@ class URLWithReactiveSearchParams extends URL {
3436 */
3537 get search ( ) {
3638 this . searchParams . toString ( ) ;
37- this . #sync_params_with_url ( 'search_params' ) ;
39+ this . #sync_params_with_url_if_not_blocked ( ) ;
3840 return super . search ;
3941 }
4042
4143 /**
4244 * @override
4345 */
4446 set search ( value ) {
47+ this . #is_in_middle_of_update = true ;
4548 super . search = value ;
4649 this . #sync_params_with_url( 'url' ) ;
50+ this . #is_in_middle_of_update = false ;
4751 }
4852
4953 /**
5054 * @override
5155 */
5256 get href ( ) {
5357 this . searchParams . toString ( ) ;
54- this . #sync_params_with_url ( 'search_params' ) ;
58+ this . #sync_params_with_url_if_not_blocked ( ) ;
5559 return super . href ;
5660 }
5761
5862 /**
5963 * @override
6064 */
6165 set href ( value ) {
66+ this . #is_in_middle_of_update = true ;
6267 super . href = value ;
6368 this . #sync_params_with_url( 'url' ) ;
69+ this . #is_in_middle_of_update = false ;
6470 }
6571
6672 /**
6773 * @param {"url" | "search_params" } changed_value
6874 */
6975 #sync_params_with_url( changed_value ) {
70- if ( super . searchParams . toString ( ) === this . searchParams . toString ( ) ) {
71- return ;
72- }
73-
74- if ( changed_value == 'url' ) {
75- this . #update_search_params_from_url( ) ;
76- } else {
77- // updating url from params
78- this . search = this . searchParams . toString ( ) ;
79- }
76+ untrack ( ( ) => {
77+ if (
78+ super . search . length === 0
79+ ? this . searchParams . size === 0
80+ : super . search === `?${ this . searchParams } `
81+ ) {
82+ return ;
83+ }
84+
85+ if ( changed_value == 'url' ) {
86+ this . #update_search_params_from_url( ) ;
87+ } else {
88+ // updating url from params
89+ this . search = this . searchParams . toString ( ) ;
90+ }
91+ } ) ;
8092 }
8193
8294 #update_search_params_from_url( ) {
83- /**
84- * keeping track of this is required because we have to keep the order in which they are updated
85- * @type {string[] }
86- */
87- const keys_with_no_change = [ ] ;
88-
8995 // remove keys that don't exist anymore and notify others
9096 for ( const [ key , value ] of Array . from ( this . searchParams . entries ( ) ) ) {
91- if ( ! super . searchParams . has ( key ) || value == super . searchParams . get ( key ) ) {
92- keys_with_no_change . push ( key ) ;
93- untrack ( ( ) => {
94- this . searchParams . delete ( key ) ;
95- } ) ;
96- continue ;
97- }
9897 this . searchParams . delete ( key ) ;
9998 }
10099
101100 // set or update keys based on the params
102101 for ( const [ key , value ] of super . searchParams . entries ( ) ) {
103- if ( keys_with_no_change . includes ( key ) ) {
104- untrack ( ( ) => {
105- this . searchParams . set ( key , value ) ;
106- } ) ;
107- continue ;
108- }
109102 this . searchParams . set ( key , value ) ;
110103 }
111104 }
112105
106+ #sync_params_with_url_if_not_blocked( ) {
107+ if ( ! this . #is_in_middle_of_update) {
108+ this . #is_in_middle_of_update = true ;
109+ this . #sync_params_with_url( 'search_params' ) ;
110+ this . #is_in_middle_of_update = false ;
111+ }
112+ }
113+
113114 /**
114115 * @override
115116 */
116117 toString ( ) {
117118 this . searchParams . toString ( ) ;
118- this . #sync_params_with_url ( 'search_params' ) ;
119+ this . #sync_params_with_url_if_not_blocked ( ) ;
119120 return super . toString ( ) ;
120121 }
121122}
@@ -201,7 +202,6 @@ export const ReactiveURL = make_reactive(URLWithReactiveSearchParams, {
201202 options . notify_read_properties ( [ 'href' , 'origin' , 'host' , 'port' ] ) ;
202203 return true ;
203204 } ,
204-
205205 pathname : ( options , ...params ) => {
206206 if ( options . value . pathname === add_character_if_not_exists ( params [ 0 ] , '/' , 'prepend' ) ) {
207207 return false ;
0 commit comments