@@ -66,6 +66,43 @@ describe("identifier", () => {
6666 run ( tests ) ;
6767 } ) ;
6868
69+ // Tests for https://github.com/webpack/webpack/issues/16819
70+ // To embed a literal '#' in a filesystem path, the caller must use the
71+ // '\0#' null-byte escape. Unescaped '#' always starts a fragment.
72+ describe ( "parse identifier. '#' escape with \\0" , ( ) => {
73+ /** @type {TestSuite[] } */
74+ const tests = [
75+ // '\0#' in path is unescaped to '#' (part of directory name), no fragment
76+ {
77+ input : "/home/user/projects/test\0#/webpack/src/file.js" ,
78+ expected : [ "/home/user/projects/test#/webpack/src/file.js" , "" , "" ] ,
79+ } ,
80+ // '\0#' dir name, with a real (unescaped) '#' fragment at the end
81+ {
82+ input : "/projects/test\0#app/src/file.js#fragment" ,
83+ expected : [ "/projects/test#app/src/file.js" , "" , "#fragment" ] ,
84+ } ,
85+ // Multiple '\0#' escapes in dir names, then a real fragment
86+ {
87+ input : "/a\0#b/c\0#d/file.js#hash" ,
88+ expected : [ "/a#b/c#d/file.js" , "" , "#hash" ] ,
89+ } ,
90+ // '\0#' dir name with both query and fragment
91+ {
92+ input : "/projects/test\0#app/file.js?query#fragment" ,
93+ expected : [ "/projects/test#app/file.js" , "?query" , "#fragment" ] ,
94+ } ,
95+ // Unescaped '#' mid-segment is still treated as a fragment start
96+ // (callers must escape '#' in paths via '\0#' — see webpack#16819)
97+ {
98+ input : "/home/user/projects/test#/webpack/src/file.js" ,
99+ expected : [ "/home/user/projects/test" , "" , "#/webpack/src/file.js" ] ,
100+ } ,
101+ ] ;
102+
103+ run ( tests ) ;
104+ } ) ;
105+
69106 describe ( "parse identifier. Windows-like paths" , ( ) => {
70107 /** @type {TestSuite[] } */
71108 const tests = [
@@ -93,6 +130,17 @@ describe("identifier", () => {
93130 input : "path\\#/not/a/hash?not-a-query" ,
94131 expected : [ "path\\" , "" , "#/not/a/hash?not-a-query" ] ,
95132 } ,
133+ // Regression (webpack#16819): '\0#' null-byte escape correctly
134+ // embeds '#' in a Windows dir name (no fragment produced)
135+ {
136+ input : "C:\\Users\\test\0#proj\\webpack\\src\\file.js" ,
137+ expected : [ "C:\\Users\\test#proj\\webpack\\src\\file.js" , "" , "" ] ,
138+ } ,
139+ // Without escaping, '#' still starts a fragment (caller must escape)
140+ {
141+ input : "C:\\Users\\test#proj\\webpack\\src\\file.js" ,
142+ expected : [ "C:\\Users\\test" , "" , "#proj\\webpack\\src\\file.js" ] ,
143+ } ,
96144 ] ;
97145
98146 run ( tests ) ;
0 commit comments