Skip to content

Conversation

@fireairforce
Copy link
Contributor

@fireairforce fireairforce commented Dec 29, 2025

Summary

compitable with: vercel/next.js#81877 and vercel/next.js#82760

Test Plan

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @fireairforce, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the core JavaScript runtime within the pack-core library. The primary goal is to enhance the module registration and factory management system, moving towards a more modern and performant approach using Map objects and a flexible array-based format for module definitions. These changes improve compatibility, support advanced features like scope hoisting, and refine error handling and debugging capabilities within the runtime.

Highlights

  • Module Factory Storage Transition: The internal storage mechanism for module factories has been upgraded from plain JavaScript objects to Map objects, enhancing performance and API consistency for module management.
  • Flexible Module Registration Format: A new array-based format for CompressedModuleFactories and ChunkRegistration has been introduced, enabling more flexible and efficient module registration, particularly beneficial for scope hoisting.
  • Enhanced Export Handling: The ESM export (esm and esmExport) and dynamic export mechanisms have been refactored to utilize a new EsmBindings array format, which now supports direct value binding and improves the clarity of export definitions.
  • Improved Error Reporting: Error handling for unavailable module factories has been refined to throw more specific and informative error messages, aiding in debugging.
  • Optimized Runtime Utilities: New utility functions, installCompressedModuleFactories and applyModuleFactoryName, have been added to streamline module factory installation and improve debugging stack traces by providing meaningful names to factory functions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@fireairforce fireairforce changed the title feat(pack): library runtime code compitable with Array [WIP]feat(pack): library runtime code compitable with Array Dec 29, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the module factory registration to use a more compact array format, which is a good optimization for bundle size. The changes are extensive, touching both Rust code generation and the TypeScript runtime. However, I've identified several critical issues. The registerChunk function in build-base.ts appears to have a bug where it doesn't register modules when runtime parameters are present. The TypeScript type for ChunkRegistration is invalid. There's also a regression where error checks for cached failed modules have been removed, which could lead to silent failures. Lastly, the snapshot test for the library build runtime seems to be broken or outdated, as it doesn't reflect the new array format for module factories, indicating the changes might not be properly tested.

Comment on lines +88 to 97
if (registration.length === 3) {
runtimeParams = registration[2] as RuntimeParams;
} else {
runtimeParams = undefined;
installCompressedModuleFactories(
registration as CompressedModuleFactories,
/* offset= */ 1,
moduleFactories,
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The logic in registerChunk is flawed. When registration.length === 3, it correctly extracts runtimeParams but fails to process registration[1], which contains the module factories. This will prevent any modules from being registered for chunks that have runtime parameters.

  if (registration.length === 3) {
    runtimeParams = registration[2] as RuntimeParams;
    installCompressedModuleFactories(
      registration[1] as CompressedModuleFactories,
      /* offset= */ 0,
      moduleFactories,
    );
  } else {
    runtimeParams = undefined;
    installCompressedModuleFactories(
      registration as CompressedModuleFactories,
      /* offset= */ 1,
      moduleFactories,
    );
  }

Comment on lines +678 to 689
function registerChunk(registration) {
const chunkPath = getPathFromScript(registration[0]);
let runtimeParams;
// When bootstrapping we are passed a single runtimeParams object so we can distinguish purely based on length
if (registration.length === 2) {
runtimeParams = registration[1];
} else {
runtimeParams = undefined;
installCompressedModuleFactories(registration, /* offset= */ 1, moduleFactories);
}
return BACKEND.registerChunk(chunkPath, runtimeParams);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This new implementation of registerChunk seems incorrect. It checks registration.length === 2 to identify bootstrap params, but the data passed at the end of this file is an array of length 3 (["main.js", {modules...}, {params...}]). This will cause the else branch to be taken, which calls installCompressedModuleFactories. This function expects a flat array of modules, but it will receive ["main.js", {modules...}, {params...}], which will cause a "malformed chunk format" error at runtime.

Furthermore, the module data at the end of the file is still in the old object format, not the new array format that chunk.rs is supposed to generate. This indicates the snapshot is not correctly updated to test the changes in this PR.

Comment on lines 43 to 46
type ChunkRegistration = [
chunkPath: ChunkScript,
chunkModules: CompressedModuleFactories,
params: RuntimeParams | undefined,
...(CompressedModuleFactories | [RuntimeParams]),
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The type definition for ChunkRegistration appears to be invalid TypeScript. The spread operator ... cannot be applied to a union of an array type and a tuple type like CompressedModuleFactories | [RuntimeParams]. A simpler tuple type would be more appropriate and correct, reflecting that params is optional.

Suggested change
type ChunkRegistration = [
chunkPath: ChunkScript,
chunkModules: CompressedModuleFactories,
params: RuntimeParams | undefined,
...(CompressedModuleFactories | [RuntimeParams]),
];
type ChunkRegistration = [
chunkPath: ChunkScript,
chunkModules: CompressedModuleFactories,
params?: RuntimeParams,
];

if (module.error) throw module.error;

// any ES module has to have `module.namespaceObject` defined.
if (module.namespaceObject) return module.namespaceObject;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The removal of if (module.error) throw module.error; could lead to suppressed errors. If a module fails to instantiate, it is cached with an error property. Subsequent imports of this module will retrieve it from the cache but will no longer re-throw the error, potentially leading to silent failures or unexpected behavior. It's recommended to re-introduce this check.

Suggested change
if (module.namespaceObject) return module.namespaceObject;
if (module.error) throw module.error;

if (module.error) throw module.error;
return module.exports;
return getOrInstantiateModuleFromParent(id, this.m).exports;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to esmImport, removing the error check if (module.error) throw module.error; can lead to suppressed errors for failed module instantiations that are retrieved from the cache.

  const module = getOrInstantiateModuleFromParent(id, this.m);
  if (module.error) throw module.error;
  return module.exports;

Comment on lines +165 to +169
let code_key = item_code
.source_code()
.to_str()
.map_err(|e| anyhow::anyhow!("Failed to convert code to string: {}", e))?
.to_string();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using the full source code of a module as a HashMap key can be inefficient, especially if the code is large. This involves string conversion and hashing the entire content on each insertion. Consider using a more efficient key, such as a hash of the code content, if performance at build time becomes a concern.

@xusd320 xusd320 force-pushed the next branch 2 times, most recently from f77808c to 567e5ae Compare January 7, 2026 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants