From afa1a9abc26b46fa6588acb90bc73a4927c02bb5 Mon Sep 17 00:00:00 2001 From: GGRei Date: Tue, 30 Jan 2024 17:16:25 +0100 Subject: [PATCH] jsgen: fix inconsistent output (u32) in JS backend (#20691) --- vlib/v/gen/js/builtin_types.v | 22 ++++++++++++++++------ vlib/v/gen/js/str.v | 8 ++++++++ vlib/v/gen/js/tests/testdata/u32.out | 2 +- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/vlib/v/gen/js/builtin_types.v b/vlib/v/gen/js/builtin_types.v index 69118fcee8..b63bbc56b4 100644 --- a/vlib/v/gen/js/builtin_types.v +++ b/vlib/v/gen/js/builtin_types.v @@ -348,15 +348,25 @@ fn (mut g JsGen) gen_builtin_type_defs() { to_jsval: '+this' ) } - // u16 / u32 requires special handling in JavaScript to correctly represent it as an unsigned 32-bit integer. - // The '>>> 0' bit operation ensures it is treated as unsigned, covering the full 0 to 2^32-1 range. - // For u16, '>>> 0' combined with a mask of 0xffff limits it to the 0 to 2^16-1 range, correctly handling values as unsigned 16-bit integers. - 'u16', 'u32' { + // u16 and u32 requires special handling in JavaScript to correctly represent it. + // u16, '>>> 0' combined with a mask of 0xffff limits it to the 0 to 2^16-1 range, correctly handling values as unsigned 16-bit integers. + 'u16' { g.gen_builtin_prototype( typ_name: typ_name default_value: 'new Number(0)' - constructor: "this.val = Math.floor(Number(val) & ('" + typ_name + - '\' === "u16" ? 0xffff : 0xffffffff)) >>> 0' + constructor: 'this.val = Math.floor(Number(val) & 0xffff) >>> 0' + value_of: 'Number(this.val)' + to_string: 'this.valueOf().toString()' + eq: 'new bool(self.valueOf() === other.valueOf())' + to_jsval: '+this' + ) + } + // u32 '>>> 0' combined with a mask of 0xffffffff limits it to the 0 to 2^32-1 range, correctly handling values as unsigned 32-bit integers. + 'u32' { + g.gen_builtin_prototype( + typ_name: typ_name + default_value: 'new Number(0)' + constructor: 'this.val = Math.floor(Number(val) & 0xffffffff) >>> 0' value_of: 'Number(this.val)' to_string: 'this.valueOf().toString()' eq: 'new bool(self.valueOf() === other.valueOf())' diff --git a/vlib/v/gen/js/str.v b/vlib/v/gen/js/str.v index ae19585d82..23c850bddf 100644 --- a/vlib/v/gen/js/str.v +++ b/vlib/v/gen/js/str.v @@ -120,11 +120,19 @@ fn (mut g JsGen) gen_expr_to_string(expr ast.Expr, etype ast.Type) { is_var_mut := expr.is_auto_deref_var() str_fn_name := g.get_str_fn(typ) g.write('${str_fn_name}(') + if str_method_expects_ptr && !is_ptr { g.write('new \$ref(') } + if typ == ast.u32_type && expr is ast.CastExpr { + g.write('new u32(') + } g.expr(expr) + + if typ == ast.u32_type && expr is ast.CastExpr { + g.write(')') + } if (!str_method_expects_ptr && is_ptr && !is_shared) || is_var_mut { g.write('.val') } diff --git a/vlib/v/gen/js/tests/testdata/u32.out b/vlib/v/gen/js/tests/testdata/u32.out index 526c33e677..aa5799ae0e 100644 --- a/vlib/v/gen/js/tests/testdata/u32.out +++ b/vlib/v/gen/js/tests/testdata/u32.out @@ -1,4 +1,4 @@ --1 +4294967295 0 true 25600000