fix(javascript): match unchanged module exports across application versions (#5196)

* fix(javascript): match unchanged module exports across application versions

An export binding's identity is keyed within its whole application root (container_sha256), so it changed whenever any sibling file changed, and no match tier paired export nodes: every export of an unchanged file was reported removed and added, and its module fell to unknown. The exact module-source-digest tier now also pairs an export binding by its own file's bytes (identity artifact_sha256) and exported name, as it already pairs a source module by source_sha256. Exports of edited files stay unmatched.

* style(javascript): format the version-matching export test

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
This commit is contained in:
rodricksz4h5
2026-10-22 23:55:43 +05:30
committed by GitHub
parent 26573c3aa4
commit 5d3ae66e63
2 changed files with 109 additions and 0 deletions
@@ -200,6 +200,18 @@ const contentDigestKey = (node: ApplicationNode): string | null =>
const moduleSourceDigestKey = (node: ApplicationNode): string | null => {
if (node.kind !== "javascript-module") return null;
// An export binding is identified within its whole application root, so its
// id changes with any sibling file. Its own file's bytes and exported name
// identify it across versions, as `source_sha256` does a source module.
if (
node.identity.strategy === "artifact-local-key" &&
node.identity.namespace === "module-export"
) {
const name = uniqueStringProperty(node, "exported_name");
return name === null
? null
: `module-export\0${node.identity.artifact_sha256}\0${name}`;
}
const value = uniqueStringProperty(node, "source_sha256");
return value === null ? null : `module-source\0${node.kind}\0${value}`;
};