From f51fa7e6659f5577fd7495b1569eefbc870de4c8 Mon Sep 17 00:00:00 2001 From: playX Date: Sat, 24 Jul 2021 15:35:17 +0300 Subject: [PATCH] v.gen.js: fix references and add iterator to map (#10938) --- vlib/builtin/js/map.js.v | 4 +++- vlib/os_js/process.js.v | 34 +++++++++++++++++----------------- vlib/v/gen/js/js.v | 37 ++++++++++++++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/vlib/builtin/js/map.js.v b/vlib/builtin/js/map.js.v index 2153b53112..894d614cf0 100644 --- a/vlib/builtin/js/map.js.v +++ b/vlib/builtin/js/map.js.v @@ -8,7 +8,9 @@ struct map { // Removes the mapping of a particular key from the map. [unsafe] pub fn (mut m map) delete(key voidptr) { - #m.m.delete(key) + #m.map.delete(key) } pub fn (m &map) free() {} + +#map.prototype[Symbol.iterator] = function () { return this.map[Symbol.iterator](); } diff --git a/vlib/os_js/process.js.v b/vlib/os_js/process.js.v index 392c4a797a..e5574d8f28 100644 --- a/vlib/os_js/process.js.v +++ b/vlib/os_js/process.js.v @@ -18,7 +18,7 @@ pub enum ProcessState { } // todo(playX): fix reference member access in JS backend -// [heap] +[heap] pub struct Process { pub: filename string @@ -41,8 +41,8 @@ pub mut: // That is done because you may want to customize it first, // by calling different set_ methods on it. // In order to start it, call p.run() or p.wait() -pub fn new_process(filename string) Process { - return Process{ +pub fn new_process(filename string) &Process { + return &Process{ filename: filename stdio_fd: [-1, -1, -1]! } @@ -71,20 +71,20 @@ pub fn (mut p Process) set_environment(envs map[string]string) { } fn (mut p Process) spawn_internal() { - #p.pid = $child_process.spawn( - #p.filename+'', - #p.args.arr.map((x) => x.valueOf() + ''), + #p.val.pid = $child_process.spawn( + #p.val.filename+'', + #p.val.args.arr.map((x) => x.valueOf() + ''), #{ - #env: (p.env_is_custom ? p.env : $process.env), + #env: (p.val.env_is_custom ? p.val.env : $process.env), #}) - #p.pid.on('error', function (err) { builtin.panic('Failed to start subprocess') }) + #p.val.pid.on('error', function (err) { builtin.panic('Failed to start subprocess') }) p.status = .running // todo(playX): stderr,stdin if p.use_stdio_ctl { - #p.pid.stdout.pipe(process.stdout) - #p.pid.stdin.pipe(process.stdin) - #p.pid.stderr.pipe(process.stderr) + #p.val.pid.stdout.pipe(process.stdout) + #p.val.pid.stdin.pipe(process.stdin) + #p.val.pid.stderr.pipe(process.stderr) } } @@ -100,7 +100,7 @@ pub fn (mut p Process) signal_kill() { if p.status !in [.running, .stopped] { return } - #p.pid.kill('SIGKILL'); + #p.val.pid.kill('SIGKILL'); p.status = .aborted } @@ -109,7 +109,7 @@ pub fn (mut p Process) signal_stop() { if p.status !in [.running, .stopped] { return } - #p.pid.kill('SIGSTOP'); + #p.val.pid.kill('SIGSTOP'); p.status = .aborted } @@ -118,7 +118,7 @@ pub fn (mut p Process) signal_continue() { if p.status != .stopped { return } - #p.pid.kill('SIGCONT'); + #p.val.pid.kill('SIGCONT'); p.status = .running return @@ -137,7 +137,7 @@ pub fn (mut p Process) wait() { } fn (mut p Process) wait_internal() { - #p.pid.on('exit', function (code) { console.log(code) }) + #p.val.pid.on('exit', function (code) { console.log(code) }) } pub fn (mut p Process) set_redirect_stdio() { @@ -147,7 +147,7 @@ pub fn (mut p Process) set_redirect_stdio() { pub fn (mut p Process) stdin_write(s string) { p.check_redirection_call('stdin_write') - #p.pid.stdin.write(s) + #p.val.pid.stdin.write(s) } // todo(playX): probably does not work @@ -157,7 +157,7 @@ pub fn (mut p Process) stdin_write(s string) { pub fn (mut p Process) stdout_slurp() string { p.check_redirection_call('stdout_slurp') mut res := '' - #p.pid.stdout.on('data', function (data) { res = new builtin.string(data) }) + #p.val.pid.stdout.on('data', function (data) { res = new builtin.string(data) }) return res } diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 2e8d230e7f..f3a95c79a3 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -306,7 +306,8 @@ pub fn (mut g JsGen) init() { g.definitions.writeln('"use strict";') g.definitions.writeln('') g.definitions.writeln('var \$global = (new Function("return this"))();') - + g.definitions.writeln('function \$ref(value) { this.val = value; } ') + g.definitions.writeln('\$ref.prototype.valueOf = function() { return this.val; } ') if g.pref.backend != .js_node { g.definitions.writeln('const \$process = {') g.definitions.writeln(' arch: "js",') @@ -681,10 +682,13 @@ fn (mut g JsGen) expr(node ast.Expr) { // C pointers/references: ignore them if node.op == .amp { type_sym := g.table.get_type_symbol(node.right_type) + if !type_sym.is_primitive() && !node.right_type.is_pointer() { - g.write('{ val: ') + // 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(')') } else { g.expr(node.right) } @@ -1111,6 +1115,9 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) { if it.kind == .string { g.write('Array.from(') g.expr(it.cond) + if it.cond_type.is_ptr() { + g.write('.valueOf()') + } g.write('.str.split(\'\').entries(), ([$it.key_var, $val]) => [$it.key_var, ') if g.ns.name == 'builtin' { g.write('new ') @@ -1118,11 +1125,17 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) { g.write('byte($val)])') } else { g.expr(it.cond) + if it.cond_type.is_ptr() { + g.write('.valueOf()') + } g.write('.entries()') } } else { g.write('for (const $val of ') g.expr(it.cond) + if it.cond_type.is_ptr() { + g.write('.valueOf()') + } if it.kind == .string { g.write(".str.split('')") } @@ -1146,6 +1159,9 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) { val := if it.val_var in ['', '_'] { '' } else { it.val_var } g.write('for (let [$key, $val] of ') g.expr(it.cond) + if it.cond_type.is_ptr() { + g.write('.valueOf()') + } g.writeln(') {') g.stmts(it.stmts) g.writeln('}') @@ -1538,6 +1554,9 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) { // TODO: Handle splice setting if it's implemented if expr.index is ast.RangeExpr { g.expr(expr.left) + if expr.left_type.is_ptr() { + g.write('.val') + } g.write('.slice(') if expr.index.has_low { g.expr(expr.index.low) @@ -1549,6 +1568,9 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) { g.expr(expr.index.high) } else { g.expr(expr.left) + if expr.left_type.is_ptr() { + g.write('.val') + } g.write('.length') } g.write(')') @@ -1573,6 +1595,9 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) { // TODO: Maybe use u16 there? JS String returns values up to 2^16-1 g.write('new byte(') g.expr(expr.left) + if expr.left_type.is_ptr() { + g.write('.val') + } g.write('.str.charCodeAt(') g.expr(expr.index) g.write('))') @@ -1580,6 +1605,9 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) { } else { // TODO Does this cover all cases? g.expr(expr.left) + if expr.left_type.is_ptr() { + g.write('.val') + } g.write('.arr') g.write('[') g.cast_stack << ast.int_type_idx @@ -1756,6 +1784,9 @@ fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) { fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) { g.expr(it.expr) + if it.expr_type.is_ptr() { + g.write('.valueOf()') + } g.write('.$it.field_name') }