From 42d8ccbdaf0d9f4d64d6a56a00ccbec016f09caa Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Sun, 3 Mar 2024 15:11:41 +0100 Subject: [PATCH 1/5] Runtime: fix memory leak wrt channels --- runtime/io.js | 95 ++++++++++++++++++++++++++++------------------ runtime/parsing.js | 3 +- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/runtime/io.js b/runtime/io.js index 48a0aeb986..6b5a2c5056 100644 --- a/runtime/io.js +++ b/runtime/io.js @@ -25,8 +25,8 @@ var caml_sys_fds = new Array(3); //Provides: caml_sys_close //Requires: caml_sys_fds function caml_sys_close(fd) { - var file = caml_sys_fds[fd]; - if(file) file.close(); + var x = caml_sys_fds[fd]; + if(x && x.file) x.file.close(); delete caml_sys_fds[fd]; return 0; } @@ -41,10 +41,17 @@ function caml_sys_close(fd) { //Requires: caml_sys_fds //Requires: caml_sys_open_for_node function caml_sys_open_internal(file,idx) { + var chanid; if(idx == undefined){ idx = caml_sys_fds.length; + chanid = Symbol(idx.toString()); } - caml_sys_fds[idx] = file; + else if(caml_sys_fds[idx]){ + chanid = caml_sys_fds[idx].chanid; + } + else + chanid = Symbol(idx.toString ()); + caml_sys_fds[idx] = {file:file, chanid: chanid}; return idx | 0; } function caml_sys_open (name, flags, _perms) { @@ -90,21 +97,30 @@ function caml_sys_open (name, flags, _perms) { //Provides: caml_ml_set_channel_name //Requires: caml_ml_channels function caml_ml_set_channel_name(chanid, name) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); chan.name = name; return 0; } //Provides: caml_ml_channels -var caml_ml_channels = new Array(); +var caml_ml_channels = new globalThis.WeakMap () + + +//Provides: caml_ml_channels_opened +var caml_ml_channels_opened = new globalThis.Set() //Provides: caml_ml_out_channels_list //Requires: caml_ml_channels +//Requires: caml_ml_channels_opened +//Requires: caml_sys_fds function caml_ml_out_channels_list () { var l = 0; - for(var c = 0; c < caml_ml_channels.length; c++){ - if(caml_ml_channels[c] && caml_ml_channels[c].opened && caml_ml_channels[c].out) - l=[0,caml_ml_channels[c].fd,l]; + var keys = caml_ml_channels_opened.keys(); + for(var k of keys){ + var chan = caml_ml_channels.get(k); + if(chan.opened && chan.out){ + l=[0,caml_sys_fds[chan.fd].chanid,l]; + } } return l; } @@ -114,8 +130,9 @@ function caml_ml_out_channels_list () { //Requires: caml_ml_channels, caml_sys_fds //Requires: caml_raise_sys_error //Requires: caml_sys_open +//Requires: caml_ml_channels_opened function caml_ml_open_descriptor_out (fd) { - var file = caml_sys_fds[fd]; + var s = caml_sys_fds[fd], file = s.file, chanid = s.chanid; if(file.flags.rdonly) caml_raise_sys_error("fd "+ fd + " is readonly"); var buffered = (file.flags.buffered !== undefined) ? file.flags.buffered : 1; var channel = { @@ -128,16 +145,18 @@ function caml_ml_open_descriptor_out (fd) { buffer:new Uint8Array(65536), buffered:buffered }; - caml_ml_channels[channel.fd]=channel; - return channel.fd; + caml_ml_channels_opened.add(chanid); + caml_ml_channels.set(chanid,channel); + return chanid; } //Provides: caml_ml_open_descriptor_in //Requires: caml_ml_channels, caml_sys_fds //Requires: caml_raise_sys_error //Requires: caml_sys_open +//Requires: caml_ml_channels_opened function caml_ml_open_descriptor_in (fd) { - var file = caml_sys_fds[fd]; + var s = caml_sys_fds[fd], file = s.file, chanid = s.chanid; if(file.flags.wronly) caml_raise_sys_error("fd "+ fd + " is writeonly"); var refill = null; var channel = { @@ -151,8 +170,9 @@ function caml_ml_open_descriptor_in (fd) { buffer:new Uint8Array(65536), refill:refill }; - caml_ml_channels[channel.fd]=channel; - return channel.fd; + caml_ml_channels_opened.add(chanid); + caml_ml_channels.set(chanid,channel); + return chanid; } @@ -174,14 +194,14 @@ function caml_ml_open_descriptor_out_with_flags(fd, flags){ //Requires: caml_ml_channels //Alias: win_filedescr_of_channel function caml_channel_descriptor(chanid){ - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); return chan.fd; } //Provides: caml_ml_set_binary_mode //Requires: caml_ml_channels function caml_ml_set_binary_mode(chanid,mode){ - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); chan.file.flags.text = !mode chan.file.flags.binary = mode return 0; @@ -191,7 +211,7 @@ function caml_ml_set_binary_mode(chanid,mode){ //Requires: caml_ml_channels //Version: >= 5.2 function caml_ml_is_binary_mode(chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); return chan.file.flags.binary } @@ -200,10 +220,12 @@ function caml_ml_is_binary_mode(chanid) { //Provides: caml_ml_close_channel //Requires: caml_ml_flush, caml_ml_channels //Requires: caml_sys_close +//Requires: caml_ml_channels_opened function caml_ml_close_channel (chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); if(chan.opened) { chan.opened = false; + delete caml_ml_channels_opened.delete(chanid); caml_sys_close(chan.fd); chan.fd = -1; chan.buffer = new Uint8Array(0); @@ -216,21 +238,21 @@ function caml_ml_close_channel (chanid) { //Provides: caml_ml_channel_size //Requires: caml_ml_channels function caml_ml_channel_size(chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); return chan.file.length(); } //Provides: caml_ml_channel_size_64 //Requires: caml_int64_of_float,caml_ml_channels function caml_ml_channel_size_64(chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); return caml_int64_of_float(chan.file.length ()); } //Provides: caml_ml_set_channel_output //Requires: caml_ml_channels function caml_ml_set_channel_output(chanid,f) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); chan.output = (function (s) {f(s)}); return 0; } @@ -238,7 +260,7 @@ function caml_ml_set_channel_output(chanid,f) { //Provides: caml_ml_set_channel_refill //Requires: caml_ml_channels function caml_ml_set_channel_refill(chanid,f) { - caml_ml_channels[chanid].refill = f; + caml_ml_channels.get(chanid).refill = f; return 0; } @@ -287,7 +309,7 @@ function caml_ml_input_bigarray (chanid, b, i, l) { //Provides: caml_ml_input_block //Requires: caml_refill, caml_ml_channels function caml_ml_input_block (chanid, ba, i, l) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); var n = l; var avail = chan.buffer_max - chan.buffer_curr; if(l <= avail) { @@ -315,7 +337,7 @@ function caml_ml_input_block (chanid, ba, i, l) { //Requires: caml_refill, caml_failwith, caml_raise_end_of_file //Requires: caml_marshal_header_size function caml_input_value (chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); var header = new Uint8Array(caml_marshal_header_size); function block(buffer, offset, n) { var r = 0; @@ -360,7 +382,7 @@ function caml_input_value_to_outside_heap(c) { //Requires: caml_raise_end_of_file, caml_array_bound_error //Requires: caml_ml_channels, caml_refill function caml_ml_input_char (chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); if(chan.buffer_curr >= chan.buffer_max){ chan.buffer_curr = 0; chan.buffer_max = 0; @@ -377,7 +399,7 @@ function caml_ml_input_char (chanid) { //Requires: caml_raise_end_of_file //Requires: caml_ml_input_char, caml_ml_channels function caml_ml_input_int (chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); var res = 0; for(var i = 0; i < 4; i++){ res = (res << 8) + caml_ml_input_char(chanid) | 0; @@ -388,7 +410,7 @@ function caml_ml_input_int (chanid) { //Provides: caml_seek_in //Requires: caml_raise_sys_error, caml_ml_channels function caml_seek_in(chanid, pos) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); if (chan.refill != null) caml_raise_sys_error("Illegal seek"); if(pos >= chan.offset - chan.buffer_max && pos <= chan.offset @@ -418,7 +440,7 @@ function caml_ml_seek_in_64(chanid,pos){ //Provides: caml_pos_in //Requires: caml_ml_channels function caml_pos_in(chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); return chan.offset - (chan.buffer_max - chan.buffer_curr) | 0; } @@ -438,7 +460,7 @@ function caml_ml_pos_in_64(chanid) { //Requires: caml_array_bound_error //Requires: caml_ml_channels, caml_refill function caml_ml_input_scan_line(chanid){ - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); var p = chan.buffer_curr; do { if(p >= chan.buffer_max) { @@ -465,7 +487,7 @@ function caml_ml_input_scan_line(chanid){ //Requires: caml_raise_sys_error, caml_ml_channels //Requires: caml_subarray_to_jsbytes function caml_ml_flush (chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); if(! chan.opened) caml_raise_sys_error("Cannot flush a closed channel"); if(!chan.buffer || chan.buffer_curr == 0) return 0; if(chan.output) { @@ -484,8 +506,9 @@ function caml_ml_flush (chanid) { //Requires: caml_ml_flush,caml_ml_bytes_length //Requires: caml_raise_sys_error, caml_ml_channels function caml_ml_output_ta(chanid,buffer,offset,len) { - var chan = caml_ml_channels[chanid]; - if(! chan.opened) caml_raise_sys_error("Cannot output to a closed channel"); + var chan = caml_ml_channels.get(chanid); + if(! chan.opened) + caml_raise_sys_error("Cannot output to a closed channel"); buffer = buffer.subarray(offset, offset + len); if(chan.buffer_curr + buffer.length > chan.buffer.length) { var b = new Uint8Array(chan.buffer_curr + buffer.length); @@ -569,7 +592,7 @@ function caml_output_value (chanid,v,flags) { //Requires: caml_ml_channels, caml_ml_flush function caml_seek_out(chanid, pos){ caml_ml_flush(chanid); - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); chan.offset = pos; return 0; } @@ -589,7 +612,7 @@ function caml_ml_seek_out_64(chanid,pos){ //Provides: caml_pos_out //Requires: caml_ml_channels, caml_ml_flush function caml_pos_out(chanid) { - var chan = caml_ml_channels[chanid]; + var chan = caml_ml_channels.get(chanid); return chan.offset + chan.buffer_curr } @@ -618,13 +641,13 @@ function caml_ml_output_int (chanid,i) { //Provides: caml_ml_is_buffered //Requires: caml_ml_channels function caml_ml_is_buffered(chanid) { - return caml_ml_channels[chanid].buffered ? 1 : 0 + return caml_ml_channels.get(chanid).buffered ? 1 : 0 } //Provides: caml_ml_set_buffered //Requires: caml_ml_channels, caml_ml_flush function caml_ml_set_buffered(chanid,v) { - caml_ml_channels[chanid].buffered = v; + caml_ml_channels.get(chanid).buffered = v; if(!v) caml_ml_flush(chanid); return 0 } diff --git a/runtime/parsing.js b/runtime/parsing.js index 406f7c8498..b9de9926f4 100644 --- a/runtime/parsing.js +++ b/runtime/parsing.js @@ -24,6 +24,7 @@ var caml_parser_trace = 0; //Requires: caml_lex_array, caml_parser_trace,caml_jsstring_of_string //Requires: caml_ml_output, caml_ml_string_length, caml_string_of_jsbytes //Requires: caml_jsbytes_of_string, MlBytes +//Requires: caml_sys_fds function caml_parse_engine(tables, env, cmd, arg) { var ERRCODE = 256; @@ -84,7 +85,7 @@ function caml_parse_engine(tables, env, cmd, arg) function log(x) { var s = caml_string_of_jsbytes(x + "\n"); - caml_ml_output(2, s, 0, caml_ml_string_length(s)); + caml_ml_output(caml_sys_fds[2].chanid, s, 0, caml_ml_string_length(s)); } function token_name(names, number) From 6a562ee462ae5869f04700d7f4f58c35dfeee4a5 Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Thu, 11 Apr 2024 08:38:52 +0200 Subject: [PATCH 2/5] WIP --- runtime/io.js | 74 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/runtime/io.js b/runtime/io.js index 6b5a2c5056..6c2a019e8e 100644 --- a/runtime/io.js +++ b/runtime/io.js @@ -97,13 +97,31 @@ function caml_sys_open (name, flags, _perms) { //Provides: caml_ml_set_channel_name //Requires: caml_ml_channels function caml_ml_set_channel_name(chanid, name) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; chan.name = name; return 0; + } + + //Provides: caml_ml_channels +var caml_ml_channels_weak = new globalThis.WeakMap (); +var channels_handlers = { + get (target, prop, receiver) { + if(typeof prop == "symbol"){ + return caml_ml_channels_weak.get(prop); + } + else { + console.log("cannot find", prop); + return + } + }, + set (target, prop, new_val) { + if(typeof prop == "symbol"){ + return caml_ml_channels_weak.set(prop, new_val); + } + return; + } } - -//Provides: caml_ml_channels -var caml_ml_channels = new globalThis.WeakMap () +var caml_ml_channels = new globalThis.Proxy(caml_ml_channels_weak, channels_handlers); //Provides: caml_ml_channels_opened @@ -117,7 +135,7 @@ function caml_ml_out_channels_list () { var l = 0; var keys = caml_ml_channels_opened.keys(); for(var k of keys){ - var chan = caml_ml_channels.get(k); + var chan = caml_ml_channels[k]; if(chan.opened && chan.out){ l=[0,caml_sys_fds[chan.fd].chanid,l]; } @@ -146,7 +164,7 @@ function caml_ml_open_descriptor_out (fd) { buffered:buffered }; caml_ml_channels_opened.add(chanid); - caml_ml_channels.set(chanid,channel); + caml_ml_channels[chanid] = channel; return chanid; } @@ -171,7 +189,7 @@ function caml_ml_open_descriptor_in (fd) { refill:refill }; caml_ml_channels_opened.add(chanid); - caml_ml_channels.set(chanid,channel); + caml_ml_channels[chanid] = channel; return chanid; } @@ -194,14 +212,14 @@ function caml_ml_open_descriptor_out_with_flags(fd, flags){ //Requires: caml_ml_channels //Alias: win_filedescr_of_channel function caml_channel_descriptor(chanid){ - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; return chan.fd; } //Provides: caml_ml_set_binary_mode //Requires: caml_ml_channels function caml_ml_set_binary_mode(chanid,mode){ - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; chan.file.flags.text = !mode chan.file.flags.binary = mode return 0; @@ -211,7 +229,7 @@ function caml_ml_set_binary_mode(chanid,mode){ //Requires: caml_ml_channels //Version: >= 5.2 function caml_ml_is_binary_mode(chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; return chan.file.flags.binary } @@ -222,7 +240,7 @@ function caml_ml_is_binary_mode(chanid) { //Requires: caml_sys_close //Requires: caml_ml_channels_opened function caml_ml_close_channel (chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; if(chan.opened) { chan.opened = false; delete caml_ml_channels_opened.delete(chanid); @@ -238,21 +256,21 @@ function caml_ml_close_channel (chanid) { //Provides: caml_ml_channel_size //Requires: caml_ml_channels function caml_ml_channel_size(chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; return chan.file.length(); } //Provides: caml_ml_channel_size_64 //Requires: caml_int64_of_float,caml_ml_channels function caml_ml_channel_size_64(chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; return caml_int64_of_float(chan.file.length ()); } //Provides: caml_ml_set_channel_output //Requires: caml_ml_channels function caml_ml_set_channel_output(chanid,f) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; chan.output = (function (s) {f(s)}); return 0; } @@ -260,7 +278,7 @@ function caml_ml_set_channel_output(chanid,f) { //Provides: caml_ml_set_channel_refill //Requires: caml_ml_channels function caml_ml_set_channel_refill(chanid,f) { - caml_ml_channels.get(chanid).refill = f; + caml_ml_channels[chanid].refill = f; return 0; } @@ -309,7 +327,7 @@ function caml_ml_input_bigarray (chanid, b, i, l) { //Provides: caml_ml_input_block //Requires: caml_refill, caml_ml_channels function caml_ml_input_block (chanid, ba, i, l) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; var n = l; var avail = chan.buffer_max - chan.buffer_curr; if(l <= avail) { @@ -337,7 +355,7 @@ function caml_ml_input_block (chanid, ba, i, l) { //Requires: caml_refill, caml_failwith, caml_raise_end_of_file //Requires: caml_marshal_header_size function caml_input_value (chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; var header = new Uint8Array(caml_marshal_header_size); function block(buffer, offset, n) { var r = 0; @@ -382,7 +400,7 @@ function caml_input_value_to_outside_heap(c) { //Requires: caml_raise_end_of_file, caml_array_bound_error //Requires: caml_ml_channels, caml_refill function caml_ml_input_char (chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; if(chan.buffer_curr >= chan.buffer_max){ chan.buffer_curr = 0; chan.buffer_max = 0; @@ -399,7 +417,7 @@ function caml_ml_input_char (chanid) { //Requires: caml_raise_end_of_file //Requires: caml_ml_input_char, caml_ml_channels function caml_ml_input_int (chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; var res = 0; for(var i = 0; i < 4; i++){ res = (res << 8) + caml_ml_input_char(chanid) | 0; @@ -410,7 +428,7 @@ function caml_ml_input_int (chanid) { //Provides: caml_seek_in //Requires: caml_raise_sys_error, caml_ml_channels function caml_seek_in(chanid, pos) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; if (chan.refill != null) caml_raise_sys_error("Illegal seek"); if(pos >= chan.offset - chan.buffer_max && pos <= chan.offset @@ -440,7 +458,7 @@ function caml_ml_seek_in_64(chanid,pos){ //Provides: caml_pos_in //Requires: caml_ml_channels function caml_pos_in(chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; return chan.offset - (chan.buffer_max - chan.buffer_curr) | 0; } @@ -460,7 +478,7 @@ function caml_ml_pos_in_64(chanid) { //Requires: caml_array_bound_error //Requires: caml_ml_channels, caml_refill function caml_ml_input_scan_line(chanid){ - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; var p = chan.buffer_curr; do { if(p >= chan.buffer_max) { @@ -487,7 +505,7 @@ function caml_ml_input_scan_line(chanid){ //Requires: caml_raise_sys_error, caml_ml_channels //Requires: caml_subarray_to_jsbytes function caml_ml_flush (chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; if(! chan.opened) caml_raise_sys_error("Cannot flush a closed channel"); if(!chan.buffer || chan.buffer_curr == 0) return 0; if(chan.output) { @@ -506,7 +524,7 @@ function caml_ml_flush (chanid) { //Requires: caml_ml_flush,caml_ml_bytes_length //Requires: caml_raise_sys_error, caml_ml_channels function caml_ml_output_ta(chanid,buffer,offset,len) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; if(! chan.opened) caml_raise_sys_error("Cannot output to a closed channel"); buffer = buffer.subarray(offset, offset + len); @@ -592,7 +610,7 @@ function caml_output_value (chanid,v,flags) { //Requires: caml_ml_channels, caml_ml_flush function caml_seek_out(chanid, pos){ caml_ml_flush(chanid); - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; chan.offset = pos; return 0; } @@ -612,7 +630,7 @@ function caml_ml_seek_out_64(chanid,pos){ //Provides: caml_pos_out //Requires: caml_ml_channels, caml_ml_flush function caml_pos_out(chanid) { - var chan = caml_ml_channels.get(chanid); + var chan = caml_ml_channels[chanid]; return chan.offset + chan.buffer_curr } @@ -641,13 +659,13 @@ function caml_ml_output_int (chanid,i) { //Provides: caml_ml_is_buffered //Requires: caml_ml_channels function caml_ml_is_buffered(chanid) { - return caml_ml_channels.get(chanid).buffered ? 1 : 0 + return caml_ml_channels[chanid].buffered ? 1 : 0 } //Provides: caml_ml_set_buffered //Requires: caml_ml_channels, caml_ml_flush function caml_ml_set_buffered(chanid,v) { - caml_ml_channels.get(chanid).buffered = v; + caml_ml_channels[chanid].buffered = v; if(!v) caml_ml_flush(chanid); return 0 } From f95dcf5abbf3918ea3fa7e7774e45b57474968ae Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Thu, 11 Apr 2024 08:40:34 +0200 Subject: [PATCH 3/5] WIP --- runtime/io.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/runtime/io.js b/runtime/io.js index 6c2a019e8e..ebea8b831a 100644 --- a/runtime/io.js +++ b/runtime/io.js @@ -525,8 +525,7 @@ function caml_ml_flush (chanid) { //Requires: caml_raise_sys_error, caml_ml_channels function caml_ml_output_ta(chanid,buffer,offset,len) { var chan = caml_ml_channels[chanid]; - if(! chan.opened) - caml_raise_sys_error("Cannot output to a closed channel"); + if(! chan.opened) caml_raise_sys_error("Cannot output to a closed channel"); buffer = buffer.subarray(offset, offset + len); if(chan.buffer_curr + buffer.length > chan.buffer.length) { var b = new Uint8Array(chan.buffer_curr + buffer.length); From 4cfb14280006797201631af728d96e6b80d4ca61 Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Thu, 11 Apr 2024 10:00:37 +0200 Subject: [PATCH 4/5] WIP --- runtime/io.js | 56 ++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/runtime/io.js b/runtime/io.js index ebea8b831a..680640ae1d 100644 --- a/runtime/io.js +++ b/runtime/io.js @@ -100,45 +100,52 @@ function caml_ml_set_channel_name(chanid, name) { var chan = caml_ml_channels[chanid]; chan.name = name; return 0; - } +} + +//Provides: caml_ml_channels +function caml_ml_channels_state() { + this.map = new globalThis.WeakMap (); + this.opened = new globalThis.Set(); +} +caml_ml_channels_state.prototype.close = function (chanid) { + this.opened.delete(chanid); +} +caml_ml_channels_state.prototype.get = function (chanid) { + return this.map.get(chanid); +} +caml_ml_channels_state.prototype.set = function (chanid, val) { + if(val.opened) this.opened.add(chanid); + return this.map.set(chanid,val); +} +caml_ml_channels_state.prototype.all = function () { + return this.opened.values(); +} - //Provides: caml_ml_channels -var caml_ml_channels_weak = new globalThis.WeakMap (); var channels_handlers = { get (target, prop, receiver) { if(typeof prop == "symbol"){ - return caml_ml_channels_weak.get(prop); - } - else { - console.log("cannot find", prop); - return + return target.get(prop); } + return globalThis.Reflect.get(...arguments); }, - set (target, prop, new_val) { + set (target, prop, new_val, receiver) { if(typeof prop == "symbol"){ - return caml_ml_channels_weak.set(prop, new_val); + target.set(prop, new_val); } - return; + return true; } } -var caml_ml_channels = new globalThis.Proxy(caml_ml_channels_weak, channels_handlers); - - -//Provides: caml_ml_channels_opened -var caml_ml_channels_opened = new globalThis.Set() +var caml_ml_channels = new globalThis.Proxy(new caml_ml_channels_state, channels_handlers); //Provides: caml_ml_out_channels_list //Requires: caml_ml_channels -//Requires: caml_ml_channels_opened //Requires: caml_sys_fds function caml_ml_out_channels_list () { var l = 0; - var keys = caml_ml_channels_opened.keys(); + var keys = caml_ml_channels.all(); for(var k of keys){ var chan = caml_ml_channels[k]; - if(chan.opened && chan.out){ - l=[0,caml_sys_fds[chan.fd].chanid,l]; - } + if(chan.opened && chan.out) l=[0,k,l]; } return l; } @@ -148,7 +155,6 @@ function caml_ml_out_channels_list () { //Requires: caml_ml_channels, caml_sys_fds //Requires: caml_raise_sys_error //Requires: caml_sys_open -//Requires: caml_ml_channels_opened function caml_ml_open_descriptor_out (fd) { var s = caml_sys_fds[fd], file = s.file, chanid = s.chanid; if(file.flags.rdonly) caml_raise_sys_error("fd "+ fd + " is readonly"); @@ -163,7 +169,6 @@ function caml_ml_open_descriptor_out (fd) { buffer:new Uint8Array(65536), buffered:buffered }; - caml_ml_channels_opened.add(chanid); caml_ml_channels[chanid] = channel; return chanid; } @@ -172,7 +177,6 @@ function caml_ml_open_descriptor_out (fd) { //Requires: caml_ml_channels, caml_sys_fds //Requires: caml_raise_sys_error //Requires: caml_sys_open -//Requires: caml_ml_channels_opened function caml_ml_open_descriptor_in (fd) { var s = caml_sys_fds[fd], file = s.file, chanid = s.chanid; if(file.flags.wronly) caml_raise_sys_error("fd "+ fd + " is writeonly"); @@ -188,7 +192,6 @@ function caml_ml_open_descriptor_in (fd) { buffer:new Uint8Array(65536), refill:refill }; - caml_ml_channels_opened.add(chanid); caml_ml_channels[chanid] = channel; return chanid; } @@ -238,12 +241,11 @@ function caml_ml_is_binary_mode(chanid) { //Provides: caml_ml_close_channel //Requires: caml_ml_flush, caml_ml_channels //Requires: caml_sys_close -//Requires: caml_ml_channels_opened function caml_ml_close_channel (chanid) { var chan = caml_ml_channels[chanid]; if(chan.opened) { chan.opened = false; - delete caml_ml_channels_opened.delete(chanid); + caml_ml_channels.close(chanid); caml_sys_close(chan.fd); chan.fd = -1; chan.buffer = new Uint8Array(0); From 81814fec883248b4893799dd8cbf15e77d0d7ef0 Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Thu, 11 Apr 2024 10:30:00 +0200 Subject: [PATCH 5/5] Changes --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index a724718ded..cfc19fbcaa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ * Compiler: fix variable renaming for property binding and assignment target * Compiler: fix separate compilation of toplevels (broken since 5.7.0) +* Runtime: no longer leak channels # 5.7.2 (2024-04-03) - Lille