refactor(ivy): remove styling state storage and introduce direct style writing (#32259) (#32596)

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:
Matias Niemelä
2019-09-09 13:14:26 -07:00
parent 55b55e7c97
commit 15aeab1620
46 changed files with 1728 additions and 1614 deletions

View File

@ -9,7 +9,7 @@
import {NgForOfContext} from '@angular/common';
import {ɵɵdefineComponent} from '../../src/render3/definition';
import {RenderFlags, ɵɵattribute, ɵɵclassMap, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵproperty, ɵɵselect, ɵɵstyleMap, ɵɵstyleProp, ɵɵstyleSanitizer, ɵɵstyling, ɵɵstylingApply, ɵɵtemplate, ɵɵtext, ɵɵtextInterpolate1} from '../../src/render3/index';
import {RenderFlags, ɵɵattribute, ɵɵclassMap, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵproperty, ɵɵselect, ɵɵstyleMap, ɵɵstyleProp, ɵɵstyleSanitizer, ɵɵtemplate, ɵɵtext, ɵɵtextInterpolate1} from '../../src/render3/index';
import {AttributeMarker} from '../../src/render3/interfaces/node';
import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, getSanitizationBypassType, unwrapSafeValue} from '../../src/sanitization/bypass';
import {ɵɵdefaultStyleSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl} from '../../src/sanitization/sanitization';
@ -20,11 +20,7 @@ import {NgForOf} from './common_with_def';
import {ComponentFixture, TemplateFixture} from './render_util';
describe('instructions', () => {
function createAnchor() {
ɵɵelementStart(0, 'a');
ɵɵstyling();
ɵɵelementEnd();
}
function createAnchor() { ɵɵelement(0, 'a'); }
function createDiv(initialClasses?: string[] | null, initialStyles?: string[] | null) {
const attrs: any[] = [];
@ -34,9 +30,7 @@ describe('instructions', () => {
if (initialStyles) {
attrs.push(AttributeMarker.Styles, ...initialStyles);
}
ɵɵelementStart(0, 'div', attrs);
ɵɵstyling();
ɵɵelementEnd();
ɵɵelement(0, 'div', attrs);
}
function createScript() { ɵɵelement(0, 'script'); }
@ -156,7 +150,6 @@ describe('instructions', () => {
t.update(() => {
ɵɵstyleSanitizer(ɵɵdefaultStyleSanitizer);
ɵɵstyleProp('background-image', 'url("http://server")');
ɵɵstylingApply();
});
// nothing is set because sanitizer suppresses it.
expect(t.html).toEqual('<div></div>');
@ -164,7 +157,6 @@ describe('instructions', () => {
t.update(() => {
ɵɵstyleSanitizer(ɵɵdefaultStyleSanitizer);
ɵɵstyleProp('background-image', bypassSanitizationTrustStyle('url("http://server2")'));
ɵɵstylingApply();
});
expect((t.hostElement.firstChild as HTMLElement).style.getPropertyValue('background-image'))
.toEqual('url("http://server2")');
@ -173,17 +165,12 @@ describe('instructions', () => {
describe('styleMap', () => {
function createDivWithStyle() {
ɵɵelementStart(0, 'div', [AttributeMarker.Styles, 'height', '10px']);
ɵɵstyling();
ɵɵelementEnd();
ɵɵelement(0, 'div', [AttributeMarker.Styles, 'height', '10px']);
}
it('should add style', () => {
const fixture = new TemplateFixture(createDivWithStyle, () => {}, 1);
fixture.update(() => {
ɵɵstyleMap({'background-color': 'red'});
ɵɵstylingApply();
});
fixture.update(() => { ɵɵstyleMap({'background-color': 'red'}); });
expect(fixture.html).toEqual('<div style="background-color: red; height: 10px;"></div>');
});
@ -205,7 +192,6 @@ describe('instructions', () => {
'filter': 'filter',
'width': 'width'
});
ɵɵstylingApply();
});
const props = detectedValues.sort();
@ -216,18 +202,11 @@ describe('instructions', () => {
});
describe('elementClass', () => {
function createDivWithStyling() {
ɵɵelementStart(0, 'div');
ɵɵstyling();
ɵɵelementEnd();
}
function createDivWithStyling() { ɵɵelement(0, 'div'); }
it('should add class', () => {
const fixture = new TemplateFixture(createDivWithStyling, () => {}, 1);
fixture.update(() => {
ɵɵclassMap('multiple classes');
ɵɵstylingApply();
});
fixture.update(() => { ɵɵclassMap('multiple classes'); });
expect(fixture.html).toEqual('<div class="classes multiple"></div>');
});
});