Index: sdk/lib/html/dartium/html_dartium.dart |
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart |
index ae546ccaa9e99b364658786784152a0c8a7685d8..42329d6cc2932d3b7e04f4502b957a0ff5cdee81 100644 |
--- a/sdk/lib/html/dartium/html_dartium.dart |
+++ b/sdk/lib/html/dartium/html_dartium.dart |
@@ -301,6 +301,7 @@ const htmlBlinkMap = const { |
'History': History, |
'ImageBitmap': ImageBitmap, |
'ImageData': ImageData, |
+ 'InjectedScriptHost': InjectedScriptHost, |
'InputMethodContext': InputMethodContext, |
'InstallEvent': InstallEvent, |
'InstallPhaseEvent': InstallPhaseEvent, |
@@ -3406,7 +3407,7 @@ class CssRule extends NativeFieldWrapperClass2 { |
@DomName('CSSStyleDeclaration') |
- class CssStyleDeclaration extends NativeFieldWrapperClass2 with |
+ class CssStyleDeclaration extends NativeFieldWrapperClass2 with |
CssStyleDeclarationBase { |
factory CssStyleDeclaration() => new CssStyleDeclaration.css(''); |
@@ -3415,7 +3416,7 @@ class CssRule extends NativeFieldWrapperClass2 { |
style.cssText = css; |
return style; |
} |
- |
+ |
String getPropertyValue(String propertyName) { |
var propValue = _getPropertyValue(propertyName); |
return propValue != null ? propValue : ''; |
@@ -3503,7 +3504,7 @@ class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase { |
} |
abstract class CssStyleDeclarationBase { |
- String getPropertyValue(String propertyName); |
+ String getPropertyValue(String propertyName); |
void setProperty(String propertyName, String value, [String priority]); |
// TODO(jacobr): generate this list of properties using the existing script. |
@@ -4363,8 +4364,8 @@ abstract class CssStyleDeclarationBase { |
} |
/** Gets the value of "box-sizing" */ |
- String get boxSizing => Device.isFirefox ? |
- getPropertyValue('${Device.cssPrefix}box-sizing') : |
+ String get boxSizing => Device.isFirefox ? |
+ getPropertyValue('${Device.cssPrefix}box-sizing') : |
getPropertyValue('box-sizing'); |
/** Sets the value of "box-sizing" */ |
@@ -7580,7 +7581,7 @@ class DivElement extends HtmlElement { |
* [Target 2: Connect Dart & HTML](http://www.dartlang.org/docs/tutorials/connect-dart-html/). |
*/ |
@DomName('Document') |
-class Document extends Node |
+class Document extends Node |
{ |
// To suppress missing implicit constructor warnings. |
@@ -8384,7 +8385,7 @@ class DocumentFragment extends Node implements ParentNode { |
this.append(new DocumentFragment.html(text)); |
} |
- /** |
+ /** |
* Alias for [querySelector]. Note this function is deprecated because its |
* semantics will be changing in the future. |
*/ |
@@ -8395,7 +8396,7 @@ class DocumentFragment extends Node implements ParentNode { |
return querySelector(relativeSelectors); |
} |
- /** |
+ /** |
* Alias for [querySelectorAll]. Note this function is deprecated because its |
* semantics will be changing in the future. |
*/ |
@@ -12310,7 +12311,7 @@ class Event extends NativeFieldWrapperClass2 { |
e._initEvent(name, canBubble, cancelable); |
return e; |
} |
- |
+ |
/** The CSS selector involved with event delegation. */ |
String _selector; |
@@ -12606,18 +12607,18 @@ class ElementEvents extends Events { |
/* Raw event target. */ |
final Element _ptr; |
static final webkitEvents = { |
- 'animationend' : 'webkitAnimationEnd', |
- 'animationiteration' : 'webkitAnimationIteration', |
- 'animationstart' : 'webkitAnimationStart', |
- 'fullscreenchange' : 'webkitfullscreenchange', |
+ 'animationend' : 'webkitAnimationEnd', |
+ 'animationiteration' : 'webkitAnimationIteration', |
+ 'animationstart' : 'webkitAnimationStart', |
+ 'fullscreenchange' : 'webkitfullscreenchange', |
'fullscreenerror' : 'webkitfullscreenerror', |
- 'keyadded' : 'webkitkeyadded', |
- 'keyerror' : 'webkitkeyerror', |
- 'keymessage' : 'webkitkeymessage', |
- 'needkey' : 'webkitneedkey', |
- 'pointerlockchange' : 'webkitpointerlockchange', |
- 'pointerlockerror' : 'webkitpointerlockerror', |
- 'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull', |
+ 'keyadded' : 'webkitkeyadded', |
+ 'keyerror' : 'webkitkeyerror', |
+ 'keymessage' : 'webkitkeymessage', |
+ 'needkey' : 'webkitneedkey', |
+ 'pointerlockchange' : 'webkitpointerlockchange', |
+ 'pointerlockerror' : 'webkitpointerlockerror', |
+ 'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull', |
'transitionend': 'webkitTransitionEnd', |
'speechchange' : 'webkitSpeechChange' |
}; |
@@ -15609,7 +15610,7 @@ class HttpRequest extends HttpRequestEventTarget { |
* |
* By default `request` will perform an HTTP GET request, but a different |
* method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the |
- * [method] parameter. (See also [HttpRequest.postFormData] for `POST` |
+ * [method] parameter. (See also [HttpRequest.postFormData] for `POST` |
* requests only. |
* |
* The Future is completed when the response is available. |
@@ -15618,8 +15619,8 @@ class HttpRequest extends HttpRequestEventTarget { |
* [Blob], [Document], [String], or [FormData] along with the HttpRequest. |
* |
* If specified, [responseType] sets the desired response format for the |
- * request. By default it is [String], but can also be 'arraybuffer', 'blob', |
- * 'document', 'json', or 'text'. See also [HttpRequest.responseType] |
+ * request. By default it is [String], but can also be 'arraybuffer', 'blob', |
+ * 'document', 'json', or 'text'. See also [HttpRequest.responseType] |
* for more information. |
* |
* The [withCredentials] parameter specified that credentials such as a cookie |
@@ -16557,6 +16558,26 @@ class ImageElement extends HtmlElement implements CanvasImageSource { |
// 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. |
+// WARNING: Do not edit - generated code. |
+ |
+ |
+@DocsEditable() |
+@DomName('InjectedScriptHost') |
+@Experimental() // untriaged |
+class InjectedScriptHost extends NativeFieldWrapperClass2 { |
+ // To suppress missing implicit constructor warnings. |
+ factory InjectedScriptHost._() { throw new UnsupportedError("Not supported"); } |
+ |
+ @DomName('InjectedScriptHost.inspect') |
+ @DocsEditable() |
+ @Experimental() // untriaged |
+ void inspect(Object objectId, Object hints) => _blink.Native_InjectedScriptHost_inspect_Callback(this, objectId, hints); |
+ |
+} |
+// Copyright (c) 2012, 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. |
+ |
@DomName('HTMLInputElement') |
class InputElement extends HtmlElement implements |
@@ -36997,7 +37018,7 @@ class FixedSizeListIterator<T> implements Iterator<T> { |
final int _length; // Cache array length for faster access. |
int _position; |
T _current; |
- |
+ |
FixedSizeListIterator(List<T> array) |
: _array = array, |
_position = -1, |
@@ -37474,6 +37495,32 @@ abstract class ElementUpgrader { |
// BSD-style license that can be found in the LICENSE file. |
+class _Property { |
+ _Property(this.name) : |
+ _hasValue = false, |
+ writable = false, |
+ isMethod = false, |
+ isOwn = true, |
+ wasThrown = false; |
+ |
+ bool get hasValue => _hasValue; |
+ get value => _value; |
+ set value(v) { |
+ _value = v; |
+ _hasValue = true; |
+ } |
+ |
+ final String name; |
+ Function setter; |
+ Function getter; |
+ var _value; |
+ bool _hasValue; |
+ bool writable; |
+ bool isMethod; |
+ bool isOwn; |
+ bool wasThrown; |
+} |
+ |
class _ConsoleVariables { |
Map<String, Object> _data = new Map<String, Object>(); |
@@ -37489,7 +37536,8 @@ class _ConsoleVariables { |
member = member.substring(0, member.length - 1); |
_data[member] = invocation.positionalArguments[0]; |
} else { |
- return Function.apply(_data[member], invocation.positionalArguments, invocation.namedArguments); |
+ return Function.apply(_data[member], invocation.positionalArguments, |
+ invocation.namedArguments); |
} |
} |
@@ -37498,7 +37546,60 @@ class _ConsoleVariables { |
/** |
* List all variables currently defined. |
*/ |
- List variables() => _data.keys.toList(growable: false); |
+ List variables() => _data.keys.toList(); |
+ |
+ void setVariable(String name, value) { |
+ _data[name] = value; |
+ } |
+} |
+ |
+/** |
+ * Base class for invocation trampolines used to closurize methods, getters |
+ * and setters. |
+ */ |
+abstract class _Trampoline implements Function { |
+ final ObjectMirror _receiver; |
+ final MethodMirror _methodMirror; |
+ final Symbol _selector; |
+ |
+ _Trampoline(this._receiver, this._methodMirror, this._selector); |
+} |
+ |
+class _MethodTrampoline extends _Trampoline { |
+ _MethodTrampoline(ObjectMirror receiver, MethodMirror methodMirror, |
+ Symbol selector) : |
+ super(receiver, methodMirror, selector); |
+ |
+ noSuchMethod(Invocation msg) { |
+ if (msg.memberName != #call) return super.noSuchMethod(msg); |
+ return _receiver.invoke(_selector, |
+ msg.positionalArguments, |
+ msg.namedArguments).reflectee; |
+ } |
+} |
+ |
+/** |
+ * Invocation trampoline class used to closurize getters. |
+ */ |
+class _GetterTrampoline extends _Trampoline { |
+ _GetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror, |
+ Symbol selector) : |
+ super(receiver, methodMirror, selector); |
+ |
+ call() => _receiver.getField(_selector).reflectee; |
+} |
+ |
+/** |
+ * Invocation trampoline class used to closurize setters. |
+ */ |
+class _SetterTrampoline extends _Trampoline { |
+ _SetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror, |
+ Symbol selector) : |
+ super(receiver, methodMirror, selector); |
+ |
+ call(value) { |
+ _receiver.setField(_selector, value); |
+ } |
} |
class _Utils { |
@@ -37614,27 +37715,6 @@ class _Utils { |
static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables(); |
/** |
- * Header passed in from the Dartium Developer Tools when an expression is |
- * evaluated in the console as opposed to the watch window or another context |
- * that does not expect REPL support in Dartium 34. |
- */ |
- static const _CONSOLE_API_SUPPORT_HEADER_34 = |
- 'with ((console && console._commandLineAPI) || { __proto__: null }) {\n'; |
- /** |
- * Header passed in from the Dartium Developer Tools when an expression is |
- * evaluated in the console as opposed to the watch window or another context |
- * that does not expect REPL support in Dartium 35. |
- */ |
- static const _CONSOLE_API_SUPPORT_HEADER_35 = |
- 'with (__commandLineAPI || { __proto__: null }) {\n'; |
- |
- |
- static bool expectsConsoleApi(String expression) { |
- return expression.indexOf(_CONSOLE_API_SUPPORT_HEADER_34) == 0 || |
- expression.indexOf(_CONSOLE_API_SUPPORT_HEADER_35) == 0; |
- } |
- |
- /** |
* Takes an [expression] and a list of [local] variable and returns an |
* expression for a closure with a body matching the original expression |
* where locals are passed in as arguments. Returns a list containing the |
@@ -37646,8 +37726,7 @@ class _Utils { |
* For example: |
* <code> |
* _consoleTempVariables = {'a' : someValue, 'b': someOtherValue} |
- * wrapExpressionAsClosure("${_CONSOLE_API_SUPPORT_HEADER35}foo + bar + a", |
- * ["bar", 40, "foo", 2]) |
+ * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true) |
* </code> |
* will return: |
* <code> |
@@ -37657,9 +37736,8 @@ class _Utils { |
* [_consoleTempVariables, 40, 2, someValue, someOtherValue]] |
* </code> |
*/ |
- static List wrapExpressionAsClosure(String expression, List locals) { |
- // FIXME: dartbug.com/10434 find a less fragile way to determine whether |
- // we need to strip off console API support added by InjectedScript. |
+ static List wrapExpressionAsClosure(String expression, List locals, |
+ bool includeCommandLineAPI) { |
var args = {}; |
var sb = new StringBuffer("("); |
addArg(arg, value) { |
@@ -37678,10 +37756,7 @@ class _Utils { |
args[arg] = value; |
} |
- if (expectsConsoleApi(expression)) { |
- expression = expression.substring(expression.indexOf('\n') + 1); |
- expression = expression.substring(0, expression.lastIndexOf('\n')); |
- |
+ if (includeCommandLineAPI) { |
addArg("\$consoleVariables", _consoleTempVariables); |
// FIXME: use a real Dart tokenizer. The following regular expressions |
@@ -37738,13 +37813,19 @@ class _Utils { |
return [sb.toString(), args.values.toList(growable: false)]; |
} |
- /** |
- * TODO(jacobr): this is a big hack to get around the fact that we are still |
- * passing some JS expression to the evaluate method even when in a Dart |
- * context. |
- */ |
- static bool isJsExpression(String expression) => |
- expression.startsWith("(function getCompletions"); |
+ static String _getShortSymbolName(Symbol symbol, |
+ DeclarationMirror declaration) { |
+ var name = MirrorSystem.getName(symbol); |
+ if (declaration is MethodMirror) { |
+ if (declaration.isSetter && name[name.length-1] == "=") { |
+ return name.substring(0, name.length-1); |
+ } |
+ if (declaration.isConstructor) { |
+ return name.substring(name.indexOf('.') + 1); |
+ } |
+ } |
+ return name; |
+ } |
/** |
* Returns a list of completions to use if the receiver is o. |
@@ -37783,97 +37864,406 @@ class _Utils { |
} |
/** |
- * Convenience helper to get the keys of a [Map] as a [List]. |
- */ |
- static List getMapKeyList(Map map) => map.keys.toList(); |
+ * Adds all candidate String completitions from [declarations] to [output] |
+ * filtering based on [staticContext] and [includePrivate]. |
+ */ |
+ static void _getCompletionsHelper(ClassMirror classMirror, |
+ bool staticContext, LibraryMirror libraryMirror, Set<String> output) { |
+ bool includePrivate = libraryMirror == classMirror.owner; |
+ classMirror.declarations.forEach((symbol, declaration) { |
+ if (!includePrivate && declaration.isPrivate) return; |
+ if (declaration is VariableMirror) { |
+ if (staticContext != declaration.isStatic) return; |
+ } else if (declaration is MethodMirror) { |
+ if (declaration.isOperator) return; |
+ if (declaration.isConstructor) { |
+ if (!staticContext) return; |
+ var name = MirrorSystem.getName(declaration.constructorName); |
+ if (name.isNotEmpty) output.add(name); |
+ return; |
+ } |
+ if (staticContext != declaration.isStatic) return; |
+ } else if (declaration is TypeMirror) { |
+ return; |
+ } |
+ output.add(_getShortSymbolName(symbol, declaration)); |
+ }); |
- /** |
- * Returns the keys of an arbitrary Dart Map encoded as unique Strings. |
- * Keys that are strings are left unchanged except that the prefix ":" is |
- * added to disambiguate keys from other Dart members. |
- * Keys that are not strings have # followed by the index of the key in the map |
- * prepended to disambuguate. This scheme is simplistic but easy to encode and |
- * decode. The use case for this method is displaying all map keys in a human |
- * readable way in debugging tools. |
- */ |
- static List<String> getEncodedMapKeyList(dynamic obj) { |
- if (obj is! Map) return null; |
- |
- var ret = new List<String>(); |
- int i = 0; |
- return obj.keys.map((key) { |
- var encodedKey; |
- if (key is String) { |
- encodedKey = ':$key'; |
- } else { |
- // If the key isn't a string, return a guaranteed unique for this map |
- // string representation of the key that is still somewhat human |
- // readable. |
- encodedKey = '#${i}:$key'; |
+ if (!staticContext) { |
+ for (var interface in classMirror.superinterfaces) { |
+ _getCompletionsHelper(interface, staticContext, |
+ libraryMirror, output); |
} |
- i++; |
- return encodedKey; |
- }).toList(growable: false); |
- } |
- |
- static final RegExp _NON_STRING_KEY_REGEXP = new RegExp("^#(\\d+):(.+)\$"); |
- |
- static _decodeKey(Map map, String key) { |
- // The key is a regular old String. |
- if (key.startsWith(':')) return key.substring(1); |
- |
- var match = _NON_STRING_KEY_REGEXP.firstMatch(key); |
- if (match != null) { |
- int index = int.parse(match.group(1)); |
- var iter = map.keys.skip(index); |
- if (iter.isNotEmpty) { |
- var ret = iter.first; |
- // Validate that the toString representation of the key matches what we |
- // expect. FIXME: throw an error if it does not. |
- assert(match.group(2) == '$ret'); |
- return ret; |
+ if (classMirror.superclass != null) { |
+ _getCompletionsHelper(classMirror.superclass, staticContext, |
+ libraryMirror, output); |
} |
} |
- return null; |
} |
+ static void _getLibraryCompletionsHelper( |
+ LibraryMirror library, bool includePrivate, Set<String> output) { |
+ library.declarations.forEach((symbol, declaration) { |
+ if (!includePrivate && declaration.isPrivate) return; |
+ output.add(_getShortSymbolName(symbol, declaration)); |
+ }); |
+ } |
+ |
+ static LibraryMirror getLibraryMirror(String url) => |
+ currentMirrorSystem().libraries[Uri.parse(url)]; |
+ |
/** |
- * Converts keys encoded with [getEncodedMapKeyList] to their actual keys. |
+ * Get code completions for [o] only showing privates from [libraryUrl]. |
*/ |
- static lookupValueForEncodedMapKey(Map obj, String key) => obj[_decodeKey(obj, key)]; |
+ static List<String> getObjectCompletions(o, String libraryUrl) { |
+ var classMirror; |
+ bool staticContext; |
+ if (o is Type) { |
+ classMirror = reflectClass(o); |
+ staticContext = true; |
+ } else { |
+ classMirror = reflect(o).type; |
+ staticContext = false; |
+ } |
+ var names = new Set<String>(); |
+ getClassCompletions(classMirror, names, staticContext, libraryUrl); |
+ return names.toList()..sort(); |
+ } |
+ |
+ static void getClassCompletions(ClassMirror classMirror, Set<String> names, |
+ bool staticContext, String libraryUrl) { |
+ LibraryMirror libraryMirror = getLibraryMirror(libraryUrl); |
+ _getCompletionsHelper(classMirror, staticContext, libraryMirror, names); |
+ } |
+ |
+ static List<String> getLibraryCompletions(String url) { |
+ var names = new Set<String>(); |
+ _getLibraryCompletionsHelper(getLibraryMirror(url), true, names); |
+ return names.toList(); |
+ } |
/** |
- * Builds a constructor name with the form expected by the C Dart mirrors API. |
+ * Get valid code completitions from within a library and all libraries |
+ * imported by that library. |
*/ |
- static String buildConstructorName(String className, String constructorName) => '$className.$constructorName'; |
+ static List<String> getLibraryCompletionsIncludingImports(String url) { |
+ var names = new Set<String>(); |
+ var libraryMirror = getLibraryMirror(url); |
+ _getLibraryCompletionsHelper(libraryMirror, true, names); |
+ for (var dependency in libraryMirror.libraryDependencies) { |
+ if (dependency.isImport) { |
+ if (dependency.prefix == null) { |
+ _getLibraryCompletionsHelper(dependency.targetLibrary, false, names); |
+ } else { |
+ names.add(MirrorSystem.getName(dependency.prefix)); |
+ } |
+ } |
+ } |
+ return names.toList(); |
+ } |
+ |
+ static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>() |
+ ..add('dart:html') |
+ ..add('dart:indexed_db') |
+ ..add('dart:svg') |
+ ..add('dart:typed_data') |
+ ..add('dart:web_audio') |
+ ..add('dart:web_gl') |
+ ..add('dart:web_sql'); |
+ |
+ static LibraryMirror _getLibrary(MethodMirror methodMirror) { |
+ var owner = methodMirror.owner; |
+ if (owner is ClassMirror) { |
+ return owner; |
+ } else if (owner is LibraryMirror) { |
+ return owner; |
+ } |
+ return null; |
+ } |
/** |
- * Strips the class name from an expression of the form "className.someName". |
+ * For parity with the JavaScript debugger, we treat some getters as if |
+ * they are fields so that users can see their values immediately. |
+ * This matches JavaScript's behavior for getters on DOM objects. |
+ * In the future we should consider adding an annotation to tag getters |
+ * in user libraries as side effect free. |
*/ |
- static String stripClassName(String str, String className) { |
- if (str.length > className.length + 1 && |
- str.startsWith(className) && str[className.length] == '.') { |
- return str.substring(className.length + 1); |
- } else { |
- return str; |
+ static bool _isSideEffectFreeGetter(MethodMirror methodMirror, |
+ LibraryMirror libraryMirror) { |
+ // This matches JavaScript behavior. We should consider displaying |
+ // getters for all dart platform libraries rather than just the DOM |
+ // libraries. |
+ return libraryMirror.uri.scheme == 'dart' && |
+ SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString()); |
+ } |
+ |
+ /** |
+ * Whether we should treat a property as a field for the purposes of the |
+ * debugger. |
+ */ |
+ static bool treatPropertyAsField(MethodMirror methodMirror, |
+ LibraryMirror libraryMirror) { |
+ return (methodMirror.isGetter || methodMirror.isSetter) && |
+ (methodMirror.isSynthetic || |
+ _isSideEffectFreeGetter(methodMirror,libraryMirror)); |
+ } |
+ |
+ // TODO(jacobr): generate more concise function descriptions instead of |
+ // dumping the entire function source. |
+ static String describeFunction(function) { |
+ if (function is _Trampoline) return function._methodMirror.source; |
+ try { |
+ return reflect(function).function.source; |
+ } catch (e) { |
+ return function.toString(); |
+ } |
+ } |
+ |
+ static List getInvocationTrampolineDetails(_Trampoline method) { |
+ var loc = method._methodMirror.location; |
+ return [loc.line, loc.column, loc.sourceUri.toString(), |
+ MirrorSystem.getName(method._selector)]; |
+ } |
+ |
+ static List getLibraryProperties(String libraryUrl, bool ownProperties, |
+ bool accessorPropertiesOnly) { |
+ var properties = new Map<String, _Property>(); |
+ var libraryMirror = getLibraryMirror(libraryUrl); |
+ _addInstanceMirrors(libraryMirror, libraryMirror, |
+ libraryMirror.declarations, |
+ ownProperties, accessorPropertiesOnly, false, false, |
+ properties); |
+ if (!accessorPropertiesOnly) { |
+ // We need to add class properties for all classes in the library. |
+ libraryMirror.declarations.forEach((symbol, declarationMirror) { |
+ if (declarationMirror is ClassMirror) { |
+ var name = MirrorSystem.getName(symbol); |
+ if (declarationMirror.hasReflectedType |
+ && !properties.containsKey(name)) { |
+ properties[name] = new _Property(name) |
+ ..value = declarationMirror.reflectedType; |
+ } |
+ } |
+ }); |
+ } |
+ return packageProperties(properties); |
+ } |
+ |
+ static List getObjectProperties(o, bool ownProperties, |
+ bool accessorPropertiesOnly) { |
+ var properties = new Map<String, _Property>(); |
+ var names = new Set<String>(); |
+ var objectMirror = reflect(o); |
+ var classMirror = objectMirror.type; |
+ _addInstanceMirrors(objectMirror, classMirror.owner, |
+ classMirror.instanceMembers, |
+ ownProperties, accessorPropertiesOnly, false, true, |
+ properties); |
+ return packageProperties(properties); |
+ } |
+ |
+ static List getObjectClassProperties(o, bool ownProperties, |
+ bool accessorPropertiesOnly) { |
+ var properties = new Map<String, _Property>(); |
+ var objectMirror = reflect(o); |
+ var classMirror = objectMirror.type; |
+ _addInstanceMirrors(objectMirror, classMirror.owner, |
+ classMirror.instanceMembers, |
+ ownProperties, accessorPropertiesOnly, true, false, |
+ properties); |
+ _addStatics(classMirror, properties, accessorPropertiesOnly); |
+ return packageProperties(properties); |
+ } |
+ |
+ static List getClassProperties(Type t, bool ownProperties, |
+ bool accessorPropertiesOnly) { |
+ var properties = new Map<String, _Property>(); |
+ var classMirror = reflectClass(t); |
+ _addStatics(classMirror, properties, accessorPropertiesOnly); |
+ return packageProperties(properties); |
+ } |
+ |
+ static void _addStatics(ClassMirror classMirror, |
+ Map<String, _Property> properties, |
+ bool accessorPropertiesOnly) { |
+ var libraryMirror = classMirror.owner; |
+ classMirror.declarations.forEach((symbol, declaration) { |
+ var name = _getShortSymbolName(symbol, declaration); |
+ if (declaration is VariableMirror) { |
+ if (accessorPropertiesOnly) return; |
+ if (!declaration.isStatic) return; |
+ properties.putIfAbsent(name, () => new _Property(name)) |
+ ..value = classMirror.getField(symbol).reflectee |
+ ..writable = !declaration.isFinal && !declaration.isConst; |
+ } else if (declaration is MethodMirror) { |
+ MethodMirror methodMirror = declaration; |
+ // FIXMEDART: should we display constructors? |
+ if (methodMirror.isConstructor) return; |
+ if (!methodMirror.isStatic) return; |
+ if (accessorPropertiesOnly) { |
+ if (methodMirror.isRegularMethod || |
+ treatPropertyAsField(methodMirror, libraryMirror)) { |
+ return; |
+ } |
+ } else if (!methodMirror.isRegularMethod && |
+ !treatPropertyAsField(methodMirror, libraryMirror)) { |
+ return; |
+ } |
+ var property = properties.putIfAbsent(name, () => new _Property(name)); |
+ _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror, |
+ symbol, accessorPropertiesOnly, property); |
+ } |
+ }); |
+ } |
+ |
+ static void _fillMethodMirrorProperty(LibraryMirror libraryMirror, |
+ Mirror methodOwner, MethodMirror methodMirror, Symbol symbol, |
+ bool accessorPropertiesOnly, _Property property) { |
+ if (methodMirror.isRegularMethod) { |
+ property |
+ ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol) |
+ ..isMethod = true; |
+ } else if (methodMirror.isGetter) { |
+ if (treatPropertyAsField(methodMirror, libraryMirror)) { |
+ try { |
+ property.value = methodOwner.getField(symbol).reflectee; |
+ } catch (e) { |
+ property |
+ ..wasThrown = true |
+ ..value = e; |
+ } |
+ } else if (accessorPropertiesOnly) { |
+ property.getter = new _GetterTrampoline(methodOwner, |
+ methodMirror, symbol); |
+ } |
+ } else if (methodMirror.isSetter) { |
+ if (accessorPropertiesOnly && |
+ !treatPropertyAsField(methodMirror, libraryMirror)) { |
+ property.setter = new _SetterTrampoline(methodOwner, |
+ methodMirror, MirrorSystem.getSymbol(property.name, libraryMirror)); |
+ } |
+ property.writable = true; |
} |
} |
/** |
- * Removes the trailing dot from an expression ending in a dot. |
- * This method is used as Library prefixes include a trailing dot when using |
- * the C Dart debugger API. |
- */ |
- static String stripTrailingDot(String str) => |
- (str != null && str[str.length - 1] == '.') ? str.substring(0, str.length - 1) : str; |
+ * Helper method that handles collecting up properties from classes |
+ * or libraries using the filters [ownProperties], [accessorPropertiesOnly], |
+ * [hideFields], and [hideMethods] to determine which properties are |
+ * collected. [accessorPropertiesOnly] specifies whether all properties |
+ * should be returned or just accessors. [hideFields] specifies whether |
+ * fields should be hidden. hideMethods specifies whether methods should be |
+ * shown or hidden. [ownProperties] is not currently used but is part of the |
+ * Blink devtools API for enumerating properties. |
+ */ |
+ static void _addInstanceMirrors( |
+ ObjectMirror objectMirror, |
+ LibraryMirror libraryMirror, |
+ Map<Symbol, Mirror> declarations, |
+ bool ownProperties, bool accessorPropertiesOnly, |
+ bool hideFields, bool hideMethods, |
+ Map<String, _Property> properties) { |
+ declarations.forEach((Symbol symbol, Mirror declaration) { |
+ if (declaration is TypedefMirror || declaration is ClassMirror) return; |
+ var name = _getShortSymbolName(symbol, declaration); |
+ bool isField = declaration is VariableMirror || |
+ (declaration is MethodMirror && |
+ treatPropertyAsField(declaration, libraryMirror)); |
+ if ((isField && hideFields) || (hideMethods && !isField)) return; |
+ if (accessorPropertiesOnly) { |
+ if (declaration is VariableMirror || declaration.isRegularMethod || |
+ isField) { |
+ return; |
+ } |
+ } else if (declaration is MethodMirror && |
+ (declaration.isGetter || declaration.isSetter) && |
+ !treatPropertyAsField(declaration, libraryMirror)) { |
+ return; |
+ } |
+ var property = properties.putIfAbsent(name, () => new _Property(name)); |
+ if (declaration is VariableMirror) { |
+ property |
+ ..value = objectMirror.getField(symbol).reflectee |
+ ..writable = !declaration.isFinal && !declaration.isConst; |
+ return; |
+ } |
+ _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration, |
+ symbol, accessorPropertiesOnly, property); |
+ }); |
+ } |
- static String addTrailingDot(String str) => '${str}.'; |
+ /** |
+ * Flatten down the properties data structure into a List that is easy to |
+ * access from native code. |
+ */ |
+ static List packageProperties(Map<String, _Property> properties) { |
+ var ret = []; |
+ for (var property in properties.values) { |
+ ret.addAll([property.name, |
+ property.setter, |
+ property.getter, |
+ property.value, |
+ property.hasValue, |
+ property.writable, |
+ property.isMethod, |
+ property.isOwn, |
+ property.wasThrown]); |
+ } |
+ return ret; |
+ } |
+ |
+ /** |
+ * Get a property, returning null if the property does not exist. |
+ * For private property names, we attempt to resolve the property in the |
+ * context of each library that the property name could be associated with. |
+ */ |
+ static getObjectPropertySafe(o, String propertyName) { |
+ var objectMirror = reflect(o); |
+ var classMirror = objectMirror.type; |
+ if (propertyName.startsWith("_")) { |
+ var attemptedLibraries = new Set<LibraryMirror>(); |
+ while (classMirror != null) { |
+ LibraryMirror library = classMirror.owner; |
+ if (!attemptedLibraries.contains(library)) { |
+ try { |
+ return objectMirror.getField( |
+ MirrorSystem.getSymbol(propertyName, library)).reflectee; |
+ } catch (e) { } |
+ attemptedLibraries.add(library); |
+ } |
+ classMirror = classMirror.superclass; |
+ } |
+ return null; |
+ } |
+ try { |
+ return objectMirror.getField( |
+ MirrorSystem.getSymbol(propertyName)).reflectee; |
+ } catch (e) { |
+ return null; |
+ } |
+ } |
- static String demangle(String str) { |
- var atPos = str.indexOf('@'); |
- return atPos == -1 ? str : str.substring(0, atPos); |
+ /** |
+ * Helper to wrap the inspect method on InjectedScriptHost to provide the |
+ * inspect method required for the |
+ */ |
+ static List consoleApi(host) { |
+ return [ |
+ "inspect", |
+ (o) { |
+ host.inspect(o, null); |
+ return o; |
+ }, |
+ "dir", |
+ window().console.dir, |
+ "dirxml", |
+ window().console.dirxml |
+ // FIXME: add copy method. |
+ ]; |
} |
+ static List getMapKeyList(Map map) => map.keys.toList(); |
+ |
static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError; |
static void register(Document document, String tag, Type type, |