123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- --[[
- Lua 5.2/5.3 hotfix. Hot update functions and keep old data.
- Author: Jin Qing ( http://blog.csdn.net/jq0123 )
- --]]
- local M = {}
- local module_updater = require("hotfix.internal.module_updater")
- local functions_replacer = require("hotfix.internal.functions_replacer")
- -- Do not update and replace protected objects.
- local protected = {}
- -- To protect self.
- local function add_self_to_protect()
- M.add_protect{
- M,
- M.hotfix_module,
- M.log_error,
- M.log_info,
- M.log_debug,
- M.add_protect,
- M.remove_protect,
- module_updater,
- module_updater.log_debug,
- module_updater.update_loaded_module,
- functions_replacer,
- functions_replacer.replace_all,
- }
- end -- add_self_to_protect
- -- Hotfix module with new module object.
- -- Update package.loaded[module_name] and replace all functions.
- -- module_obj is the newly loaded module object.
- local function hotfix_module_with_obj(module_name, module_obj)
- assert("string" == type(module_name))
- add_self_to_protect()
- module_updater.log_debug = M.log_debug
- -- Step 1: Update package.loaded[module_name], recording updated functions.
- local updated_function_map = module_updater.update_loaded_module(
- module_name, protected, module_obj)
- -- Step 2: Replace old functions with new ones in module_obj, _G and registry.
- functions_replacer.replace_all(protected, updated_function_map, module_obj, module_name)
- end -- hotfix_module_with_obj()
- -- Hotfix module.
- -- Skip unloaded module.
- -- Usage: hotfix_module("mymodule.sub_module")
- -- Returns package.loaded[module_name].
- function M.hotfix_module(module_name)
- assert("string" == type(module_name))
- if not package.loaded[module_name] then
- M.log_debug("Skip unloaded module: " .. module_name)
- return package.loaded[module_name]
- end
- M.log_debug("Hot fix module: " .. module_name)
- local file_path = assert(package.searchpath(module_name, package.path))
- local fp = assert(io.open(file_path))
- local chunk = fp:read("*all")
- fp:close()
- -- Load chunk.
- local func = assert(load(chunk, '@'..file_path))
- local ok, obj = assert(pcall(func))
- if nil == obj then obj = true end -- obj may be false
- hotfix_module_with_obj(module_name, obj)
- return package.loaded[module_name]
- end
- -- User can set log functions. Default is no log.
- -- Like: require("hotfix").log_info = function(s) mylog:info(s) end
- function M.log_error(msg_str) end
- function M.log_info(msg_str) end
- function M.log_debug(msg_str) end
- -- Add objects to protect.
- -- Example: add_protect({table, math, print})
- function M.add_protect(object_array)
- for _, obj in pairs(object_array) do
- protected[obj] = true
- end
- end -- add_protect()
- -- Remove objects in protected set.
- -- Example: remove_protect({table, math, print})
- function M.remove_protect(object_array)
- for _, obj in pairs(object_array) do
- protected[obj] = nil
- end
- end -- remove_protect()
- return M
|