Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

Commit

Permalink
feat(compiler): useShadowDom option
Browse files Browse the repository at this point in the history
Closes #367
  • Loading branch information
jbdeboer committed Apr 22, 2014
1 parent f4893e0 commit c78d251
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 9 deletions.
13 changes: 11 additions & 2 deletions lib/core/annotation_src.dart
Expand Up @@ -308,6 +308,13 @@ class Component extends Directive {
@deprecated
final String publishAs;

/**
* If set to true, this component will always use shadow DOM.
* If set to false, this component will never use shadow DOM.
* If unset, the compiler's default construction strategy will be used
*/
final bool useShadowDom;

const Component({
this.template,
this.templateUrl,
Expand All @@ -320,7 +327,8 @@ class Component extends Directive {
selector,
visibility,
exportExpressions,
exportExpressionAttrs})
exportExpressionAttrs,
this.useShadowDom})
: _cssUrls = cssUrl,
_applyAuthorStyles = applyAuthorStyles,
_resetStyleInheritance = resetStyleInheritance,
Expand Down Expand Up @@ -349,7 +357,8 @@ class Component extends Directive {
selector: selector,
visibility: visibility,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);
exportExpressionAttrs: exportExpressionAttrs,
useShadowDom: useShadowDom);
}

/**
Expand Down
29 changes: 25 additions & 4 deletions lib/core_dom/element_binder.dart
Expand Up @@ -14,9 +14,13 @@ class TemplateElementBinder extends ElementBinder {
return _directiveCache = [template];
}

TemplateElementBinder(_perf, _expando, _parser, _componentFactory, this.template, this.templateBinder,
TemplateElementBinder(perf, expando, parser, componentFactory,
transcludingComponentFactory, shadowDomComponentFactory,
this.template, this.templateBinder,
onEvents, bindAttrs, childMode)
: super(_perf, _expando, _parser, _componentFactory, null, null, onEvents, bindAttrs, childMode);
: super(perf, expando, parser, componentFactory,
transcludingComponentFactory, shadowDomComponentFactory,
null, null, onEvents, bindAttrs, childMode);

String toString() => "[TemplateElementBinder template:$template]";

Expand All @@ -41,7 +45,11 @@ class ElementBinder {
final Profiler _perf;
final Expando _expando;
final Parser _parser;

// The default component factory
final ComponentFactory _componentFactory;
final TranscludingComponentFactory _transcludingComponentFactory;
final ShadowDomComponentFactory _shadowDomComponentFactory;
final Map onEvents;
final Map bindAttrs;

Expand All @@ -53,7 +61,11 @@ class ElementBinder {
// Can be either COMPILE_CHILDREN or IGNORE_CHILDREN
final String childMode;

ElementBinder(this._perf, this._expando, this._parser, this._componentFactory, this.component, this.decorators,
ElementBinder(this._perf, this._expando, this._parser,
this._componentFactory,
this._transcludingComponentFactory,
this._shadowDomComponentFactory,
this.component, this.decorators,
this.onEvents, this.bindAttrs, this.childMode);

final bool hasTemplate = false;
Expand Down Expand Up @@ -215,7 +227,16 @@ class ElementBinder {
}
nodesAttrsDirectives.add(ref);
} else if (ref.annotation is Component) {
nodeModule.factory(ref.type, _componentFactory.call(node, ref), visibility: visibility);
var factory;
var annotation = ref.annotation as Component;
if (annotation.useShadowDom == true) {
factory = _shadowDomComponentFactory;
} else if (annotation.useShadowDom == false) {
factory = _transcludingComponentFactory;
} else {
factory = _componentFactory;
}
nodeModule.factory(ref.type, factory.call(node, ref), visibility: visibility);
} else {
nodeModule.type(ref.type, visibility: visibility);
}
Expand Down
7 changes: 6 additions & 1 deletion lib/core_dom/element_binder_builder.dart
Expand Up @@ -6,17 +6,22 @@ class ElementBinderFactory {
final Profiler _perf;
final Expando _expando;
final ComponentFactory _componentFactory;
final TranscludingComponentFactory _transcludingComponentFactory;
final ShadowDomComponentFactory _shadowDomComponentFactory;

ElementBinderFactory(this._parser, this._perf, this._expando, this._componentFactory);
ElementBinderFactory(this._parser, this._perf, this._expando, this._componentFactory,
this._transcludingComponentFactory, this._shadowDomComponentFactory);

// TODO: Optimize this to re-use a builder.
ElementBinderBuilder builder() => new ElementBinderBuilder(this);

ElementBinder binder(ElementBinderBuilder b) =>
new ElementBinder(_perf, _expando, _parser, _componentFactory,
_transcludingComponentFactory, _shadowDomComponentFactory,
b.component, b.decorators, b.onEvents, b.bindAttrs, b.childMode);
TemplateElementBinder templateBinder(ElementBinderBuilder b, ElementBinder transclude) =>
new TemplateElementBinder(_perf, _expando, _parser, _componentFactory,
_transcludingComponentFactory, _shadowDomComponentFactory,
b.template, transclude, b.onEvents, b.bindAttrs, b.childMode);
}

Expand Down
4 changes: 3 additions & 1 deletion lib/core_dom/module_internal.dart
Expand Up @@ -57,9 +57,11 @@ class CoreDomModule extends Module {
type(Compiler, implementedBy: TaggingCompiler);

type(ComponentFactory, implementedBy: ShadowDomComponentFactory);
type(ShadowDomComponentFactory);
type(TranscludingComponentFactory);
type(_Content);
value(_ContentPort, null);

type(Http);
type(UrlRewriter);
type(HttpBackend);
Expand Down
3 changes: 2 additions & 1 deletion test/core/annotation_src_spec.dart
Expand Up @@ -45,7 +45,8 @@ void main() => describe('annotations', () {
selector: '',
visibility: Directive.LOCAL_VISIBILITY,
exportExpressions: [],
exportExpressionAttrs: []
exportExpressionAttrs: [],
useShadowDom: true
);

// Check that no fields are null
Expand Down
50 changes: 50 additions & 0 deletions test/core_dom/compiler_spec.dart
Expand Up @@ -618,6 +618,35 @@ void main() {
}).toThrow('Unknown selector format \'buttonbar button\' for InvalidSelector');
});
});

describe('useShadowDom option', () {
beforeEachModule((Module m) {
m.type(ShadowyComponent);
m.type(ShadowlessComponent);
});

it('should create shadowy components', async((Logger log) {
_.compile('<shadowy></shadowy>');
expect(log).toEqual(['shadowy']);
expect(_.rootElement.shadowRoot).toBeNotNull();
}));

it('should create shadowless components', async((Logger log) {
_.compile('<shadowless></shadowless>');
expect(log).toEqual(['shadowless']);
expect(_.rootElement.shadowRoot).toBeNull();
}));

it('should create other components with the default strategy', async((ComponentFactory factory) {
_.compile('<simple></simple>');
if (factory is TranscludingComponentFactory) {
expect(_.rootElement.shadowRoot).toBeNull();
} else {
expect(factory is ShadowDomComponentFactory).toBeTruthy();
expect(_.rootElement.shadowRoot).toBeNotNull();
}
}));
});
});


Expand Down Expand Up @@ -807,6 +836,27 @@ class SimpleComponent {
}
}

@Component(
selector: 'shadowy',
template: r'With shadow DOM',
useShadowDom: true
)
class ShadowyComponent {
ShadowyComponent(Logger log) {
log('shadowy');
}
}

@Component(
selector: 'shadowless',
template: r'Without shadow DOM',
useShadowDom: false
)
class ShadowlessComponent {
ShadowlessComponent(Logger log) {
log('shadowless');
}
}

@Component(
selector: 'sometimes',
Expand Down

0 comments on commit c78d251

Please sign in to comment.