refactor(ivy): evaluate prop-based styling bindings with a new algorithm (#30469)

This is the first refactor PR designed to change how styling bindings
(i.e. `[style]` and `[class]`) behave in Ivy. Instead of having a heavy
element-by-element context be generated for each element, this new
refactor aims to use a single context for each `tNode` element that is
examined and iterated over when styling values are to be applied to the
element.

This patch brings this new functionality to prop-based bindings such as
`[style.prop]` and `[class.name]`.

PR Close #30469
This commit is contained in:
Matias Niemelä
2019-05-08 16:30:28 -07:00
committed by Jason Aden
parent 848e53efd0
commit f03475cac8
24 changed files with 1993 additions and 26 deletions

View File

@ -13,7 +13,6 @@ import {BindingForm, convertPropertyBinding} from '../../compiler_util/expressio
import {ConstantPool, DefinitionKind} from '../../constant_pool';
import * as core from '../../core';
import {AST, ParsedEvent, ParsedEventType, ParsedProperty} from '../../expression_parser/ast';
import {LifecycleHooks} from '../../lifecycle_reflector';
import {DEFAULT_INTERPOLATION_CONFIG} from '../../ml_parser/interpolation_config';
import * as o from '../../output/output_ast';
import {ParseError, ParseSourceSpan, typeSourceSpan} from '../../parse_util';
@ -725,6 +724,7 @@ function createHostBindingsFunction(
// the update block of a component/directive templateFn/hostBindingsFn so that the bindings
// are evaluated and updated for the element.
styleBuilder.buildUpdateLevelInstructions(getValueConverter()).forEach(instruction => {
totalHostVarsCount += instruction.allocateBindingSlots;
updateStatements.push(createStylingStmt(instruction, bindingContext, bindingFn));
});
}

View File

@ -15,6 +15,7 @@ import * as t from '../r3_ast';
import {Identifiers as R3} from '../r3_identifiers';
import {parse as parseStyle} from './style_parser';
import {compilerIsNewStylingInUse} from './styling_state';
import {ValueConverter} from './template';
const IMPORTANT_FLAG = '!important';
@ -389,6 +390,11 @@ export class StylingBuilder {
const bindingIndex: number = mapIndex.get(input.name !) !;
const value = input.value.visit(valueConverter);
totalBindingSlotsRequired += (value instanceof Interpolation) ? value.expressions.length : 0;
if (compilerIsNewStylingInUse()) {
// the old implementation does not reserve slot values for
// binding entries. The new one does.
totalBindingSlotsRequired++;
}
return {
sourceSpan: input.sourceSpan,
allocateBindingSlots: totalBindingSlotsRequired, reference,

View File

@ -0,0 +1,37 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A temporary enum of states that inform the core whether or not
* to defer all styling instruction calls to the old or new
* styling implementation.
*/
export const enum CompilerStylingMode {
UseOld = 0,
UseBothOldAndNew = 1,
UseNew = 2,
}
let _stylingMode = 0;
/**
* Temporary function used to inform the existing styling algorithm
* code to delegate all styling instruction calls to the new refactored
* styling code.
*/
export function compilerSetStylingMode(mode: CompilerStylingMode) {
_stylingMode = mode;
}
export function compilerIsNewStylingInUse() {
return _stylingMode > CompilerStylingMode.UseOld;
}
export function compilerAllowOldStyling() {
return _stylingMode < CompilerStylingMode.UseNew;
}