Commit 8b33d813 authored by meir's avatar meir
Browse files

Added support for Lua readonly tables.

The new feature can be turned off and on using the new `lua_enablereadonlytable` Lua API.
parent 81926254
...@@ -674,6 +674,8 @@ LUA_API void lua_rawset (lua_State *L, int idx) { ...@@ -674,6 +674,8 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
api_checknelems(L, 2); api_checknelems(L, 2);
t = index2adr(L, idx); t = index2adr(L, idx);
api_check(L, ttistable(t)); api_check(L, ttistable(t));
if (hvalue(t)->readonly)
luaG_runerror(L, "Attempt to modify a readonly table");
setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
luaC_barriert(L, hvalue(t), L->top-1); luaC_barriert(L, hvalue(t), L->top-1);
L->top -= 2; L->top -= 2;
...@@ -687,6 +689,8 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) { ...@@ -687,6 +689,8 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
api_checknelems(L, 1); api_checknelems(L, 1);
o = index2adr(L, idx); o = index2adr(L, idx);
api_check(L, ttistable(o)); api_check(L, ttistable(o));
if (hvalue(o)->readonly)
luaG_runerror(L, "Attempt to modify a readonly table");
setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
luaC_barriert(L, hvalue(o), L->top-1); luaC_barriert(L, hvalue(o), L->top-1);
L->top--; L->top--;
...@@ -709,6 +713,8 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { ...@@ -709,6 +713,8 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
} }
switch (ttype(obj)) { switch (ttype(obj)) {
case LUA_TTABLE: { case LUA_TTABLE: {
if (hvalue(obj)->readonly)
luaG_runerror(L, "Attempt to modify a readonly table");
hvalue(obj)->metatable = mt; hvalue(obj)->metatable = mt;
if (mt) if (mt)
luaC_objbarriert(L, hvalue(obj), mt); luaC_objbarriert(L, hvalue(obj), mt);
...@@ -1085,3 +1091,11 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { ...@@ -1085,3 +1091,11 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
return name; return name;
} }
LUA_API void lua_enablereadonlytable (lua_State *L, int objindex, int enabled) {
const TValue* o = index2adr(L, objindex);
api_check(L, ttistable(o));
Table* t = hvalue(o);
api_check(L, t != hvalue(registry(L)));
t->readonly = enabled;
}
...@@ -80,7 +80,6 @@ LUA_API int lua_gethookcount (lua_State *L) { ...@@ -80,7 +80,6 @@ LUA_API int lua_gethookcount (lua_State *L) {
return L->basehookcount; return L->basehookcount;
} }
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
int status; int status;
CallInfo *ci; CallInfo *ci;
......
...@@ -337,7 +337,8 @@ typedef struct Node { ...@@ -337,7 +337,8 @@ typedef struct Node {
typedef struct Table { typedef struct Table {
CommonHeader; CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */ lu_byte flags; /* 1<<p means tagmethod(p) is not present */
int readonly;
lu_byte lsizenode; /* log2 of size of `node' array */ lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable; struct Table *metatable;
TValue *array; /* array part */ TValue *array; /* array part */
......
...@@ -364,6 +364,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) { ...@@ -364,6 +364,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) {
t->array = NULL; t->array = NULL;
t->sizearray = 0; t->sizearray = 0;
t->lsizenode = 0; t->lsizenode = 0;
t->readonly = 0;
t->node = cast(Node *, dummynode); t->node = cast(Node *, dummynode);
setarrayvector(L, t, narray); setarrayvector(L, t, narray);
setnodevector(L, t, nhash); setnodevector(L, t, nhash);
......
...@@ -358,6 +358,8 @@ struct lua_Debug { ...@@ -358,6 +358,8 @@ struct lua_Debug {
int i_ci; /* active function */ int i_ci; /* active function */
}; };
LUA_API void lua_enablereadonlytable (lua_State *L, int index, int enabled);
/* }====================================================================== */ /* }====================================================================== */
......
...@@ -138,6 +138,8 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { ...@@ -138,6 +138,8 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
const TValue *tm; const TValue *tm;
if (ttistable(t)) { /* `t' is a table? */ if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t); Table *h = hvalue(t);
if (h->readonly)
luaG_runerror(L, "Attempt to modify a readonly table");
TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
if (!ttisnil(oldval) || /* result is no nil? */ if (!ttisnil(oldval) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment