Skip to content

fix(builder): Skip minify of a .js with an existing -dbg.js sibling - #1659

Open
matz3 wants to merge 1 commit into
mainfrom
fix-minify-dbg-collision
Open

matz3 wants to merge 1 commit into
mainfrom
fix-minify-dbg-collision

Conversation

@matz3

@matz3 matz3 commented Oct 13, 2026

Copy link
Copy Markdown
Member

A -dbg.js next to its .js in the sources is a broken input state: the minify task owns the -dbg.js path and generates it from the .js, so a pre-existing one must not be there. The glob matched both as separate map-step keys. The .js key wrote its generated debug variant to the -dbg.js path, which the -dbg.js key also wrote - two concurrent keys writing one path, which the shared assertDistinctWrite guard rejected, so the build crashed.

To stay robust rather than crash, filter the step keys to skip both members of such a pair: a .js whose -dbg.js sibling already exists is left as it is (that -dbg.js already serves as the debug variant), the -dbg.js is passed through, and a warning is logged. The sibling paths are derived with the shared getDebugName and getNonDebugName helpers, so the special .view.js / .controller.js suffixes are handled consistently.

The integration test reproduces the crash and pins the expected skip; unit tests cover the filter and the warning.

Also add a TODO in the minify processor: a lone -dbg.js (no .js sibling) still reaches the processor and gets a -dbg-dbg.js debug variant, which is almost certainly unintended. Clarify whether such files should be skipped instead.

@matz3
matz3 requested a review from a team October 13, 2026 13:35
@codeworrior

Copy link
Copy Markdown
Member

Maybe I forgot about an earlier decision (e.g. in the wake of the transition from Maven to CLI), but IMO the existence of a *-dbg.js file is not a broken input state. Maybe the capability to deal with it went lost somewhen, but I'm sure we used that in the past, especially for some bootable bundles (for which normally no dbg file is created, but restarting in debug mode required such a file in the past) and for files that our old tooling could not minify at that time (e.g. newer ES6 code).

I searched the SAPUI5 codebase and only found one example in sap.ushell_abap (sap/ushell_abap/thirdparty/sap-xhrlib-esm-dbg.js, an ESM file).

@matz3

matz3 commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

Thanks for the feedback. So is your comment only about the framing of this scenario as broken, or is it also supposed to be handled differently in the minify task?

@codeworrior

Copy link
Copy Markdown
Member

Mhmm, good question. My first reaction was "about framing the scenario as broken only". But reading the commit message again, it might be about the warning, too. sap.ushell_abap will see a warning in each build although they can't handle it differently (as we do not support ES modules?).

@RandomByte

Copy link
Copy Markdown
Member

I was also wondering about past cases. I believe this is not the first time we encounter this and have to fix bugs (around pre-existing source maps maybe?) because of it.

UI5 CLI v4 seems to be able to deal with such cases while not logging a warning, right?

@matz3

matz3 commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

UI5 CLI v4 seems to be able to deal with such cases while not logging a warning, right?

I assume that the result is at least unexpected (both files end up being minified, plus a -dbg-dbg.js file) and it might even be non-deterministic because of the parallel processing. But I need to verify this.

@matz3

matz3 commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

I searched the SAPUI5 codebase and only found one example in sap.ushell_abap (sap/ushell_abap/thirdparty/sap-xhrlib-esm-dbg.js, an ESM file).

In the current internal untested version I can see that the sap/ushell_abap/thirdparty/sap-xhrlib-esm-dbg.js is being minified and there is a sap/ushell_abap/thirdparty/sap-xhrlib-esm-dbg-dbg.js in the build output.

I agree, we should consider changing the log from warning to verbose, as this can be expected.
But on the other hand, we do have minification excludes that can be configured, and I would assume they are exactly for that purpose. Maybe the warning should include a hint to configure the exclude if this is an expected input for the build.

I assume that the result is at least unexpected (both files end up being minified, plus a -dbg-dbg.js file) and it might even be non-deterministic because of the parallel processing. But I need to verify this.

It's non-deterministic if the input .js and -dbg.js files are not aligned (i.e. if they are out of sync or minified differently than our task would do).

@d3xter666

Copy link
Copy Markdown
Member

With the current architecture a new build that finds a -dbg file will read it as an input. And since it can't be a file we generated in this build - so it's either a real source file, or something a previous run left behind.

Whether a -dbg source file is valid, I don't know (the ushell ESM case says maybe it is, sometimes).

But I think the crash shows we need something more than a fix in the minify task. Right now a build that fails halfway can leave files behind that the next build picks up as input. Either:

  • some recovery after a crash (cleanup or some kind of resume), or
  • make cache + its generation atomic (write/output to an external, sandboxed dir until everything is ready, then commit everything/write the cache at once). It's also what Nix and Bazel do - build into a sandbox, move the output in only on success, so a failed build leaves nothing behind.

@matz3

matz3 commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

Right now a build that fails halfway can leave files behind that the next build picks up as input

@d3xter666 would you mind explaining what you mean here and how it relates to this issue? So far, this is about receiving -dbg.js files as input in a build (either from the sources, or (in theory) produced by a task that ran before).

@d3xter666

d3xter666 commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

@matz3 , my point was that if we have -dbg files that come from the previous task, we sould have known how to deal with them already and this could not be an issue.

If this is a real source file we need to manage it some way.

This is the sentence that made me think that at some point a -dbg file got there by accident: https://github.com/UI5/cli/pull/1659/changes#diff-4f43d1cd6ec6cf637f7b56971d7a8f7e94364b8e29373ee0c40dbe07a89dfd2cR76-R77 and the test https://github.com/UI5/cli/pull/1659/changes#diff-228a76e5624ca54d1ccfc5704d42a8ab2a30dcc0f4c30957219a6f22dfd56368R446-R472 and I was thinknig how is this possible apart of -dbg being a source file? a crash maybe...

Maybe I have missunderstood how the -dbg collision happened, but to me still feels like we should not fix this in the minify task. And my expectation would be that we manage this internally, so that case is not possible in general.
My point is that we own the mapping between .js -> -dbg.js, therefore such cases should not occur.
Of course, if a -dbg file comes from the souce as a real input, we need some way to know that and handle it properly.

@matz3

matz3 commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

Of course, if a -dbg file comes from the souce as a real input, we need some way to know that and handle it properly.

That is what this PR addresses. I am not aware of a case where a crash of our build will end up using that state as input when building again, unless you explicitly point our build to a result of a previous build. And this is actually what happened. But it is outside of the UI5 CLI, so we can only handle and skip those cases.

The current code did not detect or properly handle the case, but the task steps implementation now detects such faulty states, where the same resource is written by multiple executions of a step. This is unexpected when the steps runs the invocations in parallel. And it is unexpected by the design of the minify task because each invocation is supposed to be independent, and therefore can be run in parallel.

If you have an idea on how we could better handle this in general, I'm open. But I would be against a solution that involves some heuristic to detect an already built projects as input. We should rather make our tasks robust against states where they would cause unstable or unexpected outputs, this this is one of them.

I will go through the change again, and adjust the warning to also give a hint about minification excludes for cases where a -dbg.js input is actually correct and expected. I'm not in favour of silently skipping the files. @codeworrior I hope this is fine for you, as I think the mentioned case in sap.ushell_abap is currently not handled as expected, and it should emit a warning unless the file is excluded from minification.

@matz3
matz3 force-pushed the fix-minify-dbg-collision branch from de1c095 to f9fb0d3 Compare October 15, 2026 13:21
A -dbg.js next to its .js in the sources is unexpected: the minify task
owns the -dbg.js path and generates it from the .js. The glob matched
both as separate map-step keys. The .js key wrote its generated debug
variant to the -dbg.js path, which the -dbg.js key also wrote - two
concurrent keys writing one path, which the shared assertDistinctWrite
guard rejected, so the build crashed.

To stay robust rather than crash, filter the step keys to skip both
members of such a pair: a .js whose -dbg.js sibling already exists is
left as it is (that -dbg.js already serves as the debug variant), the
-dbg.js is passed through, and a warning is logged. The sibling paths
are derived with the shared getDebugName and getNonDebugName helpers, so
the special .view.js / .controller.js suffixes are handled consistently.

The warning states that sources normally must not contain a -dbg.js, but
if the pairing is intentional (for example the file uses ECMAScript
syntax the minify task does not support yet), the user should list both
files in the "builder.minification.excludes" configuration of the
project's ui5.yaml.

The integration test reproduces the crash and pins the expected skip;
unit tests cover the filter and the warning.

Also add a TODO in the minify processor: a lone -dbg.js (no .js sibling)
still reaches the processor and gets a -dbg-dbg.js debug variant, which
is almost certainly unintended. Clarify whether such files should be
skipped instead.
@matz3
matz3 force-pushed the fix-minify-dbg-collision branch from f9fb0d3 to c5dd531 Compare October 15, 2026 15:15
@matz3

matz3 commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

I will go through the change again, and adjust the warning to also give a hint about minification excludes for cases where a -dbg.js input is actually correct and expected. I'm not in favour of silently skipping the files. @codeworrior I hope this is fine for you, as I think the mentioned case in sap.ushell_abap is currently not handled as expected, and it should emit a warning unless the file is excluded from minification.

Done. It turned out that ESM files are supported already, but newer ECMAScript syntax might still be a valid reason, so I've adjusted the warning message.

This branch has not been deployed

No deployments
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.

4 participants