@@ -196,23 +196,31 @@ function getAbsoluteSrcsetString(doc: Document, attributeValue: string) {
196
196
return output . join ( ', ' ) ;
197
197
}
198
198
199
+ const cachedDocument = new WeakMap < Document , HTMLAnchorElement > ( ) ;
200
+
199
201
export function absoluteToDoc ( doc : Document , attributeValue : string ) : string {
200
202
if ( ! attributeValue || attributeValue . trim ( ) === '' ) {
201
203
return attributeValue ;
202
204
}
203
- const a : HTMLAnchorElement = doc . createElement ( 'a' ) ;
204
- a . href = attributeValue ;
205
- return a . href ;
205
+
206
+ return getHref ( doc , attributeValue ) ;
206
207
}
207
208
208
209
function isSVGElement ( el : Element ) : boolean {
209
210
return Boolean ( el . tagName === 'svg' || ( el as SVGElement ) . ownerSVGElement ) ;
210
211
}
211
212
212
- function getHref ( ) {
213
- // return a href without hash
214
- const a = document . createElement ( 'a' ) ;
215
- a . href = '' ;
213
+ function getHref ( doc : Document , customHref ?: string ) {
214
+ let a = cachedDocument . get ( doc ) ;
215
+ if ( ! a ) {
216
+ a = doc . createElement ( 'a' ) ;
217
+ cachedDocument . set ( doc , a ) ;
218
+ }
219
+ if ( ! customHref ) {
220
+ customHref = '' ;
221
+ }
222
+ // note: using `new URL` is slower. See #1434 or https://jsbench.me/uqlud17rxo/1
223
+ a . setAttribute ( 'href' , customHref ) ;
216
224
return a . href ;
217
225
}
218
226
@@ -244,7 +252,7 @@ export function transformAttribute(
244
252
} else if ( name === 'srcset' ) {
245
253
return getAbsoluteSrcsetString ( doc , value ) ;
246
254
} else if ( name === 'style' ) {
247
- return absoluteToStylesheet ( value , getHref ( ) ) ;
255
+ return absoluteToStylesheet ( value , getHref ( doc ) ) ;
248
256
} else if ( tagName === 'object' && name === 'data' ) {
249
257
return absoluteToDoc ( doc , value ) ;
250
258
}
@@ -506,6 +514,7 @@ function serializeNode(
506
514
} ) ;
507
515
case n . TEXT_NODE :
508
516
return serializeTextNode ( n as Text , {
517
+ doc,
509
518
needsMask,
510
519
maskTextFn,
511
520
rootId,
@@ -536,6 +545,7 @@ function getRootId(doc: Document, mirror: Mirror): number | undefined {
536
545
function serializeTextNode (
537
546
n : Text ,
538
547
options : {
548
+ doc : Document ;
539
549
needsMask : boolean | undefined ;
540
550
maskTextFn : MaskTextFn | undefined ;
541
551
rootId : number | undefined ;
@@ -567,7 +577,7 @@ function serializeTextNode(
567
577
n ,
568
578
) ;
569
579
}
570
- textContent = absoluteToStylesheet ( textContent , getHref ( ) ) ;
580
+ textContent = absoluteToStylesheet ( textContent , getHref ( options . doc ) ) ;
571
581
}
572
582
if ( isScript ) {
573
583
textContent = 'SCRIPT_PLACEHOLDER' ;
@@ -661,7 +671,7 @@ function serializeElementNode(
661
671
( n as HTMLStyleElement ) . sheet as CSSStyleSheet ,
662
672
) ;
663
673
if ( cssText ) {
664
- attributes . _cssText = absoluteToStylesheet ( cssText , getHref ( ) ) ;
674
+ attributes . _cssText = absoluteToStylesheet ( cssText , getHref ( doc ) ) ;
665
675
}
666
676
}
667
677
// form fields
0 commit comments