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

Unified Diff: packages/polymer_expressions/lib/polymer_expressions.dart

Issue 2312183003: Removed Polymer from Observatory deps (Closed)
Patch Set: Created 4 years, 3 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
« no previous file with comments | « packages/polymer_expressions/lib/parser.dart ('k') | packages/polymer_expressions/lib/src/globals.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/polymer_expressions/lib/polymer_expressions.dart
diff --git a/packages/polymer_expressions/lib/polymer_expressions.dart b/packages/polymer_expressions/lib/polymer_expressions.dart
deleted file mode 100644
index 332e3a1ae9c2b8e8fa63b20e455718b44926847e..0000000000000000000000000000000000000000
--- a/packages/polymer_expressions/lib/polymer_expressions.dart
+++ /dev/null
@@ -1,397 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/**
- * A binding delegate used with Polymer elements that
- * allows for complex binding expressions, including
- * property access, function invocation,
- * list/map indexing, and two-way filtering.
- *
- * When you install polymer.dart,
- * polymer_expressions is automatically installed as well.
- *
- * Polymer expressions are part of the Polymer.dart project.
- * Refer to the
- * [Polymer.dart](http://www.dartlang.org/polymer-dart/)
- * homepage for example code, project status, and
- * information about how to get started using Polymer.dart in your apps.
- *
- * ## Other resources
- *
- * The
- * [Polymer expressions](http://pub.dartlang.org/packages/polymer_expressions)
- * pub repository contains detailed documentation about using polymer
- * expressions.
- */
-
-library polymer_expressions;
-
-import 'dart:async';
-import 'dart:html';
-
-import 'package:observe/observe.dart';
-import 'package:template_binding/template_binding.dart';
-
-import 'eval.dart';
-import 'expression.dart';
-import 'parser.dart';
-import 'src/globals.dart';
-
-Object _classAttributeConverter(v) =>
- (v is Map) ? v.keys.where((k) => v[k] == true).join(' ') :
- (v is Iterable) ? v.join(' ') :
- v;
-
-Object _styleAttributeConverter(v) =>
- (v is Map) ? v.keys.map((k) => '$k: ${v[k]}').join(';') :
- (v is Iterable) ? v.join(';') :
- v;
-
-class PolymerExpressions extends BindingDelegate {
- /** The default [globals] to use for Polymer expressions. */
- static const Map DEFAULT_GLOBALS = const { 'enumerate': enumerate };
-
- final ScopeFactory _scopeFactory;
- final Map<String, Object> globals;
-
- // allows access to scopes created for template instances
- final Expando<Scope> _scopes = new Expando<Scope>();
- // allows access to scope identifiers (for "in" and "as")
- final Expando<String> _scopeIdents = new Expando<String>();
-
- /**
- * Creates a new binding delegate for Polymer expressions, with the provided
- * variables used as [globals]. If no globals are supplied, a copy of the
- * [DEFAULT_GLOBALS] will be used.
- */
- PolymerExpressions({Map<String, Object> globals,
- ScopeFactory scopeFactory: const ScopeFactory()})
- : globals = globals == null ?
- new Map<String, Object>.from(DEFAULT_GLOBALS) : globals,
- _scopeFactory = scopeFactory;
-
- @override
- PrepareBindingFunction prepareBinding(String path, name, Node boundNode) {
- if (path == null) return null;
- var expr = new Parser(path).parse();
-
- if (isSemanticTemplate(boundNode) && (name == 'bind' || name == 'repeat')) {
- if (expr is HasIdentifier) {
- var identifier = expr.identifier;
- var bindExpr = expr.expr;
- return (model, Node node, bool oneTime) {
- _scopeIdents[node] = identifier;
- // model may not be a Scope if it was assigned directly via
- // template.model = x; In that case, prepareInstanceModel will
- // be called _after_ prepareBinding and will lookup this scope from
- // _scopes
- var scope = _scopes[node] = (model is Scope)
- ? model
- : _scopeFactory.modelScope(model: model, variables: globals);
- return new _Binding(bindExpr, scope);
- };
- } else {
- return (model, Node node, bool oneTime) {
- var scope = _scopes[node] = (model is Scope)
- ? model
- : _scopeFactory.modelScope(model: model, variables: globals);
- if (oneTime) {
- return _Binding._oneTime(expr, scope);
- }
- return new _Binding(expr, scope);
- };
- }
- }
-
- // For regular bindings, not bindings on a template, the model is always
- // a Scope created by prepareInstanceModel
- _Converter converter = null;
- if (boundNode is Element && name == 'class') {
- converter = _classAttributeConverter;
- } else if (boundNode is Element && name == 'style') {
- converter = _styleAttributeConverter;
- }
-
- return (model, Node node, bool oneTime) {
- var scope = _getScopeForModel(node, model);
- if (oneTime) {
- return _Binding._oneTime(expr, scope, converter);
- }
- return new _Binding(expr, scope, converter);
- };
- }
-
- prepareInstanceModel(Element template) {
- var ident = _scopeIdents[template];
-
- if (ident == null) {
- return (model) {
- var existingScope = _scopes[template];
- // TODO (justinfagnani): make template binding always call
- // prepareInstanceModel first and get rid of this check
- if (existingScope != null) {
- // If there's an existing scope, we created it in prepareBinding
- // If it has the same model, then we can reuse it, otherwise it's
- // a repeat with no identifier and we create new scope to occlude
- // the outer one
- if (model == existingScope.model) return existingScope;
- return _scopeFactory.modelScope(model: model, variables: globals);
- } else {
- return _getScopeForModel(template, model);
- }
- };
- }
-
- return (model) {
- var existingScope = _scopes[template];
- if (existingScope != null) {
- // This only happens when a model has been assigned programatically
- // and prepareBinding is called _before_ prepareInstanceModel.
- // The scope assigned in prepareBinding wraps the model and is the
- // scope of the expression. That should be the parent of the templates
- // scope in the case of bind/as or repeat/in bindings.
- return _scopeFactory.childScope(existingScope, ident, model);
- } else {
- // If there's not an existing scope then we have a bind/as or
- // repeat/in binding enclosed in an outer scope, so we use that as
- // the parent
- var parentScope = _getParentScope(template);
- return _scopeFactory.childScope(parentScope, ident, model);
- }
- };
- }
-
- /**
- * Gets an existing scope for use as a parent, but does not create a new one.
- */
- Scope _getParentScope(Node node) {
- var parent = node.parentNode;
- if (parent == null) return null;
-
- if (isSemanticTemplate(node)) {
- var templateExtension = templateBind(node);
- var templateInstance = templateExtension.templateInstance;
- var model = templateInstance == null
- ? templateExtension.model
- : templateInstance.model;
- if (model is Scope) {
- return model;
- } else {
- // A template with a bind binding might have a non-Scope model
- return _scopes[node];
- }
- }
- if (parent != null) return _getParentScope(parent);
- return null;
- }
-
- /**
- * Returns the Scope to be used to evaluate expressions in the template
- * containing [node]. Since all expressions in the same template evaluate
- * against the same model, [model] is passed in and checked against the
- * template model to make sure they agree.
- *
- * For nested templates, we might have a binding on the nested template that
- * should be evaluated in the context of the parent template. All scopes are
- * retreived from an ancestor of [node], since node may be establishing a new
- * Scope.
- */
- Scope _getScopeForModel(Node node, model) {
- // This only happens in bindings_test because it calls prepareBinding()
- // directly. Fix the test and throw if node is null?
- if (node == null) {
- return _scopeFactory.modelScope(model: model, variables: globals);
- }
-
- var id = node is Element ? node.id : '';
- if (model is Scope) {
- return model;
- }
- if (_scopes[node] != null) {
- var scope = _scopes[node];
- assert(scope.model == model);
- return _scopes[node];
- } else if (node.parentNode != null) {
- return _getContainingScope(node.parentNode, model);
- } else {
- // here we should be at a top-level template, so there's no parent to
- // look for a Scope on.
- if (!isSemanticTemplate(node)) {
- throw "expected a template instead of $node";
- }
- return _getContainingScope(node, model);
- }
- }
-
- Scope _getContainingScope(Node node, model) {
- if (isSemanticTemplate(node)) {
- var templateExtension = templateBind(node);
- var templateInstance = templateExtension.templateInstance;
- var templateModel = templateInstance == null
- ? templateExtension.model
- : templateInstance.model;
- assert(templateModel == model);
- var scope = _scopes[node];
- assert(scope != null);
- assert(scope.model == model);
- return scope;
- } else if (node.parent == null) {
- var scope = _scopes[node];
- if (scope != null) {
- assert(scope.model == model);
- } else {
- // only happens in bindings_test
- scope = _scopeFactory.modelScope(model: model, variables: globals);
- }
- return scope;
- } else {
- return _getContainingScope(node.parentNode, model);
- }
- }
-
- /// Parse the expression string and return an expression tree.
- static Expression getExpression(String exprString) =>
- new Parser(exprString).parse();
-
- /// Determines the value of evaluating [expr] on the given [model] and returns
- /// either its value or a binding for it. If [oneTime] is true, it direclty
- /// returns the value. Otherwise, when [oneTime] is false, it returns a
- /// [Bindable] that besides evaluating the expression, it will also react to
- /// observable changes from the model and update the value accordingly.
- static getBinding(Expression expr, model, {Map<String, Object> globals,
- oneTime: false}) {
- if (globals == null) globals = new Map.from(DEFAULT_GLOBALS);
- var scope = model is Scope ? model
- : new Scope(model: model, variables: globals);
- return oneTime ? _Binding._oneTime(expr, scope)
- : new _Binding(expr, scope);
- }
-}
-
-typedef Object _Converter(Object);
-
-class _Binding extends Bindable {
- final Scope _scope;
- final _Converter _converter;
- final Expression _expr;
-
- Function _callback;
- StreamSubscription _sub;
- ExpressionObserver _observer;
- var _value;
-
- _Binding(this._expr, this._scope, [this._converter]);
-
- static Object _oneTime(Expression expr, Scope scope, [_Converter converter]) {
- try {
- var value = eval(expr, scope);
- return (converter == null) ? value : converter(value);
- } catch (e, s) {
- new Completer().completeError(
- "Error evaluating expression '$expr': $e", s);
- }
- return null;
- }
-
- bool _convertAndCheck(newValue, {bool skipChanges: false}) {
- var oldValue = _value;
- _value = _converter == null ? newValue : _converter(newValue);
-
- if (!skipChanges && _callback != null && oldValue != _value) {
- _callback(_value);
- return true;
- }
- return false;
- }
-
- get value {
- // if there's a callback, then _value has been set, if not we need to
- // force an evaluation
- if (_callback != null) {
- _check(skipChanges: true);
- return _value;
- }
- return _Binding._oneTime(_expr, _scope, _converter);
- }
-
- set value(v) {
- try {
- assign(_expr, v, _scope, checkAssignability: false);
- } catch (e, s) {
- new Completer().completeError(
- "Error evaluating expression '$_expr': $e", s);
- }
- }
-
- Object open(callback(value)) {
- if (_callback != null) throw new StateError('already open');
-
- _callback = callback;
- _observer = observe(_expr, _scope);
- _sub = _observer.onUpdate.listen(_convertAndCheck)..onError((e, s) {
- new Completer().completeError(
- "Error evaluating expression '$_observer': $e", s);
- });
-
- _check(skipChanges: true);
- return _value;
- }
-
- bool _check({bool skipChanges: false}) {
- try {
- update(_observer, _scope, skipChanges: skipChanges);
- return _convertAndCheck(_observer.currentValue, skipChanges: skipChanges);
- } catch (e, s) {
- new Completer().completeError(
- "Error evaluating expression '$_observer': $e", s);
- return false;
- }
- }
-
- void close() {
- if (_callback == null) return;
-
- _sub.cancel();
- _sub = null;
- _callback = null;
-
- new Closer().visit(_observer);
- _observer = null;
- }
-
-
- // TODO(jmesserly): the following code is copy+pasted from path_observer.dart
- // What seems to be going on is: polymer_expressions.dart has its own _Binding
- // unlike polymer-expressions.js, which builds on CompoundObserver.
- // This can lead to subtle bugs and should be reconciled. I'm not sure how it
- // should go, but CompoundObserver does have some nice optimizations around
- // ObservedSet which are lacking here. And reuse is nice.
- void deliver() {
- if (_callback != null) _dirtyCheck();
- }
-
- bool _dirtyCheck() {
- var cycles = 0;
- while (cycles < _MAX_DIRTY_CHECK_CYCLES && _check()) {
- cycles++;
- }
- return cycles > 0;
- }
-
- static const int _MAX_DIRTY_CHECK_CYCLES = 1000;
-}
-
-_identity(x) => x;
-
-/**
- * Factory function used for testing.
- */
-class ScopeFactory {
- const ScopeFactory();
- modelScope({Object model, Map<String, Object> variables}) =>
- new Scope(model: model, variables: variables);
-
- childScope(Scope parent, String name, Object value) =>
- parent.childScope(name, value);
-}
« no previous file with comments | « packages/polymer_expressions/lib/parser.dart ('k') | packages/polymer_expressions/lib/src/globals.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698