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

Commit aabe363

Browse files
committed
Revert "fix(directive-injector): Pass the correct injector into nested views"
This reverts 59323da. Without a default implementation for DirectiveInjector, this results in a runtime exception (no provider found.) Issue #1244
1 parent d19d256 commit aabe363

31 files changed

+191
-237
lines changed

lib/application.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ abstract class Application {
180180
DirectiveMap directiveMap = injector.getByKey(DIRECTIVE_MAP_KEY);
181181
RootScope rootScope = injector.getByKey(ROOT_SCOPE_KEY);
182182
ViewFactory viewFactory = compiler(rootElements, directiveMap);
183-
viewFactory(rootScope, null, rootElements);
183+
viewFactory(rootScope, injector.get(DirectiveInjector), rootElements);
184184
} catch (e, s) {
185185
exceptionHandler(e, s);
186186
}

lib/core_dom/common.dart

+18
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,21 @@ class DirectiveRef {
4343
}
4444
}
4545

46+
/**
47+
* Creates a child injector that allows loading new directives, formatters and
48+
* services from the provided modules.
49+
*/
50+
Injector forceNewDirectivesAndFormatters(Injector injector, DirectiveInjector dirInjector,
51+
List<Module> modules) {
52+
modules.add(new Module()
53+
..bind(Scope, toFactory: (Injector injector) {
54+
var scope = injector.parent.getByKey(SCOPE_KEY);
55+
return scope.createChild(new PrototypeMap(scope.context));
56+
}, inject: [INJECTOR_KEY])
57+
..bind(DirectiveMap)
58+
..bind(FormatterMap)
59+
..bind(DirectiveInjector,
60+
toFactory: () => new DefaultDirectiveInjector.newAppInjector(dirInjector, injector)));
61+
62+
return new ModuleInjector(modules, injector);
63+
}

lib/core_dom/directive_injector.dart

+55-48
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ const int CONTENT_PORT_KEY_ID = 16;
5252
const int EVENT_HANDLER_KEY_ID = 17;
5353
const int KEEP_ME_LAST = 18;
5454

55-
EventHandler eventHandler(DirectiveInjector di) => di._eventHandler;
56-
5755
class DirectiveInjector implements DirectiveBinder {
5856
static bool _isInit = false;
5957
static initUID() {
@@ -102,8 +100,8 @@ class DirectiveInjector implements DirectiveBinder {
102100
, KEEP_ME_LAST
103101
];
104102

105-
final DirectiveInjector _parent;
106-
final Injector _appInjector;
103+
final DirectiveInjector parent;
104+
final Injector appInjector;
107105
final Node _node;
108106
final NodeAttrs _nodeAttrs;
109107
final Animate _animate;
@@ -142,8 +140,17 @@ class DirectiveInjector implements DirectiveBinder {
142140

143141
static Binding _temp_binding = new Binding();
144142

145-
DirectiveInjector(this._parent, this._appInjector, this._node, this._nodeAttrs, this._eventHandler,
146-
this.scope, this._animate);
143+
DirectiveInjector(parent, appInjector, this._node, this._nodeAttrs, this._eventHandler,
144+
this.scope, this._animate)
145+
: appInjector = appInjector,
146+
parent = parent == null ? new DefaultDirectiveInjector(appInjector) : parent;
147+
148+
DirectiveInjector._default(this.parent, this.appInjector)
149+
: _node = null,
150+
_nodeAttrs = null,
151+
_eventHandler = null,
152+
scope = null,
153+
_animate = null;
147154

148155
bind(key, {dynamic toValue: DEFAULT_VALUE,
149156
Function toFactory: DEFAULT_VALUE,
@@ -183,17 +190,12 @@ class DirectiveInjector implements DirectiveBinder {
183190
else { throw 'Maximum number of directives per element reached.'; }
184191
}
185192

186-
// Get a key from the directive injector chain. When it is exhausted, get from
187-
// the current application injector chain.
188193
Object get(Type type) => getByKey(new Key(type));
189194

190-
// Same behavior as get but skips the current injector.
191-
Object parentGet(Type type) => parentGetByKey(new Key(type));
192-
193195
Object getByKey(Key key) {
194196
var oldTag = _TAG_GET.makeCurrent();
195197
try {
196-
return _getByKey(key, _appInjector);
198+
return _getByKey(key);
197199
} on ResolvingError catch (e, s) {
198200
e.appendKey(key);
199201
rethrow;
@@ -202,15 +204,7 @@ class DirectiveInjector implements DirectiveBinder {
202204
}
203205
}
204206

205-
Object parentGetByKey(Key key) {
206-
if (_parent == null) {
207-
return _appInjector.getByKey(key);
208-
} else {
209-
return _parent._getByKey(key, _appInjector);
210-
}
211-
}
212-
213-
Object _getByKey(Key key, Injector appInjector) {
207+
Object _getByKey(Key key) {
214208
int uid = key.uid;
215209
if (uid == null || uid == UNDEFINED_ID) return appInjector.getByKey(key);
216210
bool isDirective = uid < 0;
@@ -230,10 +224,8 @@ class DirectiveInjector implements DirectiveBinder {
230224
if (_key8 == null) break; if (identical(_key8, k)) return _obj8 == null ? _obj8 = _new(_pKeys8, _factory8) : _obj8;
231225
if (_key9 == null) break; if (identical(_key9, k)) return _obj9 == null ? _obj9 = _new(_pKeys9, _factory9) : _obj9;
232226
} while (false);
233-
var parent = this._parent;
234-
if (parent == null) return i.getByKey(k);
235227
switch (visType) {
236-
case VISIBILITY_LOCAL: return i.getByKey(k);
228+
case VISIBILITY_LOCAL: return appInjector.getByKey(k);
237229
case VISIBILITY_DIRECT_CHILD: return parent._getDirectiveByKey(k, VISIBILITY_LOCAL, i);
238230
case VISIBILITY_CHILDREN: return parent._getDirectiveByKey(k, VISIBILITY_CHILDREN, i);
239231
// SHADOW
@@ -242,7 +234,6 @@ class DirectiveInjector implements DirectiveBinder {
242234
case VISIBILITY_COMPONENT_CHILDREN: return parent._getDirectiveByKey(k, VISIBILITY_CHILDREN, i);
243235
default: throw null;
244236
}
245-
246237
}
247238

248239
List get directives {
@@ -262,7 +253,7 @@ class DirectiveInjector implements DirectiveBinder {
262253

263254
Object _getById(int keyId) {
264255
switch(keyId) {
265-
case INJECTOR_KEY_ID: return _appInjector;
256+
case INJECTOR_KEY_ID: return appInjector;
266257
case DIRECTIVE_INJECTOR_KEY_ID: return this;
267258
case NODE_KEY_ID: return _node;
268259
case ELEMENT_KEY_ID: return _node;
@@ -272,8 +263,7 @@ class DirectiveInjector implements DirectiveBinder {
272263
case ELEMENT_PROBE_KEY_ID: return elementProbe;
273264
case NG_ELEMENT_KEY_ID: return ngElement;
274265
case EVENT_HANDLER_KEY_ID: return _eventHandler;
275-
case CONTENT_PORT_KEY_ID:
276-
return _parent == null ? null : _parent._getById(keyId);
266+
case CONTENT_PORT_KEY_ID: return parent._getById(keyId);
277267
default: new NoProviderError(_KEYS[keyId]);
278268
}
279269
}
@@ -282,30 +272,29 @@ class DirectiveInjector implements DirectiveBinder {
282272
var oldTag = _TAG_GET.makeCurrent();
283273
int size = paramKeys.length;
284274
var obj;
285-
var appInjector = this._appInjector;
286275
if (size > 15) {
287276
var params = new List(paramKeys.length);
288277
for(var i = 0; i < paramKeys.length; i++) {
289-
params[i] = _getByKey(paramKeys[i], appInjector);
278+
params[i] = _getByKey(paramKeys[i]);
290279
}
291280
_TAG_INSTANTIATE.makeCurrent();
292281
obj = Function.apply(fn, params);
293282
} else {
294-
var a01 = size >= 01 ? _getByKey(paramKeys[00], appInjector) : null;
295-
var a02 = size >= 02 ? _getByKey(paramKeys[01], appInjector) : null;
296-
var a03 = size >= 03 ? _getByKey(paramKeys[02], appInjector) : null;
297-
var a04 = size >= 04 ? _getByKey(paramKeys[03], appInjector) : null;
298-
var a05 = size >= 05 ? _getByKey(paramKeys[04], appInjector) : null;
299-
var a06 = size >= 06 ? _getByKey(paramKeys[05], appInjector) : null;
300-
var a07 = size >= 07 ? _getByKey(paramKeys[06], appInjector) : null;
301-
var a08 = size >= 08 ? _getByKey(paramKeys[07], appInjector) : null;
302-
var a09 = size >= 09 ? _getByKey(paramKeys[08], appInjector) : null;
303-
var a10 = size >= 10 ? _getByKey(paramKeys[09], appInjector) : null;
304-
var a11 = size >= 11 ? _getByKey(paramKeys[10], appInjector) : null;
305-
var a12 = size >= 12 ? _getByKey(paramKeys[11], appInjector) : null;
306-
var a13 = size >= 13 ? _getByKey(paramKeys[12], appInjector) : null;
307-
var a14 = size >= 14 ? _getByKey(paramKeys[13], appInjector) : null;
308-
var a15 = size >= 15 ? _getByKey(paramKeys[14], appInjector) : null;
283+
var a01 = size >= 01 ? _getByKey(paramKeys[00]) : null;
284+
var a02 = size >= 02 ? _getByKey(paramKeys[01]) : null;
285+
var a03 = size >= 03 ? _getByKey(paramKeys[02]) : null;
286+
var a04 = size >= 04 ? _getByKey(paramKeys[03]) : null;
287+
var a05 = size >= 05 ? _getByKey(paramKeys[04]) : null;
288+
var a06 = size >= 06 ? _getByKey(paramKeys[05]) : null;
289+
var a07 = size >= 07 ? _getByKey(paramKeys[06]) : null;
290+
var a08 = size >= 08 ? _getByKey(paramKeys[07]) : null;
291+
var a09 = size >= 09 ? _getByKey(paramKeys[08]) : null;
292+
var a10 = size >= 10 ? _getByKey(paramKeys[09]) : null;
293+
var a11 = size >= 11 ? _getByKey(paramKeys[10]) : null;
294+
var a12 = size >= 12 ? _getByKey(paramKeys[11]) : null;
295+
var a13 = size >= 13 ? _getByKey(paramKeys[12]) : null;
296+
var a14 = size >= 14 ? _getByKey(paramKeys[13]) : null;
297+
var a15 = size >= 15 ? _getByKey(paramKeys[14]) : null;
309298
_TAG_INSTANTIATE.makeCurrent();
310299
switch(size) {
311300
case 00: obj = fn(); break;
@@ -333,7 +322,7 @@ class DirectiveInjector implements DirectiveBinder {
333322

334323
ElementProbe get elementProbe {
335324
if (_elementProbe == null) {
336-
ElementProbe parentProbe = _parent == null ? null : _parent.elementProbe;
325+
ElementProbe parentProbe = parent is DirectiveInjector ? parent.elementProbe : null;
337326
_elementProbe = new ElementProbe(parentProbe, _node, this, scope);
338327
}
339328
return _elementProbe;
@@ -364,7 +353,7 @@ class TemplateDirectiveInjector extends DirectiveInjector {
364353
case VIEW_PORT_KEY_ID: return ((_viewPort) == null) ?
365354
_viewPort = new ViewPort(this, scope, _node, _animate) : _viewPort;
366355
case BOUND_VIEW_FACTORY_KEY_ID: return (_boundViewFactory == null) ?
367-
_boundViewFactory = _viewFactory.bind(this._parent) : _boundViewFactory;
356+
_boundViewFactory = _viewFactory.bind(this.parent) : _boundViewFactory;
368357
default: return super._getById(keyId);
369358
}
370359
}
@@ -420,9 +409,27 @@ class ShadowDomComponentDirectiveInjector extends ComponentDirectiveInjector {
420409

421410
ElementProbe get elementProbe {
422411
if (_elementProbe == null) {
423-
ElementProbe parentProbe = _parent == null ? null : _parent.elementProbe;
412+
ElementProbe parentProbe =
413+
parent is DirectiveInjector ? parent.elementProbe : parent.getByKey(ELEMENT_PROBE_KEY);
424414
_elementProbe = new ElementProbe(parentProbe, _shadowRoot, this, scope);
425415
}
426416
return _elementProbe;
427417
}
428418
}
419+
420+
@Injectable()
421+
class DefaultDirectiveInjector extends DirectiveInjector {
422+
DefaultDirectiveInjector(Injector appInjector): super._default(null, appInjector);
423+
DefaultDirectiveInjector.newAppInjector(DirectiveInjector parent, Injector appInjector)
424+
: super._default(parent, appInjector);
425+
426+
Object getByKey(Key key) => appInjector.getByKey(key);
427+
_getDirectiveByKey(Key key, int visType, Injector i) =>
428+
parent == null ? i.getByKey(key) : parent._getDirectiveByKey(key, visType, i);
429+
_getById(int keyId) {
430+
switch (keyId) {
431+
case CONTENT_PORT_KEY_ID: return null;
432+
default: throw new NoProviderError(DirectiveInjector._KEYS[keyId]);
433+
}
434+
}
435+
}

lib/core_dom/directive_map.dart

+3-4
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ class DirectiveMap {
1313
DirectiveSelectorFactory _directiveSelectorFactory;
1414
FormatterMap _formatters;
1515
DirectiveSelector _selector;
16-
Injector _injector;
1716

18-
DirectiveMap(Injector this._injector,
17+
DirectiveMap(Injector injector,
1918
this._formatters,
2019
MetadataExtractor metadataExtractor,
2120
this._directiveSelectorFactory) {
22-
(_injector as ModuleInjector).types.forEach((type) {
21+
(injector as ModuleInjector).types.forEach((type) {
2322
metadataExtractor(type)
2423
.where((annotation) => annotation is Directive)
2524
.forEach((Directive directive) {
@@ -30,7 +29,7 @@ class DirectiveMap {
3029

3130
DirectiveSelector get selector {
3231
if (_selector != null) return _selector;
33-
return _selector = _directiveSelectorFactory.selector(this, _injector, _formatters);
32+
return _selector = _directiveSelectorFactory.selector(this, _formatters);
3433
}
3534

3635
List<DirectiveTypeTuple> operator[](String key) {

lib/core_dom/element_binder.dart

+11-16
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ class TemplateElementBinder extends ElementBinder {
1414
return _directiveCache = [template];
1515
}
1616

17-
TemplateElementBinder(perf, expando, parser, config, appInjector,
17+
TemplateElementBinder(perf, expando, parser, config,
1818
this.template, this.templateBinder,
1919
onEvents, bindAttrs, childMode)
20-
: super(perf, expando, parser, config, appInjector,
20+
: super(perf, expando, parser, config,
2121
null, null, onEvents, bindAttrs, childMode);
2222

2323
String toString() => "[TemplateElementBinder template:$template]";
@@ -47,8 +47,6 @@ class ElementBinder {
4747
final Expando _expando;
4848
final Parser _parser;
4949
final CompilerConfig _config;
50-
final Injector _appInjector;
51-
Animate _animate;
5250

5351
final Map onEvents;
5452
final Map bindAttrs;
@@ -62,10 +60,8 @@ class ElementBinder {
6260
final String childMode;
6361

6462
ElementBinder(this._perf, this._expando, this._parser, this._config,
65-
this._appInjector, this.componentData, this.decorators,
66-
this.onEvents, this.bindAttrs, this.childMode) {
67-
_animate = _appInjector.getByKey(ANIMATE_KEY);
68-
}
63+
this.componentData, this.decorators,
64+
this.onEvents, this.bindAttrs, this.childMode);
6965

7066
final bool hasTemplate = false;
7167

@@ -261,21 +257,20 @@ class ElementBinder {
261257

262258
DirectiveInjector bind(View view, Scope scope,
263259
DirectiveInjector parentInjector,
264-
dom.Node node) {
260+
dom.Node node, EventHandler eventHandler, Animate animate) {
265261
var nodeAttrs = node is dom.Element ? new NodeAttrs(node) : null;
266262

267263
var directiveRefs = _usableDirectiveRefs;
268264
if (!hasDirectivesOrEvents) return parentInjector;
269265

270266
DirectiveInjector nodeInjector;
271-
var parentEventHandler = parentInjector == null ?
272-
_appInjector.getByKey(EVENT_HANDLER_KEY) :
273-
eventHandler(parentInjector);
274267
if (this is TemplateElementBinder) {
275-
nodeInjector = new TemplateDirectiveInjector(parentInjector, _appInjector,
276-
node, nodeAttrs, parentEventHandler, scope, _animate, (this as TemplateElementBinder).templateViewFactory);
268+
nodeInjector = new TemplateDirectiveInjector(parentInjector, parentInjector.appInjector,
269+
node, nodeAttrs, eventHandler, scope, animate,
270+
(this as TemplateElementBinder).templateViewFactory);
277271
} else {
278-
nodeInjector = new DirectiveInjector(parentInjector, _appInjector, node, nodeAttrs, parentEventHandler, scope, _animate);
272+
nodeInjector = new DirectiveInjector(parentInjector, parentInjector.appInjector,
273+
node, nodeAttrs, eventHandler, scope, animate);
279274
}
280275

281276
for(var i = 0; i < directiveRefs.length; i++) {
@@ -304,7 +299,7 @@ class ElementBinder {
304299

305300
if (onEvents.isNotEmpty) {
306301
onEvents.forEach((event, value) {
307-
parentEventHandler.register(EventHandler.attrNameToEventName(event));
302+
view.registerEvent(EventHandler.attrNameToEventName(event));
308303
});
309304
}
310305
return nodeInjector;

lib/core_dom/element_binder_builder.dart

+7-9
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,16 @@ class ElementBinderFactory {
1515
this.astParser, this.componentFactory, this.shadowDomComponentFactory, this.transcludingComponentFactory);
1616

1717
// TODO: Optimize this to re-use a builder.
18-
ElementBinderBuilder builder(FormatterMap formatters, DirectiveMap directives, Injector injector) =>
19-
new ElementBinderBuilder(this, formatters, directives, injector);
18+
ElementBinderBuilder builder(FormatterMap formatters, DirectiveMap directives) =>
19+
new ElementBinderBuilder(this,formatters, directives);
2020

2121
ElementBinder binder(ElementBinderBuilder b) =>
2222

23-
new ElementBinder(_perf, _expando, _parser, _config, b._injector,
23+
new ElementBinder(_perf, _expando, _parser, _config,
2424
b.componentData, b.decorators, b.onEvents, b.bindAttrs, b.childMode);
2525

26-
TemplateElementBinder templateBinder(
27-
ElementBinderBuilder b, ElementBinder transclude) =>
28-
new TemplateElementBinder(_perf, _expando, _parser, _config, b._injector,
26+
TemplateElementBinder templateBinder(ElementBinderBuilder b, ElementBinder transclude) =>
27+
new TemplateElementBinder(_perf, _expando, _parser, _config,
2928
b.template, transclude, b.onEvents, b.bindAttrs, b.childMode);
3029
}
3130

@@ -46,14 +45,13 @@ class ElementBinderBuilder {
4645
final bindAttrs = new HashMap<String, AST>();
4746

4847
final decorators = <DirectiveRef>[];
49-
final Injector _injector;
5048
DirectiveRef template;
5149
BoundComponentData componentData;
5250

5351
// Can be either COMPILE_CHILDREN or IGNORE_CHILDREN
5452
String childMode = Directive.COMPILE_CHILDREN;
5553

56-
ElementBinderBuilder(this._factory, this._formatters, this._directives, this._injector);
54+
ElementBinderBuilder(this._factory, this._formatters, this._directives);
5755

5856
/**
5957
* Adds [DirectiveRef]s to this [ElementBinderBuilder].
@@ -81,7 +79,7 @@ class ElementBinderBuilder {
8179
factory = _factory.componentFactory;
8280
}
8381

84-
componentData = new BoundComponentData(ref, () => factory.bind(ref, _directives, _injector));
82+
componentData = new BoundComponentData(ref, () => factory.bind(ref, _directives));
8583
} else {
8684
decorators.add(ref);
8785
}

0 commit comments

Comments
 (0)