we (web engine): Experimental web browser project to understand the limits of Claude
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix parseInt default radix, array concat with empty arrays, and dead code

- parseInt: default radix 0 (auto-detect) instead of 10, so "0xFF" works
- array_concat: use array_length_exists() to correctly spread empty arrays
- Remove unused obj_proto parameter from error constructor helpers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+20 -16
+20 -16
crates/js/src/builtins.rs
··· 118 118 } 119 119 } 120 120 121 + /// Check whether an object has a "length" property (i.e. is array-like). 122 + fn array_length_exists(gc: &Gc<HeapObject>, obj: GcRef) -> bool { 123 + match gc.get(obj) { 124 + Some(HeapObject::Object(data)) => data.properties.contains_key("length"), 125 + _ => false, 126 + } 127 + } 128 + 121 129 /// Get an element by index from an array-like object. 122 130 fn array_get(gc: &Gc<HeapObject>, obj: GcRef, idx: usize) -> Value { 123 131 match gc.get(obj) { ··· 180 188 vm.set_global("Array", Value::Function(arr_ctor)); 181 189 182 190 // Create and register Error constructors. 183 - init_error_constructors(vm, obj_proto, err_proto); 191 + init_error_constructors(vm, err_proto); 184 192 185 193 // Register global utility functions. 186 194 init_global_functions(vm); ··· 1057 1065 match arg { 1058 1066 Value::Object(r) => { 1059 1067 let arg_len = array_length(ctx.gc, *r); 1060 - if arg_len > 0 { 1068 + // Only spread array-like objects (those with a length property). 1069 + if array_length_exists(ctx.gc, *r) { 1061 1070 for i in 0..arg_len { 1062 1071 items.push(array_get(ctx.gc, *r, i)); 1063 1072 } ··· 1307 1316 set_builtin_prop(gc, proto, "toString", Value::Function(to_string)); 1308 1317 } 1309 1318 1310 - fn init_error_constructors(vm: &mut Vm, obj_proto: GcRef, err_proto: GcRef) { 1319 + fn init_error_constructors(vm: &mut Vm, err_proto: GcRef) { 1311 1320 // Base Error. 1312 1321 let error_ctor = make_error_constructor(&mut vm.gc, "Error", err_proto); 1313 1322 vm.set_global("Error", Value::Function(error_ctor)); 1314 1323 1315 1324 // TypeError. 1316 - let te_proto = make_error_subclass_proto(&mut vm.gc, "TypeError", err_proto, obj_proto); 1325 + let te_proto = make_error_subclass_proto(&mut vm.gc, "TypeError", err_proto); 1317 1326 let te_ctor = make_error_constructor(&mut vm.gc, "TypeError", te_proto); 1318 1327 vm.set_global("TypeError", Value::Function(te_ctor)); 1319 1328 1320 1329 // ReferenceError. 1321 - let re_proto = make_error_subclass_proto(&mut vm.gc, "ReferenceError", err_proto, obj_proto); 1330 + let re_proto = make_error_subclass_proto(&mut vm.gc, "ReferenceError", err_proto); 1322 1331 let re_ctor = make_error_constructor(&mut vm.gc, "ReferenceError", re_proto); 1323 1332 vm.set_global("ReferenceError", Value::Function(re_ctor)); 1324 1333 1325 1334 // SyntaxError. 1326 - let se_proto = make_error_subclass_proto(&mut vm.gc, "SyntaxError", err_proto, obj_proto); 1335 + let se_proto = make_error_subclass_proto(&mut vm.gc, "SyntaxError", err_proto); 1327 1336 let se_ctor = make_error_constructor(&mut vm.gc, "SyntaxError", se_proto); 1328 1337 vm.set_global("SyntaxError", Value::Function(se_ctor)); 1329 1338 1330 1339 // RangeError. 1331 - let rae_proto = make_error_subclass_proto(&mut vm.gc, "RangeError", err_proto, obj_proto); 1340 + let rae_proto = make_error_subclass_proto(&mut vm.gc, "RangeError", err_proto); 1332 1341 let rae_ctor = make_error_constructor(&mut vm.gc, "RangeError", rae_proto); 1333 1342 vm.set_global("RangeError", Value::Function(rae_ctor)); 1334 1343 1335 1344 // URIError. 1336 - let ue_proto = make_error_subclass_proto(&mut vm.gc, "URIError", err_proto, obj_proto); 1345 + let ue_proto = make_error_subclass_proto(&mut vm.gc, "URIError", err_proto); 1337 1346 let ue_ctor = make_error_constructor(&mut vm.gc, "URIError", ue_proto); 1338 1347 vm.set_global("URIError", Value::Function(ue_ctor)); 1339 1348 1340 1349 // EvalError. 1341 - let ee_proto = make_error_subclass_proto(&mut vm.gc, "EvalError", err_proto, obj_proto); 1350 + let ee_proto = make_error_subclass_proto(&mut vm.gc, "EvalError", err_proto); 1342 1351 let ee_ctor = make_error_constructor(&mut vm.gc, "EvalError", ee_proto); 1343 1352 vm.set_global("EvalError", Value::Function(ee_ctor)); 1344 1353 } 1345 1354 1346 - fn make_error_subclass_proto( 1347 - gc: &mut Gc<HeapObject>, 1348 - name: &str, 1349 - parent_proto: GcRef, 1350 - _obj_proto: GcRef, 1351 - ) -> GcRef { 1355 + fn make_error_subclass_proto(gc: &mut Gc<HeapObject>, name: &str, parent_proto: GcRef) -> GcRef { 1352 1356 let mut data = ObjectData::new(); 1353 1357 data.prototype = Some(parent_proto); 1354 1358 data.properties.insert( ··· 1430 1434 .first() 1431 1435 .map(|v| v.to_js_string(ctx.gc)) 1432 1436 .unwrap_or_default(); 1433 - let radix = args.get(1).map(|v| v.to_number() as u32).unwrap_or(10); 1437 + let radix = args.get(1).map(|v| v.to_number() as u32).unwrap_or(0); 1434 1438 let s = s.trim(); 1435 1439 if s.is_empty() { 1436 1440 return Ok(Value::Number(f64::NAN));