Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.
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
1 change: 1 addition & 0 deletions lib/application_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import 'dart:html';
metaTargets: const [
Injectable,
Decorator,
Template,
Controller,
Component,
Formatter
Expand Down
1 change: 1 addition & 0 deletions lib/core/annotation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export "package:angular/core/annotation_src.dart" show
Component,
Controller,
Decorator,
Template,

DirectiveAnnotation,
NgAttr,
Expand Down
108 changes: 64 additions & 44 deletions lib/core/annotation_src.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ RegExp _ATTR_NAME = new RegExp(r'\[([^\]]+)\]$');

const String SHADOW_DOM_INJECTOR_NAME = 'SHADOW_INJECTOR';

skipShadow(Injector injector)
=> injector.name == SHADOW_DOM_INJECTOR_NAME ? injector.parent : injector;
skipShadow(Injector injector) =>
injector.name == SHADOW_DOM_INJECTOR_NAME ? injector.parent : injector;

localVisibility (Injector requesting, Injector defining)
=> identical(skipShadow(requesting), defining);
localVisibility (Injector requesting, Injector defining) =>
identical(skipShadow(requesting), defining);

directChildrenVisibility(Injector requesting, Injector defining) {
requesting = skipShadow(requesting);
return identical(requesting.parent, defining) || localVisibility(requesting, defining);
}

Directive cloneWithNewMap(Directive annotation, map)
=> annotation._cloneWithNewMap(map);
Directive cloneWithNewMap(Directive annotation, map) => annotation._cloneWithNewMap(map);

String mappingSpec(DirectiveAnnotation annotation) => annotation._mappingSpec;

Expand Down Expand Up @@ -69,30 +68,11 @@ abstract class Directive {
* Specifies the compiler action to be taken on the child nodes of the
* element which this currently being compiled. The values are:
*
* * [COMPILE_CHILDREN] (*default*)
* * [TRANSCLUDE_CHILDREN]
* * [IGNORE_CHILDREN]
* * [:true:] Compile the child nodes of the element. (default)
* * [:false:] Do not compile/visit the child nodes. Angular markup on
* descendant nodes will not be processed.
*/
@deprecated
final String children;

/**
* Compile the child nodes of the element. This is the default.
*/
@deprecated
static const String COMPILE_CHILDREN = 'compile';
/**
* Compile the child nodes for transclusion and makes available
* [BoundViewFactory], [ViewFactory] and [ViewPort] for injection.
*/
@deprecated
static const String TRANSCLUDE_CHILDREN = 'transclude';
/**
* Do not compile/visit the child nodes. Angular markup on descendant nodes
* will not be processed.
*/
@deprecated
static const String IGNORE_CHILDREN = 'ignore';
final bool compileChildren;

/**
* A directive/component controller class can be injected into other
Expand Down Expand Up @@ -123,7 +103,7 @@ abstract class Directive {
* module: Foo.moduleFactory)
* class Foo {
* static moduleFactory() => new Module()
* ..bind(SomeTypeA, visibility: Directive.LOCAL_VISIBILITY);
* ..bind(SomeTypeA, visibility: Directive.LOCAL_VISIBILITY);
* }
*
* When specifying types, factories or values in the module, notice that
Expand Down Expand Up @@ -215,18 +195,19 @@ abstract class Directive {

const Directive({
this.selector,
this.children: Directive.COMPILE_CHILDREN,
this.compileChildren: true,
this.visibility: Directive.LOCAL_VISIBILITY,
this.module,
this.map: const {},
this.exportExpressions: const [],
this.exportExpressionAttrs: const []
});

toString() => selector;
get hashCode => selector.hashCode;
operator==(other) =>
other is Directive && selector == other.selector;
String toString() => selector;

int get hashCode => selector.hashCode;

bool operator==(other) => other is Directive && selector == other.selector;

Directive _cloneWithNewMap(newMap);
}
Expand Down Expand Up @@ -333,7 +314,7 @@ class Component extends Directive {
_applyAuthorStyles = applyAuthorStyles,
_resetStyleInheritance = resetStyleInheritance,
super(selector: selector,
children: Directive.COMPILE_CHILDREN,
compileChildren: true,
visibility: visibility,
map: map,
module: module,
Expand All @@ -344,7 +325,7 @@ class Component extends Directive {
const [] :
_cssUrls is List ? _cssUrls : [_cssUrls];

Directive _cloneWithNewMap(newMap) =>
Component _cloneWithNewMap(newMap) =>
new Component(
template: template,
templateUrl: templateUrl,
Expand Down Expand Up @@ -375,24 +356,24 @@ class Component extends Directive {
* * `detach()` - Called on when owning scope is destroyed.
*/
class Decorator extends Directive {
const Decorator({children: Directive.COMPILE_CHILDREN,
const Decorator({compileChildren: true,
map,
selector,
module,
visibility,
exportExpressions,
exportExpressionAttrs})
: super(selector: selector,
children: children,
compileChildren: compileChildren,
visibility: visibility,
map: map,
module: module,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);

Directive _cloneWithNewMap(newMap) =>
Decorator _cloneWithNewMap(newMap) =>
new Decorator(
children: children,
compileChildren: compileChildren,
map: newMap,
module: module,
selector: selector,
Expand All @@ -401,6 +382,45 @@ class Decorator extends Directive {
exportExpressionAttrs: exportExpressionAttrs);
}



/**
* Meta-data marker placed on a class which should act as template.
*
* Angular templates are instantiated using dependency injection, and can
* ask for any injectable object in their constructor. Templates can also ask
* for other components or directives declared on the DOM element.
*
* Templates can implement [NgAttachAware], [NgDetachAware] and declare these
* optional methods:
*
* * `attach()` - Called on first [Scope.apply()].
* * `detach()` - Called on when owning scope is destroyed.
*/
class Template extends Directive {
const Template({map,
selector,
module,
visibility,
exportExpressions,
exportExpressionAttrs})
: super(selector: selector,
compileChildren: true,
visibility: visibility,
map: map,
module: module,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);

Template _cloneWithNewMap(newMap) =>
new Template(map: newMap,
module: module,
selector: selector,
visibility: visibility,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);
}

/**
* Meta-data marker placed on a class which should act as a controller for your
* application.
Expand Down Expand Up @@ -428,7 +448,7 @@ class Controller extends Decorator {
final String publishAs;

const Controller({
children: Directive.COMPILE_CHILDREN,
compileChildren: true,
this.publishAs,
map,
module,
Expand All @@ -438,7 +458,7 @@ class Controller extends Decorator {
exportExpressionAttrs
})
: super(selector: selector,
children: children,
compileChildren: compileChildren,
visibility: visibility,
map: map,
module: module,
Expand All @@ -447,7 +467,7 @@ class Controller extends Decorator {

Directive _cloneWithNewMap(newMap) =>
new Controller(
children: children,
compileChildren: compileChildren,
publishAs: publishAs,
module: module,
map: newMap,
Expand Down
12 changes: 6 additions & 6 deletions lib/core/registry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,29 @@ abstract class AnnotationsMap<K> {
extractMetadata(type)
.where((annotation) => annotation is K)
.forEach((annotation) {
map.putIfAbsent(annotation, () => []).add(type);
map.putIfAbsent(annotation, () => <Type>[]).add(type);
});
});
}

List operator[](K annotation) {
List<Type> operator[](K annotation) {
var value = map[annotation];
if (value == null) throw 'No $annotation found!';
return value;
}

void forEach(fn(K, Type)) {
map.forEach((annotation, types) {
types.forEach((type) {
map.forEach((K annotation, List<Type> types) {
types.forEach((Type type) {
fn(annotation, type);
});
});
}

List<K> annotationsFor(Type type) {
var res = <K>[];
forEach((ann, annType) {
if (annType == type) res.add(ann);
map.forEach((K ann, List<Type> types) {
if (types.contains(type)) res.add(ann);
});
return res;
}
Expand Down
53 changes: 24 additions & 29 deletions lib/core/registry_dynamic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import 'package:angular/core/registry.dart';
export 'package:angular/core/registry.dart' show
MetadataExtractor;

var _fieldMetadataCache = new Map<Type, Map<String, DirectiveAnnotation>>();

class DynamicMetadataExtractor implements MetadataExtractor {
static final _fieldMetadataCache = <Type, Map<String, DirectiveAnnotation>>{};

final _fieldAnnotations = [
reflectType(NgAttr),
reflectType(NgOneWay),
Expand All @@ -24,29 +24,28 @@ class DynamicMetadataExtractor implements MetadataExtractor {
if (metadata == null) {
metadata = [];
} else {
metadata = metadata.map((InstanceMirror im) => map(type, im.reflectee));
metadata = metadata.map((InstanceMirror im) => _mergeMap(type, im.reflectee));
}
return metadata;
}

map(Type type, obj) {
if (obj is Directive) {
return mapDirectiveAnnotation(type, obj);
} else {
return obj;
}
}

Directive mapDirectiveAnnotation(Type type, Directive annotation) {
var match;
var fieldMetadata = fieldMetadataExtractor(type);
if (fieldMetadata.isNotEmpty) {
var newMap = annotation.map == null ? {} : new Map.from(annotation.map);
fieldMetadata.forEach((String fieldName, DirectiveAnnotation ann) {
/**
* Merges the field annotations with the [AbstractNgAttrAnnotation.map]
* definition from the [Directive].
*
* [_mergeDirectiveMap] throws when the definition for an annotated is
* duplicated in the [AbstractNgAttrAnnotation.map]
*/
dynamic _mergeMap(Type type, annotation) {
if (annotation is! Directive) return annotation;
var metaData = _extractFieldMetadata(type);
if (metaData.isNotEmpty) {
var newMap = annotation.map == null ? <String, String>{} : new Map.from(annotation.map);
metaData.forEach((String fieldName, DirectiveAnnotation ann) {
var attrName = ann.attrName;
if (newMap.containsKey(attrName)) {
throw 'Mapping for attribute $attrName is already defined (while '
'processing annottation for field $fieldName of $type)';
'processing annotation for field $fieldName of $type)';
}
newMap[attrName] = '${mappingSpec(ann)}$fieldName';
});
Expand All @@ -55,21 +54,17 @@ class DynamicMetadataExtractor implements MetadataExtractor {
return annotation;
}


Map<String, DirectiveAnnotation> fieldMetadataExtractor(Type type) =>
Map<String, DirectiveAnnotation> _extractFieldMetadata(Type type) =>
_fieldMetadataCache.putIfAbsent(type, () => _fieldMetadataExtractor(reflectType(type)));

/// Extract metadata defined on fields via a [DirectiveAnnotation]
Map<String, DirectiveAnnotation> _fieldMetadataExtractor(ClassMirror cm) {
var fields = <String, DirectiveAnnotation>{};
if(cm.superclass != null) {
fields.addAll(_fieldMetadataExtractor(cm.superclass));
} else {
fields = {};
}
if(cm.superclass != null) fields.addAll(_fieldMetadataExtractor(cm.superclass));

Map<Symbol, DeclarationMirror> declarations = cm.declarations;
declarations.forEach((symbol, dm) {
if(dm is VariableMirror ||
dm is MethodMirror && (dm.isGetter || dm.isSetter)) {
declarations.forEach((Symbol symbol, DeclarationMirror dm) {
if (dm is VariableMirror || dm is MethodMirror && (dm.isGetter || dm.isSetter)) {
var fieldName = MirrorSystem.getName(symbol);
if (dm is MethodMirror && dm.isSetter) {
// Remove "=" from the end of the setter.
Expand All @@ -79,7 +74,7 @@ class DynamicMetadataExtractor implements MetadataExtractor {
if (_fieldAnnotations.contains(meta.type)) {
if (fields.containsKey(fieldName)) {
throw 'Attribute annotation for $fieldName is defined more '
'than once in ${cm.reflectedType}';
'than once in ${cm.reflectedType}';
}
fields[fieldName] = meta.reflectee as DirectiveAnnotation;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/core/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ class Scope {
} else if (expression.startsWith(':')) {
expression = expression.substring(1);
fn = (value, last) {
if (value != null) reactionFn(value, last);
if (value != null) reactionFn(value, last);
};
}
}
Expand Down
Loading