Chromium Code Reviews| Index: tools/dom/src/dartium_CustomElementSupport.dart |
| diff --git a/tools/dom/src/dartium_CustomElementSupport.dart b/tools/dom/src/dartium_CustomElementSupport.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..df29593070b03ac280cb7b5255487686d51b8a62 |
| --- /dev/null |
| +++ b/tools/dom/src/dartium_CustomElementSupport.dart |
| @@ -0,0 +1,89 @@ |
| +// Copyright (c) 2014, 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. |
| + |
| +part of dart.dom.html; |
| + |
| +/// Dartium ElementUpgrader implementation. |
| +class _VMElementUpgrader implements ElementUpgrader { |
| + final Type _type; |
| + final Type _nativeType; |
| + |
| + _VMElementUpgrader(Document document, Type type, String extendsTag) : |
| + _type = type, |
| + _nativeType = _validateCustomType(type).reflectedType { |
| + |
| + if (extendsTag == null) { |
| + if (_nativeType != HtmlElement) { |
| + throw new UnsupportedError('Class must provide extendsTag if base ' |
| + 'native class is not HtmlElement'); |
| + } |
| + } else { |
| + if (document.createElement(extendsTag).runtimeType != _nativeType) { |
| + throw new UnsupportedError( |
| + 'extendsTag does not match base native class'); |
| + } |
| + } |
| + } |
| + |
| + Element upgrade(Element element) { |
| + if (element.runtimeType != _nativeType) { |
| + throw new UnsupportedError('Element is incorrect type'); |
| + } |
| + return _Utils.changeElementWrapper(element, _type); |
| + return null; |
| + } |
| +} |
| + |
| +/// Validates that the custom type is properly formed- |
| +/// |
| +/// * Is a user-defined class. |
| +/// * Has a created constructor with zero args. |
| +/// * Derives from an Element subclass. |
| +/// |
| +/// Then returns the native base class. |
| +ClassMirror _validateCustomType(Type type) { |
| + ClassMirror cls = reflectClass(type); |
| + if (_isBuiltinType(cls)) { |
| + throw new UnsupportedError('Invalid custom element from ' |
| + '${(cls.owner as LibraryMirror).uri}.'); |
| + } |
| + |
| + var className = MirrorSystem.getName(cls.simpleName); |
| + var createdConstructor = cls.declarations[new Symbol('$className.created')]; |
| + if (createdConstructor == null || |
| + createdConstructor is! MethodMirror || |
| + !createdConstructor.isConstructor) { |
| + throw new UnsupportedError( |
| + 'Class is missing constructor $className.created'); |
| + } |
| + |
| + if (createdConstructor.parameters.length > 0) { |
| + throw new UnsupportedError( |
| + 'Constructor $className.created must take zero arguments'); |
| + } |
| + |
| + Symbol objectName = reflectClass(Object).qualifiedName; |
|
Jennifer Messerly
2014/03/07 00:00:49
note: my comments below are before I realized this
|
| + bool isRoot(ClassMirror cls) => |
| + cls == null || cls.qualifiedName == objectName; |
| + Symbol elementName = reflectClass(HtmlElement).qualifiedName; |
|
Jennifer Messerly
2014/03/07 00:00:49
Hmmm. It might be more reliable to compare reflect
|
| + bool isElement(ClassMirror cls) => |
| + cls != null && cls.qualifiedName == elementName; |
| + ClassMirror superClass = cls.superclass; |
| + ClassMirror nativeClass = _isBuiltinType(superClass) ? superClass : null; |
| + while(!isRoot(superClass) && !isElement(superClass)) { |
|
Jennifer Messerly
2014/03/07 00:00:49
for isRoot, you could just walk up superClass == n
|
| + superClass = superClass.superclass; |
| + if (nativeClass == null && _isBuiltinType(superClass)) { |
| + nativeClass = superClass; |
| + } |
| + } |
| + return nativeClass; |
| +} |
| + |
| + |
| +bool _isBuiltinType(ClassMirror cls) { |
| + // TODO(vsm): Find a less hackish way to do this. |
|
Jennifer Messerly
2014/03/07 00:00:49
ah, I see. I think instances compare correctly in
|
| + LibraryMirror lib = cls.owner; |
| + String libName = lib.uri.toString(); |
| + return libName.startsWith('dart:'); |
| +} |