为什么 / 🌈 是无效的路径,而 /a🌈 是有效的?

Why is /🌈 an invalid path when /a🌈 is valid?

提问人:ændrük 提问时间:9/25/2022 最后编辑:Bergiændrük 更新时间:12/15/2022 访问量:678

问:

我试图理解为什么某些 HTML 属性无法通过 W3C 验证。我在真实的代码库中遇到了这种情况,但这里有一个最小的复制:

<!DOCTYPE html><html lang="en"><head><title>a</title></head><body>

<img alt="1" src="⭐">
<img alt="2" src="/⭐">
<img alt="3" src="/a⭐">
<img alt="4" src="/a/⭐">
<img alt="5" src="🌈">
<img alt="6" src="/🌈"> <!-- Only this is invalid. -->
<img alt="7" src="/a🌈">
<img alt="8" src="/a/🌈">

</body></html>

W3C 验证器仅报告一个错误,影响第六个图像:

  1. 错误:元素上的属性值错误:不允许路径段中的非法字符。/🌈srcimg?

    <img alt="6" src="/🌈">
    

为什么只有一个问题,而其他问题却没有?它有什么不同?

HTML 表情符号 w3c-validation url-parsing

评论

5赞 Heretic Monkey 9/26/2022
您可能希望通过他们的 GitHub 将其作为可能的错误提交:github.com/validator/validator/issues
3赞 sideshowbarker 10/3/2022
顺便说一句,当我意识到像这样的错误时,它存在于代码的一部分中,该错误旨在完全符合相关规范,但实际上并没有,我几乎会停止我正在做的任何其他事情并对其进行处理,直到它被修复 - 这通常是在我第一次发现错误后的几个小时内。几个小时前,我只是非常偶然地遇到了这个 SO 问题。因此,如果/当您在检查器中遇到您认为可能是错误的其他问题时,请像这里的其他人所建议的那样,在 github.com/validator/validator/issues 提出问题。
3赞 sideshowbarker 10/3/2022
此外,如果您确实在 SO 上发布了有关检查器行为的其他问题,请使用 w3c-validation 标签标记它们。我看那个标签——每当有人在那里发帖时,我都会在 15 分钟内收到通知(目前还有 77 人也在看这个标签)。如果是关于 URL 有效性的,并且您不确定预期的行为实际上应该是什么,那么 matrix.to/#/#whatwg:matrix.org 的 WHATWG Matrix 房间是一个提问的好地方。对于此处的 URL 问题,url 解析是一个有用的标签。
3赞 Bergi 10/3/2022
@sideshowbarker w3c-validation 标签已经出现在这个问题上,我不确定为什么@TylerH删除它 - 可能是因为他认为这不是一个官方的 w3c 项目
2赞 Bergi 10/3/2022
@TylerH 标签没什么不好的,它显然很有用。不,问题不在于一些任意验证,而在于检查某些东西是否符合 w3c 标准的 w3c 验证服务。在再次删除标签之前,请将此讨论带到 meta。

答:

13赞 sideshowbarker 10/3/2022 #1

问题中描述的行为是由现已修复的检查器(验证器)代码中的错误引起的;请参阅 https://github.com/validator/galimatias/pull/2。由于测试套件没有涵盖以斜杠开头的相对 URL 后跟大于 U+FFFF 的代码点的情况,因此该错误被忽视了——就像问题中的 U+1F30 🌈(彩虹)字符一样。因此,测试套件也进行了更新,以增加对该情况的覆盖范围;请参见 https://github.com/web-platform-tests/wpt/pull/36213


顺便说一句,U+2b50 (⭐) 案例没有受到 bug 的影响,而 U+1F308 () 案例的原因是:Java 使用 UTF-16,而 U+1F308 在所谓的补充字符范围内(🌈即 U+FFFF 上方的代码点集),因此——如上面的评论中所述——在 UTF-16 中,代码点 U+1F308 由两个 char 值的代理对表示,而 U+2b50 表示单个值。char

值数的差异影响 URL 解析方式的原因是 HTML 检查器的 URL 解析代码中的状态机维护字符索引并在状态更改期间递减它。因此,如果它正在处理一个可以包含高于 U+FFFF 的代码点的 URL 段,它必须明智地决定它减少了多少个字符 - 对于高于 U+FFFF 的代码点,它需要将其减少 2,否则减少 1。char

为此,代码有一个调用 Character.charCount() 的 decrIdx() 方法:

Determines the number of values needed to represent the specified character (Unicode code point). If the specified character is equal to or greater than 0x10000, then the method returns 2. Otherwise, the method returns 1.char

So the code change that got made to the checker replaced a simple decrementing of the index value with a smarter -enabled decrIdx() call.idx--Character.charCount()

评论

0赞 ændrük 10/3/2022
“Java uses UTF-16” This is the missing piece for me. I’d read through the state machine and couldn’t figure out how it would work in UTF-8.