in plugins/experimental/wasm/lib/src/v8/v8.cc [342:463]
bool V8::link(std::string_view /*debug_name*/) {
assert(module_ != nullptr);
const auto import_types = module_.get()->imports();
std::vector<const wasm::Extern *> imports;
for (size_t i = 0; i < import_types.size(); i++) {
std::string_view module(import_types[i]->module().get(), import_types[i]->module().size());
std::string_view name(import_types[i]->name().get(), import_types[i]->name().size());
const auto *import_type = import_types[i]->type();
switch (import_type->kind()) {
case wasm::EXTERN_FUNC: {
auto it = host_functions_.find(std::string(module) + "." + std::string(name));
if (it == host_functions_.end()) {
fail(FailState::UnableToInitializeCode,
std::string("Failed to load Wasm module due to a missing import: ") +
std::string(module) + "." + std::string(name));
return false;
}
auto *func = it->second->callback_.get();
if (!equalValTypes(import_type->func()->params(), func->type()->params()) ||
!equalValTypes(import_type->func()->results(), func->type()->results())) {
fail(FailState::UnableToInitializeCode,
std::string("Failed to load Wasm module due to an import type mismatch: ") +
std::string(module) + "." + std::string(name) +
", want: " + printValTypes(import_type->func()->params()) + " -> " +
printValTypes(import_type->func()->results()) +
", but host exports: " + printValTypes(func->type()->params()) + " -> " +
printValTypes(func->type()->results()));
return false;
}
imports.push_back(func);
} break;
case wasm::EXTERN_GLOBAL: {
// TODO(PiotrSikora): add support when/if needed.
fail(FailState::UnableToInitializeCode,
"Failed to load Wasm module due to a missing import: " + std::string(module) + "." +
std::string(name));
return false;
} break;
case wasm::EXTERN_MEMORY: {
assert(memory_ == nullptr);
auto type = wasm::MemoryType::make(import_type->memory()->limits());
if (type == nullptr) {
return false;
}
memory_ = wasm::Memory::make(store_.get(), type.get());
if (memory_ == nullptr) {
return false;
}
imports.push_back(memory_.get());
} break;
case wasm::EXTERN_TABLE: {
assert(table_ == nullptr);
auto type =
wasm::TableType::make(wasm::ValType::make(import_type->table()->element()->kind()),
import_type->table()->limits());
if (type == nullptr) {
return false;
}
table_ = wasm::Table::make(store_.get(), type.get());
if (table_ == nullptr) {
return false;
}
imports.push_back(table_.get());
} break;
}
}
if (import_types.size() != imports.size()) {
return false;
}
instance_ = wasm::Instance::make(store_.get(), module_.get(), imports.data());
if (instance_ == nullptr) {
fail(FailState::UnableToInitializeCode, "Failed to create new Wasm instance");
return false;
}
const auto export_types = module_.get()->exports();
const auto exports = instance_.get()->exports();
assert(export_types.size() == exports.size());
for (size_t i = 0; i < export_types.size(); i++) {
std::string_view name(export_types[i]->name().get(), export_types[i]->name().size());
const auto *export_type = export_types[i]->type();
auto *export_item = exports[i].get();
assert(export_type->kind() == export_item->kind());
switch (export_type->kind()) {
case wasm::EXTERN_FUNC: {
assert(export_item->func() != nullptr);
module_functions_.insert_or_assign(std::string(name), export_item->func()->copy());
} break;
case wasm::EXTERN_GLOBAL: {
// TODO(PiotrSikora): add support when/if needed.
} break;
case wasm::EXTERN_MEMORY: {
assert(export_item->memory() != nullptr);
assert(memory_ == nullptr);
memory_ = exports[i]->memory()->copy();
if (memory_ == nullptr) {
return false;
}
} break;
case wasm::EXTERN_TABLE: {
// TODO(PiotrSikora): add support when/if needed.
} break;
}
}
return true;
}