diff --git a/shop.cm b/shop.cm index 6c3bf97a..39f49323 100644 --- a/shop.cm +++ b/shop.cm @@ -99,6 +99,36 @@ function get_import_package(name) { return null } +function split_explicit_package_import(path) +{ + if (!path) return null + var parts = path.split('/') + + if (parts.length < 2) return null + + var looks_explicit = path.startsWith('/') || (parts[0] && parts[0].includes('.')) + if (!looks_explicit) return null + + // Find the longest prefix that is an installed package + for (var i = parts.length - 1; i >= 1; i--) { + var pkg_candidate = parts.slice(0, i).join('/') + var mod_path = parts.slice(i).join('/') + if (!mod_path || mod_path.length == 0) continue + + var candidate_dir = get_packages_dir() + '/' + safe_package_path(pkg_candidate) + if (fd.is_file(candidate_dir + '/cell.toml')) + return {package: pkg_candidate, path: mod_path} + + if (package_in_shop(pkg_candidate)) + return {package: pkg_candidate, path: mod_path} + + if (Shop.resolve_package_info(pkg_candidate)) + return {package: pkg_candidate, path: mod_path} + } + + return null +} + function package_in_shop(package) { var lock = Shop.load_lock() return package in lock @@ -334,6 +364,15 @@ function resolve_mod_fn(path, pkg) { // return module info about where it was found function resolve_locator(path, ctx) { + var explicit = split_explicit_package_import(path) + if (explicit) { + var explicit_path = get_packages_dir() + '/' + safe_package_path(explicit.package) + '/' + explicit.path + if (fd.is_file(explicit_path)) { + var fn = resolve_mod_fn(explicit_path, explicit.package) + return {path: explicit_path, scope: SCOPE_PACKAGE, symbol: fn} + } + } + // 1. If no context, resolve from core only if (!ctx) { var core_dir = Shop.get_core_dir() @@ -410,6 +449,32 @@ function get_lib_path(pkg) { // Core is never loaded as a dynamic library via dlopen function resolve_c_symbol(path, package_context) { + var explicit = split_explicit_package_import(path) + if (explicit) { + var sym = make_c_symbol(explicit.package, explicit.path) + if (os.internal_exists(sym)) { + return { + symbol: function() { return os.load_internal(sym) }, + scope: SCOPE_PACKAGE, + package: explicit.package, + path: sym + } + } + + 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 no package context, only check core internal symbols if (!package_context) { var core_sym = `js_${path}_use`