diff --git a/lib/js_of_ocaml/js_of_ocaml_stubs.c b/lib/js_of_ocaml/js_of_ocaml_stubs.c index 0e1c1b22db..9577aa127c 100644 --- a/lib/js_of_ocaml/js_of_ocaml_stubs.c +++ b/lib/js_of_ocaml/js_of_ocaml_stubs.c @@ -232,6 +232,10 @@ void caml_read_file_content () { fprintf(stderr, "Unimplemented Javascript primitive caml_read_file_content!\n"); exit(1); } +void caml_register_lazy () { + fprintf(stderr, "Unimplemented Javascript primitive caml_register_lazy!\n"); + exit(1); +} void caml_string_of_array () { fprintf(stderr, "Unimplemented Javascript primitive caml_string_of_array!\n"); exit(1); diff --git a/lib/js_of_ocaml/sys_js.ml b/lib/js_of_ocaml/sys_js.ml index 79455100fe..9288569bab 100644 --- a/lib/js_of_ocaml/sys_js.ml +++ b/lib/js_of_ocaml/sys_js.ml @@ -61,3 +61,5 @@ let js_of_ocaml_version = if String.equal Lib_version.git_version "" then Lib_version.s else Lib_version.s ^ "+" ^ Lib_version.git_version + +external register_lazy : string -> unit = "caml_register_lazy" diff --git a/lib/js_of_ocaml/sys_js.mli b/lib/js_of_ocaml/sys_js.mli index 0c06137acc..84b66e27f8 100644 --- a/lib/js_of_ocaml/sys_js.mli +++ b/lib/js_of_ocaml/sys_js.mli @@ -56,6 +56,12 @@ val create_file : name:string -> content:string -> unit [create_file ~name ~content] register the file [name] with content [content] so it can be be opened with [open_in name] *) +val register_lazy : string -> unit +(** Register a lazy file to a Pseudo Filesystem. + [register_lazy name] causes an entry to be made in the filesystem such that it + will be present in a directory list, but the callback will be called when the + file is opened. *) + val update_file : name:string -> content:string -> unit (** Update a file in the Pseudo Filesystem. [update_file ~name ~content] update the file [name] with content [content] *) diff --git a/runtime/fs.js b/runtime/fs.js index 2ee2a47d4d..e8ecafa3b2 100644 --- a/runtime/fs.js +++ b/runtime/fs.js @@ -314,7 +314,6 @@ function caml_create_file(name,content) { return 0; } - //Provides: jsoo_create_file //Requires: caml_create_file, caml_string_of_jsbytes function jsoo_create_file(name,content) { @@ -324,6 +323,16 @@ function jsoo_create_file(name,content) { } +//Provides: caml_register_lazy +//Requires: caml_failwith, resolve_fs_device, caml_string_of_jsbytes +function caml_register_lazy(name) { + var name = (typeof name == "string")?caml_string_of_jsbytes(name):name; + var root = resolve_fs_device(name); + if(! root.device.register_lazy) caml_failwith("cannot register lazy file"); + root.device.register_lazy(root.rest); + return 0; +} + //Provides: caml_read_file_content //Requires: resolve_fs_device, caml_raise_no_such_file, caml_create_bytes, caml_string_of_bytes //Requires: caml_string_of_jsbytes diff --git a/runtime/fs_fake.js b/runtime/fs_fake.js index cf71290193..3f78932cf4 100644 --- a/runtime/fs_fake.js +++ b/runtime/fs_fake.js @@ -27,6 +27,7 @@ //Requires: make_unix_err_args function MlFakeDevice (root, f) { this.content={}; + this.lazyfiles = []; this.root = root; this.lookupFun = f; } @@ -60,13 +61,15 @@ MlFakeDevice.prototype.exists = function(name) { // Check if a directory exists var name_slash = this.slash(name); if(this.content[name_slash]) return 1; + // If it's a lazy file, let's say it exists without doing a lookup. + if(this.lazyfiles.indexOf(name) >= 0) return 1; // Check if a file exists this.lookup(name); return this.content[name]?1:0; } MlFakeDevice.prototype.mkdir = function(name,mode, raise_unix) { var unix_error = raise_unix && caml_named_value('Unix.Unix_error'); - if(this.exists(name)) { + if(this.exists(name) || (this.lazyfiles.indexOf(name) >= 0)) { if (unix_error) { caml_raise_with_args(unix_error, make_unix_err_args("EEXIST", "mkdir", this.nm(name))); } @@ -140,6 +143,10 @@ MlFakeDevice.prototype.readdir = function(name) { var m = n.match(r); if(m && !seen[m[1]]) {seen[m[1]] = true; a.push(m[1])} } + this.lazyfiles.forEach(function(n) { + var m = n.match(r); + if(m && !seen[m[1]]) {seen[m[1]] = true; a.push(m[1])} + }) return a; } MlFakeDevice.prototype.is_dir = function(name) { @@ -148,7 +155,7 @@ MlFakeDevice.prototype.is_dir = function(name) { return this.content[name_slash]?1:0; } MlFakeDevice.prototype.unlink = function(name) { - var ok = this.content[name]?true:false; + var ok = (this.content[name]?true:false) || (this.lazyfiles.indexOf(name) >= 0); delete this.content[name]; return ok; } @@ -195,6 +202,10 @@ MlFakeDevice.prototype.register= function (name,content){ else caml_raise_sys_error(this.nm(name) + " : registering file with invalid content type"); } +MlFakeDevice.prototype.register_lazy = function (name) { + this.lazyfiles.push(name) +} + MlFakeDevice.prototype.constructor = MlFakeDevice //Provides: MlFakeFile