require
すでに編集されているモジュールをホットリロードするスクリプトを作成しました。部分的にしか機能しませんが...
このタスクに対する私のアプローチは非常に単純です。Lua のrequire
関数を変更して、ロードしたモジュールをタイムスタンプとそのファイル パスと共に記憶するようにしました。次に、シェル スクリプトを使用してこれらのファイルの変更時刻を監視し、変更された場合はそれらを再要求します。dofile()
エラーが発生しない場合は、戻り値を取得して (再) 割り当てますpackage.loaded[<module>]
。ここまでは順調ですね。
などのグローバル変数を使用すると、これらすべてが完全に機能しますfoo = require "foobar"
が、 のようなローカル割り当てを使用するlocal foo = require "foobar"
と、ホットスワッパーが (部分的に) 失敗します。
パッケージは意図したとおりにスワップ アウトされているようですが、ローカル変数 (上記の割り当てによる) は古い参照または require が初めて呼び出されたときに取得した古い値を保持しています。
私のアイデアは、Luadebug.getlocal
とdebug.setlocal
関数を使用してすべてのローカル変数 (スタック内の上位値) を見つけ、それらの値/参照を更新することでした。
しかし、変更したい上限値が「範囲外」であるというエラーが表示されます...誰か助けてくれませんか? どうすればよいですか、またはこれを回避するにはどうすればよいですか?
完全なコードは Gistにありますが、重要/関連するスニペットは...
local_upvalues()
利用可能なすべての上位値を収集する 27 行目の関数
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()
廃止されたモジュール参照を保持する upvalue を更新しようとしています。
-- 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