add hot reload to util

This commit is contained in:
2026-02-25 17:28:11 -06:00
parent 9c1141f408
commit 1cfd5b8133
3 changed files with 46 additions and 9 deletions

View File

@@ -703,6 +703,27 @@ static JSValue js_os_stack(JSContext *js, JSValue self, int argc, JSValue *argv)
JS_RETURN(arr.val);
}
static JSValue js_os_unstone(JSContext *js, JSValue self, int argc, JSValue *argv) {
if (argc < 1) return JS_NULL;
JSValue obj = argv[0];
if (mist_is_blob(obj)) {
JSBlob *bd = (JSBlob *)chase(obj);
bd->mist_hdr = objhdr_set_s(bd->mist_hdr, false);
return obj;
}
if (JS_IsArray(obj)) {
JSArray *arr = JS_VALUE_GET_ARRAY(obj);
arr->mist_hdr = objhdr_set_s(arr->mist_hdr, false);
return obj;
}
if (mist_is_gc_object(obj)) {
JSRecord *rec = JS_VALUE_GET_RECORD(obj);
rec->mist_hdr = objhdr_set_s(rec->mist_hdr, false);
return obj;
}
return JS_NULL;
}
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, platform, 0),
MIST_FUNC_DEF(os, arch, 0),
@@ -731,6 +752,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, getenv, 1),
MIST_FUNC_DEF(os, qbe, 1),
MIST_FUNC_DEF(os, stack, 1),
MIST_FUNC_DEF(os, unstone, 1),
};
JSValue js_core_internal_os_use(JSContext *js) {

View File

@@ -455,6 +455,7 @@ Shop.extract_commit_hash = function(pkg, response) {
var open_dls = {}
var package_dylibs = {} // pkg -> [{file, symbol, dylib}, ...]
var reload_hashes = {} // cache_key -> content hash for reload change detection
function open_dylib_cached(path) {
var handle = open_dls[path]
@@ -1982,19 +1983,27 @@ Shop.file_reload = function(file)
}
Shop.module_reload = function(path, package) {
if (!Shop.is_loaded(path,package)) return
if (!Shop.is_loaded(path, package)) return false
// Clear the module info cache for this path
var lookup_key = package ? package + ':' + path : ':' + path
module_info_cache[lookup_key] = null
var info = resolve_module_info(path, package)
if (!info) return false
// Invalidate package dylib cache so next resolve triggers rebuild
if (package) {
package_dylibs[package] = null
// Check if source actually changed
var mod_path = null
var source = null
var new_hash = null
if (info.mod_resolve) mod_path = info.mod_resolve.path
if (mod_path && fd.is_file(mod_path)) {
source = fd.slurp(mod_path)
new_hash = content_hash(stone(blob(text(source))))
if (reload_hashes[info.cache_key] == new_hash) return false
reload_hashes[info.cache_key] = new_hash
}
var info = resolve_module_info(path, package)
if (!info) return
// Clear caches
module_info_cache[lookup_key] = null
if (package) package_dylibs[package] = null
var cache_key = info.cache_key
var old = use_cache[cache_key]
@@ -2003,13 +2012,18 @@ Shop.module_reload = function(path, package) {
var newmod = get_module(path, package)
use_cache[cache_key] = newmod
// Smart update: unstone -> merge -> re-stone to preserve references
if (old && is_object(old) && is_object(newmod)) {
os.unstone(old)
arrfor(array(newmod), function(k) { old[k] = newmod[k] })
arrfor(array(old), function(k) {
if (!(k in newmod)) old[k] = null
})
stone(old)
use_cache[cache_key] = old
}
return true
}
function get_package_scripts(package)

View File

@@ -1,5 +1,6 @@
var shop = use('internal/shop')
return {
file_reload: shop.file_reload
file_reload: shop.file_reload,
reload: shop.module_reload
}