diff options
author | daurnimator <quae@daurnimator.com> | 2017-12-15 14:57:13 +1100 |
---|---|---|
committer | daurnimator <quae@daurnimator.com> | 2017-12-15 14:57:13 +1100 |
commit | e0e5d05626fcd6cb4622abcaae9fc951d9ae91b1 (patch) | |
tree | 49531b2a69c166ad193adddf50edbadb5e1a91a1 /src | |
parent | 6099ba186c38c854332ec483edd6cbca3cf94871 (diff) | |
parent | 8249248f80467f1660509a30623f40bb9ff1eba7 (diff) | |
download | fengari-e0e5d05626fcd6cb4622abcaae9fc951d9ae91b1.tar.gz fengari-e0e5d05626fcd6cb4622abcaae9fc951d9ae91b1.tar.bz2 fengari-e0e5d05626fcd6cb4622abcaae9fc951d9ae91b1.zip |
Merge branch 'Uint8Array'
Diffstat (limited to 'src')
-rw-r--r-- | src/defs.js | 7 | ||||
-rw-r--r-- | src/lapi.js | 15 | ||||
-rw-r--r-- | src/lauxlib.js | 17 | ||||
-rw-r--r-- | src/lbaselib.js | 2 | ||||
-rw-r--r-- | src/ldblib.js | 4 | ||||
-rw-r--r-- | src/ldump.js | 23 | ||||
-rw-r--r-- | src/llex.js | 9 | ||||
-rw-r--r-- | src/llimits.js | 4 | ||||
-rw-r--r-- | src/lobject.js | 31 | ||||
-rw-r--r-- | src/loslib.js | 10 | ||||
-rw-r--r-- | src/lstring.js | 5 | ||||
-rw-r--r-- | src/luaconf.js | 2 | ||||
-rw-r--r-- | src/lundump.js | 4 | ||||
-rw-r--r-- | src/lutf8lib.js | 2 | ||||
-rw-r--r-- | src/lvm.js | 29 | ||||
-rw-r--r-- | src/lzio.js | 42 |
16 files changed, 112 insertions, 94 deletions
diff --git a/src/defs.js b/src/defs.js index 27498c6..381114b 100644 --- a/src/defs.js +++ b/src/defs.js @@ -131,10 +131,10 @@ class lua_Debug { } -const string_of = Array.of; +const string_of = Uint8Array.of.bind(Uint8Array); const is_luastring = function(s) { - return Array.isArray(s); + return s instanceof Uint8Array; }; /* test two lua strings for equality */ @@ -143,7 +143,7 @@ const luastring_cmp = function(a, b) { }; const to_jsstring = function(value, from, to) { - assert(is_luastring(value), "jsstring expects an array of bytes"); + assert(is_luastring(value), "jsstring expects a Uint8Array"); if (to === void 0) { to = value.length; @@ -240,6 +240,7 @@ const to_luastring = function(str, cache) { outU8Array[outIdx++] = 0x80 | (u & 63); } } + outU8Array = Uint8Array.from(outU8Array); if (cache) to_luastring_cache[str] = outU8Array; diff --git a/src/lapi.js b/src/lapi.js index afa94ce..111735f 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -672,19 +672,8 @@ const lua_toljsstring = function(L, idx) { const lua_tojsstring = lua_toljsstring; const lua_todataview = function(L, idx) { - let o = index2addr(L, idx); - - if (!o.ttisstring()) { - if (!lvm.cvt2str(o)) { /* not convertible? */ - return null; - } - lobject.luaO_tostring(L, o); - } - - let dv = new DataView(new ArrayBuffer(o.vslen())); - o.svalue().forEach((e, i) => dv.setUint8(i, e, true)); - - return dv; + let u8 = lua_tolstring(L, idx); + return new DataView(u8.buffer, u8.byteOffset, u8.byteLength); }; const lua_rawlen = function(L, idx) { diff --git a/src/lauxlib.js b/src/lauxlib.js index b9b7078..5687242 100644 --- a/src/lauxlib.js +++ b/src/lauxlib.js @@ -62,7 +62,7 @@ const pushglobalfuncname = function(L, ar) { if (findfield(L, top + 1, 2)) { let name = lua.lua_tostring(L, -1); if (name[0] === "_".charCodeAt(0) && name[1] === "G".charCodeAt(0) && name[2] === ".".charCodeAt(0)) { /* name start with '_G.'? */ - lua.lua_pushstring(L, name.slice(3)); /* push name without prefix */ + lua.lua_pushstring(L, name.subarray(3)); /* push name without prefix */ lua.lua_remove(L, -2); /* remove original name */ } lua.lua_copy(L, -1, top + 1); /* move name to proper place */ @@ -381,14 +381,14 @@ const luaL_prepbuffer = function(B) { }; const luaL_addlstring = function(B, s, l) { - B.b = B.b.concat(s.slice(0, l)); + B.b = B.b.concat(Array.from(s.subarray(0, l))); }; const luaL_addstring = luaL_addlstring; const luaL_pushresult = function(B) { let L = B.L; - lua.lua_pushstring(L, B.b); + lua.lua_pushstring(L, Uint8Array.from(B.b)); }; const luaL_addchar = function(B, c) { @@ -558,7 +558,7 @@ const luaL_gsub = function(L, s, p, r) { s = s.slice(wild + p.length); /* continue after 'p' */ } b.push(...s); /* push last suffix */ - lua.lua_pushstring(L, b); + lua.lua_pushstring(L, Uint8Array.from(b)); return lua.lua_tostring(L, -1); }; @@ -713,7 +713,7 @@ class LoadF { constructor() { this.n = NaN; /* number of pre-read characters */ this.f = null; /* file being read */ - this.buff = typeof process === "undefined" ? new Array(1024) : new Buffer(1024); /* area for reading file */ + this.buff = new Uint8Array(1024); /* area for reading file */ this.pos = 0; /* current position in file */ this.err = void 0; } @@ -726,8 +726,8 @@ if (typeof process === "undefined") { if (lf.f !== null && lf.n > 0) { /* are there pre-read characters to be read? */ let bytes = lf.n; /* return them (chars already in buffer) */ lf.n = 0; /* no more pre-read characters */ - lf.f = lf.f.slice(lf.pos); /* we won't use lf.buff anymore */ - return lf.buff.slice(0, bytes); + lf.f = lf.f.subarray(lf.pos); /* we won't use lf.buff anymore */ + return lf.buff.subarray(0, bytes); } let f = lf.f; @@ -789,7 +789,6 @@ if (typeof process === "undefined") { 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) { @@ -799,7 +798,7 @@ if (typeof process === "undefined") { lf.pos += bytes; } if (bytes > 0) - return lf.buff.slice(0, bytes); /* slice on a node.js Buffer is 'free' */ + return lf.buff.subarray(0, bytes); /* slice on a node.js Buffer is 'free' */ else return null; }; diff --git a/src/lbaselib.js b/src/lbaselib.js index 30e77fb..103a9ca 100644 --- a/src/lbaselib.js +++ b/src/lbaselib.js @@ -8,7 +8,7 @@ let lua_writeline; if (typeof process === "undefined") { let buff = []; lua_writestring = function(s) { - buff = buff.concat(s); + buff = buff.concat(Array.from(s)); }; lua_writeline = function() { console.log(new TextDecoder("utf-8").decode(Uint8Array.from(buff))); diff --git a/src/ldblib.js b/src/ldblib.js index 746d3bf..df7d2ff 100644 --- a/src/ldblib.js +++ b/src/ldblib.js @@ -306,7 +306,7 @@ const unmakemask = function(mask, smask) { if (mask & lua.LUA_MASKCALL) smask[i++] = "c".charCodeAt(0); if (mask & lua.LUA_MASKRET) smask[i++] = "r".charCodeAt(0); if (mask & lua.LUA_MASKLINE) smask[i++] = "l".charCodeAt(0); - return smask; + return smask.subarray(0, i); }; const db_sethook = function(L) { @@ -344,7 +344,7 @@ const db_sethook = function(L) { const db_gethook = function(L) { let thread = getthread(L); let L1 = thread.thread; - let buff = []; + let buff = new Uint8Array(5); let mask = lua.lua_gethookmask(L1); let hook = lua.lua_gethook(L1); if (hook === null) /* no hook? */ diff --git a/src/ldump.js b/src/ldump.js index 964d6ff..7e62da3 100644 --- a/src/ldump.js +++ b/src/ldump.js @@ -34,31 +34,26 @@ const DumpByte = function(y, D) { }; const DumpInt = function(x, D) { - let dv = new DataView(new ArrayBuffer(4)); + let ab = new ArrayBuffer(4); + let dv = new DataView(ab); dv.setInt32(0, x, true); - let t = []; - for (let i = 0; i < 4; i++) - t.push(dv.getUint8(i, true)); - + let t = new Uint8Array(ab); DumpBlock(t, 4, D); }; const DumpInteger = function(x, D) { - let dv = new DataView(new ArrayBuffer(4)); + let ab = new ArrayBuffer(4); + let dv = new DataView(ab); dv.setInt32(0, x, true); - let t = []; - for (let i = 0; i < 4; i++) - t.push(dv.getUint8(i, true)); + let t = new Uint8Array(ab); DumpBlock(t, 4, D); }; const DumpNumber = function(x, D) { - let dv = new DataView(new ArrayBuffer(8)); + let ab = new ArrayBuffer(8); + let dv = new DataView(ab); dv.setFloat64(0, x, true); - let t = []; - for (let i = 0; i < 8; i++) - t.push(dv.getUint8(i, true)); - + let t = new Uint8Array(ab); DumpBlock(t, 8, D); }; diff --git a/src/llex.js b/src/llex.js index 779557a..438f288 100644 --- a/src/llex.js +++ b/src/llex.js @@ -112,6 +112,8 @@ const save = function(ls, c) { if (b.n + 1 > b.buffer.length) { if (b.buffer.length >= llimits.MAX_INT/2) lexerror(ls, defs.to_luastring("lexical element too long", true), 0); + let newsize = b.buffer.length*2; + lzio.luaZ_resizebuffer(ls.L, b, newsize); } b.buffer[b.n++] = c < 0 ? 255 + c + 1 : c; }; @@ -192,6 +194,7 @@ const luaX_setinput = function(L, ls, z, source, firstchar) { ls.lastline = 1; ls.source = source; ls.envn = lstring.luaS_bless(L, LUA_ENV); + lzio.luaZ_resizebuffer(L, ls.buff, llimits.LUA_MINBUFFER); /* initialize buffer */ }; const check_next1 = function(ls, c) { @@ -325,7 +328,7 @@ const read_long_string = function(ls, seminfo, sep) { } if (seminfo) - seminfo.ts = luaX_newstring(ls, ls.buff.buffer.slice(2 + sep, ls.buff.n - (2 + sep))); + seminfo.ts = luaX_newstring(ls, ls.buff.buffer.subarray(2 + sep, ls.buff.n - (2 + sep))); }; const esccheck = function(ls, c, msg) { @@ -369,7 +372,7 @@ const readutf8desc = function(ls) { }; const utf8esc = function(ls) { - let buff = new Array(lobject.UTF8BUFFSZ); + let buff = new Uint8Array(lobject.UTF8BUFFSZ); let n = lobject.luaO_utf8esc(buff, readutf8desc(ls)); for (; n > 0; n--) /* add 'buff' to string */ save(ls, buff[lobject.UTF8BUFFSZ - n]); @@ -450,7 +453,7 @@ const read_string = function(ls, del, seminfo) { } save_and_next(ls); /* skip delimiter */ - seminfo.ts = luaX_newstring(ls, ls.buff.buffer.slice(1, ls.buff.n-1)); + seminfo.ts = luaX_newstring(ls, ls.buff.buffer.subarray(1, ls.buff.n-1)); }; const token_to_index = Object.create(null); /* don't want to return true for e.g. 'hasOwnProperty' */ diff --git a/src/llimits.js b/src/llimits.js index 21a09a0..4a76bbe 100644 --- a/src/llimits.js +++ b/src/llimits.js @@ -3,6 +3,10 @@ const LUAI_MAXCCALLS = 200; module.exports.LUAI_MAXCCALLS = LUAI_MAXCCALLS; +/* minimum size for string buffer */ +const LUA_MINBUFFER = 32; +module.exports.LUA_MINBUFFER = LUA_MINBUFFER; + const luai_nummod = function(L, a, b) { let m = a % b; if ((m*b) < 0) diff --git a/src/lobject.js b/src/lobject.js index 707cdf8..c02bc91 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -294,7 +294,7 @@ class LocVar { } } -const RETS = defs.to_luastring("...", true); +const RETS = defs.to_luastring("..."); const PRE = defs.to_luastring("[string \""); const POS = defs.to_luastring("\"]"); @@ -305,26 +305,37 @@ const luaO_chunkid = function(source, bufflen) { if (l < bufflen) /* small enough? */ out = source.slice(1); else { /* truncate it */ - out = source.slice(1, bufflen); + out = source.slice(1, bufflen+1); } } else if (source[0] === char['@']) { /* file name */ if (l <= bufflen) /* small enough? */ out = source.slice(1); else { /* add '...' before rest of name */ + out = new Uint8Array(bufflen); + out.set(RETS); bufflen -= RETS.length; - out = RETS.concat(source.slice(1 + l - bufflen)); + out.set(source.subarray(l - bufflen), RETS.length); } } else { /* string; format as [string "source"] */ + out = new Uint8Array(bufflen); let nli = source.indexOf(char['\n']); /* find first new line (if any) */ - out = PRE; /* add prefix */ - bufflen -= PRE.length + RETS.length + POS.length + 1; /* save space for prefix+suffix+'\0' */ + out.set(PRE); /* add prefix */ + let out_i = PRE.length; + bufflen -= PRE.length + RETS.length + POS.length; /* save space for prefix+suffix */ if (l < bufflen && nli === -1) { /* small one-line source? */ - out = out.concat(source, POS); /* keep it */ + out.set(source, out_i); /* keep it */ + out_i += source.length; } else { if (nli !== -1) l = nli; /* stop at first newline */ if (l > bufflen) l = bufflen; - out = out.concat(source.slice(0, l), RETS, POS); + out.set(source.subarray(0, l), out_i); + out_i += l; + out.set(RETS, out_i); + out_i += RETS.length; } + out.set(POS, out_i); + out_i += POS.length; + out = out.subarray(0, out_i); } return out; }; @@ -530,7 +541,7 @@ const luaO_pushvfstring = function(L, fmt, argp) { for (;;) { e = fmt.indexOf(char['%'], i); if (e == -1) break; - pushstr(L, fmt.slice(i, e)); + pushstr(L, fmt.subarray(i, e)); switch(fmt[e+1]) { case char['s']: { let s = argp[a++]; @@ -539,7 +550,7 @@ const luaO_pushvfstring = function(L, fmt, argp) { /* respect null terminator */ let i = s.indexOf(0); if (i !== -1) - s = s.slice(0, i); + s = s.subarray(0, i); } pushstr(L, s); break; @@ -608,7 +619,7 @@ const luaO_pushvfstring = function(L, fmt, argp) { i = e + 2; } ldo.luaD_checkstack(L, 1); - pushstr(L, fmt.slice(i)); + pushstr(L, fmt.subarray(i)); if (n > 0) lvm.luaV_concat(L, n+1); return L.stack[L.top-1].svalue(); }; diff --git a/src/loslib.js b/src/loslib.js index 19dfd02..f27a7ed 100644 --- a/src/loslib.js +++ b/src/loslib.js @@ -73,7 +73,7 @@ const checkoption = function(L, conv, i, buff) { if (option[o] === '|'.charCodeAt(0)) /* next block? */ oplen++; /* will check options with next length (+1) */ else if (array_cmp(conv, i, option, o, oplen)) { /* match? */ - buff.push(...conv.slice(i, i+oplen)); /* copy valid option to buffer */ + buff.set(conv.slice(i, i+oplen)); /* copy valid option to buffer */ return i + oplen; /* return next item */ } } @@ -102,6 +102,8 @@ const os_date = function(L) { lua.lua_createtable(L, 0, 9); /* 9 = number of fields */ setallfields(L, stm, utc); } else { + let cc = new Uint8Array(4); + cc[0] = "%".charCodeAt(0); let b = new lauxlib.luaL_Buffer(); lauxlib.luaL_buffinit(L, b); while (i < s.length) { @@ -109,8 +111,10 @@ const os_date = function(L) { lauxlib.luaL_addchar(b, s[i++]); } else { i++; /* skip '%' */ - let cc = ["%".charCodeAt(0)]; - i = checkoption(L, s, i, cc); /* copy specifier to 'cc' */ + i = checkoption(L, s, i, cc.subarray(1)); /* copy specifier to 'cc' */ + let len = cc.indexOf(0); + if (len !== -1) + cc = cc.subarray(0, len); let buff = strftime(lua.to_jsstring(cc), stm); lauxlib.luaL_addstring(b, lua.to_luastring(buff)); } diff --git a/src/lstring.js b/src/lstring.js index c85e5b2..c8da56a 100644 --- a/src/lstring.js +++ b/src/lstring.js @@ -31,7 +31,7 @@ const luaS_eqlngstr = function(a, b) { make sure this doesn't conflict with any of the anti-collision strategies in ltable */ const luaS_hash = function(str) { assert(defs.is_luastring(str)); - return str.map(e => `${e}|`).join(''); + return '|'+str.join('|'); }; const luaS_hashlongstr = function(ts) { @@ -44,12 +44,13 @@ const luaS_hashlongstr = function(ts) { /* variant that takes ownership of array */ const luaS_bless = function(L, str) { + assert(str instanceof Uint8Array); return new TString(L, str); }; /* makes a copy */ const luaS_new = function(L, str) { - return luaS_bless(L, str.slice(0)); + return luaS_bless(L, Uint8Array.from(str)); }; /* takes a js string */ diff --git a/src/luaconf.js b/src/luaconf.js index 00663a6..5331720 100644 --- a/src/luaconf.js +++ b/src/luaconf.js @@ -19,7 +19,7 @@ const LUAI_MAXSTACK = 100000; @@ of a function in debug information. ** CHANGE it if you want a different size. */ -const LUA_IDSIZE = 60; +const LUA_IDSIZE = 60-1; /* fengari uses 1 less than lua as we don't embed the null byte */ const lua_integer2str = function(n) { return sprintf(LUA_INTEGER_FMT, n); diff --git a/src/lundump.js b/src/lundump.js index ff87903..e49c376 100644 --- a/src/lundump.js +++ b/src/lundump.js @@ -25,7 +25,7 @@ class BytecodeParser { assert(defs.is_luastring(name)); if (name[0] == defs.char["@"] || name[0] == defs.char["="]) - this.name = name.slice(1); + this.name = name.subarray(1); else if (name[0] == defs.LUA_SIGNATURE.charCodeAt(0)) this.name = defs.to_luastring("binary string", true); else @@ -46,7 +46,7 @@ class BytecodeParser { let u8 = new Uint8Array(size); if(lzio.luaZ_read(this.Z, u8, 0, size) !== 0) this.error("truncated"); - return Array.from(u8); + return u8; } readByte() { diff --git a/src/lutf8lib.js b/src/lutf8lib.js index 3baeeef..f581a9e 100644 --- a/src/lutf8lib.js +++ b/src/lutf8lib.js @@ -216,7 +216,7 @@ const funcs = { }; /* pattern to match a single UTF-8 character */ -const UTF8PATT = [ 91, 0, 45, 127, 194, 45, 244, 93, 91, 128, 45, 191, 93, 42 ]; +const UTF8PATT = Uint8Array.of(91, 0, 45, 127, 194, 45, 244, 93, 91, 128, 45, 191, 93, 42); const luaopen_utf8 = function(L) { lauxlib.luaL_newlib(L, funcs); @@ -937,6 +937,18 @@ const isemptystr = function(o) { return o.ttisstring() && o.vslen() === 0; }; +/* copy strings in stack from top - n up to top - 1 to buffer */ +const copy2buff = function(L, top, n, buff) { + let tl = 0; /* size already copied */ + do { + let tv = L.stack[top-n]; + let l = tv.vslen(); /* length of string being copied */ + let s = tv.svalue(); + buff.set(s, tl); + tl += l; + } while (--n > 0); +}; + /* ** Main operation for concatenation: concat 'total' values in the stack, ** from 'L->top - total' up to 'L->top - 1'. @@ -955,16 +967,15 @@ const luaV_concat = function(L, total) { lobject.setobjs2s(L, top - 2, top - 1); } else { /* at least two non-empty string values; get as many as possible */ - let toconcat = new Array(total); - toconcat[total-1] = L.stack[top-1].svalue(); - for (n = 1; n < total; n++) { - if (!tostring(L, top - n - 1)) { - toconcat = toconcat.slice(total-n); - break; - } - toconcat[total-n-1] = L.stack[top - n - 1].svalue(); + let tl = L.stack[top-1].vslen(); + /* collect total length and number of strings */ + for (n = 1; n < total && tostring(L, top - n - 1); n++) { + let l = L.stack[top - n - 1].vslen(); + tl += l; } - let ts = lstring.luaS_bless(L, Array.prototype.concat.apply([], toconcat)); + let buff = new Uint8Array(tl); + copy2buff(L, top, n, buff); + let ts = lstring.luaS_bless(L, buff); lobject.setsvalue2s(L, top - n, ts); } total -= n - 1; /* got 'n' strings to create 1 new */ diff --git a/src/lzio.js b/src/lzio.js index 3d877aa..a00a24b 100644 --- a/src/lzio.js +++ b/src/lzio.js @@ -11,7 +11,7 @@ class MBuffer { } const luaZ_buffer = function(buff) { - return buff.buffer; + return buff.buffer.subarray(0, buff.n); }; const luaZ_buffremove = function(buff, i) { @@ -20,7 +20,13 @@ const luaZ_buffremove = function(buff, i) { const luaZ_resetbuffer = function(buff) { buff.n = 0; - buff.buffer = []; +}; + +const luaZ_resizebuffer = function(L, buff, size) { + let newbuff = new Uint8Array(size); + if (buff.buffer) + newbuff.set(buff.buffer); + buff.buffer = newbuff; }; class ZIO { @@ -42,22 +48,15 @@ class ZIO { const EOZ = -1; const luaZ_fill = function(z) { - let size; let buff = z.reader(z.L, z.data); if (buff === null) return EOZ; - if (buff instanceof DataView) { - z.buffer = new Uint8Array(buff.buffer, buff.byteOffset, buff.byteLength); - z.off = 0; - size = buff.byteLength - buff.byteOffset; - } else { - assert(typeof buff !== "string", "Should only load binary of array of bytes"); - z.buffer = buff; - z.off = 0; - size = buff.length; - } + assert(buff instanceof Uint8Array, "Should only load binary of array of bytes"); + let size = buff.length; if (size === 0) return EOZ; + z.buffer = buff; + z.off = 0; z.n = size - 1; return z.buffer[z.off++]; }; @@ -87,11 +86,12 @@ const luaZ_read = function(z, b, b_offset, n) { return 0; }; -module.exports.EOZ = EOZ; -module.exports.luaZ_buffer = luaZ_buffer; -module.exports.luaZ_buffremove = luaZ_buffremove; -module.exports.luaZ_fill = luaZ_fill; -module.exports.luaZ_read = luaZ_read; -module.exports.luaZ_resetbuffer = luaZ_resetbuffer; -module.exports.MBuffer = MBuffer; -module.exports.ZIO = ZIO; +module.exports.EOZ = EOZ; +module.exports.luaZ_buffer = luaZ_buffer; +module.exports.luaZ_buffremove = luaZ_buffremove; +module.exports.luaZ_fill = luaZ_fill; +module.exports.luaZ_read = luaZ_read; +module.exports.luaZ_resetbuffer = luaZ_resetbuffer; +module.exports.luaZ_resizebuffer = luaZ_resizebuffer; +module.exports.MBuffer = MBuffer; +module.exports.ZIO = ZIO; |