From 923b410d4d84ec851e53c8c179fda8b784db61c2 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 30 Dec 2023 23:04:27 +0200 Subject: [PATCH] x.vweb: fix `$vweb.html()` integration in cgen for the newer `x.vweb` module (fix #20204) --- examples/xvweb/todo/main.v | 4 +-- vlib/v/gen/c/cgen.v | 1 + vlib/v/gen/c/comptime.v | 28 +++++++++++++++---- vlib/v/gen/c/str_intp.v | 2 +- .../x/vweb/escape_html_strings_in_templates.v | 11 ++++++++ 5 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 vlib/x/vweb/escape_html_strings_in_templates.v diff --git a/examples/xvweb/todo/main.v b/examples/xvweb/todo/main.v index 5c4bd4b110434f..43a903d42aa774 100644 --- a/examples/xvweb/todo/main.v +++ b/examples/xvweb/todo/main.v @@ -39,9 +39,7 @@ pub fn (app &App) index(mut ctx Context) vweb.Result { todos := sql app.db { select from Todo } or { return ctx.server_error('could not fetch todos from database!') } - - // TODO: use $vweb.html() - return ctx.html($tmpl('templates/index.html')) + return $vweb.html() } // This method will only handle POST requests to the index page diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 8eed9200e67c51..3c1e1f862c0d7c 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -246,6 +246,7 @@ mut: has_reflection bool reflection_strings &map[string]int defer_return_tmp_var string + vweb_filter_fn_name string // vweb__filter or x__vweb__filter, used by $vweb.html() for escaping strings in the templates, depending on which `vweb` import is used } // global or const variable definition string diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index e07aa02f85227a..c176a6c0ecf026 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -59,25 +59,43 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) { cur_line = g.go_before_last_stmt() } + ret_sym := g.table.sym(g.fn_decl.return_type) + fn_name := g.fn_decl.name.replace('.', '__') + node.pos.pos.str() + is_x_vweb := ret_sym.cname == 'x__vweb__Result' + for stmt in node.vweb_tmpl.stmts { if stmt is ast.FnDecl { - // insert stmts from vweb_tmpl fn if stmt.name.starts_with('main.vweb_tmpl') { if is_html { g.inside_vweb_tmpl = true + if is_x_vweb { + g.vweb_filter_fn_name = 'x__vweb__filter' + } else { + g.vweb_filter_fn_name = 'vweb__filter' + } } + // insert stmts from vweb_tmpl fn g.stmts(stmt.stmts.filter(it !is ast.Return)) + // g.inside_vweb_tmpl = false + g.vweb_filter_fn_name = '' break } } } - fn_name := g.fn_decl.name.replace('.', '__') + node.pos.pos.str() if is_html { - // return vweb html template - app_name := g.fn_decl.params[0].name - g.writeln('vweb__Context_html(&${app_name}->Context, _tmpl_res_${fn_name}); strings__Builder_free(&sb_${fn_name}); string_free(&_tmpl_res_${fn_name});') + // return a vweb or x.vweb html template + if is_x_vweb { + ctx_name := g.fn_decl.params[1].name + g.writeln('x__vweb__Context_html(${ctx_name}, _tmpl_res_${fn_name});') + } else { + // old vweb: + app_name := g.fn_decl.params[0].name + g.writeln('vweb__Context_html(&${app_name}->Context, _tmpl_res_${fn_name});') + } + g.writeln('strings__Builder_free(&sb_${fn_name});') + g.writeln('string_free(&_tmpl_res_${fn_name});') } else { // return $tmpl string g.write(cur_line) diff --git a/vlib/v/gen/c/str_intp.v b/vlib/v/gen/c/str_intp.v index b3253e3de51971..9d0fbc3d0457c7 100644 --- a/vlib/v/gen/c/str_intp.v +++ b/vlib/v/gen/c/str_intp.v @@ -168,7 +168,7 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) { typ_sym := g.table.sym(typ) if typ == ast.string_type && g.comptime.comptime_for_method.len == 0 { if g.inside_vweb_tmpl { - g.write('vweb__filter(') + g.write('${g.vweb_filter_fn_name}(') if expr.is_auto_deref_var() && fmt != `p` { g.write('*') } diff --git a/vlib/x/vweb/escape_html_strings_in_templates.v b/vlib/x/vweb/escape_html_strings_in_templates.v new file mode 100644 index 00000000000000..cccbdff9862048 --- /dev/null +++ b/vlib/x/vweb/escape_html_strings_in_templates.v @@ -0,0 +1,11 @@ +module vweb + +import encoding.html + +// Do not delete. +// Calls to this function are generated by `fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) {` in vlib/v/gen/c/str_intp.v, +// for string interpolation inside vweb templates. +// TODO: move it to template render +fn filter(s string) string { + return html.escape(s) +}