diff --git a/vlib/builtin/js/map.js.v b/vlib/builtin/js/map.js.v index 94a88a5e0e..eec4815f46 100644 --- a/vlib/builtin/js/map.js.v +++ b/vlib/builtin/js/map.js.v @@ -10,7 +10,7 @@ fn (mut m map) internal_set(key JS.Any, val JS.Any) { //$if es5 { #if (key.hasOwnProperty('$toJS')) key = key.$toJS(); #if (!(key in m.val.map)) m.val.length++; - #m.val.map[key] = val + #m.val.map[key].val = val /*} $else { # if (key.hasOwnProperty('$toJS')) key = key.$toJS(); # m.val.m.set(key,val); @@ -23,7 +23,7 @@ fn (mut m map) internal_get(key JS.Any) JS.Any { mut val := JS.Any(unsafe { nil }) //$if es5 { #if (typeof key != "string" && key.hasOwnProperty('$toJS')) key = key.$toJS(); - #val = m.val.map[key] + #val = m.val.map[key].val /*} $else { # if (key.hasOwnProperty('$toJS')) key = key.$toJS(); # val = m.val.m.get(key) @@ -49,14 +49,14 @@ pub fn (m &map) free() {} pub fn (m map) keys() array { ret := JS.makeEmptyArray() - #for (var key in m.map) array_push(ret,new string(`${key}`),false); + #for (var key in m.map) array_push(ret,m.map[key].key,false) return ret } pub fn (m map) values() array { ret := JS.makeEmptyArray() - #for (var key in m.map) array_push(ret,m.map[key],false); + #for (var key in m.map) array_push(ret,m.map[key].val,false); return ret } diff --git a/vlib/v/gen/js/auto_str_methods.v b/vlib/v/gen/js/auto_str_methods.v index 4418aeb8d6..69aa06375d 100644 --- a/vlib/v/gen/js/auto_str_methods.v +++ b/vlib/v/gen/js/auto_str_methods.v @@ -610,7 +610,7 @@ fn (mut g JsGen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) g.definitions.writeln('\tlet keys = Object.keys(m.map);') g.definitions.writeln('\tfor (let j = 0; j < keys.length;j++) {') g.definitions.writeln('\t\tlet key = keys[j];') - g.definitions.writeln('\t\tlet value = m.map[key];') + g.definitions.writeln('\t\tlet value = m.map[key].val;') g.definitions.writeln('\t\tkey = new ${key_styp}(key);') if key_sym.kind == .string { g.definitions.writeln('\t\tstrings__Builder_write_string(sb, new string("\'" + key.str + "\'"));') diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 551a63d8b5..c3fc0713a4 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -1328,7 +1328,7 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) { g.expr(left.left) g.write('.map[') g.expr(left.index) - g.write('.\$toJS()] = ') + g.write('.\$toJS()] = { val: ') } else { g.write('.arr.set(') g.write('new int(') @@ -1426,6 +1426,11 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) { if array_set && !map_set { g.write(')') } + if left is ast.IndexExpr && left.is_map { + g.write(', key: ') + g.expr(left.index) + g.write(' }') + } if semicolon { if g.inside_loop { g.write('; ') @@ -1511,7 +1516,7 @@ fn (mut g JsGen) gen_enum_decl(it ast.EnumDecl) { if field.has_expr && field.expr is ast.IntegerLiteral { i = field.expr.val.int() } - g.writeln('${i},') + g.writeln('new int(${i}),') i++ } g.dec_indent() @@ -1707,7 +1712,7 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) { g.writeln('for (var ${tmp2} in ${tmp}.map) {') g.inc_indent() - g.writeln('let ${val} = ${tmp}.map[${tmp2}];') + g.writeln('let ${val} = ${tmp}.map[${tmp2}].val;') sym := g.table.sym(it.key_type) if sym.is_number() { g.writeln('let ${key} = new ${g.styp(it.key_type)}(+${tmp2})') @@ -3216,8 +3221,11 @@ fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) { g.write('[') g.expr(key) g.write('.\$toJS()]') - g.write(': ') + g.write(': { val: ') g.expr(val) + g.write(', key: ') + g.expr(key) + g.write(' }') if i < it.keys.len - 1 { g.write(',') } diff --git a/vlib/v/gen/js/tests/map.v b/vlib/v/gen/js/tests/map.v index 042c725116..1f03b73f67 100644 --- a/vlib/v/gen/js/tests/map.v +++ b/vlib/v/gen/js/tests/map.v @@ -1,8 +1,17 @@ +type T0 = int | string +type T1 = T0 | rune + struct Point { x f64 y f64 } +enum Colors { + red = 1 + green + blue +} + fn generic_map[T](items map[string]T) []T { return items.values() } @@ -226,17 +235,111 @@ fn test_map_len() { assert items_2.len == 2 } -fn test_rune_keys() { - mut m := { +fn test_map_with_different_key_types() { + // map[int]string + mut items_1 := { + 1: 'one' + 2: 'two' + 3: 'three' + } + assert typeof(items_1).name == 'map[int]string' + assert items_1[2] == 'two' + items_1[4] = 'four' + assert items_1[4].len == 4 + keys_1 := items_1.keys() + assert keys_1.contains(1) + assert keys_1.contains(2) + assert keys_1.contains(3) + assert keys_1.contains(4) + assert '${items_1}' == "{1: 'one', 2: 'two', 3: 'three', 4: 'four'}" + + // map[string]int + mut items_2 := { + 'one': 1 + 'two': 2 + 'three': 3 + } + assert typeof(items_2).name == 'map[string]int' + assert items_2['two'] == 2 + items_2['four'] = 4 + assert items_2['four'] == 4 + keys_2 := items_2.keys() + assert keys_2.contains('one') + assert keys_2.contains('two') + assert keys_2.contains('three') + assert keys_2.contains('four') + assert '${items_2}' == "{'one': 1, 'two': 2, 'three': 3, 'four': 4}" + + // map[f64]string + mut items_3 := { + 1.1: 'one dot one' + 2.2: 'two dot two' + 3.3: 'three dot three' + } + assert typeof(items_3).name == 'map[f64]string' + assert items_3[2.2] == 'two dot two' + items_3[4.4] = 'four dot four' + assert items_3[4.4].len == 13 + keys_3 := items_3.keys() + assert keys_3.contains(1.1) + assert keys_3.contains(2.2) + assert keys_3.contains(3.3) + assert keys_3.contains(4.4) + assert '${items_3}' == "{1.1: 'one dot one', 2.2: 'two dot two', 3.3: 'three dot three', 4.4: 'four dot four'}" + + // map[u8]string + mut items_4 := { + u8(1): 'one' + 2: 'two' + } + assert typeof(items_4).name == 'map[u8]string' + assert items_4[2] == 'two' + items_4[3] = 'three' + assert items_4[3].len == 5 + keys_4 := items_4.keys() + assert keys_4.contains(1) + assert keys_4.contains(2) + assert keys_4.contains(3) + assert '${items_4}' == "{49: 'one', 50: 'two', 51: 'three'}" + + // map[rune]int + mut items_5 := { `!`: 2 `%`: 3 } - assert typeof(m).name == 'map[rune]int' - assert m[`!`] == 2 - m[`@`] = 7 - assert m.len == 3 - println(m) - assert '${m}' == '{`!`: 2, `%`: 3, `@`: 7}' + assert typeof(items_5).name == 'map[rune]int' + assert items_5[`!`] == 2 + items_5[`@`] = 7 + assert items_5.len == 3 + keys_5 := items_5.keys() + assert keys_5.contains(`!`) + assert keys_5.contains(`%`) + assert keys_5.contains(`@`) + assert '${items_5}' == '{`!`: 2, `%`: 3, `@`: 7}' + + // map[sum-type]string + mut items_6 := { + T1(T0(1)): 'one' + T0('2'): 'two' + } + items_6[`!`] = 'exclamation' + assert items_6[`!`].len == 11 + keys_6 := items_6.keys() + assert keys_6.contains(T0(1)) + assert keys_6.contains(T0('2')) + assert keys_6.contains(`!`) + + // map[enum-type]string + mut items_7 := { + Colors.red: 'red' + .green: 'green' + } + items_7[.blue] = 'blue' + assert items_7[.blue].len == 4 + keys_7 := items_7.keys() + keys_7.contains(.red) + keys_7.contains(.green) + keys_7.contains(.blue) } fn main() { @@ -246,5 +349,5 @@ fn main() { test_keys_method_with_generic_constraints() test_direct_map_access() test_map_len() - test_rune_keys() + test_map_with_different_key_types() }