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

Aperta Adatta ai principianti
#7,017 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
72/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
css, html, javascript, node.js, typescript
Ambito
testing, tooling

Direzione di ricerca

Inizia in packages/mock-doc/src/css-style-declaration.ts nel setter set cssText, dove cssText.split(';') viene eseguito incondizionatamente prima della ricomposizione esistente con slice(1).join(':') per i valori. Esegui prima lo script di riproduzione dell'issue (MockDocument + parseHtmlToFragment da @stencil/core/mock-doc) per vedere il troncamento, poi guarda i test spec mock-doc esistenti per css-style-declaration per allinearti al loro stile. Fatto significa che le dichiarazioni vengono divise solo in corrispondenza di punti e virgola di primo livello fuori da parentesi e virgolette, così che i tre output attesi nell'issue (round-trip di innerHTML, style.backgroundImage e round-trip di parseHtmlToFragment) valgano tutti.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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/

Lingua principale
TypeScript
Stelle
13.2k
Fork
865
Merge medio
2g 16h
PR unite (30g)
29

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di stenciljs/core

Tutte le issue di stenciljs/core

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.