Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

## Bug fixes
* Fix small bug in global data flow analysis (#1768)
* Runtime: no longer leak channels

# 5.9.1 (02-12-2024) - Lille

Expand Down
2 changes: 1 addition & 1 deletion compiler/bin-js_of_ocaml/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ let run
| None -> None
| Some file ->
if not (Sys.file_exists file)
then failwith (Printf.sprintf "export file %S does not exists" file);
then failwith (Printf.sprintf "export file %S does not exist" file);
let ic = open_in file in
let t = Hashtbl.create 17 in
(try
Expand Down
2 changes: 1 addition & 1 deletion dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
(depends
(ocaml (and (>= 4.08) (< 5.4)))
(num :with-test)
(ppx_expect (and (>= v0.14.2) :with-test))
(ppx_expect (and (>= v0.16.1) :with-test))
(ppxlib (>= 0.15.0))
(re :with-test)
(cmdliner (>= 1.1.0))
Expand Down
2 changes: 1 addition & 1 deletion js_of_ocaml-compiler.opam
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ depends: [
"dune" {>= "3.17"}
"ocaml" {>= "4.08" & < "5.4"}
"num" {with-test}
"ppx_expect" {>= "v0.14.2" & with-test}
"ppx_expect" {>= "v0.16.1" & with-test}
"ppxlib" {>= "0.15.0"}
"re" {with-test}
"cmdliner" {>= "1.1.0"}
Expand Down
93 changes: 66 additions & 27 deletions runtime/js/io.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,19 @@ 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();
delete caml_sys_fds[fd];
var x = caml_sys_fds[fd];
if (x) {
x.file.close();
delete caml_sys_fds[fd];
}
return 0;
}

//Provides: MlChanid
function MlChanid(id) {
this.id = id;
}

//Provides: caml_sys_open
//Requires: caml_raise_sys_error
//Requires: MlFakeFd_out
Expand All @@ -39,11 +46,16 @@ function caml_sys_close(fd) {
//Requires: fs_node_supported
//Requires: caml_sys_fds
//Requires: caml_sys_open_for_node
//Requires: MlChanid
function caml_sys_open_internal(file, idx) {
var chanid;
if (idx === undefined) {
idx = caml_sys_fds.length;
}
caml_sys_fds[idx] = file;
chanid = new MlChanid(idx);
} else if (caml_sys_fds[idx]) {
chanid = caml_sys_fds[idx].chanid;
} else chanid = new MlChanid(idx);
caml_sys_fds[idx] = { file: file, chanid: chanid };
return idx | 0;
}
function caml_sys_open(name, flags, _perms) {
Expand Down Expand Up @@ -125,41 +137,58 @@ function caml_ml_set_channel_name(chanid, name) {
}

//Provides: caml_ml_channels
var caml_ml_channels = new Array();
//Requires: MlChanid
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();
};

var caml_ml_channels = new caml_ml_channels_state();

//Provides: caml_ml_channel_get
//Requires: caml_ml_channels
function caml_ml_channel_get(id) {
return caml_ml_channels.get(id);
}

//Provides: caml_ml_channel_redirect
//Requires: caml_ml_channel_get, caml_ml_channels
function caml_ml_channel_redirect(captured, into) {
var to_restore = caml_ml_channel_get(captured);
var new_ = caml_ml_channel_get(into);
caml_ml_channels[captured] = new_; // XXX
caml_ml_channels.set(captured, new_);
return to_restore;
}

//Provides: caml_ml_channel_restore
//Requires: caml_ml_channels
function caml_ml_channel_restore(captured, to_restore) {
caml_ml_channels[captured] = to_restore; // XXX
caml_ml_channels.set(captured, to_restore);
return 0;
}

//Provides: caml_ml_channel_get
//Requires: caml_ml_channels
function caml_ml_channel_get(id) {
return caml_ml_channels[id]; // XXX
}

//Provides: caml_ml_out_channels_list
//Requires: caml_ml_channels
//Requires: caml_ml_channel_get
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.all();
for (var k of keys) {
var chan = caml_ml_channel_get(k);
if (chan.opened && chan.out) l = [0, k, l];
}
return l;
}
Expand All @@ -169,7 +198,11 @@ function caml_ml_out_channels_list() {
//Requires: caml_raise_sys_error
//Requires: caml_sys_open
function caml_ml_open_descriptor_out(fd) {
var file = caml_sys_fds[fd];
var fd_desc = caml_sys_fds[fd];
if (fd_desc === undefined)
caml_raise_sys_error("fd " + fd + " doesn't exist");
var file = fd_desc.file;
var chanid = fd_desc.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 = {
Expand All @@ -182,16 +215,20 @@ 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.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
function caml_ml_open_descriptor_in(fd) {
var file = caml_sys_fds[fd];
var fd_desc = caml_sys_fds[fd];
if (fd_desc === undefined)
caml_raise_sys_error("fd " + fd + " doesn't exist");
var file = fd_desc.file;
var chanid = fd_desc.chanid;
if (file.flags.wronly) caml_raise_sys_error("fd " + fd + " is writeonly");
var refill = null;
var channel = {
Expand All @@ -205,8 +242,8 @@ 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.set(chanid, channel);
return chanid;
}

//Provides: caml_ml_open_descriptor_in_with_flags
Expand Down Expand Up @@ -253,10 +290,12 @@ function caml_ml_is_binary_mode(chanid) {
//Provides: caml_ml_close_channel
//Requires: caml_ml_flush, caml_ml_channel_get
//Requires: caml_sys_close
//Requires: caml_ml_channels
function caml_ml_close_channel(chanid) {
var chan = caml_ml_channel_get(chanid);
if (chan.opened) {
chan.opened = false;
caml_ml_channels.close(chanid);
caml_sys_close(chan.fd);
chan.fd = -1;
chan.buffer = new Uint8Array(0);
Expand Down
3 changes: 2 additions & 1 deletion runtime/js/parsing.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -82,7 +83,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) {
Expand Down
Loading