| 14 | using namespace WasmVM; |
| 15 | |
| 16 | ModuleQueue::ModuleQueue( |
| 17 | std::filesystem::path main_module, |
| 18 | std::map<std::filesystem::path, ModuleInst>& module_insts, |
| 19 | std::vector<std::filesystem::path> extra_paths, |
| 20 | std::optional<std::filesystem::path> system_path, |
| 21 | bool check_parent, |
| 22 | bool validate |
| 23 | ) : module_insts(module_insts), system_path(system_path), check_parent(check_parent){ |
| 24 | |
| 25 | if(!std::filesystem::exists(main_module)){ |
| 26 | throw Exception::Exception("main module not found"); |
| 27 | } |
| 28 | |
| 29 | for(std::filesystem::path path : extra_paths){ |
| 30 | if(!std::filesystem::exists(path)){ |
| 31 | Exception::Warning(std::string("extra path '" + path.string() + "' not found")); |
| 32 | } |
| 33 | this->extra_paths.push_back(path); |
| 34 | } |
| 35 | |
| 36 | std::set<std::filesystem::path> ancestors; |
| 37 | std::set<std::filesystem::path> members; |
| 38 | std::function<void(std::filesystem::path)> find_deps = [&](std::filesystem::path file_path){ |
| 39 | Node node; |
| 40 | node.file_path = file_path; |
| 41 | std::ifstream istream(file_path, std::ios::binary | std::ios::in); |
| 42 | node.module = module_decode(istream); |
| 43 | if(validate){ |
| 44 | std::optional<Exception::Exception> err = module_validate(node.module); |
| 45 | if(err){ |
| 46 | throw err.value(); |
| 47 | } |
| 48 | } |
| 49 | istream.close(); |
| 50 | if(!node.module.imports.empty()){ |
| 51 | ancestors.emplace(file_path); |
| 52 | for(WasmImport& import : node.module.imports){ |
| 53 | if(module_insts.contains(import.module)){ |
| 54 | node.import_paths.emplace_back(import.module); |
| 55 | continue; |
| 56 | } |
| 57 | std::filesystem::path import_path = std::filesystem::canonical(resolve(import.module, file_path.parent_path())); |
| 58 | if(ancestors.contains(import_path)){ |
| 59 | throw Exception::Exception(std::string("invalid loop dependency of '") + import.module + "'"); |
| 60 | } |
| 61 | node.import_paths.emplace_back(import_path); |
| 62 | find_deps(import_path); |
| 63 | } |
| 64 | ancestors.erase(file_path); |
| 65 | } |
| 66 | if(!members.contains(file_path)){ |
| 67 | modules.emplace(node); |
| 68 | members.emplace(file_path); |
| 69 | } |
| 70 | }; |
| 71 | find_deps(std::filesystem::canonical(main_module)); |
| 72 | } |
| 73 | |