diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 81493c68fd..707735eec4 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -5565,6 +5565,18 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { node.expr_type = c.expr(node.expr) // type to be casted from_type_sym := c.table.get_type_symbol(node.expr_type) to_type_sym := c.table.get_type_symbol(node.typ) // type to be used as cast + + if (to_type_sym.is_number() && from_type_sym.name == 'JS.Number') + || (to_type_sym.is_number() && from_type_sym.name == 'JS.BigInt') + || (to_type_sym.is_string() && from_type_sym.name == 'JS.String') + || (node.typ.is_bool() && from_type_sym.name == 'JS.Boolean') + || (node.expr_type.is_bool() && to_type_sym.name == 'JS.Boolean') + || (from_type_sym.is_number() && to_type_sym.name == 'JS.Number') + || (from_type_sym.is_number() && to_type_sym.name == 'JS.BigInt') + || (from_type_sym.is_string() && to_type_sym.name == 'JS.String') { + return node.typ + } + if to_type_sym.language != .c { c.ensure_type_exists(node.typ, node.pos) or {} } diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 93b48a4936..7fe6037fe1 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -3226,8 +3226,39 @@ fn (mut g JsGen) gen_cast_tmp(tmp string, typ_ ast.Type) { fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) { is_literal := ((it.expr is ast.IntegerLiteral && it.typ in ast.integer_type_idxs) || (it.expr is ast.FloatLiteral && it.typ in ast.float_type_idxs)) + from_type_sym := g.table.get_type_symbol(it.expr_type) + to_type_sym := g.table.get_type_symbol(it.typ) // type to be used as cast + if it.typ.is_bool() && from_type_sym.name == 'JS.Boolean' { + g.write('new bool(') + g.expr(it.expr) + g.write(')') + return + } + if it.expr_type.is_bool() && to_type_sym.name == 'JS.Boolean' { + g.expr(it.expr) + g.write('.\$toJS()') + return + } + if (to_type_sym.is_number() && from_type_sym.name == 'JS.Number') + || (to_type_sym.is_number() && from_type_sym.name == 'JS.BigInt') + || (to_type_sym.is_string() && from_type_sym.name == 'JS.String') { + g.write('new ${to_type_sym.kind.str()}(') + g.expr(it.expr) + g.write(')') + return + } + + if (from_type_sym.is_number() && to_type_sym.name == 'JS.Number') + || (from_type_sym.is_number() && to_type_sym.name == 'JS.BigInt') + || (from_type_sym.is_string() && to_type_sym.name == 'JS.String') { + g.write('${g.typ(it.typ)}(') + g.expr(it.expr) + g.write('.\$toJS())') + return + } + // Skip cast if type is the same as the parrent caster - tsym := g.table.get_final_type_symbol(it.typ) + tsym := to_type_sym if tsym.kind == .sum_type { g.expr(it.expr) return diff --git a/vlib/v/tests/cast_test.js.v b/vlib/v/tests/cast_test.js.v new file mode 100644 index 0000000000..3a0e2a5607 --- /dev/null +++ b/vlib/v/tests/cast_test.js.v @@ -0,0 +1,12 @@ +fn JS.Math.pow(JS.Number, JS.Number) JS.Number + +fn test_js_prim_cast() { + x := JS.Number(f64(42.42)) + assert f64(x) == 42.42 + y := JS.BigInt(u64(18446744073709551615)) + assert u64(y) == u64(18446744073709551615) + z := JS.String('hello, world!') + assert string(z) == 'hello, world!' + w := int(JS.Math.pow(JS.Number(int(2)), JS.Number(int(3)))) + assert w == 8 +}