Jackmcbarn has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/178760

Change subject: Allow non-hacky modification of loadData tables
......................................................................

Allow non-hacky modification of loadData tables

It's always been possible to use rawset() to modify loadData tables. This
adds a non-hacky way to do so. With this method, iteration works normally,
and there's still no cross-invoke leakage.

Change-Id: Ic647be3e00b9c80a54cecff2c87b072b84c36e59
---
M engines/LuaCommon/lualib/mw.lua
M tests/engines/LuaCommon/CommonTests.lua
2 files changed, 20 insertions(+), 35 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Scribunto 
refs/changes/60/178760/1

diff --git a/engines/LuaCommon/lualib/mw.lua b/engines/LuaCommon/lualib/mw.lua
index f6a2aee..9e8a9d7 100644
--- a/engines/LuaCommon/lualib/mw.lua
+++ b/engines/LuaCommon/lualib/mw.lua
@@ -628,18 +628,18 @@
 end
 
 ---
--- Wrapper for mw.loadData. This creates the read-only dummy table for
+-- Wrapper for mw.loadData. This creates the dummy table for
 -- accessing the real data.
 --
 -- @param data table Data to access
 -- @param seen table|nil Table of already-seen tables.
 -- @return table
 local function dataWrapper( data, seen )
-       local t = {}
+       local t, dummyValue, changes = {}, {}
        seen = seen or { [data] = t }
 
        local function pairsfunc( s, k )
-               k = next( data, k )
+               k = next( changes or data, k )
                if k ~= nil then
                        return k, t[k]
                end
@@ -648,7 +648,7 @@
 
        local function ipairsfunc( s, i )
                i = i + 1
-               if data[i] ~= nil then
+               if t[i] ~= nil then
                        return i, t[i]
                end
                return -- no nil to match default ipairs()
@@ -657,6 +657,9 @@
        local mt = {
                __index = function ( tt, k )
                        assert( t == tt )
+                       if changes and changes[k] ~= dummyValue then
+                               return changes[k]
+                       end
                        local v = data[k]
                        if type( v ) == 'table' then
                                seen[v] = seen[v] or dataWrapper( v, seen )
@@ -664,8 +667,15 @@
                        end
                        return v
                end,
-               __newindex = function ( t, k, v )
-                       error( "table from mw.loadData is read-only", 2 )
+               __newindex = function ( tt, k, v )
+                       assert( t == tt )
+                       if not changes then
+                               changes = {}
+                               for k in pairs( data ) do
+                                       changes[k] = dummyValue
+                               end
+                       end
+                       changes[k] = v
                end,
                __pairs = function ( tt )
                        assert( t == tt )
diff --git a/tests/engines/LuaCommon/CommonTests.lua 
b/tests/engines/LuaCommon/CommonTests.lua
index fef18ed..acb9a80 100644
--- a/tests/engines/LuaCommon/CommonTests.lua
+++ b/tests/engines/LuaCommon/CommonTests.lua
@@ -177,17 +177,6 @@
        return d
 end
 
-function test.loadData.set( v, ... )
-       local d = mw.loadData( 'Module:CommonTests-data' )
-       local n = select( '#', ... )
-       for i = 1, n - 1 do
-               local k = select( i, ... )
-               d = d[k]
-       end
-       d[select( n, ... )] = v
-       return d[select( n, ... )]
-end
-
 function test.loadData.recursion()
        local d = mw.loadData( 'Module:CommonTests-data' )
        return d == d.t, d.t == d.t.t, d.table2 == d.table
@@ -208,12 +197,10 @@
        return 'setmetatable succeeded'
 end
 
-function test.loadData.rawset()
-       -- We can't easily prevent rawset (and it's not worth trying to redefine
-       -- it), but we can make sure it doesn't affect other instances of the 
data
+function test.loadData.set()
        local d1 = mw.loadData( 'Module:CommonTests-data' )
        local d2 = mw.loadData( 'Module:CommonTests-data' )
-       rawset( d1, 'str', 'ugh' )
+       d1.str = 'ugh'
        local d3 = mw.loadData( 'Module:CommonTests-data' )
        return d1.str, d2.str, d3.str
 end
@@ -368,20 +355,8 @@
          func = test.loadData.setmetatable,
          expect = "cannot change a protected metatable"
        },
-       { name = 'mw.loadData, setter (1)',
-         func = test.loadData.set, args = { 'ugh', 'str' },
-         expect = "table from mw.loadData is read-only",
-       },
-       { name = 'mw.loadData, setter (2)',
-         func = test.loadData.set, args = { 'ugh', 'table', 2 },
-         expect = "table from mw.loadData is read-only",
-       },
-       { name = 'mw.loadData, setter (3)',
-         func = test.loadData.set, args = { 'ugh', 't' },
-         expect = "table from mw.loadData is read-only",
-       },
-       { name = 'mw.loadData, rawset',
-         func = test.loadData.rawset,
+       { name = 'mw.loadData, set',
+         func = test.loadData.set,
          expect = { 'ugh', 'foo bar', 'foo bar' },
        },
 } )

-- 
To view, visit https://gerrit.wikimedia.org/r/178760
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic647be3e00b9c80a54cecff2c87b072b84c36e59
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Scribunto
Gerrit-Branch: master
Gerrit-Owner: Jackmcbarn <jackmcb...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to