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

perf(view factory): Compute DI Keys ahead of time #1085

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/core_dom/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ class MappingParts {
class DirectiveRef {
final dom.Node element;
final Type type;
final Key typeKey;
final Directive annotation;
final String value;
final mappings = new List<MappingParts>();

DirectiveRef(this.element, this.type, this.annotation, [ this.value ]);
DirectiveRef(this.element, this.type, this.annotation, this.typeKey, [ this.value ]);

String toString() {
var html = element is dom.Element
Expand Down
51 changes: 26 additions & 25 deletions lib/core_dom/element_binder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ class TemplateElementBinder extends ElementBinder {
_registerViewFactory(node, parentInjector, nodeModule) {
assert(templateViewFactory != null);
nodeModule
..bind(ViewPort, toFactory: (_) =>
new ViewPort(node, parentInjector.get(Animate)))
..bind(ViewFactory, toValue: templateViewFactory)
..bind(BoundViewFactory, toFactory: (Injector injector) =>
..bindByKey(_VIEW_PORT_KEY, toFactory: (_) =>
new ViewPort(node, parentInjector.getByKey(_ANIMATE_KEY)))
..bindByKey(_VIEW_FACTORY_KEY, toValue: templateViewFactory)
..bindByKey(_BOUND_VIEW_FACTORY_KEY, toFactory: (Injector injector) =>
templateViewFactory.bind(injector));
}
}
Expand Down Expand Up @@ -203,7 +203,7 @@ class ElementBinder {

void _link(nodeInjector, probe, scope, nodeAttrs, formatters) {
_usableDirectiveRefs.forEach((DirectiveRef ref) {
var directive = nodeInjector.get(ref.type);
var directive = nodeInjector.getByKey(ref.typeKey);
probe.directives.add(directive);

if (ref.annotation is Controller) {
Expand Down Expand Up @@ -240,18 +240,18 @@ class ElementBinder {
void _createDirectiveFactories(DirectiveRef ref, nodeModule, node, nodesAttrsDirectives, nodeAttrs,
visibility) {
if (ref.type == TextMustache) {
nodeModule.bind(TextMustache, toFactory: (Injector injector) {
return new TextMustache(node, ref.value, injector.get(Interpolate),
injector.get(Scope), injector.get(FormatterMap));
nodeModule.bindByKey(_TEXT_MUSTACHE_KEY, toFactory: (Injector injector) {
return new TextMustache(node, ref.value, injector.getByKey(_INTERPOLATE_KEY),
injector.getByKey(_SCOPE_KEY), injector.getByKey(_FORMATTER_MAP_KEY));
});
} else if (ref.type == AttrMustache) {
if (nodesAttrsDirectives.isEmpty) {
nodeModule.bind(AttrMustache, toFactory: (Injector injector) {
var scope = injector.get(Scope);
var interpolate = injector.get(Interpolate);
var scope = injector.getByKey(_SCOPE_KEY);
var interpolate = injector.getByKey(_INTERPOLATE_KEY);
for (var ref in nodesAttrsDirectives) {
new AttrMustache(nodeAttrs, ref.value, interpolate, scope,
injector.get(FormatterMap));
injector.getByKey(_FORMATTER_MAP_KEY));
}
});
}
Expand All @@ -266,23 +266,24 @@ class ElementBinder {
} else {
factory = _componentFactory;
}
nodeModule.bind(ref.type, toFactory: factory.call(node, ref), visibility: visibility);
nodeModule.bindByKey(ref.typeKey, toFactory: factory.call(node, ref), visibility: visibility);
} else {
nodeModule.bind(ref.type, visibility: visibility);
nodeModule.bindByKey(ref.typeKey, visibility: visibility);
}
}

// Overridden in TemplateElementBinder
void _registerViewFactory(node, parentInjector, nodeModule) {
nodeModule..bind(ViewPort, toValue: null)
..bind(ViewFactory, toValue: null)
..bind(BoundViewFactory, toValue: null);
nodeModule..bindByKey(_VIEW_PORT_KEY, toValue: null)
..bindByKey(_VIEW_FACTORY_KEY, toValue: null)
..bindByKey(_BOUND_VIEW_FACTORY_KEY, toValue: null);
}


Injector bind(View view, Injector parentInjector, dom.Node node) {
Injector nodeInjector;
Scope scope = parentInjector.get(Scope);
FormatterMap formatters = parentInjector.get(FormatterMap);
Scope scope = parentInjector.getByKey(_SCOPE_KEY);
FormatterMap formatters = parentInjector.getByKey(_FORMATTER_MAP_KEY);
var nodeAttrs = node is dom.Element ? new NodeAttrs(node) : null;
ElementProbe probe;

Expand All @@ -291,12 +292,12 @@ class ElementBinder {

var nodesAttrsDirectives = [];
var nodeModule = new Module()
..bind(NgElement)
..bind(View, toValue: view)
..bind(dom.Element, toValue: node)
..bind(dom.Node, toValue: node)
..bind(NodeAttrs, toValue: nodeAttrs)
..bind(ElementProbe, toFactory: (_) => probe);
..bindByKey(_NG_ELEMENT_KEY)
..bindByKey(_VIEW_KEY, toValue: view)
..bindByKey(_ELEMENT_KEY, toValue: node)
..bindByKey(_NODE_KEY, toValue: node)
..bindByKey(_NODE_ATTRS_KEY, toValue: nodeAttrs)
..bindByKey(_ELEMENT_PROBE_KEY, toFactory: (_) => probe);

directiveRefs.forEach((DirectiveRef ref) {
Directive annotation = ref.annotation;
Expand All @@ -317,7 +318,7 @@ class ElementBinder {

nodeInjector = parentInjector.createChild([nodeModule]);
probe = _expando[node] = new ElementProbe(
parentInjector.get(ElementProbe), node, nodeInjector, scope);
parentInjector.getByKey(_ELEMENT_PROBE_KEY), node, nodeInjector, scope);

_link(nodeInjector, probe, scope, nodeAttrs, formatters);

Expand Down
1 change: 1 addition & 0 deletions lib/core_dom/module_internal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ part 'transcluding_component_factory.dart';
part 'tree_sanitizer.dart';
part 'walking_compiler.dart';
part 'ng_element.dart';
part 'static_keys.dart';

class CoreDomModule extends Module {
CoreDomModule() {
Expand Down
6 changes: 3 additions & 3 deletions lib/core_dom/selector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class DirectiveSelector {
// the value. Yes it is a bit of a hack.
_directives[selectorRegExp.annotation].forEach((type) {
builder.addDirective(new DirectiveRef(
node, type, selectorRegExp.annotation, '$attrName=$value'));
node, type, selectorRegExp.annotation, new Key(type), '$attrName=$value'));
});
}
}
Expand Down Expand Up @@ -131,7 +131,7 @@ class DirectiveSelector {
if (selectorRegExp.regexp.hasMatch(value)) {
_directives[selectorRegExp.annotation].forEach((type) {
builder.addDirective(new DirectiveRef(node, type,
selectorRegExp.annotation, value));
selectorRegExp.annotation, new Key(type), value));
});
}
}
Expand Down Expand Up @@ -204,7 +204,7 @@ class _SelectorPart {
_addRefs(ElementBinderBuilder builder, List<_Directive> directives, dom.Node node,
[String attrValue]) {
directives.forEach((directive) {
builder.addDirective(new DirectiveRef(node, directive.type, directive.annotation, attrValue));
builder.addDirective(new DirectiveRef(node, directive.type, directive.annotation, new Key(directive.type), attrValue));
});
}

Expand Down
50 changes: 26 additions & 24 deletions lib/core_dom/shadow_dom_component_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,24 @@ class ShadowDomComponentFactory implements ComponentFactory {

final Map<_ComponentAssetKey, async.Future<dom.StyleElement>> _styleElementCache = {};



FactoryFn call(dom.Node node, DirectiveRef ref) {
return (Injector injector) {
var component = ref.annotation as Component;
Scope scope = injector.get(Scope);
ViewCache viewCache = injector.get(ViewCache);
Http http = injector.get(Http);
TemplateCache templateCache = injector.get(TemplateCache);
DirectiveMap directives = injector.get(DirectiveMap);
NgBaseCss baseCss = injector.get(NgBaseCss);
Scope scope = injector.getByKey(_SCOPE_KEY);
ViewCache viewCache = injector.getByKey(_VIEW_CACHE_KEY);
Http http = injector.getByKey(_HTTP_KEY);
TemplateCache templateCache = injector.getByKey(_TEMPLATE_CACHE_KEY);
DirectiveMap directives = injector.getByKey(_DIRECTIVE_MAP_KEY);
NgBaseCss baseCss = injector.getByKey(_NG_BASE_CSS_KEY);
// This is a bit of a hack since we are returning different type then we are.
var componentFactory = new _ComponentFactory(node,
ref.type,
ref.typeKey,
component,
injector.get(dom.NodeTreeSanitizer),
injector.get(WebPlatform),
injector.get(ComponentCssRewriter),
injector.getByKey(_NODE_TREE_SANITIZER_KEY),
injector.getByKey(_WEB_PLATFORM_KEY),
injector.getByKey(_COMPONENT_CSS_REWRITER_KEY),
_expando,
baseCss,
_styleElementCache);
Expand All @@ -70,7 +72,7 @@ class ShadowDomComponentFactory implements ComponentFactory {
class _ComponentFactory implements Function {

final dom.Element element;
final Type type;
final Key typeKey;
final Component component;
final dom.NodeTreeSanitizer treeSanitizer;
final Expando _expando;
Expand All @@ -85,7 +87,7 @@ class _ComponentFactory implements Function {
Injector shadowInjector;
var controller;

_ComponentFactory(this.element, this.type, this.component, this.treeSanitizer,
_ComponentFactory(this.element, this.typeKey, this.component, this.treeSanitizer,
this.platform, this.componentCssRewriter, this._expando,
this._baseCss, this._styleElementCache);

Expand Down Expand Up @@ -164,7 +166,7 @@ class _ComponentFactory implements Function {
}
return shadowDom;
}));
controller = createShadowInjector(injector, templateLoader).get(type);
controller = createShadowInjector(injector, templateLoader).getByKey(typeKey);
ComponentFactory._setupOnShadowDomAttach(controller, templateLoader, shadowScope);
return controller;
}
Expand All @@ -177,17 +179,17 @@ class _ComponentFactory implements Function {

Injector createShadowInjector(injector, TemplateLoader templateLoader) {
var probe;
var shadowModule = new Module()
..bind(type)
..bind(NgElement)
..bind(EventHandler, toImplementation: ShadowRootEventHandler)
..bind(Scope, toValue: shadowScope)
..bind(TemplateLoader, toValue: templateLoader)
..bind(dom.ShadowRoot, toValue: shadowDom)
..bind(ElementProbe, toFactory: (_) => probe);
shadowInjector = injector.createChild([shadowModule], name: SHADOW_DOM_INJECTOR_NAME);
var shadowModule = new Module()
..bindByKey(typeKey)
..bindByKey(_NG_ELEMENT_KEY)
..bindByKey(_EVENT_HANDLER_KEY, toImplementation: ShadowRootEventHandler)
..bindByKey(_SCOPE_KEY, toValue: shadowScope)
..bindByKey(_TEMPLATE_LOADER_KEY, toValue: templateLoader)
..bindByKey(_SHADOW_ROOT_KEY, toValue: shadowDom)
..bindByKey(_ELEMENT_PROBE, toFactory: (_) => probe);
shadowInjector = injector.createChild([shadowModule], name: SHADOW_DOM_INJECTOR_NAME);
probe = _expando[shadowDom] = new ElementProbe(
injector.get(ElementProbe), shadowDom, shadowInjector, shadowScope);
injector.getByKey(_ELEMENT_PROBE), shadowDom, shadowInjector, shadowScope);
return shadowInjector;
}
}
Expand Down Expand Up @@ -220,4 +222,4 @@ class ComponentCssRewriter {
String call(String css, { String selector, String cssUrl} ) {
return css;
}
}
}
30 changes: 30 additions & 0 deletions lib/core_dom/static_keys.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
part of angular.core.dom_internal;

// Keys used to call Injector.getByKey and Module.bindByKey

Key _ANIMATE_KEY = new Key(Animate);
Key _BOUND_VIEW_FACTORY_KEY = new Key(BoundViewFactory);
Key _COMPONENT_CSS_REWRITER_KEY = new Key(ComponentCssRewriter);
Key _DIRECTIVE_MAP_KEY = new Key(DirectiveMap);
Key _ELEMENT_KEY = new Key(dom.Element);
Key _ELEMENT_PROBE_KEY = new Key(ElementProbe);
Key _ELEMENT_PROBE = new Key(ElementProbe);
Key _EVENT_HANDLER_KEY = new Key(EventHandler);
Key _FORMATTER_MAP_KEY = new Key(FormatterMap);
Key _HTTP_KEY = new Key(Http);
Key _INTERPOLATE_KEY = new Key(Interpolate);
Key _NG_BASE_CSS_KEY = new Key(NgBaseCss);
Key _NG_ELEMENT_KEY = new Key(NgElement);
Key _NODE_ATTRS_KEY = new Key(NodeAttrs);
Key _NODE_KEY = new Key(dom.Node);
Key _NODE_TREE_SANITIZER_KEY = new Key(dom.NodeTreeSanitizer);
Key _SCOPE_KEY = new Key(Scope);
Key _SHADOW_ROOT_KEY = new Key(dom.ShadowRoot);
Key _TEMPLATE_CACHE_KEY = new Key(TemplateCache);
Key _TEMPLATE_LOADER_KEY = new Key(TemplateLoader);
Key _TEXT_MUSTACHE_KEY = new Key(TextMustache);
Key _VIEW_CACHE_KEY = new Key(ViewCache);
Key _VIEW_FACTORY_KEY = new Key(ViewFactory);
Key _VIEW_KEY = new Key(View);
Key _VIEW_PORT_KEY = new Key(ViewPort);
Key _WEB_PLATFORM_KEY = new Key(WebPlatform);
4 changes: 3 additions & 1 deletion lib/core_dom/tagging_view_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ class TaggingViewFactory implements ViewFactory {

BoundViewFactory bind(Injector injector) => new BoundViewFactory(this, injector);

static Key _EVENT_HANDLER_KEY = new Key(EventHandler);

View call(Injector injector, [List<dom.Node> nodes /* TODO: document fragment */]) {
if (nodes == null) {
nodes = cloneElements(templateNodes);
}
var timerId;
try {
assert((timerId = _perf.startTimer('ng.view')) != false);
var view = new View(nodes, injector.get(EventHandler));
var view = new View(nodes, injector.getByKey(_EVENT_HANDLER_KEY));
_link(view, nodes, injector);
return view;
} finally {
Expand Down
4 changes: 3 additions & 1 deletion lib/core_dom/view_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ class BoundViewFactory {

BoundViewFactory(this.viewFactory, this.injector);

static Key _SCOPE_KEY = new Key(Scope);

View call(Scope scope) =>
viewFactory(injector.createChild([new Module()..bind(Scope, toValue: scope)]));
viewFactory(injector.createChild([new Module()..bindByKey(_SCOPE_KEY, toValue: scope)]));
}

abstract class ViewFactory implements Function {
Expand Down
2 changes: 1 addition & 1 deletion test/core_dom/element_binder_builder_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ main() => describe('ElementBinderBuilder', () {
addDirective(selector) {
directives.forEach((Directive annotation, Type type) {
if (annotation.selector == selector)
b.addDirective(new DirectiveRef(node, type, annotation, null));
b.addDirective(new DirectiveRef(node, type, annotation, new Key(type), null));
});
b = b.binder;
}
Expand Down