From 74faf2305c5d18430df7ddd30ac8252547c85838 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 18 Apr 2026 23:45:15 +0300 Subject: [PATCH] all: fix more tests --- vlib/builtin/builtin_print_write_error_test.v | 8 ++- vlib/builtin/builtin_windows.c.v | 4 +- vlib/builtin/js/array.js.v | 4 +- vlib/builtin/js/builtin.js.v | 3 +- vlib/builtin/js/string.js.v | 17 +++--- vlib/builtin/printing.c.v | 11 +++- vlib/db/pg/orm.v | 12 ++-- vlib/v/builder/builder.v | 6 +- vlib/v/gen/js/infix.v | 56 +++++++++++++++++++ vlib/v/gen/js/js.v | 52 +++++++++++++---- 10 files changed, 140 insertions(+), 33 deletions(-) diff --git a/vlib/builtin/builtin_print_write_error_test.v b/vlib/builtin/builtin_print_write_error_test.v index 7ccfda27c..0ccb6d339 100644 --- a/vlib/builtin/builtin_print_write_error_test.v +++ b/vlib/builtin/builtin_print_write_error_test.v @@ -20,8 +20,14 @@ fn main() { ' fn test_println_does_not_hang_on_failed_stdout_write() { + child_source_path := os.join_path(os.vtmp_dir(), + 'broken_stdout_child_${time.now().unix_milli()}.v') + os.write_file(child_source_path, broken_stdout_child_source)! + defer { + os.rm(child_source_path) or {} + } mut p := os.new_process(@VEXE) - p.set_args(['-e', broken_stdout_child_source]) + p.set_args(['run', child_source_path]) p.set_redirect_stdio() p.run() defer { diff --git a/vlib/builtin/builtin_windows.c.v b/vlib/builtin/builtin_windows.c.v index 6c323ae08..5bfd87b03 100644 --- a/vlib/builtin/builtin_windows.c.v +++ b/vlib/builtin/builtin_windows.c.v @@ -79,8 +79,8 @@ fn builtin_init() { C.SetConsoleMode(C.GetStdHandle(std_error_handle), enable_processed_output | enable_wrap_at_eol_output | evable_virtual_terminal_processing) unsafe { - C.setbuf(C.stdout, 0) - C.setbuf(C.stderr, 0) + set_stream_unbuffered(C.stdout) + set_stream_unbuffered(C.stderr) } } $if !no_backtrace ? { diff --git a/vlib/builtin/js/array.js.v b/vlib/builtin/js/array.js.v index a1b508baa..64ac932e1 100644 --- a/vlib/builtin/js/array.js.v +++ b/vlib/builtin/js/array.js.v @@ -163,11 +163,11 @@ fn (a &array) set_len(i int) { } pub fn (mut a array) sort_with_compare(compare voidptr) { - v_sort(mut a, compare) + #v_sort(a, compare instanceof voidptr ? compare.val : compare) } pub fn (mut a array) sort_with_compare_old(compare voidptr) { - #a.val.arr.arr.sort(compare) + #a.val.arr.arr.sort(compare instanceof voidptr ? compare.val : compare) } pub fn (mut a array) sort() { diff --git a/vlib/builtin/js/builtin.js.v b/vlib/builtin/js/builtin.js.v index 0fbafa8c4..093858386 100644 --- a/vlib/builtin/js/builtin.js.v +++ b/vlib/builtin/js/builtin.js.v @@ -122,7 +122,8 @@ pub fn print_backtrace() { pub fn (a array) clone() array { mut res := empty_array() - #const cloned = a.arr.arr.slice(a.arr.index_start.valueOf(), a.arr.index_start.valueOf() + a.len.valueOf()).map(v_clone_value) + #const source = a instanceof $ref ? a.val : a + #const cloned = source.arr.arr.slice(source.arr.index_start.valueOf(), source.arr.index_start.valueOf() + source.len.valueOf()).map(v_clone_value) #res = new array(new array_buffer({arr: cloned, len: new int(cloned.length), cap: new int(cloned.length), index_start: new int(0), has_slice: new bool(false)})) return res diff --git a/vlib/builtin/js/string.js.v b/vlib/builtin/js/string.js.v index 7550521bb..105e6ce64 100644 --- a/vlib/builtin/js/string.js.v +++ b/vlib/builtin/js/string.js.v @@ -278,7 +278,10 @@ pub fn (s string) int() int { // i64 returns the value of the string as i64 `'1'.i64() == i64(1)`. pub fn (s string) i64() i64 { - return i64(JS.parseInt(s.str)) + mut res := i64(0) + #res = new i64(BigInt(s.str)) + + return res } // i8 returns the value of the string as i8 `'1'.i8() == i8(1)`. @@ -319,16 +322,16 @@ pub fn (s string) u32() u32 { // u64 returns the value of the string as u64 `'1'.u64() == u64(1)`. pub fn (s string) u64() u64 { - return u64(JS.parseInt(s.str)) -} - -pub fn (s string) u8() u64 { - res := u8(0) - #res.val = u8(JS.parseInt(s.str)) + mut res := u64(0) + #res = new u64(BigInt(s.str)) return res } +pub fn (s string) u8() u8 { + return u8(JS.parseInt(s.str)) +} + // trim_right strips any of the characters given in `cutset` from the right of the string. // Example: assert ' Hello V d'.trim_right(' d') == ' Hello V' @[direct_array_access] diff --git a/vlib/builtin/printing.c.v b/vlib/builtin/printing.c.v index 7330afe5d..1a7ba664c 100644 --- a/vlib/builtin/printing.c.v +++ b/vlib/builtin/printing.c.v @@ -1,5 +1,14 @@ module builtin +fn C.setvbuf(voidptr, &char, i32, usize) i32 + +// set_stream_unbuffered switches a stdio stream to unbuffered mode without using the +// deprecated `setbuf` API on Windows toolchains. +@[unsafe] +fn set_stream_unbuffered(stream voidptr) { + C.setvbuf(stream, &char(nil), C._IONBF, usize(0)) +} + // eprintln prints a message with a line end, to stderr. Both stderr and stdout are flushed. @[if !noeprintln ?] pub fn eprintln(s string) { @@ -90,7 +99,7 @@ pub fn unbuffer_stdout() { not_implemented := 'unbuffer_stdout is not implemented\n' bare_eprint(not_implemented.str, u64(not_implemented.len)) } $else { - unsafe { C.setbuf(C.stdout, 0) } + unsafe { set_stream_unbuffered(C.stdout) } } } diff --git a/vlib/db/pg/orm.v b/vlib/db/pg/orm.v index 61f127b7b..da3730bac 100644 --- a/vlib/db/pg/orm.v +++ b/vlib/db/pg/orm.v @@ -80,32 +80,32 @@ pub fn (db DB) drop(table orm.Table) ! { } // orm_begin starts a transaction for ORM helpers. -pub fn (db DB) orm_begin() ! { +pub fn (mut db DB) orm_begin() ! { db.begin()! } // orm_commit commits a transaction for ORM helpers. -pub fn (db DB) orm_commit() ! { +pub fn (mut db DB) orm_commit() ! { db.commit()! } // orm_rollback rolls back a transaction for ORM helpers. -pub fn (db DB) orm_rollback() ! { +pub fn (mut db DB) orm_rollback() ! { db.rollback()! } // orm_savepoint creates a savepoint for ORM helpers. -pub fn (db DB) orm_savepoint(name string) ! { +pub fn (mut db DB) orm_savepoint(name string) ! { db.savepoint(name)! } // orm_rollback_to rolls back to a savepoint for ORM helpers. -pub fn (db DB) orm_rollback_to(name string) ! { +pub fn (mut db DB) orm_rollback_to(name string) ! { db.rollback_to(name)! } // orm_release_savepoint releases a savepoint for ORM helpers. -pub fn (db DB) orm_release_savepoint(name string) ! { +pub fn (mut db DB) orm_release_savepoint(name string) ! { db.release_savepoint(name)! } diff --git a/vlib/v/builder/builder.v b/vlib/v/builder/builder.v index 4c23f267f..52a8a36b3 100644 --- a/vlib/v/builder/builder.v +++ b/vlib/v/builder/builder.v @@ -65,13 +65,15 @@ mut: names map[string]bool } -fn (mut c CFunctionCallCollector) visit(node &ast.Node) ! { +fn c_function_call_collector_visit(node &ast.Node, data voidptr) bool { + mut c := unsafe { &CFunctionCallCollector(data) } if node is ast.Expr && node is ast.CallExpr { call := node as ast.CallExpr if call.name.starts_with('C.') { c.names[call.name] = true } } + return true } pub fn new_builder(pref_ &pref.Preferences) Builder { @@ -443,7 +445,7 @@ fn (mut b Builder) collect_used_c_function_calls(file &ast.File) map[string]bool mut collector := CFunctionCallCollector{ names: map[string]bool{} } - walker.walk(mut collector, file) + walker.inspect(file, &collector, c_function_call_collector_visit) return collector.names } diff --git a/vlib/v/gen/js/infix.v b/vlib/v/gen/js/infix.v index 500039fb1..96d0d5417 100644 --- a/vlib/v/gen/js/infix.v +++ b/vlib/v/gen/js/infix.v @@ -219,6 +219,34 @@ fn (mut g JsGen) infix_expr_eq_op(node ast.InfixExpr) { } else {} } + } else if !g.pref.output_es5 + && (left.sym.kind in [.i64, .u64] || right.sym.kind in [.i64, .u64]) { + if left.sym.kind in [.i64, .u64] && node.right is ast.IntegerLiteral { + g.expr(node.left) + g.gen_deref_ptr(node.left_type) + g.write('.valueOf() ${node.op.str()} ') + g.cast_stack << left.typ + g.expr(node.right) + g.cast_stack.delete_last() + g.gen_deref_ptr(node.right_type) + g.write('.valueOf()') + } else if right.sym.kind in [.i64, .u64] && node.left is ast.IntegerLiteral { + g.cast_stack << right.typ + g.expr(node.left) + g.cast_stack.delete_last() + g.gen_deref_ptr(node.left_type) + g.write('.valueOf() ${node.op.str()} ') + g.expr(node.right) + g.gen_deref_ptr(node.right_type) + g.write('.valueOf()') + } else { + g.expr(node.left) + g.gen_deref_ptr(node.left_type) + g.write('.valueOf() ${node.op.str()} ') + g.expr(node.right) + g.gen_deref_ptr(node.right_type) + g.write('.valueOf()') + } } else { g.expr(node.left) g.gen_deref_ptr(node.left_type) @@ -259,6 +287,34 @@ fn (mut g JsGen) infix_expr_cmp_op(node ast.InfixExpr) { g.gen_deref_ptr(right.typ) g.write(')') } + } else if !g.pref.output_es5 + && (left.sym.kind in [.i64, .u64] || right.sym.kind in [.i64, .u64]) { + if left.sym.kind in [.i64, .u64] && node.right is ast.IntegerLiteral { + g.expr(node.left) + g.gen_deref_ptr(node.left_type) + g.write('.valueOf() ${node.op.str()} ') + g.cast_stack << left.typ + g.expr(node.right) + g.cast_stack.delete_last() + g.gen_deref_ptr(node.right_type) + g.write('.valueOf()') + } else if right.sym.kind in [.i64, .u64] && node.left is ast.IntegerLiteral { + g.cast_stack << right.typ + g.expr(node.left) + g.cast_stack.delete_last() + g.gen_deref_ptr(node.left_type) + g.write('.valueOf() ${node.op.str()} ') + g.expr(node.right) + g.gen_deref_ptr(node.right_type) + g.write('.valueOf()') + } else { + g.expr(node.left) + g.gen_deref_ptr(node.left_type) + g.write('.valueOf() ${node.op.str()} ') + g.expr(node.right) + g.gen_deref_ptr(node.right_type) + g.write('.valueOf()') + } } else { g.expr(node.left) g.gen_deref_ptr(node.left_type) diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 5509d99f9..09d0fff0d 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -353,14 +353,14 @@ pub fn (mut g JsGen) gen_js_main_for_tests() { if g.pref.is_stats { g.writeln('let bt = main__start_testing(new int(${all_tfuncs.len}), new string("${g.pref.path}"))') } - for tname in all_tfuncs { + for i, tname in all_tfuncs { tcname := g.js_name(tname) if g.pref.is_stats { g.writeln('main__BenchedTests_testing_step_start(bt,new string("${tcname}"))') g.writeln('try {') } - g.writeln('let res = ${tcname}(); if (res instanceof Promise) { await res; }') + g.writeln('let res_${i} = ${tcname}(); if (res_${i} instanceof Promise) { await res_${i}; }') if g.pref.is_stats { g.writeln('} finally {') g.writeln('main__BenchedTests_testing_step_end(bt);') @@ -409,6 +409,30 @@ fn (g &JsGen) get_all_test_function_names() []string { return all_tfuncs } +fn (mut g JsGen) write_js_default_value(typ ast.Type) { + sym := g.table.sym(g.table.unaliased_type(typ)) + if sym.kind != .array_fixed { + g.write(g.to_js_typ_val(typ)) + return + } + info := sym.info as ast.ArrayFixed + tmp := g.new_tmp_var() + idx := g.new_tmp_var() + g.writeln('(function() {') + g.inc_indent() + g.writeln('const ${tmp} = [];') + g.writeln('for (let ${idx} = 0; ${idx} < ${info.size}; ${idx}++) {') + g.inc_indent() + g.write('${tmp}.push(') + g.write_js_default_value(info.elem_type) + g.writeln(');') + g.dec_indent() + g.writeln('}') + g.writeln('return new array(new array_buffer({arr: ${tmp}, len: new int(${info.size}), cap: new int(${info.size})}));') + g.dec_indent() + g.write('})()') +} + pub fn (mut g JsGen) enter_namespace(name string) { unsafe { if g.namespaces[name] == 0 { @@ -2070,7 +2094,7 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) { if field.has_default_expr { g.expr(field.default_expr) } else { - g.write('${g.to_js_typ_val(field.typ)}') + g.write_js_default_value(field.typ) } g.writeln('\n}') } @@ -2096,7 +2120,7 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) { } else if field.typ.has_flag(.option) { g.write('none__') } else { - g.write('${g.to_js_typ_val(field.typ)}') + g.write_js_default_value(field.typ) } } if i < node.fields.len - 1 { @@ -2208,8 +2232,7 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) { g.expr(it.init_expr) } else { // Fill the array with the default values for its type - t := g.to_js_typ_val(it.elem_type) - g.write(t) + g.write_js_default_value(it.elem_type) } g.writeln(');') g.dec_indent() @@ -2240,8 +2263,7 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) { g.expr(it.init_expr) } else { // Fill the array with the default values for its type - t := g.to_js_typ_val(it.elem_type) - g.write(t) + g.write_js_default_value(it.elem_type) } g.writeln(');') g.dec_indent() @@ -3858,10 +3880,18 @@ fn (mut g JsGen) gen_integer_literal_expr(it ast.IntegerLiteral) { // Skip cast if type is the same as the parent caster if g.cast_stack.len > 0 { - if g.cast_stack.last() in ast.integer_type_idxs { + cast_type := g.cast_stack.last() + if cast_type in ast.integer_type_idxs { + cast_sym := g.table.final_sym(cast_type) g.write('new ') - - g.write('int(${it.val})') + g.write(g.styp(cast_type)) + g.write('(') + if cast_sym.kind in [.i64, .u64] { + g.write('"${it.val}"') + } else { + g.write(it.val) + } + g.write(')') return } } -- 2.39.5