js: fix interfaces behaviour & disable struct deep copy for now (#12333)

pull/12353/head
playX 2021-10-29 11:23:40 +03:00 committed by GitHub
parent d33f7d12f7
commit a32dae335a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 54 deletions

View File

@ -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.

View File

@ -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())
})
*/
}

View File

@ -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");')

View File

@ -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

View File

@ -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 {
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
}

View File

@ -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])