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

Unified Diff: third_party/pkg/angular/lib/core_dom/element_binder.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/element_binder.dart
diff --git a/third_party/pkg/angular/lib/core_dom/element_binder.dart b/third_party/pkg/angular/lib/core_dom/element_binder.dart
new file mode 100644
index 0000000000000000000000000000000000000000..dd01377ac78e04ce11e6b9f1abd796616577cf1e
--- /dev/null
+++ b/third_party/pkg/angular/lib/core_dom/element_binder.dart
@@ -0,0 +1,383 @@
+part of angular.core.dom_internal;
+
+class TemplateElementBinder extends ElementBinder {
+ final DirectiveRef template;
+ ViewFactory templateViewFactory;
+
+ final bool hasTemplate = true;
+
+ final ElementBinder templateBinder;
+
+ var _directiveCache;
+ List<DirectiveRef> get _usableDirectiveRefs {
+ if (_directiveCache != null) return _directiveCache;
+ return _directiveCache = [template];
+ }
+
+ TemplateElementBinder(perf, expando, parser, componentFactory,
+ transcludingComponentFactory, shadowDomComponentFactory,
+ this.template, this.templateBinder,
+ onEvents, bindAttrs, childMode)
+ : super(perf, expando, parser, componentFactory,
+ transcludingComponentFactory, shadowDomComponentFactory,
+ null, null, onEvents, bindAttrs, childMode);
+
+ String toString() => "[TemplateElementBinder template:$template]";
+
+ _registerViewFactory(node, parentInjector, nodeModule) {
+ assert(templateViewFactory != null);
+ nodeModule
+ ..factory(ViewPort, (_) =>
+ new ViewPort(node, parentInjector.get(Animate)))
+ ..value(ViewFactory, templateViewFactory)
+ ..factory(BoundViewFactory, (Injector injector) =>
+ templateViewFactory.bind(injector));
+ }
+}
+
+
+/**
+ * ElementBinder is created by the Selector and is responsible for instantiating
+ * individual directives and binding element properties.
+ */
+class ElementBinder {
+ // DI Services
+ final Profiler _perf;
+ final Expando _expando;
+ final Parser _parser;
+
+ // The default component factory
+ final ComponentFactory _componentFactory;
+ final TranscludingComponentFactory _transcludingComponentFactory;
+ final ShadowDomComponentFactory _shadowDomComponentFactory;
+ final Map onEvents;
+ final Map bindAttrs;
+
+ // Member fields
+ final decorators;
+
+ final DirectiveRef component;
+
+ // Can be either COMPILE_CHILDREN or IGNORE_CHILDREN
+ final String childMode;
+
+ ElementBinder(this._perf, this._expando, this._parser,
+ this._componentFactory,
+ this._transcludingComponentFactory,
+ this._shadowDomComponentFactory,
+ this.component, this.decorators,
+ this.onEvents, this.bindAttrs, this.childMode);
+
+ final bool hasTemplate = false;
+
+ bool get shouldCompileChildren =>
+ childMode == Directive.COMPILE_CHILDREN;
+
+ var _directiveCache;
+ List<DirectiveRef> get _usableDirectiveRefs {
+ if (_directiveCache != null) return _directiveCache;
+ if (component != null) return _directiveCache = new List.from(decorators)..add(component);
+ return _directiveCache = decorators;
+ }
+
+ bool get hasDirectivesOrEvents =>
+ _usableDirectiveRefs.isNotEmpty || onEvents.isNotEmpty;
+
+ _createAttrMappings(controller, scope, DirectiveRef ref, nodeAttrs, formatters, tasks) {
+ ref.mappings.forEach((MappingParts p) {
+ var attrName = p.attrName;
+ var dstExpression = p.dstExpression;
+ if (nodeAttrs == null) nodeAttrs = new _AnchorAttrs(ref);
+
+ Expression dstPathFn = _parser(dstExpression);
+ if (!dstPathFn.isAssignable) {
+ throw "Expression '$dstExpression' is not assignable in mapping '${p.originalValue}' "
+ "for attribute '$attrName'.";
+ }
+
+ switch (p.mode) {
+ case '@': // string
+ var taskId = tasks.registerTask();
+ nodeAttrs.observe(attrName, (value) {
+ dstPathFn.assign(controller, value);
+ tasks.completeTask(taskId);
+ });
+ break;
+
+ case '<=>': // two-way
+ if (nodeAttrs[attrName] == null) return;
+
+ var taskId = tasks.registerTask();
+ String expression = nodeAttrs[attrName];
+ Expression expressionFn = _parser(expression);
+ var viewOutbound = false;
+ var viewInbound = false;
+ scope.watch(expression, (inboundValue, _) {
+ if (!viewInbound) {
+ viewOutbound = true;
+ scope.rootScope.runAsync(() => viewOutbound = false);
+ var value = dstPathFn.assign(controller, inboundValue);
+ tasks.completeTask(taskId);
+ return value;
+ }
+ }, formatters: formatters);
+ if (expressionFn.isAssignable) {
+ scope.watch(dstExpression, (outboundValue, _) {
+ if (!viewOutbound) {
+ viewInbound = true;
+ scope.rootScope.runAsync(() => viewInbound = false);
+ expressionFn.assign(scope.context, outboundValue);
+ tasks.completeTask(taskId);
+ }
+ }, context: controller, formatters: formatters);
+ }
+ break;
+
+ case '=>': // one-way
+ if (nodeAttrs[attrName] == null) return;
+ var taskId = tasks.registerTask();
+
+ Expression attrExprFn = _parser(nodeAttrs[attrName]);
+ scope.watch(nodeAttrs[attrName], (v, _) {
+ dstPathFn.assign(controller, v);
+ tasks.completeTask(taskId);
+ }, formatters: formatters);
+ break;
+
+ case '=>!': // one-way, one-time
+ if (nodeAttrs[attrName] == null) return;
+
+ Expression attrExprFn = _parser(nodeAttrs[attrName]);
+ var watch;
+ watch = scope.watch(nodeAttrs[attrName], (value, _) {
+ if (dstPathFn.assign(controller, value) != null) {
+ watch.remove();
+ }
+ }, formatters: formatters);
+ break;
+
+ case '&': // callback
+ dstPathFn.assign(controller,
+ _parser(nodeAttrs[attrName]).bind(scope.context, ScopeLocals.wrapper));
+ break;
+ }
+ });
+ }
+
+ _link(nodeInjector, probe, scope, nodeAttrs, formatters) {
+ _usableDirectiveRefs.forEach((DirectiveRef ref) {
+ var linkTimer;
+ try {
+ var linkMapTimer;
+ assert((linkTimer = _perf.startTimer('ng.view.link', ref.type)) != false);
+ var controller = nodeInjector.get(ref.type);
+ probe.directives.add(controller);
+ assert((linkMapTimer = _perf.startTimer('ng.view.link.map', ref.type)) != false);
+
+ if (ref.annotation is Controller) {
+ scope.context[(ref.annotation as Controller).publishAs] = controller;
+ }
+
+ var tasks = new _TaskList(controller is AttachAware ? () {
+ if (scope.isAttached) controller.attach();
+ } : null);
+
+ _createAttrMappings(controller, scope, ref, nodeAttrs, formatters, tasks);
+
+ if (controller is AttachAware) {
+ var taskId = tasks.registerTask();
+ Watch watch;
+ watch = scope.watch('1', // Cheat a bit.
+ (_, __) {
+ watch.remove();
+ tasks.completeTask(taskId);
+ });
+ }
+
+ tasks.doneRegistering();
+
+ if (controller is DetachAware) {
+ scope.on(ScopeEvent.DESTROY).listen((_) => controller.detach());
+ }
+
+ assert(_perf.stopTimer(linkMapTimer) != false);
+ } finally {
+ assert(_perf.stopTimer(linkTimer) != false);
+ }
+ });
+ }
+
+ _createDirectiveFactories(DirectiveRef ref, nodeModule, node, nodesAttrsDirectives, nodeAttrs,
+ visibility) {
+ if (ref.type == TextMustache) {
+ nodeModule.factory(TextMustache, (Injector injector) {
+ return new TextMustache(node, ref.value, injector.get(Interpolate),
+ injector.get(Scope), injector.get(FormatterMap));
+ });
+ } else if (ref.type == AttrMustache) {
+ if (nodesAttrsDirectives.isEmpty) {
+ nodeModule.factory(AttrMustache, (Injector injector) {
+ var scope = injector.get(Scope);
+ var interpolate = injector.get(Interpolate);
+ for (var ref in nodesAttrsDirectives) {
+ new AttrMustache(nodeAttrs, ref.value, interpolate, scope,
+ injector.get(FormatterMap));
+ }
+ });
+ }
+ nodesAttrsDirectives.add(ref);
+ } else if (ref.annotation is Component) {
+ var factory;
+ var annotation = ref.annotation as Component;
+ if (annotation.useShadowDom == true) {
+ factory = _shadowDomComponentFactory;
+ } else if (annotation.useShadowDom == false) {
+ factory = _transcludingComponentFactory;
+ } else {
+ factory = _componentFactory;
+ }
+ nodeModule.factory(ref.type, factory.call(node, ref), visibility: visibility);
+ } else {
+ nodeModule.type(ref.type, visibility: visibility);
+ }
+ }
+
+ // Overridden in TemplateElementBinder
+ _registerViewFactory(node, parentInjector, nodeModule) {
+ nodeModule..factory(ViewPort, null)
+ ..factory(ViewFactory, null)
+ ..factory(BoundViewFactory, null);
+ }
+
+ Injector bind(View view, Injector parentInjector, dom.Node node) {
+ Injector nodeInjector;
+ Scope scope = parentInjector.get(Scope);
+ FormatterMap formatters = parentInjector.get(FormatterMap);
+ var nodeAttrs = node is dom.Element ? new NodeAttrs(node) : null;
+ ElementProbe probe;
+
+ var timerId;
+ assert((timerId = _perf.startTimer('ng.view.link.setUp', _html(node))) != false);
+ var directiveRefs = _usableDirectiveRefs;
+ try {
+ if (!hasDirectivesOrEvents) return parentInjector;
+
+ var nodesAttrsDirectives = [];
+ var nodeModule = new Module()
+ ..type(NgElement)
+ ..value(View, view)
+ ..value(dom.Element, node)
+ ..value(dom.Node, node)
+ ..value(NodeAttrs, nodeAttrs)
+ ..factory(ElementProbe, (_) => probe);
+
+ directiveRefs.forEach((DirectiveRef ref) {
+ Directive annotation = ref.annotation;
+ var visibility = ref.annotation.visibility;
+ if (ref.annotation is Controller) {
+ scope = scope.createChild(new PrototypeMap(scope.context));
+ nodeModule.value(Scope, scope);
+ }
+
+ _createDirectiveFactories(ref, nodeModule, node, nodesAttrsDirectives, nodeAttrs,
+ visibility);
+ if (ref.annotation.module != null) {
+ nodeModule.install(ref.annotation.module());
+ }
+ });
+
+ _registerViewFactory(node, parentInjector, nodeModule);
+
+ nodeInjector = parentInjector.createChild([nodeModule]);
+ probe = _expando[node] = new ElementProbe(
+ parentInjector.get(ElementProbe), node, nodeInjector, scope);
+ } finally {
+ assert(_perf.stopTimer(timerId) != false);
+ }
+
+ _link(nodeInjector, probe, scope, nodeAttrs, formatters);
+
+ onEvents.forEach((event, value) {
+ view.registerEvent(EventHandler.attrNameToEventName(event));
+ });
+ return nodeInjector;
+ }
+
+ String toString() => "[ElementBinder decorators:$decorators]";
+}
+
+/**
+ * Private class used for managing controller.attach() calls
+ */
+class _TaskList {
+ var onDone;
+ final List _tasks = [];
+ bool isDone = false;
+
+ _TaskList(this.onDone) {
+ if (onDone == null) isDone = true;
+ }
+
+ int registerTask() {
+ if (isDone) return null; // Do nothing if there is nothing to do.
+ _tasks.add(false);
+ return _tasks.length - 1;
+ }
+
+ void completeTask(id) {
+ if (isDone) return;
+ _tasks[id] = true;
+ if (_tasks.every((a) => a)) {
+ onDone();
+ isDone = true;
+ }
+ }
+
+ doneRegistering() {
+ completeTask(registerTask());
+ }
+}
+
+// Used for walking the DOM
+class ElementBinderTreeRef {
+ final int offsetIndex;
+ final ElementBinderTree subtree;
+
+ ElementBinderTreeRef(this.offsetIndex, this.subtree);
+}
+
+class ElementBinderTree {
+ final ElementBinder binder;
+ final List<ElementBinderTreeRef> subtrees;
+
+ ElementBinderTree(this.binder, this.subtrees);
+}
+
+class TaggedTextBinder {
+ final ElementBinder binder;
+ final int offsetIndex;
+
+ TaggedTextBinder(this.binder, this.offsetIndex);
+ toString() => "[TaggedTextBinder binder:$binder offset:$offsetIndex]";
+}
+
+// Used for the tagging compiler
+class TaggedElementBinder {
+ final ElementBinder binder;
+ int parentBinderOffset;
+ var injector;
+ bool isTopLevel;
+
+ List<TaggedTextBinder> textBinders;
+
+ TaggedElementBinder(this.binder, this.parentBinderOffset, this.isTopLevel);
+
+ void addText(TaggedTextBinder tagged) {
+ if (textBinders == null) textBinders = [];
+ textBinders.add(tagged);
+ }
+
+ String toString() => "[TaggedElementBinder binder:$binder parentBinderOffset:"
+ "$parentBinderOffset textBinders:$textBinders "
+ "injector:$injector]";
+}
« no previous file with comments | « third_party/pkg/angular/lib/core_dom/dom_util.dart ('k') | third_party/pkg/angular/lib/core_dom/element_binder_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698