@@ -14,33 +14,34 @@ import {
1414 isNull ,
1515 isTrue ,
1616 isUndefined ,
17- toString ,
1817 KEY__SCOPED_CSS ,
18+ toString ,
1919} from '@lwc/shared' ;
2020
2121import { logError } from '../shared/logger' ;
2222import { getComponentTag } from '../shared/format' ;
23-
2423import api , { RenderAPI } from './api' ;
2524import {
25+ RenderMode ,
2626 resetComponentRoot ,
2727 runWithBoundaryProtection ,
28+ ShadowMode ,
2829 SlotSet ,
2930 TemplateCache ,
3031 VM ,
31- RenderMode ,
3232} from './vm' ;
3333import { EmptyArray } from './utils' ;
3434import { defaultEmptyTemplate , isTemplateRegistered } from './secure-template' ;
3535import {
36- TemplateStylesheetFactories ,
3736 createStylesheet ,
3837 getStylesheetsContent ,
38+ TemplateStylesheetFactories ,
3939 updateStylesheetToken ,
4040} from './stylesheet' ;
41- import { logOperationStart , logOperationEnd , OperationId } from './profiler' ;
41+ import { logOperationEnd , logOperationStart , OperationId } from './profiler' ;
4242import { getTemplateOrSwappedTemplate , setActiveVM } from './hot-swaps' ;
4343import { VNodes } from './vnodes' ;
44+ import { RendererAPI } from './renderer' ;
4445
4546export interface Template {
4647 ( api : RenderAPI , cmp : object , slotSet : SlotSet , cache : TemplateCache ) : VNodes ;
@@ -113,6 +114,82 @@ function validateLightDomTemplate(template: Template, vm: VM) {
113114 }
114115}
115116
117+ const enum FragmentCache {
118+ HAS_SCOPED_STYLE = 1 << 0 ,
119+ SHADOW_MODE_SYNTHETIC = 1 << 1 ,
120+ }
121+
122+ function buildParseFragmentFn (
123+ createFragmentFn : ( html : string , renderer : RendererAPI ) => Element
124+ ) : ( strings : string [ ] , ...keys : number [ ] ) => ( ) => Element {
125+ return ( strings : string [ ] , ...keys : number [ ] ) => {
126+ const cache = create ( null ) ;
127+
128+ return function ( ) : Element {
129+ const {
130+ context : { hasScopedStyles, stylesheetToken } ,
131+ shadowMode,
132+ renderer,
133+ } = getVMBeingRendered ( ) ! ;
134+ const hasStyleToken = ! isUndefined ( stylesheetToken ) ;
135+ const isSyntheticShadow = shadowMode === ShadowMode . Synthetic ;
136+
137+ let cacheKey = 0 ;
138+ if ( hasStyleToken && hasScopedStyles ) {
139+ cacheKey |= FragmentCache . HAS_SCOPED_STYLE ;
140+ }
141+ if ( hasStyleToken && isSyntheticShadow ) {
142+ cacheKey |= FragmentCache . SHADOW_MODE_SYNTHETIC ;
143+ }
144+
145+ if ( ! isUndefined ( cache [ cacheKey ] ) ) {
146+ return cache [ cacheKey ] ;
147+ }
148+
149+ const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetToken : '' ;
150+ const classAttrToken =
151+ hasScopedStyles && hasStyleToken ? ` class="${ stylesheetToken } "` : '' ;
152+ const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetToken : '' ;
153+
154+ let htmlFragment = '' ;
155+ for ( let i = 0 , n = keys . length ; i < n ; i ++ ) {
156+ switch ( keys [ i ] ) {
157+ case 0 : // styleToken in existing class attr
158+ htmlFragment += strings [ i ] + classToken ;
159+ break ;
160+ case 1 : // styleToken for added class attr
161+ htmlFragment += strings [ i ] + classAttrToken ;
162+ break ;
163+ case 2 : // styleToken as attr
164+ htmlFragment += strings [ i ] + attrToken ;
165+ break ;
166+ case 3 : // ${1}${2}
167+ htmlFragment += strings [ i ] + classAttrToken + attrToken ;
168+ break ;
169+ }
170+ }
171+
172+ htmlFragment += strings [ strings . length - 1 ] ;
173+
174+ cache [ cacheKey ] = createFragmentFn ( htmlFragment , renderer ) ;
175+
176+ return cache [ cacheKey ] ;
177+ } ;
178+ } ;
179+ }
180+
181+ // Note: at the moment this code executes, we don't have a renderer yet.
182+ export const parseFragment = buildParseFragmentFn ( ( html , renderer ) => {
183+ const { createFragment } = renderer ;
184+ return createFragment ( html ) ;
185+ } ) ;
186+
187+ export const parseSVGFragment = buildParseFragmentFn ( ( html , renderer ) => {
188+ const { createFragment, getFirstChild } = renderer ;
189+ const fragment = createFragment ( '<svg>' + html + '</svg>' ) ;
190+ return getFirstChild ( fragment ) ;
191+ } ) ;
192+
116193export function evaluateTemplate ( vm : VM , html : Template ) : VNodes {
117194 if ( process . env . NODE_ENV !== 'production' ) {
118195 assert . isTrue (
0 commit comments