v.gen.js: Interfaces support, fix for error propagation & panic stacktraces (#11471)
parent
90e04d03b2
commit
5b619b99c2
|
@ -79,3 +79,12 @@ pub fn (r rune) str() string {
|
|||
|
||||
return sb.str()
|
||||
}
|
||||
|
||||
fn js_stacktrace() string {
|
||||
stacktrace := ''
|
||||
#let err = new TypeError();
|
||||
#err.name = 'stacktrace: '
|
||||
#stacktrace.str = err.stack
|
||||
|
||||
return stacktrace
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ module builtin
|
|||
fn (a any) toString()
|
||||
|
||||
pub fn panic(s string) {
|
||||
eprintln('V panic: $s')
|
||||
eprintln('V panic: $s\n$js_stacktrace()')
|
||||
exit(1)
|
||||
}
|
||||
|
||||
|
|
|
@ -130,9 +130,16 @@ fn (mut g JsGen) method_call(node ast.CallExpr) {
|
|||
}
|
||||
|
||||
if typ_sym.kind == .interface_ && (typ_sym.info as ast.Interface).defines_method(node.name) {
|
||||
// g.write('${g.js_name(receiver_type_name)}_name_table')
|
||||
// g.expr(node.left)
|
||||
g.writeln('/* TODO: Interface call */')
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write('.${it.name}(')
|
||||
for i, arg in it.args {
|
||||
g.expr(arg.expr)
|
||||
if i != it.args.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
}
|
||||
g.write(')')
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -229,9 +236,9 @@ fn (mut g JsGen) method_call(node ast.CallExpr) {
|
|||
.propagate {
|
||||
panicstr := '`optional not set (\${err})`'
|
||||
if g.file.mod.name == 'main' && g.fn_decl.name == 'main.main' {
|
||||
g.writeln('return builtin.panic($panicstr)')
|
||||
g.writeln('return panic($panicstr)')
|
||||
} else {
|
||||
g.writeln('builtin.js_throw(err)')
|
||||
g.writeln('js_throw(err)')
|
||||
}
|
||||
}
|
||||
else {}
|
||||
|
@ -315,7 +322,7 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
|
|||
g.stmt(it.or_block.stmts.last())
|
||||
}
|
||||
.propagate {
|
||||
panicstr := '`optional not set (\${err})`'
|
||||
panicstr := '`optional not set (\${err.val.msg})`'
|
||||
if g.file.mod.name == 'main' && g.fn_decl.name == 'main.main' {
|
||||
g.writeln('return panic($panicstr)')
|
||||
} else {
|
||||
|
|
|
@ -156,6 +156,45 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
|||
if g.pref.is_test {
|
||||
g.gen_js_main_for_tests()
|
||||
}
|
||||
g.enter_namespace('main')
|
||||
// generate JS methods for interface methods
|
||||
for _, iface_types in g.table.iface_types {
|
||||
for ty in iface_types {
|
||||
sym := g.table.get_type_symbol(ty)
|
||||
for method in sym.methods {
|
||||
p_sym := g.table.get_type_symbol(method.params[0].typ)
|
||||
mname := g.js_name(p_sym.name) + '_' + method.name
|
||||
g.write('${g.js_name(sym.name)}.prototype.$method.name = function(')
|
||||
for i, param in method.params {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
g.write('${g.js_name(param.name)}')
|
||||
if i != method.params.len - 1 {
|
||||
g.write(',')
|
||||
}
|
||||
}
|
||||
g.writeln(') {')
|
||||
g.inc_indent()
|
||||
g.write('return ${mname}(')
|
||||
for i, param in method.params {
|
||||
if i == 0 {
|
||||
g.write('this')
|
||||
} else {
|
||||
g.write('${g.js_name(param.name)}')
|
||||
}
|
||||
if i != method.params.len - 1 {
|
||||
g.write(',')
|
||||
}
|
||||
}
|
||||
g.writeln(')')
|
||||
g.dec_indent()
|
||||
g.writeln('}')
|
||||
}
|
||||
}
|
||||
}
|
||||
g.write('js_main();')
|
||||
g.escape_namespace()
|
||||
// resolve imports
|
||||
deps_resolved := graph.resolve()
|
||||
nodes := deps_resolved.nodes
|
||||
|
@ -178,6 +217,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
|||
out += g.out.str()
|
||||
|
||||
/*
|
||||
TODO(playX): Again add support for these doc comments
|
||||
for node in nodes {
|
||||
name := g.js_name(node.name).replace('.', '_')
|
||||
if g.enable_doc {
|
||||
|
@ -212,6 +252,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
|||
// public scope
|
||||
out += '\n'
|
||||
}*/
|
||||
|
||||
if g.pref.sourcemap {
|
||||
out += g.create_sourcemap()
|
||||
}
|
||||
|
@ -229,7 +270,7 @@ fn (g JsGen) create_sourcemap() string {
|
|||
|
||||
pub fn (mut g JsGen) gen_js_main_for_tests() {
|
||||
g.enter_namespace('main')
|
||||
g.writeln('(function() { ')
|
||||
g.writeln('function js_main() { ')
|
||||
g.inc_indent()
|
||||
all_tfuncs := g.get_all_test_function_names()
|
||||
|
||||
|
@ -256,7 +297,7 @@ pub fn (mut g JsGen) gen_js_main_for_tests() {
|
|||
g.writeln('bt.end_testing();')
|
||||
}
|
||||
g.dec_indent()
|
||||
g.writeln('})();')
|
||||
g.writeln('}')
|
||||
g.escape_namespace()
|
||||
}
|
||||
|
||||
|
@ -888,9 +929,13 @@ fn (mut g JsGen) expr(node ast.Expr) {
|
|||
if node.op == .amp {
|
||||
// if !node.right_type.is_pointer() {
|
||||
// kind of weird way to handle references but it allows us to access type methods easily.
|
||||
/*
|
||||
g.write('(function(x) {')
|
||||
g.write(' return { val: x, __proto__: Object.getPrototypeOf(x), valueOf: function() { return this.val; } }})( ')
|
||||
g.expr(node.right)
|
||||
g.write(')')*/
|
||||
g.write('new \$ref(')
|
||||
g.expr(node.right)
|
||||
g.write(')')
|
||||
//} else {
|
||||
// g.expr(node.right)
|
||||
|
@ -1406,11 +1451,11 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) {
|
|||
// there is no concept of main in JS but we do have iife
|
||||
g.writeln('/* program entry point */')
|
||||
|
||||
g.write('(')
|
||||
// g.write('(')
|
||||
if has_go {
|
||||
g.write('async ')
|
||||
}
|
||||
g.write('function(')
|
||||
g.write('function js_main(')
|
||||
} else if it.is_anon {
|
||||
g.write('function (')
|
||||
} else {
|
||||
|
@ -1451,9 +1496,18 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) {
|
|||
g.writeln('}')
|
||||
|
||||
if is_main {
|
||||
g.write(')();')
|
||||
// g.write(')')
|
||||
}
|
||||
g.writeln('')
|
||||
|
||||
for attr in it.attrs {
|
||||
match attr.name {
|
||||
'export' {
|
||||
g.writeln('globalThis.$attr.arg = ${g.js_name(it.name)};')
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if typ == .alias_method || typ == .iface_method {
|
||||
sym := g.table.get_final_type_symbol(it.params[0].typ.set_nr_muls(0))
|
||||
|
@ -1733,7 +1787,7 @@ fn (mut g JsGen) gen_return_stmt(it ast.Return) {
|
|||
fn_return_is_optional := g.fn_decl.return_type.has_flag(.optional)
|
||||
if node.exprs.len == 0 {
|
||||
if fn_return_is_optional {
|
||||
g.writeln('return {}')
|
||||
g.writeln('return {state: new int(0)}')
|
||||
} else {
|
||||
g.writeln('return;')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue