33/** @import  { StandardSchemaV1 } from '@standard-schema/spec' */ 
44
55import  {  DEV  }  from  'esm-env' ; 
6- import  *  as  svelte  from  'svelte' ; 
7- // Svelte 4 and under don't have `untrack` - you'll not be able to use remote functions with Svelte 4 but this will still be loaded 
8- const  untrack  =  svelte . untrack  ??  ( ( value )  =>  value ( ) ) ; 
96
107/** 
11-  * Sets a value in a nested object using a path string, not  mutating the original object but returning a new  object 
8+  * Sets a value in a nested object using a path string, mutating the original object 
129 * @param  {Record<string, any> } object 
1310 * @param  {string } path_string 
1411 * @param  {any } value 
@@ -22,7 +19,7 @@ export function set_nested_value(object, path_string, value) {
2219value  =  value  ===  'on' ; 
2320} 
2421
25- return   deep_set ( object ,  split_path ( path_string ) ,  value ) ; 
22+ deep_set ( object ,  split_path ( path_string ) ,  value ) ; 
2623} 
2724
2825/** 
@@ -31,7 +28,7 @@ export function set_nested_value(object, path_string, value) {
3128 */ 
3229export  function  convert_formdata ( data )  { 
3330/** @type  {Record<string, any> } */ 
34- let  result  =  Object . create ( null ) ;   // guard against prototype pollution 
31+ const  result  =  { } ; 
3532
3633for  ( let  key  of  data . keys ( ) )  { 
3734if  ( key . startsWith ( 'sveltekit:' ) )  { 
@@ -61,7 +58,7 @@ export function convert_formdata(data) {
6158values  =  values . map ( ( v )  =>  v  ===  'on' ) ; 
6259} 
6360
64- result   =   set_nested_value ( result ,  key ,  is_array  ? values  : values [ 0 ] ) ; 
61+ set_nested_value ( result ,  key ,  is_array  ? values  : values [ 0 ] ) ; 
6562} 
6663
6764return  result ; 
@@ -81,18 +78,32 @@ export function split_path(path) {
8178} 
8279
8380/** 
84-  * Sets a value in a nested object using an array of keys. 
85-  * Does not mutate the original object; returns a new object. 
81+  * Check if a property key is dangerous and could lead to prototype pollution 
82+  * @param  {string } key 
83+  */ 
84+ function  check_prototype_pollution ( key )  { 
85+ if  ( key  ===  '__proto__'  ||  key  ===  'constructor'  ||  key  ===  'prototype' )  { 
86+ throw  new  Error ( 
87+ `Invalid key "${ key }   + 
88+ ( DEV  ? ': This key is not allowed to prevent prototype pollution.'  : '' ) 
89+ ) ; 
90+ } 
91+ } 
92+ 
93+ /** 
94+  * Sets a value in a nested object using an array of keys, mutating the original object. 
8695 * @param  {Record<string, any> } object 
8796 * @param  {string[] } keys 
8897 * @param  {any } value 
8998 */ 
9099export  function  deep_set ( object ,  keys ,  value )  { 
91- const  result  =  Object . assign ( Object . create ( null ) ,  object ) ;  // guard against prototype pollution 
92- let  current  =  result ; 
100+ let  current  =  object ; 
93101
94102for  ( let  i  =  0 ;  i  <  keys . length  -  1 ;  i  +=  1 )  { 
95103const  key  =  keys [ i ] ; 
104+ 
105+ check_prototype_pollution ( key ) ; 
106+ 
96107const  is_array  =  / ^ \d + $ / . test ( keys [ i  +  1 ] ) ; 
97108const  exists  =  key  in  current ; 
98109const  inner  =  current [ key ] ; 
@@ -101,18 +112,16 @@ export function deep_set(object, keys, value) {
101112throw  new  Error ( `Invalid array key ${ keys [ i  +  1 ] }  ) ; 
102113} 
103114
104- current [ key ]  =  is_array 
105- ? exists 
106- ? [ ...inner ] 
107- : [ ] 
108- : // guard against prototype pollution 
109- Object . assign ( Object . create ( null ) ,  inner ) ; 
115+ if  ( ! exists )  { 
116+ current [ key ]  =  is_array  ? [ ]  : { } ; 
117+ } 
110118
111119current  =  current [ key ] ; 
112120} 
113121
114- current [ keys [ keys . length  -  1 ] ]  =  value ; 
115- return  result ; 
122+ const  final_key  =  keys [ keys . length  -  1 ] ; 
123+ check_prototype_pollution ( final_key ) ; 
124+ current [ final_key ]  =  value ; 
116125} 
117126
118127/** 
@@ -196,18 +205,14 @@ export function deep_get(object, path) {
196205 * Creates a proxy-based field accessor for form data 
197206 * @param  {any } target - Function or empty POJO 
198207 * @param  {() => Record<string, any> } get_input - Function to get current input data 
199-  * @param  {(path: string) => void } depend - Function to make an effect depend on a specific field 
200208 * @param  {(path: (string | number)[], value: any) => void } set_input - Function to set input data 
201209 * @param  {() => Record<string, InternalRemoteFormIssue[]> } get_issues - Function to get current issues 
202210 * @param  {(string | number)[] } path - Current access path 
203211 * @returns  {any } Proxy object with name(), value(), and issues() methods 
204212 */ 
205- export  function  create_field_proxy ( target ,  get_input ,  depend ,  set_input ,  get_issues ,  path  =  [ ] )  { 
206- const  path_string  =  build_path_string ( path ) ; 
207- 
213+ export  function  create_field_proxy ( target ,  get_input ,  set_input ,  get_issues ,  path  =  [ ] )  { 
208214const  get_value  =  ( )  =>  { 
209- depend ( path_string ) ; 
210- return  untrack ( ( )  =>  deep_get ( get_input ( ) ,  path ) ) ; 
215+ return  deep_get ( get_input ( ) ,  path ) ; 
211216} ; 
212217
213218return  new  Proxy ( target ,  { 
@@ -216,7 +221,7 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
216221
217222// Handle array access like jobs[0] 
218223if  ( / ^ \d + $ / . test ( prop ) )  { 
219- return  create_field_proxy ( { } ,  get_input ,  depend ,   set_input ,  get_issues ,  [ 
224+ return  create_field_proxy ( { } ,  get_input ,  set_input ,  get_issues ,  [ 
220225...path , 
221226parseInt ( prop ,  10 ) 
222227] ) ; 
@@ -229,17 +234,11 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
229234set_input ( path ,  newValue ) ; 
230235return  newValue ; 
231236} ; 
232- return  create_field_proxy ( set_func ,  get_input ,  depend ,  set_input ,  get_issues ,  [ 
233- ...path , 
234- prop 
235- ] ) ; 
237+ return  create_field_proxy ( set_func ,  get_input ,  set_input ,  get_issues ,  [ ...path ,  prop ] ) ; 
236238} 
237239
238240if  ( prop  ===  'value' )  { 
239- return  create_field_proxy ( get_value ,  get_input ,  depend ,  set_input ,  get_issues ,  [ 
240- ...path , 
241- prop 
242- ] ) ; 
241+ return  create_field_proxy ( get_value ,  get_input ,  set_input ,  get_issues ,  [ ...path ,  prop ] ) ; 
243242} 
244243
245244if  ( prop  ===  'issues'  ||  prop  ===  'allIssues' )  { 
@@ -259,10 +258,7 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
259258} ) ) ; 
260259} ; 
261260
262- return  create_field_proxy ( issues_func ,  get_input ,  depend ,  set_input ,  get_issues ,  [ 
263- ...path , 
264- prop 
265- ] ) ; 
261+ return  create_field_proxy ( issues_func ,  get_input ,  set_input ,  get_issues ,  [ ...path ,  prop ] ) ; 
266262} 
267263
268264if  ( prop  ===  'as' )  { 
@@ -411,14 +407,11 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
411407} ) ; 
412408} ; 
413409
414- return  create_field_proxy ( as_func ,  get_input ,  depend ,  set_input ,  get_issues ,  [ 
415- ...path , 
416- 'as' 
417- ] ) ; 
410+ return  create_field_proxy ( as_func ,  get_input ,  set_input ,  get_issues ,  [ ...path ,  'as' ] ) ; 
418411} 
419412
420413// Handle property access (nested fields) 
421- return  create_field_proxy ( { } ,  get_input ,  depend ,   set_input ,  get_issues ,  [ ...path ,  prop ] ) ; 
414+ return  create_field_proxy ( { } ,  get_input ,  set_input ,  get_issues ,  [ ...path ,  prop ] ) ; 
422415} 
423416} ) ; 
424417} 
0 commit comments