@@ -7,6 +7,7 @@ import { is } from '../../../proxy.js';
77import { queue_micro_task } from '../../task.js' ;
88import { hydrating } from '../../hydration.js' ;
99import { untrack } from '../../../runtime.js' ;
10+ import { is_runes } from '../../../context.js' ;
1011import { current_batch , previous_batch } from '../../../reactivity/batch.js' ;
1112
1213/**
@@ -16,6 +17,8 @@ import { current_batch, previous_batch } from '../../../reactivity/batch.js';
1617 * @returns {void }
1718 */
1819export function bind_value ( input , get , set = get ) {
20+ var runes = is_runes ( ) ;
21+
1922 var batches = new WeakSet ( ) ;
2023
2124 listen_to_event_and_reset_event ( input , 'input' , ( is_reset ) => {
@@ -27,8 +30,26 @@ export function bind_value(input, get, set = get) {
2730 /** @type {any } */
2831 var value = is_reset ? input . defaultValue : input . value ;
2932 value = is_numberlike_input ( input ) ? to_number ( value ) : value ;
30- set ( value ) ;
3133
34+ // handle both async and normal set callback
35+ Promise . resolve ( set ( value ) ) . then ( ( ) => {
36+ // In runes mode, respect any validation in accessors (doesn't apply in legacy mode,
37+ // because we use mutable state which ensures the render effect always runs)
38+ if ( runes && value !== ( value = get ( ) ) ) {
39+ var start = input . selectionStart ;
40+ var end = input . selectionEnd ;
41+
42+ // the value is coerced on assignment
43+ input . value = value ?? '' ;
44+
45+ // Restore selection
46+ if ( end !== null ) {
47+ input . selectionStart = start ;
48+ input . selectionEnd = Math . min ( end , input . value . length ) ;
49+ }
50+ }
51+ } ) ;
52+ // This ensures that the current batch is tracked for any changes related to the input event and is done at end
3253 if ( current_batch !== null ) {
3354 batches . add ( current_batch ) ;
3455 }
0 commit comments