【发布时间】:2020-04-16 23:07:12
【问题描述】:
我已经编写了一个脚本来热重载requireed 模块。但是它只能部分工作......
我完成这项任务的方法非常简单。我更改了 Lua 的 require 函数,以便它记住与时间戳及其文件路径一起加载的模块。然后我使用一个 shell 脚本来观察这些文件的修改时间,并在它们发生变化时重新要求它们。我只是dofile(),如果没有发生错误,我将返回值并(重新)分配给package.loaded[<module>]。到目前为止一切顺利。
当我使用全局变量时,所有这些都很完美,例如foo = require "foobar",但是当我使用本地分配时,比如local foo = require "foobar",我的热交换失败(部分)!
似乎包被按预期换出,但是局部变量(来自上面的赋值)仍然保存旧引用或它在第一次调用 require 时获得的旧值。
我的想法是使用 Lua 的 debug.getlocal 和 debug.setlocal 函数来查找所有局部变量(堆栈中的上值)并更新它们的值/引用。
但是我得到一个错误,我想要更改的上值是“超出范围”......有人可以帮我吗?我应该怎么做或如何解决这个问题?
The complete code is over at Gist,但是重要/相关的 sn-ps 是...
- 第 27 行的函数
local_upvalues(),它收集所有可用的上值
local function local_upvalues()
local upvalues = {}
local failures = 0
local thread = 0
while true do
thread = thread + 1
local index = 0
while true do
index = index + 1
local success, name, value = pcall(debug.getlocal, thread, index)
if success and name ~= nil then
table.insert(upvalues, {
name = name,
value = value,
thread = thread,
index = index
})
else
if index == 1 then failures = failures + 1 end
break
end
end
if failures > 1 then break end
end
return upvalues
end
- 和第 89 行的
debug.setlocal(),它尝试更新包含废弃模块引用的上值
-- update module references of local upvalues
for count, upvalue in ipairs(local_upvalues()) do
if upvalue.value == package.loaded[resource] then
-- print(upvalue.name, "updated from", upvalue.value, "to", message)
table.foreach(debug.getinfo(1), print)
print(upvalue.name, upvalue.thread, upvalue.index)
debug.setlocal(upvalue.thread, upvalue.index, message)
end
end
package.loaded[resource] = message -- update the absolete module
【问题讨论】:
标签: lua hot-reload upvalue