Почему браузеры по-разному анализируют теги <script>? - PullRequest
1 голос
/ 23 апреля 2019

Я занимаюсь разработкой нового сайта и при написании некоторого клиентского кода HTML / Javascript, я столкнулся с этим сценарием.

Если в теге <script> есть, например, * 1004, символы HTML в кодировке* предупреждение должно всплывать с &gt;, и это происходит потому, что я считаю, что анализатор HTML запускается первым перед анализатором javascript для тегов <script> и <style>.Это работает, как и ожидалось.

Теперь, когда я писал какой-то код, я сделал это - <svg><script>alert("&gt;");</script></svg>.На этот раз я получаю всплывающее окно с > вместо &gt;.Хотя я могу понять, что это из-за тега <svg>, я не уверен, что является основной причиной и какие другие теги помимо <svg> изменяют поведение по умолчанию.

Если кто-то может указать на официальную документацию, это было бы очень полезно.

Вот простой JSFiddle, который я создал для этого сценария - https://jsfiddle.net/emz8Lfxt/.

Ответы [ 3 ]

1 голос
/ 23 апреля 2019

Честно говоря, я чувствую, что вам будет сложно найти официальную документацию о том, почему это происходит.

Мое лучшее предположение в этом сценарии заключается в том, что элемент SVG является контейнером для графики SVG, и этоконтейнер SVG основан на XML и может содержать другие элементы HTML;пример:

<svg>
    <rect style="fill:rgb(0,0,255);" />
</svg>

Браузер пытается проанализировать внутренний html, пытаясь нарисовать объект.Однако, как только он понимает, что это не совсем SVG-элемент, он просто останавливается и продолжает выполнять полученный там javascript.Как следствие, &gt; анализируется до того, как исполняется JavaScript.

Мне кажется, что нам нужен кто-то с глубокими знаниями о деталях обработки SVG-элемента.

Я отмечу, для справки, этот пример:

<script>alert("&gt;")</script>
<svg><script>alert("&gt;")</script></svg>
<span><script>alert("&gt;")</script></span>

Будет выводить по порядку:

&gt;
>
&gt;
1 голос
/ 23 апреля 2019

Браузеры специально разбирают <script>, они не заменяют в них HTML-сущности. Это позволяет писать такие вещи, как:

if (a < b)

вместо того, чтобы писать:

if (a &lt; b)

В ранних браузерах вам приходилось писать что-то вроде:

<script type="text/javascript">
<![CDATA[
  …
]]>
</script>

Секция CDATA не выполняла подстановку сущностей, поэтому вы могли бы написать код "нормально" там.

Но более поздние спецификации HTML сделали это по умолчанию для <script> тел, поэтому в этом больше нет необходимости.

Но когда <script> находится внутри <svg>, очевидно, SVG-парсер имеет преимущество. Так &gt; переводится в >.

0 голосов
/ 23 апреля 2019

Встроенный SVG в документе HTML рассматривается синтаксическим анализатором как внешний элемент . Затем его содержимое анализируется анализатором SVG, и, таким образом, все содержимое этого SVGElement анализируется как SVG.

SVG имеет свое собственное определение элемента , и здесь у вас есть SVGScriptElement, а не HTML:

<svg>
  <script>
    const thisScript = document.currentScript;
    console.log('HTMLScriptElement?', thisScript instanceof HTMLScriptElement); // false
    console.log('SVGScriptElement?', thisScript instanceof SVGScriptElement); // true
  </script>
</svg>

Теперь, что касается того, почему содержимое элемента <svg:script> анализируется так, как если бы он был XML, прежде чем он будет выполнен, нам нужно немного вернуться назад во времени.

SVG1.1 определил его элемент как

Категория:
Ни один
Модель содержимого:
Любые элементы или символьные данные.
Атрибуты: ...

Это означает, что SVG1.1, в отличие от HTML, позволяет своему элементу иметь другое содержимое, нежели символьные данные . (HTML4 определил модель содержимого сценария как Данные сценария , которые в конечном итоге сопоставлены с CDATA ).

SVG tiny 1.2 с тех пор последовал за HTML и действительно обрабатывает контент как символьные данные, но, к сожалению, браузеры реализовали только vector-эффекты из этой бедной версии tiny1.2, поэтому разбираем скрипт тег все еще сделан согласно 1.1 правилам.

[Но входящий SVG2] (https://www.w3.org/TR/SVG/interact.html#ScriptElement должен следовать здесь, пока он еще обсуждается, что означает, что в ближайшем будущем нам больше не нужно будет оборачивать наш код в блоки //<![CDATA[, даже если это будет решение для вашего случая:

<svg>
  <script>
    console.log("out", "&gt;"); // >
  //<![CDATA[ 
    // ^- this forces the SVG parser to treat the content as Character Data
    console.log("in", "&gt;"); // &gt;
  //]]>
  </script>
</svg>

Однако будьте осторожны, блоки <![CDATA[ недопустимы в HTML (отсюда // js комментарии), за исключением внешних элементов , таких как SVG и MathML, поэтому вместо этого вы можете просто захотеть переместите свой скрипт из элемента , чтобы он был частью вашего HTML-документа напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...