diff --git a/vlib/v/gen/js/fn.v b/vlib/v/gen/js/fn.v index fce5eb090c..4971858e3c 100644 --- a/vlib/v/gen/js/fn.v +++ b/vlib/v/gen/js/fn.v @@ -97,6 +97,11 @@ fn (mut g JsGen) js_call(node ast.CallExpr) { } if call_return_is_optional { g.write(';\n') + prev_inside_or := g.inside_or + g.inside_or = true + defer { + g.inside_or = prev_inside_or + } g.writeln('if (tmp === null) throw "none";') g.writeln('return tmp;') g.writeln('} catch(err) {') @@ -151,6 +156,11 @@ fn (mut g JsGen) js_method_call(node ast.CallExpr) { // end method call g.write(')') if call_return_is_optional { + prev_inside_or := g.inside_or + g.inside_or = true + defer { + g.inside_or = prev_inside_or + } g.write(';\n') g.writeln('if (tmp === null) throw "none";') g.writeln('return tmp;') @@ -339,6 +349,11 @@ fn (mut g JsGen) method_call(node ast.CallExpr) { // end unwrap g.writeln(')') g.dec_indent() + prev_inside_or := g.inside_or + g.inside_or = true + defer { + g.inside_or = prev_inside_or + } // begin catch block g.writeln('} catch(err) {') g.inc_indent() @@ -432,6 +447,11 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) { g.write(')') if call_return_is_optional { // end unwrap + prev_inside_or := g.inside_or + g.inside_or = true + defer { + g.inside_or = prev_inside_or + } g.writeln(')') g.dec_indent() // begin catch block diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index e3a9f34fcd..9109910bd2 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -54,6 +54,7 @@ mut: file &ast.File tmp_count int inside_ternary bool + inside_or bool inside_loop bool inside_map_set bool // map.set(key, value) inside_builtin bool @@ -478,6 +479,9 @@ pub fn (mut g JsGen) init() { g.definitions.writeln('function checkDefine(key) {') g.definitions.writeln('\tif (globalThis.hasOwnProperty(key)) { return !!globalThis[key]; } return false;') g.definitions.writeln('}') + + g.definitions.writeln('function BreakException() {}') + g.definitions.writeln('function ContinueException() {}') } pub fn (g JsGen) hashes() string { @@ -1500,6 +1504,20 @@ fn (mut g JsGen) gen_block(it ast.Block) { fn (mut g JsGen) gen_branch_stmt(it ast.BranchStmt) { // continue or break + if g.inside_or { + match it.kind { + .key_break { + g.writeln('throw new BreakException();') + } + .key_continue { + g.writeln('throw new ContinueException();') + } + else { + verror('unexpected branch stmt: $it.kind') + } + } + return + } g.write(it.kind.str()) g.writeln(';') } @@ -1606,7 +1624,12 @@ fn (mut g JsGen) gen_for_c_stmt(it ast.ForCStmt) { g.stmt_no_semi(it.inc) } g.writeln(') {') + g.writeln('try { ') g.stmts(it.stmts) + g.writeln('} catch (e) {') + g.writeln(' if (e instanceof BreakException) { break; }') + g.writeln(' else if (e instanceof ContinueException) { continue; }') + g.writeln(' else { throw e; } }') g.writeln('}') g.inside_loop = false } @@ -1625,7 +1648,12 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) { g.expr(it.high) g.writeln('; $i = new int($i + 1)) {') g.inside_loop = false + g.writeln('try { ') g.stmts(it.stmts) + g.writeln('} catch (e) {') + g.writeln(' if (e instanceof BreakException) { break; }') + g.writeln(' else if (e instanceof ContinueException) { continue; }') + g.writeln(' else { throw e; } }') g.writeln('}') } else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) { // `for num in nums {` @@ -1670,7 +1698,12 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) { } } g.writeln(') {') + g.writeln('try { ') g.stmts(it.stmts) + g.writeln('} catch (e) {') + g.writeln(' if (e instanceof BreakException) { break; }') + g.writeln(' else if (e instanceof ContinueException) { continue; }') + g.writeln(' else { throw e; } }') g.writeln('}') } else if it.kind == .map { // `for key, val in map[string]int {` @@ -1695,7 +1728,12 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) { g.writeln('\tlet $key = $tmp[$tmp3];') g.writeln('\tlet $val = ${tmp2}.map[$tmp[$tmp3]];') g.inc_indent() + g.writeln('try { ') g.stmts(it.stmts) + g.writeln('} catch (e) {') + g.writeln(' if (e instanceof BreakException) { break; }') + g.writeln(' else if (e instanceof ContinueException) { continue; }') + g.writeln(' else { throw e; } }') g.dec_indent() g.writeln('}') } else { @@ -1710,7 +1748,12 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) { g.inc_indent() g.writeln('let $val = ${tmp}.map[$tmp2];') g.writeln('let $key = $tmp2;') + g.writeln('try { ') g.stmts(it.stmts) + g.writeln('} catch (e) {') + g.writeln(' if (e instanceof BreakException) { break; }') + g.writeln(' else if (e instanceof ContinueException) { continue; }') + g.writeln(' else { throw e; } } ') g.dec_indent() g.writeln('}') } @@ -1726,7 +1769,12 @@ fn (mut g JsGen) gen_for_stmt(it ast.ForStmt) { g.expr(it.cond) } g.writeln(') {') + g.writeln('try { ') g.stmts(it.stmts) + g.writeln('} catch (e) {') + g.writeln(' if (e instanceof BreakException) { break; }') + g.writeln(' else if (e instanceof ContinueException) { continue; }') + g.writeln(' else { throw e; } }') g.writeln('}') } diff --git a/vlib/v/gen/js/tests/js.v b/vlib/v/gen/js/tests/js.v index 82d2849a45..a81b7839fe 100644 --- a/vlib/v/gen/js/tests/js.v +++ b/vlib/v/gen/js/tests/js.v @@ -31,7 +31,7 @@ fn main() { println('Hello from V.js!') println(JS.Math.atan2(1, 0)) non := JS.eval("console.log('Hello!')".str) - if isnil (non) { + if isnil(non) { println('non=nil') } ren := int(JS.eval('3'.str))