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

Đang mở Phù hợp với người mới
#7,017 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
72/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
css, html, javascript, node.js, typescript
Lĩnh vực
testing, tooling

Hướng nghiên cứu

Bắt đầu trong packages/mock-doc/src/css-style-declaration.ts tại setter set cssText, nơi cssText.split(';') chạy vô điều kiện trước bước ghép lại hiện có bằng slice(1).join(':') cho các giá trị. Chạy script repro từ issue trước (MockDocument + parseHtmlToFragment từ @stencil/core/mock-doc) để thấy việc cắt cụt, sau đó xem các test spec mock-doc hiện có cho css-style-declaration để khớp phong cách của chúng. Hoàn thành nghĩa là các khai báo chỉ được tách tại dấu chấm phẩy cấp cao nhất bên ngoài dấu ngoặc và dấu nháy, sao cho ba kết quả đầu ra mong đợi trong issue (round-trip innerHTML, style.backgroundImage, và round-trip parseHtmlToFragment) đều đúng.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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/

Ngôn ngữ chính
TypeScript
Star
13.2k
Fork
865
Merge trung bình
2 ngày 16 giờ
Pull request đã merge (30 ngày)
29

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của stenciljs/core

Tất cả issue của stenciljs/core

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.