From b1502d4ff1b235b3c3a915210faaa02404bc89a0 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 16 Dec 2024 11:54:46 -0300 Subject: [PATCH 1/2] parser,checker,cgen,fmt: fix array fixed option initialization (`none`) (complete #23164) (#23176) --- cmd/tools/vast/vast.v | 1 + vlib/v/ast/ast.v | 3 ++- vlib/v/checker/containers.v | 3 +++ vlib/v/fmt/fmt.v | 3 +++ vlib/v/gen/c/array.v | 16 +++++++++++++--- vlib/v/parser/containers.v | 1 + vlib/v/tests/array_fixed_none_init_test.v | 23 +++++++++++++++++++++++ 7 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/array_fixed_none_init_test.v diff --git a/cmd/tools/vast/vast.v b/cmd/tools/vast/vast.v index d39bb087baf608..f8e4db9828ee56 100644 --- a/cmd/tools/vast/vast.v +++ b/cmd/tools/vast/vast.v @@ -1645,6 +1645,7 @@ fn (t Tree) array_init(node ast.ArrayInit) &Node { obj.add('pre_cmnts', t.array_node_comment(node.pre_cmnts)) obj.add('elem_type_pos', t.pos(node.elem_type_pos)) obj.add_terse('is_fixed', t.bool_node(node.is_fixed)) + obj.add_terse('is_option', t.bool_node(node.is_option)) obj.add_terse('has_val', t.bool_node(node.has_val)) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('len_expr', t.expr(node.len_expr)) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 64cfead4abefea..b6b1bc0642c194 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1546,12 +1546,13 @@ pub: ecmnts [][]Comment // optional iembed comments after each expr pre_cmnts []Comment is_fixed bool + is_option bool // true if it was declared as ?[2]Type or ?[]Type has_val bool // fixed size literal `[expr, expr]!` mod string has_len bool has_cap bool has_init bool - has_index bool // true if temp variable index is used + has_index bool // true if temp variable index is used pub mut: exprs []Expr // `[expr, expr]` or `[expr]Type{}` for fixed array len_expr Expr // len: expr diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index b94dd7a0232e30..37cced8ab54e97 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -285,6 +285,9 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type { || c.array_fixed_has_unresolved_size(sym.info as ast.ArrayFixed) { mut size_expr := node.exprs[0] node.typ = c.eval_array_fixed_sizes(mut size_expr, 0, node.elem_type) + if node.is_option { + node.typ = node.typ.set_flag(.option) + } node.elem_type = (c.table.sym(node.typ).info as ast.ArrayFixed).elem_type } if node.has_init { diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 32925545ef3f1a..b3bfc4145c0095 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1818,6 +1818,9 @@ pub fn (mut f Fmt) array_decompose(node ast.ArrayDecompose) { } pub fn (mut f Fmt) array_init(node ast.ArrayInit) { + if node.is_fixed && node.is_option { + f.write('?') + } if node.exprs.len == 0 && node.typ != 0 && node.typ != ast.void_type { // `x := []string{}` f.mark_types_import_as_used(node.typ) diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index 1e8498df2395f6..f0c91673aca5e4 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -125,15 +125,20 @@ fn (mut g Gen) fixed_array_init(node ast.ArrayInit, array_type Type, var_name st g.set_current_pos_as_last_stmt_pos() return } - if g.inside_struct_init && g.inside_cast && !g.inside_memset { + is_none := node.is_option && !node.has_init && !node.has_val + + if (g.inside_struct_init && g.inside_cast && !g.inside_memset) || (node.is_option && !is_none) { ret_typ_str := g.styp(node.typ) g.write('(${ret_typ_str})') } elem_sym := g.table.final_sym(node.elem_type) is_struct := g.inside_array_fixed_struct && elem_sym.kind == .struct - if !is_struct { + if !is_struct && !is_none { g.write('{') } + if node.is_option && !is_none { + g.write('.state=0, .err=_const_none__, .data={') + } if node.has_val { tmp_inside_array := g.inside_array_item g.inside_array_item = true @@ -212,6 +217,8 @@ fn (mut g Gen) fixed_array_init(node ast.ArrayInit, array_type Type, var_name st }) schan_expr := g.out.cut_to(before_chan_expr_pos) g.write_c99_elements_for_array(array_info.size, schan_expr) + } else if is_none { + g.gen_option_error(node.typ, ast.None{}) } else { std := g.type_default(node.elem_type) if g.can_use_c99_designators() && std == '0' { @@ -226,7 +233,10 @@ fn (mut g Gen) fixed_array_init(node ast.ArrayInit, array_type Type, var_name st } } } - if !is_struct { + if node.is_option && !is_none { + g.write('}') + } + if !is_struct && !is_none { g.write('}') } } diff --git a/vlib/v/parser/containers.v b/vlib/v/parser/containers.v index 87ab37dcaa0659..496b0770202273 100644 --- a/vlib/v/parser/containers.v +++ b/vlib/v/parser/containers.v @@ -192,6 +192,7 @@ fn (mut p Parser) array_init(is_option bool, alias_array_type ast.Type) ast.Arra has_index: has_index cap_expr: cap_expr init_expr: init_expr + is_option: is_option } } diff --git a/vlib/v/tests/array_fixed_none_init_test.v b/vlib/v/tests/array_fixed_none_init_test.v new file mode 100644 index 00000000000000..b9eeef9dfd07b7 --- /dev/null +++ b/vlib/v/tests/array_fixed_none_init_test.v @@ -0,0 +1,23 @@ +fn test_none_init() { + a := ?[3]u8(none) + assert a == none + + b := ?[3]u8{} + assert b == none + + c := ?[3]u8{} + assert c == none +} + +fn foo() u8 { + return 123 +} + +fn test_non_none_init() { + c := ?[3]u8{init: 2} + assert c? == [u8(2), 2, 2]! + assert c != none + + d := ?[3]u8{init: foo()} + assert d? == [u8(123), 123, 123]! +} From 03f3f7a9ff9655c446e704d02cd35f6e04dfca73 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Mon, 16 Dec 2024 22:59:58 +0800 Subject: [PATCH 2/2] net.urllib: fix parse of url relative address (fix #21061) (#23180) --- vlib/net/urllib/urllib.v | 21 +++++++++++++-------- vlib/net/urllib/urllib_test.v | 6 ++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/vlib/net/urllib/urllib.v b/vlib/net/urllib/urllib.v index 22ec412c8c8137..22114362da63a9 100644 --- a/vlib/net/urllib/urllib.v +++ b/vlib/net/urllib/urllib.v @@ -436,11 +436,15 @@ fn split(s string, sep u8, cutc bool) (string, string) { pub fn parse(rawurl string) !URL { // Cut off #frag u, frag := split(rawurl, `#`, true) - mut url := parse_url(u, false) or { return error(error_msg(err_msg_parse, u)) } + mut url := parse_url(u, false) or { + return error(error_msg(err_msg_parse + '[${err.msg()}]', u)) + } if frag == '' { return url } - f := unescape(frag, .encode_fragment) or { return error(error_msg(err_msg_parse, u)) } + f := unescape(frag, .encode_fragment) or { + return error(error_msg(err_msg_parse + '[${err.msg()}]', u)) + } url.fragment = f return url } @@ -503,12 +507,13 @@ fn parse_url(rawurl string, via_request bool) !URL { // RFC 3986, ยง3.3: // In addition, a URI reference (Section 4.1) may be a relative-path reference, // in which case the first path segment cannot contain a colon (':') character. - colon := rest.index(':') or { return error('there should be a : in the URL') } - slash := rest.index('/') or { return error('there should be a / in the URL') } - if colon >= 0 && (slash < 0 || colon < slash) { - // First path segment has colon. Not allowed in relative URL. - return error(error_msg('parse_url: first path segment in URL cannot contain colon', - '')) + if colon := rest.index(':') { + slash := rest.index('/') or { return error('there should be a / in the URL') } + if colon >= 0 && (slash < 0 || colon < slash) { + // First path segment has colon. Not allowed in relative URL. + return error(error_msg('parse_url: first path segment in URL cannot contain colon', + '')) + } } } if ((url.scheme != '' || !via_request) && !rest.starts_with('///')) && rest.starts_with('//') diff --git a/vlib/net/urllib/urllib_test.v b/vlib/net/urllib/urllib_test.v index 8a3973c3d65bf7..6af3d07654b93d 100644 --- a/vlib/net/urllib/urllib_test.v +++ b/vlib/net/urllib/urllib_test.v @@ -102,6 +102,9 @@ fn test_parse() { 'foo://example.com:8042/over/there?name=ferret#nose', 'ftp://2001:0db8:85a3:0000:0000:8a2e:0370:7334/path/file.txt', 'ws://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:4000', + '/2000k/hls/mixed.m3u8', + '2000k/hls/mixed.m3u8', + './2000k:hls/mixed.m3u8', ] for url in urls { urllib.parse(url)! @@ -112,6 +115,9 @@ fn test_parse() { assert u.scheme == 'https' && u.hostname() == 'www.mydomain.com' && u.port() == '8080' && u.path == '/som/url' && u.fragment == 'testfragment' && u.user.username == 'joe' && u.user.password == 'pass' + + v := urllib.parse('https://vip.ffzy-online4.com/20230205/6094_d2720761/index.m3u8')!.resolve_reference(urllib.parse('2000k/hls/mixed.m3u8')!)! + assert v.str() == 'https://vip.ffzy-online4.com/20230205/6094_d2720761/2000k/hls/mixed.m3u8' } fn test_parse_authority() {