This patch is a final major refactor in styling Angular. This PR includes three main fixes: All temporary state taht is persisted between template style/class application and style/class application in host bindings is now removed. Removes the styling() and stylingApply() instructions. Introduces a "direct apply" mode that is used apply prop-based style/class in the event that there are no map-based bindings as well as property collisions. PR Close #32259 PR Close #32596
This commit is contained in:
@ -69,8 +69,6 @@ export class Identifiers {
|
||||
|
||||
static elementContainer: o.ExternalReference = {name: 'ɵɵelementContainer', moduleName: CORE};
|
||||
|
||||
static styling: o.ExternalReference = {name: 'ɵɵstyling', moduleName: CORE};
|
||||
|
||||
static styleMap: o.ExternalReference = {name: 'ɵɵstyleMap', moduleName: CORE};
|
||||
|
||||
static classMap: o.ExternalReference = {name: 'ɵɵclassMap', moduleName: CORE};
|
||||
@ -115,8 +113,6 @@ export class Identifiers {
|
||||
static stylePropInterpolateV:
|
||||
o.ExternalReference = {name: 'ɵɵstylePropInterpolateV', moduleName: CORE};
|
||||
|
||||
static stylingApply: o.ExternalReference = {name: 'ɵɵstylingApply', moduleName: CORE};
|
||||
|
||||
static styleSanitizer: o.ExternalReference = {name: 'ɵɵstyleSanitizer', moduleName: CORE};
|
||||
|
||||
static elementHostAttrs: o.ExternalReference = {name: 'ɵɵelementHostAttrs', moduleName: CORE};
|
||||
|
@ -713,16 +713,6 @@ function createHostBindingsFunction(
|
||||
}
|
||||
|
||||
if (styleBuilder.hasBindings) {
|
||||
// singular style/class bindings (things like `[style.prop]` and `[class.name]`)
|
||||
// MUST be registered on a given element within the component/directive
|
||||
// templateFn/hostBindingsFn functions. The instruction below will figure out
|
||||
// what all the bindings are and then generate the statements required to register
|
||||
// those bindings to the element via `styling`.
|
||||
const stylingInstruction = styleBuilder.buildStylingInstruction(null, constantPool);
|
||||
if (stylingInstruction) {
|
||||
createStatements.push(createStylingStmt(stylingInstruction, bindingContext, bindingFn));
|
||||
}
|
||||
|
||||
// finally each binding that was registered in the statement above will need to be added to
|
||||
// the update block of a component/directive templateFn/hostBindingsFn so that the bindings
|
||||
// are evaluated and updated for the element.
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
import {ConstantPool} from '../../constant_pool';
|
||||
import {AttributeMarker} from '../../core';
|
||||
import {AST, BindingType, Interpolation} from '../../expression_parser/ast';
|
||||
import {AST, ASTWithSource, BindingPipe, BindingType, Interpolation} from '../../expression_parser/ast';
|
||||
import * as o from '../../output/output_ast';
|
||||
import {ParseSourceSpan} from '../../parse_util';
|
||||
import {isEmptyExpression} from '../../template_parser/template_parser';
|
||||
@ -68,7 +68,6 @@ interface BoundStylingEntry {
|
||||
* classMap(...)
|
||||
* styleProp(...)
|
||||
* classProp(...)
|
||||
* stylingApply(...)
|
||||
* }
|
||||
*
|
||||
* The creation/update methods within the builder class produce these instructions.
|
||||
@ -81,6 +80,7 @@ export class StylingBuilder {
|
||||
* (i.e. `[style]`, `[class]`, `[style.prop]` or `[class.name]`)
|
||||
*/
|
||||
public hasBindings = false;
|
||||
public hasBindingsWithPipes = false;
|
||||
|
||||
/** the input for [class] (if it exists) */
|
||||
private _classMapInput: BoundStylingEntry|null = null;
|
||||
@ -187,6 +187,7 @@ export class StylingBuilder {
|
||||
}
|
||||
this._lastStylingInput = entry;
|
||||
this._firstStylingInput = this._firstStylingInput || entry;
|
||||
this._checkForPipes(value);
|
||||
this.hasBindings = true;
|
||||
return entry;
|
||||
}
|
||||
@ -207,10 +208,17 @@ export class StylingBuilder {
|
||||
}
|
||||
this._lastStylingInput = entry;
|
||||
this._firstStylingInput = this._firstStylingInput || entry;
|
||||
this._checkForPipes(value);
|
||||
this.hasBindings = true;
|
||||
return entry;
|
||||
}
|
||||
|
||||
private _checkForPipes(value: AST) {
|
||||
if ((value instanceof ASTWithSource) && (value.ast instanceof BindingPipe)) {
|
||||
this.hasBindingsWithPipes = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the element's static style string value to the builder.
|
||||
*
|
||||
@ -284,25 +292,6 @@ export class StylingBuilder {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an instruction with all the expressions and parameters for `styling`.
|
||||
*
|
||||
* The instruction generation code below is used for producing the AOT statement code which is
|
||||
* responsible for registering style/class bindings to an element.
|
||||
*/
|
||||
buildStylingInstruction(sourceSpan: ParseSourceSpan|null, constantPool: ConstantPool):
|
||||
StylingInstruction|null {
|
||||
if (this.hasBindings) {
|
||||
return {
|
||||
sourceSpan,
|
||||
allocateBindingSlots: 0,
|
||||
reference: R3.styling,
|
||||
params: () => [],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an instruction with all the expressions and parameters for `classMap`.
|
||||
*
|
||||
@ -422,15 +411,6 @@ export class StylingBuilder {
|
||||
return [];
|
||||
}
|
||||
|
||||
private _buildApplyFn(): StylingInstruction {
|
||||
return {
|
||||
sourceSpan: this._lastStylingInput ? this._lastStylingInput.sourceSpan : null,
|
||||
reference: R3.stylingApply,
|
||||
allocateBindingSlots: 0,
|
||||
params: () => { return []; }
|
||||
};
|
||||
}
|
||||
|
||||
private _buildSanitizerFn(): StylingInstruction {
|
||||
return {
|
||||
sourceSpan: this._firstStylingInput ? this._firstStylingInput.sourceSpan : null,
|
||||
@ -460,7 +440,6 @@ export class StylingBuilder {
|
||||
}
|
||||
instructions.push(...this._buildStyleInputs(valueConverter));
|
||||
instructions.push(...this._buildClassInputs(valueConverter));
|
||||
instructions.push(this._buildApplyFn());
|
||||
}
|
||||
return instructions;
|
||||
}
|
||||
|
@ -623,11 +623,10 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
const hasChildren = (!isI18nRootElement && this.i18n) ? !hasTextChildrenOnly(element.children) :
|
||||
element.children.length > 0;
|
||||
|
||||
const createSelfClosingInstruction = !stylingBuilder.hasBindings &&
|
||||
const createSelfClosingInstruction = !stylingBuilder.hasBindingsWithPipes &&
|
||||
element.outputs.length === 0 && i18nAttrs.length === 0 && !hasChildren;
|
||||
|
||||
const createSelfClosingI18nInstruction = !createSelfClosingInstruction &&
|
||||
!stylingBuilder.hasBindings && hasTextChildrenOnly(element.children);
|
||||
const createSelfClosingI18nInstruction =
|
||||
!createSelfClosingInstruction && hasTextChildrenOnly(element.children);
|
||||
|
||||
if (createSelfClosingInstruction) {
|
||||
this.creationInstruction(
|
||||
@ -681,16 +680,6 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
}
|
||||
}
|
||||
|
||||
// The style bindings code is placed into two distinct blocks within the template function AOT
|
||||
// code: creation and update. The creation code contains the `styling` instructions
|
||||
// which will apply the collected binding values to the element. `styling` is
|
||||
// designed to run inside of `elementStart` and `elementEnd`. The update instructions
|
||||
// (things like `styleProp`, `classProp`, etc..) are applied later on in this
|
||||
// file
|
||||
this.processStylingInstruction(
|
||||
elementIndex,
|
||||
stylingBuilder.buildStylingInstruction(element.sourceSpan, this.constantPool), true);
|
||||
|
||||
// Generate Listeners (outputs)
|
||||
element.outputs.forEach((outputAst: t.BoundEvent) => {
|
||||
this.creationInstruction(
|
||||
|
Reference in New Issue
Block a user