aboutsummaryrefslogtreecommitdiff
path: root/src/ltable.js
diff options
context:
space:
mode:
authordaurnimator <quae@daurnimator.com>2017-05-11 17:14:31 +1000
committerdaurnimator <quae@daurnimator.com>2017-05-11 17:22:36 +1000
commita9fe1ab76cb527d8bdafa3071f796b646aada17e (patch)
treee18d6f1eab3eb6ea3cbda9fc8e777d07039942f6 /src/ltable.js
parent6f93b0a3af9e64d3f69a2442af3c21b6fa794ed7 (diff)
downloadfengari-a9fe1ab76cb527d8bdafa3071f796b646aada17e.tar.gz
fengari-a9fe1ab76cb527d8bdafa3071f796b646aada17e.tar.bz2
fengari-a9fe1ab76cb527d8bdafa3071f796b646aada17e.zip
src/ltable.js: luaH_delete can't fully delete immediately as it might need dead keys for next()
Diffstat (limited to 'src/ltable.js')
-rw-r--r--src/ltable.js23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/ltable.js b/src/ltable.js
index b1f48e8..79c8215 100644
--- a/src/ltable.js
+++ b/src/ltable.js
@@ -34,10 +34,17 @@ class Table {
constructor(L) {
this.id = L.l_G.id_counter++;
this.strong = new Map();
+ this.dead_hashes = [];
this.metatable = null;
}
}
+const clean_dead_keys = function(t) {
+ for (let i=0; i<t.dead_hashes.length; i++) {
+ t.strong.delete(t.dead_hashes[i]);
+ }
+};
+
const luaH_new = function(L) {
return new Table(L);
};
@@ -69,6 +76,7 @@ const setgeneric = function(t, hash, key) {
if (v)
return v.value;
+ clean_dead_keys(t);
let tv = new lobject.TValue(CT.LUA_TNIL, null);
t.strong.set(hash, {
key: key,
@@ -81,7 +89,7 @@ const luaH_setint = function(t, key, value) {
assert(typeof key == "number" && (key|0) === key && value instanceof lobject.TValue);
let hash = key; /* table_hash known result */
if (value.ttisnil()) {
- t.strong.delete(hash);
+ delete_hash(t, hash);
return;
}
let v = t.strong.get(hash);
@@ -89,6 +97,7 @@ const luaH_setint = function(t, key, value) {
let tv = v.value;
tv.setfrom(value);
} else {
+ clean_dead_keys(t);
t.strong.set(hash, {
key: new lobject.TValue(CT.LUA_TNUMINT, key),
value: new lobject.TValue(value.type, value.value)
@@ -102,10 +111,20 @@ const luaH_set = function(t, key) {
return setgeneric(t, hash, new lobject.TValue(key.type, key.value));
};
+/* Can't remove from table immediately due to next() */
+const delete_hash = function(t, hash) {
+ let e = t.strong.get(hash);
+ if (e) {
+ e.key.setdeadvalue();
+ e.value = lobject.luaO_nilobject;
+ t.dead_hashes.push(hash);
+ }
+};
+
const luaH_delete = function(t, key) {
assert(key instanceof lobject.TValue);
let hash = table_hash(key);
- t.strong.delete(hash);
+ return delete_hash(t, hash);
};
/*