Skip to content
Snippets Groups Projects
Commit d688c50d authored by Alexander Turenko's avatar Alexander Turenko Committed by Igor Munkin
Browse files

lua: allow to refuse caching in package.loaded

Use case: an override module is designed to replace a built-in module
only when the module is required from an application, not from the
platform itself.

Now it is possible:

```lua
-- override/fio.lua
local loaders = require('internal.loaders')

if loaders.initializing then
    loaders.no_package_loaded.fio = true
    return loaders.builtin.fio
end

return {
    whoami = 'override.fio',
}
```

Follows up #7774

NO_DOC=Planned as an internal API. See the previous commit.
NO_CHANGELOG=see NO_DOC
parent 01a4af8d
No related branches found
No related tags found
No related merge requests found
......@@ -373,6 +373,27 @@ rawset(package, "search", search)
rawset(package, "searchroot", searchroot)
rawset(package, "setsearchroot", setsearchroot)
local no_package_loaded = {}
local raw_require = require
-- Allow an override module to refuse caching in package.loaded.
--
-- It may be useful to return a built-in module into the platform,
-- but the override module into application's code.
_G.require = function(modname)
if no_package_loaded[modname] then
no_package_loaded[modname] = nil
package.loaded[modname] = nil
end
-- NB: This call is a tail call and it is important to some
-- extent. At least luajit's test suites expect certain error
-- messages from `require()` calls and from the `-l` option.
--
-- A non-tail call changes the filename at the beginning of
-- the error message.
return raw_require(modname)
end
return {
ROCKS_LIB_PATH = ROCKS_LIB_PATH,
ROCKS_LUA_PATH = ROCKS_LUA_PATH,
......@@ -386,4 +407,15 @@ return {
-- It is `true` during tarantool initialization, but once all
-- the built-in modules are ready, will be set to `nil`.
initializing = true,
raw_require = raw_require,
-- Add a module name here to ignore package.loaded[modname] at
-- next require(). The flag is dropped at the require() call.
--
-- This is intended to be used from inside a module to refuse
-- caching in package.loaded. Any other usage has unspecified
-- behavior (just manipulate package.loaded directly if you
-- need it).
--
-- Usage: loaders.no_package_loaded[modname] = true
no_package_loaded = no_package_loaded,
}
......@@ -65,3 +65,26 @@ g.test_initializing = function(g)
local exp = expected_output('socket')
t.assert_equals(res, exp)
end
g.test_no_package_loaded = function()
local LOAD_LIMIT = 3
local LOAD_ATTEMPTS = LOAD_LIMIT + 1
local load_cnt = 0
local foo = {whoami = 'foo'}
package.preload.foo = function()
local loaders = require('internal.loaders')
load_cnt = load_cnt + 1
if load_cnt < LOAD_LIMIT then
loaders.no_package_loaded.foo = true
end
return foo
end
for _ = 1, LOAD_ATTEMPTS do
require('foo')
end
package.preload.foo = nil
t.assert_equals(load_cnt, LOAD_LIMIT)
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment