6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
import { StyleSanitizeFn } from '../../sanitization/style_sanitizer' ;
9
+ import { assertEqual } from '../../util/assert' ;
9
10
import { TNode , TNodeType } from '../interfaces/node' ;
10
11
import { PlayerFactory } from '../interfaces/player' ;
11
- import { FLAGS , HEADER_OFFSET , LViewFlags , RENDERER , RootContextFlags } from '../interfaces/view' ;
12
+ import { FLAGS , HEADER_OFFSET , LView , LViewFlags , RENDERER , RootContextFlags } from '../interfaces/view' ;
12
13
import { getActiveDirectiveId , getActiveDirectiveSuperClassDepth , getLView , getPreviousOrParentTNode , getSelectedIndex } from '../state' ;
13
14
import { getInitialClassNameValue , renderStyling , updateClassProp as updateElementClassProp , updateContextWithBindings , updateStyleProp as updateElementStyleProp , updateStylingMap } from '../styling/class_and_style_bindings' ;
14
15
import { ParamsOf , enqueueHostInstruction , registerHostDirective } from '../styling/host_instructions_queue' ;
15
16
import { BoundPlayerFactory } from '../styling/player_factory' ;
16
17
import { DEFAULT_TEMPLATE_DIRECTIVE_INDEX } from '../styling/shared' ;
17
- import { allocateOrUpdateDirectiveIntoContext , createEmptyStylingContext , forceClassesAsString , forceStylesAsString , getStylingContext , hasClassInput , hasStyleInput } from '../styling/util' ;
18
+ import { getCachedStylingContext , setCachedStylingContext } from '../styling/state' ;
19
+ import { allocateOrUpdateDirectiveIntoContext , createEmptyStylingContext , forceClassesAsString , forceStylesAsString , getStylingContextFromLView , hasClassInput , hasStyleInput } from '../styling/util' ;
18
20
import { NO_CHANGE } from '../tokens' ;
19
21
import { renderStringify } from '../util/misc_utils' ;
20
22
import { getRootContext } from '../util/view_traversal_utils' ;
@@ -170,9 +172,9 @@ export function ɵɵelementStyleProp(
170
172
index : number , styleIndex : number , value : string | number | String | PlayerFactory | null ,
171
173
suffix ?: string | null , forceOverride ?: boolean ) : void {
172
174
const valueToAdd = resolveStylePropValue ( value , suffix ) ;
175
+ const stylingContext = getStylingContext ( index , getLView ( ) ) ;
173
176
updateElementStyleProp (
174
- getStylingContext ( index + HEADER_OFFSET , getLView ( ) ) , styleIndex , valueToAdd ,
175
- DEFAULT_TEMPLATE_DIRECTIVE_INDEX , forceOverride ) ;
177
+ stylingContext , styleIndex , valueToAdd , DEFAULT_TEMPLATE_DIRECTIVE_INDEX , forceOverride ) ;
176
178
}
177
179
178
180
/**
@@ -206,9 +208,7 @@ export function ɵɵelementHostStyleProp(
206
208
const directiveStylingIndex = getActiveDirectiveStylingIndex ( ) ;
207
209
const hostElementIndex = getSelectedIndex ( ) ;
208
210
209
- const lView = getLView ( ) ;
210
- const stylingContext = getStylingContext ( hostElementIndex + HEADER_OFFSET , lView ) ;
211
-
211
+ const stylingContext = getStylingContext ( hostElementIndex , getLView ( ) ) ;
212
212
const valueToAdd = resolveStylePropValue ( value , suffix ) ;
213
213
const args : ParamsOf < typeof updateElementStyleProp > =
214
214
[ stylingContext , styleIndex , valueToAdd , directiveStylingIndex , forceOverride ] ;
@@ -259,9 +259,9 @@ export function ɵɵelementClassProp(
259
259
const input = ( value instanceof BoundPlayerFactory ) ?
260
260
( value as BoundPlayerFactory < boolean | null > ) :
261
261
booleanOrNull ( value ) ;
262
+ const stylingContext = getStylingContext ( index , getLView ( ) ) ;
262
263
updateElementClassProp (
263
- getStylingContext ( index + HEADER_OFFSET , getLView ( ) ) , classIndex , input ,
264
- DEFAULT_TEMPLATE_DIRECTIVE_INDEX , forceOverride ) ;
264
+ stylingContext , classIndex , input , DEFAULT_TEMPLATE_DIRECTIVE_INDEX , forceOverride ) ;
265
265
}
266
266
267
267
@@ -287,9 +287,7 @@ export function ɵɵelementHostClassProp(
287
287
classIndex : number , value : boolean | PlayerFactory , forceOverride ?: boolean ) : void {
288
288
const directiveStylingIndex = getActiveDirectiveStylingIndex ( ) ;
289
289
const hostElementIndex = getSelectedIndex ( ) ;
290
-
291
- const lView = getLView ( ) ;
292
- const stylingContext = getStylingContext ( hostElementIndex + HEADER_OFFSET , lView ) ;
290
+ const stylingContext = getStylingContext ( hostElementIndex , getLView ( ) ) ;
293
291
294
292
const input = ( value instanceof BoundPlayerFactory ) ?
295
293
( value as BoundPlayerFactory < boolean | null > ) :
@@ -330,8 +328,8 @@ export function ɵɵelementStylingMap(
330
328
index : number , classes : { [ key : string ] : any } | string | NO_CHANGE | null ,
331
329
styles ?: { [ styleName : string ] : any } | NO_CHANGE | null ) : void {
332
330
const lView = getLView ( ) ;
331
+ const stylingContext = getStylingContext ( index , lView ) ;
333
332
const tNode = getTNode ( index , lView ) ;
334
- const stylingContext = getStylingContext ( index + HEADER_OFFSET , lView ) ;
335
333
336
334
// inputs are only evaluated from a template binding into a directive, therefore,
337
335
// there should not be a situation where a directive host bindings function
@@ -384,10 +382,7 @@ export function ɵɵelementHostStylingMap(
384
382
styles ?: { [ styleName : string ] : any } | NO_CHANGE | null ) : void {
385
383
const directiveStylingIndex = getActiveDirectiveStylingIndex ( ) ;
386
384
const hostElementIndex = getSelectedIndex ( ) ;
387
-
388
- const lView = getLView ( ) ;
389
- const stylingContext = getStylingContext ( hostElementIndex + HEADER_OFFSET , lView ) ;
390
-
385
+ const stylingContext = getStylingContext ( hostElementIndex , getLView ( ) ) ;
391
386
const args : ParamsOf < typeof updateStylingMap > =
392
387
[ stylingContext , classes , styles , directiveStylingIndex ] ;
393
388
enqueueHostInstruction ( stylingContext , directiveStylingIndex , updateStylingMap , args ) ;
@@ -432,13 +427,22 @@ export function elementStylingApplyInternal(directiveStylingIndex: number, index
432
427
// the styling apply code knows not to actually apply the values...
433
428
const renderer = tNode . type === TNodeType . Element ? lView [ RENDERER ] : null ;
434
429
const isFirstRender = ( lView [ FLAGS ] & LViewFlags . FirstLViewPass ) !== 0 ;
435
- const stylingContext = getStylingContext ( index + HEADER_OFFSET , lView ) ;
430
+ const stylingContext = getStylingContext ( index , lView ) ;
436
431
const totalPlayersQueued = renderStyling (
437
432
stylingContext , renderer , lView , isFirstRender , null , null , directiveStylingIndex ) ;
438
433
if ( totalPlayersQueued > 0 ) {
439
434
const rootContext = getRootContext ( lView ) ;
440
435
scheduleTick ( rootContext , RootContextFlags . FlushPlayers ) ;
441
436
}
437
+
438
+ // because select(n) may not run between every instruction, the cached styling
439
+ // context may not get cleared between elements. The reason for this is because
440
+ // styling bindings (like `[style]` and `[class]`) are not recognized as property
441
+ // bindings by default so a select(n) instruction is not generated. To ensure the
442
+ // context is loaded correctly for the next element the cache below is pre-emptively
443
+ // cleared because there is no code in Angular that applies more styling code after a
444
+ // styling flush has occurred. Note that this will be fixed once FW-1254 lands.
445
+ setCachedStylingContext ( null ) ;
442
446
}
443
447
444
448
export function getActiveDirectiveStylingIndex ( ) {
@@ -450,3 +454,15 @@ export function getActiveDirectiveStylingIndex() {
450
454
// sub-classed directive the inheritance depth is taken into account as well.
451
455
return getActiveDirectiveId ( ) + getActiveDirectiveSuperClassDepth ( ) ;
452
456
}
457
+
458
+ function getStylingContext ( index : number , lView : LView ) {
459
+ let context = getCachedStylingContext ( ) ;
460
+ if ( ! context ) {
461
+ context = getStylingContextFromLView ( index + HEADER_OFFSET , lView ) ;
462
+ setCachedStylingContext ( context ) ;
463
+ } else if ( ngDevMode ) {
464
+ const actualContext = getStylingContextFromLView ( index + HEADER_OFFSET , lView ) ;
465
+ assertEqual ( context , actualContext , 'The cached styling context is invalid' ) ;
466
+ }
467
+ return context ;
468
+ }
0 commit comments