5.11 Recursive module loading

Overview

As demonstrated in the preceding section, the process of loading modules recursively is a complex task. The result of this recursive module loading process is a module graph, which holds parsed modules. All the dependencies of these modules are loaded upon the completion of this phase. Going further, let's explore a segment of code within the JavaScript runtime's load_main_module() function that holds significance for the recursive module loading process:

let mut load =
      ModuleMap::load_main(module_map_rc.clone(), &specifier).await?;

while let Some(load_result) = load.next().await {
  let (request, info) = load_result?;
  let scope = &mut self.handle_scope(isolate);
  load.register_and_recurse(scope, &request, info).map_err(
    |e| match e {
      ModuleError::Exception(exception) => {
        let exception = v8::Local::new(scope, exception);
        exception_to_err_result::<()>(scope, exception, false).unwrap_err()
      }
      ModuleError::Other(error) => error,
    },
  )?;
}

Here are the required procedures in this section:

  1. Establishing a Recursive Module Loader: To begin, we must construct a module loader that works in a loop, repeatedly calling itself. This loader takes various arguments, including the module loader itself.

  2. Getting Modules Ready: Next, we need to make sure our modules are ready for use. This involves two main actions:

    • Fetching: We retrieve the necessary modules, ensuring they are available for the program.

    • Inserting into Graph: We organize these modules within a graphical structure, creating connections between them based on their dependencies.

  3. Iterating Through Modules and Registration: After the preparation phase, we proceed to loop through all the modules. This process is also referred to as instantiation or registration. During this loop, each module is formally registered, allowing it to be utilized as part of the program's execution.

The primary function is called "register_and_recurse," and it's quite intricate in its workings:

  • It performs a recursive journey through all the modules using a graph-like structure of data.

  • During this process, it covers all the distinct modules present.

  • The function retrieves all the necessary imports that a module needs.

  • This action involves further recursive exploration of all the imports.

From the long function above, we can look at two important points:

Get the imports present in a module

Add imports to the list and visit them if not already visited.

--

In the next section, we'll explore the process of building module graphs, which will reveal the interconnectedness of modules. We'll also examine the specific module graph related to our example, providing a detailed visual representation of its structure and relationships.

Last updated