Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Lua 5.2/5.3 hotfix. Hot update functions and keep old data.

License

NotificationsYou must be signed in to change notification settings

jinq0123/hotfix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lua 5.2/5.3 hotfix. Hot update functions and keep old data.

What does hotfix do

If we have a test.lua

localM= {}M.count=0functionM.func()M.count=M.count+1return"v1"endreturnM

Require test and call func(), then count will be 1.

> test = require("test")                              > test.func()                                         v1                                                    > test.count                                          1

Change "v1" to "v2" in test.lua, then hotfix module test and call func() again.The result shows that func() has been updated, but the count is kept.

> hotfix = require("hotfix.hotfix")                          > hotfix.hotfix_module("test")                        table: 0000000002752060                               > test.func()                                         v2                                                    > test.count                                          2

Install

UsingLuaRocks:

luarocks install hotfix

Or manually copylua/hotfix directory into your Lua module path.

Usage

localhotfix=require("hotfix.hotfix")hotfix.hotfix_module("mymodule.sub_module")

helper/hotfix_helper.luais an example to hotfix modified modules usinglfs.Please seehelper/README.md.

hotfix_module(module_name)

hotfix_module() usespackage.searchpath(module_name, package.path)to search the path of module.The module is reloaded and the returned value is updated topackage.loaded[module_name].If the returned value isnil, thenpackage.loaded[module_name] is assigned totrue.hotfix_module() returns the final value ofpackage.loaded[module_name].

hotfix_module() will skip unloaded module to avoid unexpected loading,and also to work around the issue of"Three dots module name will be nil".

Functons are updated to new ones but old upvalues are kept.Old tables are kept and new fields are inserted.All references to old functions are replaced to new ones.

The module may change any global variables if it wants to.See"Why not protect the global variables" below.

Local variable which is not referenced by_G is not updated.

-- test.lua: return { function func() return "old" end }localtest=require("test")-- referenced by _G.package.loaded["test"]localfunc=test.func-- is not upvalue nor is referenced by _G-- test.lua: return { function func() return "new" end }require("hotfix.hotfix").hotfix_module("test")test.func()-- "new"func()-- "old"

Why not protect the global variables

We can protect the global variables on loading in some ways, but there are other problems.

  • [1] uses a read onlyENV to load.
localenv= {}setmetatable(env, {__index=_G })load(chunk,check_name,'t',env)

But it can not stop indirect write.Global variables may be changed.In the following example,t is OK butmath.sin is changed.

Lua 5.3.2  Copyright (C) 1994-2015 Lua.org, PUC-Rio> math.sin(123)-0.45990349068959> do>> local _ENV = setmetatable({}, {__index = _G})>> t = 123>> math.sin = print>> end> tnil> math.sin(123)123
  • [2] uses a fakeENV to load and ignores all operations.In this case, we can not init new local variables.
localM= {}+locallog=require("log")-- Can not require!functionM.foo()+log.info("test")endreturnM

Another problem is the new function's_ENV is not the realENV.Following test will fail becauseset_global() has a protectedENV.

log("New upvalue which is a function set global...")run_test([[        local M = {}        function M.foo() return 12345 end        return M]],function()assert(nil==global_test)end,[[        local M = {}        local function set_global() global_test = 11111 end        function M.foo()            set_global()        end        return M]],function()assert(nil==test.foo())assert(11111==global_test)-- FAIL!global_test=nilend)

How to run test

Runmain.lua in test dir.main.lua will write atest.lua file and hotfix it.main.lua will write log tolog.txt.

D:\Jinq\Git\hotfix\test>..\..\..\tools\lua-5.3.2_Win64_bin\lua53Lua 5.3.2  Copyright (C) 1994-2015 Lua.org, PUC-Rio> require("main").run()main.lua:80: assertion failed!

Unexpected update

log function is changed fromprint to an empty function.The hotfix will replace allprint to an empty function which is totally unexpected.

localM= {}locallog=printfunctionM.foo()log("Old")endreturnM
localM= {}locallog=function()endfunctionM.foo()log("Old")endreturnM

hotfix.add_protect{print} can protectprint function from being replaced.But it also means thatlog can not be updated.

Known issue

Can not load utf8 with BOM.

hotfix.lua:210: file.lua:1: unexpected symbol near '<\239>'

Three dots module name will benil.

--- test.lua.-- @module testlocalmodule_name=...print(module_name)

require("test") will print "test", but hotfix which usesload() will print "nil".

Reference

localM= {}+functionM.foo()end-- Can not add M.foo().returnM

About

Lua 5.2/5.3 hotfix. Hot update functions and keep old data.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp