From 79a630503c8f609094f6fca8a489fd965f424d17 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Thu, 23 Mar 2017 10:11:27 +0100 Subject: Test for require and fs instead of testing for window --- src/lauxlib.js | 252 ++++++++++++++++++++++++++++---------------------------- src/lbaselib.js | 85 ++++++++++--------- 2 files changed, 174 insertions(+), 163 deletions(-) diff --git a/src/lauxlib.js b/src/lauxlib.js index 689abbb..f175fde 100644 --- a/src/lauxlib.js +++ b/src/lauxlib.js @@ -401,139 +401,143 @@ const luaL_newlib = function(L, l) { }; // Only with Node -if (typeof window === "undefined") { - 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.binary = false; +if (typeof require === "function") { + let fs = false; + try { + fs = require('fs'); + } catch (e) {} + + if (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.binary = false; + } } - } - const toDataView = function(buffer) { - let ab = new ArrayBuffer(buffer.length); - let au = new Uint8Array(ab); - for (let i = 0; i < buffer.length; i++) - au[i] = buffer[i]; - return new DataView(ab); - }; - - const getF = function(L, ud) { - let lf = ud; - let bytes = 0; - if (lf.n > 0) { /* are there pre-read characters to be read? */ - lf.n = 0; /* no more pre-read characters */ - } else { /* read a block from file */ - lf.buff.fill(0); - bytes = fs.readSync(lf.f, lf.buff, 0, lf.buff.length, lf.pos); /* read block */ + const toDataView = function(buffer) { + let ab = new ArrayBuffer(buffer.length); + let au = new Uint8Array(ab); + for (let i = 0; i < buffer.length; i++) + au[i] = buffer[i]; + return new DataView(ab); + }; + + const getF = function(L, ud) { + let lf = ud; + let bytes = 0; + if (lf.n > 0) { /* are there pre-read characters to be read? */ + lf.n = 0; /* no more pre-read characters */ + } else { /* read a block from file */ + lf.buff.fill(0); + bytes = fs.readSync(lf.f, lf.buff, 0, lf.buff.length, lf.pos); /* read block */ + lf.pos += bytes; + } + if (bytes > 0) + return lf.binary ? toDataView(lf.buff) : new lobject.TValue(0, lf.buff).jsstring(); // TODO: Here reading utf8 only + else return null; + }; + + const errfile = function(L, what, fnameindex, error) { + let serr = error.message; + let filename = lapi.lua_tostring(L, fnameindex).slice(1); + lapi.lua_pushstring(L, `cannot ${what} ${filename}: ${serr}`); + lapi.lua_remove(L, fnameindex); + return lua.thread_status.LUA_ERRFILE; + }; + + const getc = function(lf) { + let b = new Buffer(1); + let bytes = fs.readSync(lf.f, b, 0, 1, lf.pos); lf.pos += bytes; - } - if (bytes > 0) - return lf.binary ? toDataView(lf.buff) : new lobject.TValue(0, lf.buff).jsstring(); // TODO: Here reading utf8 only - else return null; - }; - - const errfile = function(L, what, fnameindex, error) { - let serr = error.message; - let filename = lapi.lua_tostring(L, fnameindex).slice(1); - lapi.lua_pushstring(L, `cannot ${what} ${filename}: ${serr}`); - lapi.lua_remove(L, fnameindex); - return lua.thread_status.LUA_ERRFILE; - }; - - const 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; - }; - - const skipBOM = function(lf) { - let p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ - lf.n = 0; - let c; - do { - c = getc(lf); - if (c === null || c !== p.charCodeAt(0)) return c; - p = p.slice(1); - lf.buff[lf.n++] = c; /* to be read by the parser */ - } while (p.length > 0); - lf.n = 0; /* prefix matched; discard it */ - return getc(lf); /* return next character */ - }; - - /* - ** reads the first character of file 'f' and skips an optional BOM mark - ** in its beginning plus its first line if it starts with '#'. Returns - ** true if it skipped the first line. In any case, '*cp' has the - ** first "valid" character of the file (after the optional BOM and - ** a first-line comment). - */ - const skipcomment = function(lf) { - let c = skipBOM(lf); - if (c === '#'.charCodeAt(0)) { /* first line is a comment (Unix exec. file)? */ - do { /* skip first line */ + return bytes > 0 ? b.readUInt8() : null; + }; + + const skipBOM = function(lf) { + let p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + lf.n = 0; + let c; + do { c = getc(lf); - } while (c && c !== '\n'.charCodeAt(0)); - - return { - skipped: true, - c: getc(lf) /* skip end-of-line, if present */ - }; - } else { - lf.pos--; - return { - skipped: false, - c: c - }; - } - }; - - const luaL_loadfilex = function(L, filename, mode) { - let lf = new LoadF(); - let fnameindex = lapi.lua_gettop(L) + 1; /* index of filename on the stack */ - if (filename === null) { - lapi.lua_pushliteral(L, "=stdin"); - lf.f = process.stdin.fd; - } else { - lapi.lua_pushstring(L, `@${filename}`); - try { - lf.f = fs.openSync(filename, "r"); - } catch (e) { - return errfile(L, "open", fnameindex, e); + if (c === null || c !== p.charCodeAt(0)) return c; + p = p.slice(1); + lf.buff[lf.n++] = c; /* to be read by the parser */ + } while (p.length > 0); + lf.n = 0; /* prefix matched; discard it */ + return getc(lf); /* return next character */ + }; + + /* + ** reads the first character of file 'f' and skips an optional BOM mark + ** in its beginning plus its first line if it starts with '#'. Returns + ** true if it skipped the first line. In any case, '*cp' has the + ** first "valid" character of the file (after the optional BOM and + ** a first-line comment). + */ + const skipcomment = function(lf) { + let c = skipBOM(lf); + if (c === '#'.charCodeAt(0)) { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf); + } while (c && c !== '\n'.charCodeAt(0)); + + return { + skipped: true, + c: getc(lf) /* skip end-of-line, if present */ + }; + } else { + lf.pos--; + return { + skipped: false, + c: c + }; } - } - - try { - let com; - if ((com = skipcomment(lf)).skipped) /* read initial portion */ - lf.buff[lf.n++] = '\n'.charCodeAt(0); /* add line to correct line numbers */ - - if (com.c === lua.LUA_SIGNATURE.charCodeAt(0) && filename) { /* binary file? */ - lf.binary = true; + }; + + const luaL_loadfilex = function(L, filename, mode) { + let lf = new LoadF(); + let fnameindex = lapi.lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename === null) { + lapi.lua_pushliteral(L, "=stdin"); + lf.f = process.stdin.fd; + } else { + lapi.lua_pushstring(L, `@${filename}`); + try { + lf.f = fs.openSync(filename, "r"); + } catch (e) { + return errfile(L, "open", fnameindex, e); + } } - let status = lapi.lua_load(L, getF, lf, lapi.lua_tostring(L, -1), mode); - if (filename) fs.closeSync(lf.f); /* close file (even in case of errors) */ - lapi.lua_remove(L, fnameindex); - return status; - } catch (err) { - lapi.lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ - return errfile(L, "read", fnameindex); - } - }; - - const luaL_loadfile = function(L, filename) { - return luaL_loadfilex(L, filename, null); - }; + try { + let com; + if ((com = skipcomment(lf)).skipped) /* read initial portion */ + lf.buff[lf.n++] = '\n'.charCodeAt(0); /* add line to correct line numbers */ + + if (com.c === lua.LUA_SIGNATURE.charCodeAt(0) && filename) { /* binary file? */ + lf.binary = true; + } + + let status = lapi.lua_load(L, getF, lf, lapi.lua_tostring(L, -1), mode); + if (filename) fs.closeSync(lf.f); /* close file (even in case of errors) */ + lapi.lua_remove(L, fnameindex); + return status; + } catch (err) { + lapi.lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ + return errfile(L, "read", fnameindex); + } + }; - module.exports.luaL_loadfilex = luaL_loadfilex; - module.exports.luaL_loadfile = luaL_loadfile; + const luaL_loadfile = function(L, filename) { + return luaL_loadfilex(L, filename, null); + }; + module.exports.luaL_loadfilex = luaL_loadfilex; + module.exports.luaL_loadfile = luaL_loadfile; + } } module.exports.LUA_LOADED_TABLE = LUA_LOADED_TABLE; diff --git a/src/lbaselib.js b/src/lbaselib.js index 83b3c33..762838c 100644 --- a/src/lbaselib.js +++ b/src/lbaselib.js @@ -333,46 +333,53 @@ const base_funcs = { }; // Only with Node -if (typeof window === "undefined") { - - const load_aux = function(L, status, envidx) { - if (status === TS.LUA_OK) { - if (envidx !== 0) { /* 'env' parameter? */ - lapi.lua_pushvalue(L, envidx); /* environment for loaded function */ - if (!lapi.lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ - lapi.lua_pop(L, 1); /* remove 'env' if not used by previous call */ +if (typeof require === "function") { + + let fs = false; + try { + fs = require('fs'); + } catch (e) {} + + if (fs) { + const load_aux = function(L, status, envidx) { + if (status === TS.LUA_OK) { + if (envidx !== 0) { /* 'env' parameter? */ + lapi.lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lapi.lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lapi.lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } + return 1; + } else { /* error (message is on top of the stack) */ + lapi.lua_pushnil(L); + lapi.lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ } - return 1; - } else { /* error (message is on top of the stack) */ - lapi.lua_pushnil(L); - lapi.lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ - } - }; - - const luaB_loadfile = function(L) { - let fname = lauxlib.luaL_optstring(L, 1, null); - let mode = lauxlib.luaL_optstring(L, 2, null); - let env = !lapi.lua_isnone(L, 3) ? 3 : 0; /* 'env' index or 0 if no 'env' */ - let status = lauxlib.luaL_loadfilex(L, fname, mode); - return load_aux(L, status, env); - }; - - const dofilecont = function(L, d1, d2) { - return lapi.lua_gettop(L) - 1; - }; - - const luaB_dofile = function(L) { - let fname = lauxlib.luaL_optstring(L, 1, null); - lapi.lua_settop(L, 1); - if (lauxlib.luaL_loadfile(L, fname) !== TS.LUA_OK) - return lapi.lua_error(L); - lapi.lua_callk(L, 0, lua.LUA_MULTRET, 0, dofilecont); - return dofilecont(L, 0, 0); - }; - - base_funcs.loadfile = luaB_loadfile; - base_funcs.dofile = luaB_dofile; + }; + + const luaB_loadfile = function(L) { + let fname = lauxlib.luaL_optstring(L, 1, null); + let mode = lauxlib.luaL_optstring(L, 2, null); + let env = !lapi.lua_isnone(L, 3) ? 3 : 0; /* 'env' index or 0 if no 'env' */ + let status = lauxlib.luaL_loadfilex(L, fname, mode); + return load_aux(L, status, env); + }; + + const dofilecont = function(L, d1, d2) { + return lapi.lua_gettop(L) - 1; + }; + + const luaB_dofile = function(L) { + let fname = lauxlib.luaL_optstring(L, 1, null); + lapi.lua_settop(L, 1); + if (lauxlib.luaL_loadfile(L, fname) !== TS.LUA_OK) + return lapi.lua_error(L); + lapi.lua_callk(L, 0, lua.LUA_MULTRET, 0, dofilecont); + return dofilecont(L, 0, 0); + }; + + base_funcs.loadfile = luaB_loadfile; + base_funcs.dofile = luaB_dofile; + } } -- cgit v1.2.3-70-g09d2