aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Giannangeli <giann008@gmail.com>2017-03-12 10:23:11 +0100
committerBenoit Giannangeli <giann@users.noreply.github.com>2017-03-13 11:03:24 +0100
commit52fa5f8a97fd5322fcb110298c4ce14328074818 (patch)
treefbfb7f43039885491a87bdfc71f21a73e3dfbe25
parente96d75a87d879f7f455e4b9c6457bf6580743fa5 (diff)
downloadfengari-52fa5f8a97fd5322fcb110298c4ce14328074818.tar.gz
fengari-52fa5f8a97fd5322fcb110298c4ce14328074818.tar.bz2
fengari-52fa5f8a97fd5322fcb110298c4ce14328074818.zip
[Strings] lvm.js
-rw-r--r--src/ldo.js2
-rw-r--r--src/lobject.js11
-rw-r--r--src/lundump.js35
-rw-r--r--src/lvm.js43
-rw-r--r--tests/tests.js3
5 files changed, 65 insertions, 29 deletions
diff --git a/src/ldo.js b/src/ldo.js
index 6773278..cde2755 100644
--- a/src/ldo.js
+++ b/src/ldo.js
@@ -532,7 +532,7 @@ const f_parser = function(L, p) {
let c = p.z.getc(); /* read first character */
if (String.fromCharCode(c) === lua.LUA_SIGNATURE.charAt(0)) {
checkmode(L, p.mode, "binary");
- cl = new BytecodeParser(p.z.buffer).luaU_undump(L);
+ cl = new BytecodeParser(L, p.z.buffer);
} else {
checkmode(L, p.mode, "text");
cl = lparser.luaY_parser(L, p.z, p.buff, p.dyd, p.name, c);
diff --git a/src/lobject.js b/src/lobject.js
index 3d9edb0..92dd560 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -124,14 +124,15 @@ class Table extends TValue {
static keyValue(key) {
// Those lua values are used by value, others by reference
- if (key instanceof TValue
- && [CT.LUA_TNIL,
+ if (key instanceof TValue) {
+ if ([CT.LUA_TNIL,
CT.LUA_TBOOLEAN,
CT.LUA_TSTRING,
- CT.LUA_TSHRSTR,
- CT.LUA_TLNGSTR,
CT.LUA_TNUMINT].indexOf(key.type) > -1) {
- key = key.value;
+ key = key.value;
+ } else if ([CT.LUA_TSHRSTR, CT.LUA_TLNGSTR].indexOf(key.type) > -1) {
+ key = key.value.map(e => `${e}|`).join('');
+ }
}
return key;
diff --git a/src/lundump.js b/src/lundump.js
index aa66584..d215c60 100644
--- a/src/lundump.js
+++ b/src/lundump.js
@@ -15,7 +15,8 @@ const LUAI_MAXSHORTLEN = 40;
class BytecodeParser {
- constructor(dataView) {
+ constructor(L, dataView) {
+ this.L = L;
this.intSize = 4;
this.size_tSize = 8;
this.instructionSize = 4;
@@ -69,7 +70,7 @@ class BytecodeParser {
return number;
}
- readString(n) {
+ read8bitString(n) {
let size = typeof n !== 'undefined' ? n : this.readByte() - 1;
if (size === 0xFF) // TODO: test
@@ -79,7 +80,7 @@ class BytecodeParser {
return null;
}
- let string = new Uint8Array();
+ let string = [];//new Uint8Array();
for (let i = 0; i < size; i++)
string.push(this.readByte());
@@ -87,6 +88,24 @@ class BytecodeParser {
return string;
}
+ readString(n) {
+ let size = typeof n !== 'undefined' ? n : this.readByte() - 1;
+
+ if (size === 0xFF) // TODO: test
+ this.offset += this.size_tSize;
+
+ if (size === 0) {
+ return null;
+ }
+
+ let string = "";
+
+ for (let i = 0; i < size; i++)
+ string += String.fromCharCode(this.readByte());
+
+ return string;
+ }
+
/* creates a mask with 'n' 1 bits at position 'p' */
static MASK1(n, p) {
return ((~((~0)<<(n)))<<(p));
@@ -158,7 +177,7 @@ class BytecodeParser {
break;
case constant_types.LUA_TSHRSTR:
case constant_types.LUA_TLNGSTR:
- f.k.push(new TValue(constant_types.LUA_TLNGSTR, this.readString()));
+ f.k.push(this.L.l_G.intern(this.read8bitString()));
break;
default:
throw new Error(`unrecognized constant '${t}'`);
@@ -238,13 +257,13 @@ class BytecodeParser {
}
- luaU_undump(L) {
+ luaU_undump() {
this.checkHeader();
- let cl = new LClosure(L, this.readByte());
+ let cl = new LClosure(this.L, this.readByte());
- L.stack[L.top] = cl;
- L.top++;
+ this.L.stack[this.L.top] = cl;
+ this.L.top++;
cl.p = new Proto();
diff --git a/src/lvm.js b/src/lvm.js
index 54d34e3..3cf3fb6 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -768,9 +768,22 @@ const luaV_equalobj = function(L, t1, t2) {
case CT.LUA_TNUMFLT:
case CT.LUA_TBOOLEAN:
case CT.LUA_TLCF:
- case CT.LUA_TSHRSTR:
- case CT.LUA_TLNGSTR:
return t1.value === t2.value ? 1 : 0;
+ case CT.LUA_TSHRSTR:
+ case CT.LUA_TLNGSTR: {
+ let l1 = t1.value.length;
+ let l2 = t2.value.length;
+
+ if (l1 !== l2) return 0;
+
+ let i;
+ for (i = 0; i < l1; i++) {
+ if (t1.value[i] !== t2.value[i])
+ return 0;
+ }
+
+ return 1;
+ }
case CT.LUA_TLIGHTUSERDATA:
case CT.LUA_TUSERDATA:
case CT.LUA_TTABLE:
@@ -843,7 +856,8 @@ const luaV_tointeger = function(obj, mode) {
} else if (obj.ttisinteger()) {
return obj.value|0;
} else if (obj.ttisstring()) {
- return luaV_tointeger(new TValue(CT.LUA_TNUMFLT, parseFloat(obj.value)), mode); // TODO: luaO_str2num
+ let str = String.fromCharCode(...obj.value);
+ return luaV_tointeger(new TValue(CT.LUA_TNUMFLT, parseFloat(str)), mode); // TODO: luaO_str2num
}
return false;
@@ -872,7 +886,7 @@ const LTnum = function(l, r) {
} else {
if (r.ttisfloat())
return l.value < r.value ? 1 : 0;
- else if (isNan(l.value))
+ else if (isNaN(l.value))
return 0;
else
return !LEintfloat(r.value, l.value);
@@ -888,7 +902,7 @@ const LEnum = function(l, r) {
} else {
if (r.ttisfloat())
return l.value <= r.value ? 1 : 0;
- else if (isNan(l.value))
+ else if (isNaN(l.value))
return false;
else
return !LTintfloat(r.value, l.value);
@@ -907,7 +921,9 @@ const LTintfloat = function(l, r) {
const l_strcmp = function(ls, rs) {
// TODO: lvm.c:248 static int l_strcmp (const TString *ls, const TString *rs)
- return ls.value === rs.value ? 0 : (ls.value < rs.value ? -1 : 1);
+ ls = String.fromCharCode(...ls.value);
+ rs = String.fromCharCode(...rs.value);
+ return ls === rs ? 0 : (ls < rs ? -1 : 1);
};
/*
@@ -924,7 +940,7 @@ const luaV_objlen = function(L, ra, rb) {
}
case CT.LUA_TSHRSTR:
case CT.LUA_TLNGSTR:
- L.stack[ra] = new TValue(CT.LUA_TNUMINT, rb.value.length); // TODO: 8-byte clean string
+ L.stack[ra] = new TValue(CT.LUA_TNUMINT, rb.value.length);
return;
default: {
tm = ltm.luaT_gettmbyobj(L, rb, ltm.TMS.TM_LEN);
@@ -940,9 +956,10 @@ const luaV_objlen = function(L, ra, rb) {
const tostring = function(L, i) {
let o = L.stack[i];
let str = `${o.value}`;
+ str = lua.to_luastring(str, str.length);
if (o.ttisstring() || (o.ttisnumber() && !isNaN(str))) {
- L.stack[i] = new TValue(CT.LUA_TLNGSTR, str);
+ L.stack[i] = L.l_G.intern(str);
return true;
}
@@ -964,7 +981,7 @@ const luaV_concat = function(L, total) {
if (!(v.ttisstring() || v.ttisnumber()) || !tostring(L, top - 2)) // TODO: tostring
ltm.luaT_trybinTM(L, v, v2, top-2, ltm.TMS.TM_CONCAT);
else if (v2.ttisstring() && v2.value.length === 0)
- tostring(L, top - 2)
+ tostring(L, top - 2);
else if (v.ttisstring() && v.value.length === 0)
L.stack[top - 2] = L.stack[top - 1];
else {
@@ -977,12 +994,12 @@ const luaV_concat = function(L, total) {
tl += l;
}
- let ts = new TValue(CT.LUA_TLNGSTR, "");
+ let ts = [];
for (let i = n; i > 0; i--) {
- ts.value = `${ts.value}${L.stack[top - i].value}`;
+ ts = ts.concat(L.stack[top - i].value);
}
- L.stack[top - n] = ts;
+ L.stack[top - n] = L.l_G.intern(ts);
}
total -= n - 1; /* got 'n' strings to create 1 new */
L.top -= n - 1; /* popped 'n' strings and pushed one */
@@ -1074,7 +1091,7 @@ const luaV_finishset = function(L, t, key, val, slot, recur) {
}
settable(L, tm, key, val, recur + 1);
-}
+};
module.exports.LEintfloat = LEintfloat;
diff --git a/tests/tests.js b/tests/tests.js
index d4173c3..32f6563 100644
--- a/tests/tests.js
+++ b/tests/tests.js
@@ -35,8 +35,7 @@ const getState = function(luaCode) {
let L = lauxlib.luaL_newstate();
- let p = new BytecodeParser(dv);
- let cl = p.luaU_undump(L);
+ let p = new BytecodeParser(L, dv).luaU_undump();
return L;
};