diff --git a/internal/shop.cm b/internal/shop.cm index b24bcac6..018605bf 100644 --- a/internal/shop.cm +++ b/internal/shop.cm @@ -329,6 +329,7 @@ Shop.extract_commit_hash = function(pkg, response) { return null } +var dylib_visited = {} var open_dls = {} // Default capabilities injected into scripts @@ -519,6 +520,46 @@ function get_lib_path(pkg) { return global_shop_path + '/lib/' + lib_name + dylib_ext } +// Open a package's dynamic library and all its dependencies +Shop.open_package_dylib = function(pkg) { + if (pkg == 'core' || !pkg) return + if (dylib_visited[pkg]) return + dylib_visited[pkg] = true + + var link_target = link.get_target(pkg) + var resolved_pkg = link_target ? link_target : pkg + + var pkg_dir; + if (resolved_pkg.startsWith('/')) { + pkg_dir = resolved_pkg + } else { + pkg_dir = get_packages_dir() + '/' + safe_package_path(resolved_pkg) + } + + var toml_path = pkg_dir + '/cell.toml' + if (fd.is_file(toml_path)) { + try { + var content = text(fd.slurp(toml_path)) + var cfg = toml.decode(content) + if (cfg.dependencies) { + for (var alias in cfg.dependencies) { + var dep_pkg = cfg.dependencies[alias] + Shop.open_package_dylib(dep_pkg) + } + } + } catch (e) { + // Ignore errors reading cell.toml + } + } + + var dl_path = get_lib_path(pkg) + if (fd.is_file(dl_path)) { + if (!open_dls[dl_path]) { + open_dls[dl_path] = os.dylib_open(dl_path) + } + } +} + // Resolve a C symbol by searching: // 1. If package_context is null, only check core internal symbols // 2. Otherwise: own package (internal then dylib) -> other packages (internal then dylib) -> core (internal only) @@ -541,16 +582,14 @@ function get_lib_path(pkg) { } } + Shop.open_package_dylib(explicit.package) var dl_path = get_lib_path(explicit.package) - if (fd.is_file(dl_path)) { - if (!open_dls[dl_path]) open_dls[dl_path] = os.dylib_open(dl_path) - if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) { - return { - symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) }, - scope: SCOPE_PACKAGE, - package: explicit.package, - path: sym - } + if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) { + return { + symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) }, + scope: SCOPE_PACKAGE, + package: explicit.package, + path: sym } } } @@ -578,16 +617,14 @@ function get_lib_path(pkg) { } } + Shop.open_package_dylib(package_context) var dl_path = get_lib_path(package_context) - if (fd.is_file(dl_path)) { - if (!open_dls[dl_path]) open_dls[dl_path] = os.dylib_open(dl_path) - if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) { - return { - symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) }, - scope: SCOPE_LOCAL, - path: sym - } + if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) { + return { + symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) }, + scope: SCOPE_LOCAL, + path: sym } } @@ -613,16 +650,14 @@ function get_lib_path(pkg) { } // Then check dylib + Shop.open_package_dylib(canon_pkg) var dl_path = get_lib_path(canon_pkg) - if (fd.is_file(dl_path)) { - if (!open_dls[dl_path]) open_dls[dl_path] = os.dylib_open(dl_path) - if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) { - return { - symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) }, - scope: SCOPE_PACKAGE, - package: canon_pkg, - path: sym - } + if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) { + return { + symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) }, + scope: SCOPE_PACKAGE, + package: canon_pkg, + path: sym } } } diff --git a/source/cell.h b/source/cell.h index c40a9081..625c1ef0 100644 --- a/source/cell.h +++ b/source/cell.h @@ -11,8 +11,8 @@ extern "C" { // blob fns JSValue js_blob_use(JSContext *js); JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes); -void *js_get_blob_data(JSContext *js, size_t *size, JSValue v); -void *js_get_blob_data_bits(JSContext *js, size_t *bits, JSValue v); +void *js_get_blob_data(JSContext *js, size_t *size, JSValue v); // bytes +void *js_get_blob_data_bits(JSContext *js, size_t *bits, JSValue v); // bits int js_is_blob(JSContext *js, JSValue v); double cell_random();