diff --git a/examples/js_dom_draw/README.md b/examples/js_dom_draw/README.md index 8baae5cb51..82664aee82 100644 --- a/examples/js_dom_draw/README.md +++ b/examples/js_dom_draw/README.md @@ -2,6 +2,6 @@ Drawing with mouse events using DOM API. Adopted from MDN examples. # Compiling ``` -v -b js_browser examples/js_dom_draw/draw.v +v -b js_browser examples/js_dom_draw/draw.js.v ``` Then you can open `index.html` with your favourite browser. diff --git a/examples/js_dom_draw/draw.js.v b/examples/js_dom_draw/draw.js.v index b078059e69..1385dc7749 100644 --- a/examples/js_dom_draw/draw.js.v +++ b/examples/js_dom_draw/draw.js.v @@ -27,8 +27,14 @@ fn draw_line(context ctx.CanvasRenderingContext2D, x1 int, y1 int, x2 int, y2 in context.close_path() } +struct DrawState { +mut: + drawing bool + x int + y int +} + fn main() { - /* document := jsdom.document elem := document.get_element_by_id('myButton') ? @@ -36,39 +42,36 @@ fn main() { canv := jsdom.get_html_canvas_element(elemc) or { panic('expected canvas') } context := get_2dcontext(canv) or { panic('wow') } - mut drawing := false - mut x := int(0) - mut y := int(0) - canv.add_event_listener('mousedown', fn [mut drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) { - drawing = true + mut state := DrawState{} + canv.add_event_listener('mousedown', fn [mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) { + state.drawing = true if event is jsdom.MouseEvent { - x = event.offset_x() - y = event.offset_y() + state.x = event.offset_x() + state.y = event.offset_y() } }) - canv.add_event_listener('mousemove', fn [context, drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) { - if drawing { + canv.add_event_listener('mousemove', fn [context, mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) { + if state.drawing { if event is jsdom.MouseEvent { - draw_line(context, x, y, event.offset_x(), event.offset_y()) - x = event.offset_x() - y = event.offset_y() + draw_line(context, state.x, state.y, event.offset_x(), event.offset_y()) + state.x = event.offset_x() + state.y = event.offset_y() } } }) - jsdom.window.add_event_listener('mouseup', fn [context, mut drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) { - if drawing { + jsdom.window.add_event_listener('mouseup', fn [context, mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) { + if state.drawing { if event is jsdom.MouseEvent { - draw_line(context, x, y, event.offset_x(), event.offset_y()) + draw_line(context, state.x, state.y, event.offset_x(), event.offset_y()) } - x = 0 - y = 0 - drawing = false + state.x = 0 + state.y = 0 + state.drawing = false } }) elem.add_event_listener('click', fn [context, canv] (_ jsdom.IEventTarget, _ jsdom.IEvent) { context.clear_rect(0, 0, canv.width(), canv.height()) }) - */ } diff --git a/vlib/v/gen/js/auto_str_methods.v b/vlib/v/gen/js/auto_str_methods.v index 157da30d0d..52d8b08077 100644 --- a/vlib/v/gen/js/auto_str_methods.v +++ b/vlib/v/gen/js/auto_str_methods.v @@ -21,6 +21,7 @@ fn (mut g JsGen) get_str_fn(typ ast.Type) string { unwrapped = ast.u64_type } } + if typ.has_flag(.optional) { unwrapped.set_flag(.optional) } @@ -50,6 +51,9 @@ fn (mut g JsGen) final_gen_str(typ StrType) { return } styp := typ.styp + if styp == 'any' { + return + } str_fn_name := styp_to_str_fn_name(styp) if typ.typ.has_flag(.optional) { g.gen_str_for_option(typ.typ, styp, str_fn_name) @@ -346,37 +350,25 @@ fn (mut g JsGen) gen_str_for_interface(info ast.Interface, styp string, str_fn_n for typ in info.types { subtype := g.table.get_type_symbol(typ) mut func_name := g.get_str_fn(typ) - sym_has_str_method, _, _ := subtype.str_method_info() + sym_has_str_method, str_method_expects_ptr, _ := subtype.str_method_info() if should_use_indent_func(subtype.kind) && !sym_has_str_method { func_name = 'indent_$func_name' } - + deref := if sym_has_str_method && str_method_expects_ptr { ' ' } else { '.valueOf()' } // str_intp if typ == ast.string_type { - /* - mut val := '${func_name}(${deref}($subtype.cname*)x._$subtype.cname' - if should_use_indent_func(subtype.kind) && !sym_has_str_method { - val += ', indent_count' - } - val += ')' - val = val - */ - res := '"TODO"' - fn_builder.write_string('\tif (x._typ == _${styp}_${subtype.cname}_index)') - fn_builder.write_string(' return $res;') + fn_builder.write_string('\tif (x.val instanceof string)') + fn_builder.write_string(' return "new string(${clean_interface_v_type_name}(" + x.val.str + ")");') } else { - /* - mut val := '${func_name}(${deref}($subtype.cname*)x._$subtype.cname' + mut val := '${func_name}(x $deref' if should_use_indent_func(subtype.kind) && !sym_has_str_method { val += ', indent_count' } val += ')' - val = val - */ - res := '"TODO' - fn_builder.write_string('\tif (x._typ == _${styp}_${subtype.cname}_index)') - fn_builder.write_string(' return $res;\n') + + fn_builder.write_string('\tif (x.val instanceof $subtype.cname)') + fn_builder.write_string(' return new string("${clean_interface_v_type_name}(" + ${val}.str + ")");\n') } } fn_builder.writeln('\treturn new string("unknown interface value");') diff --git a/vlib/v/gen/js/builtin_types.v b/vlib/v/gen/js/builtin_types.v index 337a32a78b..46e04d2e80 100644 --- a/vlib/v/gen/js/builtin_types.v +++ b/vlib/v/gen/js/builtin_types.v @@ -46,7 +46,7 @@ fn (mut g JsGen) to_js_typ_val(t ast.Type) string { styp = 'new ${g.js_name(sym.name)}(${g.to_js_typ_def_val(sym.name)})' } .voidptr { - styp = 'null' + styp = 'new voidptr(null)' } else { // TODO @@ -108,7 +108,7 @@ fn (mut g JsGen) sym_to_js_typ(sym ast.TypeSymbol) string { styp = 'array' } .voidptr { - styp = 'any' + styp = 'voidptr' } .rune { styp = 'rune' @@ -137,7 +137,7 @@ fn (mut g JsGen) base_type(_t ast.Type) string { pub fn (mut g JsGen) typ(t ast.Type) string { sym := g.table.get_final_type_symbol(t) if sym.kind == .voidptr { - return 'any' + return 'voidptr' } styp := g.base_type(t) @@ -157,7 +157,7 @@ pub fn (mut g JsGen) doc_typ(t ast.Type) string { styp = 'void' } .voidptr { - styp = 'any' + styp = 'voidptr' } .byteptr, .charptr { styp = '${g.sym_to_js_typ(sym)}' @@ -438,6 +438,18 @@ fn (mut g JsGen) gen_builtin_type_defs() { to_jsval: 'this.arr' ) } + 'voidptr' { + g.gen_builtin_prototype( + typ_name: typ_name + val_name: 'val' + default_value: 'null' + constructor: 'this.val = val;' + value_of: 'this' + to_string: '"voidptr(" + this.val + ")"' + eq: 'this.val === other.val' + to_jsval: 'this.val' + ) + } 'any' { g.gen_builtin_prototype( typ_name: typ_name diff --git a/vlib/v/gen/js/deep_copy.v b/vlib/v/gen/js/deep_copy.v index 0613f4cf25..55f20814cc 100644 --- a/vlib/v/gen/js/deep_copy.v +++ b/vlib/v/gen/js/deep_copy.v @@ -155,15 +155,32 @@ fn (mut g JsGen) gen_copy_for_struct(info ast.Struct, styp string, copy_fn_name g.definitions.writeln(fn_builder.str()) } - fn_builder.writeln('function ${copy_fn_name}(it) {') + fn_builder.writeln('function ${copy_fn_name}(it) { return it }') + /* tmp := g.new_tmp_var() fn_builder.writeln('\tlet $tmp = new ${styp}({});') for field in info.fields { - func_name := g.get_copy_fn(field.typ) - fn_builder.writeln('\t${tmp}.$field.name = ${func_name}(it.$field.name);') + println(field) + if field.name.len == 0 { + + } else { + mut shall_copy := true + for attr in field.attrs { + if attr.name == 'noinit' { + shall_copy = false + break + } + } + if shall_copy { + func_name := g.get_copy_fn(field.typ) + fn_builder.writeln('\t${tmp}.$field.name = ${func_name}(it.$field.name);') + } else { + fn_builder.writeln('\t${tmp}.$field.name = it.$field.name') + } + } } - fn_builder.writeln('\treturn $tmp;\n}') + fn_builder.writeln('\treturn $tmp;\n}')*/ } fn (mut g JsGen) final_gen_copy(typ StrType) { @@ -181,9 +198,9 @@ fn (mut g JsGen) final_gen_copy(typ StrType) { g.gen_copy_for_option(typ.typ, styp, copy_fn_name) return } - match sym.kind { - .byte, .u8, .u16, .u32, .u64, .i16, .int, .i64, .isize, .usize, .bool, .int_literal, - .float_literal, .f32, .f64 { + match styp { + 'byte', 'u8', 'u16', 'u32', 'u64', 'i16', 'int', 'i64', 'isize', 'usize', 'bool', + 'int_literal', 'float_literal', 'f32', 'f64', 'voidptr' { g.definitions.writeln('function ${sym.cname}_\$copy(it) { return new ${sym.cname}(it.val); }') return } diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 0a3a788e3a..93b48a4936 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -20,7 +20,7 @@ const ( 'Array', 'Map', 'document'] // used to generate type structs v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64', - 'int_literal', 'float_literal', 'bool', 'string', 'map', 'array', 'rune', 'any'] + 'int_literal', 'float_literal', 'bool', 'string', 'map', 'array', 'rune', 'any', 'voidptr'] shallow_equatables = [ast.Kind.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64, .int_literal, .float_literal, .bool, .string] ) @@ -1709,7 +1709,7 @@ fn (mut g JsGen) gen_interface_decl(it ast.InterfaceDecl) { // TODO: interfaces are always `pub`? name := g.js_name(it.name) g.push_pub_var('/** @type $name */\n\t\t$name') - g.writeln('function ${g.js_name(it.name)} (arg) { return arg; }') + g.writeln('function ${g.js_name(it.name)} (arg) { return new \$ref(arg); }') } fn (mut g JsGen) gen_optional_error(expr ast.Expr) { @@ -2335,6 +2335,7 @@ fn (mut g JsGen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var M g.write(' instanceof ') g.expr(branch.exprs[sumtype_index]) } else if sym.kind == .interface_ { + g.write('.val') if branch.exprs[sumtype_index] is ast.TypeNode { g.write(' instanceof ') g.expr(branch.exprs[sumtype_index])