feat(@angular/build): emit debug ids for stable subresource integrity hashes#33110
feat(@angular/build): emit debug ids for stable subresource integrity hashes#33110IchordeDionysos wants to merge 2 commits intoangular:mainfrom
Conversation
… hashes Enable generating sub-resource integrity hashes when using error tracking tools relying on Debug IDs linking generated code files with source maps. Closes angular#33108
There was a problem hiding this comment.
Code Review
This pull request implements ECMA-426 Debug ID injection into JavaScript files and source maps using a new deterministic UUIDv5 utility. The injection is integrated into the post-bundle build process and includes validation tests. Review feedback suggests hardening the regex for comment detection to prevent false positives and optimizing the source map JSON update to maintain formatting and performance.
| const DEBUG_ID_COMMENT = /^[ \t]*\/\/[ \t]*#[ \t]*debugId=[^\n]*\n?/m; | ||
|
|
||
| /** Pattern matching the `//# sourceMappingURL=` comment, used to position the debug-id line. */ | ||
| const SOURCE_MAPPING_URL_COMMENT = /^[ \t]*\/\/[ \t]*#[ \t]*sourceMappingURL=[^\n]*$/m; |
There was a problem hiding this comment.
The current regexes for debugId and sourceMappingURL use the multiline flag (/m) and are anchored to the start of the line (^). This can lead to false positives if these strings appear inside string literals or comments within the JavaScript code. Since these magic comments are required to be at the end of the file (per ECMA-426), it is safer to anchor them to the end of the string and avoid the multiline flag.
| const DEBUG_ID_COMMENT = /^[ \t]*\/\/[ \t]*#[ \t]*debugId=[^\n]*\n?/m; | |
| /** Pattern matching the `//# sourceMappingURL=` comment, used to position the debug-id line. */ | |
| const SOURCE_MAPPING_URL_COMMENT = /^[ \t]*\/\/[ \t]*#[ \t]*sourceMappingURL=[^\n]*$/m; | |
| const DEBUG_ID_COMMENT = /\/\/[ \t]*#[ \t]*debugId=[^\n]*\n?(?=\s*\/\/[ \t]*#[ \t]*sourceMappingURL=|\s*$)/; | |
| const SOURCE_MAPPING_URL_COMMENT = /\/\/[ \t]*#[ \t]*sourceMappingURL=[^\n]*\s*$/; |
| export function generateDebugId(name: string | Uint8Array): string { | ||
| const sha = createHash('sha1').update(ANGULAR_BUILD_NAMESPACE).update(name).digest(); | ||
|
|
||
| // Set version (5) in the high nibble of byte 6. | ||
| sha[6] = (sha[6] & 0x0f) | 0x50; | ||
| // Set RFC 4122 variant bits (10xx) in byte 8. | ||
| sha[8] = (sha[8] & 0x3f) | 0x80; | ||
|
|
||
| const h = sha.toString('hex'); | ||
|
|
||
| return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`; | ||
| } |
There was a problem hiding this comment.
There would also be the possibility of using an existing implementation, e.g. of uuid.
Happy to make this change.
Enable generating sub-resource integrity hashes when using error tracking tools relying on Debug IDs linking generated code files with source maps.
Closes #33108
PR Checklist
Please check to confirm your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
When Angular generates source maps, they only include a link to the source map URL and no Debug ID:
The source map file also does not contain a debug ID:
{ "version": 3, "debugId": "old", "mappings": "" }Issue Number: #33108
What is the new behavior?
When Angular generates source maps, in addition to the source map URL, generated files will also include a Debug ID above the
sourceMappingURL:In addition the source map file will include the matching Debug ID:
{ "version": 3, "debugId": "old", "mappings": "", "debugId": "11111111-2222-5333-9444-555555555555" }Does this PR introduce a breaking change?
Other information
I'm happy to hear if there are concerns with this particular approach and which alternative solutions might be a better solution.
This allows error tracking to more reliably map generated code files to their corresponding stack traces.
Error tracking tools have historically solved this by running post-processing scripts that generate and inject Debug IDs after the framework build script and before deployment.
However, this approach will break any integrity hash that Angular generated for SRI as the file content will have changed.
--
This PR is part of a two fold effort to enable SRI for our specific integration of Angular.
The first PR, implementing support for dynamically loaded files can be found here, and should be merged first: #33109