aurelia / aurelia/framework

Custom attribute causes custom element styles to be re-injected into head

Open
#805 3 comments 0 reactions 0 assignees View on GitHub
bug help wanted
Dominant language
TypeScript
Stars
11.7k
Forks
608
PR merge metrics
No merged PRs in 30d

Description

**I'm submitting a bug report**

From [stack overflow](https://stackoverflow.com/q/45112582/762175) by request of @AshleyGrant.

* **Library Version:**
* bootstrapper: `^2.0.1`
* framework: `1.0.8`

**Please tell us about your environment:**
* **Operating System:**
Windows 10

* **Node Version:**
7.7.3

* **NPM Version:**
4.1.2

* **JSPM**
JSPM 0.17.0-beta.42

* **Browser:**
Chrome 59 (no other supported browser supports Shadow DOM)

* **Language:**
ESNext

**Current behavior:**
Shadow DOM scoped CSS includes are injected into the shadow root _and into ``_.

**Expected/desired behavior:**
Shadow DOM scoped CSS includes are injected _only_ into the shadow root.

---

**From Stack Overflow:**
In my aurelia application, one of my custom elements `panel` (shadow DOM) includes another custom element `widget` (shadow DOM) that has a custom attribute `own-attribute` (template controller) on it. `panel` has a scoped stylesheet (``). While compiling, aurelia correctly injects `./panel.css` into the shadow root of `panel`. However, in a separate step, while compiling `own-context` on `widget` within `panel`, aurelia injects `./panel.css` into ``, thus breaking the abstraction of custom element stylesheets and generally playing havoc with my app.

How do I fix this?

I tried making a plunker [here](https://embed.plnkr.co/L065Tu/) but it doesn't work. I'm using ES2017 so that makes life more complicated.

---

- `panel` is being compiled by [`ViewCompiler.compile()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L77)
- This [calls `ViewCompiler._compileNode()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L98)
- This [calls itself](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L153) on `widget`
- This [calls `ViewCompiler._compileElement()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L129) on `widget`
- This detects `own-context` as a "lifting instruction" and [calls `HtmlBehaviorResource.compile()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L417)
- This [calls `ViewCompiler.compile()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/html-behavior.js#L238) on `widget`
- As a [`beforeCompile` `invokeHook`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L95), [`CSSViewEngineHooks.beforeCompile()`](https://github.com/aurelia/templating-resources/blob/master/src/css-resource.js#L64), is called, which injects a bunch of styles into ``

This is an issue. `HtmlBehaviorResource.compile()`'s call to `ViewResource.compile()` does not pass a compile instruction, so the latter uses the default. Thus the CSS hooks don't get the message that they should be injecting into the shadow root. Not to mention this is double-injecting these styles for no good reason.

at eval (eval at injectStyles (http://example.com/jspm/npm/aurelia-pal-browser@1.1.0/aurelia-pal-browser.js), :1:11)
at Object.injectStyles (http://example.com/jspm/npm/aurelia-pal-browser@1.1.0/aurelia-pal-browser.js:434:27)
at ViewCSS.beforeCompile (http://example.com/jspm/npm/aurelia-templating-resources@1.2.0/css-resource.js:105:25)
at ViewResources._invokeHook (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:1281:25)
at ViewCompiler.compile (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2509:17)
at HtmlBehaviorResource.compile (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:3972:46)
at ViewCompiler._compileElement (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2813:40)
at ViewCompiler._compileNode (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2543:23)
at ViewCompiler._compileNode (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2565:33)
at ViewCompiler.compile (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2512:12)

---

### panel.js

```javascript
import { useShadowDOM, customElement } from 'aurelia-templating';

export { PanelModule };

@useShadowDOM
@customElement('panel-elem')
class PanelModule {}
```

### panel.html

```html




some content

```

### widget.js

```javascript
import { useShadowDOM, customElement } from 'aurelia-templating';

export { WidgetModule };

@useShadowDOM
@customElement('widget-elem')
class WidgetModule {}
```

### widget.html

```html




```

### own-context.js

```javascript
import { inject, templateController, BoundViewFactory, ViewSlot } from 'aurelia-framework';
import { createOverrideContext } from 'aurelia-binding';

// from https://github.com/aurelia/templating/issues/411
@templateController
@inject(BoundViewFactory, ViewSlot)
class OwnContextCustomAttribute {
constructor(factory, slot) {
this.factory = factory;
this.slot = slot;
}

bind(bindingContext, overrideContext) {
let newContext = { };
overrideContext = createOverrideContext(newContext, overrideContext);

if (!this.view) {
this.view = this.factory.create();
this.view.bind(newContext, overrideContext);
this.slot.add(this.view);
} else {
this.view.bind(newContext, overrideContext);
}
}

unbind() {
if (this.view)
this.view.unbind();
}
}
```

Contributor guide

Open the contributing guide

Research direction

Start with ViewCompiler.compile(), ViewCompiler._compileNode(), ViewCompiler._compileElement(), and HtmlBehaviorResource.compile(), following the linked call chain into CSSViewEngineHooks.beforeCompile() in css-resource.js. Reproduce the panel/widget/own-context example and verify that scoped CSS is injected only into the shadow root, not duplicated in .

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.