Skip to content

Commit 1c4d233

Browse files
vicbyjbanov
authored andcommitted
fix(ShadowDomStrategy): always inline import rules
fixes angular#1694
1 parent d575915 commit 1c4d233

File tree

9 files changed

+149
-43
lines changed

9 files changed

+149
-43
lines changed

modules/angular2/src/core/application.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
108108
},
109109
[NgZone]),
110110
bind(ShadowDomStrategy)
111-
.toFactory((styleUrlResolver, doc) =>
112-
new EmulatedUnscopedShadowDomStrategy(styleUrlResolver, doc.head),
113-
[StyleUrlResolver, DOCUMENT_TOKEN]),
111+
.toFactory((styleInliner, styleUrlResolver, doc) => new EmulatedUnscopedShadowDomStrategy(
112+
styleInliner, styleUrlResolver, doc.head),
113+
[StyleInliner, StyleUrlResolver, DOCUMENT_TOKEN]),
114114
DomRenderer,
115115
DefaultDomCompiler,
116116
bind(Renderer).toAlias(DomRenderer),

modules/angular2/src/render/dom/shadow_dom/emulated_scoped_shadow_dom_strategy.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ import {
2727
* - see `ShadowCss` for more information and limitations.
2828
*/
2929
export class EmulatedScopedShadowDomStrategy extends EmulatedUnscopedShadowDomStrategy {
30-
constructor(public styleInliner: StyleInliner, styleUrlResolver: StyleUrlResolver, styleHost) {
31-
super(styleUrlResolver, styleHost);
30+
styleInliner: StyleInliner;
31+
32+
constructor(styleInliner: StyleInliner, styleUrlResolver: StyleUrlResolver, styleHost) {
33+
super(styleInliner, styleUrlResolver, styleHost);
34+
this.styleInliner = styleInliner;
3235
}
3336

3437
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
@@ -37,20 +40,21 @@ export class EmulatedScopedShadowDomStrategy extends EmulatedUnscopedShadowDomSt
3740
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
3841
var inlinedCss = this.styleInliner.inlineImports(cssText, templateUrl);
3942

43+
var ret = null;
4044
if (isPromise(inlinedCss)) {
4145
DOM.setText(styleEl, '');
42-
return (<Promise<string>>inlinedCss)
43-
.then((css) => {
44-
css = shimCssForComponent(css, hostComponentId);
45-
DOM.setText(styleEl, css);
46-
this._moveToStyleHost(styleEl);
47-
});
46+
ret = (<Promise<string>>inlinedCss)
47+
.then((css) => {
48+
css = shimCssForComponent(css, hostComponentId);
49+
DOM.setText(styleEl, css);
50+
});
4851
} else {
4952
var css = shimCssForComponent(<string>inlinedCss, hostComponentId);
5053
DOM.setText(styleEl, css);
51-
this._moveToStyleHost(styleEl);
52-
return null;
5354
}
55+
56+
this._moveToStyleHost(styleEl);
57+
return ret;
5458
}
5559

5660
_moveToStyleHost(styleEl) {

modules/angular2/src/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {isPromise} from 'angular2/src/facade/lang';
12
import {Promise} from 'angular2/src/facade/async';
23

34
import {DOM} from 'angular2/src/dom/dom_adapter';
@@ -7,6 +8,7 @@ import * as viewModule from '../view/view';
78
import {LightDom} from './light_dom';
89
import {ShadowDomStrategy} from './shadow_dom_strategy';
910
import {StyleUrlResolver} from './style_url_resolver';
11+
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
1012
import {insertSharedStyleText} from './util';
1113

1214
/**
@@ -19,7 +21,10 @@ import {insertSharedStyleText} from './util';
1921
* - you can **not** use shadow DOM specific selectors in the styles
2022
*/
2123
export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
22-
constructor(public styleUrlResolver: StyleUrlResolver, public styleHost) { super(); }
24+
constructor(public styleInliner: StyleInliner, public styleUrlResolver: StyleUrlResolver,
25+
public styleHost) {
26+
super();
27+
}
2328

2429
hasNativeContentElement(): boolean { return false; }
2530

@@ -31,11 +36,19 @@ export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
3136

3237
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
3338
var cssText = DOM.getText(styleEl);
39+
3440
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
35-
DOM.setText(styleEl, cssText);
36-
DOM.remove(styleEl);
41+
var inlinedCss = this.styleInliner.inlineImports(cssText, templateUrl);
42+
43+
var ret = null;
44+
if (isPromise(inlinedCss)) {
45+
DOM.setText(styleEl, '');
46+
ret = (<Promise<string>>inlinedCss).then(css => { DOM.setText(styleEl, css); });
47+
} else {
48+
DOM.setText(styleEl, <string>inlinedCss);
49+
}
3750

3851
insertSharedStyleText(cssText, this.styleHost, styleEl);
39-
return null;
52+
return ret;
4053
}
4154
}
Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import {isPromise} from 'angular2/src/facade/lang';
12
import {Promise} from 'angular2/src/facade/async';
23
import {Injectable} from 'angular2/di';
34

45
import {DOM} from 'angular2/src/dom/dom_adapter';
56

67
import {StyleUrlResolver} from './style_url_resolver';
78
import {ShadowDomStrategy} from './shadow_dom_strategy';
9+
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
810

911
/**
1012
* This strategies uses the native Shadow DOM support.
@@ -14,14 +16,23 @@ import {ShadowDomStrategy} from './shadow_dom_strategy';
1416
*/
1517
@Injectable()
1618
export class NativeShadowDomStrategy extends ShadowDomStrategy {
17-
constructor(public styleUrlResolver: StyleUrlResolver) { super(); }
19+
constructor(public styleInliner: StyleInliner, public styleUrlResolver: StyleUrlResolver) {
20+
super();
21+
}
1822

1923
prepareShadowRoot(el) { return DOM.createShadowRoot(el); }
2024

2125
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
2226
var cssText = DOM.getText(styleEl);
27+
2328
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
24-
DOM.setText(styleEl, cssText);
25-
return null;
29+
var inlinedCss = this.styleInliner.inlineImports(cssText, templateUrl);
30+
31+
if (isPromise(inlinedCss)) {
32+
return (<Promise<string>>inlinedCss).then(css => { DOM.setText(styleEl, css); });
33+
} else {
34+
DOM.setText(styleEl, <string>inlinedCss);
35+
return null;
36+
}
2637
}
2738
}

modules/angular2/src/test_lib/test_injector.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ function _getAppBindings() {
8585
bind(DOCUMENT_TOKEN)
8686
.toValue(appDoc),
8787
bind(ShadowDomStrategy)
88-
.toFactory((styleUrlResolver, doc) =>
89-
new EmulatedUnscopedShadowDomStrategy(styleUrlResolver, doc.head),
90-
[StyleUrlResolver, DOCUMENT_TOKEN]),
88+
.toFactory((styleInliner, styleUrlResolver, doc) => new EmulatedUnscopedShadowDomStrategy(
89+
styleInliner, styleUrlResolver, doc.head),
90+
[StyleInliner, StyleUrlResolver, DOCUMENT_TOKEN]),
9191
DomRenderer,
9292
DefaultDomCompiler,
9393
bind(Renderer).toAlias(DomRenderer),

modules/angular2/test/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy_spec.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,26 @@ import {
2323
} from 'angular2/src/render/dom/shadow_dom/util';
2424
import {UrlResolver} from 'angular2/src/services/url_resolver';
2525
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
26+
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
27+
28+
import {isBlank} from 'angular2/src/facade/lang';
29+
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
30+
31+
import {XHR} from 'angular2/src/render/xhr';
2632

2733
export function main() {
2834
var strategy;
2935

3036
describe('EmulatedUnscopedShadowDomStrategy', () => {
31-
var styleHost;
37+
var xhr, styleHost;
3238

3339
beforeEach(() => {
3440
var urlResolver = new UrlResolver();
3541
var styleUrlResolver = new StyleUrlResolver(urlResolver);
42+
xhr = new FakeXHR();
43+
var styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
3644
styleHost = el('<div></div>');
37-
strategy = new EmulatedUnscopedShadowDomStrategy(styleUrlResolver, styleHost);
45+
strategy = new EmulatedUnscopedShadowDomStrategy(styleInliner, styleUrlResolver, styleHost);
3846
resetShadowDomCache();
3947
});
4048

@@ -49,11 +57,20 @@ export function main() {
4957
expect(styleElement).toHaveText(".foo {background-image: url('http://base/img.jpg');}");
5058
});
5159

52-
it('should not inline import rules', () => {
53-
var styleElement = el('<style>@import "other.css";</style>');
54-
strategy.processStyleElement('someComponent', 'http://base', styleElement);
55-
expect(styleElement).toHaveText("@import 'http://base/other.css';");
56-
});
60+
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
61+
xhr.reply('http://base/one.css', '.one {}');
62+
63+
var styleElement = el('<style>@import "one.css";</style>');
64+
var stylePromise =
65+
strategy.processStyleElement('someComponent', 'http://base', styleElement);
66+
expect(stylePromise).toBePromise();
67+
expect(styleElement).toHaveText('');
68+
69+
stylePromise.then((_) => {
70+
expect(styleElement).toHaveText('.one {}\n');
71+
async.done();
72+
});
73+
}));
5774

5875
it('should move the style element to the style host', () => {
5976
var compileElement = el('<div><style>.one {}</style></div>');
@@ -79,3 +96,23 @@ export function main() {
7996

8097
});
8198
}
99+
100+
class FakeXHR extends XHR {
101+
_responses: Map<string, string>;
102+
103+
constructor() {
104+
super();
105+
this._responses = MapWrapper.create();
106+
}
107+
108+
get(url: string): Promise<string> {
109+
var response = MapWrapper.get(this._responses, url);
110+
if (isBlank(response)) {
111+
return PromiseWrapper.reject('xhr error', null);
112+
}
113+
114+
return PromiseWrapper.resolve(response);
115+
}
116+
117+
reply(url: string, response: string) { MapWrapper.set(this._responses, url, response); }
118+
}

modules/angular2/test/render/dom/shadow_dom/native_shadow_dom_strategy_spec.ts

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,27 @@ import {
1717
} from 'angular2/src/render/dom/shadow_dom/native_shadow_dom_strategy';
1818
import {UrlResolver} from 'angular2/src/services/url_resolver';
1919
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
20+
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
21+
22+
import {XHR} from 'angular2/src/render/xhr';
23+
24+
import {isBlank} from 'angular2/src/facade/lang';
25+
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
26+
import {Map, MapWrapper} from 'angular2/src/facade/collection';
2027

2128
import {DOM} from 'angular2/src/dom/dom_adapter';
2229

2330
export function main() {
2431
var strategy;
2532

2633
describe('NativeShadowDomStrategy', () => {
34+
var xhr;
2735
beforeEach(() => {
2836
var urlResolver = new UrlResolver();
2937
var styleUrlResolver = new StyleUrlResolver(urlResolver);
30-
strategy = new NativeShadowDomStrategy(styleUrlResolver);
38+
xhr = new FakeXHR();
39+
var styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
40+
strategy = new NativeShadowDomStrategy(styleInliner, styleUrlResolver);
3141
});
3242

3343
if (DOM.supportsNativeShadowDOM()) {
@@ -44,10 +54,39 @@ export function main() {
4454
.toHaveText(".foo {" + "background-image: url('http://base/img.jpg');" + "}");
4555
});
4656

47-
it('should not inline import rules', () => {
48-
var styleElement = el('<style>@import "other.css";</style>');
49-
strategy.processStyleElement('someComponent', 'http://base', styleElement);
50-
expect(styleElement).toHaveText("@import 'http://base/other.css';");
51-
});
57+
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
58+
xhr.reply('http://base/one.css', '.one {}');
59+
60+
var styleElement = el('<style>@import "one.css";</style>');
61+
var stylePromise =
62+
strategy.processStyleElement('someComponent', 'http://base', styleElement);
63+
expect(stylePromise).toBePromise();
64+
65+
stylePromise.then((_) => {
66+
expect(styleElement).toHaveText('.one {}\n');
67+
async.done();
68+
});
69+
}));
70+
5271
});
5372
}
73+
74+
class FakeXHR extends XHR {
75+
_responses: Map<string, string>;
76+
77+
constructor() {
78+
super();
79+
this._responses = MapWrapper.create();
80+
}
81+
82+
get(url: string): Promise<string> {
83+
var response = MapWrapper.get(this._responses, url);
84+
if (isBlank(response)) {
85+
return PromiseWrapper.reject('xhr error', null);
86+
}
87+
88+
return PromiseWrapper.resolve(response);
89+
}
90+
91+
reply(url: string, response: string) { MapWrapper.set(this._responses, url, response); }
92+
}

modules/angular2/test/render/dom/shadow_dom_emulation_integration_spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ export function main() {
4343
.toFactory((styleInliner, styleUrlResolver) => new EmulatedScopedShadowDomStrategy(
4444
styleInliner, styleUrlResolver, styleHost),
4545
[StyleInliner, StyleUrlResolver]),
46-
"unscoped": bind(ShadowDomStrategy)
47-
.toFactory((styleUrlResolver) => new EmulatedUnscopedShadowDomStrategy(
48-
styleUrlResolver, styleHost),
49-
[StyleUrlResolver])
46+
"unscoped": bind(ShadowDomStrategy).toFactory(
47+
(styleInliner, styleUrlResolver) => new EmulatedUnscopedShadowDomStrategy(
48+
styleInliner, styleUrlResolver, null), [StyleInliner, StyleUrlResolver])
5049
};
5150
if (DOM.supportsNativeShadowDOM()) {
5251
StringMapWrapper.set(
5352
strategies, "native",
5453
bind(ShadowDomStrategy)
55-
.toFactory((styleUrlResolver) => new NativeShadowDomStrategy(styleUrlResolver),
56-
[StyleUrlResolver]));
54+
.toFactory((styleInliner, styleUrlResolver) =>
55+
new NativeShadowDomStrategy(styleInliner, styleUrlResolver),
56+
[StyleInliner, StyleUrlResolver]));
5757
}
5858
beforeEach(() => { styleHost = el('<div></div>'); });
5959

modules/benchmarks/src/compiler/compiler_benchmark.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
1717
import {TemplateResolver} from 'angular2/src/core/compiler/template_resolver';
1818
import {UrlResolver} from 'angular2/src/services/url_resolver';
1919
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
20+
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
2021
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
2122

2223
import {reflector} from 'angular2/src/reflection/reflection';
@@ -37,7 +38,8 @@ export function main() {
3738
count, [BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]);
3839
var urlResolver = new UrlResolver();
3940
var styleUrlResolver = new StyleUrlResolver(urlResolver);
40-
var shadowDomStrategy = new NativeShadowDomStrategy(styleUrlResolver);
41+
var styleInliner = new StyleInliner(null, styleUrlResolver, urlResolver);
42+
var shadowDomStrategy = new NativeShadowDomStrategy(styleInliner, styleUrlResolver);
4143
var renderCompiler = new rc.DefaultDomCompiler(new Parser(new Lexer()), shadowDomStrategy,
4244
new TemplateLoader(null, urlResolver));
4345
var compiler =

0 commit comments

Comments
 (0)