Skip to content

Commit 99f141f

Browse files
committed
all: fix more tests
1 parent 8d745ef commit 99f141f

13 files changed

Lines changed: 93 additions & 41 deletions

vlib/builtin/js/array.js.v

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ fn empty_array() array {
158158
return JS.makeEmptyArray()
159159
}
160160

161+
#function v_clone_for_array_value(value) {
162+
#if (value instanceof $ref || value instanceof voidptr || typeof value === 'function') return value;
163+
#return v_clone_value(value);
164+
#}
165+
161166
fn (a &array) set_len(i int) {
162167
#a.arr.arr.length=i
163168
}
@@ -208,19 +213,22 @@ pub fn (a array) slice(start int, end int) array {
208213

209214
pub fn (mut a array) insert(i int, val voidptr) {
210215
#a.val.arr.make_copy()
211-
#a.val.arr.arr.splice(i,0,val)
216+
#a.val.arr.arr.splice(i,0,v_clone_for_array_value(val))
217+
#a.val.arr.len.val = a.val.arr.arr.length
212218
}
213219

214220
pub fn (mut a array) insert_many(i int, val voidptr, size int) {
215-
#a.val.arr.arr.splice(i,0,...val.arr.slice(0,+size))
221+
#a.val.arr.make_copy()
222+
#a.val.arr.arr.splice(i,0,...val.arr.slice(0,+size).map(v_clone_for_array_value))
223+
#a.val.arr.len.val = a.val.arr.arr.length
216224
}
217225

218226
fn (mut a array) push(val voidptr) {
219227
#a.val.arr.make_copy()
220-
#if (arguments[2] && arguments[2].valueOf()) {a.val.arr.arr.push(...val)} else {
221-
#a.val.arr.arr.push(val)
228+
#if (arguments[2] && arguments[2].valueOf()) {a.val.arr.arr.push(...val.map(v_clone_for_array_value))} else {
229+
#a.val.arr.arr.push(v_clone_for_array_value(val))
222230
#}
223-
#a.val.arr.len.val += 1
231+
#a.val.arr.len.val = a.val.arr.arr.length
224232
}
225233

226234
fn v_filter(arr array, callback fn (voidptr) bool) array {
@@ -302,6 +310,7 @@ fn arr_copy(mut dst array, src array, count int) {
302310
pub fn (mut a array) delete_many(i int, size int) {
303311
#a.val.arr.make_copy()
304312
#a.val.arr.arr.splice(i.valueOf(),size.valueOf())
313+
#a.val.arr.len.val = a.val.arr.arr.length
305314
}
306315

307316
// prepend prepends one value to the array.
@@ -331,6 +340,7 @@ pub fn (mut a array) reverse_in_place() {
331340
pub fn (mut a array) clear() {
332341
#a.val.arr.make_copy()
333342
#a.val.arr.arr.length = 0
343+
#a.val.arr.len.val = 0
334344
}
335345

336346
// reduce executes a given reducer function on each element of the array, resulting in a single output value.
@@ -350,7 +360,7 @@ pub fn (mut a array) pop() voidptr {
350360
mut res := unsafe { nil }
351361
#a.val.arr.make_copy()
352362
#res = a.val.arr.arr.pop()
353-
#a.val.arr.len.val -= 1
363+
#a.val.arr.len.val = a.val.arr.arr.length
354364

355365
return res
356366
}

vlib/builtin/js/map.js.v

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub:
99
fn (mut m map) internal_set(key JS.Any, val JS.Any) {
1010
//$if es5 {
1111
#let skey = key;
12-
#if (key.hasOwnProperty('$toJS')) key = key.$toJS();
12+
#if (key != null && typeof key.$toJS === 'function') key = key.$toJS();
1313
#if (!(key in m.val.map)) {
1414
#m.val.length++;
1515
#m.val.map[key] = { key: skey, val: val };
@@ -27,7 +27,7 @@ fn (mut m map) internal_set(key JS.Any, val JS.Any) {
2727
fn (mut m map) internal_get(key JS.Any) JS.Any {
2828
mut val := JS.Any(unsafe { nil })
2929
//$if es5 {
30-
#if (typeof key != "string" && key.hasOwnProperty('$toJS')) key = key.$toJS();
30+
#if (typeof key != "string" && key != null && typeof key.$toJS === 'function') key = key.$toJS();
3131
#if (key in m.val.map) {
3232
#val = m.val.map[key].val
3333
#} else {
@@ -43,11 +43,11 @@ fn (mut m map) internal_get(key JS.Any) JS.Any {
4343

4444
#map.prototype.get = function (key) { return map_internal_get(this,key); }
4545
#map.prototype.set = function(key,val) { map_internal_set(this,key,val); }
46-
#map.prototype.has = function (key) { if (typeof key != "string" && key.hasOwnProperty('$toJS')) { key = key.$toJS() } return key in this.map; }
46+
#map.prototype.has = function (key) { if (typeof key != "string" && key != null && typeof key.$toJS === 'function') { key = key.$toJS() } return key in this.map; }
4747
// Removes the mapping of a particular key from the map.
4848
@[unsafe]
4949
pub fn (mut m map) delete(key JS.Any) {
50-
#let k = key.hasOwnProperty('$toJS') ? key.$toJS() : key;
50+
#let k = key != null && typeof key.$toJS === 'function' ? key.$toJS() : key;
5151

5252
#if (k in m.val.map) {
5353
#delete m.val.map[k];
@@ -91,4 +91,4 @@ pub fn (m map) values() array {
9191
#return res;
9292
#}
9393

94-
#map.prototype.getOrSet = function (key, init) { const skey = key; if (typeof key != "string" && key.hasOwnProperty('$toJS')) { key = key.$toJS() } if (key in this.map) { return this.map[key].val; } this.length++; this.map[key] = { key: skey, val: init }; return this.map[key].val; }
94+
#map.prototype.getOrSet = function (key, init) { const skey = key; if (typeof key != "string" && key != null && typeof key.$toJS === 'function') { key = key.$toJS() } if (key in this.map) { return this.map[key].val; } this.length++; this.map[key] = { key: skey, val: init }; return this.map[key].val; }

vlib/v/gen/c/cgen.v

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4454,14 +4454,12 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
44544454
return
44554455
}
44564456
}
4457-
// For auto-heap variables in generic contexts, the variable is
4458-
// already a pointer in C. Treat got_is_ptr as true to prevent
4459-
// adding a spurious `&`, and suppress the auto-heap deref in
4460-
// g.expr() so it emits `t` (the pointer) instead of `(*t)`.
4457+
// Auto-heap variables are already pointers in C. Treat them as
4458+
// pointer-backed here to avoid wrapping the raw pointer in an
4459+
// extra HEAP(...) and to suppress the usual auto-deref in g.expr().
44614460
mut effective_got_is_ptr := got_is_ptr
44624461
mut suppress_auto_heap_deref := false
4463-
if !got_is_ptr && g.cur_fn != unsafe { nil } && g.cur_concrete_types.len > 0
4464-
&& expr is ast.Ident && g.resolved_ident_is_auto_heap(expr) {
4462+
if !got_is_ptr && expr is ast.Ident && g.resolved_ident_is_auto_heap(expr) {
44654463
effective_got_is_ptr = true
44664464
suppress_auto_heap_deref = true
44674465
}

vlib/v/gen/c/fn.v

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6451,10 +6451,18 @@ fn (mut g Gen) ref_or_deref_arg_ex(arg ast.CallArg, expected_type_ ast.Type, lan
64516451
}
64526452
}
64536453
effective_arg_sym := g.table.sym(effective_arg_typ)
6454-
if effective_arg_typ.is_ptr() && effective_arg_typ.deref() == expected_ref_inner_type {
6454+
effective_arg_is_auto_heap_ident := effective_arg_expr is ast.Ident
6455+
&& g.resolved_ident_is_auto_heap(effective_arg_expr)
6456+
if (effective_arg_typ.is_ptr() && effective_arg_typ.deref() == expected_ref_inner_type)
6457+
|| (effective_arg_is_auto_heap_ident
6458+
&& effective_arg_typ.idx() == expected_ref_inner_type.idx()) {
64556459
g.prevent_sum_type_unwrapping_once = g.is_expr_smartcast_to_sumtype(effective_arg_expr,
64566460
expected_ref_inner_type)
6457-
g.expr(effective_arg_expr)
6461+
if effective_arg_is_auto_heap_ident {
6462+
g.write_raw_receiver_expr(effective_arg_expr)
6463+
} else {
6464+
g.expr(effective_arg_expr)
6465+
}
64586466
} else if effective_arg_sym.kind == expected_ref_inner_sym.kind
64596467
&& effective_arg_typ.idx() == expected_ref_inner_type.idx() {
64606468
g.prevent_sum_type_unwrapping_once = g.is_expr_smartcast_to_sumtype(effective_arg_expr,

vlib/v/gen/c/if.v

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ fn (mut g Gen) write_if_guard_gc_pin(scope &ast.Scope, name string, cvar_name st
3535
}
3636
}
3737

38-
fn (mut g Gen) if_guard_error_cleanup(_ string, _ ast.Type) {
39-
// TODO: the frees here cause double-free crashes when error objects
40-
// are shared/global (e.g. map access errors reuse the same MessageError).
41-
// Disabled until a safe ownership/refcounting mechanism is implemented.
38+
fn (mut g Gen) if_guard_error_cleanup(cvar_name string, expr_type ast.Type) {
39+
if expr_type.has_flag(.option) {
40+
g.writeln('\tif (${cvar_name}.state == 2 && ${cvar_name}.err._object != _const_none__._object) { builtin___v_free(${cvar_name}.err._object); }')
41+
} else if expr_type.has_flag(.result) {
42+
g.writeln('\tif (${cvar_name}.is_error && ${cvar_name}.err._object != _const_none__._object) { builtin___v_free(${cvar_name}.err._object); }')
43+
}
4244
}
4345

4446
fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool {
@@ -394,6 +396,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
394396
mut guard_vars := []string{}
395397
mut guard_expr_types := []ast.Type{len: node.branches.len}
396398
mut guard_else_uses_err := []bool{len: node.branches.len}
399+
mut guard_owns_error := []bool{len: node.branches.len}
397400
for i, branch in node.branches {
398401
cond := branch.cond
399402
if cond is ast.IfGuardExpr {
@@ -403,6 +406,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
403406
}
404407
guard_idx = i // saves the last if guard index
405408
guard_else_uses_err[i] = g.if_guard_else_uses_err(node, i)
409+
guard_owns_error[i] = cond.expr is ast.IndexExpr
406410
if cond.expr !in [ast.IndexExpr, ast.PrefixExpr] {
407411
var_name := g.new_tmp_var()
408412
guard_vars[i] = var_name
@@ -470,7 +474,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
470474
g.writeln('\tIError err = ${cvar_name}.err;')
471475
}
472476
}
473-
} else if guard_expr_types[guard_idx] != 0 {
477+
} else if guard_owns_error[guard_idx] && guard_expr_types[guard_idx] != 0 {
474478
g.if_guard_error_cleanup(cvar_name, guard_expr_types[guard_idx])
475479
}
476480
}
@@ -726,7 +730,8 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
726730
}
727731
}
728732
for i, var_name in guard_vars {
729-
if var_name == '' || guard_expr_types[i] == 0 || guard_else_uses_err[i] {
733+
if var_name == '' || guard_expr_types[i] == 0 || guard_else_uses_err[i]
734+
|| !guard_owns_error[i] {
730735
continue
731736
}
732737
if node.has_else && i == node.branches.len - 2 {

vlib/v/gen/c/str_intp.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,12 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
719719
const simple_string_interpolation_default_precision = 987698
720720

721721
fn (mut g Gen) gen_simple_string_inter_literal(node ast.StringInterLiteral, fmts []u8) bool {
722+
if g.is_autofree || g.pref.gc_mode == .boehm_leak {
723+
// The fast `string_plus_many` lowering can leave nested temporary
724+
// strings without scope cleanup in autofree/leak-detection modes.
725+
// Use the regular `str_intp` path there so temporaries remain explicit.
726+
return false
727+
}
722728
if node.exprs.len == 0 || node.expr_types.len < node.exprs.len {
723729
return false
724730
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
int (*real_open) (charptr , int , int ) = ((main__RealOpen)((dl__sym((voidptr)RTLD_NEXT, _S("open")))));
1+
int (*real_open) (charptr _d1, int _d2, int _d3) = ((main__RealOpen)((dl__sym(RTLD_NEXT, _S("open")))));

vlib/v/gen/c/testdata/dump_low_alloc.c.must_have

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
int _v_dump_expr_int(string fpath, int line, string sexpr, int dump_arg) {
1+
int_literal _v_dump_expr_int_literal(string fpath, int line, string sexpr, int_literal dump_arg) {
22
builtin___write_buf_to_fd(2, _S("[").str, _S("[").len);
33
builtin___write_buf_to_fd(2, sline.str, sline.len);
44
builtin___writeln_to_fd(2, value);
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
void main__IFoo_free(main__IFoo* it) {
22
if (it->_typ == _main__IFoo_main__Foo_index) { main__Foo_free(it->_main__Foo); return; }
3-
if (it->_typ == _main__IFoo_array_index) { array_free(it->_array); return; }
4-
if (it->_typ == _main__IFoo_map_index) { map_free(it->_map); return; }
5-
if (it->_typ == _main__IFoo_VAssertMetaInfo_index) { VAssertMetaInfo_free(it->_VAssertMetaInfo); return; }
6-
if (it->_typ == _main__IFoo_MessageError_index) { MessageError_free(it->_MessageError); return; }
7-
}
3+
if (it->_typ == _main__IFoo_array_index) { builtin__array_free(it->_array); return; }
4+
if (it->_typ == _main__IFoo_map_index) { builtin__map_free(it->_map); return; }
5+
if (it->_typ == _main__IFoo_MessageError_index) { builtin__MessageError_free(it->_MessageError); return; }
6+
if (it->_typ == _main__IFoo_VAssertMetaInfo_index) { builtin__VAssertMetaInfo_free(it->_VAssertMetaInfo); return; }
7+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
i32 ExternalSymbol(char* );
1+
i32 ExternalSymbol(char* _d1);
22
i32 a = ExternalSymbol("hello");
33
extern struct my_struct my_instance;

0 commit comments

Comments
 (0)