From da93f26fa66bcadfc15f6033d1acd1fce2d73525 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 23 Apr 2026 21:56:08 +0300 Subject: [PATCH] jsgen: fix Playground `@LOCATION` and `@FILE_LINE` interpolation problems (fixes #23554) --- vlib/v/gen/js/js.v | 4 ++++ vlib/v/gen/js/jsgen_test.v | 23 +++++++++++++++++++++++ vlib/v/gen/js/str.v | 4 ++++ 3 files changed, 31 insertions(+) diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index e5c606ddc..3937286fd 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -3639,6 +3639,10 @@ fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) { continue } expr := it.exprs[i] + if expr is ast.AtExpr { + g.write(escape_template_literal_value(expr.val)) + continue + } // fmt := it.fmts[i] // fwidth := it.fwidths[i] // precision := it.precisions[i] diff --git a/vlib/v/gen/js/jsgen_test.v b/vlib/v/gen/js/jsgen_test.v index 91e90bfbf..be0d322f2 100644 --- a/vlib/v/gen/js/jsgen_test.v +++ b/vlib/v/gen/js/jsgen_test.v @@ -88,6 +88,29 @@ fn test_issue_20667_js_can_compile_game_of_life_example() { assert os.exists(output) } +fn test_issue_23554_js_browser_interpolated_at_exprs_do_not_emit_nested_templates() { + vexe := os.getenv('VEXE') + os.chdir(os.dir(vexe)) or {} + os.mkdir_all(output_dir) or { panic(err) } + program := os.join_path(output_dir, 'issue_23554.v') + output := os.join_path(output_dir, 'issue_23554.js') + source := [ + 'fn main() {', + "\tprintln('\${@LOCATION}')", + "\tprintln('\${@FILE_LINE}')", + "\tprintln('X \${@LOCATION}')", + "\tprintln('X \${@FILE_LINE}')", + '}', + ].join_lines() + os.write_file(program, source) or { panic(err) } + res := + os.execute('${os.quoted_path(vexe)} -b js_browser -o ${os.quoted_path(output)} ${os.quoted_path(program)}') + assert res.exit_code == 0, res.output + js := os.read_file(output) or { panic(err) } + assert !js.contains('new string(`' + '$' + '{"') + assert os.exists(output) +} + fn find_test_files() []string { files := os.ls(test_dir) or { panic(err) } // The life example never exits, so tests would hang with it, skip diff --git a/vlib/v/gen/js/str.v b/vlib/v/gen/js/str.v index 2421f3120..f13712cc9 100644 --- a/vlib/v/gen/js/str.v +++ b/vlib/v/gen/js/str.v @@ -2,6 +2,10 @@ module js import v.ast +fn escape_template_literal_value(s string) string { + return s.replace('\\', '\\\\').replace('`', '\\`').replace('$' + '{', '\\' + '$' + '{') +} + /* fn (mut g JsGen) gen_expr_to_string(expr ast.Expr, etype ast.Type) { is_shared := etype.has_flag(.shared_f) -- 2.39.5