@@ -30,7 +30,7 @@ class ShadowDomComponentFactory implements ComponentFactory {
3030
3131 ShadowDomComponentFactory (this ._expando);
3232
33- final Map <String , async.Future <dom.StyleElement >> _styleElementCache = {};
33+ final Map <_ComponentAssetKey , async.Future <dom.StyleElement >> _styleElementCache = {};
3434
3535 FactoryFn call (dom.Node node, DirectiveRef ref) {
3636 return (Injector injector) {
@@ -42,8 +42,15 @@ class ShadowDomComponentFactory implements ComponentFactory {
4242 DirectiveMap directives = injector.get (DirectiveMap );
4343 NgBaseCss baseCss = injector.get (NgBaseCss );
4444 // This is a bit of a hack since we are returning different type then we are.
45- var componentFactory = new _ComponentFactory (node, ref.type, component,
46- injector.get (dom.NodeTreeSanitizer ), _expando, baseCss, _styleElementCache);
45+ var componentFactory = new _ComponentFactory (node,
46+ ref.type,
47+ component,
48+ injector.get (dom.NodeTreeSanitizer ),
49+ injector.get (WebPlatform ),
50+ injector.get (ComponentCssRewriter ),
51+ _expando,
52+ baseCss,
53+ _styleElementCache);
4754 var controller = componentFactory.call (injector, scope, viewCache, http, templateCache,
4855 directives);
4956
@@ -67,15 +74,19 @@ class _ComponentFactory implements Function {
6774 final dom.NodeTreeSanitizer treeSanitizer;
6875 final Expando _expando;
6976 final NgBaseCss _baseCss;
70- final Map <String , async.Future <dom.StyleElement >> _styleElementCache;
77+ final Map <_ComponentAssetKey , async.Future <dom.StyleElement >>
78+ _styleElementCache;
79+ final ComponentCssRewriter componentCssRewriter;
80+ final WebPlatform platform;
7181
7282 dom.ShadowRoot shadowDom;
7383 Scope shadowScope;
7484 Injector shadowInjector;
7585 var controller;
7686
7787 _ComponentFactory (this .element, this .type, this .component, this .treeSanitizer,
78- this ._expando, this ._baseCss, this ._styleElementCache);
88+ this .platform, this .componentCssRewriter, this ._expando,
89+ this ._baseCss, this ._styleElementCache);
7990
8091 dynamic call (Injector injector, Scope scope,
8192 ViewCache viewCache, Http http, TemplateCache templateCache,
@@ -92,22 +103,57 @@ class _ComponentFactory implements Function {
92103 // better work around is found.
93104 Iterable <async.Future <dom.StyleElement >> cssFutures;
94105 var cssUrls = []..addAll (_baseCss.urls)..addAll (component.cssUrls);
106+ var tag = element.tagName.toLowerCase ();
95107 if (cssUrls.isNotEmpty) {
96- cssFutures = cssUrls.map ((cssUrl) => _styleElementCache.putIfAbsent (cssUrl, () =>
108+ cssFutures = cssUrls.map ((cssUrl) => _styleElementCache.putIfAbsent (
109+ new _ComponentAssetKey (tag, cssUrl), () =>
97110 http.get (cssUrl, cache: templateCache)
98111 .then ((resp) => resp.responseText,
99112 onError: (e) => '/*\n $e \n */\n ' )
100- .then ((styleContent) => new dom.StyleElement ()..appendText (styleContent))
113+ .then ((String css) {
114+
115+ // Shim CSS if required
116+ if (platform.cssShimRequired) {
117+ css = platform.shimCss (css, selector: tag, cssUrl: cssUrl);
118+ }
119+
120+ // If a css rewriter is installed, run the css through a rewriter
121+ var styleElement = new dom.StyleElement ()
122+ ..appendText (componentCssRewriter (css, selector: tag,
123+ cssUrl: cssUrl));
124+
125+ // ensure there are no invalid tags or modifications
126+ treeSanitizer.sanitizeTree (styleElement);
127+
128+ // If the css shim is required, it means that scoping does not
129+ // work, and adding the style to the head of the document is
130+ // preferrable.
131+ if (platform.cssShimRequired) {
132+ dom.document.head.append (styleElement);
133+ }
134+
135+ return styleElement;
136+ })
101137 )).toList ();
102138 } else {
103139 cssFutures = [new async .Future .value (null )];
104140 }
105- var viewFuture = ComponentFactory ._viewFuture (component, viewCache, directives);
141+
142+ var platformViewCache = new PlatformViewCache (viewCache, tag, platform);
143+
144+ var viewFuture = ComponentFactory ._viewFuture (component, platformViewCache,
145+ directives);
146+
106147 TemplateLoader templateLoader = new TemplateLoader (
107148 async .Future .wait (cssFutures).then ((Iterable <dom.StyleElement > cssList) {
108- cssList
109- .where ((styleElement) => styleElement != null )
110- .forEach ((styleElement) => shadowDom.append (styleElement.clone (true )));
149+ // This prevents style duplication by only adding css to the shadow
150+ // root if there is a native implementation of shadow dom.
151+ if (! platform.cssShimRequired) {
152+ cssList.where ((styleElement) => styleElement != null )
153+ .forEach ((styleElement) {
154+ shadowDom.append (styleElement.clone (true ));
155+ });
156+ }
111157 if (viewFuture != null ) {
112158 return viewFuture.then ((ViewFactory viewFactory) {
113159 return (! shadowScope.isAttached) ?
@@ -144,3 +190,33 @@ class _ComponentFactory implements Function {
144190 return shadowInjector;
145191 }
146192}
193+
194+ class _ComponentAssetKey {
195+ final String tag;
196+ final String assetUrl;
197+
198+ final String _key;
199+
200+ _ComponentAssetKey (String tag, String assetUrl)
201+ : _key = "$tag |$assetUrl " ,
202+ this .tag = tag,
203+ this .assetUrl = assetUrl;
204+
205+ @override
206+ String toString () => _key;
207+
208+ @override
209+ int get hashCode => _key.hashCode;
210+
211+ bool operator == (key) =>
212+ key is _ComponentAssetKey
213+ && tag == key.tag
214+ && assetUrl == key.assetUrl;
215+ }
216+
217+ @Injectable ()
218+ class ComponentCssRewriter {
219+ String call (String css, { String selector, String cssUrl} ) {
220+ return css;
221+ }
222+ }
0 commit comments