Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Unified Diff: third_party/pkg/angular/lib/core_dom/selector.dart

Issue 257423008: Update all Angular libs (run update_all.sh). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/pkg/angular/lib/core_dom/selector.dart
diff --git a/third_party/pkg/angular/lib/core_dom/selector.dart b/third_party/pkg/angular/lib/core_dom/selector.dart
index 2492d0608208a7831af9a8dc56412db804a71fe3..fec6946e86c683a223c3acbae18ceed9489b51fa 100644
--- a/third_party/pkg/angular/lib/core_dom/selector.dart
+++ b/third_party/pkg/angular/lib/core_dom/selector.dart
@@ -1,4 +1,4 @@
-part of angular.core.dom;
+part of angular.core.dom_internal;
/**
* DirectiveSelector is a function which given a node it will return a
@@ -7,8 +7,7 @@ part of angular.core.dom;
* DirectiveSelector is used by the [Compiler] during the template walking
* to extract the [DirectiveRef]s.
*
- * DirectiveSelector can be created using the [directiveSelectorFactory]
- * method.
+ * DirectiveSelector can be created using the [DirectiveSelectorFactory].
*
* The DirectiveSelector supports CSS selectors which do not cross
* element boundaries only. The selectors can have any mix of element-name,
@@ -16,39 +15,171 @@ part of angular.core.dom;
*
* Examples:
*
- * <pre>
- * element
- * .class
- * [attribute]
- * [attribute=value]
- * element[attribute1][attribute2=value]
- * </pre>
- *
- *
+ * * element
+ * * .class
+ * * [attribute]
+ * * [attribute=value]
+ * * element[attribute1][attribute2=value]
+ * * :contains(/abc/)
+ */
+class DirectiveSelector {
+ ElementBinderFactory _binderFactory;
+ DirectiveMap _directives;
+ var elementSelector;
+ var attrSelector;
+ var textSelector;
+
+ DirectiveSelector(this._directives, this._binderFactory) {
+ elementSelector = new _ElementSelector('');
+ attrSelector = <_ContainsSelector>[];
+ textSelector = <_ContainsSelector>[];
+ _directives.forEach((Directive annotation, Type type) {
+ var match;
+ var selector = annotation.selector;
+ List<_SelectorPart> selectorParts;
+ if (selector == null) {
+ throw new ArgumentError('Missing selector annotation for $type');
+ }
+
+ if ((match = _CONTAINS_REGEXP.firstMatch(selector)) != null) {
+ textSelector.add(new _ContainsSelector(annotation, match.group(1)));
+ } else if ((match = _ATTR_CONTAINS_REGEXP.firstMatch(selector)) != null) {
+ attrSelector.add(new _ContainsSelector(annotation, match[1]));
+ } else if ((selectorParts = _splitCss(selector, type)) != null){
+ elementSelector.addDirective(selectorParts,
+ new _Directive(type, annotation));
+ } else {
+ throw new ArgumentError('Unsupported Selector: $selector');
+ }
+ });
+ }
+
+ ElementBinder matchElement(dom.Node node) {
+ assert(node is dom.Element);
+
+ ElementBinderBuilder builder = _binderFactory.builder();
+ List<_ElementSelector> partialSelection;
+ var classes = <String, bool>{};
+ Map<String, String> attrs = {};
+
+ dom.Element element = node;
+ String nodeName = element.tagName.toLowerCase();
+
+ // Set default attribute
+ if (nodeName == 'input' && !element.attributes.containsKey('type')) {
+ element.attributes['type'] = 'text';
+ }
+
+ // Select node
+ partialSelection = elementSelector.selectNode(builder,
+ partialSelection, element, nodeName);
+
+ // Select .name
+ if ((element.classes) != null) {
+ for (var name in element.classes) {
+ classes[name] = true;
+ partialSelection = elementSelector.selectClass(builder,
+ partialSelection, element, name);
+ }
+ }
+
+ // Select [attributes]
+ element.attributes.forEach((attrName, value) {
+
+ if (attrName.startsWith("on-")) {
+ builder.onEvents[attrName] = value;
+ } else if (attrName.startsWith("bind-")) {
+ builder.bindAttrs[attrName] = value;
+ }
+
+ attrs[attrName] = value;
+ for (var k = 0; k < attrSelector.length; k++) {
+ _ContainsSelector selectorRegExp = attrSelector[k];
+ if (selectorRegExp.regexp.hasMatch(value)) {
+ // this directive is matched on any attribute name, and so
+ // we need to pass the name to the directive by prefixing it to
+ // 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'));
+ });
+ }
+ }
+
+ partialSelection = elementSelector.selectAttr(builder,
+ partialSelection, node, attrName, value);
+ });
+
+ while (partialSelection != null) {
+ List<_ElementSelector> elementSelectors = partialSelection;
+ partialSelection = null;
+ elementSelectors.forEach((_ElementSelector elementSelector) {
+ classes.forEach((className, _) {
+ partialSelection = elementSelector.selectClass(builder,
+ partialSelection, node, className);
+ });
+ attrs.forEach((attrName, value) {
+ partialSelection = elementSelector.selectAttr(builder,
+ partialSelection, node, attrName, value);
+ });
+ });
+ }
+ return builder.binder;
+ }
+
+ ElementBinder matchText(dom.Node node) {
+ ElementBinderBuilder builder = _binderFactory.builder();
+
+ var value = node.nodeValue;
+ for (var k = 0; k < textSelector.length; k++) {
+ var selectorRegExp = textSelector[k];
+ if (selectorRegExp.regexp.hasMatch(value)) {
+ _directives[selectorRegExp.annotation].forEach((type) {
+ builder.addDirective(new DirectiveRef(node, type,
+ selectorRegExp.annotation, value));
+ });
+ }
+ }
+ return builder.binder;
+ }
+
+ ElementBinder matchComment(dom.Node node) =>
+ _binderFactory.builder().binder;
+}
+
+/**
+ * Factory for creating a [DirectiveSelector].
*/
-typedef List<DirectiveRef> DirectiveSelector(dom.Node node);
+@Injectable()
+class DirectiveSelectorFactory {
+ ElementBinderFactory _binderFactory;
+
+ DirectiveSelectorFactory(this._binderFactory);
+
+ DirectiveSelector selector(DirectiveMap directives) =>
+ new DirectiveSelector(directives, _binderFactory);
+}
class _Directive {
final Type type;
- final NgAnnotation annotation;
+ final Directive annotation;
_Directive(this.type, this.annotation);
toString() => annotation.selector;
}
-
class _ContainsSelector {
- final NgAnnotation annotation;
+ final Directive annotation;
final RegExp regexp;
_ContainsSelector(this.annotation, String regexp)
: regexp = new RegExp(regexp);
}
-var _SELECTOR_REGEXP = new RegExp(r'^(?:([\w\-]+)|(?:\.([\w\-]+))|'
- r'(?:\[([\w\-\*]+)(?:=([^\]]*))?\]))');
-var _COMMENT_COMPONENT_REGEXP = new RegExp(r'^\[([\w\-]+)(?:\=(.*))?\]$');
+var _SELECTOR_REGEXP = new RegExp(r'^(?:([-\w]+)|(?:\.([-\w]+))|'
+ r'(?:\[([-\w*]+)(?:=([^\]]*))?\]))');
+var _COMMENT_COMPONENT_REGEXP = new RegExp(r'^\[([-\w]+)(?:\=(.*))?\]$');
var _CONTAINS_REGEXP = new RegExp(r'^:contains\(\/(.+)\/\)$'); //
var _ATTR_CONTAINS_REGEXP = new RegExp(r'^\[\*=\/(.+)\/\]$'); //
@@ -64,7 +195,6 @@ class _SelectorPart {
const _SelectorPart.fromClass(this.className)
: element = null, attrName = null, attrValue = null;
-
const _SelectorPart.fromAttribute(this.attrName, this.attrValue)
: element = null, className = null;
@@ -76,6 +206,12 @@ class _SelectorPart {
: element;
}
+_addRefs(ElementBinderBuilder builder, List<_Directive> directives, dom.Node node,
+ [String attrValue]) {
+ directives.forEach((directive) {
+ builder.addDirective(new DirectiveRef(node, directive.type, directive.annotation, attrValue));
+ });
+}
class _ElementSelector {
final String name;
@@ -97,9 +233,7 @@ class _ElementSelector {
var name;
if ((name = selectorPart.element) != null) {
if (terminal) {
- elementMap
- .putIfAbsent(name, () => [])
- .add(directive);
+ elementMap.putIfAbsent(name, () => []).add(directive);
} else {
elementPartialMap
.putIfAbsent(name, () => new _ElementSelector(name))
@@ -133,18 +267,13 @@ class _ElementSelector {
}
}
- _addRefs(List<DirectiveRef> refs, List<_Directive> directives, dom.Node node,
- [String attrValue]) {
- directives.forEach((directive) =>
- refs.add(new DirectiveRef(node, directive.type, directive.annotation,
- attrValue)));
- }
- List<_ElementSelector> selectNode(List<DirectiveRef> refs,
+
+ List<_ElementSelector> selectNode(ElementBinderBuilder builder,
List<_ElementSelector> partialSelection,
dom.Node node, String nodeName) {
if (elementMap.containsKey(nodeName)) {
- _addRefs(refs, elementMap[nodeName], node);
+ _addRefs(builder, elementMap[nodeName], node);
}
if (elementPartialMap.containsKey(nodeName)) {
if (partialSelection == null) {
@@ -155,11 +284,11 @@ class _ElementSelector {
return partialSelection;
}
- List<_ElementSelector> selectClass(List<DirectiveRef> refs,
+ List<_ElementSelector> selectClass(ElementBinderBuilder builder,
List<_ElementSelector> partialSelection,
dom.Node node, String className) {
if (classMap.containsKey(className)) {
- _addRefs(refs, classMap[className], node);
+ _addRefs(builder, classMap[className], node);
}
if (classPartialMap.containsKey(className)) {
if (partialSelection == null) {
@@ -170,7 +299,7 @@ class _ElementSelector {
return partialSelection;
}
- List<_ElementSelector> selectAttr(List<DirectiveRef> refs,
+ List<_ElementSelector> selectAttr(ElementBinderBuilder builder,
List<_ElementSelector> partialSelection,
dom.Node node, String attrName,
String attrValue) {
@@ -180,10 +309,10 @@ class _ElementSelector {
if (matchingKey != null) {
Map<String, List<_Directive>> valuesMap = attrValueMap[matchingKey];
if (valuesMap.containsKey('')) {
- _addRefs(refs, valuesMap[''], node, attrValue);
+ _addRefs(builder, valuesMap[''], node, attrValue);
}
if (attrValue != '' && valuesMap.containsKey(attrValue)) {
- _addRefs(refs, valuesMap[attrValue], node, attrValue);
+ _addRefs(builder, valuesMap[attrValue], node, attrValue);
}
}
if (attrValuePartialMap.containsKey(attrName)) {
@@ -205,9 +334,14 @@ class _ElementSelector {
return partialSelection;
}
+ // A global cache for the _matchingKey RegExps. The size is bounded by
+ // the number of attribute directive selectors used in the application.
+ static var _matchingKeyCache = <String, RegExp>{};
+
String _matchingKey(Iterable<String> keys, String attrName) =>
keys.firstWhere((key) =>
- new RegExp('^${key.replaceAll('*', r'[\w\-]+')}\$')
+ _matchingKeyCache.putIfAbsent(key,
+ () => new RegExp('^${key.replaceAll('*', r'[\w\-]+')}\$'))
.hasMatch(attrName), orElse: () => null);
toString() => 'ElementSelector($name)';
@@ -237,128 +371,3 @@ List<_SelectorPart> _splitCss(String selector, Type type) {
}
return parts;
}
-
-/**
- * Factory method for creating a [DirectiveSelector].
- */
-DirectiveSelector directiveSelectorFactory(DirectiveMap directives) {
-
- var elementSelector = new _ElementSelector('');
- var attrSelector = <_ContainsSelector>[];
- var textSelector = <_ContainsSelector>[];
- directives.forEach((NgAnnotation annotation, Type type) {
- var match;
- var selector = annotation.selector;
- List<_SelectorPart> selectorParts;
- if (selector == null) {
- throw new ArgumentError('Missing selector annotation for $type');
- }
-
- if ((match = _CONTAINS_REGEXP.firstMatch(selector)) != null) {
- textSelector.add(new _ContainsSelector(annotation, match.group(1)));
- } else if ((match = _ATTR_CONTAINS_REGEXP.firstMatch(selector)) != null) {
- attrSelector.add(new _ContainsSelector(annotation, match[1]));
- } else if ((selectorParts = _splitCss(selector, type)) != null){
- elementSelector.addDirective(selectorParts,
- new _Directive(type, annotation));
- } else {
- throw new ArgumentError('Unsupported Selector: $selector');
- }
- });
-
- return (dom.Node node) {
- var directiveRefs = <DirectiveRef>[];
- List<_ElementSelector> partialSelection;
- var classes = <String, bool>{};
- var attrs = <String, String>{};
-
- switch(node.nodeType) {
- case 1: // Element
- dom.Element element = node;
- String nodeName = element.tagName.toLowerCase();
- Map<String, String> attrs = {};
-
- // Set default attribute
- if (nodeName == 'input' && !element.attributes.containsKey('type')) {
- element.attributes['type'] = 'text';
- }
-
- // Select node
- partialSelection = elementSelector.selectNode(directiveRefs,
- partialSelection, element, nodeName);
-
- // Select .name
- if ((element.classes) != null) {
- for (var name in element.classes) {
- classes[name] = true;
- partialSelection = elementSelector.selectClass(directiveRefs,
- partialSelection, element, name);
- }
- }
-
- // Select [attributes]
- element.attributes.forEach((attrName, value) {
- attrs[attrName] = value;
- for (var k = 0; k < attrSelector.length; k++) {
- _ContainsSelector selectorRegExp = attrSelector[k];
- if (selectorRegExp.regexp.hasMatch(value)) {
- // this directive is matched on any attribute name, and so
- // we need to pass the name to the directive by prefixing it to
- // the value. Yes it is a bit of a hack.
- directives[selectorRegExp.annotation].forEach((type) {
- directiveRefs.add(new DirectiveRef(
- node, type, selectorRegExp.annotation, '$attrName=$value'));
- });
- }
- }
-
- partialSelection = elementSelector.selectAttr(directiveRefs,
- partialSelection, node, attrName, value);
- });
-
- while(partialSelection != null) {
- List<_ElementSelector> elementSelectors = partialSelection;
- partialSelection = null;
- elementSelectors.forEach((_ElementSelector elementSelector) {
- classes.forEach((className, _) {
- partialSelection = elementSelector.selectClass(directiveRefs,
- partialSelection, node, className);
- });
- attrs.forEach((attrName, value) {
- partialSelection = elementSelector.selectAttr(directiveRefs,
- partialSelection, node, attrName, value);
- });
- });
- }
- break;
- case 3: // Text Node
- var value = node.nodeValue;
- for (var k = 0; k < textSelector.length; k++) {
- var selectorRegExp = textSelector[k];
-
- if (selectorRegExp.regexp.hasMatch(value)) {
- directives[selectorRegExp.annotation].forEach((type) {
- directiveRefs.add(new DirectiveRef(node, type,
- selectorRegExp.annotation, value));
- });
- }
- }
- break;
- }
-
- directiveRefs.sort(_priorityComparator);
- return directiveRefs;
- };
-}
-
-int _directivePriority(NgAnnotation annotation) {
- if (annotation is NgDirective) {
- return (annotation.children == NgAnnotation.TRANSCLUDE_CHILDREN) ? 2 : 1;
- } else if (annotation is NgComponent) {
- return 0;
- }
- throw "Unexpected Type: ${annotation}.";
-}
-
-int _priorityComparator(DirectiveRef a, DirectiveRef b) =>
- _directivePriority(b.annotation) - _directivePriority(a.annotation);

Powered by Google App Engine
This is Rietveld 408576698