From e27371519c9674e9891f8dbdf4413b98ab567026 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Wed, 2 Aug 2017 08:03:33 +0200 Subject: LoadF is the same in the browser and in node --- README.md | 2 +- src/lauxlib.js | 133 ++++++++++++++++++++++++++------------------------------- src/loadlib.js | 61 +++++++++++++------------- 3 files changed, 91 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index 4ce66c7..78ed892 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ To address that issue, Lua strings are represented by an array of bytes in Fenga ### `require` and `package.loadlib` -In the browser `require` and `package.loadlib` try to find a file by making XHR requests. +In the browser `require` and `package.loadlib` try to find a file by making synchronous XHR requests. ### _Missing_ features diff --git a/src/lauxlib.js b/src/lauxlib.js index eb174be..6489dc7 100644 --- a/src/lauxlib.js +++ b/src/lauxlib.js @@ -698,62 +698,48 @@ const skipcomment = function(lf) { let luaL_loadfilex; -if (!WEB) { - const fs = require('fs'); - - class LoadF { - constructor() { - this.n = NaN; /* number of pre-read characters */ - this.f = null; /* file being read */ - this.buff = new Buffer(1024); /* area for reading file */ - this.pos = 0; /* current position in file */ - this.err = void 0; - } +class LoadF { + constructor() { + this.n = NaN; /* number of pre-read characters */ + this.f = null; /* file being read */ + this.buff = new Buffer(1024); /* area for reading file */ + this.pos = 0; /* current position in file */ + this.err = void 0; } +} +if (WEB) { const getF = function(L, ud) { let lf = ud; - let bytes = 0; - if (lf.n > 0) { /* are there pre-read characters to be read? */ - bytes = lf.n; /* return them (chars already in buffer) */ - lf.n = 0; /* no more pre-read characters */ - } else { /* read a block from file */ - lf.buff.fill(0); - try { - bytes = fs.readSync(lf.f, lf.buff, 0, lf.buff.length, lf.pos); /* read block */ - } catch(e) { - lf.err = e; - bytes = 0; - } - lf.pos += bytes; - } - if (bytes > 0) - return lf.buff.slice(0, bytes); /* slice on a node.js Buffer is 'free' */ - else return null; + let f = lf.f; + lf.f = null; + return f; }; getc = function(lf) { - let b = new Buffer(1); - let bytes = fs.readSync(lf.f, b, 0, 1, lf.pos); - lf.pos += bytes; - return bytes > 0 ? b.readUInt8() : null; + return lf.pos < lf.f.length ? lf.f[lf.pos++] : null; }; luaL_loadfilex = function(L, filename, mode) { let lf = new LoadF(); let fnameindex = lua.lua_gettop(L) + 1; /* index of filename on the stack */ if (filename === null) { - lua.lua_pushliteral(L, "=stdin"); - lf.f = process.stdin.fd; + throw new Error("Can't read stdin in the browser"); } else { let jsfilename = lua.to_jsstring(filename); lua.lua_pushfstring(L, "@%s", filename); - try { - lf.f = fs.openSync(jsfilename, "r"); - if (!fs.fstatSync(lf.f).isFile()) - throw new Error(`${jsfilename} is not a readable file`); - } catch (e) { - return errfile(L, "open", fnameindex, e); + + let xhr = new XMLHttpRequest(); + xhr.open("GET", jsfilename, false); + // TODO: find a way to load bytes instead of js string + xhr.send(); + + if (xhr.status >= 200 && xhr.status <= 299) { + /* TODO: Synchronous xhr alway return a js string */ + lf.f = lua.to_luastring(xhr.response); + } else { + lf.err = xhr.status; + return errfile(L, "open", fnameindex, { message: `${xhr.status}: ${xhr.statusText}` }); } } let com = skipcomment(lf); @@ -767,7 +753,6 @@ if (!WEB) { lf.buff[lf.n++] = com.c; /* 'c' is the first character of the stream */ let status = lua.lua_load(L, getF, lf, lua.lua_tostring(L, -1), mode); let readstatus = lf.err; - if (filename) try { fs.closeSync(lf.f); } catch(e) {} /* close file (even in case of errors) */ if (readstatus) { lua.lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ return errfile(L, "read", fnameindex, readstatus); @@ -776,47 +761,51 @@ if (!WEB) { return status; }; } else { - class LoadF { - constructor() { - this.n = NaN; /* number of pre-read characters */ - this.f = null; /* file being read */ - this.buff = new Buffer(1024); /* area for reading file */ - this.pos = 0; /* current position in file */ - this.err = void 0; - } - } + const fs = require('fs'); const getF = function(L, ud) { let lf = ud; - let f = lf.f; - lf.f = null; - return f; + let bytes = 0; + if (lf.n > 0) { /* are there pre-read characters to be read? */ + bytes = lf.n; /* return them (chars already in buffer) */ + lf.n = 0; /* no more pre-read characters */ + } else { /* read a block from file */ + lf.buff.fill(0); + try { + bytes = fs.readSync(lf.f, lf.buff, 0, lf.buff.length, lf.pos); /* read block */ + } catch(e) { + lf.err = e; + bytes = 0; + } + lf.pos += bytes; + } + if (bytes > 0) + return lf.buff.slice(0, bytes); /* slice on a node.js Buffer is 'free' */ + else return null; }; getc = function(lf) { - return lf.pos < lf.f.length ? lf.f[lf.pos++] : null; + let b = new Buffer(1); + let bytes = fs.readSync(lf.f, b, 0, 1, lf.pos); + lf.pos += bytes; + return bytes > 0 ? b.readUInt8() : null; }; luaL_loadfilex = function(L, filename, mode) { let lf = new LoadF(); let fnameindex = lua.lua_gettop(L) + 1; /* index of filename on the stack */ if (filename === null) { - throw new Error("Can't read stdin in the browser"); + lua.lua_pushliteral(L, "=stdin"); + lf.f = process.stdin.fd; } else { let jsfilename = lua.to_jsstring(filename); - lua.lua_pushliteral(L, `@${jsfilename}`); - - let xhr = new XMLHttpRequest(); - xhr.open("GET", jsfilename, false); - // TODO: find a way to load bytes instead of js string - xhr.send(); - - if (xhr.status >= 200 && xhr.status <= 299) { - /* TODO: Synchronous xhr alway return a js string */ - lf.f = lua.to_luastring(xhr.response); - } else { - lf.err = xhr.status; - return errfile(L, "open", fnameindex, { message: `${xhr.status}: ${xhr.statusText}` }); + lua.lua_pushfstring(L, "@%s", filename); + try { + lf.f = fs.openSync(jsfilename, "r"); + if (!fs.fstatSync(lf.f).isFile()) + throw new Error(`${jsfilename} is not a readable file`); + } catch (e) { + return errfile(L, "open", fnameindex, e); } } let com = skipcomment(lf); @@ -830,6 +819,7 @@ if (!WEB) { lf.buff[lf.n++] = com.c; /* 'c' is the first character of the stream */ let status = lua.lua_load(L, getF, lf, lua.lua_tostring(L, -1), mode); let readstatus = lf.err; + if (filename) try { fs.closeSync(lf.f); } catch(e) {} /* close file (even in case of errors) */ if (readstatus) { lua.lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ return errfile(L, "read", fnameindex, readstatus); @@ -847,10 +837,6 @@ const luaL_dofile = function(L, filename) { return (luaL_loadfile(L, filename) || lua.lua_pcall(L, 0, lua.LUA_MULTRET, 0)); }; -module.exports.luaL_dofile = luaL_dofile; -module.exports.luaL_loadfilex = luaL_loadfilex; -module.exports.luaL_loadfile = luaL_loadfile; - const lua_writestringerror = function(s) { if (process.stderr) process.stderr.write(s); else console.error(s); @@ -895,6 +881,7 @@ module.exports.luaL_checkstring = luaL_checkstring; module.exports.luaL_checktype = luaL_checktype; module.exports.luaL_checkudata = luaL_checkudata; module.exports.luaL_checkversion = luaL_checkversion; +module.exports.luaL_dofile = luaL_dofile; module.exports.luaL_dostring = luaL_dostring; module.exports.luaL_error = luaL_error; module.exports.luaL_execresult = luaL_execresult; @@ -906,6 +893,8 @@ module.exports.luaL_gsub = luaL_gsub; module.exports.luaL_len = luaL_len; module.exports.luaL_loadbuffer = luaL_loadbuffer; module.exports.luaL_loadbufferx = luaL_loadbufferx; +module.exports.luaL_loadfile = luaL_loadfile; +module.exports.luaL_loadfilex = luaL_loadfilex; module.exports.luaL_loadstring = luaL_loadstring; module.exports.luaL_newlib = luaL_newlib; module.exports.luaL_newlibtable = luaL_newlibtable; diff --git a/src/loadlib.js b/src/loadlib.js index 9400bb0..ecb5cd2 100644 --- a/src/loadlib.js +++ b/src/loadlib.js @@ -34,20 +34,36 @@ const AUXMARK = [1]; ** Returns the library; in case of error, returns NULL plus an ** error string in the stack. */ -let lsys_load = function(L, path) { - try { - path = lua.to_jsstring(path); +let lsys_load; +if (WEB) { + lsys_load = function(L, path) { + let xhr = new XMLHttpRequest(); + xhr.open("GET", lua.to_jsstring(path), false); + xhr.send(); - // Relative path ? - if (path.startsWith('.')) - path = `${process.env.PWD}/${path}`; + if (xhr.status >= 200 && xhr.status <= 299) { + return eval(xhr.response); + } else { + lua.lua_pushstring(L, lua.to_luastring(`${xhr.status}: ${xhr.statusText}`)); + return null; + } + }; +} else { + lsys_load = function(L, path) { + try { + path = lua.to_jsstring(path); - return require(path); - } catch (e) { - lua.lua_pushstring(L, lua.to_luastring(e.message)); - return null; - } -}; + // Relative path ? + if (path.startsWith('.')) + path = `${process.env.PWD}/${path}`; + + return require(path); + } catch (e) { + lua.lua_pushstring(L, lua.to_luastring(e.message)); + return null; + } + }; +} /* ** Try to find a function named 'sym' in library 'lib'. @@ -65,22 +81,6 @@ const lsys_sym = function(L, lib, sym) { } }; -if (WEB) { - lsys_load = function(L, path) { - let xhr = new XMLHttpRequest(); - xhr.open("GET", lua.to_jsstring(path), false); - xhr.send(); - /* TODO: subresource integrity check? */ - - if (xhr.status === 200) { - return eval(xhr.response); - } else { - lua.lua_pushstring(L, lua.to_luastring(`${xhr.status}: ${xhr.statusText}`)); - return null; - } - }; -} - /* ** return registry.LUA_NOENV as a boolean */ @@ -91,9 +91,7 @@ const noenv = function(L) { return b; }; -let readable = function() { - return false; -}; +let readable; // Only with Node if (!WEB) { @@ -118,7 +116,6 @@ if (!WEB) { /* Following GET request done by searcher_Web will be cached */ xhr.open("GET", lua.to_jsstring(filename), false); xhr.send(); - /* TODO: subresource integrity check? */ return xhr.status >= 200 && xhr.status <= 299; }; -- cgit v1.2.3-70-g09d2