bug: mock-doc splits inline style at `;` inside url(), corrupting data-URI backgrounds

オープン 初心者向け
#7,017 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
72/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
css, html, javascript, node.js, typescript
領域
testing, tooling

調査の方向性

packages/mock-doc/src/css-style-declaration.ts の set cssText セッターから始めてください。ここでは、値に対する既存の slice(1).join(':') による再結合の前に、cssText.split(';') が無条件で実行されます。まず issue の再現スクリプト(@stencil/core/mock-doc の MockDocument + parseHtmlToFragment)を実行して切り詰めを確認し、次に css-style-declaration の既存の mock-doc spec テストを見て、そのスタイルに合わせてください。完了とは、宣言が括弧と引用符の外側にあるトップレベルのセミコロンでのみ分割され、issue にある 3 つの期待出力(innerHTML のラウンドトリップ、style.backgroundImage、parseHtmlToFragment のラウンドトリップ)がすべて成り立つことです。

索引モデルが issue の本文から書いたものです。

説明

Prerequisites
Stencil Version

4.45.3 (also reproduced on main at f4fe940 and 5.0.0-rc.1 / v5 at 1ed1c6c)

Current Behavior

MockCSSStyleDeclaration's cssText setter splits declarations with cssText.split(';'), so a semicolon inside url(...) (such as ;base64, in a data URI) or inside quotes terminates the declaration early. The remainder of the data URI is dropped (or misparsed as the next property if it contains :), leaving an unclosed url( or quote in the serialized style attribute.

This affects:

  • renderToString() when hydrating HTML that contains inline data-URI styles (<div style="background: url(data:image/gif;base64,...) no-repeat; color: red">), emitting <div style="background: url(data:image/gif; color: red;"> where the unclosed url( also invalidates color: red in browsers.
  • el.setAttribute('style', ...) and el.style.cssText = ... in components running under SSR or newSpecPage().
  • toEqualHtml() in spec tests: JSX style={{ backgroundImage: 'url(data:image/png;base64,...)' }} uses style.setProperty() and serializes intact on the live element, whereas parseHtmlToFragment() re-parses the expected HTML string through cssText and truncates it, so toEqualHtml() fails even against the element's own outerHTML.
Expected Behavior

MockCSSStyleDeclaration.cssText only splits declarations at top-level semicolons (outside parentheses and quotes), matching browser CSSStyleDeclaration behavior and CSS Syntax Module Level 3:

  • doc.body.innerHTML preserves <div style="background: url(data:image/gif;base64,R0lGOD==) no-repeat; color: red;">x</div>.
  • div.style.backgroundImage is url('data:image/png;base64,iVBORw0KGgo=') and div.getAttribute('style') is background-image: url('data:image/png;base64,iVBORw0KGgo='); color: red;.
  • parseHtmlToFragment(rendered.outerHTML) round-trips background-image: url(data:image/png;base64,iVBORw0KGgo=); color: blue; unchanged.
System Info
      System: node 26.13.0
    Platform: linux (6.1.0-54-cloud-amd64)
   CPU Model: Intel(R) Xeon(R) CPU @ 2.80GHz (64 cpus)
     Stencil: 4.45.3
  TypeScript: 5.8.3
      Rollup: 4.44.0
      Parse5: 7.2.1
      jQuery: 4.0.0-pre
      Terser: 5.37.0
Steps to Reproduce

Run npm install @stencil/[email protected] && node stencil-core-tslib.repro.mjs:

// stencil-core-tslib.repro.mjs
import { MockDocument, parseHtmlToFragment } from "@stencil/core/mock-doc";

const doc = new MockDocument(
  '<div style="background: url(data:image/gif;base64,R0lGOD==) no-repeat; color: red">x</div>'
);
console.log(doc.body.innerHTML);

const div = doc.createElement("div");
div.setAttribute("style", "background-image: url('data:image/png;base64,iVBORw0KGgo='); color: red");
console.log(div.getAttribute("style"));
console.log(div.style.backgroundImage);

const rendered = doc.createElement("div");
rendered.style.setProperty("background-image", "url(data:image/png;base64,iVBORw0KGgo=)");
rendered.style.setProperty("color", "blue");
console.log("before parse:", rendered.outerHTML);
console.log("after parse: ", parseHtmlToFragment(rendered.outerHTML).firstElementChild.outerHTML);

Actual output:

<div style="background: url(data:image/gif; color: red;">x</div>
background-image: url('data:image/png; color: red;
url('data:image/png
before parse: <div style="background-image: url(data:image/png;base64,iVBORw0KGgo=); color: blue;"></div>
after parse:  <div style="background-image: url(data:image/png; color: blue;"></div>
Code Reproduction URL

https://gist.github.com/trackoor/624030cdd797e27d114e86126108b278

Additional Information

In src/mock-doc/css-style-declaration.ts (packages/mock-doc/src/css-style-declaration.ts on v5), set cssText already rejoins : segments via splt.slice(1).join(':') so URLs with schemes survive, while the outer cssText.split(';') splits unconditionally.

Credit: https://ucsbplse.github.io/

主要言語
TypeScript
スター
13.2k
フォーク
865
平均マージ
2日 16時間
マージ済み PR(30日)
29

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

stenciljs/core のほかの issue

stenciljs/core の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。