Skip to content

Commit 6f4a39c

Browse files
committed
refactor(di): removed @parent
BREAKING CHANGE The @parent annotation has been removed. Use @ancestor instead. @parent was used to enforce a particular DOM structure (e.g., a pane component is a direct child of the tabs component). DI is not the right mechanism to do it. We should enforce it using schema instead.
1 parent a472eac commit 6f4a39c

File tree

16 files changed

+263
-250
lines changed

16 files changed

+263
-250
lines changed

modules/angular2/di.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export {
1010
InjectableMetadata,
1111
VisibilityMetadata,
1212
SelfMetadata,
13-
ParentMetadata,
1413
AncestorMetadata,
1514
UnboundedMetadata,
1615
DependencyMetadata,
@@ -24,12 +23,12 @@ export {forwardRef, resolveForwardRef, ForwardRefFn} from './src/di/forward_ref'
2423
export {
2524
Injector,
2625
ProtoInjector,
26+
BindingWithVisibility,
2727
DependencyProvider,
2828
PUBLIC_AND_PRIVATE,
2929
PUBLIC,
3030
PRIVATE,
3131
undefinedValue
32-
3332
} from './src/di/injector';
3433
export {Binding, BindingBuilder, ResolvedBinding, Dependency, bind} from './src/di/binding';
3534
export {Key, KeyRegistry, TypeLiteral} from './src/di/key';

modules/angular2/docs/core/02_directives.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ There are five kinds of visibilities:
262262

263263
* (no annotation): Inject dependent directives only if they are on the current element.
264264
* `@ancestor`: Inject a directive if it is at any element above the current element.
265-
* `@parent`: Inject a directive which is a direct parent of the current element.
266265
* `@child`: Inject a list of direct children which match a given type. (Used with `Query`)
267266
* `@descendant`: Inject a list of any children which match a given type. (Used with `Query`)
268267

@@ -301,7 +300,7 @@ class FieldSet { |
301300
class Field { |
302301
constructor( |
303302
@ancestor field:Form, |
304-
@parent field:FieldSet, |
303+
@ancestor field:FieldSet, |
305304
) { ... } |
306305
} |
307306
|
@@ -337,7 +336,7 @@ Shadow DOM provides an encapsulation for components, so as a general rule it doe
337336
})
338337
class Kid {
339338
constructor(
340-
@Parent() dad:Dad,
339+
@Ancestor() dad:Dad,
341340
@Optional() grandpa:Grandpa
342341
) {
343342
this.name = 'Billy';
@@ -354,7 +353,7 @@ class Kid {
354353
directives: [Kid]
355354
})
356355
class Dad {
357-
constructor(@Parent() dad:Grandpa) {
356+
constructor(@Ancestor() dad:Grandpa) {
358357
this.name = 'Joe Jr';
359358
this.dad = dad.name;
360359
}

modules/angular2/src/core/annotations_impl/annotations.ts

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ import {DEFAULT} from 'angular2/change_detection';
5858
* Shadow DOM root. Current element is not included in the resolution, therefore even if it could
5959
* resolve it, it will
6060
* be ignored.
61-
* - `@Parent() directive:DirectiveType`: any directive that matches the type on a direct parent
62-
* element only.
6361
* - `@Query(DirectiveType) query:QueryList<DirectiveType>`: A live collection of direct child
6462
* directives.
6563
* - `@QueryDescendants(DirectiveType) query:QueryList<DirectiveType>`: A live collection of any
@@ -163,27 +161,6 @@ import {DEFAULT} from 'angular2/change_detection';
163161
* This directive would be instantiated with `Dependency` declared at the same element, in this case
164162
* `dependency="3"`.
165163
*
166-
*
167-
* ### Injecting a directive from a direct parent element
168-
*
169-
* Directives can inject other directives declared on a direct parent element. By definition, a
170-
* directive with a
171-
* `@Parent` annotation does not attempt to resolve dependencies for the current element, even if
172-
* this would satisfy
173-
* the dependency.
174-
*
175-
* ```
176-
* @Directive({ selector: '[my-directive]' })
177-
* class MyDirective {
178-
* constructor(@Parent() dependency: Dependency) {
179-
* expect(dependency.id).toEqual(2);
180-
* }
181-
* }
182-
* ```
183-
* This directive would be instantiated with `Dependency` declared at the parent element, in this
184-
* case `dependency="2"`.
185-
*
186-
*
187164
* ### Injecting a directive from any ancestor elements
188165
*
189166
* Directives can inject other directives declared on any ancestor element (in the current Shadow
@@ -201,8 +178,8 @@ import {DEFAULT} from 'angular2/change_detection';
201178
* }
202179
* ```
203180
*
204-
* Unlike the `@Parent` which only checks the parent, `@Ancestor` checks the parent, as well as its
205-
* parents recursively. If `dependency="2"` didn't exist on the direct parent, this injection would
181+
* `@Ancestor` checks the parent, as well as its parents recursively. If `dependency="2"` didn't
182+
* exist on the direct parent, this injection would
206183
* have returned
207184
* `dependency="1"`.
208185
*

modules/angular2/src/core/compiler/element_injector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ export class ProtoElementInjector {
397397
public directiveVariableBindings: Map<string, number>) {
398398
var length = bwv.length;
399399

400-
this.protoInjector = new ProtoInjector(bwv, distanceToParent);
400+
this.protoInjector = new ProtoInjector(bwv);
401401

402402
this.eventEmitterAccessors = ListWrapper.createFixedSize(length);
403403
this.hostActionAccessors = ListWrapper.createFixedSize(length);

modules/angular2/src/di/decorators.dart

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ class Self extends SelfMetadata {
3131
const Self(): super();
3232
}
3333

34-
/**
35-
* {@link ParentMetadata}.
36-
*/
37-
class Parent extends ParentMetadata {
38-
const Parent({bool self}): super(self:self);
39-
}
40-
4134
/**
4235
* {@link AncestorMetadata}.
4336
*/

modules/angular2/src/di/decorators.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
InjectableMetadata,
55
SelfMetadata,
66
VisibilityMetadata,
7-
ParentMetadata,
87
AncestorMetadata,
98
UnboundedMetadata
109
} from './metadata';
@@ -42,14 +41,6 @@ export interface SelfFactory {
4241
new (): SelfMetadata;
4342
}
4443

45-
/**
46-
* Factory for creating {@link ParentMetadata}.
47-
*/
48-
export interface ParentFactory {
49-
(visibility?: {self: boolean}): any;
50-
new (visibility?: {self: boolean}): ParentMetadata;
51-
}
52-
5344
/**
5445
* Factory for creating {@link AncestorMetadata}.
5546
*/
@@ -86,11 +77,6 @@ export var Injectable: InjectableFactory = <InjectableFactory>makeDecorator(Inje
8677
*/
8778
export var Self: SelfFactory = makeParamDecorator(SelfMetadata);
8879

89-
/**
90-
* Factory for creating {@link ParentMetadata}.
91-
*/
92-
export var Parent: ParentFactory = makeParamDecorator(ParentMetadata);
93-
9480
/**
9581
* Factory for creating {@link AncestorMetadata}.
9682
*/

modules/angular2/src/di/injector.ts

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
1515
import {Key} from './key';
1616
import {resolveForwardRef} from './forward_ref';
17-
import {VisibilityMetadata, DEFAULT_VISIBILITY} from './metadata';
17+
import {VisibilityMetadata, DEFAULT_VISIBILITY, SelfMetadata, AncestorMetadata} from './metadata';
1818

1919
const _constructing = CONST_EXPR(new Object());
2020
const _notFound = CONST_EXPR(new Object());
@@ -175,7 +175,7 @@ export class ProtoInjectorDynamicStrategy implements ProtoInjectorStrategy {
175175
export class ProtoInjector {
176176
_strategy: ProtoInjectorStrategy;
177177

178-
constructor(bwv: BindingWithVisibility[], public distanceToParent: number) {
178+
constructor(bwv: BindingWithVisibility[]) {
179179
this._strategy = bwv.length > _MAX_CONSTRUCTION_COUNTER ?
180180
new ProtoInjectorDynamicStrategy(this, bwv) :
181181
new ProtoInjectorInlineStrategy(this, bwv);
@@ -459,7 +459,7 @@ export class Injector {
459459
static fromResolvedBindings(bindings: List<ResolvedBinding>,
460460
depProvider: DependencyProvider = null): Injector {
461461
var bd = bindings.map(b => new BindingWithVisibility(b, PUBLIC));
462-
var proto = new ProtoInjector(bd, 0);
462+
var proto = new ProtoInjector(bd);
463463
var inj = new Injector(proto, null, depProvider);
464464
return inj;
465465
}
@@ -542,7 +542,7 @@ export class Injector {
542542
createChildFromResolved(bindings: List<ResolvedBinding>,
543543
depProvider: DependencyProvider = null): Injector {
544544
var bd = bindings.map(b => new BindingWithVisibility(b, PUBLIC));
545-
var proto = new ProtoInjector(bd, 1);
545+
var proto = new ProtoInjector(bd);
546546
var inj = new Injector(proto, null, depProvider);
547547
inj._parent = this;
548548
return inj;
@@ -678,48 +678,78 @@ export class Injector {
678678
return this;
679679
}
680680

681-
var inj = this;
682-
var lastInjector = false;
683-
var depth = depVisibility.depth;
681+
if (depVisibility instanceof SelfMetadata) {
682+
return this._getByKeySelf(key, optional, bindingVisibility);
683+
684+
} else if (depVisibility instanceof AncestorMetadata) {
685+
return this._getByKeyAncestor(key, optional, bindingVisibility, depVisibility.includeSelf);
686+
687+
} else {
688+
return this._getByKeyUnbounded(key, optional, bindingVisibility, depVisibility.includeSelf);
689+
}
690+
}
691+
692+
_throwOrNull(key: Key, optional: boolean): any {
693+
if (optional) {
694+
return null;
695+
} else {
696+
throw new NoBindingError(key);
697+
}
698+
}
684699

685-
if (!depVisibility.includeSelf) {
686-
depth -= inj._proto.distanceToParent;
700+
_getByKeySelf(key: Key, optional: boolean, bindingVisibility: number): any {
701+
var obj = this._strategy.getObjByKeyId(key.id, bindingVisibility);
702+
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
703+
}
687704

705+
_getByKeyAncestor(key: Key, optional: boolean, bindingVisibility: number,
706+
includeSelf: boolean): any {
707+
var inj = this;
708+
709+
if (!includeSelf) {
688710
if (inj._isBoundary) {
689-
if (depVisibility.crossBoundaries) {
690-
bindingVisibility = PUBLIC_AND_PRIVATE;
691-
} else {
692-
bindingVisibility = PRIVATE;
693-
lastInjector = true;
694-
}
711+
return this._getPrivateDependency(key, optional, inj);
712+
} else {
713+
inj = inj._parent;
695714
}
696-
inj = inj._parent;
697715
}
698716

699-
while (inj != null && depth >= 0) {
717+
while (inj != null) {
700718
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
701719
if (obj !== undefinedValue) return obj;
702720

703-
depth -= inj._proto.distanceToParent;
721+
if (isPresent(inj._parent) && inj._isBoundary) {
722+
return this._getPrivateDependency(key, optional, inj);
723+
} else {
724+
inj = inj._parent;
725+
}
726+
}
704727

705-
if (lastInjector) break;
728+
return this._throwOrNull(key, optional);
729+
}
706730

707-
if (inj._isBoundary) {
708-
if (depVisibility.crossBoundaries) {
709-
bindingVisibility = PUBLIC_AND_PRIVATE;
710-
} else {
711-
bindingVisibility = PRIVATE;
712-
lastInjector = true;
713-
}
714-
}
731+
_getPrivateDependency(key: Key, optional: boolean, inj: Injector): any {
732+
var obj = inj._parent._strategy.getObjByKeyId(key.id, PRIVATE);
733+
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
734+
}
735+
736+
_getByKeyUnbounded(key: Key, optional: boolean, bindingVisibility: number,
737+
includeSelf: boolean): any {
738+
var inj = this;
739+
if (!includeSelf) {
740+
bindingVisibility = inj._isBoundary ? PUBLIC_AND_PRIVATE : PUBLIC;
715741
inj = inj._parent;
716742
}
717743

718-
if (optional) {
719-
return null;
720-
} else {
721-
throw new NoBindingError(key);
744+
while (inj != null) {
745+
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
746+
if (obj !== undefinedValue) return obj;
747+
748+
bindingVisibility = inj._isBoundary ? PUBLIC_AND_PRIVATE : PUBLIC;
749+
inj = inj._parent;
722750
}
751+
752+
return this._throwOrNull(key, optional);
723753
}
724754
}
725755

0 commit comments

Comments
 (0)